gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] 01/03: run integration tests in worker process


From: gnunet
Subject: [taler-wallet-core] 01/03: run integration tests in worker process
Date: Wed, 13 Jan 2021 13:48:34 +0100

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

commit 9139a08c4d8e16b68682272aea629610739f7c67
Author: Florian Dold <florian@dold.me>
AuthorDate: Wed Jan 13 13:17:38 2021 +0100

    run integration tests in worker process
---
 .../src/integrationtests/harness.ts                |   9 +-
 .../src/integrationtests/testrunner.ts             | 119 +++++++++++++++++++--
 2 files changed, 116 insertions(+), 12 deletions(-)

diff --git a/packages/taler-wallet-cli/src/integrationtests/harness.ts 
b/packages/taler-wallet-cli/src/integrationtests/harness.ts
index 6d1d4e16..3bfe8570 100644
--- a/packages/taler-wallet-cli/src/integrationtests/harness.ts
+++ b/packages/taler-wallet-cli/src/integrationtests/harness.ts
@@ -1086,13 +1086,13 @@ export class ExchangeService implements 
ExchangeServiceInterface {
 
     this.helperCryptoEddsaProc = this.globalState.spawnService(
       "taler-helper-crypto-eddsa",
-      ["-c", this.configFilename, ...this.timetravelArgArr],
+      ["-c", this.configFilename, "-LDEBUG", ...this.timetravelArgArr],
       `exchange-crypto-eddsa-${this.name}`,
     );
 
     this.helperCryptoRsaProc = this.globalState.spawnService(
       "taler-helper-crypto-rsa",
-      ["-c", this.configFilename, ...this.timetravelArgArr],
+      ["-c", this.configFilename, "-LDEBUG", ...this.timetravelArgArr],
       `exchange-crypto-rsa-${this.name}`,
     );
 
@@ -1458,10 +1458,9 @@ export async function runTestWithState(
   const handleSignal = (s: string) => {
     gc.shutdownSync();
     console.warn(
-      "**** received fatal proces event, shutting down test harness",
+      `**** received fatal proces event, terminating test ${testName}`,
     );
-    status = "fail";
-    p.reject(Error("caught signal"));
+    process.exit(1);
   };
 
   process.on("SIGINT", handleSignal);
diff --git a/packages/taler-wallet-cli/src/integrationtests/testrunner.ts 
b/packages/taler-wallet-cli/src/integrationtests/testrunner.ts
index 578e9488..5717bb76 100644
--- a/packages/taler-wallet-cli/src/integrationtests/testrunner.ts
+++ b/packages/taler-wallet-cli/src/integrationtests/testrunner.ts
@@ -19,6 +19,7 @@ import { runPaymentTest } from "./test-payment";
 import * as fs from "fs";
 import * as path from "path";
 import * as os from "os";
+import * as child_process from "child_process";
 import { runBankApiTest } from "./test-bank-api";
 import { runClaimLoopTest } from "./test-claim-loop";
 import { runExchangeManagementTest } from "./test-exchange-management";
@@ -123,6 +124,11 @@ export function getTestName(tf: TestMainFunction): string {
     .toLowerCase();
 }
 
+interface RunTestChildInstruction {
+  testName: string;
+  testRootDir: string;
+}
+
 export async function runTests(spec: TestRunSpec) {
   const testRootDir = fs.mkdtempSync(
     path.join(os.tmpdir(), "taler-integrationtests-"),
@@ -137,20 +143,70 @@ export async function runTests(spec: TestRunSpec) {
 
   const testResults: TestRunResult[] = [];
 
+  let currentChild: child_process.ChildProcess | undefined;
+
+  const handleSignal = () => {
+    if (currentChild) {
+      currentChild.kill("SIGTERM");
+    }
+    process.exit(3);
+  };
+
+  process.on("SIGINT", () => handleSignal);
+  process.on("SIGTERM", () => handleSignal);
+  process.on("unhandledRejection", handleSignal);
+  process.on("uncaughtException", handleSignal);
+
   for (const [n, testCase] of allTests.entries()) {
     const testName = getTestName(testCase);
     if (spec.include_pattern && !M(testName, spec.include_pattern)) {
       continue;
     }
-    const testDir = path.join(testRootDir, testName);
-    fs.mkdirSync(testDir);
-    console.log(`running test ${testName}`);
-    const gc = new GlobalTestState({
-      testDir,
+
+    const testInstr: RunTestChildInstruction = {
+      testName,
+      testRootDir,
+    };
+
+    currentChild = child_process.fork(__filename, {
+      env: {
+        TWCLI_RUN_TEST_INSTRUCTION: JSON.stringify(testInstr),
+        ...process.env,
+      },
+      stdio: ["pipe", "pipe", "pipe", "ipc"],
     });
-    const result = await runTestWithState(gc, testCase, testName);
+
+    currentChild.stderr?.pipe(process.stderr);
+    currentChild.stdout?.pipe(process.stdout);
+
+    const result: TestRunResult = await new Promise((resolve, reject) => {
+      let msg: TestRunResult | undefined;
+      currentChild!.on("message", (m) => {
+        msg = m as TestRunResult;
+      });
+      currentChild!.on("exit", (code, signal) => {
+        if (signal) {
+          reject(new Error(`test worker exited with signal ${signal}`));
+        } else if (code != 0) {
+          reject(new Error(`test worker exited with code ${code}`));
+        } else if (!msg) {
+          reject(
+            new Error(
+              `test worker exited without giving back the test results`,
+            ),
+          );
+        } else {
+          resolve(msg);
+        }
+      });
+      currentChild!.on("error", (err) => {
+        reject(err);
+      });
+    });
+
+    console.log(`parent: got result ${JSON.stringify(result)}`);
+
     testResults.push(result);
-    console.log(result);
     numTotal++;
     if (result.status === "fail") {
       numFail++;
@@ -160,6 +216,7 @@ export async function runTests(spec: TestRunSpec) {
       numPass++;
     }
   }
+
   const resultsFile = path.join(testRootDir, "results.json");
   fs.writeFileSync(
     path.join(testRootDir, "results.json"),
@@ -179,3 +236,51 @@ export function getTestInfo(): TestInfo[] {
     name: getTestName(x),
   }));
 }
+
+const runTestInstrStr = process.env["TWCLI_RUN_TEST_INSTRUCTION"];
+if (runTestInstrStr) {
+  // Test will call taler-wallet-cli, so we must not propagate this variable.
+  delete process.env["TWCLI_RUN_TEST_NAME"];
+  const { testRootDir, testName } = JSON.parse(
+    runTestInstrStr,
+  ) as RunTestChildInstruction;
+  console.log(`running test ${testName} in worker process`);
+
+  process.on("disconnect", () => {
+    process.exit(3);
+  });
+
+  const runTest = async () => {
+    let testMain: TestMainFunction | undefined;
+    for (const t of allTests) {
+      if (getTestName(t) === testName) {
+        testMain = t;
+        break;
+      }
+    }
+
+    if (!process.send) {
+      console.error("can't communicate with parent");
+      process.exit(2);
+    }
+
+    if (!testMain) {
+      console.log(`test ${testName} not found`);
+      process.exit(2);
+    }
+
+    const testDir = path.join(testRootDir, testName);
+    fs.mkdirSync(testDir);
+    console.log(`running test ${testName}`);
+    const gc = new GlobalTestState({
+      testDir,
+    });
+    const testResult = await runTestWithState(gc, testMain, testName);
+    process.send(testResult);
+  };
+
+  runTest().catch((e) => {
+    console.log(e);
+    process.exit(1);
+  });
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]