Closed2

CanonicalABI の全てのケースの動作をテストできるようなWIT

tanishikingtanishiking

https://zenn.dev/tanishiking/articles/2024-1209-canonical-abi

Type store stack store memory load stack load memory
bool ✅ import roundtrip ☐ export tupled values ✅ import roundtirp ☐ import tupled values
u8 - u64 ✅ import roundtrip ☐ export tupled values ✅ import roundtirp ☐ import tupled values
s8 - s64 ✅ import roundtrip ☐ export tupled values ✅ import roundtirp ☐ import tupled values
f32 ✅ import roundtrip ☐ export tupled values ✅ import roundtirp ☐ import tupled values
f64 ✅ import roundtrip ☐ export tupled values ✅ import roundtirp ☐ import tupled values
char ✅ import roundtrip ☐ export tupled values ✅ import roundtirp ☐ import tupled values
string ✅ import roundtrip export roundtrip export roundtrip ✅ import roundtrip
list ☐ import roundtrip export roundtrip export roundtrip ☐ import roundtrip
record ✅ import roundtrip export roundtrip export roundtrip ✅ import roundtrip
tuple ✅ import roundtrip export roundtrip export roundtrip ✅ import roundtrip
variant ✅ import roundtrip export roundtrip export roundtrip ✅ import roundtrip
enum ✅ import roundtrip export roundtrip export roundtrip ✅ import roundtrip
option ☐ import roundtrip export roundtrip export roundtrip ☐ import roundtrip
result ☐ import roundtrip export roundtrip export roundtrip ☐ import roundtrip
flags ☐ import roundtrip ☐ export tupled values ☐ import roundtirp ☐ import tupled values
resource ☐ import roundtrip ☐ import roundtirp

bool, u8-u64, s8-s64, char

roundtrip-bool: func(x: bool) -> bool;

みたいなのを import すると

  • 引数渡しで store stack
  • 返り値を返すので load stack
roundtrip-tupled: func(x: tuple<bool, bool>) -> tuple<bool, bool>;
  • importの場合は
    • 引数渡しで store stack
    • 返り値を受け取るので load memory
  • export の場合は
    • 引数で load stack
    • 返り値 store memory

ああ、じゃあ普通のroundtripいらなくね

string

roundtrip-string: func(x: string) -> string;
  • import
    • 引数は store stack
    • 返り値は load memory
  • export
    • 引数は load stack
    • 返り値は store memory

文字コードは全てVMが面倒見てくれるので気にする必要はない。
空文字を渡したり返したりするのはテストしておきたい気がする

list

roundtrip-list-u8: func(x: list<u8>) -> list<u8>;
roundtrip-list-string: func(x: list<string>) -> list<string>;
  • import
    • 引数は store stack
    • 返り値は load memory
  • export
    • 引数は load stack
    • 返り値は store memory

https://github.com/bytecodealliance/wit-bindgen/blob/f2393e6e98fa5f9236cac580db8a3fc9de6a4b70/tests/runtime/lists/world.wit

list<list<string>> や、list<point> なんかもテストしたい

record, tuple

record point { x: s32, y: s32 };
roundtrip-point: func(x: point) -> point;
roundtrip-tuple: func(x: tuple<s32, string>) -> tuple<s32, string>;
  • import
    • 引数は store stack
    • 返り値は load memory
  • export
    • 引数は load stack
    • 返り値は store memory

variant, enum, option, result

// https://github.com/bytecodealliance/wit-bindgen/blob/f2393e6e98fa5f9236cac580db8a3fc9de6a4b70/tests/runtime/variants/world.wit#L12-L26
variant c1 { a(s32), b(s64) }
variant c2 { a(s32), b(f32) }
variant c3 { a(s32), b(f64) }
variant c4 { a(s64), b(f32) }
variant c5 { a(s64), b(f64) }
variant c6 { a(f32), b(f64) }
type casts = tuple<c1, c2, c3, c4, c5, c6>;
variant-casts: func(a: casts) -> casts;

variant z1 { a(s32), b }
variant z2 { a(s64), b }
variant z3 { a(f32), b }
variant z4 { a(f64), b }
type zeros = tuple<z1, z2, z3, z4>;
variant-zeros: func(a: zeros) -> zeros;

これいいね。

variant の specialized types 達
stack から load/store するときは coerce values や padding に気をつけたい。

  • import
    • 引数は store stack
    • 返り値は load memory
  • export
    • 引数は load stack
    • 返り値は store memory

flags

何にせよ lowered type は i32 なので

flags f { a, b }
roundtrip-flag: func(x: f) -> f;
roundtrip-flag-mem: func(x: tuple<i32, f>) -> tuple<i32, f>;

roundtrip-flag

  • 引数渡しで store stack
  • 返り値を返すので load stack

roundtrip-flag-mem

  • importの場合は
    • 引数渡しで store stack
    • 返り値を受け取るので load memory
  • export の場合は
    • 引数で load stack
    • 返り値 store memory

resource

resource のテストはデータ受けて返してだけじゃなくて、resource-new とか resource-drop とかも実行が必要になる

tanishikingtanishiking

wit-bindgen のテストケースが参考になる

https://github.com/bytecodealliance/wit-bindgen/tree/f2393e6e98fa5f9236cac580db8a3fc9de6a4b70/tests/runtime

https://github.com/bytecodealliance/wit-bindgen/blob/f2393e6e98fa5f9236cac580db8a3fc9de6a4b70/tests/README.md

例えば tests/runtime/resources/ には world.witwasm.* (go,cs,rs など)

  • 各言語はその wasm.* ファイルから wasm component を生成し
  • tests/runtime/resources.rs などが、その wasm component を compose して実行する。
  • だいたいの場合 test_importsresources.rs が実行していて
    • ホスト側は export した test_imports 関数に、import した関数を使ったテストケースを実装
  • export した関数のテストはどうするのか?
    • resources.rs がそれらの関数を呼び出して実行してくれる。そっちにテストが書かれてるのね
このスクラップは2025/02/06にクローズされました