Skip to content

Commit

Permalink
test: fix failed tests due to port reuse
Browse files Browse the repository at this point in the history
  • Loading branch information
mhchia committed Jun 9, 2023
1 parent 7fd7812 commit eb5e38a
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 33 deletions.
15 changes: 2 additions & 13 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,10 @@ jobs:
id: cache-zkeyFiles
uses: actions/cache@v3
with:
path: ./zkeyFiles/rln
path: ./zkeyFiles
# Since the version of rln-circuits is specified in `scripts/build-zkeys.sh`,
# as long as the file doesn't change we can reuse the zkeyFiles.
key: ${{ runner.os }}-${{ matrix.node-version }}-zkeyFiles-${{ hashFiles('./scripts/build-zkeys.sh') }}
- name: Cache cloned js-rln zkeyFiles
id: cache-js-rln-zkeyFiles
uses: actions/cache@v3
with:
path: ./zkeyFiles/js-rln
# Since the version of js-rln is specified in `scripts/clone-js-rln-zkeys.sh`,
# as long as the file doesn't change we can reuse the zkeyFiles from js-rln.
key: ${{ runner.os }}-${{ matrix.node-version }}-zkeyFiles-${{ hashFiles('./scripts/clone-js-rln-zkeys.sh') }}
- name: Build circuit params
run: ./scripts/build-zkeys.sh
- name: Clone js-rln params
run: ./scripts/clone-js-rln-zkeys.sh
- run: npm run lint
- run: npm test
- run: npm run test:debug
4 changes: 4 additions & 0 deletions hardhat.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.18",
};
2 changes: 1 addition & 1 deletion jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const config: Config.InitialOptions = {
},
"silent": true,
"detectOpenHandles": true,
"testTimeout": 60000,
"testTimeout": 100000,
"collectCoverage": true,
"forceExit": true,
};
Expand Down
5 changes: 4 additions & 1 deletion src/rln.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,15 @@ export interface IRLN {
register(userMessageLimit: bigint, messageIDCounter?: IMessageIDCounter): Promise<void>
// User withdraws from the registry
withdraw(): Promise<void>
// User slashes another user with their secret
slash(secretToBeSlashed: bigint, receiver?: string): Promise<void>

/* Proof-related */
// Generate a proof for the given epoch and message
createProof(epoch: bigint, message: string): Promise<RLNFullProof>
// Verify a proof
verifyProof(proof: RLNFullProof): Promise<boolean>
// Verify a proof and check if the proof is valid
saveProof(proof: RLNFullProof): Promise<EvaluatedProof>
}

