Live video on the AT Protocol
1import { bytesToMultibase } from "@atproto/crypto";
2import { ChildProcess } from "child_process";
3import fs from "fs/promises";
4import os from "os";
5import path from "path";
6import { privateKeyToAccount } from "viem/accounts";
7import getEnv from "../env";
8import makeNode from "../node";
9import { playbackTest } from "./playback-test";
10import { resumeLoopTest } from "./resume-loop-test";
11import { syncTest } from "./sync-test";
12import { E2ETest, TestEnv } from "./test-env";
13
14const allTests: Record<string, E2ETest> = {
15 playback: playbackTest,
16 sync: syncTest,
17 resume: resumeLoopTest,
18};
19
20export const allTestNames = Object.keys(allTests);
21
22const randomPort = () => Math.floor(Math.random() * 20000) + 20000;
23
24export default async function runTests(
25 tests: string[],
26 duration: string,
27 privateKey: `0x${string}`,
28): Promise<boolean> {
29 const testFuncs = [];
30 for (const test of tests) {
31 if (!allTests[test]) {
32 throw new Error(`Test ${test} not found`);
33 }
34 testFuncs.push(allTests[test]);
35 }
36 try {
37 const results = [];
38 for (const test of testFuncs) {
39 let testProc: ChildProcess | undefined;
40 try {
41 const { skipNode } = getEnv();
42 const hexKey = privateKey.slice(2); // Remove 0x prefix
43 const exportedKey = new Uint8Array(
44 hexKey.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)),
45 );
46 const multibaseKey = bytesToMultibase(exportedKey, "base58btc");
47 const account = privateKeyToAccount(privateKey);
48 const tmpDir = await fs.mkdtemp(
49 path.join(os.tmpdir(), "streamplace-test-"),
50 );
51
52 let testEnv: TestEnv = {
53 addr: "http://127.0.0.1:38080",
54 internalAddr: "http://127.0.0.1:39090",
55 privateKey: privateKey,
56 publicAddress: account.address.toLowerCase(),
57 testDuration: parseInt(duration),
58 multibaseKey,
59 env: {},
60 };
61 if (!skipNode) {
62 testEnv.env = {
63 SP_HTTP_ADDR: `127.0.0.1:${randomPort()}`,
64 SP_HTTP_INTERNAL_ADDR: `127.0.0.1:${randomPort()}`,
65 SP_DATA_DIR: tmpDir,
66 };
67 }
68 if (test.setup) {
69 testEnv = await test.setup(testEnv);
70 }
71 if (!skipNode) {
72 const { addr, internalAddr, proc } = await makeNode({
73 env: testEnv.env,
74 autoQuit: false,
75 });
76 testEnv.addr = addr;
77 testEnv.internalAddr = internalAddr;
78 testProc = proc;
79 }
80 const result = await test.test(testEnv);
81 results.push(result);
82 } catch (e) {
83 console.error("error running test", e.message);
84 results.push(e.message);
85 } finally {
86 if (testProc) {
87 testProc.kill("SIGTERM");
88 }
89 }
90 }
91 const failures = results.filter((r) => r !== null);
92 if (failures.length > 0) {
93 console.error("tests failed", failures.join(", "));
94 return false;
95 }
96 return true;
97 } catch (e) {
98 console.error("error running tests", e.message);
99 return false;
100 }
101}