Files
pig/packages/prime/test/map.test.ts
2026-08-13 01:39:01 -07:00

169 lines
6.3 KiB
TypeScript

/**
* Tests for the upstream-to-PIG mapping.
*
* Two things here are worth defending with tests, because getting either wrong
* is expensive and neither would throw:
*
* **Money.** Upstream sends floating-point dollars; PIG stores integer
* cents. Truncating instead of rounding loses a cent on values that cannot
* be represented exactly in binary, and a cent compounds across millions of
* GPU-hours.
*
* **Node totals.** Prime reports on-demand price and GPU memory for the whole
* node. PIG compares per-GPU values, so a larger node must not look more
* expensive merely because it contains more GPUs.
*
* **Interconnect.** The field that decides whether capacity can train or
* only serve. Guessing wrong in either direction loses a deal or sells a
* customer a cluster that cannot do the job.
*/
import { strict as assert } from 'node:assert';
import { describe, it } from 'node:test';
import { mapListing, toCents } from '../src/map';
import type { PrimeGpuListing } from '../src/client';
const listing = (over: Partial<PrimeGpuListing> = {}): PrimeGpuListing => ({
gpuType: 'H100_80GB',
gpuCount: 8,
raw: {},
...over,
});
describe('toCents', () => {
it('rounds rather than truncating', () => {
// 2.43 is 2.4299999... in binary. Truncating gives 242 and loses a cent
// on every single listing.
assert.equal(toCents(2.43), 243);
assert.equal(toCents(0.47), 47);
assert.equal(toCents(12.005), 1201);
});
it('passes through null and rejects nonsense', () => {
assert.equal(toCents(null), null);
assert.equal(toCents(undefined), null);
assert.equal(toCents(Number.NaN), null);
assert.equal(toCents(Number.POSITIVE_INFINITY), null);
});
it('handles zero, which is a real price and not a missing one', () => {
assert.equal(toCents(0), 0);
});
});
describe('mapListing — interconnect', () => {
const cases: [string, string][] = [
['Infiniband', 'Infiniband'],
['InfiniBand', 'Infiniband'],
['INFINIBAND', 'Infiniband'],
['infini_band', 'Infiniband'],
['IB', 'Infiniband'],
['RoCE', 'RoCE'],
['roce v2', 'RoCE'],
['NVLink', 'NVLink'],
['nvl', 'NVLink'],
['Ethernet', 'Ethernet'],
['eth', 'Ethernet'],
];
for (const [input, expected] of cases) {
it(`normalises "${input}" to ${expected}`, () => {
assert.equal(mapListing(listing({ interconnectType: input }))!.interconnectType, expected);
});
}
it('maps an unrecognised fabric to Unknown, never to Ethernet', () => {
// Assuming Ethernet would understate real capacity; assuming InfiniBand
// would sell a training customer a cluster that cannot train. Neither
// error is acceptable, so it stays explicitly unknown.
assert.equal(mapListing(listing({ interconnectType: 'Omni-Path' }))!.interconnectType, 'Unknown');
assert.equal(mapListing(listing({ interconnectType: '' }))!.interconnectType, 'Unknown');
assert.equal(mapListing(listing({ interconnectType: undefined }))!.interconnectType, 'Unknown');
});
});
describe('mapListing — stock', () => {
it('treats an unrecognised stock signal as Unavailable', () => {
// Under-promising inventory is recoverable. A seller offering capacity
// that turns out not to exist is not.
assert.equal(mapListing(listing({ stockStatus: 'wat' }))!.stockStatus, 'Unavailable');
assert.equal(mapListing(listing({ stockStatus: undefined }))!.stockStatus, 'Unavailable');
});
it('passes known values through, case-insensitively', () => {
assert.equal(mapListing(listing({ stockStatus: 'available' }))!.stockStatus, 'Available');
assert.equal(mapListing(listing({ stockStatus: 'HIGH' }))!.stockStatus, 'High');
});
});
describe('mapListing — general', () => {
it('drops a listing with no GPU type or count — there is nothing sellable', () => {
assert.equal(mapListing(listing({ gpuType: undefined })), null);
assert.equal(mapListing(listing({ gpuCount: undefined })), null);
assert.equal(mapListing(listing({ gpuCount: 0 })), null);
});
it('converts prices to integer cents', () => {
const m = mapListing(
listing({ gpuCount: 1, prices: { onDemand: 2.43, communityPrice: 0.94 } }),
)!;
assert.equal(m.onDemandPriceCents, 243);
assert.equal(m.communityPriceCents, 94);
});
it('normalises verified DataCrunch A100 node totals to the same per-GPU values', () => {
const oneGpuRaw = {
provider: 'datacrunch',
gpuType: 'A100_80GB',
gpuCount: 1,
gpuMemory: 80,
prices: { onDemand: 1.79 },
};
const twoGpuRaw = {
provider: 'datacrunch',
gpuType: 'A100_80GB',
gpuCount: 2,
gpuMemory: 160,
prices: { onDemand: 3.58 },
};
const oneGpu = mapListing({ ...oneGpuRaw, raw: oneGpuRaw })!;
const twoGpu = mapListing({ ...twoGpuRaw, raw: twoGpuRaw })!;
assert.equal(oneGpu.onDemandPriceCents, 179);
assert.equal(twoGpu.onDemandPriceCents, 179);
assert.equal(oneGpu.gpuMemoryGb, 80);
assert.equal(twoGpu.gpuMemoryGb, 80);
assert.deepEqual(twoGpu.raw, twoGpuRaw);
});
it('defaults to the secure tier unless community is stated', () => {
// Mislabelling community capacity as secure would let it be sold against a
// requirement it cannot meet.
assert.equal(mapListing(listing({}))!.securityTier, 'secure_cloud');
assert.equal(
mapListing(listing({ security: 'community_cloud' }))!.securityTier,
'community_cloud',
);
});
it('normalises sockets and drops unknown ones rather than inventing a value', () => {
assert.equal(mapListing(listing({ socket: 'sxm5' }))!.socket, 'SXM5');
assert.equal(mapListing(listing({ socket: 'pcie' }))!.socket, 'PCIe');
assert.equal(mapListing(listing({ socket: 'SXM_5' }))!.socket, 'SXM5');
// The column is an enum; an unmapped value would fail the insert.
assert.equal(mapListing(listing({ socket: 'weird' }))!.socket, null);
});
it('unwraps counts sent as objects', () => {
const m = mapListing(listing({ vcpu: { defaultCount: 96 }, memory: 1024 }))!;
assert.equal(m.vcpu, 96);
assert.equal(m.memoryGb, 1024);
});
it('preserves the raw payload so a new upstream field is not lost', () => {
const raw = { gpuType: 'H100_80GB', gpuCount: 8, somethingNew: 'value' };
const m = mapListing({ ...listing(), raw })!;
assert.equal((m.raw as Record<string, unknown>).somethingNew, 'value');
});
});