Expand Down Expand Up @@ -265,5 +269,4 @@ export class RLN implements IRLN {
const { x, y, nullifier } = snarkProof.publicSignals
return this.cache.addProof({ x, y, nullifier, epoch })
}

}
5 changes: 4 additions & 1 deletion tests/contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe("RLNContract", () => {
let mockVerifierContract: ethers.Contract
let rlnContractWrapper: RLNContract
let waitUntilFreezePeriodPassed: () => Promise<void>
let killNode: () => Promise<void>

let signerAnother: ethers.Signer
let rlnContractWrapperAnother: RLNContract
Expand Down Expand Up @@ -71,6 +72,7 @@ describe("RLNContract", () => {
rlnContract = deployed.rlnContract
rlnContractWrapper = deployed.rlnContractWrapper
waitUntilFreezePeriodPassed = deployed.waitUntilFreezePeriodPassed
killNode = deployed.killNode
signerAnother = deployed.signer1
rlnContractWrapperAnother = new RLNContract({
provider,
Expand All @@ -84,7 +86,8 @@ describe("RLNContract", () => {

afterAll(async () => {
console.log("killing node")
node.kill('SIGKILL')
await killNode()
console.log("node killed")
});

it("should be enough tokens in signer account", async () => {
Expand Down
57 changes: 49 additions & 8 deletions tests/factories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@ import { rlnContractABI, RLNContract } from "../src/contract-wrapper";

import { rlnContractBytecode, testERC20ContractBytecode, mockVerifierBytecode } from "./configs";

export const url = "http://127.0.0.1:8545"
const url = "http://127.0.0.1:8545"
const testERC20ABI = '[{"inputs": [{"internalType": "uint256", "name": "amount", "type": "uint256"}], "stateMutability": "nonpayable", "type": "constructor"}, {"anonymous": false, "inputs": [{"indexed": true, "internalType": "address", "name": "owner", "type": "address"}, {"indexed": true, "internalType": "address", "name": "spender", "type": "address"}, {"indexed": false, "internalType": "uint256", "name": "value", "type": "uint256"}], "name": "Approval", "type": "event"}, {"anonymous": false, "inputs": [{"indexed": true, "internalType": "address", "name": "from", "type": "address"}, {"indexed": true, "internalType": "address", "name": "to", "type": "address"}, {"indexed": false, "internalType": "uint256", "name": "value", "type": "uint256"}], "name": "Transfer", "type": "event"}, {"inputs": [{"internalType": "address", "name": "owner", "type": "address"}, {"internalType": "address", "name": "spender", "type": "address"}], "name": "allowance", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"}, {"inputs": [{"internalType": "address", "name": "spender", "type": "address"}, {"internalType": "uint256", "name": "amount", "type": "uint256"}], "name": "approve", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "nonpayable", "type": "function"}, {"inputs": [{"internalType": "address", "name": "account", "type": "address"}], "name": "balanceOf", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "decimals", "outputs": [{"internalType": "uint8", "name": "", "type": "uint8"}], "stateMutability": "view", "type": "function"}, {"inputs": [{"internalType": "address", "name": "spender", "type": "address"}, {"internalType": "uint256", "name": "subtractedValue", "type": "uint256"}], "name": "decreaseAllowance", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "nonpayable", "type": "function"}, {"inputs": [{"internalType": "address", "name": "spender", "type": "address"}, {"internalType": "uint256", "name": "addedValue", "type": "uint256"}], "name": "increaseAllowance", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "nonpayable", "type": "function"}, {"inputs": [], "name": "name", "outputs": [{"internalType": "string", "name": "", "type": "string"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "symbol", "outputs": [{"internalType": "string", "name": "", "type": "string"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "totalSupply", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"}, {"inputs": [{"internalType": "address", "name": "to", "type": "address"}, {"internalType": "uint256", "name": "amount", "type": "uint256"}], "name": "transfer", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "nonpayable", "type": "function"}, {"inputs": [{"internalType": "address", "name": "from", "type": "address"}, {"internalType": "address", "name": "to", "type": "address"}, {"internalType": "uint256", "name": "amount", "type": "uint256"}], "name": "transferFrom", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "nonpayable", "type": "function"}]'
const mockVerifierABI = '[{"inputs": [], "stateMutability": "nonpayable", "type": "constructor"}, {"inputs": [{"internalType": "bool", "name": "_result", "type": "bool"}], "name": "changeResult", "outputs": [], "stateMutability": "nonpayable", "type": "function"}, {"inputs": [], "name": "result", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "view", "type": "function"}, {"inputs": [{"internalType": "uint256[2]", "name": "", "type": "uint256[2]"}, {"internalType": "uint256[2][2]", "name": "", "type": "uint256[2][2]"}, {"internalType": "uint256[2]", "name": "", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "", "type": "uint256[2]"}], "name": "verifyProof", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "view", "type": "function"}]'

async function sleep(time: number) {
return new Promise((resolve) => setTimeout(resolve, time));
}
const timeout = 30000

async function deployContract(signer: ethers.Signer, bytecode: string, abi: string, args?: any[]) {
const factory = new ethers.ContractFactory(abi, bytecode, signer)
Expand All @@ -32,9 +29,36 @@ export async function setupTestingContracts(args: {
feeReceiver: string,
freezePeriod: bigint,
}) {
const node = spawn("npx", ["hardhat", "node"])
// FIXME: sleep for 5 seconds is not a good way to wait for the node to start
await sleep(5000)
const node = spawn("npx", ["hardhat", "node", "--port", "0"])
const pid = node.pid
if (!pid) {
throw new Error("process failed to start")
}
const endString = "Any funds sent to them on Mainnet or any other live network WILL BE LOST."
let url: string | undefined = undefined;
await new Promise((resolve, reject) => {
const t = setTimeout(() => {
reject(new Error("Timeout when waiting for hardhat node to start"))
}, timeout)
const f = (data) => {
const dataString = data.toString()
const ipAddressMatch = dataString.match(/Started HTTP and WebSocket JSON-RPC server at (http:\/\/127\.0\.0\.1:\d+)/)
if (ipAddressMatch !== null) {
url = ipAddressMatch[1]
return;
}
if (dataString.indexOf(endString) !== -1) {
clearTimeout(t)
resolve(undefined)
node.stdout.removeListener("data", f)
}
}
node.stdout.on("data", f);
})

if (url === undefined) {
throw new Error("Failed to get url from hardhat node")
}

const provider = new ethers.JsonRpcProvider(url)
const signer0 = await provider.getSigner(0)
Expand Down Expand Up @@ -77,6 +101,22 @@ export async function setupTestingContracts(args: {
}
}

const pidToKill = node.pid

async function killNode() {
await new Promise((resolve, reject) => {
const t = setTimeout(() => {
reject(new Error('Killing node process timeout'));
}, timeout);
node.on('exit', () => {
clearTimeout(t);
resolve(undefined)
});
node.kill(9);

})
}

return {
node,
provider,
Expand All @@ -88,5 +128,6 @@ export async function setupTestingContracts(args: {
rlnContractWrapper,
contractAtBlock,
waitUntilFreezePeriodPassed,
killNode,
}
}
10 changes: 6 additions & 4 deletions tests/rln-registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { withdrawParams } from "./configs";
describe('RLNRegistry', () => {
let node: ChildProcessWithoutNullStreams
let waitUntilFreezePeriodPassed: () => Promise<void>
let killNode: () => Promise<void>
let registry: IRLNRegistry;

const rlnIdentifier = BigInt(1)
Expand Down Expand Up @@ -47,6 +48,7 @@ describe('RLNRegistry', () => {
});
node = deployed.node
waitUntilFreezePeriodPassed = deployed.waitUntilFreezePeriodPassed
killNode = deployed.killNode
registry = new ContractRLNRegistry({
rlnIdentifier,
rlnContract: deployed.rlnContractWrapper,
Expand All @@ -56,10 +58,10 @@ describe('RLNRegistry', () => {
})
});

afterAll(() => {
if (node !== undefined) {
node.kill()
}
afterAll(async () => {
console.log("killing node")
await killNode()
console.log("node killed")
});

it('should be initialized correctly', async () => {
Expand Down
12 changes: 7 additions & 5 deletions tests/rln.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { RLN, RLNFullProof } from "../src";
import { ICache, MemoryCache, Status } from "../src/cache";
import { Status } from "../src/cache";
import { rlnParams, withdrawParams } from "./configs";
import { MemoryMessageIDCounter } from "../src/message-id-counter";
import { IRLNRegistry } from "../src/registry";
import { ethers } from "ethers";
import { setupTestingContracts, url } from "./factories";
import { ContractRLNRegistry } from "../src/registry";
import { setupTestingContracts } from "./factories";
import { ChildProcessWithoutNullStreams } from "child_process";

class FakeMessageIDCounter extends MemoryMessageIDCounter {
Expand Down Expand Up @@ -84,6 +82,7 @@ describe("RLN", function () {
let node: ChildProcessWithoutNullStreams
let deployed;
let waitUntilFreezePeriodPassed: () => Promise<void>
let killNode: () => Promise<void>

let rlnA0: RLN;
const messageLimitA0 = BigInt(1);
Expand Down Expand Up @@ -138,6 +137,7 @@ describe("RLN", function () {
});
node = deployed.node
waitUntilFreezePeriodPassed = deployed.waitUntilFreezePeriodPassed
killNode = deployed.killNode

tokenAddress = await deployed.erc20Contract.getAddress()
contractAddress = await deployed.rlnContract.getAddress()
Expand All @@ -153,7 +153,9 @@ describe("RLN", function () {
});

afterAll(async () => {
node.kill()
console.log("killing node")
await killNode()
console.log("node killed")
});

it("should have correct members after initialization", async function () {
Expand Down

0 comments on commit eb5e38a

Please sign in to comment.