mirror of
https://github.com/proffesor-for-testing/agentic-qe.git
synced 2026-09-19 08:45:47 +08:00
94c3d032ec
Phase 1 Implementation (Bun-Inspired Improvements): A1 - Binary Cache System: - BinaryMetadataCache with MessagePack serialization - BinaryCacheManager integrated into PatternStoreFactory - CacheValidator, CacheInvalidator for lifecycle management - Target: <5ms pattern load (vs 32ms baseline) C1 - AI-Friendly Output: - OutputFormatter with AI mode detection (CLAUDECODE env) - AIActionSuggester for intelligent recommendations - CLIOutputHelper integrated into MCP BaseHandler - Structured JSON output for Claude Code integration C2 - Benchmark Suite: - Tinybench-based suite with real TestGeneratorAgent - Baseline collector and honest v2.3.5 template - GitHub Actions workflow for CI integration - Performance regression detection (10% threshold) Integration fixes: - Binary cache wired into PatternStoreFactory.create() - AI output methods added to MCP BaseHandler - PerformanceOptimizer logging reduced (debug level) - Fabricated benchmark data replaced with honest template Tests: 78 output tests pass, 71 cache tests pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
668 lines
22 KiB
TypeScript
668 lines
22 KiB
TypeScript
/**
|
|
* Binary Metadata Cache - Unit Tests
|
|
*
|
|
* Comprehensive test suite for BinaryMetadataCache interfaces and type definitions.
|
|
* Tests cache creation, validation, serialization, and error handling.
|
|
*
|
|
* Coverage target: 95%+
|
|
*
|
|
* @module tests/unit/cache/BinaryMetadataCache
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals';
|
|
import {
|
|
// Types and Interfaces
|
|
BinaryCache,
|
|
CacheVersion,
|
|
PatternEntry,
|
|
PatternMetadata,
|
|
AgentConfigEntry,
|
|
CacheIndexData,
|
|
ValidationResult,
|
|
CacheInvalidation,
|
|
BinaryCacheConfig,
|
|
CacheMetrics,
|
|
CacheBuildResult,
|
|
CacheLoadError,
|
|
SerializationError,
|
|
DeserializationError,
|
|
|
|
// Helper Functions
|
|
testPatternToEntry,
|
|
entryToTestPattern,
|
|
|
|
// Constants
|
|
DEFAULT_CACHE_CONFIG,
|
|
CACHE_MAGIC_NUMBER,
|
|
CACHE_HEADER_SIZE,
|
|
CACHE_VERSION,
|
|
} from '@/core/cache/BinaryMetadataCache';
|
|
import type { TestPattern } from '@/core/memory/IPatternStore';
|
|
|
|
describe('BinaryMetadataCache', () => {
|
|
describe('Type Definitions', () => {
|
|
describe('CacheVersion', () => {
|
|
it('should have major, minor, and patch fields', () => {
|
|
const version: CacheVersion = { major: 1, minor: 2, patch: 3 };
|
|
expect(version.major).toBe(1);
|
|
expect(version.minor).toBe(2);
|
|
expect(version.patch).toBe(3);
|
|
});
|
|
|
|
it('should work with zero versions', () => {
|
|
const version: CacheVersion = { major: 0, minor: 0, patch: 0 };
|
|
expect(version.major).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe('BinaryCache', () => {
|
|
it('should contain all required fields', () => {
|
|
const cache: BinaryCache = {
|
|
version: 0x010203,
|
|
timestamp: Date.now(),
|
|
checksum: 'abc123',
|
|
patterns: [],
|
|
agentConfigs: [],
|
|
indexes: {
|
|
domainIndex: new Map(),
|
|
typeIndex: new Map(),
|
|
frameworkIndex: new Map(),
|
|
},
|
|
};
|
|
|
|
expect(cache.version).toBeGreaterThan(0);
|
|
expect(cache.timestamp).toBeGreaterThan(0);
|
|
expect(cache.checksum).toBe('abc123');
|
|
expect(Array.isArray(cache.patterns)).toBe(true);
|
|
expect(Array.isArray(cache.agentConfigs)).toBe(true);
|
|
expect(cache.indexes).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('PatternEntry', () => {
|
|
it('should contain pattern metadata with embedding', () => {
|
|
const entry: PatternEntry = {
|
|
id: 'pattern-1',
|
|
type: 'unit-test',
|
|
domain: 'api',
|
|
framework: 'jest',
|
|
embedding: new Float32Array(768),
|
|
content: 'test content',
|
|
metadata: {
|
|
coverage: 0.95,
|
|
flakinessScore: 0.01,
|
|
verdict: 'success',
|
|
createdAt: Date.now(),
|
|
lastUsed: Date.now(),
|
|
usageCount: 10,
|
|
successCount: 9,
|
|
},
|
|
};
|
|
|
|
expect(entry.id).toBe('pattern-1');
|
|
expect(entry.embedding).toBeInstanceOf(Float32Array);
|
|
expect(entry.embedding.length).toBe(768);
|
|
expect(entry.metadata.coverage).toBe(0.95);
|
|
expect(entry.metadata.verdict).toBe('success');
|
|
});
|
|
|
|
it('should support different verdict types', () => {
|
|
const verdicts: PatternMetadata['verdict'][] = [
|
|
'success',
|
|
'failure',
|
|
'flaky',
|
|
'unknown',
|
|
];
|
|
|
|
verdicts.forEach((verdict) => {
|
|
const metadata: PatternMetadata = {
|
|
coverage: 0.8,
|
|
flakinessScore: 0.1,
|
|
verdict,
|
|
createdAt: Date.now(),
|
|
lastUsed: Date.now(),
|
|
usageCount: 5,
|
|
successCount: 4,
|
|
};
|
|
expect(metadata.verdict).toBe(verdict);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('AgentConfigEntry', () => {
|
|
it('should store agent configuration as JSON string', () => {
|
|
const config: AgentConfigEntry = {
|
|
agentId: 'test-gen-1',
|
|
type: 'test-generator',
|
|
configJson: JSON.stringify({ timeout: 5000, retries: 3 }),
|
|
version: '1.0.0',
|
|
updatedAt: Date.now(),
|
|
};
|
|
|
|
expect(config.agentId).toBe('test-gen-1');
|
|
expect(JSON.parse(config.configJson)).toEqual({
|
|
timeout: 5000,
|
|
retries: 3,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('CacheIndexData', () => {
|
|
it('should support domain-based indexing', () => {
|
|
const indexes: CacheIndexData = {
|
|
domainIndex: new Map([
|
|
['api', ['pattern-1', 'pattern-2']],
|
|
['ui', ['pattern-3']],
|
|
]),
|
|
typeIndex: new Map(),
|
|
frameworkIndex: new Map(),
|
|
};
|
|
|
|
expect(indexes.domainIndex.get('api')).toEqual([
|
|
'pattern-1',
|
|
'pattern-2',
|
|
]);
|
|
expect(indexes.domainIndex.get('ui')).toEqual(['pattern-3']);
|
|
});
|
|
|
|
it('should support type-based indexing', () => {
|
|
const indexes: CacheIndexData = {
|
|
domainIndex: new Map(),
|
|
typeIndex: new Map([
|
|
['unit-test', ['pattern-1']],
|
|
['integration-test', ['pattern-2']],
|
|
]),
|
|
frameworkIndex: new Map(),
|
|
};
|
|
|
|
expect(indexes.typeIndex.get('unit-test')).toEqual(['pattern-1']);
|
|
});
|
|
|
|
it('should support framework-based indexing', () => {
|
|
const indexes: CacheIndexData = {
|
|
domainIndex: new Map(),
|
|
typeIndex: new Map(),
|
|
frameworkIndex: new Map([
|
|
['jest', ['pattern-1', 'pattern-2']],
|
|
['vitest', ['pattern-3']],
|
|
]),
|
|
};
|
|
|
|
expect(indexes.frameworkIndex.get('jest')).toEqual([
|
|
'pattern-1',
|
|
'pattern-2',
|
|
]);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Validation Types', () => {
|
|
describe('ValidationResult', () => {
|
|
it('should represent successful validation', () => {
|
|
const result: ValidationResult = {
|
|
valid: true,
|
|
checksumValid: true,
|
|
versionCompatible: true,
|
|
};
|
|
|
|
expect(result.valid).toBe(true);
|
|
expect(result.checksumValid).toBe(true);
|
|
expect(result.versionCompatible).toBe(true);
|
|
});
|
|
|
|
it('should represent failed validation with error', () => {
|
|
const result: ValidationResult = {
|
|
valid: false,
|
|
checksumValid: false,
|
|
versionCompatible: true,
|
|
error: 'Checksum mismatch',
|
|
computedChecksum: 'abc123',
|
|
cacheVersion: { major: 1, minor: 0, patch: 0 },
|
|
};
|
|
|
|
expect(result.valid).toBe(false);
|
|
expect(result.error).toBe('Checksum mismatch');
|
|
expect(result.computedChecksum).toBeDefined();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Cache Invalidation', () => {
|
|
describe('CacheInvalidation', () => {
|
|
it('should support pattern_stored trigger', () => {
|
|
const invalidation: CacheInvalidation = {
|
|
trigger: 'pattern_stored',
|
|
timestamp: Date.now(),
|
|
requiresRebuild: true,
|
|
};
|
|
|
|
expect(invalidation.trigger).toBe('pattern_stored');
|
|
expect(invalidation.requiresRebuild).toBe(true);
|
|
});
|
|
|
|
it('should support all trigger types', () => {
|
|
const triggers: CacheInvalidation['trigger'][] = [
|
|
'pattern_stored',
|
|
'pattern_deleted',
|
|
'config_updated',
|
|
'schema_migration',
|
|
'manual',
|
|
'ttl_expired',
|
|
];
|
|
|
|
triggers.forEach((trigger) => {
|
|
const invalidation: CacheInvalidation = {
|
|
trigger,
|
|
timestamp: Date.now(),
|
|
requiresRebuild: trigger !== 'ttl_expired',
|
|
metadata: { reason: `Testing ${trigger}` },
|
|
};
|
|
expect(invalidation.trigger).toBe(trigger);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Configuration', () => {
|
|
describe('BinaryCacheConfig', () => {
|
|
it('should have default configuration values', () => {
|
|
expect(DEFAULT_CACHE_CONFIG.enabled).toBe(true);
|
|
expect(DEFAULT_CACHE_CONFIG.cachePath).toBe('.aqe/cache/patterns.bin');
|
|
expect(DEFAULT_CACHE_CONFIG.maxAge).toBe(3600000); // 1 hour
|
|
expect(DEFAULT_CACHE_CONFIG.checkInterval).toBe(300000); // 5 minutes
|
|
expect(DEFAULT_CACHE_CONFIG.backgroundRebuild).toBe(true);
|
|
expect(DEFAULT_CACHE_CONFIG.fallbackToSQLite).toBe(true);
|
|
expect(DEFAULT_CACHE_CONFIG.enableMetrics).toBe(true);
|
|
});
|
|
|
|
it('should allow custom configuration', () => {
|
|
const config: BinaryCacheConfig = {
|
|
enabled: false,
|
|
cachePath: '/custom/path/cache.bin',
|
|
maxAge: 7200000, // 2 hours
|
|
checkInterval: 600000, // 10 minutes
|
|
backgroundRebuild: false,
|
|
fallbackToSQLite: false,
|
|
version: { major: 2, minor: 0, patch: 0 },
|
|
enableMetrics: false,
|
|
};
|
|
|
|
expect(config.enabled).toBe(false);
|
|
expect(config.cachePath).toBe('/custom/path/cache.bin');
|
|
expect(config.maxAge).toBe(7200000);
|
|
});
|
|
});
|
|
|
|
describe('Cache Constants', () => {
|
|
it('should have correct magic number', () => {
|
|
expect(CACHE_MAGIC_NUMBER).toBe(0x41514543); // "AQEC"
|
|
});
|
|
|
|
it('should have correct header size', () => {
|
|
expect(CACHE_HEADER_SIZE).toBe(64);
|
|
});
|
|
|
|
it('should have current cache version', () => {
|
|
expect(CACHE_VERSION.major).toBe(1);
|
|
expect(CACHE_VERSION.minor).toBe(0);
|
|
expect(CACHE_VERSION.patch).toBe(0);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Metrics', () => {
|
|
describe('CacheMetrics', () => {
|
|
it('should track cache hit rate', () => {
|
|
const metrics: CacheMetrics = {
|
|
cacheHits: 950,
|
|
cacheMisses: 50,
|
|
cacheHitRate: 0.95,
|
|
avgCacheLoadTime: 3.5,
|
|
avgSQLiteFallbackTime: 28.0,
|
|
cacheCorruptionCount: 0,
|
|
cacheRebuildCount: 2,
|
|
lastCacheGenerationTime: Date.now(),
|
|
cacheFileSize: 1024 * 1024 * 5, // 5 MB
|
|
patternCount: 1000,
|
|
};
|
|
|
|
expect(metrics.cacheHitRate).toBeGreaterThanOrEqual(0.95);
|
|
expect(metrics.avgCacheLoadTime).toBeLessThan(5);
|
|
expect(metrics.cacheHits + metrics.cacheMisses).toBe(1000);
|
|
});
|
|
|
|
it('should detect performance degradation', () => {
|
|
const metrics: CacheMetrics = {
|
|
cacheHits: 100,
|
|
cacheMisses: 900,
|
|
cacheHitRate: 0.1,
|
|
avgCacheLoadTime: 15.0,
|
|
avgSQLiteFallbackTime: 30.0,
|
|
cacheCorruptionCount: 5,
|
|
cacheRebuildCount: 10,
|
|
lastCacheGenerationTime: Date.now() - 3600000 * 2,
|
|
cacheFileSize: 1024 * 1024 * 50,
|
|
patternCount: 1000,
|
|
};
|
|
|
|
expect(metrics.cacheHitRate).toBeLessThan(0.5);
|
|
expect(metrics.cacheCorruptionCount).toBeGreaterThan(0);
|
|
expect(metrics.avgCacheLoadTime).toBeGreaterThan(10);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Build Results', () => {
|
|
describe('CacheBuildResult', () => {
|
|
it('should represent successful build', () => {
|
|
const result: CacheBuildResult = {
|
|
success: true,
|
|
duration: 250,
|
|
patternCount: 1000,
|
|
agentConfigCount: 5,
|
|
cacheFileSize: 1024 * 1024 * 5,
|
|
version: { major: 1, minor: 0, patch: 0 },
|
|
checksum: 'sha256hash',
|
|
};
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.duration).toBeLessThan(500);
|
|
expect(result.patternCount).toBe(1000);
|
|
});
|
|
|
|
it('should represent failed build with error', () => {
|
|
const result: CacheBuildResult = {
|
|
success: false,
|
|
duration: 100,
|
|
patternCount: 0,
|
|
agentConfigCount: 0,
|
|
cacheFileSize: 0,
|
|
version: { major: 1, minor: 0, patch: 0 },
|
|
checksum: '',
|
|
error: 'Failed to serialize patterns',
|
|
};
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toBeDefined();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Error Classes', () => {
|
|
describe('CacheLoadError', () => {
|
|
it('should create error with type and message', () => {
|
|
const error = new CacheLoadError(
|
|
'file_not_found',
|
|
'Cache file does not exist',
|
|
{ path: '/path/to/cache.bin' }
|
|
);
|
|
|
|
expect(error.name).toBe('CacheLoadError');
|
|
expect(error.type).toBe('file_not_found');
|
|
expect(error.message).toBe('Cache file does not exist');
|
|
expect(error.metadata?.path).toBe('/path/to/cache.bin');
|
|
});
|
|
|
|
it('should support all error types', () => {
|
|
const errorTypes: Array<typeof CacheLoadError.prototype.type> = [
|
|
'file_not_found',
|
|
'permission_denied',
|
|
'checksum_mismatch',
|
|
'version_incompatible',
|
|
'corrupted_data',
|
|
'io_error',
|
|
];
|
|
|
|
errorTypes.forEach((type) => {
|
|
const error = new CacheLoadError(type, `Test error: ${type}`);
|
|
expect(error.type).toBe(type);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('SerializationError', () => {
|
|
it('should create error with message', () => {
|
|
const error = new SerializationError('Failed to encode patterns');
|
|
expect(error.name).toBe('SerializationError');
|
|
expect(error.message).toBe('Failed to encode patterns');
|
|
});
|
|
|
|
it('should support cause chain', () => {
|
|
const cause = new Error('Original error');
|
|
const error = new SerializationError('Serialization failed', cause);
|
|
expect(error.cause).toBe(cause);
|
|
});
|
|
});
|
|
|
|
describe('DeserializationError', () => {
|
|
it('should create error with message', () => {
|
|
const error = new DeserializationError('Failed to decode buffer');
|
|
expect(error.name).toBe('DeserializationError');
|
|
expect(error.message).toBe('Failed to decode buffer');
|
|
});
|
|
|
|
it('should support cause chain', () => {
|
|
const cause = new Error('Invalid buffer format');
|
|
const error = new DeserializationError('Deserialization failed', cause);
|
|
expect(error.cause).toBe(cause);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Helper Functions', () => {
|
|
describe('testPatternToEntry', () => {
|
|
it('should convert TestPattern to PatternEntry', () => {
|
|
const pattern: TestPattern = {
|
|
id: 'test-1',
|
|
type: 'unit-test',
|
|
domain: 'api',
|
|
framework: 'jest',
|
|
embedding: new Array(768).fill(0.5),
|
|
content: 'describe("test", () => {})',
|
|
coverage: 0.95,
|
|
flakinessScore: 0.01,
|
|
verdict: 'success',
|
|
createdAt: Date.now(),
|
|
lastUsed: Date.now(),
|
|
usageCount: 10,
|
|
metadata: { successCount: 9 },
|
|
};
|
|
|
|
const entry = testPatternToEntry(pattern);
|
|
|
|
expect(entry.id).toBe(pattern.id);
|
|
expect(entry.type).toBe(pattern.type);
|
|
expect(entry.domain).toBe(pattern.domain);
|
|
expect(entry.framework).toBe(pattern.framework);
|
|
expect(entry.embedding).toBeInstanceOf(Float32Array);
|
|
expect(entry.embedding.length).toBe(768);
|
|
expect(entry.content).toBe(pattern.content);
|
|
expect(entry.metadata.coverage).toBe(0.95);
|
|
expect(entry.metadata.verdict).toBe('success');
|
|
});
|
|
|
|
it('should handle missing optional fields', () => {
|
|
const pattern: TestPattern = {
|
|
id: 'test-2',
|
|
type: 'integration-test',
|
|
domain: 'database',
|
|
embedding: new Array(768).fill(0),
|
|
content: 'test content',
|
|
};
|
|
|
|
const entry = testPatternToEntry(pattern);
|
|
|
|
expect(entry.framework).toBe('unknown');
|
|
expect(entry.metadata.coverage).toBe(0);
|
|
expect(entry.metadata.flakinessScore).toBe(0);
|
|
expect(entry.metadata.verdict).toBe('unknown');
|
|
expect(entry.metadata.usageCount).toBe(0);
|
|
});
|
|
|
|
it('should convert array embedding to Float32Array', () => {
|
|
const pattern: TestPattern = {
|
|
id: 'test-3',
|
|
type: 'e2e-test',
|
|
domain: 'ui',
|
|
embedding: [0.1, 0.2, 0.3],
|
|
content: 'test',
|
|
};
|
|
|
|
const entry = testPatternToEntry(pattern);
|
|
expect(entry.embedding).toBeInstanceOf(Float32Array);
|
|
const embeddingArray = Array.from(entry.embedding);
|
|
expect(embeddingArray.length).toBe(3);
|
|
expect(embeddingArray[0]).toBeCloseTo(0.1, 5);
|
|
expect(embeddingArray[1]).toBeCloseTo(0.2, 5);
|
|
expect(embeddingArray[2]).toBeCloseTo(0.3, 5);
|
|
});
|
|
});
|
|
|
|
describe('entryToTestPattern', () => {
|
|
it('should convert PatternEntry to TestPattern', () => {
|
|
const entry: PatternEntry = {
|
|
id: 'pattern-1',
|
|
type: 'unit-test',
|
|
domain: 'api',
|
|
framework: 'jest',
|
|
embedding: new Float32Array([0.1, 0.2, 0.3]),
|
|
content: 'test content',
|
|
metadata: {
|
|
coverage: 0.9,
|
|
flakinessScore: 0.05,
|
|
verdict: 'success',
|
|
createdAt: Date.now(),
|
|
lastUsed: Date.now(),
|
|
usageCount: 15,
|
|
successCount: 14,
|
|
},
|
|
};
|
|
|
|
const pattern = entryToTestPattern(entry);
|
|
|
|
expect(pattern.id).toBe(entry.id);
|
|
expect(pattern.type).toBe(entry.type);
|
|
expect(pattern.domain).toBe(entry.domain);
|
|
expect(pattern.framework).toBe(entry.framework);
|
|
expect(Array.isArray(pattern.embedding)).toBe(true);
|
|
expect(pattern.embedding.length).toBe(3);
|
|
expect(pattern.embedding[0]).toBeCloseTo(0.1, 5);
|
|
expect(pattern.embedding[1]).toBeCloseTo(0.2, 5);
|
|
expect(pattern.embedding[2]).toBeCloseTo(0.3, 5);
|
|
expect(pattern.content).toBe(entry.content);
|
|
expect(pattern.coverage).toBe(0.9);
|
|
expect(pattern.verdict).toBe('success');
|
|
});
|
|
|
|
it('should handle unknown verdict', () => {
|
|
const entry: PatternEntry = {
|
|
id: 'pattern-2',
|
|
type: 'unit-test',
|
|
domain: 'api',
|
|
framework: 'jest',
|
|
embedding: new Float32Array(768),
|
|
content: 'test',
|
|
metadata: {
|
|
coverage: 0.8,
|
|
flakinessScore: 0.1,
|
|
verdict: 'unknown',
|
|
createdAt: Date.now(),
|
|
lastUsed: Date.now(),
|
|
usageCount: 5,
|
|
successCount: 4,
|
|
},
|
|
};
|
|
|
|
const pattern = entryToTestPattern(entry);
|
|
expect(pattern.verdict).toBeUndefined();
|
|
});
|
|
|
|
it('should convert Float32Array to regular array', () => {
|
|
const entry: PatternEntry = {
|
|
id: 'pattern-3',
|
|
type: 'unit-test',
|
|
domain: 'api',
|
|
framework: 'vitest',
|
|
embedding: new Float32Array([1, 2, 3, 4, 5]),
|
|
content: 'test',
|
|
metadata: {
|
|
coverage: 0,
|
|
flakinessScore: 0,
|
|
verdict: 'unknown',
|
|
createdAt: Date.now(),
|
|
lastUsed: Date.now(),
|
|
usageCount: 0,
|
|
successCount: 0,
|
|
},
|
|
};
|
|
|
|
const pattern = entryToTestPattern(entry);
|
|
expect(Array.isArray(pattern.embedding)).toBe(true);
|
|
expect(pattern.embedding).toEqual([1, 2, 3, 4, 5]);
|
|
});
|
|
});
|
|
|
|
describe('Round-trip conversion', () => {
|
|
it('should maintain data integrity in round-trip conversion', () => {
|
|
const original: TestPattern = {
|
|
id: 'round-trip-test',
|
|
type: 'property-based',
|
|
domain: 'validation',
|
|
framework: 'fast-check',
|
|
embedding: new Array(768).fill(0.5),
|
|
content: 'property test content',
|
|
coverage: 0.88,
|
|
flakinessScore: 0.02,
|
|
verdict: 'success',
|
|
createdAt: 1234567890,
|
|
lastUsed: 1234567900,
|
|
usageCount: 20,
|
|
metadata: { successCount: 19 },
|
|
};
|
|
|
|
const entry = testPatternToEntry(original);
|
|
const converted = entryToTestPattern(entry);
|
|
|
|
expect(converted.id).toBe(original.id);
|
|
expect(converted.type).toBe(original.type);
|
|
expect(converted.domain).toBe(original.domain);
|
|
expect(converted.framework).toBe(original.framework);
|
|
expect(converted.content).toBe(original.content);
|
|
expect(converted.coverage).toBe(original.coverage);
|
|
expect(converted.flakinessScore).toBe(original.flakinessScore);
|
|
expect(converted.verdict).toBe(original.verdict);
|
|
expect(converted.usageCount).toBe(original.usageCount);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Version Encoding', () => {
|
|
it('should encode version as uint32', () => {
|
|
const version: CacheVersion = { major: 1, minor: 2, patch: 3 };
|
|
const encoded = (version.major << 16) | (version.minor << 8) | version.patch;
|
|
expect(encoded).toBe(0x010203); // 66051 in decimal
|
|
});
|
|
|
|
it('should decode uint32 to version', () => {
|
|
const encoded = 0x020305; // v2.3.5
|
|
const major = (encoded >> 16) & 0xff;
|
|
const minor = (encoded >> 8) & 0xff;
|
|
const patch = encoded & 0xff;
|
|
|
|
expect(major).toBe(2);
|
|
expect(minor).toBe(3);
|
|
expect(patch).toBe(5);
|
|
});
|
|
|
|
it('should handle edge cases in version encoding', () => {
|
|
const maxVersion: CacheVersion = { major: 255, minor: 255, patch: 255 };
|
|
const encoded = (maxVersion.major << 16) | (maxVersion.minor << 8) | maxVersion.patch;
|
|
expect(encoded).toBe(0xffffff);
|
|
|
|
const zeroVersion: CacheVersion = { major: 0, minor: 0, patch: 0 };
|
|
const encodedZero = (zeroVersion.major << 16) | (zeroVersion.minor << 8) | zeroVersion.patch;
|
|
expect(encodedZero).toBe(0);
|
|
});
|
|
});
|
|
});
|