// Which archive paths name the same file: the TypeScript folding against what // the Swift core decides for the same pairs (path-folding.swift.json, written // by tools/swift-oracle/run.sh; the Swift folding is Linux Foundation's). import { readFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { describe, expect, it } from 'vitest'; import { FlsArchiveError, writeZipEntries } from '../src/index.js'; const here = dirname(fileURLToPath(import.meta.url)); const cases = JSON.parse(readFileSync(join(here, 'path-folding.cases.json'), 'utf8')) as { name: string; first: string; second: string; }[]; const swift = new Map( (JSON.parse(readFileSync(join(here, 'path-folding.swift.json'), 'utf8')) as { name: string; outcome: string }[]).map( (item) => [item.name, item.outcome], ), ); function outcome(first: string, second: string): string { try { writeZipEntries( new Map([ [first, Uint8Array.of(1)], [second, Uint8Array.of(2)], ]), ); return 'distinct'; } catch (error) { if (error instanceof FlsArchiveError) return error.code === 'duplicateEntry' ? 'collide' : error.code; throw error; } } describe('archive path folding matches Swift', () => { it('has a Swift result for every case', () => { expect(cases.every((item) => swift.has(item.name))).toBe(true); }); for (const item of cases) { it(item.name, () => { // Swift strings compare by canonical equivalence, so a composed and a // decomposed spelling are one dictionary key there ("sameKey"). A Map // here keeps both — and the writer then refuses them as one file. const expected = swift.get(item.name) === 'sameKey' ? 'collide' : swift.get(item.name); expect(outcome(item.first, item.second)).toBe(expected); }); } });