113 lines
3.1 KiB
JavaScript
113 lines
3.1 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { connect } from "node:net";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
createControlCoreApp,
|
|
} from "../../device-control-core/src/app.mjs";
|
|
import { createCoreDiscoveryClient } from "../src/core-client.mjs";
|
|
import { createDeviceGatewayRuntime } from "../src/runtime.mjs";
|
|
|
|
const gatewayToken = "test-only-gateway-token-with-32-bytes";
|
|
const identifierPepper = "test-only-identifier-pepper-with-32-bytes";
|
|
const specificationHeader = Buffer.from(
|
|
"FF23E9EF782DE7120300",
|
|
"hex",
|
|
);
|
|
const specificationPackage = Buffer.from(
|
|
"5B01010000FBDEC251EC5D",
|
|
"hex",
|
|
);
|
|
|
|
test("B2 HEADER2 becomes a persisted masked quarantine discovery before ACK", async () => {
|
|
let stored;
|
|
const core = createControlCoreApp({
|
|
discoveryIngestEnabled: true,
|
|
gatewayToken,
|
|
identifierPepper,
|
|
repository: {
|
|
health: async () => "ready",
|
|
upsertQuarantineDiscovery: async (value) => {
|
|
stored = value;
|
|
return {
|
|
created: true,
|
|
value: {
|
|
...value.safeView,
|
|
discoveryRef: "discovery:integration-001",
|
|
},
|
|
};
|
|
},
|
|
},
|
|
});
|
|
await listen(core);
|
|
const coreAddress = core.address();
|
|
const observe = createCoreDiscoveryClient({
|
|
coreUrl: `http://127.0.0.1:${coreAddress.port}`,
|
|
gatewayToken,
|
|
});
|
|
const gateway = createDeviceGatewayRuntime({
|
|
healthPort: 0,
|
|
tcpHost: "0.0.0.0",
|
|
tcpPort: 0,
|
|
listenEnabled: true,
|
|
publicIngressEnabled: true,
|
|
now: () => new Date(0x52db95de * 1000),
|
|
onDiscovery: observe,
|
|
});
|
|
const addresses = await gateway.start();
|
|
try {
|
|
const response = await exchange(
|
|
addresses.tcpAddress.port,
|
|
Buffer.concat([specificationHeader, specificationPackage]),
|
|
13,
|
|
);
|
|
assert.equal(
|
|
response.toString("hex").toUpperCase(),
|
|
"7B0400A0DE95DB527D7B00017D",
|
|
);
|
|
assert.match(stored.identifierDigest, /^hmac-sha256:[a-f0-9]{64}$/);
|
|
assert.equal(stored.safeView.lifecycleState, "quarantine");
|
|
assert.equal(stored.safeView.identifier.masked, "***********7769");
|
|
assert.equal(stored.safeView.commandTransport, "disabled");
|
|
assert.equal(
|
|
JSON.stringify(stored).includes("865209039777769"),
|
|
false,
|
|
);
|
|
} finally {
|
|
await gateway.stop();
|
|
await close(core);
|
|
}
|
|
});
|
|
|
|
function listen(server) {
|
|
return new Promise((resolve, reject) => {
|
|
server.once("error", reject);
|
|
server.listen(0, "127.0.0.1", resolve);
|
|
});
|
|
}
|
|
|
|
function close(server) {
|
|
return new Promise((resolve, reject) => {
|
|
server.close((error) => (error ? reject(error) : resolve()));
|
|
});
|
|
}
|
|
|
|
function exchange(port, payload, expectedBytes) {
|
|
return new Promise((resolve, reject) => {
|
|
const chunks = [];
|
|
let byteLength = 0;
|
|
const socket = connect({ host: "127.0.0.1", port }, () => {
|
|
socket.write(payload);
|
|
});
|
|
socket.on("data", (chunk) => {
|
|
chunks.push(chunk);
|
|
byteLength += chunk.length;
|
|
if (byteLength >= expectedBytes) {
|
|
socket.destroy();
|
|
resolve(Buffer.concat(chunks, byteLength));
|
|
}
|
|
});
|
|
socket.on("error", reject);
|
|
});
|
|
}
|