Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(ci): Nightly Integration testing #2596

Merged
merged 19 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .actrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-P ubuntu-latest=catthehacker/ubuntu:runner-latest
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
# --env ACTIONS_RUNTIME_TOKEN=foobar
# --bind
123 changes: 123 additions & 0 deletions .github/workflows/test-integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
name: test-integration

on:
workflow_dispatch:
schedule:
- cron: "0 2 * * *" # Run nightly at 2 AM UTC

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }}
cancel-in-progress: true

jobs:
wasm-packages-build:
runs-on: ubuntu-latest
env:
CACHED_PATH: /tmp/nix-cache

steps:
- name: Install Yarn
run: npm install -g yarn

- name: Checkout noir sources
uses: actions/checkout@v4

- name: Checkout acvm sources
uses: actions/checkout@v3 # v3 is needed here otherwise this fails in local execution
with:
repository: noir-lang/acvm
path: acvm

- name: Setup Nix
uses: cachix/install-nix-action@v22
with:
nix_path: nixpkgs=channel:nixos-23.05
github_access_token: ${{ secrets.GITHUB_TOKEN }}

- uses: cachix/cachix-action@v12
with:
name: barretenberg
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"

- name: Restore nix store cache
if: env.ACT != 'true'
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
uses: actions/cache/restore@v3
id: cache
with:
path: ${{ env.CACHED_PATH }}
key: ${{ runner.os }}-flake-wasm-${{ hashFiles('*.lock') }}

