Skip to content

Commit

Permalink
test: integrate runtime-tests as a helper library (#549)
Browse files Browse the repository at this point in the history
test: integrate runtime-tests as a helper library (#549)
  • Loading branch information
TarikGul committed May 18, 2021
1 parent 3ae0c3f commit ea904f3
Show file tree
Hide file tree
Showing 27 changed files with 344 additions and 4 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
**/build/*
calc
docs
runtime-tests
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/.vscode
**/node_modules
/build
/runtime-tests/build
/target
yarn-error.log
**/*.rs.bk
Expand All @@ -12,7 +13,6 @@ yarn-error.log
**.log
**/logs
.yarn/*
/docs/.yarn/*
!.yarn/releases
!.yarn/plugins
/docs/.yarn
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ All the commits in this repo follow the [Conventional Commits spec](https://www.
* @polkadot/apps-config [release notes](https://github.com/polkadot-js/apps/releases)
* @polkadot/util-crypto [release notes](https://github.com/polkadot-js/common/releases)

1. After updating the dependencies, the next step is making sure the release will work against all noted runtimes for Polkadot, Kusama, and Westend. This can be handled via the [sidecar-runtime-test](https://github.com/TarikGul/sidecar-runtime-test) helper library. Instructions for how to run it are in the repos README.md. Before moving forward ensure all tests pass, and if it warns of any missing types feel free to make an issue [here](https://github.com/paritytech/substrate-api-sidecar/issues).
1. After updating the dependencies, the next step is making sure the release will work against all noted runtimes for Polkadot, Kusama, and Westend. This can be handled by running `yarn test:init-runtime-tests`. You must have `python3`, and the dependencies inside of `./scripts/requirements.txt` installed to run the script (Read the [README](./scripts/README.md) for more instructions). Before moving forward ensure all tests pass, and if it warns of any missing types feel free to make an issue [here](https://github.com/paritytech/substrate-api-sidecar/issues).

1. Update the version in the package.json (this is very important for releasing on NPM).

Expand Down
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ const base = require('@substrate/dev/config/jest')

module.exports = {
...base,
testPathIgnorePatterns: ['/build/', '/node_modules/', '/docs/'],
testPathIgnorePatterns: ['/build/', '/node_modules/', '/docs/', '/runtime-tests'],
};
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@
"start": "yarn run main",
"start:log-rpc": "yarn run build && NODE_ENV=test yarn run main ",
"dev": "tsc-watch --onSuccess \"yarn run main\"",
"test": "substrate-exec-jest --silent"
"test": "substrate-exec-jest --silent",
"lint:runtime-tests": "cd runtime-tests && substrate-dev-run-lint",
"build:runtime-tests": "(cd runtime-tests && substrate-exec-tsc)",
"test:runtime-tests": "yarn build:runtime-tests && node ./runtime-tests/build/index.js --config=./runtime-tests/jest.config.js",
"test:init-runtime-tests": "python3 ./scripts/run_chain_tests.py"
},
"dependencies": {
"@polkadot/api": "beta",
Expand All @@ -51,11 +55,13 @@
},
"devDependencies": {
"@substrate/dev": "^0.5.2",
"@types/argparse": "^2.0.7",
"@types/express": "^4.17.11",
"@types/express-serve-static-core": "^4.17.19",
"@types/http-errors": "^1.8.0",
"@types/morgan": "^1.9.2",
"@types/triple-beam": "^1.3.2",
"argparse": "^2.0.1",
"rimraf": "^3.0.2",
"standard-version": "^9.3.0",
"tsc-watch": "^4.2.9",
Expand Down
1 change: 1 addition & 0 deletions runtime-tests/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/build/*
1 change: 1 addition & 0 deletions runtime-tests/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@substrate/dev/config/eslint');
30 changes: 30 additions & 0 deletions runtime-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## Summary

This is a helper library for Sidecar to run runtime tests against specific chains, at certain blocks.

## Testing

The below instructions are specific to runtime-tests against one chain.
If you are looking to run the runtime-tests against all 3 chains (Polkadot, Kusama, Westend) then run `yarn test:init-runtime-tests` in
the root directory of sidecar.

### Polkadot

Lets first get sidecar ready in a seperate terminal.

```
$ cd substrate-api-sidecar
$ git checkout <your_branch>
$ export SAS_SUBSTRATE_WS_URL=<network archive node>
$ yarn
$ yarn build && yarn start
```

Sidecar should now be connected to the node and running successfully. If you find a bug file an issue [here](https://github.com/paritytech/substrate-api-sidecar/issues).

Now lets run our runtime tests against polkadot. Go to a separate terminal and run:

`yarn test:runtime-tests --chain polkadot`

Thats it!
All the tests should come back with green checkmarks.
10 changes: 10 additions & 0 deletions runtime-tests/endpoints/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ChainSpec } from '../types';
import { kusamaEndpoints } from './kusamaEndpoints';
import { polkadotEndpoints } from './polkadotEndpoints';
import { westendEndpoints } from './westendEndpoints';

export const endpoints: Record<ChainSpec, string[][]> = {
kusama: kusamaEndpoints,
polkadot: polkadotEndpoints,
westend: westendEndpoints,
};
21 changes: 21 additions & 0 deletions runtime-tests/endpoints/kusamaEndpoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const kusamaEndpoints = [
['/blocks/2350438', '2350438'], //v1062
['/blocks/2684767', '2684767'], //v2005
['/blocks/2713513', '2713513'], //v2007
['/blocks/2786879', '2786879'], //v2008
['/blocks/2863649', '2863649'], //v2011
['/blocks/3102680', '3102680'], //v2012
['/blocks/3305067', '3305067'], //v2015
['/blocks/3492347', '3492347'], //v2019
['/blocks/3573193', '3573193'], //v2022
['/blocks/4086065', '4086065'], //v2023
['/blocks/4178606', '4178606'], //v2024
['/blocks/4542697', '4542697'], //v2025
['/blocks/5265416', '5265416'], //v2026
['/blocks/6065416', '6065416'], //v2027
['/blocks/6396694', '6396694'], //v2028
['/blocks/6566865', '6566865'], //v2029
['/blocks/6819725', '6819725'], //v2029
['/blocks/7354817', '7354817'], //v2030
['/blocks/7519631', '7519631'], //v9010
];
12 changes: 12 additions & 0 deletions runtime-tests/endpoints/polkadotEndpoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const polkadotEndpoints = [
['/blocks/943438', '943438'], //v17
['/blocks/1603025', '1603025'], //v18
['/blocks/1662525', '1662525'], //v23
['/blocks/1993625', '1993625'], //v24
['/blocks/2392625', '2392625'], //v25
['/blocks/3592619', '3592619'], //v26
['/blocks/3892620', '3892620'], //v27
['/blocks/4092619', '4092619'], //v28
['/blocks/4392619', '4392619'], //v29
['/blocks/4947391', '4947391'], //v30
];
11 changes: 11 additions & 0 deletions runtime-tests/endpoints/westendEndpoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const westendEndpoints = [
['/blocks/3813629', '3813629'],
['/blocks/3032259', '3032259'],
['/blocks/3891809', '3891809'],
['/blocks/4781573', '4781573'],
['/blocks/5277929', '5277929'],
['/blocks/5480769', '5480769'], //v9000
['/blocks/5493461', '5493461'], //v9000
['/blocks/5495855', '5495855'], //v9000
['/blocks/5657482', '5657482'], //v9010
];
9 changes: 9 additions & 0 deletions runtime-tests/helpers/consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Port to Substrate-api-sidecar
*/
export const PORT = 8080;

/**
* Path to Substrate-api-sidecar
*/
export const HOST = '127.0.0.1';
15 changes: 15 additions & 0 deletions runtime-tests/helpers/request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import http from 'http';

export const request = (
path: string,
hostname: string,
port: number
): Promise<string> => {
return new Promise((resolve) => {
http.get({ path, hostname, port }, (response) => {
let data = '';
response.on('data', (_data) => (data += _data));
response.on('end', () => resolve(data));
});
});
};
40 changes: 40 additions & 0 deletions runtime-tests/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ArgumentParser } from 'argparse';

import { IParser } from './types';

const config = {
chain: 'polkadot',
};

const argv = process.argv.slice(0, 2);

/**
* The arg parser takes in two commands.
* @arg --chain The chain to be passed into the jest test
* @arg --config The path to the correct jest config. This is important as the
* jest config inside of /runtime-tests ignores all the other tests.
*/
const parser = new ArgumentParser();

parser.add_argument('--chain', {
choices: ['polkadot', 'kusama', 'westend'],
default: 'polkadot',
});
parser.add_argument('--config', { default: './runtime-tests/jest.config.js' });

const args = parser.parse_args() as IParser;

// Set the chain property for the jest test
config['chain'] = args.chain;

// Pass in the Jest CLI path option to the correct config
argv.push('--config='.concat(args.config));

// Store configuration on env
process.env.__SAS_RUNTIME_TEST_CONFIGURATION = JSON.stringify(config);

// Setting real ARGV
process.argv = argv;

// Calling jest runner
require('jest-cli/bin/jest');
6 changes: 6 additions & 0 deletions runtime-tests/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const base = require('@substrate/dev/config/jest')

module.exports = {
...base,
testPathIgnorePatterns: ['/build/', '/node_modules/', '/src/'],
};
28 changes: 28 additions & 0 deletions runtime-tests/runtimeTests.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { endpoints } from './endpoints';
import { HOST, PORT } from './helpers/consts';
import { request } from './helpers/request';
import { BlockResponse, ChainConfig, ChainSpec } from './types';

const config = JSON.parse(
process.env.__SAS_RUNTIME_TEST_CONFIGURATION as string
) as ChainConfig;
const chain = config.chain as ChainSpec;

const polkadotEndpoints: string[][] = endpoints[chain];

describe('Runtime Tests for blocks', () => {
jest.setTimeout(15000);

/**
* Test runtimes for `/blocks`
*/
test.each(polkadotEndpoints)(
'Given path %p, it should return block height %p',
async (blockPath, blockHeight) => {
const res = await request(blockPath, HOST, PORT);
const responseJson = JSON.parse(res) as BlockResponse;

expect(responseJson['number']).toBe(blockHeight);
}
);
});
9 changes: 9 additions & 0 deletions runtime-tests/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "@substrate/dev/config/tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"outDir": "build",
"suppressImplicitAnyIndexErrors": true,
"resolveJsonModule": true,
},
}
11 changes: 11 additions & 0 deletions runtime-tests/types/chainSpec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* String literal for specific chains that are being tested for
*/
export type ChainSpec = 'polkadot' | 'kusama' | 'westend';

