import { describe, expect, test } from 'vitest'; import { CapacityPolicyValidationError, computePhysicalDatabasePoolKey, encodeCapacityPolicyTag, parseCapacityPolicyTag, parseCapacityPolicyTags, type PhysicalDatabaseCapacityPolicy, validateCapacityPolicyCompatibility } from './capacityPolicy.js'; describe('capacity policy tags', () => { test('round-trips percentage policies with trimmed case-sensitive agent names', () => { const shared: PhysicalDatabaseCapacityPolicy = { agentName: 'Customer OPA', engine: 'postgres', thresholdType: 'minAvailableCapacityPercent', thresholdValue: 20 }; expect( parseCapacityPolicyTag( encodeCapacityPolicyTag({ ...shared, agentName: ' Customer OPA ' }) ) ).toEqual(shared); expect(encodeCapacityPolicyTag(shared)).toBe('v2|Customer%20OPA|postgres|minAvailableCapacityPercent|20'); expect(encodeCapacityPolicyTag({ ...shared, agentName: 'customer opa' })).not.toBe(encodeCapacityPolicyTag(shared)); }); test('parseCapacityPolicyTags returns empty when the tag is omitted', () => { expect(parseCapacityPolicyTags(undefined)).toEqual([]); }); test('rejects unsupported versions, empty agent names, blank values, and out-of-range thresholds', () => { const agentName = encodeURIComponent('customer-opa'); expect(() => parseCapacityPolicyTag(`v1|${agentName}|postgres|minAvailableCapacityPercent|20`)).toThrow(/unsupported version/); expect(() => parseCapacityPolicyTag(`v2|%20%20|postgres|minAvailableCapacityPercent|20`)).toThrow(/agentName must be non-empty/); expect(() => parseCapacityPolicyTag(`v2|${agentName}|postgres|minAvailableCapacityPercent|`)).toThrow( /thresholdValue must be a non-empty integer/ ); expect(() => parseCapacityPolicyTag(`v2|${agentName}|postgres|minAvailableCapacityPercent|101`)).toThrow(/<= 100/); expect(() => parseCapacityPolicyTag(`v2|${agentName}|postgres|minAvailableCapacityPercent|-1`)).toThrow(/>= 0/); expect(() => parseCapacityPolicyTag(`v2|${agentName}|postgres|minEmptyPhysicalInstances|1`)).toThrow(/unknown thresholdType/); }); test('parseCapacityPolicyTags fails closed on any invalid value', () => { const valid = encodeCapacityPolicyTag({ agentName: 'customer-opa', engine: 'postgres', thresholdType: 'minAvailableCapacityPercent', thresholdValue: 20 }); expect(() => parseCapacityPolicyTags([valid, 'not-a-policy'])).toThrow(CapacityPolicyValidationError); }); test('rejects duplicate policies for the same agent name and engine', () => { const first = encodeCapacityPolicyTag({ agentName: 'Customer OPA', engine: 'postgres', thresholdType: 'minAvailableCapacityPercent', thresholdValue: 20 }); const duplicate = encodeCapacityPolicyTag({ agentName: ' Customer OPA ', engine: 'postgres', thresholdType: 'minAvailableCapacityPercent', thresholdValue: 10 }); try { parseCapacityPolicyTags([first, duplicate]); expect.fail('Expected duplicate capacity policy validation to fail'); } catch (error) { expect(error).toBeInstanceOf(CapacityPolicyValidationError); if (!(error instanceof CapacityPolicyValidationError)) { throw error; } expect(error.details).toEqual([expect.stringContaining('duplicate capacity policy')]); } }); test('allows distinct agent names for the same engine', () => { const first = encodeCapacityPolicyTag({ agentName: 'customer-opa-a', engine: 'postgres', thresholdType: 'minAvailableCapacityPercent', thresholdValue: 20 }); const second = encodeCapacityPolicyTag({ agentName: 'customer-opa-b', engine: 'postgres', thresholdType: 'minAvailableCapacityPercent', thresholdValue: 10 }); expect(parseCapacityPolicyTags([first, second])).toHaveLength(2); }); test('computePhysicalDatabasePoolKey is trimmed, case-sensitive, and delimiter-safe', () => { expect( computePhysicalDatabasePoolKey({ organizationId: 'org:1', agentName: ' customer:opa ', engine: 'postgres' }) ).toBe( computePhysicalDatabasePoolKey({ organizationId: 'org:1', agentName: 'customer:opa', engine: 'postgres' }) ); expect( computePhysicalDatabasePoolKey({ organizationId: 'org:1', agentName: 'customer:opa', engine: 'postgres' }) ).not.toBe( computePhysicalDatabasePoolKey({ organizationId: 'org', agentName: '1:customer:opa', engine: 'postgres' }) ); expect( computePhysicalDatabasePoolKey({ organizationId: 'org:1', agentName: 'Customer:OPA', engine: 'postgres' }) ).not.toBe( computePhysicalDatabasePoolKey({ organizationId: 'org:1', agentName: 'customer:opa', engine: 'postgres' }) ); expect(() => computePhysicalDatabasePoolKey({ organizationId: 'org:1', agentName: ' ', engine: 'postgres' }) ).toThrow(/agentName must be non-empty/); }); test('allows replicas to publish the same pool and threshold', () => { const policy: PhysicalDatabaseCapacityPolicy = { agentName: 'customer-opa', engine: 'postgres', thresholdType: 'minAvailableCapacityPercent', thresholdValue: 20 }; expect(() => validateCapacityPolicyCompatibility([policy], [{ ...policy }])).not.toThrow(); }); test('rejects different thresholds for the same pool', () => { expect(() => validateCapacityPolicyCompatibility( [ { agentName: 'customer-opa', engine: 'postgres', thresholdType: 'minAvailableCapacityPercent', thresholdValue: 20 } ], [ { agentName: 'customer-opa', engine: 'postgres', thresholdType: 'minAvailableCapacityPercent', thresholdValue: 10 } ] ) ).toThrow(/different thresholds/); }); test('allows different agent names and case-distinct agent names for the same engine', () => { expect(() => validateCapacityPolicyCompatibility( [ { agentName: 'Customer OPA', engine: 'postgres', thresholdType: 'minAvailableCapacityPercent', thresholdValue: 20 } ], [ { agentName: 'customer opa', engine: 'postgres', thresholdType: 'minAvailableCapacityPercent', thresholdValue: 10 } ] ) ).not.toThrow(); }); });