# Based on https://github.com/marigold-dev/deku/blob/b5016f0cf4bf6ac48db9111b70dd7fb49b969dfd/.github/workflows/build.yml#L26
- name: Copy cache into nix store
if: steps.cache.outputs.cache-hit == 'true' && env.ACT != 'true'
# We don't check the signature because we're the one that created the cache
run: |
for narinfo in ${{ env.CACHED_PATH }}/*.narinfo; do
path=$(head -n 1 "$narinfo" | awk '{print $2}')
nix copy --no-check-sigs --from "file://${{ env.CACHED_PATH }}" "$path"
done

- name: Build noir_wasm package
run: |
nix build -L .#wasm
mkdir -p ./.packages/noir_wasm
cp -r ./result/* ./.packages/noir_wasm/
echo "UPLOAD_PATH=$(readlink -f result)" >> $GITHUB_ENV

- name: Upload `noir_wasm` artifact
if: env.ACT != 'true'
uses: actions/upload-artifact@v3
with:
name: noir_wasm
path: ${{ env.UPLOAD_PATH }}
retention-days: 3

- name: Build noirc_abi_wasm package
run: |
nix build -L .#noirc_abi_wasm
mkdir -p ./.packages/noirc_abi_wasm
cp -r ./result/* ./.packages/noirc_abi_wasm/
echo "UPLOAD_PATH=$(readlink -f result)" >> $GITHUB_ENV

- name: Upload `noirc_abi_wasm` artifact
if: env.ACT != 'true'
uses: actions/upload-artifact@v3
with:
name: noirc_abi_wasm
path: ${{ env.UPLOAD_PATH }}
retention-days: 3

- name: Build `acvm_js` package
working-directory: ./acvm
run: |
nix build -L .#
mkdir -p ../.packages/acvm_js
cp -r ./result/* ../.packages/acvm_js/
echo "UPLOAD_PATH=$(readlink -f result)" >> $GITHUB_ENV
kevaundray marked this conversation as resolved.
Show resolved Hide resolved

- name: Upload `acvm_js` artifact
if: env.ACT != 'true'
uses: actions/upload-artifact@v3
with:
name: acvm_js
path: ${{ env.UPLOAD_PATH }}
retention-days: 3

- name: Install Yarn (local)
if: env.ACT == 'true'
run: npm install -g yarn
kobyhallx marked this conversation as resolved.
Show resolved Hide resolved

# - name: Install `playwright` deps
# working-directory: ./crates/integration-tests
# run: |
# npx playwright install
# npx playwright install-deps
kevaundray marked this conversation as resolved.
Show resolved Hide resolved

- name: Install `integration-tests` dependencies
working-directory: ./crates/integration-tests
run: yarn install

- name: Run `integration-tests`
working-directory: ./crates/integration-tests
run: |
yarn test:browser
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@ result
# Github Actions scratch space
# This gives a location to download artifacts into the repository in CI without making git dirty.
libbarretenberg-wasm32

.packages/
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
19 changes: 19 additions & 0 deletions crates/integration-tests/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint", "prettier"],
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
rules: {
"comma-spacing": ["error", { before: false, after: true }],
// "no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"warn", // or "error"
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
"prettier/prettier": "error",
}
};
36 changes: 36 additions & 0 deletions crates/integration-tests/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "integration-tests",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha",
"test:browser": "web-test-runner",
"test:node": "env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha",
"test:integration:browser": "web-test-runner test//integration/browser/**/*.test.ts",
"test:integration:browser:watch": "web-test-runner test/integration/browser/**/*.test.ts --watch"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@esm-bundle/chai": "^4.3.4-fix.0",
"@web/dev-server-esbuild": "^0.3.6",
"@web/test-runner": "^0.15.3",
"@web/test-runner-playwright": "^0.10.0",
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
"@web/test-runner-webdriver": "^0.7.0",
"chai": "^4.3.7",
"fflate": "^0.8.0",
"mocha": "^10.2.0",
"smol-toml": "^1.1.2",
"ts-node": "^10.9.1",
"typescript": "^5.0.4"
},
"dependencies": {
"@aztec/bb.js": "^0.5.1",
"@noir-lang/acvm_js": "./../../.packages/acvm_js",
"@noir-lang/noir-source-resolver": "^1.1.4",
"@noir-lang/noir_wasm": "./../../.packages/noir_wasm",
"@noir-lang/noirc_abi": "./../../.packages/noirc_abi_wasm"
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { expect } from '@esm-bundle/chai';
import { initialiseResolver } from "@noir-lang/noir-source-resolver";
import newCompiler, {
compile
} from "@noir-lang/noir_wasm";
import { decompressSync as gunzip } from 'fflate';
import newABICoder, { abiEncode } from "@noir-lang/noirc_abi";
import initACVM, {
executeCircuit,
WitnessMap,
compressWitness,
} from "@noir-lang/acvm_js";

// @ts-ignore
import { Barretenberg, RawBuffer, Crs } from '@aztec/bb.js';

import * as TOML from 'smol-toml'

await newCompiler();
await newABICoder();
await initACVM();

async function getFile(url: URL): Promise<string> {

const response = await fetch(url)

if (!response.ok) throw new Error('Network response was not OK');

return await response.text();
}

const CIRCUIT_SIZE = 2 ** 19;


const test_cases = [
{
case: "crates/nargo_cli/tests/execution_success/1_mul"
},
// Below fails
TomAFrench marked this conversation as resolved.
Show resolved Hide resolved
// {
// case: "crates/nargo_cli/tests/execution_success/double_verify_proof"
// }
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
];

const numberOfThreads = navigator.hardwareConcurrency || 1;

let suite = Mocha.Suite.create(mocha.suite, "Noir end to end test");

suite.timeout(60*10e3);//10mins

test_cases.forEach((testInfo) => {
const test_name = testInfo.case.split("/").pop();
const mochaTest = new Mocha.Test(`${test_name} (Compile, Execute, Proove, Verify)`, async () => {

const base_relative_path = "../../../../..";
const test_case = testInfo.case;

const noir_source_url = new URL(`${base_relative_path}/${test_case}/src/main.nr`, import.meta.url);
const prover_toml_url = new URL(`${base_relative_path}/${test_case}/Prover.toml`, import.meta.url);

const noir_source = await getFile(noir_source_url);
const prover_toml = await getFile(prover_toml_url);

expect(noir_source).to.be.a.string;

initialiseResolver((id: String) => {
return noir_source;
});

const inputs = TOML.parse(prover_toml);

expect(inputs, "Prover.toml").to.be.an('object');

let compile_output;

try {

compile_output = await compile({});

expect(await compile_output, "Compile output ").to.be.an('object');

} catch (e) {
expect(e, "Compilation Step").to.not.be.an('error');
throw e;
}


let witnessMap = abiEncode(compile_output.abi, inputs, null);
kobyhallx marked this conversation as resolved.
Show resolved Hide resolved
try {

witnessMap = abiEncode(compile_output.abi, inputs, null);

} catch (e) {
expect(e, "Abi Encoding Step").to.not.be.an('error');
throw e;
}

let solvedWitness: WitnessMap;
let compressedByteCode;
try {
compressedByteCode = Uint8Array.from(atob(compile_output.circuit), c => c.charCodeAt(0));

solvedWitness = await executeCircuit(
compressedByteCode,
witnessMap,
() => {
throw Error("unexpected oracle");
}
);

} catch (e) {
expect(e, "Abi Encoding Step").to.not.be.an('error');
throw e;
}

try {
const compressedWitness = compressWitness(solvedWitness);
const acirUint8Array = gunzip(compressedByteCode);
const witnessUint8Array = gunzip(compressedWitness);

const isRecursive = true;
const api = await Barretenberg.new(numberOfThreads);
await api.commonInitSlabAllocator(CIRCUIT_SIZE);

// Plus 1 needed!
const crs = await Crs.new(CIRCUIT_SIZE + 1);
await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data()));

const acirComposer = await api.acirNewAcirComposer(CIRCUIT_SIZE);

const proof = await api.acirCreateProof(
acirComposer,
acirUint8Array,
witnessUint8Array,
isRecursive
);


const verified = await api.acirVerifyProof(acirComposer, proof, isRecursive);

expect(verified).to.be.true;

} catch (e) {
expect(e, "Proving and Verifying").to.not.be.an('error');
throw e;
}

});

suite.addTest(mochaTest);

});
37 changes: 37 additions & 0 deletions crates/integration-tests/web-test-runner.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { fileURLToPath } from 'url';
import { esbuildPlugin } from "@web/dev-server-esbuild";
// import { playwrightLauncher } from "@web/test-runner-playwright";
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
import { webdriverLauncher } from '@web/test-runner-webdriver';

export default {
browsers: [
// playwrightLauncher({ product: "chromium" }),
// playwrightLauncher({ product: "webkit" }),
// playwrightLauncher({ product: "firefox" }),
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
webdriverLauncher({
automationProtocol: 'webdriver',
capabilities: {
browserName: 'firefox',
'moz:firefoxOptions': {
args: ['-headless'],
},
},
}),

],
plugins: [
esbuildPlugin({
ts: true,
}),
],
files: ["test/integration/browser/**/*.test.ts"],
nodeResolve: { browser: true },
testFramework: {
config: {
ui: "bdd",
// timeout: 420000,
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
},
},
rootDir: fileURLToPath(new URL('./../..', import.meta.url)),

};
Loading