/**
*
*/
export interface ChainConfig {
chain: string;
}
3 changes: 3 additions & 0 deletions runtime-tests/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './chainSpec';
export * from './parser';
export * from './responses';
7 changes: 7 additions & 0 deletions runtime-tests/types/parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* Interface type for args for the arg parser
*/
export interface IParser {
chain: string;
config: string;
}
16 changes: 16 additions & 0 deletions runtime-tests/types/responses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Block Responses
*/
export interface BlockResponse {
number: string;
hash: string;
parentHash: string;
stateRoot: string;
extrinsicsRoot: string;
authorId: string | undefined;
logs: Array<object>;
onInitialize: object;
extrinsics: Array<object>;
onFinalize: object;
finalized: boolean | undefined;
}
23 changes: 23 additions & 0 deletions scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<div style="text-align:center">
<h2>Sidecar Scripts</h2>
<div>
A set of notes and instructions for scripts used in Substrate-api-sidecar
</div>
</div>
<br></br>


## Script `run_chain_tests.py`

### Summary

This script calls the local runtime-tests helper library in order to test the current branch or development enviornment against
a collection of different blocks, across different runtimes. It does this for Polkadot, Kusama, and Westend.

### Requirements

`python3` - required to run the script

`psutil` - package needed to run the script

