125 lines
6.5 KiB
JavaScript
125 lines
6.5 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import { readFile, readdir } from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import test from 'node:test'
|
|
|
|
const root = path.resolve(import.meta.dirname, '..')
|
|
const contractPath = path.join(root, 'contracts', 'numbered-ipc-registry.json')
|
|
const libPath = path.join(root, 'src-tauri', 'src', 'lib.rs')
|
|
const dispatcherPath = path.join(root, 'src-tauri', 'src', 'numbered_ipc_dispatch.rs')
|
|
const clientPath = path.join(root, 'src', 'modules', 'numbered-ipc.ts')
|
|
const rustRoot = path.join(root, 'src-tauri', 'src')
|
|
const frontendRoot = path.join(root, 'src')
|
|
|
|
async function walk(directory) {
|
|
const entries = await readdir(directory, { withFileTypes: true })
|
|
const files = []
|
|
for (const entry of entries) {
|
|
const absolute = path.join(directory, entry.name)
|
|
if (entry.isDirectory()) files.push(...await walk(absolute))
|
|
else files.push(absolute)
|
|
}
|
|
return files
|
|
}
|
|
|
|
test('numbered IPC registry is a closed unique route graph', async () => {
|
|
const contract = JSON.parse(await readFile(contractPath, 'utf8'))
|
|
assert.equal(contract.schema, 'hololake.numbered-ipc-registry/v1')
|
|
assert.equal(contract.record_id, 'HLP-NUMBERED-IPC-ROOT-001')
|
|
assert.equal(contract.runtime.public_tauri_command, 'numbered_ipc')
|
|
assert.equal(contract.runtime.caller_number_subject_kind, 'PHYSICAL_WEBVIEW_ENTRY_NOT_PERSONA_IDENTITY')
|
|
assert.equal(contract.runtime.caller_number_grants_persona_binding, false)
|
|
assert.equal(contract.runtime.legacy_direct_commands_allowed, false)
|
|
assert.equal(contract.runtime.grant_single_use, true)
|
|
assert.equal(contract.runtime.payload_bound_grants, true)
|
|
assert.equal(contract.runtime.authority_binding_issued_server_side, true)
|
|
assert.equal(contract.runtime.persona_binding_claimed, false)
|
|
assert.equal(contract.runtime.unknown_route, 'FAIL_CLOSED')
|
|
assert.ok(contract.operations.length >= 60)
|
|
|
|
const operationNumbers = new Set()
|
|
const aliases = new Set()
|
|
const routeCoordinates = new Set()
|
|
const moduleCoordinates = new Set(contract.modules.map((module) => `${module.module_number}/${module.target_number}`))
|
|
for (const operation of contract.operations) {
|
|
assert.match(operation.operation_number, /^HLP-NIPC-OP-\d{4}$/)
|
|
assert.match(operation.module_number, /^HLP-NIPC-MOD-\d{4}$/)
|
|
assert.match(operation.channel_number, /^HLP-NIPC-CH-\d{4}$/)
|
|
assert.match(operation.target_number, /^HLP-NIPC-TGT-\d{4}$/)
|
|
assert.ok(operation.handler.includes('::'))
|
|
assert.equal(operationNumbers.has(operation.operation_number), false)
|
|
assert.equal(aliases.has(operation.alias), false)
|
|
operationNumbers.add(operation.operation_number)
|
|
aliases.add(operation.alias)
|
|
const coordinate = [operation.channel_number, operation.module_number, operation.operation_number, operation.target_number].join('/')
|
|
assert.equal(routeCoordinates.has(coordinate), false)
|
|
routeCoordinates.add(coordinate)
|
|
assert.equal(moduleCoordinates.has(`${operation.module_number}/${operation.target_number}`), true)
|
|
}
|
|
const payloadAliases = [
|
|
...contract.payload_contract.empty_object_aliases,
|
|
...contract.payload_contract.input_wrapper_aliases,
|
|
...Object.keys(contract.payload_contract.direct_field_aliases),
|
|
]
|
|
assert.equal(new Set(payloadAliases).size, payloadAliases.length)
|
|
assert.deepEqual([...payloadAliases].sort(), [...aliases].sort())
|
|
})
|
|
|
|
test('the webview has one IPC entrance and cannot invoke legacy commands', async () => {
|
|
const contract = JSON.parse(await readFile(contractPath, 'utf8'))
|
|
const aliases = new Set(contract.operations.map((operation) => operation.alias))
|
|
const files = (await walk(frontendRoot)).filter((file) => /\.(ts|tsx)$/.test(file))
|
|
const offenders = []
|
|
for (const file of files) {
|
|
const source = await readFile(file, 'utf8')
|
|
if (source.includes("from '@tauri-apps/api/core'") && !file.endsWith(path.join('modules', 'numbered-ipc.ts'))) {
|
|
offenders.push(`${path.relative(root, file)}:raw-tauri-import`)
|
|
}
|
|
if (file.endsWith(path.join('modules', 'numbered-ipc.ts'))) {
|
|
const calls = [...source.matchAll(/\binvoke(?:<[^>]+>)?\s*\(\s*['"]([^'"]+)['"]/g)]
|
|
for (const call of calls) if (call[1] !== 'numbered_ipc') offenders.push(`${path.relative(root, file)}:${call[1]}`)
|
|
} else {
|
|
const calls = [...source.matchAll(/\binvoke(?:<[^>]+>)?\s*\(\s*['"]([^'"]+)['"]/g)]
|
|
for (const call of calls) if (!aliases.has(call[1])) offenders.push(`${path.relative(root, file)}:unregistered-alias:${call[1]}`)
|
|
}
|
|
}
|
|
assert.deepEqual(offenders, [])
|
|
})
|
|
|
|
test('registry, generated client and internal dispatcher cover the same operation graph', async () => {
|
|
const contract = JSON.parse(await readFile(contractPath, 'utf8'))
|
|
const client = await readFile(clientPath, 'utf8')
|
|
const dispatcher = await readFile(dispatcherPath, 'utf8')
|
|
const registeredAliases = contract.operations.map((operation) => operation.alias).sort()
|
|
const clientAliases = [...client.matchAll(/^ "([a-z0-9_]+)": \{$/gm)].map((match) => match[1]).sort()
|
|
const registeredHandlers = contract.operations.map((operation) => operation.handler).sort()
|
|
const dispatchedHandlers = [...dispatcher.matchAll(/^ "([a-z0-9_]+::[a-z0-9_]+)" =>/gm)]
|
|
.map((match) => match[1])
|
|
.sort()
|
|
assert.deepEqual(clientAliases, registeredAliases)
|
|
assert.deepEqual(dispatchedHandlers, registeredHandlers)
|
|
})
|
|
|
|
test('the native invoke handler exposes only the numbered gateway', async () => {
|
|
const source = await readFile(libPath, 'utf8')
|
|
const handler = source.match(/invoke_handler\(tauri::generate_handler!\[([\s\S]*?)\]\)/)?.[1]
|
|
assert.ok(handler)
|
|
const commands = [...handler.matchAll(/([a-z_]+::[a-z_]+)/g)].map((match) => match[1])
|
|
assert.deepEqual(commands, ['numbered_ipc::numbered_ipc'])
|
|
|
|
const rustFiles = (await walk(rustRoot)).filter((file) => file.endsWith('.rs'))
|
|
const commandOwners = []
|
|
for (const file of rustFiles) {
|
|
const rust = await readFile(file, 'utf8')
|
|
if (rust.includes('#[tauri::command]')) commandOwners.push(path.basename(file))
|
|
}
|
|
assert.deepEqual(commandOwners, ['numbered_ipc.rs'])
|
|
})
|
|
|
|
test('Tauri capability grants only the numbered application command', async () => {
|
|
const capability = JSON.parse(await readFile(path.join(root, 'src-tauri', 'capabilities', 'default.json'), 'utf8'))
|
|
assert.ok(capability.permissions.includes('allow-numbered-ipc'))
|
|
const permission = await readFile(path.join(root, 'src-tauri', 'permissions', 'numbered-ipc.toml'), 'utf8')
|
|
assert.match(permission, /identifier\s*=\s*"allow-numbered-ipc"/)
|
|
assert.match(permission, /commands\.allow\s*=\s*\["numbered_ipc"\]/)
|
|
})
|