From 7fcaec15a13d5ed5323f91306893104ba288673f Mon Sep 17 00:00:00 2001 From: Ryan Lee Date: Mon, 23 Jan 2023 17:23:01 -0500 Subject: [PATCH] feat: integrate examples as deno tests for ci --- .github/workflows/spawn_examples.yml | 28 -------------- .github/workflows/test.yml | 2 +- deno.jsonc | 1 + deps/run_with_limit.ts | 1 + deps/std/io.ts | 1 + deps/std/streams.ts | 1 + effects/extrinsic.test.ts | 12 ++++-- examples/.ignore | 1 + examples/derp.ts | 13 +++++++ examples/examples.test.ts | 56 ++++++++++++++++++++++++++++ util/constants.ts | 6 +++ util/mod.ts | 1 + 12 files changed, 90 insertions(+), 33 deletions(-) delete mode 100644 .github/workflows/spawn_examples.yml create mode 100644 deps/run_with_limit.ts create mode 100644 deps/std/io.ts create mode 100644 deps/std/streams.ts create mode 100644 examples/derp.ts create mode 100644 examples/examples.test.ts create mode 100644 util/constants.ts diff --git a/.github/workflows/spawn_examples.yml b/.github/workflows/spawn_examples.yml deleted file mode 100644 index a8c6a179c..000000000 --- a/.github/workflows/spawn_examples.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Spawn Examples -on: - workflow_dispatch: - pull_request: - push: - branches: - - main -jobs: - generate_example_paths: - name: Generate example paths - runs-on: ubuntu-latest - outputs: - example_paths: ${{ steps.generate_example_paths.outputs.example_paths }} - steps: - - uses: actions/checkout@v3 - - name: Setup fd-find - uses: ./.github/actions/setup-fd-find - - id: generate_example_paths - run: | - fd --print0 --glob "*.ts" ./examples | jq -Rnc '(input | split("\u0000"))' > example_paths.json - example_paths=`cat example_paths.json` - echo "example_paths=$example_paths" >> $GITHUB_OUTPUT - run_example_workflow: - needs: generate_example_paths - name: Run examples - uses: ./.github/workflows/example.yml - with: - example_paths: ${{ needs.generate_example_paths.outputs.example_paths }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index da8904bc3..53953b587 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,4 +18,4 @@ jobs: - run: deno lint - run: deno task codegen - run: deno task star - - run: deno task test + - run: deno task test:ci diff --git a/deno.jsonc b/deno.jsonc index fbff8f1b8..29ca9e228 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -36,6 +36,7 @@ "star": "deno task run _tasks/star.ts && deno cache --check target/star.ts", "codegen": "deno task run cache.ts examples/mod.ts", "test": "deno task run test_util/ctx.ts -- deno test -A -L=info --ignore=target --parallel", + "test:ci": "ENV_TYPE_CI=1 deno task test", "test:update": "deno task test -- -- --update", "bench": "deno bench -A", "moderate": "deno task run https://deno.land/x/moderate@0.0.5/mod.ts && dprint fmt" diff --git a/deps/run_with_limit.ts b/deps/run_with_limit.ts new file mode 100644 index 000000000..e1258b2b7 --- /dev/null +++ b/deps/run_with_limit.ts @@ -0,0 +1 @@ +export * from "https://deno.land/x/run_with_limit@v1.0.1/mod.ts" diff --git a/deps/std/io.ts b/deps/std/io.ts new file mode 100644 index 000000000..0328cb286 --- /dev/null +++ b/deps/std/io.ts @@ -0,0 +1 @@ +export * from "https://deno.land/std@0.172.0/io/mod.ts" diff --git a/deps/std/streams.ts b/deps/std/streams.ts new file mode 100644 index 000000000..6f625b942 --- /dev/null +++ b/deps/std/streams.ts @@ -0,0 +1 @@ +export * from "https://deno.land/std@0.172.0/streams/mod.ts" diff --git a/effects/extrinsic.test.ts b/effects/extrinsic.test.ts index 05dca1d3d..e569e63bd 100644 --- a/effects/extrinsic.test.ts +++ b/effects/extrinsic.test.ts @@ -1,12 +1,16 @@ import * as A from "../deps/std/testing/asserts.ts" import * as T from "../test_util/mod.ts" +import { EXISTENTIAL_DEPOSIT_AMOUNT } from "../util/constants.ts" import * as U from "../util/mod.ts" +import { Sr25519 } from "../util/mod.ts" import { entryRead } from "./entryRead.ts" import { extrinsic } from "./extrinsic.ts" Deno.test({ name: "Balances.transfer", fn: async (ctx) => { + const kp = Sr25519.fromSeed(crypto.getRandomValues(new Uint8Array(32))) + await ctx.step("extrinsic events", async () => { await assertExtrinsicStatusOrder({ keypair: T.alice, @@ -14,10 +18,10 @@ Deno.test({ type: "Balances", value: { type: "transfer", - value: 12345n, + value: EXISTENTIAL_DEPOSIT_AMOUNT + 12345n, dest: { type: "Id", - value: T.bob.publicKey, + value: kp.publicKey, }, }, }, @@ -28,10 +32,10 @@ Deno.test({ await ctx.step({ name: "account balance updated", fn: async () => { - const state = await entryRead(T.westend)("System", "Account", [T.bob.publicKey]).run() + const state = await entryRead(T.westend)("System", "Account", [kp.publicKey]).run() A.assertObjectMatch(state, { value: { - data: { free: 10000000000012345n }, + data: { free: EXISTENTIAL_DEPOSIT_AMOUNT + 12345n }, }, }) }, diff --git a/examples/.ignore b/examples/.ignore index c941fcc58..302b3aa7d 100644 --- a/examples/.ignore +++ b/examples/.ignore @@ -2,3 +2,4 @@ mod.ts multisig_transfer.ts smart_contract.ts xcm_teleport_assets.ts +examples.test.ts diff --git a/examples/derp.ts b/examples/derp.ts new file mode 100644 index 000000000..2b7ae396b --- /dev/null +++ b/examples/derp.ts @@ -0,0 +1,13 @@ +import { Keyring } from "https://deno.land/x/polkadot@0.2.23/keyring/mod.ts" +import { + cryptoWaitReady, + randomAsHex, +} from "https://deno.land/x/polkadot@0.2.23/util-crypto/mod.ts" + +const a = new Keyring() + +await cryptoWaitReady() + +const keyring = new Keyring({ type: "sr25519", ss58Format: 2 }) +keyring.addFromUri(randomAsHex(32), { name: `testing` }) +console.log(keyring.getPairs().map((kp) => kp.meta)) diff --git a/examples/examples.test.ts b/examples/examples.test.ts new file mode 100644 index 000000000..b470679f7 --- /dev/null +++ b/examples/examples.test.ts @@ -0,0 +1,56 @@ +import * as path from "http://localhost:5646/@local/deps/std/path.ts" +import { makeRunWithLimit } from "../deps/run_with_limit.ts" +import { readLines } from "../deps/std/io.ts" +import { writeAll } from "../deps/std/streams.ts" +import { assert } from "../deps/std/testing/asserts.ts" + +function getModuleDir(importMeta: ImportMeta): string { + return path.resolve(path.dirname(path.fromFileUrl(importMeta.url))) +} + +Deno.test({ + name: "examples", + ignore: Deno.env.get("ENV_TYPE_CI") ? false : true, + async fn(t) { + const { runWithLimit } = makeRunWithLimit(navigator.hardwareConcurrency) + + const ignoreFile = await Deno.readTextFile(path.join(getModuleDir(import.meta), ".ignore")) + const ignoredFiles = new Set(ignoreFile.split("\n")) + + const exampleFileNames = Array.from(Deno.readDirSync(getModuleDir(import.meta))) + .filter((e) => e.name.match(/^.*\.ts$/g) && e.isFile && !ignoredFiles.has(e.name)) + .map((f) => f.name) + + await Promise.all(exampleFileNames.map((fileName) => + runWithLimit(async () => { + const task = Deno.run({ + cmd: ["deno", "task", "run", `${getModuleDir(import.meta)}/${fileName}`], + stdout: "null", + stderr: "piped", + }) + + try { + await t.step({ + name: fileName, + async fn() { + const encoder = new TextEncoder() + for await (const line of readLines(task.stderr)) { + await writeAll(Deno.stdout, encoder.encode(`[examples/${fileName}] ${line}\n`)) + } + const status = await task.status() + + assert(status.code === 0, `task failed with status code: ${status.code}`) + assert(status.success, `unsuccessful`) + }, + sanitizeOps: false, + sanitizeResources: false, + sanitizeExit: false, + }) + } finally { + task.stderr.close() + task.close() + } + }) + )) + }, +}) diff --git a/util/constants.ts b/util/constants.ts new file mode 100644 index 000000000..c69013441 --- /dev/null +++ b/util/constants.ts @@ -0,0 +1,6 @@ +/** + * Minimum deposit amount to activate an account + * + * {@link https://support.polkadot.network/support/solutions/articles/65000168651-what-is-the-existential-deposit-#:~:text=On%20the%20Polkadot%20network%2C%20an,the%20Existential%20Deposit%20(ED) What is the Existential Deposit} + */ +export const EXISTENTIAL_DEPOSIT_AMOUNT = 10_000_000_000n diff --git a/util/mod.ts b/util/mod.ts index f6efb2f19..1012852fc 100644 --- a/util/mod.ts +++ b/util/mod.ts @@ -1,5 +1,6 @@ export * from "./branded.ts" export * from "./case.ts" +export * from "./constants.ts" export * from "./Counter.ts" export * from "./error.ts" export * from "./fetch.ts"