dfinity / motoko

Simple high-level language for writing Internet Computer canisters
Apache License 2.0
498 stars 98 forks source link

moc interpreter misses featuers (randomness, time, etc…) #2840

Open infu opened 2 years ago

infu commented 2 years ago

There are few problems I found while writing tests in motoko and running them with moc -r.

Testing my canisters this way to me personally is 100x better than writing ic-repl scripts and 1000x faster than deploying and then testing. My canisters get tested on file save for half sec and I love that.

The worst thing is.. that now I have to abandon 99% coverage with tests in order to use mo:base/Random

1) import Random "mo:base/Random" ( Issue 2805 ) If you could just throw any random number, that would be good enough for testing. Right now, the only workaround is to write text preprocessing script which replaces it with a dummy for the tests

2) Principal.fromActor( someactor )) (Which is commonly used in token canisters) Gives error. There is a workaround tho - storing a debug mode variable inside canister and avoiding that function

3) Trying to spoof shared({caller}) for the purposes of testing canister security The only thing which succeeded was this. A bit ugly, but at least works. I failed in making a shortcut function for it, because then the principal doesn't change.

actor class Infu() { // all methods in this actor will have their own principal dfferent from the main one

    public shared({caller}) func run() : async () {
        user_infu_principal := await someactor.whoAmI();
        Debug.print("Infu's Principal: " # Principal.toText(user_infu_principal));
    };

}; 

let infu = await Infu();
await infu.run(); 

4) Time.now() returns +42 (the ultimate question of life, the universe, and everything) no matter what, which makes it hard to test things depending on it

5) Having to write Debug.print(debug_show()) makes my fingers hurt. Not able to write a shortcut function to it hurts my ego :D

ggreif commented 2 years ago

Here is an idea. It is certainly not elegant and neither universal, but it might work in your particular case. One could harvest some entropy from the operating system before testing runs, inject it into the Random.mo file (e.g. as a long array of 32-byte blobs). Then the test would edit out the await which obtains the entropy from the IC and replace it to get the randomness from that array. Maybe this helps.