summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/full_check.yaml65
-rw-r--r--.gitignore4
-rwxr-xr-xtests/compare.ts17
-rw-r--r--tests/deno.lock46
-rw-r--r--tests/integration.test.ts28
-rwxr-xr-xtests/regression.test.ts6
-rwxr-xr-xtests/utils.ts143
7 files changed, 187 insertions, 122 deletions
diff --git a/.github/workflows/full_check.yaml b/.github/workflows/full_check.yaml
index 2beda33..abc91f8 100644
--- a/.github/workflows/full_check.yaml
+++ b/.github/workflows/full_check.yaml
@@ -585,7 +585,8 @@ jobs:
cd impls/monero.ts
deno run --unstable-ffi --allow-ffi checksum.ts
- regression_check:
+ regression_tests_linux:
+ name: linux regression tests
strategy:
matrix:
coin: [monero, wownero]
@@ -611,7 +612,35 @@ jobs:
- name: Run regression tests
run: COIN="${{ matrix.coin }}" deno test -A tests/regression.test.ts
- integration_check:
+ regression_tests_macos:
+ name: macos regression tests
+ strategy:
+ matrix:
+ coin: [monero, wownero]
+ needs: [
+ lib_macos
+ ]
+ runs-on: macos-14
+ steps:
+ - uses: denoland/setup-deno@v2
+ with:
+ deno-version: v2.x
+
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ submodules: recursive
+
+ - uses: actions/download-artifact@v4
+ with:
+ name: linux ${{ matrix.coin }}
+ path: release/${{ matrix.coin }}
+
+ - name: Run regression tests
+ run: COIN="${{ matrix.coin }}" deno test -A tests/regression.test.ts
+
+ integration_tests_linux:
+ name: linux integration tests
strategy:
matrix:
coin: [monero, wownero]
@@ -642,6 +671,38 @@ jobs:
SECRET_WALLET_RESTORE_HEIGHT: ${{ secrets.SECRET_WALLET_RESTORE_HEIGHT }}
+ integration_tests_macos:
+ name: macos integration tests
+ strategy:
+ matrix:
+ coin: [monero, wownero]
+ needs: [
+ lib_macos
+ ]
+ runs-on: macos-14
+ steps:
+ - uses: denoland/setup-deno@v2
+ with:
+ deno-version: v2.x
+
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ submodules: recursive
+
+ - uses: actions/download-artifact@v4
+ with:
+ name: linux ${{ matrix.coin }}
+ path: release/${{ matrix.coin }}
+
+ - name: Run integration tests
+ run: COIN="${{ matrix.coin }}" deno test -A tests/integration.test.ts
+ env:
+ SECRET_WALLET_PASSWORD: ${{ secrets.SECRET_WALLET_PASSWORD }}
+ SECRET_WALLET_MNEMONIC: ${{ secrets.SECRET_WALLET_MNEMONIC }}
+ SECRET_WALLET_RESTORE_HEIGHT: ${{ secrets.SECRET_WALLET_RESTORE_HEIGHT }}
+
+
comment_pr:
name: comment on pr
runs-on: ubuntu-latest
diff --git a/.gitignore b/.gitignore
index 9159f7d..7dc5983 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,4 @@
release/
build/
-tests/monero-cli
-tests/wownero-cli
-tests/libs
+tests/dependencies
tests/wallets
diff --git a/tests/compare.ts b/tests/compare.ts
index 2fd27b8..8c13fc5 100755
--- a/tests/compare.ts
+++ b/tests/compare.ts
@@ -1,24 +1,13 @@
import { assertEquals } from "jsr:@std/assert";
-import {
- loadMoneroDylib,
- loadWowneroDylib,
- moneroSymbols,
- WalletManager,
- wowneroSymbols,
-} from "../impls/monero.ts/mod.ts";
+import { WalletManager } from "../impls/monero.ts/mod.ts";
+import { loadDylib } from "./utils.ts";
const coin = Deno.args[0] as "monero" | "wownero";
const version = Deno.args[1];
const walletInfo = JSON.parse(Deno.args[2]);
-if (coin === "monero") {
- const dylib = Deno.dlopen(`tests/libs/${version}/monero_libwallet2_api_c.so`, moneroSymbols);
- loadMoneroDylib(dylib);
-} else {
- const dylib = Deno.dlopen(`tests/libs/${version}/wownero_libwallet2_api_c.so`, wowneroSymbols);
- loadWowneroDylib(dylib);
-}
+loadDylib(coin, version);
const walletManager = await WalletManager.new();
const wallet = await walletManager.openWallet(walletInfo.path, walletInfo.password);
diff --git a/tests/deno.lock b/tests/deno.lock
index b67d77d..8d368f6 100644
--- a/tests/deno.lock
+++ b/tests/deno.lock
@@ -4,19 +4,15 @@
"jsr:@david/dax@*": "0.42.0",
"jsr:@david/path@0.2": "0.2.0",
"jsr:@david/which@~0.4.1": "0.4.1",
- "jsr:@std/assert@*": "0.221.0",
"jsr:@std/assert@0.221": "0.221.0",
"jsr:@std/bytes@0.221": "0.221.0",
- "jsr:@std/fmt@0.221": "0.221.0",
"jsr:@std/fmt@1": "1.0.2",
- "jsr:@std/fs@1": "1.0.4",
+ "jsr:@std/fs@1": "1.0.5",
"jsr:@std/io@0.221": "0.221.0",
- "jsr:@std/path@1": "1.0.6",
- "jsr:@std/path@1.0.8": "1.0.8",
- "jsr:@std/path@^1.0.6": "1.0.6",
- "jsr:@std/streams@0.221": "0.221.0",
- "jsr:@std/streams@^1.0.7": "1.0.7",
- "jsr:@std/tar@*": "0.1.2"
+ "jsr:@std/path@*": "1.0.8",
+ "jsr:@std/path@1": "1.0.8",
+ "jsr:@std/path@^1.0.7": "1.0.8",
+ "jsr:@std/streams@0.221": "0.221.0"
},
"jsr": {
"@david/dax@0.42.0": {
@@ -24,11 +20,11 @@
"dependencies": [
"jsr:@david/path",
"jsr:@david/which",
- "jsr:@std/fmt@1",
+ "jsr:@std/fmt",
"jsr:@std/fs",
"jsr:@std/io",
"jsr:@std/path@1",
- "jsr:@std/streams@0.221"
+ "jsr:@std/streams"
]
},
"@david/path@0.2.0": {
@@ -42,36 +38,27 @@
"integrity": "896a682b111f92ab866cc70c5b4afab2f5899d2f9bde31ed00203b9c250f225e"
},
"@std/assert@0.221.0": {
- "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a",
- "dependencies": [
- "jsr:@std/fmt@0.221"
- ]
+ "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a"
},
"@std/bytes@0.221.0": {
"integrity": "64a047011cf833890a4a2ab7293ac55a1b4f5a050624ebc6a0159c357de91966"
},
- "@std/fmt@0.221.0": {
- "integrity": "379fed69bdd9731110f26b9085aeb740606b20428ce6af31ef6bd45ef8efa62a"
- },
"@std/fmt@1.0.2": {
"integrity": "87e9dfcdd3ca7c066e0c3c657c1f987c82888eb8103a3a3baa62684ffeb0f7a7"
},
- "@std/fs@1.0.4": {
- "integrity": "2907d32d8d1d9e540588fd5fe0ec21ee638134bd51df327ad4e443aaef07123c",
+ "@std/fs@1.0.5": {
+ "integrity": "41806ad6823d0b5f275f9849a2640d87e4ef67c51ee1b8fb02426f55e02fd44e",
"dependencies": [
- "jsr:@std/path@^1.0.6"
+ "jsr:@std/path@^1.0.7"
]
},
"@std/io@0.221.0": {
"integrity": "faf7f8700d46ab527fa05cc6167f4b97701a06c413024431c6b4d207caa010da",
"dependencies": [
- "jsr:@std/assert@0.221",
+ "jsr:@std/assert",
"jsr:@std/bytes"
]
},
- "@std/path@1.0.6": {
- "integrity": "ab2c55f902b380cf28e0eec501b4906e4c1960d13f00e11cfbcd21de15f18fed"
- },
"@std/path@1.0.8": {
"integrity": "548fa456bb6a04d3c1a1e7477986b6cffbce95102d0bb447c67c4ee70e0364be"
},
@@ -80,15 +67,6 @@
"dependencies": [
"jsr:@std/io"
]
- },
- "@std/streams@1.0.7": {
- "integrity": "1a93917ca0c58c01b2bfb93647189229b1702677f169b6fb61ad6241cd2e499b"
- },
- "@std/tar@0.1.2": {
- "integrity": "98183102395decd6268253996177804f818580ef547a25b81da0e7cc334db708",
- "dependencies": [
- "jsr:@std/streams@^1.0.7"
- ]
}
}
}
diff --git a/tests/integration.test.ts b/tests/integration.test.ts
index 1a65009..100bd43 100644
--- a/tests/integration.test.ts
+++ b/tests/integration.test.ts
@@ -1,16 +1,7 @@
-import {
- CoinsInfo,
- type Dylib,
- loadMoneroDylib,
- loadWowneroDylib,
- moneroSymbols,
- Wallet,
- WalletManager,
- wowneroSymbols,
-} from "../impls/monero.ts/mod.ts";
+import { CoinsInfo, Wallet, WalletManager } from "../impls/monero.ts/mod.ts";
import { assert, assertEquals } from "jsr:@std/assert";
-import { $, downloadCli, getMoneroC } from "./utils.ts";
+import { $, loadDylib, prepareCli, prepareMoneroC } from "./utils.ts";
const coin = Deno.env.get("COIN");
if (coin !== "monero" && coin !== "wownero") {
@@ -53,7 +44,7 @@ const DESTINATION_ADDRESS = coin === "monero" ? MONERO_DESTINATION_ADDRESS : WOW
const BILLION = 10n ** 9n;
-await getMoneroC(coin, "next");
+await prepareMoneroC(coin, "next");
interface WalletInfo {
name: string;
@@ -74,14 +65,7 @@ async function clearWallets() {
await Deno.mkdir("tests/wallets/");
}
-let dylib: Dylib;
-if (coin === "monero") {
- dylib = Deno.dlopen(`tests/libs/next/monero_libwallet2_api_c.so`, moneroSymbols);
- loadMoneroDylib(dylib);
-} else {
- dylib = Deno.dlopen(`tests/libs/next/wownero_libwallet2_api_c.so`, wowneroSymbols);
- loadWowneroDylib(dylib);
-}
+loadDylib(coin, "next");
Deno.test("0001-polyseed.patch", async (t) => {
const WALLETS: Record<"monero" | "wownero", WalletInfo[]> = {
@@ -487,7 +471,7 @@ Deno.test("0004-coin-control.patch", {
Deno.test("0009-Add-recoverDeterministicWalletFromSpendKey.patch", async () => {
await Promise.all([
- downloadCli(coin),
+ prepareCli(coin),
clearWallets(),
]);
@@ -498,7 +482,7 @@ Deno.test("0009-Add-recoverDeterministicWalletFromSpendKey.patch", async () => {
await Deno.remove("./tests/wallets/stoat");
- const cliPath = `./tests/${coin}-cli/${coin}-wallet-cli`;
+ const cliPath = `./tests/dependencies/${coin}-cli/${coin}-wallet-cli`;
const moneroCliSeed = (await $.raw`${cliPath} --wallet-file ./tests/wallets/stoat --password gornostay --command seed`
.stdinText(`gornostay\n`)
.lines()).slice(-3).join(" ");
diff --git a/tests/regression.test.ts b/tests/regression.test.ts
index 82a9f95..14e9847 100755
--- a/tests/regression.test.ts
+++ b/tests/regression.test.ts
@@ -1,4 +1,4 @@
-import { $, createWalletViaCli, downloadCli, getMoneroC, getMoneroCTags } from "./utils.ts";
+import { $, createWalletViaCli, getMoneroCTags, prepareCli, prepareMoneroC } from "./utils.ts";
const coin = Deno.env.get("COIN");
if (coin !== "monero" && coin !== "wownero") {
@@ -11,7 +11,7 @@ Deno.test(`Regression tests (${coin})`, async (t) => {
const tags = await getMoneroCTags();
const latestTag = tags[0];
- await Promise.all([getMoneroC(coin, "next"), await getMoneroC(coin, latestTag), downloadCli(coin)]);
+ await Promise.all([prepareMoneroC(coin, "next"), await prepareMoneroC(coin, latestTag), prepareCli(coin)]);
await t.step("Simple (next, latest, next)", async () => {
const walletInfo = await createWalletViaCli(coin, "dog", "sobaka");
@@ -27,7 +27,7 @@ Deno.test(`Regression tests (${coin})`, async (t) => {
const walletInfo = await createWalletViaCli(coin, "cat", "koshka");
for (const version of tags.toReversed()) {
- if (version !== "next" && version !== tags[0]) await getMoneroC(coin, version);
+ if (version !== "next" && version !== tags[0]) await prepareMoneroC(coin, version);
await $`deno run -A ./tests/compare.ts ${coin} ${version} ${JSON.stringify(walletInfo)}`;
}
diff --git a/tests/utils.ts b/tests/utils.ts
index cd05232..60afdb5 100755
--- a/tests/utils.ts
+++ b/tests/utils.ts
@@ -1,4 +1,15 @@
import { build$, CommandBuilder } from "jsr:@david/dax";
+import { dirname, join } from "jsr:@std/path";
+import {
+ downloadDependencies,
+ getFileInfo,
+ moneroCInfos,
+ moneroCliInfo,
+ Target,
+ target,
+ wowneroCliInfo,
+} from "./download_deps.ts";
+import { loadMoneroDylib, loadWowneroDylib, moneroSymbols, wowneroSymbols } from "../impls/monero.ts/mod.ts";
export const $ = build$({
commandBuilder: new CommandBuilder()
@@ -10,32 +21,69 @@ export const $ = build$({
type Coin = "monero" | "wownero";
-export async function downloadMoneroCli() {
- const MONERO_CLI_FILE_NAME = "monero-linux-x64-v0.18.3.4";
- const MONERO_WALLET_CLI_URL = `https://downloads.getmonero.org/cli/${MONERO_CLI_FILE_NAME}.tar.bz2`;
+export const dylibNames: (coin: Coin) => Partial<Record<Target, string>> = (coin) => ({
+ linux_x86_64: `${coin}_x86_64-linux-gnu_libwallet2_api_c.so`,
+ darwin_aarch64: `${coin}_aarch64-apple-darwin11_libwallet2_api_c.dylib`,
+ windows_x86_64: `${coin}_x86_64-w64-mingw32_libwallet2_api_c.dll`,
+});
- await $`wget -q -o /dev/null ${MONERO_WALLET_CLI_URL}`;
- await $
- .raw`tar -xf ${MONERO_CLI_FILE_NAME}.tar.bz2 --one-top-level=monero-cli --strip-components=1 -C tests`;
- await $.raw`rm ${MONERO_CLI_FILE_NAME}.tar.bz2`;
+export const moneroTsDylibNames: (coin: Coin) => Partial<Record<Target, string>> = (coin) => ({
+ linux_x86_64: `${coin}_libwallet2_api_c.so`,
+ darwin_aarch64: `${coin}_aarch64-apple-darwin11_libwallet2_api_c.dylib`,
+ windows_x86_64: `${coin}_libwallet2_api_c.dll`,
+});
+
+export function loadDylib(coin: Coin, version: MoneroCVersion) {
+ const dylibName = moneroTsDylibNames(coin)[target]!;
+
+ if (coin === "monero") {
+ const dylib = Deno.dlopen(`tests/dependencies/libs/${version}/${dylibName}`, moneroSymbols);
+ loadMoneroDylib(dylib);
+ return dylib;
+ } else {
+ const dylib = Deno.dlopen(`tests/dependencies/libs/${version}/${dylibName}`, wowneroSymbols);
+ loadWowneroDylib(dylib);
+ return dylib;
+ }
}
-export async function downloadWowneroCli() {
- const WOWNERO_CLI_FILE_NAME = "wownero-x86_64-linux-gnu-59db3fe8d";
- const WOWNERO_WALLET_CLI_URL =
- `https://codeberg.org/wownero/wownero/releases/download/v0.11.2.0/wownero-x86_64-linux-gnu-59db3fe8d.tar.bz2`;
+export async function extract(path: string, out: string) {
+ const outDir = out.endsWith("/") ? out : dirname(out);
+ await Deno.mkdir(outDir, { recursive: true });
+
+ if (path.endsWith(".tar.bz2")) {
+ let args = `-C ${dirname(out)}`;
+ if (outDir !== out) {
+ args = `-C ${out} --strip-components=1`;
+ }
+ await $.raw`tar -xf ${path} ${args}`;
+ } else if (path.endsWith(".zip")) {
+ await $.raw`unzip ${path} -nu -d ${outDir}`;
+ } else if (path.endsWith(".xz")) {
+ await $.raw`xz -kd ${path}`;
+ await Deno.rename(path.slice(0, -3), out);
+ } else {
+ throw new Error("Unsupported archive file for:" + path);
+ }
+}
- await $`wget -q -o /dev/null ${WOWNERO_WALLET_CLI_URL}`;
- await $
- .raw`tar -xf ${WOWNERO_CLI_FILE_NAME}.tar.bz2 --one-top-level=wownero-cli --strip-components=1 -C tests`;
- await $.raw`rm ${WOWNERO_CLI_FILE_NAME}.tar.bz2`;
+export async function prepareMoneroCli() {
+ downloadDependencies(moneroCliInfo);
+ const path = join("./tests/dependencies", moneroCliInfo.outDir ?? "", getFileInfo(moneroCliInfo).name);
+ await extract(path, "./tests/dependencies/monero-cli/");
}
-export function downloadCli(coin: Coin) {
+export async function prepareWowneroCli() {
+ downloadDependencies(wowneroCliInfo);
+ const path = join("./tests/dependecies", wowneroCliInfo.outDir ?? "", getFileInfo(wowneroCliInfo).name);
+ await extract(path, "./tests/dependencies/wownero-cli/");
+}
+
+export function prepareCli(coin: Coin) {
if (coin === "wownero") {
- return downloadWowneroCli();
+ return prepareWowneroCli();
}
- return downloadMoneroCli();
+ return prepareMoneroCli();
}
interface WalletInfo {
@@ -54,7 +102,7 @@ export async function createWalletViaCli(
password: string,
): Promise<WalletInfo> {
const path = `./tests/wallets/${name}`;
- const cliPath = `./tests/${coin}-cli/${coin}-wallet-cli`;
+ const cliPath = `./tests/dependencies/${coin}-cli/${coin}-wallet-cli`;
await $
.raw`${cliPath} --generate-new-wallet ${path} --password ${password} --mnemonic-language English --command exit`
@@ -97,35 +145,42 @@ export async function createWalletViaCli(
export type MoneroCVersion = "next" | (string & {});
export async function getMoneroCTags(): Promise<string[]> {
- return ((
- await (await fetch(
- "https://api.github.com/repos/MrCyjanek/monero_c/releases",
- )).json()
- ) as { tag_name: string }[])
- .map(({ tag_name }) => tag_name);
+ const response = await fetch(
+ "https://api.github.com/repos/MrCyjanek/monero_c/releases",
+ );
+
+ if (!response.ok) {
+ throw new Error("Could not receive monero_c release tags");
+ }
+
+ const json = await response.json() as { tag_name: string }[];
+ return json.map(({ tag_name }) => tag_name);
}
-export async function getMoneroC(coin: Coin, version: MoneroCVersion) {
- const dylibName = `${coin}_x86_64-linux-gnu_libwallet2_api_c.so`;
- const endpointDylibName = `${coin}_libwallet2_api_c.so`;
+
+export async function prepareMoneroC(coin: Coin, version: MoneroCVersion) {
+ const dylibName = dylibNames(coin)[target];
+ const moneroTsDylibName = moneroTsDylibNames(coin)[target];
+
+ if (!dylibName || !moneroTsDylibName) {
+ throw new Error(`Missing dylib name value for target: ${target}`);
+ }
+
const releaseDylibName = dylibName.slice(`${coin}_`.length);
if (version === "next") {
- await $.raw`xz -kd release/${coin}/${releaseDylibName}.xz`;
- await $`mkdir -p tests/libs/next`;
- await $`mv release/${coin}/${releaseDylibName} tests/libs/next/${endpointDylibName}`;
+ await extract(
+ `./release/${coin}/${releaseDylibName}.xz`,
+ `./tests/dependencies/libs/next/${moneroTsDylibName}`,
+ );
} else {
- const downloadUrl = `https://github.com/MrCyjaneK/monero_c/releases/download/${version}/${dylibName}.xz`;
-
- const file = await Deno.open(`./tests/${dylibName}.xz`, {
- create: true,
- write: true,
- });
- file.write(await (await fetch(downloadUrl)).bytes());
- file.close();
-
- await $.raw`xz -d ./tests/${dylibName}.xz`;
- await $.raw`mkdir -p ./tests/libs/${version}`;
- await $
- .raw`mv ./tests/${dylibName} ./tests/libs/${version}/${endpointDylibName}`;
+ const downloadInfo = moneroCInfos.find((info) => info.outDir?.includes(version));
+ if (downloadInfo) {
+ await downloadDependencies(downloadInfo);
+ }
+
+ await extract(
+ `./tests/dependencies/libs/${version}/${dylibName}.xz`,
+ `./tests/dependencies/libs/${version}/${moneroTsDylibName}`,
+ );
}
}