Run: `pip install -r requirements.txt` from this directory in order to install necessary dependencies.
1 change: 1 addition & 0 deletions scripts/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
psutil==5.8.0
62 changes: 62 additions & 0 deletions scripts/run_chain_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env python3

import os
import psutil
import signal
import subprocess
import time

def run_process(args):
return subprocess.check_output(args, stderr=subprocess.STDOUT,
encoding="utf-8")

def run_chain_test(chain):
run_process(["yarn"])

if chain == "polkadot":
url = "wss://rpc.polkadot.io"
chain = "polkadot"
elif chain == "kusama":
url = "wss://kusama-rpc.polkadot.io"
chain = "kusama"
elif chain == "westend":
url = "wss://westend-rpc.polkadot.io"
chain = "westend"
else:
return -1

os.environ["SAS_SUBSTRATE_WS_URL"] = url
proc = subprocess.Popen(["yarn", "dev"], stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)

print('Sidecar is loading in development mode...')
time.sleep(30)

print('Running `yarn`, and checking/loading cache...')
run_process(["yarn"])

print('Running runtime tests for {}'.format(chain))
res = run_process(["yarn", "test:runtime-tests", "--chain", chain])

print('Killing all processes...')
for child in psutil.Process(proc.pid).children(recursive=True):
child.kill()
proc.kill()

print(res)
return res.find("PASS")


def main():
polka_test = run_chain_test("polkadot")
kusama_test = run_chain_test("kusama")
westend_test = run_chain_test("westend")

if polka_test == 0 and kusama_test == 0 and westend_test == 0:
return 0
else:
return -1


if __name__ == "__main__":
main()
Loading

0 comments on commit ea904f3

Please sign in to comment.