macos-runtime.spec.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
  2. import { tmpdir } from 'node:os'
  3. import { join } from 'node:path'
  4. import { afterEach, expect, it, vi } from 'vitest'
  5. import { signMacOSRuntime } from '../scripts/macos-runtime.ts'
  6. import { signMacOSRuntimeCode, verifyMacOSRuntimeCode } from '../scripts/verify-macos-signature.mjs'
  7. vi.mock('../scripts/verify-macos-signature.mjs', () => ({ signMacOSRuntimeCode: vi.fn(), verifyMacOSRuntimeCode: vi.fn() }))
  8. const roots: string[] = []
  9. function root(): string {
  10. const path = mkdtempSync(join(tmpdir(), 'desktop-signing-'))
  11. roots.push(path)
  12. return path
  13. }
  14. const identity = { signingIdentity: 'Example (TEAMID1234)', teamId: 'TEAMID1234' }
  15. afterEach(() => {
  16. vi.resetAllMocks()
  17. for (const path of roots.splice(0)) rmSync(path, { recursive: true, force: true })
  18. })
  19. it('signs Mach-O files in their final locations and verifies each signature', async () => {
  20. const path = root()
  21. writeFileSync(join(path, 'addon.node'), Buffer.from('cffaedfe00000000', 'hex'))
  22. writeFileSync(join(path, 'source.js'), 'export {}')
  23. await expect(signMacOSRuntime(path, 'com.example.app', identity)).resolves.toBe(1)
  24. expect(signMacOSRuntimeCode).toHaveBeenCalledWith(join(path, 'addon.node'), expect.stringMatching(/^com\.example\.app\.runtime\.[a-f0-9]{64}$/u), identity)
  25. expect(verifyMacOSRuntimeCode).toHaveBeenCalledWith(join(path, 'addon.node'), identity)
  26. })
  27. it('awaits other signers before rejecting and permitting output cleanup', async () => {
  28. const path = root()
  29. for (const name of ['a.node', 'b.node']) writeFileSync(join(path, name), Buffer.from('cffaedfe00000000', 'hex'))
  30. let release!: () => void
  31. const barrier = new Promise<void>((resolve) => { release = resolve })
  32. let started!: () => void
  33. const ready = new Promise<void>((resolve) => { started = resolve })
  34. vi.mocked(signMacOSRuntimeCode).mockImplementation(async (file) => {
  35. if (file.endsWith('a.node')) throw new Error('sign failure')
  36. started()
  37. await barrier
  38. })
  39. let completed = false
  40. const result = signMacOSRuntime(path, 'com.example.app', identity).catch((error: unknown) => { completed = true; return error })
  41. try {
  42. await ready
  43. expect(completed).toBe(false)
  44. } finally { release() }
  45. expect(await result).toBeInstanceOf(AggregateError)
  46. expect(verifyMacOSRuntimeCode).toHaveBeenCalledWith(join(path, 'b.node'), identity)
  47. })