ICBlast - quick javascript async tests

Just made this repo and decided to share it.
I am going to make a security audit of my canisters with this.

Purpose

Made for easy testing of any canisters, including Motoko Playground canisters without manually providing interface spec.

If you use too high concurrency you may get IP blocked by gateways.

By default works with production IC network.

You can also make it work with your local replica if you specify NODE_ENV=development and IC_HOST in .env

Easy as:

let output = await(await anycan("x2ojg-ciaaa-aaaab-qadba-cai")).anyfunc(input);

Usage

import { anycan, fileIdentity, blast } from "./sys/index.js";

let identityJohn = fileIdentity(0);

// TIP: Go to Motoko Playground at https://m7sm4-2iaaa-aaaab-qabra-cai.raw.ic0.app/
// Choose "Counter" and deploy it
// Take the canister id and put replace it in this code

let counterCanJohn = await anycan("x2ojg-ciaaa-aaaab-qadba-cai", identityJohn);

// If you need different callers
// let identityPeter = fileIdentity(1);
// let counterCanPeter = await anycan("x2ojg-ciaaa-aaaab-qadba-cai", identityPeter);

// sends 10 requests with max concurrency 5 at a time
let results = await blast(10, 5, (idx) => {
  return counterCanJohn.get();
});
5 Likes

Here is one example of why I made this:
A canister with the following code Motoko Playground - DFINITY

actor Counter {

  stable var counter:Nat32 = 0;

  public func waste_some_time() : async () {
    ()
  };

  public func inc() : async Nat32 {
    
    counter += 1;
    await waste_some_time();

    return counter

  };
};

When executed without concurrency, the output is
[
1, 2, 3, 4, 5,
6, 7, 8, 9, 10
]
TEST: 38.432s

// No concurrency
let results = await blast(10, 1, async (idx) => {
  await delay(1); // 1ms 
  return counterCanJohn.inc();
});

When executed with 10 concurrent requests, the output is
[
10, 9, 9, 9, 9,
9, 9, 9, 9, 9
]
TEST: 5.551s

// 10 concurrent requests
let results = await blast(10, 10, async (idx) => {
  await delay(1); // 1ms
  return counterCanJohn.inc();
});

The proper order → you switch counter and await like so:

    await waste_some_time();
    counter += 1;

Then 10 concurrent requests produce this:
[
1, 2, 3, 4, 7,
8, 5, 6, 9, 10
]
TEST: 6.292s

NOTE: at first I was getting the same results with concurrent requests no matter what the canister code was. After placing 1ms delay things got fixed. There is probably some protection in the fetch library or agentjs against making a lot of calls by mistake.

5 Likes