Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ edition = '2018'
name = 'moonbeam'
path = 'src/main.rs'

[features]
test-spec = []

[dependencies]
async-io = "1.3"
derive_more = '0.99'
Expand Down
2 changes: 1 addition & 1 deletion node/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ pub fn moonbeam_inflation_config() -> InflationInfo<Balance> {
}
}

fn testnet_genesis(
pub fn testnet_genesis(
root_key: AccountId,
stakers: Vec<(AccountId, Option<AccountId>, Balance)>,
inflation_config: InflationInfo<Balance>,
Expand Down
2 changes: 2 additions & 0 deletions node/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ fn load_spec(
)?)),
"dev" | "development" => Ok(Box::new(chain_spec::development_chain_spec(None, None))),
"local" => Ok(Box::new(chain_spec::get_chain_spec(para_id))),
#[cfg(feature = "test-spec")]
"staking" => Ok(Box::new(crate::test_spec::staking_spec(para_id))),
"" => Err(
"You have not specified what chain to sync. In the future, this will default to \
Moonbeam mainnet. Mainnet is not yet live so you must choose a spec."
Expand Down
2 changes: 2 additions & 0 deletions node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#![warn(unused_extern_crates)]

mod chain_spec;
#[cfg(feature = "test-spec")]
mod test_spec;
#[macro_use]
mod service;
mod cli;
Expand Down
71 changes: 71 additions & 0 deletions node/src/test_spec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright 2019-2021 PureStake Inc.
// This file is part of Moonbeam.

// Moonbeam is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Moonbeam is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Moonbeam. If not, see <http://www.gnu.org/licenses/>.

//! Embedded specs for testing purposes, must be compiled with --features=test-spec
use crate::chain_spec::{moonbeam_inflation_config, testnet_genesis, ChainSpec, Extensions};
use cumulus_primitives_core::ParaId;
use moonbeam_runtime::{AccountId, GLMR};
use sc_service::ChainType;
use std::str::FromStr;

/// Generate testing chain_spec for staking integration tests with accounts initialized for
/// collating and nominating.
pub fn staking_spec(para_id: ParaId) -> ChainSpec {
ChainSpec::from_genesis(
"Moonbase Development Testnet",
"staking",
ChainType::Local,
move || {
testnet_genesis(
// Root
AccountId::from_str("6Be02d1d3665660d22FF9624b7BE0551ee1Ac91b").unwrap(),
// Collators
vec![
(
AccountId::from_str("6Be02d1d3665660d22FF9624b7BE0551ee1Ac91b").unwrap(),
None,
1_000 * GLMR,
),
(
AccountId::from_str("C0F0f4ab324C46e55D02D0033343B4Be8A55532d").unwrap(),
None,
1_000 * GLMR,
),
],
// Inflation config
moonbeam_inflation_config(),
// Endowed accounts (each minted 1 << 80 balance)
vec![
AccountId::from_str("6Be02d1d3665660d22FF9624b7BE0551ee1Ac91b").unwrap(),
AccountId::from_str("C0F0f4ab324C46e55D02D0033343B4Be8A55532d").unwrap(),
AccountId::from_str("Ff64d3F6efE2317EE2807d223a0Bdc4c0c49dfDB").unwrap(),
AccountId::from_str("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac").unwrap(),
],
para_id,
// Chain ID
1280,
)
},
vec![],
None,
None,
Some(serde_json::from_str("{\"tokenDecimals\": 18}").expect("Provided valid json map")),
Extensions {
relay_chain: "local_testnet".into(),
para_id: para_id.into(),
},
)
}
4 changes: 2 additions & 2 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ You can also add the node's logs to the output using the `MOONBEAM_LOG` env vari
MOONBEAM_LOG="warn,rpc=trace" npm run test
```

The Moonbeam node will be listening for RPC on port 19933, mostly to avoid
conflicts with already running Substrate nodes.
The test script will find available ports above 20000 in order to ensure that it doesn't conflict
with any other running services.
40 changes: 40 additions & 0 deletions tests/non_ci_tests/test-frontier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { expect } from "chai";

import { customRequest } from "../tests/util";
import { GENESIS_ACCOUNT, GENESIS_ACCOUNT_PRIVATE_KEY, TEST_ACCOUNT } from "../tests/constants";
import {
createAndFinalizeBlockWithFrontier,
describeWithFrontier,
} from "../tests/util/testWithFrontier";

const FRONTIER_GENESIS_ACCOUNT_BALANCE = "340282366920938463463374607431768211455";

// This is an example of a Frontier test. It requires to have a clone of frontier in the same repo
// The binary needs to be built with `cargo build --no-default-features --features=manual-seal`
describeWithFrontier("Frontier RPC (Balance)", `frontier-specs.json`, (context) => {
it("genesis balance is setup correctly (web3)", async function () {
expect(await context.web3.eth.getBalance(GENESIS_ACCOUNT)).to.equal(
FRONTIER_GENESIS_ACCOUNT_BALANCE
);
});
it("balance to be updated after transfer", async function () {
this.timeout(15000);

const tx = await context.web3.eth.accounts.signTransaction(
{
from: GENESIS_ACCOUNT,
to: TEST_ACCOUNT,
value: "0x200", // Must be higher than ExistentialDeposit (0)
gasPrice: "0x01",
gas: "0x100000",
},
GENESIS_ACCOUNT_PRIVATE_KEY
);
await customRequest(context.web3, "eth_sendRawTransaction", [tx.rawTransaction]);
await createAndFinalizeBlockWithFrontier(context.web3);
expect(await context.web3.eth.getBalance(GENESIS_ACCOUNT)).to.equal(
"340282366920938463463374607431768189943"
);
expect(await context.web3.eth.getBalance(TEST_ACCOUNT)).to.equal("512");
});
});
44 changes: 44 additions & 0 deletions tests/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"main": "index.js",
"scripts": {
"test-with-logs": "mocha --printlogs -r ts-node/register 'tests/**/*.ts'",
"test": "mocha -r ts-node/register 'tests/**/*.ts'"
"test": "mocha --parallel -r ts-node/register 'tests/**/*.ts'",
"non-ci-test": "mocha -r ts-node/register 'non_ci_tests/**/*.ts'"
},
"author": "",
"license": "ISC",
Expand All @@ -19,6 +20,7 @@
"mocha": "^8.3.2",
"mocha-steps": "^1.3.0",
"rimraf": "^3.0.2",
"tcp-port-used": "^1.0.2",
"ts-node": "9.1",
"typescript": "^3.9.6",
"web3": "^1.3.5"
Expand Down
3 changes: 0 additions & 3 deletions tests/tests/constants/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
export const PORT = 19931;
export const RPC_PORT = 19932;
export const WS_PORT = 19933;
export const SPECS_PATH = `./moonbeam-test-specs`;

export const DISPLAY_LOG = process.env.MOONBEAM_LOG || false;
Expand Down
1 change: 0 additions & 1 deletion tests/tests/test-block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ describeWithMoonbeam("Moonbeam RPC (Block)", `simple-specs.json`, (context) => {
//fetch block again using hash
const block = await context.web3.eth.getBlock(0);
const blockByHash = await context.web3.eth.getBlock(block.hash);
console.log("blockbyhash", blockByHash);
expect(blockByHash).to.include({
author: "0x0000000000000000000000000000000000000000",
difficulty: "0",
Expand Down
18 changes: 4 additions & 14 deletions tests/tests/test-ethers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,12 @@ describeWithMoonbeam("Moonbeam RPC (Ethers.js)", `simple-specs.json`, (context)
const GENESIS_ACCOUNT_PRIVATE_KEY =
"0x99B3C12287537E38C90A9219D4CB074A89A16E9CDB20BF85728EBD97C343E342";

it("get network ids", async function () {
// Providers
let prov = context.web3.currentProvider as HttpProvider;
const provider = new ethers.providers.JsonRpcProvider(prov.host);
expect((await provider.getNetwork()).chainId).to.equal(1281);
const providerTestnet = new ethers.providers.JsonRpcProvider(
"https://rpc.testnet.moonbeam.network"
);
expect((await providerTestnet.getNetwork()).chainId).to.equal(1287);
it("get network id", async function () {
expect((await context.ethers.getNetwork()).chainId).to.equal(1281);
});
it("deploy contract and interact with it", async function () {
// Providers
let prov = context.web3.currentProvider as HttpProvider;
const provider = new ethers.providers.JsonRpcProvider(prov.host);

let signer = new ethers.Wallet(GENESIS_ACCOUNT_PRIVATE_KEY, provider);
it("deploy contract and interact with it", async function () {
let signer = new ethers.Wallet(GENESIS_ACCOUNT_PRIVATE_KEY, context.ethers);

// deploy contract
const factory = new ethers.ContractFactory(
Expand Down
8 changes: 0 additions & 8 deletions tests/tests/test-trace-filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ describeWithMoonbeam("Moonbeam RPC (trace_filter)", `simple-specs.json`, (contex
},
]);

// console.log(JSON.stringify(response));

expect(response.result.length).to.equal(1);
expect(response.result[0].action.createMethod).to.equal("create");
expect(response.result[0].action.from).to.equal("0x6be02d1d3665660d22ff9624b7be0551ee1ac91b");
Expand Down Expand Up @@ -101,8 +99,6 @@ describeWithMoonbeam("Moonbeam RPC (trace_filter)", `simple-specs.json`, (contex
},
]);

// console.log(JSON.stringify(response));

expect(response.result.length).to.equal(1);
expect(response.result[0].action.createMethod).to.equal("create");
expect(response.result[0].action.from).to.equal("0x6be02d1d3665660d22ff9624b7be0551ee1ac91b");
Expand Down Expand Up @@ -164,8 +160,6 @@ describeWithMoonbeam("Moonbeam RPC (trace_filter)", `simple-specs.json`, (contex
expect(response.result[1].transactionPosition).to.equal(0);
expect(response.result[2].blockNumber).to.equal(3);
expect(response.result[2].transactionPosition).to.equal(1);

// console.log(JSON.stringify(response));
});

step("Call with subcalls, some reverting", async function () {
Expand Down Expand Up @@ -197,7 +191,6 @@ describeWithMoonbeam("Moonbeam RPC (trace_filter)", `simple-specs.json`, (contex
},
]);

// console.log(JSON.stringify(response));
expect(response.result.length).to.equal(7);
expect(response.result[0].subtraces).to.equal(2);
expect(response.result[0].traceAddress).to.deep.equal([]);
Expand All @@ -223,7 +216,6 @@ describeWithMoonbeam("Moonbeam RPC (trace_filter)", `simple-specs.json`, (contex
},
]);

// console.log(JSON.stringify(response));
expect(response.result.length).to.equal(9);
expect(response.result[0].blockNumber).to.equal(3);
expect(response.result[0].transactionPosition).to.equal(0);
Expand Down
28 changes: 28 additions & 0 deletions tests/tests/util/findAvailablePorts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import tcpPortUsed from "tcp-port-used";

export async function findAvailablePorts() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would design it differently. The risk here comes from the fact it is checking the ports incrementally, starting from the same number each time, the race condition are more likely to happen in that case. It is also not efficient.

Using a random port might be more effective

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this is for the parallel mode, not the serial one)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. Turns out this isn't exactly a trivial problem... I'll leave this link here: mochajs/mocha#4456

const availablePorts = await Promise.all(
[null, null, null].map(async (_, index) => {
let selectedPort = 0;
let port = 1024 + index * 20000 + (process.pid % 20000);
let endingPort = 65535;
while (!selectedPort && port < endingPort) {
const inUse = await tcpPortUsed.check(port, "127.0.0.1");
if (!inUse) {
selectedPort = port;
}
port++;
}
if (!selectedPort) {
throw new Error(`No available port`);
}
return selectedPort;
})
);

return {
p2pPort: availablePorts[0],
rpcPort: availablePorts[1],
wsPort: availablePorts[2],
};
}
Loading