Skip to content

Commit

Permalink
housekeeping and README
Browse files Browse the repository at this point in the history
  • Loading branch information
bee344 committed Jan 12, 2024
1 parent 729e799 commit 6730c62
Show file tree
Hide file tree
Showing 16 changed files with 391 additions and 154 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,3 +323,7 @@ From the root directory run `./<zombienet_binary_name> -p native spawn ./zombien
### Create an asset

From the root directory run `yarn start:zombienet-post-script`. You can run this right after running your zombienet network.

## E2E Testing

You can access the E2E tests and its documentation [here](./e2e-tests/).
36 changes: 36 additions & 0 deletions e2e-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## E2E Tests

End-to-end tests that run on a zombienet testnet.

**NOTE: tested using polkadot v1.4.0**

### Setup

To setup the testing environment you need to first download the `polkadot`, `polkadot-execute-worker`, `polkadot-prepare-worker` and `polkadot-parachain` from the `polkadot-sdk` [release page](https://github.com/paritytech/polkadot-sdk/releases/latest), as well as the `trappist-node` from its [release page](https://github.com/paritytech/trappist/releases/latest), and place them in the `../zombienet/bin/` folder.

You also need to have the latest `zombienet` executable in the `../zombienet/` folder, which you can download from [here](https://github.com/paritytech/zombienet/releases/latest).

### Launching zombienet

To launch the zombienet, all you need to do is run the following commands:
```bash
$ yarn build && yarn e2e:build
```
Then you need to run:
```bash
$ yarn e2e:zombienet
```
And this will launch the zombienet using the config file located in the `../zombienet/` directory. Once it finished its setup, you can proceed to the following step.

### Launching the tests

For testing, we provide 4 options:

* Testing liquidity tokens transfers with the command `yarn e2e:liquidity-assets`.
* Testing foreign assets transfers with the command `yarn e2e:foreign-assets`.
* Testing local transferss with the command `yarn e2e:local`.
* Testing assets transfers with the command `yarn e2e:assets`.

Each of these commands will run the appropiate script to setup the basics, located in `../scripts/`, wait for it to finish setting up the testing environment, and then go through the tests indicated in the `./tests/index.ts` file for the chosen option.

After each testing suite has been completed, it's recommended to restart the zombienet before running another test suite.
12 changes: 11 additions & 1 deletion e2e-tests/balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ export interface IBalance {
final: [string, number][];
}

/**
*
* @param api api instance
* @param test name of the test currently being ran
* @param address address of the account whose balance is being queried
* @param assetIds Ids of the assets being queried
* @param balance initial balance for the account queried
* @returns instance of IBalance containing the initial and optionally the final
* balance of the account queried
*/
export const balanceTracker = async (
api: ApiPromise,
test: string,
Expand Down Expand Up @@ -72,7 +82,7 @@ export const balanceTracker = async (
if (!balance) {
for (const assetId of assetIds) {
accountInfo = await api.query.assets.account(assetId, address);
if (accountInfo === null) {
if (accountInfo.isNone) {
balances.initial.push([assetId, 0]);
} else {
balances.initial.push([assetId, accountInfo.unwrap().balance.toBn().toNumber()]);
Expand Down
7 changes: 1 addition & 6 deletions e2e-tests/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,8 @@
export const KUSAMA_ASSET_HUB_WS_URL = 'ws://127.0.0.1:9911';
export const ROCOCO_ALICE_WS_URL = 'ws://127.0.0.1:9900';
export const TRAPPIST_WS_URL = 'ws://127.0.0.1:9921';
export const MOONRIVER_WS_URL = 'ws://127.0.0.1:9931';

export const BOB_ADDR = '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty';
export const FERDE_ADDR = '5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL';

export const ASSET_ID = 1;

export const MOONRIVER_ADDR = '5Eg2fnt8QeGtg4mcc5ELxPx6qxP2FSEWHbbYXENZ17ormkGP';
export const TRAPPIST_ADDR = '5Eg2fntDDP4P8TjqRg3Jq89y5boE26JUMM3D7VU3bCAp76nc';
export const ASSET_HUB_ADDR = '5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV';
export const EXTRINSIC_VERSION = 4;
36 changes: 11 additions & 25 deletions e2e-tests/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { cryptoWaitReady } from '@polkadot/util-crypto';
import { delay } from '../scripts/util';
import { constructApiPromise } from '../src';
import { balanceTracker, IBalance } from './balance';
import { KUSAMA_ASSET_HUB_WS_URL, MOONRIVER_WS_URL, ROCOCO_ALICE_WS_URL, TRAPPIST_WS_URL } from './consts';
import { KUSAMA_ASSET_HUB_WS_URL, ROCOCO_ALICE_WS_URL, TRAPPIST_WS_URL } from './consts';
import { startProgressBar, startTestLogger, terminateProgressBar, testResultLogger, updateProgressBar } from './logger';
import { assetTests, foreignAssetsTests, IndividualTest, liquidPoolsTests, localTests, tests } from './tests';
import { verification } from './verification';
Expand Down Expand Up @@ -54,13 +54,6 @@ const executor = async (testCase: string) => {
break;
}

let originChainId = '';
let destChainId = '';
let originAddr = '';
let destAddr = '';
let assetIds: string[] = [];
let amounts: string[] = [];
let opts: object = {};
let counter: number = 0;

startTestLogger(testCase);
Expand All @@ -70,13 +63,13 @@ const executor = async (testCase: string) => {
const results: [string, string, string, boolean][] = [];

for (const t of testData) {
originChainId = t.args[0];
destChainId = t.args[1];
originAddr = t.args[2];
destAddr = t.args[3];
assetIds = t.args[4].slice(1, -1).split(',');
amounts = t.args[5].slice(1, -1).split(',');
opts = JSON.parse(t.args[6], (key: string, value: string) => {
const originChainId: string = t.args[0];
const destChainId: string = t.args[1];
const originAddr: string = t.args[2];
const destAddr: string = t.args[3];
const assetIds: string[] = t.args[4].slice(1, -1).split(',');
const amounts: string[] = t.args[5].slice(1, -1).split(',');
const opts: object = JSON.parse(t.args[6], (key: string, value: string) => {
return key === 'paysWithFeeOrigin' ? JSON.stringify(value) : value;
}) as object;
let chainName: string = '';
Expand All @@ -94,10 +87,6 @@ const executor = async (testCase: string) => {
originWsUrl = TRAPPIST_WS_URL;
chainName = 'Trappist';
break;
case '4000':
originWsUrl = MOONRIVER_WS_URL;
chainName = 'Moonriver';
break;
}
if (originChainId == destChainId) {
destWsUrl = originWsUrl;
Expand All @@ -115,10 +104,6 @@ const executor = async (testCase: string) => {
destWsUrl = TRAPPIST_WS_URL;
chainName = 'Trappist';
break;
case '4000':
destWsUrl = MOONRIVER_WS_URL;
chainName = 'Moonriver';
break;
}
}

Expand Down Expand Up @@ -152,9 +137,10 @@ const executor = async (testCase: string) => {
destInitialBalance,
);

const correctlyReceived = verification(assetIds, amounts, destFinalBalance);
const verificationAssetIds: string[] = t.verification[0].slice(1, -1).split(',');
const verificationAmounts: string[] = t.verification[1].slice(1, -1).split(',');

await delay(12000);
const correctlyReceived = verification(verificationAssetIds, verificationAmounts, destFinalBalance);

await originApi.disconnect();
await destinationApi.disconnect();
Expand Down
36 changes: 36 additions & 0 deletions e2e-tests/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import chalk from 'chalk';
import * as cliProgress from 'cli-progress';
import { IndividualTest } from 'tests';

/**
*
* @param testCase a string containing the test option selected
* @returns a prettified version of the testCase
*/
const defineTest = (testCase: string): string => {
let test: string = '';

Expand All @@ -24,12 +29,26 @@ const defineTest = (testCase: string): string => {
return test;
};

/**
* Calls defineTest and prints a message signaling the begining of the tests
* @param testCase a string containing the test option selected
*/
export const startTestLogger = (testCase: string) => {
const test = defineTest(testCase);

console.log(chalk.yellow(`Initializing tests for ${test}\n`));
};

/**
* This creates and starts an instance of cliProgress containing a SingleBar to
* display the test suite's progress
*
* @param testData an array containing the individual tests for the test suite
* selected
* @param testCase the test suite selected
* @returns an instance of the cliProgress that will be used to track the progress
* of the tests
*/
export const startProgressBar = (testData: IndividualTest[], testCase: string): cliProgress.SingleBar => {
const test = defineTest(testCase);

Expand All @@ -48,6 +67,11 @@ export const startProgressBar = (testData: IndividualTest[], testCase: string):
return progressBar;
};

/**
* Clears the progress bar in place and prints an updated version
* @param counter current test number
* @param progressBar instance of the cliProgress
*/
export const updateProgressBar = (counter: number, progressBar: cliProgress.SingleBar) => {
process.stdout.moveCursor(0, -2);

Expand All @@ -56,6 +80,11 @@ export const updateProgressBar = (counter: number, progressBar: cliProgress.Sing
progressBar.increment(counter);
};

/**
* Terminates the cliProgess instance. It's called after the test suite is over
* @param progressBar instance of cliProgress to be terminated
* @param testCase
*/
export const terminateProgressBar = (progressBar: cliProgress.SingleBar, testCase: string) => {
const test = defineTest(testCase);
console.log(chalk.yellow(`Test Suite for ${test} completed.\n`));
Expand All @@ -64,6 +93,13 @@ export const terminateProgressBar = (progressBar: cliProgress.SingleBar, testCas
console.log('\n');
};

/**
*
* @param testName current test's name
* @param assetId Id of the asset tested against
* @param chainName Name of the chain against the test ran
* @param passed whether the test passed or failed
*/
export const testResultLogger = (testName: string, assetId: string, chainName: string, passed: boolean) => {
const tokenId = assetId === '' ? 'native asset' : `asset ${assetId}`;
if (passed) {
Expand Down
32 changes: 24 additions & 8 deletions e2e-tests/tests/assets.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2023 Parity Technologies (UK) Ltd.
import { ApiPromise } from '@polkadot/api';
import { KeyringPair } from '@polkadot/keyring/types';
import { EXTRINSIC_VERSION } from 'consts';

import { AssetTransferApi } from '../../src';
import { TxResult } from '../../src/types';
Expand All @@ -9,10 +10,10 @@ const createAssetApi = (api: ApiPromise, specName: string, safeXcmVersion: numbe
const injectedRegistry = {
rococo: {
'1836': {
tokens: ['ROC'],
tokens: ['HOP'],
assetsInfo: {},
foreignAssetsInfo: {},
specName: 'asset-hub-rococo',
specName: 'trappist-rococo',
poolPairsInfo: {},
},
},
Expand All @@ -36,10 +37,17 @@ const createLocalSystemAssetsTransferTransaction = async (
) => {
const assetApi = createAssetApi(api, specName, safeXcmVersion);

let localTransfer: TxResult<'submittable'>;
let localTransferInfo: TxResult<'payload'>;
try {
localTransfer = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts);
await localTransfer.tx.signAndSend(origin);
localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts);

const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, {
version: EXTRINSIC_VERSION,
});

const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 });

await api.tx(extrinsic).signAndSend(origin);
} catch (e) {
console.error(e);
throw Error(e as string);
Expand All @@ -59,15 +67,23 @@ const createPayFeesTransaction = async (
) => {
const assetApi = createAssetApi(api, specName, safeXcmVersion);

let localTransfer: TxResult<'submittable'>;
let localTransferInfo: TxResult<'payload'>;
try {
localTransfer = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts);
await localTransfer.tx.signAndSend(origin);
localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts);

const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, {
version: EXTRINSIC_VERSION,
});

const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 });

await api.tx(extrinsic).signAndSend(origin);
} catch (e) {
console.error(e);
throw Error(e as string);
}
};

export const assetTests: { [K: string]: Function } = {
createLocalSystemAssetsTransferTransaction,
createPayFeesTransaction,
Expand Down
56 changes: 49 additions & 7 deletions e2e-tests/tests/foreignAssets.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2023 Parity Technologies (UK) Ltd.
import { ApiPromise } from '@polkadot/api';
import { KeyringPair } from '@polkadot/keyring/types';
import { EXTRINSIC_VERSION } from 'consts';

import { AssetTransferApi } from '../../src';
import { TxResult } from '../../src/types';
Expand All @@ -9,10 +10,10 @@ const createAssetApi = (api: ApiPromise, specName: string, safeXcmVersion: numbe
const injectedRegistry = {
rococo: {
'1836': {
tokens: ['ROC'],
tokens: ['HOP'],
assetsInfo: {},
foreignAssetsInfo: {},
specName: 'asset-hub-rococo',
specName: 'trappist-rococo',
poolPairsInfo: {},
},
},
Expand All @@ -23,7 +24,7 @@ const createAssetApi = (api: ApiPromise, specName: string, safeXcmVersion: numbe
return assetApi;
};

const createTransferTransaction = async (
const createForeignTransferTransaction = async (
origin: KeyringPair,
destChainId: string,
destAddr: string,
Expand All @@ -36,13 +37,54 @@ const createTransferTransaction = async (
) => {
const assetApi = createAssetApi(api, specName, safeXcmVersion);

let localTransfer: TxResult<'submittable'>;
let localTransferInfo: TxResult<'payload'>;
try {
localTransfer = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts);
await localTransfer.tx.signAndSend(origin);
localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts);

const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, {
version: EXTRINSIC_VERSION,
});

const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 });

await api.tx(extrinsic).signAndSend(origin);
} catch (e) {
console.error(e);
throw Error(e as string);
}
};
export const foreignAssetsTests: { [K: string]: Function } = { createTransferTransaction };

const createLocalForeignTransferTransaction = async (
origin: KeyringPair,
destChainId: string,
destAddr: string,
assetIds: string[],
amounts: string[],
opts: object,
api: ApiPromise,
specName: string,
safeXcmVersion: number,
) => {
const assetApi = createAssetApi(api, specName, safeXcmVersion);

let localTransferInfo: TxResult<'payload'>;
try {
localTransferInfo = await assetApi.createTransferTransaction(destChainId, destAddr, assetIds, amounts, opts);

const payload = api.createType('ExtrinsicPayload', localTransferInfo.tx, {
version: EXTRINSIC_VERSION,
});

const extrinsic = api.registry.createType('Extrinsic', { method: payload.method }, { version: 4 });

await api.tx(extrinsic).signAndSend(origin);
} catch (e) {
console.error(e);
throw Error(e as string);
}
};

export const foreignAssetsTests: { [K: string]: Function } = {
createForeignTransferTransaction,
createLocalForeignTransferTransaction,
};
Loading

0 comments on commit 6730c62

Please sign in to comment.