Skip to content

Commit

Permalink
Add ts support in parser (#1031)
Browse files Browse the repository at this point in the history
* Add ts support in parser

* Simplify solution

* Fix the rust tests

* remove unecessery tests

* update documentation

* Rename enums for JS, TS, SH

* Fix the TS convertion

* Address some comments

* Address some comments

* Bump versions of zombienet/dsl-parser-wrapper
  • Loading branch information
wirednkod authored May 12, 2023
1 parent 8ff671f commit dd771c3
Show file tree
Hide file tree
Showing 16 changed files with 166 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion crates/parser-wrapper/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dsl-parser-wrapper"
version = "0.1.7"
version = "0.1.8"
edition = "2021"
description = "Zombienet DSL parser: produces a test definition, in json format, that can be used with the ZombieNet's test-runnner."
license = "GPL-3.0-or-later"
Expand Down
1 change: 1 addition & 0 deletions crates/parser/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ pub enum AssertionKind {
cmp: Option<Comparison>,
#[serde(with = "optional_timeout")]
timeout: Option<Duration>,
is_ts: bool,
},
CustomSh {
node_name: NodeName,
Expand Down
44 changes: 35 additions & 9 deletions crates/parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ use ast::{Assertion, AssertionKind, Comparison, NodeName, ParaId, TestDefinition
#[cfg(test)]
mod tests;

enum ScriptType {
Javascript,
Typescript,
Shellscript,
}

// This include forces recompiling this source file if the grammar file changes.
// Uncomment it when doing changes to the .pest file
const _GRAMMAR: &str = include_str!("zombienet.pest");
Expand Down Expand Up @@ -155,7 +161,10 @@ fn parse_lines_count_match_pattern_rule(
Ok((name, match_type, pattern, comparison, timeout))
}

fn parse_custom_script_rule(record: Pair<Rule>, is_js: bool) -> Result<AssertionKind, ParserError> {
fn parse_custom_script_rule(
record: Pair<Rule>,
script_type: ScriptType,
) -> Result<AssertionKind, ParserError> {
let mut pairs = record.into_inner();
let node_name = parse_name(get_pair(&mut pairs, "name")?)?;
let file_path_str = get_pair(&mut pairs, "file_path")?.as_str();
Expand Down Expand Up @@ -186,22 +195,30 @@ fn parse_custom_script_rule(record: Pair<Rule>, is_js: bool) -> Result<Assertion
}
}

if is_js {
Ok(AssertionKind::CustomJs {
match script_type {
ScriptType::Javascript => Ok(AssertionKind::CustomJs {
node_name,
file_path,
custom_args: args,
cmp,
timeout,
})
} else {
Ok(AssertionKind::CustomSh {
is_ts: false,
}),
ScriptType::Typescript => Ok(AssertionKind::CustomJs {
node_name,
file_path,
custom_args: args,
cmp,
timeout,
is_ts: true,
}),
ScriptType::Shellscript => Ok(AssertionKind::CustomSh {
node_name,
file_path,
custom_args: args,
cmp,
timeout,
})
}),
}
}

Expand Down Expand Up @@ -510,7 +527,16 @@ pub fn parse(unparsed_file: &str) -> Result<ast::TestDefinition, errors::ParserE
assertions.push(assertion);
}
Rule::custom_js => {
let parsed = parse_custom_script_rule(record, true)?;
let parsed = parse_custom_script_rule(record, ScriptType::Javascript)?;
let assertion = Assertion {
parsed,
original_line,
};

assertions.push(assertion);
}
Rule::custom_ts => {
let parsed = parse_custom_script_rule(record, ScriptType::Typescript)?;
let assertion = Assertion {
parsed,
original_line,
Expand All @@ -519,7 +545,7 @@ pub fn parse(unparsed_file: &str) -> Result<ast::TestDefinition, errors::ParserE
assertions.push(assertion);
}
Rule::custom_sh => {
let parsed = parse_custom_script_rule(record, false)?;
let parsed = parse_custom_script_rule(record, ScriptType::Shellscript)?;
let assertion = Assertion {
parsed,
original_line,
Expand Down
65 changes: 63 additions & 2 deletions crates/parser/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,8 @@ fn custom_js_parse_ok() {
"node_name": "alice",
"file_path": "./0008-custom.js",
"custom_args": null,
"timeout": 200
"timeout": 200,
"is_ts": false
}
}
}
Expand Down Expand Up @@ -532,7 +533,67 @@ fn custom_js_with_args_parse_ok() {
"node_name": "alice",
"file_path": "./0008-custom.js",
"custom_args": "dave,2000-1,eve",
"timeout": 200
"timeout": 200,
"is_ts": false
}
}
}
]
}"#;
let t: TestDefinition = serde_json::from_str(data).unwrap();

