|
| 1 | +/** |
| 2 | + * Cross-check our hand-maintained codec classification against zarrita's actual |
| 3 | + * codec registry. zarrita is a devDependency only — this coupling exists purely |
| 4 | + * to keep `classifyCodec` honest, so the runtime library stays sync and |
| 5 | + * dependency-free (see codecs.ts). If zarrita adds or re-classifies a codec, |
| 6 | + * these tests fail and prompt us to update the table deliberately. |
| 7 | + */ |
| 8 | +import { describe, it, expect } from 'vitest'; |
| 9 | +import { registry } from 'zarrita'; |
| 10 | +import { classifyCodec } from './codecs.js'; |
| 11 | + |
| 12 | +type Kind = 'array_to_array' | 'array_to_bytes' | 'bytes_to_bytes'; |
| 13 | + |
| 14 | +// Best-effort extraction of a codec's pipeline `kind`. `kind` is a per-instance |
| 15 | +// field, so the codec must be instantiated; some (numcodecs-backed blosc/lz4/ |
| 16 | +// zstd) cannot be constructed without async wasm init, so we return undefined |
| 17 | +// and skip kind-based assertions for those — the "no unknowns" check still |
| 18 | +// covers them. |
| 19 | +async function kindOf(name: string): Promise<Kind | undefined> { |
| 20 | + try { |
| 21 | + const Codec = (await registry.get(name)?.()) as |
| 22 | + | { fromConfig: (cfg: unknown, meta: unknown) => { kind: Kind } } |
| 23 | + | undefined; |
| 24 | + if (!Codec) return undefined; |
| 25 | + const meta = { data_type: 'uint8', shape: [4, 4], chunk_shape: [2, 2], codecs: [] }; |
| 26 | + for (const cfg of [{}, { endian: 'little' }, { order: [0, 1] }, { keepbits: 8 }]) { |
| 27 | + try { |
| 28 | + return Codec.fromConfig(cfg, meta).kind; |
| 29 | + } catch { |
| 30 | + /* try next config shape */ |
| 31 | + } |
| 32 | + } |
| 33 | + } catch { |
| 34 | + /* codec module failed to load */ |
| 35 | + } |
| 36 | + return undefined; |
| 37 | +} |
| 38 | + |
| 39 | +describe('classifyCodec cross-check against zarrita registry', () => { |
| 40 | + const names = [...registry.keys()]; |
| 41 | + |
| 42 | + it('classifies every codec in zarrita\'s registry (no unknowns)', () => { |
| 43 | + const unknown = names.filter((n) => classifyCodec(n) === 'unknown'); |
| 44 | + expect(unknown).toEqual([]); |
| 45 | + }); |
| 46 | + |
| 47 | + it.each(names)( |
| 48 | + 'classification of "%s" is consistent with its zarrita kind', |
| 49 | + async (name) => { |
| 50 | + const kind = await kindOf(name); |
| 51 | + const classification = classifyCodec(name); |
| 52 | + |
| 53 | + // array_to_array transforms and array_to_bytes serialization codecs are |
| 54 | + // never compression — misclassifying one as compression is the exact |
| 55 | + // false-incompatible bug this guards against. |
| 56 | + if (kind === 'array_to_array' || kind === 'array_to_bytes') { |
| 57 | + expect(classification).toBe('structural'); |
| 58 | + } |
| 59 | + |
| 60 | + // Anything we call compression must be a bytes_to_bytes codec in zarrita. |
| 61 | + if (classification === 'compression' && kind !== undefined) { |
| 62 | + expect(kind).toBe('bytes_to_bytes'); |
| 63 | + } |
| 64 | + } |
| 65 | + ); |
| 66 | +}); |
0 commit comments