let result = parse(&[NETWORK, CREDS, line].join("\n")).unwrap();
assert_eq!(result, t);
}

#[test]
fn custom_ts_parse_ok() {
let line: &str = r#"alice: ts-script ./0008-custom-ts.ts within 200 seconds"#;
let data = r#"{
"description": null,
"network": "./a.toml",
"creds": "config",
"assertions": [
{
"original_line": "alice: ts-script ./0008-custom-ts.ts within 200 seconds",
"parsed": {
"fn": "CustomJs",
"args": {
"node_name": "alice",
"file_path": "./0008-custom-ts.ts",
"custom_args": null,
"timeout": 200,
"is_ts": true
}
}
}
]
}"#;
let t: TestDefinition = serde_json::from_str(data).unwrap();

let result = parse(&[NETWORK, CREDS, line].join("\n")).unwrap();
assert_eq!(result, t);
}

#[test]
fn custom_ts_with_args_parse_ok() {
let line: &str =
r#"alice: ts-script ./0008-custom-ts.ts with "dave,2000-1,eve" within 200 seconds"#;
let data = r#"{
"description": null,
"network": "./a.toml",
"creds": "config",
"assertions": [
{
"original_line": "alice: ts-script ./0008-custom-ts.ts with \"dave,2000-1,eve\" within 200 seconds",
"parsed": {
"fn": "CustomJs",
"args": {
"node_name": "alice",
"file_path": "./0008-custom-ts.ts",
"custom_args": "dave,2000-1,eve",
"timeout": 200,
"is_ts": true
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/parser/src/zombienet.pest
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ count_log_match = { node_name ~ "count of log lines" ~ ("containing"|"matching")
trace = { node_name ~ "trace with traceID" ~ span_id ~ "contains" ~ square_brackets_strings ~ within? }
system_event = { node_name ~ "system event" ~ ("contains"|"matches") ~ match_type? ~ double_quoted_string ~ within? }
custom_js = { node_name ~ "js-script" ~ file_path ~ ("with" ~ double_quoted_string)? ~ ( "return" ~ comparison )? ~ within? }
custom_ts = { node_name ~ "ts-script" ~ file_path ~ ("with" ~ double_quoted_string)? ~ ( "return" ~ comparison )? ~ within? }
custom_sh = { node_name ~ "run" ~ file_path ~ ("with" ~ double_quoted_string)? ~ ( "return" ~ comparison )? ~ within? }

/// COMMANDS
Expand Down Expand Up @@ -98,6 +99,7 @@ file = { SOI ~ (
trace |
system_event |
custom_js |
custom_ts |
custom_sh |
sleep |
pause |
Expand Down
7 changes: 6 additions & 1 deletion docs/src/cli/test-dsl-definition-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,16 @@ The first lines are used to define the **header fields**:
- `node-name`: trace with traceID <id> contains ["name", "name2",...]
- alice: trace with traceID 94c1501a78a0d83c498cc92deec264d9 contains ["answer-chunk-request", "answer-chunk-request"]

- Custom js scripts: Allow to run a defined script and assert on the completeness or return value.
- Custom js scripts: Allow to run a defined JS script and assert on the completeness or return value.

- `node-name`: js-script _script_relative_path_ [ return is *comparator target_value*] [within x seconds]
- alice: js-script ./0008-custom.js return is greater than 1 within 200 seconds

- Custom ts scripts: Allow to run a defined TS script and assert on the completeness or return value.

- `node-name`: ts-script _script_relative_path_ [ return is *comparator target_value*] [within x seconds]
- alice: ts-script ./0008-custom-ts.ts return is greater than 1 within 200 seconds

- Backchannel wait for value and register to use
- node-name: wait for `var name` and use as `X` [within 30 seconds]
- alice: wait for name and use as X within 30 seconds
Expand Down
8 changes: 4 additions & 4 deletions javascript/package-lock.json

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

2 changes: 1 addition & 1 deletion javascript/packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"url": "https://github.com/paritytech/zombienet/issues"
},
"dependencies": {
"@zombienet/dsl-parser-wrapper": "^0.1.7",
"@zombienet/dsl-parser-wrapper": "^0.1.8",
"@zombienet/orchestrator": "^0.0.41",
"@zombienet/utils": "^0.0.20",
"cli-progress": "^3.12.0",
Expand Down
22 changes: 21 additions & 1 deletion javascript/packages/orchestrator/src/test-runner/assertions.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { ApiPromise, Keyring } from "@polkadot/api";
import { decorators, isValidHttpUrl } from "@zombienet/utils";
import { assert, expect } from "chai";
import execa from "execa";
import fs from "fs/promises";
import { JSDOM } from "jsdom";
import { makeRe } from "minimatch";
import path from "path";
import ts from "typescript";
import { BackchannelMap } from ".";
import {
chainCustomSectionUpgrade,
Expand Down Expand Up @@ -189,6 +192,7 @@ const CustomJs = ({
op,
target_value,
timeout,
is_ts,
}: FnArgs) => {
timeout = timeout || DEFAULT_INDIVIDUAL_TEST_TIMEOUT;
const comparatorFn = comparators[op!];
Expand Down Expand Up @@ -232,7 +236,20 @@ const CustomJs = ({
: custom_args.split(",")
: [];

const resolvedJsFilePath = path.resolve(configBasePath, file_path!);
let resolvedJsFilePath = path.resolve(configBasePath, file_path!);

if (is_ts) {
const source = (await fs.readFile(resolvedJsFilePath)).toString();
const result = ts.transpileModule(source, {
compilerOptions: { module: ts.ModuleKind.CommonJS },
});

resolvedJsFilePath = path.resolve(
configBasePath,
path.parse(file_path!).name + ".js",
);
await fs.writeFile(resolvedJsFilePath, result.outputText);
}

// shim with jsdom
const dom = new JSDOM(
Expand Down Expand Up @@ -278,6 +295,9 @@ const CustomJs = ({
}

// remove shim
if (is_ts) {
await execa.command(`rm -rf ${resolvedJsFilePath}`);
}
(global as any).window = undefined;
(global as any).document = undefined;
(global as any).zombie = undefined;
Expand Down
1 change: 1 addition & 0 deletions javascript/packages/orchestrator/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ export interface FnArgs {
file_or_uri?: string;
after?: number;
seconds?: number;
is_ts?: boolean;
}

export interface RegisterParachainOptions {
Expand Down
10 changes: 1 addition & 9 deletions tests/0008-custom-scripts.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,4 @@ chain = "rococo-local"

[[relaychain.nodes]]
name = "bob"

[[parachains]]
id = 100
add_to_genesis = true

[parachains.collator]
name = "collator01"
image = "{{COL_IMAGE}}"
command = "adder-collator"

5 changes: 4 additions & 1 deletion tests/0008-custom-scripts.zndsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ alice: reports node_roles is 4
alice: js-script ./0008-custom.js return is greater than 1 within 200 seconds
alice: js-script ./0008-custom.js within 200 seconds
alice: js-script ./0008-custom.js with "alice" within 200 seconds
alice: run ./0008-custom.sh within 200 seconds
alice: run ./0008-custom.sh within 200 seconds
alice: ts-script ./0008-custom-ts.ts return is greater than 1 within 200 seconds
alice: ts-script ./0008-custom-ts.ts within 200 seconds
alice: ts-script ./0008-custom-ts.ts with "alice" within 200 seconds
6 changes: 6 additions & 0 deletions tests/0008-custom-ts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const run = async (nodeName: any, networkInfo: any) => {
const { wsUri, userDefinedTypes } = networkInfo.nodesByName[nodeName];
const api = await zombie.connect(wsUri, userDefinedTypes);
const validator = await api.query.session.validators();
return validator.length;
};
7 changes: 5 additions & 2 deletions tests/0013-db-snapshot.zndsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@ Description: Db Snapshot test
Network: ./0013-db-snapshot.toml
Creds: config

# check balance
alice: js-script ./check-balance.js with "alice" return is 900000999940423862 within 200 seconds
# check balance with js script
alice: js-script ./check-balance.js with "alice" return is 900000999940423862 within 200 seconds

# check balance with ts script
alice: ts-script ./check-balance-ts.ts with "alice" return is 900000999940423862 within 200 seconds
14 changes: 14 additions & 0 deletions tests/check-balance-ts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Our address for Alice on the dev chain
const ALICE = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY';
const BOB = '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty';

export const run = async (nodeName: any, networkInfo: any, args: any) {
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
const api = await zombie.connect(wsUri, userDefinedTypes);

const acc = args[0] === "alice" ? ALICE : BOB;
const balance = await api.query.system.account(acc);

console.log(`Current balances for ${args[0]} is ${balance.data.free}`);
return balance.data.free;
}

0 comments on commit dd771c3

Please sign in to comment.