1b2c64de1SMangoPeachGrape #include "utils.h"
2b2c64de1SMangoPeachGrape
3b2c64de1SMangoPeachGrape #include <gtest/gtest.h>
4b2c64de1SMangoPeachGrape #include <wasmtime.h>
5cde2e04fSAlex Crichton #include <wasmtime/component.hh>
6579ec46bSAlex Crichton #include <wasmtime/store.hh>
7b2c64de1SMangoPeachGrape
8b2c64de1SMangoPeachGrape #include <array>
9b2c64de1SMangoPeachGrape #include <format>
10fa89f323SMangoPeachGrape #include <optional>
11b2c64de1SMangoPeachGrape #include <span>
1253701b21SMangoPeachGrape #include <variant>
13b2c64de1SMangoPeachGrape
14579ec46bSAlex Crichton using namespace wasmtime::component;
15cde2e04fSAlex Crichton using wasmtime::Engine;
16cde2e04fSAlex Crichton using wasmtime::Result;
17cde2e04fSAlex Crichton using wasmtime::Span;
18cde2e04fSAlex Crichton using wasmtime::Store;
19579ec46bSAlex Crichton
echo_component(std::string_view type,std::string_view func,std::string_view host_params)20b2c64de1SMangoPeachGrape static std::string echo_component(std::string_view type, std::string_view func,
21b2c64de1SMangoPeachGrape std::string_view host_params) {
22b2c64de1SMangoPeachGrape return std::format(
23b2c64de1SMangoPeachGrape R"END(
24b2c64de1SMangoPeachGrape (component
25b2c64de1SMangoPeachGrape (type $Foo' {})
26b2c64de1SMangoPeachGrape (import "foo" (type $Foo (eq $Foo')))
27b2c64de1SMangoPeachGrape (import "do" (func $do (param "a" $Foo) (result $Foo)))
28b2c64de1SMangoPeachGrape (core module $libc
29b2c64de1SMangoPeachGrape (memory (export "memory") 1)
30b2c64de1SMangoPeachGrape {}
31b2c64de1SMangoPeachGrape )
32b2c64de1SMangoPeachGrape (core instance $libc (instantiate $libc))
33b2c64de1SMangoPeachGrape (core func $do_lower (canon lower (func $do) (memory $libc "memory") (realloc (func $libc "realloc"))))
34b2c64de1SMangoPeachGrape
35b2c64de1SMangoPeachGrape (core module $doer
3653701b21SMangoPeachGrape (import "host" "do" (func $do {}))
37b2c64de1SMangoPeachGrape (import "libc" "memory" (memory 1))
38b2c64de1SMangoPeachGrape (import "libc" "realloc" (func $realloc (param i32 i32 i32 i32) (result i32)))
39b2c64de1SMangoPeachGrape
40b2c64de1SMangoPeachGrape (func (export "call")
41b2c64de1SMangoPeachGrape {})
42b2c64de1SMangoPeachGrape )
43b2c64de1SMangoPeachGrape (core instance $doer (instantiate $doer
44b2c64de1SMangoPeachGrape (with "host" (instance (export "do" (func $do_lower))))
45b2c64de1SMangoPeachGrape (with "libc" (instance $libc))
46b2c64de1SMangoPeachGrape ))
47b2c64de1SMangoPeachGrape
48b2c64de1SMangoPeachGrape (func $call
49b2c64de1SMangoPeachGrape (param "a" $Foo)
50b2c64de1SMangoPeachGrape (result $Foo)
51b2c64de1SMangoPeachGrape (canon lift
52b2c64de1SMangoPeachGrape (core func $doer "call")
53b2c64de1SMangoPeachGrape (memory $libc "memory")
54b2c64de1SMangoPeachGrape (realloc (func $libc "realloc")))
55b2c64de1SMangoPeachGrape )
56b2c64de1SMangoPeachGrape
57b2c64de1SMangoPeachGrape (export "call" (func $call))
58b2c64de1SMangoPeachGrape )
59b2c64de1SMangoPeachGrape )END",
60b2c64de1SMangoPeachGrape type, REALLOC_AND_FREE, host_params, func);
61b2c64de1SMangoPeachGrape }
62b2c64de1SMangoPeachGrape
63b2c64de1SMangoPeachGrape struct Context {
64579ec46bSAlex Crichton Store store;
65cde2e04fSAlex Crichton Store::Context context;
66cde2e04fSAlex Crichton Instance instance;
67cde2e04fSAlex Crichton Func func;
68b2c64de1SMangoPeachGrape
NewContext69dbc21cdeSAlex Crichton static Context New(Engine &engine, std::string_view component_text,
70dbc21cdeSAlex Crichton Linker &linker) {
71579ec46bSAlex Crichton Store store(engine);
72cde2e04fSAlex Crichton const auto context = store.context();
73579ec46bSAlex Crichton Component component = Component::compile(engine, component_text).unwrap();
74b2c64de1SMangoPeachGrape
75579ec46bSAlex Crichton auto f = component.export_index(nullptr, "call");
76b2c64de1SMangoPeachGrape
77579ec46bSAlex Crichton EXPECT_TRUE(f);
78b2c64de1SMangoPeachGrape
79cde2e04fSAlex Crichton auto instance = linker.instantiate(context, component).unwrap();
80cde2e04fSAlex Crichton auto func = *instance.get_func(context, *f);
81b2c64de1SMangoPeachGrape
82b2c64de1SMangoPeachGrape return Context{
83579ec46bSAlex Crichton .store = std::move(store),
84b2c64de1SMangoPeachGrape .context = context,
85b2c64de1SMangoPeachGrape .instance = instance,
86b2c64de1SMangoPeachGrape .func = func,
87b2c64de1SMangoPeachGrape };
88b2c64de1SMangoPeachGrape }
89dbc21cdeSAlex Crichton };
90dbc21cdeSAlex Crichton
91*39ec36caSAlex Crichton typedef Result<std::monostate> (*host_func_t)(Store::Context, const FuncType &,
92*39ec36caSAlex Crichton Span<const Val>, Span<Val>);
93dbc21cdeSAlex Crichton
create(std::string_view type,std::string_view body,std::string_view host_params,host_func_t callback)94dbc21cdeSAlex Crichton static Context create(std::string_view type, std::string_view body,
95dbc21cdeSAlex Crichton std::string_view host_params, host_func_t callback) {
96dbc21cdeSAlex Crichton Engine engine;
97dbc21cdeSAlex Crichton Linker linker(engine);
98dbc21cdeSAlex Crichton linker.root().add_func("do", callback).unwrap();
99dbc21cdeSAlex Crichton auto component_text = echo_component(type, body, host_params);
100dbc21cdeSAlex Crichton return Context::New(engine, component_text, linker);
101dbc21cdeSAlex Crichton }
102b2c64de1SMangoPeachGrape
TEST(component,value_record)103b2c64de1SMangoPeachGrape TEST(component, value_record) {
104cde2e04fSAlex Crichton static const auto check = [](const Val &v, uint64_t x, uint64_t y) {
105cde2e04fSAlex Crichton EXPECT_TRUE(v.is_record());
106cde2e04fSAlex Crichton const Record &r = v.get_record();
107cde2e04fSAlex Crichton EXPECT_EQ(r.size(), 2);
108b2c64de1SMangoPeachGrape
109cde2e04fSAlex Crichton const auto &x_field = *r.begin();
110cde2e04fSAlex Crichton EXPECT_EQ(x_field.name(), "x");
111cde2e04fSAlex Crichton const auto &x_field_val = x_field.value();
112cde2e04fSAlex Crichton EXPECT_TRUE(x_field_val.is_u64());
113cde2e04fSAlex Crichton EXPECT_EQ(x_field_val.get_u64(), x);
114b2c64de1SMangoPeachGrape
115cde2e04fSAlex Crichton const auto &y_field = *(r.begin() + 1);
116cde2e04fSAlex Crichton EXPECT_EQ(y_field.name(), "y");
117cde2e04fSAlex Crichton const auto &y_field_val = y_field.value();
118cde2e04fSAlex Crichton EXPECT_TRUE(y_field_val.is_u64());
119cde2e04fSAlex Crichton EXPECT_EQ(y_field_val.get_u64(), y);
120b2c64de1SMangoPeachGrape };
121b2c64de1SMangoPeachGrape
122cde2e04fSAlex Crichton static const auto make = [](uint64_t x, uint64_t y) -> Val {
123cde2e04fSAlex Crichton return Record({
124cde2e04fSAlex Crichton {"x", x},
125cde2e04fSAlex Crichton {"y", y},
126cde2e04fSAlex Crichton });
127b2c64de1SMangoPeachGrape };
128b2c64de1SMangoPeachGrape
129b2c64de1SMangoPeachGrape auto ctx = create(
130b2c64de1SMangoPeachGrape R"((record (field "x" u64) (field "y" u64)))", R"(
131b2c64de1SMangoPeachGrape (param $x i64)
132b2c64de1SMangoPeachGrape (param $y i64)
133b2c64de1SMangoPeachGrape (result i32)
134b2c64de1SMangoPeachGrape (local $res i32)
135b2c64de1SMangoPeachGrape local.get $x
136b2c64de1SMangoPeachGrape local.get $y
137b2c64de1SMangoPeachGrape (call $realloc
138b2c64de1SMangoPeachGrape (i32.const 0)
139b2c64de1SMangoPeachGrape (i32.const 0)
140b2c64de1SMangoPeachGrape (i32.const 4)
141b2c64de1SMangoPeachGrape (i32.const 16))
142b2c64de1SMangoPeachGrape local.tee $res
143b2c64de1SMangoPeachGrape call $do
144b2c64de1SMangoPeachGrape local.get $res
145b2c64de1SMangoPeachGrape )",
14653701b21SMangoPeachGrape "(param i64 i64 i32)",
147*39ec36caSAlex Crichton +[](Store::Context, const FuncType &_ty, Span<const Val> args,
148cde2e04fSAlex Crichton Span<Val> rets) -> Result<std::monostate> {
149cde2e04fSAlex Crichton EXPECT_EQ(args.size(), 1);
150b2c64de1SMangoPeachGrape check(args[0], 1, 2);
151b2c64de1SMangoPeachGrape
152cde2e04fSAlex Crichton EXPECT_EQ(rets.size(), 1);
153b2c64de1SMangoPeachGrape rets[0] = make(3, 4);
154b2c64de1SMangoPeachGrape
155cde2e04fSAlex Crichton return std::monostate();
156b2c64de1SMangoPeachGrape });
157b2c64de1SMangoPeachGrape
158b2c64de1SMangoPeachGrape auto arg = make(1, 2);
159cde2e04fSAlex Crichton auto res = Val(false);
160b2c64de1SMangoPeachGrape
161cde2e04fSAlex Crichton ctx.func.call(ctx.context, Span<const Val>(&arg, 1), Span<Val>(&res, 1))
162cde2e04fSAlex Crichton .unwrap();
163cde2e04fSAlex Crichton ctx.func.post_return(ctx.context).unwrap();
16453701b21SMangoPeachGrape
165b2c64de1SMangoPeachGrape check(res, 3, 4);
166b2c64de1SMangoPeachGrape }
167b2c64de1SMangoPeachGrape
TEST(component,value_string)168b2c64de1SMangoPeachGrape TEST(component, value_string) {
169cde2e04fSAlex Crichton static const auto check = [](const Val &v, std::string_view text) {
170cde2e04fSAlex Crichton EXPECT_TRUE(v.is_string());
171cde2e04fSAlex Crichton EXPECT_EQ(v.get_string(), text);
172b2c64de1SMangoPeachGrape };
173b2c64de1SMangoPeachGrape
174cde2e04fSAlex Crichton static const auto make = [](std::string_view text) -> Val {
175cde2e04fSAlex Crichton return Val::string(text);
176b2c64de1SMangoPeachGrape };
177b2c64de1SMangoPeachGrape
178b2c64de1SMangoPeachGrape auto ctx = create(
179b2c64de1SMangoPeachGrape R"(string)", R"(
180b2c64de1SMangoPeachGrape (param $x i32)
181b2c64de1SMangoPeachGrape (param $y i32)
182b2c64de1SMangoPeachGrape (result i32)
183b2c64de1SMangoPeachGrape (local $res i32)
184b2c64de1SMangoPeachGrape local.get $x
185b2c64de1SMangoPeachGrape local.get $y
186b2c64de1SMangoPeachGrape (call $realloc
187b2c64de1SMangoPeachGrape (i32.const 0)
188b2c64de1SMangoPeachGrape (i32.const 0)
189b2c64de1SMangoPeachGrape (i32.const 4)
190b2c64de1SMangoPeachGrape (i32.const 8))
191b2c64de1SMangoPeachGrape local.tee $res
192b2c64de1SMangoPeachGrape call $do
193b2c64de1SMangoPeachGrape local.get $res
194b2c64de1SMangoPeachGrape )",
19553701b21SMangoPeachGrape "(param i32 i32 i32)",
196*39ec36caSAlex Crichton +[](Store::Context, const FuncType &, Span<const Val> args,
197cde2e04fSAlex Crichton Span<Val> rets) -> Result<std::monostate> {
198cde2e04fSAlex Crichton EXPECT_EQ(args.size(), 1);
199b2c64de1SMangoPeachGrape check(args[0], "hello from A!");
200b2c64de1SMangoPeachGrape
201cde2e04fSAlex Crichton EXPECT_EQ(rets.size(), 1);
202b2c64de1SMangoPeachGrape rets[0] = make("hello from B!");
203b2c64de1SMangoPeachGrape
204cde2e04fSAlex Crichton return std::monostate();
205b2c64de1SMangoPeachGrape });
206b2c64de1SMangoPeachGrape
207b2c64de1SMangoPeachGrape auto arg = make("hello from A!");
208cde2e04fSAlex Crichton auto res = Val(false);
209b2c64de1SMangoPeachGrape
210cde2e04fSAlex Crichton ctx.func.call(ctx.context, Span<const Val>(&arg, 1), Span<Val>(&res, 1))
211cde2e04fSAlex Crichton .unwrap();
212cde2e04fSAlex Crichton ctx.func.post_return(ctx.context).unwrap();
21353701b21SMangoPeachGrape
214b2c64de1SMangoPeachGrape check(res, "hello from B!");
215b2c64de1SMangoPeachGrape }
216b2c64de1SMangoPeachGrape
TEST(component,value_list)217b2c64de1SMangoPeachGrape TEST(component, value_list) {
218cde2e04fSAlex Crichton static const auto check = [](const Val &v, std::vector<uint32_t> data) {
219cde2e04fSAlex Crichton EXPECT_TRUE(v.is_list());
220cde2e04fSAlex Crichton const List &l = v.get_list();
221cde2e04fSAlex Crichton EXPECT_EQ(l.size(), data.size());
222cde2e04fSAlex Crichton
223b2c64de1SMangoPeachGrape for (auto i = 0; i < data.size(); i++) {
224cde2e04fSAlex Crichton const auto &elem = l.begin()[i];
225cde2e04fSAlex Crichton EXPECT_TRUE(elem.is_u32());
226cde2e04fSAlex Crichton EXPECT_EQ(elem.get_u32(), data[i]);
227b2c64de1SMangoPeachGrape }
228b2c64de1SMangoPeachGrape };
229b2c64de1SMangoPeachGrape
230cde2e04fSAlex Crichton static const auto make = [](std::vector<Val> data) -> Val {
231cde2e04fSAlex Crichton return List(data);
232b2c64de1SMangoPeachGrape };
233b2c64de1SMangoPeachGrape
234b2c64de1SMangoPeachGrape auto ctx = create(
235b2c64de1SMangoPeachGrape R"((list u32))", R"(
236b2c64de1SMangoPeachGrape (param $x i32)
237b2c64de1SMangoPeachGrape (param $y i32)
238b2c64de1SMangoPeachGrape (result i32)
239b2c64de1SMangoPeachGrape (local $res i32)
240b2c64de1SMangoPeachGrape local.get $x
241b2c64de1SMangoPeachGrape local.get $y
242b2c64de1SMangoPeachGrape (call $realloc
243b2c64de1SMangoPeachGrape (i32.const 0)
244b2c64de1SMangoPeachGrape (i32.const 0)
245b2c64de1SMangoPeachGrape (i32.const 4)
246b2c64de1SMangoPeachGrape (i32.const 8))
247b2c64de1SMangoPeachGrape local.tee $res
248b2c64de1SMangoPeachGrape call $do
249b2c64de1SMangoPeachGrape local.get $res
250b2c64de1SMangoPeachGrape )",
25153701b21SMangoPeachGrape "(param i32 i32 i32)",
252*39ec36caSAlex Crichton +[](Store::Context, const FuncType &, Span<const Val> args,
253cde2e04fSAlex Crichton Span<Val> rets) -> Result<std::monostate> {
254cde2e04fSAlex Crichton EXPECT_EQ(args.size(), 1);
255b2c64de1SMangoPeachGrape check(args[0], {1, 2, 3});
256b2c64de1SMangoPeachGrape
257cde2e04fSAlex Crichton EXPECT_EQ(rets.size(), 1);
258cde2e04fSAlex Crichton rets[0] = make({uint32_t(4), uint32_t(5), uint32_t(6), uint32_t(7)});
259b2c64de1SMangoPeachGrape
260cde2e04fSAlex Crichton return std::monostate();
261b2c64de1SMangoPeachGrape });
262b2c64de1SMangoPeachGrape
263cde2e04fSAlex Crichton auto arg = make({uint32_t(1), uint32_t(2), uint32_t(3)});
264cde2e04fSAlex Crichton auto res = Val(false);
265b2c64de1SMangoPeachGrape
266cde2e04fSAlex Crichton ctx.func.call(ctx.context, Span<const Val>(&arg, 1), Span<Val>(&res, 1))
267cde2e04fSAlex Crichton .unwrap();
268cde2e04fSAlex Crichton ctx.func.post_return(ctx.context).unwrap();
26953701b21SMangoPeachGrape
270b2c64de1SMangoPeachGrape check(res, {4, 5, 6, 7});
271b2c64de1SMangoPeachGrape }
272b2c64de1SMangoPeachGrape
TEST(component,value_tuple)27353701b21SMangoPeachGrape TEST(component, value_tuple) {
274cde2e04fSAlex Crichton static const auto check = [](const Val &v, std::vector<uint32_t> data) {
275cde2e04fSAlex Crichton EXPECT_TRUE(v.is_tuple());
276cde2e04fSAlex Crichton const Tuple &t = v.get_tuple();
277cde2e04fSAlex Crichton EXPECT_EQ(t.size(), data.size());
27853701b21SMangoPeachGrape for (auto i = 0; i < data.size(); i++) {
279cde2e04fSAlex Crichton const auto &elem = t.begin()[i];
280cde2e04fSAlex Crichton EXPECT_TRUE(elem.is_u32());
281cde2e04fSAlex Crichton EXPECT_EQ(elem.get_u32(), data[i]);
28253701b21SMangoPeachGrape }
28353701b21SMangoPeachGrape };
28453701b21SMangoPeachGrape
285cde2e04fSAlex Crichton static const auto make = [](std::vector<Val> data) -> Val {
286cde2e04fSAlex Crichton return Tuple(data);
28753701b21SMangoPeachGrape };
28853701b21SMangoPeachGrape
28953701b21SMangoPeachGrape auto ctx = create(
29053701b21SMangoPeachGrape R"((tuple u32 u32 u32))", R"(
29153701b21SMangoPeachGrape (param $x i32)
29253701b21SMangoPeachGrape (param $y i32)
29353701b21SMangoPeachGrape (param $z i32)
29453701b21SMangoPeachGrape (result i32)
29553701b21SMangoPeachGrape (local $res i32)
29653701b21SMangoPeachGrape local.get $x
29753701b21SMangoPeachGrape local.get $y
29853701b21SMangoPeachGrape local.get $z
29953701b21SMangoPeachGrape (call $realloc
30053701b21SMangoPeachGrape (i32.const 0)
30153701b21SMangoPeachGrape (i32.const 0)
30253701b21SMangoPeachGrape (i32.const 4)
30353701b21SMangoPeachGrape (i32.const 12))
30453701b21SMangoPeachGrape local.tee $res
30553701b21SMangoPeachGrape call $do
30653701b21SMangoPeachGrape local.get $res
30753701b21SMangoPeachGrape )",
30853701b21SMangoPeachGrape "(param i32 i32 i32 i32)",
309*39ec36caSAlex Crichton +[](Store::Context, const FuncType &, Span<const Val> args,
310cde2e04fSAlex Crichton Span<Val> rets) -> Result<std::monostate> {
311cde2e04fSAlex Crichton EXPECT_EQ(args.size(), 1);
31253701b21SMangoPeachGrape check(args[0], {1, 2, 3});
31353701b21SMangoPeachGrape
314cde2e04fSAlex Crichton EXPECT_EQ(rets.size(), 1);
315cde2e04fSAlex Crichton rets[0] = make({uint32_t(4), uint32_t(5), uint32_t(6)});
31653701b21SMangoPeachGrape
317cde2e04fSAlex Crichton return std::monostate();
31853701b21SMangoPeachGrape });
31953701b21SMangoPeachGrape
320cde2e04fSAlex Crichton auto arg = make({uint32_t(1), uint32_t(2), uint32_t(3)});
321cde2e04fSAlex Crichton auto res = Val(false);
32253701b21SMangoPeachGrape
323cde2e04fSAlex Crichton ctx.func.call(ctx.context, Span<const Val>(&arg, 1), Span<Val>(&res, 1))
324cde2e04fSAlex Crichton .unwrap();
325cde2e04fSAlex Crichton ctx.func.post_return(ctx.context).unwrap();
32653701b21SMangoPeachGrape
32753701b21SMangoPeachGrape check(res, {4, 5, 6});
32853701b21SMangoPeachGrape }
32953701b21SMangoPeachGrape
TEST(component,value_variant)33053701b21SMangoPeachGrape TEST(component, value_variant) {
331cde2e04fSAlex Crichton static const auto check_aa = [](const Val &v, uint32_t value) {
332cde2e04fSAlex Crichton EXPECT_TRUE(v.is_variant());
333cde2e04fSAlex Crichton const Variant &var = v.get_variant();
334cde2e04fSAlex Crichton EXPECT_EQ(var.discriminant(), "aa");
335cde2e04fSAlex Crichton EXPECT_NE(var.value(), nullptr);
336cde2e04fSAlex Crichton EXPECT_TRUE(var.value()->is_u32());
337cde2e04fSAlex Crichton EXPECT_EQ(var.value()->get_u32(), value);
33853701b21SMangoPeachGrape };
33953701b21SMangoPeachGrape
340cde2e04fSAlex Crichton static const auto check_bb = [](const Val &v, std::string_view value) {
341cde2e04fSAlex Crichton EXPECT_TRUE(v.is_variant());
342cde2e04fSAlex Crichton const Variant &var = v.get_variant();
343cde2e04fSAlex Crichton EXPECT_EQ(var.discriminant(), "bb");
344cde2e04fSAlex Crichton EXPECT_NE(var.value(), nullptr);
345cde2e04fSAlex Crichton EXPECT_TRUE(var.value()->is_string());
346cde2e04fSAlex Crichton EXPECT_EQ(var.value()->get_string(), value);
34753701b21SMangoPeachGrape };
34853701b21SMangoPeachGrape
349cde2e04fSAlex Crichton static const auto make_aa = [](uint32_t value) -> Val {
350cde2e04fSAlex Crichton return Variant("aa", Val(value));
35153701b21SMangoPeachGrape };
35253701b21SMangoPeachGrape
353cde2e04fSAlex Crichton static const auto make_bb = [](std::string_view value) -> Val {
354cde2e04fSAlex Crichton return Variant("bb", Val::string(value));
35553701b21SMangoPeachGrape };
35653701b21SMangoPeachGrape
35753701b21SMangoPeachGrape auto ctx = create(
35853701b21SMangoPeachGrape R"(
35953701b21SMangoPeachGrape (variant
36053701b21SMangoPeachGrape (case "aa" u32)
36153701b21SMangoPeachGrape (case "bb" string)
36253701b21SMangoPeachGrape )
36353701b21SMangoPeachGrape )",
36453701b21SMangoPeachGrape R"(
36553701b21SMangoPeachGrape (param $x i32)
36653701b21SMangoPeachGrape (param $y i32)
36753701b21SMangoPeachGrape (param $z i32)
36853701b21SMangoPeachGrape (result i32)
36953701b21SMangoPeachGrape (local $res i32)
37053701b21SMangoPeachGrape local.get $x
37153701b21SMangoPeachGrape local.get $y
37253701b21SMangoPeachGrape local.get $z
37353701b21SMangoPeachGrape (call $realloc
37453701b21SMangoPeachGrape (i32.const 0)
37553701b21SMangoPeachGrape (i32.const 0)
37653701b21SMangoPeachGrape (i32.const 4)
37753701b21SMangoPeachGrape (i32.const 12))
37853701b21SMangoPeachGrape local.tee $res
37953701b21SMangoPeachGrape call $do
38053701b21SMangoPeachGrape local.get $res
38153701b21SMangoPeachGrape )",
38253701b21SMangoPeachGrape "(param i32 i32 i32 i32)",
383*39ec36caSAlex Crichton +[](Store::Context, const FuncType &, Span<const Val> args,
384cde2e04fSAlex Crichton Span<Val> rets) -> Result<std::monostate> {
385cde2e04fSAlex Crichton EXPECT_EQ(args.size(), 1);
38653701b21SMangoPeachGrape check_aa(args[0], 123);
38753701b21SMangoPeachGrape
388cde2e04fSAlex Crichton EXPECT_EQ(rets.size(), 1);
38953701b21SMangoPeachGrape rets[0] = make_bb("textt");
39053701b21SMangoPeachGrape
391cde2e04fSAlex Crichton return std::monostate();
39253701b21SMangoPeachGrape });
39353701b21SMangoPeachGrape
39453701b21SMangoPeachGrape auto arg = make_aa(123);
395cde2e04fSAlex Crichton auto res = Val(false);
39653701b21SMangoPeachGrape
397cde2e04fSAlex Crichton ctx.func.call(ctx.context, Span<const Val>(&arg, 1), Span<Val>(&res, 1))
398cde2e04fSAlex Crichton .unwrap();
399cde2e04fSAlex Crichton ctx.func.post_return(ctx.context).unwrap();
40053701b21SMangoPeachGrape
40153701b21SMangoPeachGrape check_bb(res, "textt");
40253701b21SMangoPeachGrape }
40353701b21SMangoPeachGrape
TEST(component,value_enum)404fa89f323SMangoPeachGrape TEST(component, value_enum) {
405cde2e04fSAlex Crichton static const auto check = [](const Val &v, std::string_view text) {
406cde2e04fSAlex Crichton EXPECT_TRUE(v.is_enum());
407cde2e04fSAlex Crichton EXPECT_EQ(v.get_enum(), text);
408fa89f323SMangoPeachGrape };
409fa89f323SMangoPeachGrape
410cde2e04fSAlex Crichton static const auto make = [](std::string_view text) -> Val {
411cde2e04fSAlex Crichton return Val::enum_(text);
412fa89f323SMangoPeachGrape };
413fa89f323SMangoPeachGrape
414fa89f323SMangoPeachGrape auto ctx = create(
415fa89f323SMangoPeachGrape R"((enum "aa" "bb"))", R"(
416fa89f323SMangoPeachGrape (param $x i32)
417fa89f323SMangoPeachGrape (result i32)
418fa89f323SMangoPeachGrape local.get $x
419fa89f323SMangoPeachGrape call $do
420fa89f323SMangoPeachGrape )",
421fa89f323SMangoPeachGrape "(param i32) (result i32)",
422*39ec36caSAlex Crichton +[](Store::Context, const FuncType &, Span<const Val> args,
423cde2e04fSAlex Crichton Span<Val> rets) -> Result<std::monostate> {
424cde2e04fSAlex Crichton EXPECT_EQ(args.size(), 1);
425fa89f323SMangoPeachGrape check(args[0], "aa");
426fa89f323SMangoPeachGrape
427cde2e04fSAlex Crichton EXPECT_EQ(rets.size(), 1);
428fa89f323SMangoPeachGrape rets[0] = make("bb");
429fa89f323SMangoPeachGrape
430cde2e04fSAlex Crichton return std::monostate();
431fa89f323SMangoPeachGrape });
432fa89f323SMangoPeachGrape
433fa89f323SMangoPeachGrape auto arg = make("aa");
434cde2e04fSAlex Crichton auto res = Val(false);
435fa89f323SMangoPeachGrape
436cde2e04fSAlex Crichton ctx.func.call(ctx.context, Span<const Val>(&arg, 1), Span<Val>(&res, 1))
437cde2e04fSAlex Crichton .unwrap();
438cde2e04fSAlex Crichton ctx.func.post_return(ctx.context).unwrap();
439fa89f323SMangoPeachGrape
440fa89f323SMangoPeachGrape check(res, "bb");
441fa89f323SMangoPeachGrape }
442fa89f323SMangoPeachGrape
TEST(component,value_option)443fa89f323SMangoPeachGrape TEST(component, value_option) {
444cde2e04fSAlex Crichton static const auto check = [](const Val &v, std::optional<uint32_t> value) {
445cde2e04fSAlex Crichton EXPECT_TRUE(v.is_option());
446cde2e04fSAlex Crichton const WitOption &o = v.get_option();
447fa89f323SMangoPeachGrape if (value.has_value()) {
448cde2e04fSAlex Crichton EXPECT_NE(o.value(), nullptr);
449cde2e04fSAlex Crichton EXPECT_TRUE(o.value()->is_u32());
450cde2e04fSAlex Crichton EXPECT_EQ(o.value()->get_u32(), *value);
451fa89f323SMangoPeachGrape } else {
452cde2e04fSAlex Crichton EXPECT_EQ(o.value(), nullptr);
453fa89f323SMangoPeachGrape }
454fa89f323SMangoPeachGrape };
455fa89f323SMangoPeachGrape
456cde2e04fSAlex Crichton static const auto make = [](std::optional<uint32_t> value) -> Val {
457cde2e04fSAlex Crichton if (value) {
458cde2e04fSAlex Crichton return WitOption(Val(*value));
459fa89f323SMangoPeachGrape }
460cde2e04fSAlex Crichton return WitOption(std::nullopt);
461fa89f323SMangoPeachGrape };
462fa89f323SMangoPeachGrape
463fa89f323SMangoPeachGrape auto ctx = create(
464fa89f323SMangoPeachGrape R"((option u32))", R"(
465fa89f323SMangoPeachGrape (param $x i32)
466fa89f323SMangoPeachGrape (param $y i32)
467fa89f323SMangoPeachGrape (result i32)
468fa89f323SMangoPeachGrape (local $res i32)
469fa89f323SMangoPeachGrape local.get $x
470fa89f323SMangoPeachGrape local.get $y
471fa89f323SMangoPeachGrape (call $realloc
472fa89f323SMangoPeachGrape (i32.const 0)
473fa89f323SMangoPeachGrape (i32.const 0)
474fa89f323SMangoPeachGrape (i32.const 4)
475fa89f323SMangoPeachGrape (i32.const 8))
476fa89f323SMangoPeachGrape local.tee $res
477fa89f323SMangoPeachGrape call $do
478fa89f323SMangoPeachGrape local.get $res
479fa89f323SMangoPeachGrape )",
480fa89f323SMangoPeachGrape "(param i32 i32 i32)",
481*39ec36caSAlex Crichton +[](Store::Context, const FuncType &, Span<const Val> args,
482cde2e04fSAlex Crichton Span<Val> rets) -> Result<std::monostate> {
483cde2e04fSAlex Crichton EXPECT_EQ(args.size(), 1);
484fa89f323SMangoPeachGrape check(args[0], 123);
485fa89f323SMangoPeachGrape
486cde2e04fSAlex Crichton EXPECT_EQ(rets.size(), 1);
487fa89f323SMangoPeachGrape rets[0] = make({});
488fa89f323SMangoPeachGrape
489cde2e04fSAlex Crichton return std::monostate();
490fa89f323SMangoPeachGrape });
491fa89f323SMangoPeachGrape
492fa89f323SMangoPeachGrape auto arg = make(123);
493cde2e04fSAlex Crichton auto res = Val(false);
494fa89f323SMangoPeachGrape
495cde2e04fSAlex Crichton ctx.func.call(ctx.context, Span<const Val>(&arg, 1), Span<Val>(&res, 1))
496cde2e04fSAlex Crichton .unwrap();
497cde2e04fSAlex Crichton ctx.func.post_return(ctx.context).unwrap();
498fa89f323SMangoPeachGrape
499fa89f323SMangoPeachGrape check(res, {});
500fa89f323SMangoPeachGrape }
501fa89f323SMangoPeachGrape
TEST(component,value_result)50290a2351bSMangoPeachGrape TEST(component, value_result) {
503cde2e04fSAlex Crichton static const auto check = [](const Val &v, bool expected_is_ok,
504cde2e04fSAlex Crichton uint32_t expected_value) {
505cde2e04fSAlex Crichton EXPECT_TRUE(v.is_result());
506cde2e04fSAlex Crichton const WitResult &r = v.get_result();
507cde2e04fSAlex Crichton EXPECT_EQ(r.is_ok(), expected_is_ok);
508cde2e04fSAlex Crichton EXPECT_NE(r.payload(), nullptr);
509cde2e04fSAlex Crichton EXPECT_TRUE(r.payload()->is_u32());
510cde2e04fSAlex Crichton EXPECT_EQ(r.payload()->get_u32(), expected_value);
51190a2351bSMangoPeachGrape };
51290a2351bSMangoPeachGrape
513cde2e04fSAlex Crichton static const auto make = [](bool is_ok, uint32_t value) -> Val {
514cde2e04fSAlex Crichton if (is_ok) {
515cde2e04fSAlex Crichton return WitResult::ok(Val(value));
516cde2e04fSAlex Crichton }
517cde2e04fSAlex Crichton return WitResult::err(Val(value));
51890a2351bSMangoPeachGrape };
51990a2351bSMangoPeachGrape
52090a2351bSMangoPeachGrape auto ctx = create(
52190a2351bSMangoPeachGrape R"((result u32 (error u32)))", R"(
52290a2351bSMangoPeachGrape (param $x i32)
52390a2351bSMangoPeachGrape (param $y i32)
52490a2351bSMangoPeachGrape (result i32)
52590a2351bSMangoPeachGrape (local $res i32)
52690a2351bSMangoPeachGrape local.get $x
52790a2351bSMangoPeachGrape local.get $y
52890a2351bSMangoPeachGrape (call $realloc
52990a2351bSMangoPeachGrape (i32.const 0)
53090a2351bSMangoPeachGrape (i32.const 0)
53190a2351bSMangoPeachGrape (i32.const 4)
53290a2351bSMangoPeachGrape (i32.const 8))
53390a2351bSMangoPeachGrape local.tee $res
53490a2351bSMangoPeachGrape call $do
53590a2351bSMangoPeachGrape local.get $res
53690a2351bSMangoPeachGrape )",
53790a2351bSMangoPeachGrape "(param i32 i32 i32)",
538*39ec36caSAlex Crichton +[](Store::Context, const FuncType &, Span<const Val> args,
539cde2e04fSAlex Crichton Span<Val> rets) -> Result<std::monostate> {
540cde2e04fSAlex Crichton EXPECT_EQ(args.size(), 1);
54190a2351bSMangoPeachGrape check(args[0], true, 123);
54290a2351bSMangoPeachGrape
543cde2e04fSAlex Crichton EXPECT_EQ(rets.size(), 1);
54490a2351bSMangoPeachGrape rets[0] = make(false, 456);
54590a2351bSMangoPeachGrape
546cde2e04fSAlex Crichton return std::monostate();
54790a2351bSMangoPeachGrape });
54890a2351bSMangoPeachGrape
54990a2351bSMangoPeachGrape auto arg = make(true, 123);
550cde2e04fSAlex Crichton auto res = Val(false);
55190a2351bSMangoPeachGrape
552cde2e04fSAlex Crichton ctx.func.call(ctx.context, Span<const Val>(&arg, 1), Span<Val>(&res, 1))
553cde2e04fSAlex Crichton .unwrap();
554cde2e04fSAlex Crichton ctx.func.post_return(ctx.context).unwrap();
55590a2351bSMangoPeachGrape
55690a2351bSMangoPeachGrape check(res, false, 456);
55790a2351bSMangoPeachGrape }
55890a2351bSMangoPeachGrape
TEST(component,value_flags)5599a26c101SMangoPeachGrape TEST(component, value_flags) {
560cde2e04fSAlex Crichton static const auto check = [](const Val &v, std::vector<std::string> data) {
561cde2e04fSAlex Crichton EXPECT_TRUE(v.is_flags());
562cde2e04fSAlex Crichton const Flags &f = v.get_flags();
563cde2e04fSAlex Crichton
564cde2e04fSAlex Crichton EXPECT_EQ(f.size(), data.size());
5659a26c101SMangoPeachGrape for (auto i = 0; i < data.size(); i++) {
566cde2e04fSAlex Crichton EXPECT_EQ(f.begin()[i].name(), data[i]);
5679a26c101SMangoPeachGrape }
5689a26c101SMangoPeachGrape };
5699a26c101SMangoPeachGrape
570cde2e04fSAlex Crichton static const auto make = [](std::vector<Flag> data) -> Val {
571cde2e04fSAlex Crichton return Flags(data);
5729a26c101SMangoPeachGrape };
5739a26c101SMangoPeachGrape
5749a26c101SMangoPeachGrape auto ctx = create(
5759a26c101SMangoPeachGrape R"((flags "aa" "bb"))", R"(
5769a26c101SMangoPeachGrape (param $x i32)
5779a26c101SMangoPeachGrape (result i32)
5789a26c101SMangoPeachGrape local.get $x
5799a26c101SMangoPeachGrape call $do
5809a26c101SMangoPeachGrape )",
5819a26c101SMangoPeachGrape "(param i32) (result i32)",
582*39ec36caSAlex Crichton +[](Store::Context, const FuncType &, Span<const Val> args,
583cde2e04fSAlex Crichton Span<Val> rets) -> Result<std::monostate> {
584cde2e04fSAlex Crichton EXPECT_EQ(args.size(), 1);
5859a26c101SMangoPeachGrape check(args[0], {"aa"});
5869a26c101SMangoPeachGrape
587cde2e04fSAlex Crichton EXPECT_EQ(rets.size(), 1);
588cde2e04fSAlex Crichton rets[0] = make({Flag("aa"), Flag("bb")});
5899a26c101SMangoPeachGrape
590cde2e04fSAlex Crichton return std::monostate();
5919a26c101SMangoPeachGrape });
5929a26c101SMangoPeachGrape
593cde2e04fSAlex Crichton auto arg = make({Flag("aa")});
594cde2e04fSAlex Crichton auto res = Val(false);
5959a26c101SMangoPeachGrape
596cde2e04fSAlex Crichton ctx.func.call(ctx.context, Span<const Val>(&arg, 1), Span<Val>(&res, 1))
597cde2e04fSAlex Crichton .unwrap();
598cde2e04fSAlex Crichton ctx.func.post_return(ctx.context).unwrap();
5999a26c101SMangoPeachGrape
6009a26c101SMangoPeachGrape check(res, {"aa", "bb"});
6019a26c101SMangoPeachGrape }
6029a26c101SMangoPeachGrape
TEST(component,value_list_inner)603b2c64de1SMangoPeachGrape TEST(component, value_list_inner) {
604b2c64de1SMangoPeachGrape auto x = wasmtime_component_val_t{
605b2c64de1SMangoPeachGrape .kind = WASMTIME_COMPONENT_LIST,
606b2c64de1SMangoPeachGrape };
607b2c64de1SMangoPeachGrape wasmtime_component_vallist_new_empty(&x.of.list);
608b2c64de1SMangoPeachGrape EXPECT_EQ(x.of.list.data, nullptr);
609b2c64de1SMangoPeachGrape EXPECT_EQ(x.of.list.size, 0);
610b2c64de1SMangoPeachGrape
611b2c64de1SMangoPeachGrape wasmtime_component_vallist_new_uninit(&x.of.list, 1);
612b2c64de1SMangoPeachGrape EXPECT_NE(x.of.list.data, nullptr);
613b2c64de1SMangoPeachGrape EXPECT_EQ(x.of.list.size, 1);
614b2c64de1SMangoPeachGrape
615b2c64de1SMangoPeachGrape wasmtime_component_vallist_delete(&x.of.list);
616b2c64de1SMangoPeachGrape
617b2c64de1SMangoPeachGrape auto items = std::array{
618b2c64de1SMangoPeachGrape wasmtime_component_val_t{
619b2c64de1SMangoPeachGrape .kind = WASMTIME_COMPONENT_U32,
620b2c64de1SMangoPeachGrape .of = {.u32 = 123},
621b2c64de1SMangoPeachGrape },
622b2c64de1SMangoPeachGrape };
623b2c64de1SMangoPeachGrape
624b2c64de1SMangoPeachGrape wasmtime_component_vallist_new(&x.of.list, items.size(), items.data());
625b2c64de1SMangoPeachGrape EXPECT_NE(x.of.list.data, nullptr);
626b2c64de1SMangoPeachGrape EXPECT_EQ(x.of.list.size, 1);
627b2c64de1SMangoPeachGrape
628b2c64de1SMangoPeachGrape EXPECT_EQ(x.of.list.data[0].kind, WASMTIME_COMPONENT_U32);
629b2c64de1SMangoPeachGrape EXPECT_EQ(x.of.list.data[0].of.u32, 123);
630b2c64de1SMangoPeachGrape
631b2c64de1SMangoPeachGrape auto clone = wasmtime_component_val_t{
632b2c64de1SMangoPeachGrape .kind = WASMTIME_COMPONENT_LIST,
633b2c64de1SMangoPeachGrape };
634b2c64de1SMangoPeachGrape
635b2c64de1SMangoPeachGrape wasmtime_component_vallist_copy(&clone.of.list, &x.of.list);
636b2c64de1SMangoPeachGrape wasmtime_component_vallist_delete(&x.of.list);
637b2c64de1SMangoPeachGrape
638b2c64de1SMangoPeachGrape EXPECT_NE(clone.of.list.data, nullptr);
639b2c64de1SMangoPeachGrape EXPECT_EQ(clone.of.list.size, 1);
640b2c64de1SMangoPeachGrape
641b2c64de1SMangoPeachGrape EXPECT_EQ(clone.of.list.data[0].kind, WASMTIME_COMPONENT_U32);
642b2c64de1SMangoPeachGrape EXPECT_EQ(clone.of.list.data[0].of.u32, 123);
643b2c64de1SMangoPeachGrape
644b2c64de1SMangoPeachGrape wasmtime_component_vallist_delete(&clone.of.list);
645b2c64de1SMangoPeachGrape }
646cde2e04fSAlex Crichton
TEST(component,records)647cde2e04fSAlex Crichton TEST(component, records) {
648cde2e04fSAlex Crichton Record r({{"x", uint64_t(1)}, {"y", uint64_t(2)}});
649cde2e04fSAlex Crichton EXPECT_EQ(r.size(), 2);
650cde2e04fSAlex Crichton
651cde2e04fSAlex Crichton for (auto &field : r) {
652cde2e04fSAlex Crichton if (field.name() == "x") {
653cde2e04fSAlex Crichton EXPECT_EQ(field.value().get_u64(), 1);
654cde2e04fSAlex Crichton } else if (field.name() == "y") {
655cde2e04fSAlex Crichton EXPECT_EQ(field.value().get_u64(), 2);
656cde2e04fSAlex Crichton } else {
657cde2e04fSAlex Crichton FAIL() << "unexpected field name: " << field.name();
658cde2e04fSAlex Crichton }
659cde2e04fSAlex Crichton }
660cde2e04fSAlex Crichton
661cde2e04fSAlex Crichton Record r2({{"x", r}, {"y", uint64_t(2)}});
662cde2e04fSAlex Crichton EXPECT_EQ(r2.size(), 2);
663cde2e04fSAlex Crichton EXPECT_EQ(r.size(), 2);
664cde2e04fSAlex Crichton
665cde2e04fSAlex Crichton for (auto &field : r2) {
666cde2e04fSAlex Crichton if (field.name() == "x") {
667cde2e04fSAlex Crichton auto inner = field.value().get_record();
668cde2e04fSAlex Crichton EXPECT_EQ(inner.size(), 2);
669cde2e04fSAlex Crichton for (auto &inner_field : inner) {
670cde2e04fSAlex Crichton if (inner_field.name() == "x") {
671cde2e04fSAlex Crichton EXPECT_EQ(inner_field.value().get_u64(), 1);
672cde2e04fSAlex Crichton } else if (inner_field.name() == "y") {
673cde2e04fSAlex Crichton EXPECT_EQ(inner_field.value().get_u64(), 2);
674cde2e04fSAlex Crichton } else {
675cde2e04fSAlex Crichton FAIL() << "unexpected inner field name: " << inner_field.name();
676cde2e04fSAlex Crichton }
677cde2e04fSAlex Crichton }
678cde2e04fSAlex Crichton } else if (field.name() == "y") {
679cde2e04fSAlex Crichton EXPECT_EQ(field.value().get_u64(), 2);
680cde2e04fSAlex Crichton } else {
681cde2e04fSAlex Crichton FAIL() << "unexpected field name: " << field.name();
682cde2e04fSAlex Crichton }
683cde2e04fSAlex Crichton }
684cde2e04fSAlex Crichton
685cde2e04fSAlex Crichton Val record = r2;
686cde2e04fSAlex Crichton EXPECT_TRUE(record.is_record());
687cde2e04fSAlex Crichton EXPECT_EQ(r2.size(), 2);
688cde2e04fSAlex Crichton Val record2 = std::move(r2);
689cde2e04fSAlex Crichton EXPECT_TRUE(record2.is_record());
690cde2e04fSAlex Crichton EXPECT_EQ(r2.size(), 0);
691cde2e04fSAlex Crichton }
692cde2e04fSAlex Crichton
TEST(component,lists)693cde2e04fSAlex Crichton TEST(component, lists) {
694cde2e04fSAlex Crichton List l({uint32_t(1), uint32_t(2), uint32_t(3)});
695cde2e04fSAlex Crichton EXPECT_EQ(l.size(), 3);
696cde2e04fSAlex Crichton uint32_t expected = 1;
697cde2e04fSAlex Crichton for (auto &val : l) {
698cde2e04fSAlex Crichton EXPECT_EQ(val.get_u32(), expected);
699cde2e04fSAlex Crichton expected++;
700cde2e04fSAlex Crichton }
701cde2e04fSAlex Crichton
702cde2e04fSAlex Crichton List l2 = l;
703cde2e04fSAlex Crichton EXPECT_EQ(l.size(), 3);
704cde2e04fSAlex Crichton EXPECT_EQ(l2.size(), 3);
705cde2e04fSAlex Crichton
706cde2e04fSAlex Crichton List l3 = std::move(l);
707cde2e04fSAlex Crichton EXPECT_EQ(l.size(), 0);
708cde2e04fSAlex Crichton EXPECT_EQ(l3.size(), 3);
709cde2e04fSAlex Crichton
710cde2e04fSAlex Crichton Val value(l3);
711cde2e04fSAlex Crichton value.get_list();
712cde2e04fSAlex Crichton }
713cde2e04fSAlex Crichton
TEST(component,tuples)714cde2e04fSAlex Crichton TEST(component, tuples) {
715cde2e04fSAlex Crichton Tuple l({uint32_t(1), uint64_t(2), uint8_t(3)});
716cde2e04fSAlex Crichton EXPECT_EQ(l.size(), 3);
717cde2e04fSAlex Crichton
718cde2e04fSAlex Crichton Val value(l);
719cde2e04fSAlex Crichton EXPECT_TRUE(value.is_tuple());
720cde2e04fSAlex Crichton EXPECT_EQ(l.size(), 3);
721cde2e04fSAlex Crichton
722cde2e04fSAlex Crichton for (auto &val : l) {
723cde2e04fSAlex Crichton if (val.is_u32()) {
724cde2e04fSAlex Crichton EXPECT_EQ(val.get_u32(), 1);
725cde2e04fSAlex Crichton } else if (val.is_u64()) {
726cde2e04fSAlex Crichton EXPECT_EQ(val.get_u64(), 2);
727cde2e04fSAlex Crichton } else if (val.is_u8()) {
728cde2e04fSAlex Crichton EXPECT_EQ(val.get_u8(), 3);
729cde2e04fSAlex Crichton } else {
730cde2e04fSAlex Crichton FAIL() << "unexpected tuple value type";
731cde2e04fSAlex Crichton }
732cde2e04fSAlex Crichton }
733cde2e04fSAlex Crichton }
734cde2e04fSAlex Crichton
TEST(component,variants)735cde2e04fSAlex Crichton TEST(component, variants) {
736cde2e04fSAlex Crichton Variant v("hello", uint32_t(42));
737cde2e04fSAlex Crichton EXPECT_EQ(v.discriminant(), "hello");
738cde2e04fSAlex Crichton EXPECT_TRUE(v.value()->is_u32());
739cde2e04fSAlex Crichton EXPECT_EQ(v.value()->get_u32(), 42);
740cde2e04fSAlex Crichton
741cde2e04fSAlex Crichton Variant v2("another", v);
742cde2e04fSAlex Crichton EXPECT_EQ(v.discriminant(), "hello");
743cde2e04fSAlex Crichton EXPECT_TRUE(v.value()->is_u32());
744cde2e04fSAlex Crichton EXPECT_EQ(v.value()->get_u32(), 42);
745cde2e04fSAlex Crichton EXPECT_EQ(v2.discriminant(), "another");
746cde2e04fSAlex Crichton EXPECT_TRUE(v2.value()->is_variant());
747cde2e04fSAlex Crichton auto inner = v2.value()->get_variant();
748cde2e04fSAlex Crichton EXPECT_EQ(inner.discriminant(), "hello");
749cde2e04fSAlex Crichton EXPECT_TRUE(inner.value()->is_u32());
750cde2e04fSAlex Crichton EXPECT_EQ(inner.value()->get_u32(), 42);
751cde2e04fSAlex Crichton
752cde2e04fSAlex Crichton Val value = v;
753cde2e04fSAlex Crichton EXPECT_TRUE(value.is_variant());
754cde2e04fSAlex Crichton auto v3 = value.get_variant();
755cde2e04fSAlex Crichton EXPECT_EQ(v3.discriminant(), "hello");
756cde2e04fSAlex Crichton EXPECT_TRUE(v3.value()->is_u32());
757cde2e04fSAlex Crichton EXPECT_EQ(v3.value()->get_u32(), 42);
758cde2e04fSAlex Crichton }
759cde2e04fSAlex Crichton
TEST(component,strings)760cde2e04fSAlex Crichton TEST(component, strings) {
761cde2e04fSAlex Crichton Val v = Val::string("hi");
762cde2e04fSAlex Crichton EXPECT_TRUE(v.is_string());
763cde2e04fSAlex Crichton EXPECT_EQ(v.get_string(), "hi");
764cde2e04fSAlex Crichton
765cde2e04fSAlex Crichton v = Val::string("another");
766cde2e04fSAlex Crichton EXPECT_TRUE(v.is_string());
767cde2e04fSAlex Crichton EXPECT_EQ(v.get_string(), "another");
768cde2e04fSAlex Crichton }
769cde2e04fSAlex Crichton
TEST(component,results)770cde2e04fSAlex Crichton TEST(component, results) {
771cde2e04fSAlex Crichton WitResult r = WitResult::ok(uint32_t(42));
772cde2e04fSAlex Crichton EXPECT_TRUE(r.is_ok());
773cde2e04fSAlex Crichton EXPECT_EQ(r.payload()->get_u32(), 42);
774cde2e04fSAlex Crichton
775cde2e04fSAlex Crichton r = WitResult::ok(std::nullopt);
776cde2e04fSAlex Crichton EXPECT_TRUE(r.is_ok());
777cde2e04fSAlex Crichton EXPECT_EQ(r.payload(), nullptr);
778cde2e04fSAlex Crichton
779cde2e04fSAlex Crichton r = WitResult::err(std::nullopt);
780cde2e04fSAlex Crichton EXPECT_FALSE(r.is_ok());
781cde2e04fSAlex Crichton EXPECT_EQ(r.payload(), nullptr);
782cde2e04fSAlex Crichton
783cde2e04fSAlex Crichton Val v = r;
784cde2e04fSAlex Crichton EXPECT_TRUE(v.is_result());
785cde2e04fSAlex Crichton auto r2 = v.get_result();
786cde2e04fSAlex Crichton EXPECT_FALSE(r2.is_ok());
787cde2e04fSAlex Crichton EXPECT_EQ(r2.payload(), nullptr);
788cde2e04fSAlex Crichton
789cde2e04fSAlex Crichton r = WitResult::ok(uint32_t(99));
790cde2e04fSAlex Crichton v = r;
791cde2e04fSAlex Crichton EXPECT_TRUE(r.is_ok());
792cde2e04fSAlex Crichton EXPECT_NE(r.payload(), nullptr);
793cde2e04fSAlex Crichton EXPECT_EQ(r.payload()->get_u32(), 99);
794cde2e04fSAlex Crichton }
795cde2e04fSAlex Crichton
TEST(component,enums)796cde2e04fSAlex Crichton TEST(component, enums) {
797cde2e04fSAlex Crichton Val v = Val::enum_("hi");
798cde2e04fSAlex Crichton EXPECT_TRUE(v.is_enum());
799cde2e04fSAlex Crichton EXPECT_EQ(v.get_enum(), "hi");
800cde2e04fSAlex Crichton
801cde2e04fSAlex Crichton v = Val::enum_("another");
802cde2e04fSAlex Crichton EXPECT_TRUE(v.is_enum());
803cde2e04fSAlex Crichton EXPECT_EQ(v.get_enum(), "another");
804cde2e04fSAlex Crichton }
805cde2e04fSAlex Crichton
TEST(component,options)806cde2e04fSAlex Crichton TEST(component, options) {
807cde2e04fSAlex Crichton WitOption o(Val(uint32_t(42)));
808cde2e04fSAlex Crichton EXPECT_NE(o.value(), nullptr);
809cde2e04fSAlex Crichton EXPECT_TRUE(o.value()->is_u32());
810cde2e04fSAlex Crichton EXPECT_EQ(o.value()->get_u32(), 42);
811cde2e04fSAlex Crichton
812cde2e04fSAlex Crichton Val v(o);
813cde2e04fSAlex Crichton WitOption o2(v);
814cde2e04fSAlex Crichton EXPECT_NE(o.value(), nullptr);
815cde2e04fSAlex Crichton EXPECT_TRUE(o2.value()->is_option());
816cde2e04fSAlex Crichton auto inner = o2.value()->get_option();
817cde2e04fSAlex Crichton auto value = inner.value();
818cde2e04fSAlex Crichton EXPECT_NE(value, nullptr);
819cde2e04fSAlex Crichton EXPECT_TRUE(value->is_u32());
820cde2e04fSAlex Crichton EXPECT_EQ(value->get_u32(), 42);
821cde2e04fSAlex Crichton
822cde2e04fSAlex Crichton EXPECT_NE(o.value(), nullptr);
823cde2e04fSAlex Crichton EXPECT_TRUE(o.value()->is_u32());
824cde2e04fSAlex Crichton EXPECT_EQ(o.value()->get_u32(), 42);
825cde2e04fSAlex Crichton
826cde2e04fSAlex Crichton WitOption o3(std::nullopt);
827cde2e04fSAlex Crichton EXPECT_EQ(o3.value(), nullptr);
828cde2e04fSAlex Crichton }
829cde2e04fSAlex Crichton
TEST(component,flags)830cde2e04fSAlex Crichton TEST(component, flags) {
831cde2e04fSAlex Crichton std::vector<Flag> flags = {
832cde2e04fSAlex Crichton Flag("a"),
833cde2e04fSAlex Crichton Flag("b"),
834cde2e04fSAlex Crichton Flag("c"),
835cde2e04fSAlex Crichton };
836cde2e04fSAlex Crichton Flags f(flags);
837cde2e04fSAlex Crichton EXPECT_EQ(f.size(), 3);
838cde2e04fSAlex Crichton for (auto i = 0; i < f.size(); i++) {
839cde2e04fSAlex Crichton EXPECT_EQ(f.begin()[i].name(), flags[i].name());
840cde2e04fSAlex Crichton }
841cde2e04fSAlex Crichton
842cde2e04fSAlex Crichton flags.clear();
843cde2e04fSAlex Crichton Flags f2(flags);
844cde2e04fSAlex Crichton EXPECT_EQ(f2.size(), 0);
845cde2e04fSAlex Crichton EXPECT_EQ(f.size(), 3);
846cde2e04fSAlex Crichton
847cde2e04fSAlex Crichton Val v = f;
848cde2e04fSAlex Crichton EXPECT_TRUE(v.is_flags());
849cde2e04fSAlex Crichton Flags f3 = v.get_flags();
850cde2e04fSAlex Crichton EXPECT_EQ(f3.size(), 3);
851cde2e04fSAlex Crichton EXPECT_EQ(f.size(), 3);
852b2c64de1SMangoPeachGrape }
853dbc21cdeSAlex Crichton
TEST(component,value_host_resource)854dbc21cdeSAlex Crichton TEST(component, value_host_resource) {
855dbc21cdeSAlex Crichton static const uint32_t RESOURCE_TYPE = 100;
856dbc21cdeSAlex Crichton
857dbc21cdeSAlex Crichton static const auto check = [](Store::Context cx, const Val &v, uint32_t rep) {
858dbc21cdeSAlex Crichton EXPECT_TRUE(v.is_resource());
859dbc21cdeSAlex Crichton const ResourceAny &f = v.get_resource();
860dbc21cdeSAlex Crichton EXPECT_EQ(f.type(), ResourceType(RESOURCE_TYPE));
861dbc21cdeSAlex Crichton ResourceHost r = f.to_host(cx).unwrap();
862dbc21cdeSAlex Crichton EXPECT_EQ(r.rep(), rep);
863dbc21cdeSAlex Crichton EXPECT_EQ(r.type(), RESOURCE_TYPE);
864dbc21cdeSAlex Crichton };
865dbc21cdeSAlex Crichton
866dbc21cdeSAlex Crichton static const auto make = [](Store::Context cx, uint32_t rep) -> Val {
867dbc21cdeSAlex Crichton return ResourceHost(true, rep, RESOURCE_TYPE).to_any(cx).unwrap();
868dbc21cdeSAlex Crichton };
869dbc21cdeSAlex Crichton
870dbc21cdeSAlex Crichton Engine engine;
871dbc21cdeSAlex Crichton Linker linker(engine);
872dbc21cdeSAlex Crichton {
873dbc21cdeSAlex Crichton LinkerInstance i = linker.root();
874dbc21cdeSAlex Crichton
875dbc21cdeSAlex Crichton i.add_resource(
876dbc21cdeSAlex Crichton "r", ResourceType(RESOURCE_TYPE),
877dbc21cdeSAlex Crichton +[](Store::Context, uint32_t rep) -> Result<std::monostate> {
878dbc21cdeSAlex Crichton EXPECT_EQ(rep, 42);
879dbc21cdeSAlex Crichton return std::monostate();
880dbc21cdeSAlex Crichton })
881dbc21cdeSAlex Crichton .unwrap();
882dbc21cdeSAlex Crichton
883dbc21cdeSAlex Crichton i.add_func(
884dbc21cdeSAlex Crichton "f",
885*39ec36caSAlex Crichton +[](Store::Context cx, const FuncType &_ty, Span<const Val> args,
886dbc21cdeSAlex Crichton Span<Val> rets) -> Result<std::monostate> {
887dbc21cdeSAlex Crichton EXPECT_EQ(args.size(), 1);
888dbc21cdeSAlex Crichton check(cx, args[0], 42);
889dbc21cdeSAlex Crichton
890dbc21cdeSAlex Crichton EXPECT_EQ(rets.size(), 1);
891dbc21cdeSAlex Crichton rets[0] = make(cx, 43);
892dbc21cdeSAlex Crichton return std::monostate();
893dbc21cdeSAlex Crichton })
894dbc21cdeSAlex Crichton .unwrap();
895dbc21cdeSAlex Crichton }
896dbc21cdeSAlex Crichton
897dbc21cdeSAlex Crichton auto ctx = Context::New(engine,
898dbc21cdeSAlex Crichton R"(
899dbc21cdeSAlex Crichton (component
900dbc21cdeSAlex Crichton (import "r" (type $r (sub resource)))
901dbc21cdeSAlex Crichton (import "f" (func $f (param "a" (own $r)) (result (own $r))))
902dbc21cdeSAlex Crichton (core func $f (canon lower (func $f)))
903dbc21cdeSAlex Crichton
904dbc21cdeSAlex Crichton (core module $m
905dbc21cdeSAlex Crichton (import "" "f" (func $f (param i32) (result i32)))
906dbc21cdeSAlex Crichton
907dbc21cdeSAlex Crichton (func (export "call") (param i32) (result i32)
908dbc21cdeSAlex Crichton local.get 0
909dbc21cdeSAlex Crichton call $f)
910dbc21cdeSAlex Crichton )
911dbc21cdeSAlex Crichton
912dbc21cdeSAlex Crichton (core instance $m (instantiate $m
913dbc21cdeSAlex Crichton (with "" (instance
914dbc21cdeSAlex Crichton (export "f" (func $f))
915dbc21cdeSAlex Crichton ))
916dbc21cdeSAlex Crichton ))
917dbc21cdeSAlex Crichton
918dbc21cdeSAlex Crichton (func (export "call") (param "a" (own $r)) (result (own $r))
919dbc21cdeSAlex Crichton (canon lift (core func $m "call")))
920dbc21cdeSAlex Crichton )
921dbc21cdeSAlex Crichton )",
922dbc21cdeSAlex Crichton linker);
923dbc21cdeSAlex Crichton
924dbc21cdeSAlex Crichton auto arg = make(ctx.context, 42);
925dbc21cdeSAlex Crichton auto res = Val(false);
926dbc21cdeSAlex Crichton
927dbc21cdeSAlex Crichton ctx.func.call(ctx.context, Span<const Val>(&arg, 1), Span<Val>(&res, 1))
928dbc21cdeSAlex Crichton .unwrap();
929dbc21cdeSAlex Crichton ctx.func.post_return(ctx.context).unwrap();
930dbc21cdeSAlex Crichton
931dbc21cdeSAlex Crichton check(ctx.context, res, 43);
932dbc21cdeSAlex Crichton }
933dbc21cdeSAlex Crichton
TEST(component,value_guest_resource)934dbc21cdeSAlex Crichton TEST(component, value_guest_resource) {
935dbc21cdeSAlex Crichton Engine engine;
936dbc21cdeSAlex Crichton Linker linker(engine);
937dbc21cdeSAlex Crichton Store store(engine);
938dbc21cdeSAlex Crichton
939dbc21cdeSAlex Crichton Component c = Component::compile(engine,
940dbc21cdeSAlex Crichton R"(
941dbc21cdeSAlex Crichton (component
942dbc21cdeSAlex Crichton (core module $a
943dbc21cdeSAlex Crichton (global $g (mut i32) (i32.const 0))
944dbc21cdeSAlex Crichton
945dbc21cdeSAlex Crichton (func (export "dtor") (param i32) (global.set $g (local.get 0)))
946dbc21cdeSAlex Crichton (func (export "last-dtor-rep") (result i32) global.get $g)
947dbc21cdeSAlex Crichton )
948dbc21cdeSAlex Crichton (core instance $a (instantiate $a))
949dbc21cdeSAlex Crichton (type $r' (resource (rep i32) (dtor (func $a "dtor"))))
950dbc21cdeSAlex Crichton (export $r "r" (type $r'))
951dbc21cdeSAlex Crichton
952dbc21cdeSAlex Crichton (core func $new (canon resource.new $r))
953dbc21cdeSAlex Crichton (core func $drop (canon resource.drop $r))
954dbc21cdeSAlex Crichton
955dbc21cdeSAlex Crichton (core module $b
956dbc21cdeSAlex Crichton (import "" "new" (func $new (param i32) (result i32)))
957dbc21cdeSAlex Crichton (import "" "drop" (func $drop (param i32)))
958dbc21cdeSAlex Crichton
959dbc21cdeSAlex Crichton (func (export "new") (param i32) (result i32)
960dbc21cdeSAlex Crichton local.get 0
961dbc21cdeSAlex Crichton call $new)
962dbc21cdeSAlex Crichton
963dbc21cdeSAlex Crichton (func (export "rep") (param i32) (result i32)
964dbc21cdeSAlex Crichton local.get 0)
965dbc21cdeSAlex Crichton
966dbc21cdeSAlex Crichton (func (export "drop") (param i32)
967dbc21cdeSAlex Crichton local.get 0
968dbc21cdeSAlex Crichton call $drop)
969dbc21cdeSAlex Crichton )
970dbc21cdeSAlex Crichton (core instance $b (instantiate $b
971dbc21cdeSAlex Crichton (with "" (instance
972dbc21cdeSAlex Crichton (export "new" (func $new))
973dbc21cdeSAlex Crichton (export "drop" (func $drop))
974dbc21cdeSAlex Crichton ))
975dbc21cdeSAlex Crichton ))
976dbc21cdeSAlex Crichton
977dbc21cdeSAlex Crichton (func (export "new") (param "x" u32) (result (own $r))
978dbc21cdeSAlex Crichton (canon lift (core func $b "new")))
979dbc21cdeSAlex Crichton (func (export "rep") (param "x" (borrow $r)) (result u32)
980dbc21cdeSAlex Crichton (canon lift (core func $b "rep")))
981dbc21cdeSAlex Crichton (func (export "drop") (param "x" (own $r))
982dbc21cdeSAlex Crichton (canon lift (core func $b "drop")))
983dbc21cdeSAlex Crichton (func (export "last-dtor-rep") (result u32)
984dbc21cdeSAlex Crichton (canon lift (core func $a "last-dtor-rep")))
985dbc21cdeSAlex Crichton
986dbc21cdeSAlex Crichton )
987dbc21cdeSAlex Crichton )")
988dbc21cdeSAlex Crichton .unwrap();
989dbc21cdeSAlex Crichton
990dbc21cdeSAlex Crichton auto instance = linker.instantiate(store, c).unwrap();
991dbc21cdeSAlex Crichton auto new_index = *instance.get_export_index(store, nullptr, "new");
992dbc21cdeSAlex Crichton auto rep_index = *instance.get_export_index(store, nullptr, "rep");
993dbc21cdeSAlex Crichton auto drop_index = *instance.get_export_index(store, nullptr, "drop");
994dbc21cdeSAlex Crichton auto last_dtor_rep_index =
995dbc21cdeSAlex Crichton *instance.get_export_index(store, nullptr, "last-dtor-rep");
996dbc21cdeSAlex Crichton auto new_func = *instance.get_func(store, new_index);
997dbc21cdeSAlex Crichton auto rep_func = *instance.get_func(store, rep_index);
998dbc21cdeSAlex Crichton auto drop_func = *instance.get_func(store, drop_index);
999dbc21cdeSAlex Crichton auto last_dtor_rep_func = *instance.get_func(store, last_dtor_rep_index);
1000dbc21cdeSAlex Crichton
1001dbc21cdeSAlex Crichton auto arg1 = Val(uint32_t(100));
1002dbc21cdeSAlex Crichton auto res1 = Val(false);
1003dbc21cdeSAlex Crichton new_func.call(store, Span<const Val>(&arg1, 1), Span<Val>(&res1, 1)).unwrap();
1004dbc21cdeSAlex Crichton new_func.post_return(store).unwrap();
1005dbc21cdeSAlex Crichton
1006dbc21cdeSAlex Crichton auto arg2 = Val(uint32_t(101));
1007dbc21cdeSAlex Crichton auto res2 = Val(false);
1008dbc21cdeSAlex Crichton new_func.call(store, Span<const Val>(&arg2, 1), Span<Val>(&res2, 1)).unwrap();
1009dbc21cdeSAlex Crichton new_func.post_return(store).unwrap();
1010dbc21cdeSAlex Crichton
1011dbc21cdeSAlex Crichton {
1012dbc21cdeSAlex Crichton EXPECT_TRUE(res1.is_resource());
1013dbc21cdeSAlex Crichton EXPECT_TRUE(res2.is_resource());
1014dbc21cdeSAlex Crichton const auto &resource1 = res1.get_resource();
1015dbc21cdeSAlex Crichton const auto &resource2 = res2.get_resource();
1016dbc21cdeSAlex Crichton EXPECT_NE(resource1.type(), ResourceType(100));
1017dbc21cdeSAlex Crichton EXPECT_NE(resource2.type(), ResourceType(100));
1018dbc21cdeSAlex Crichton EXPECT_EQ(resource1.type(), resource2.type());
1019dbc21cdeSAlex Crichton EXPECT_FALSE(resource1.to_host(store));
1020dbc21cdeSAlex Crichton EXPECT_FALSE(resource2.to_host(store));
1021dbc21cdeSAlex Crichton EXPECT_TRUE(resource1.owned());
1022dbc21cdeSAlex Crichton EXPECT_TRUE(resource2.owned());
1023dbc21cdeSAlex Crichton arg1 = resource1;
1024dbc21cdeSAlex Crichton arg2 = resource2;
1025dbc21cdeSAlex Crichton }
1026dbc21cdeSAlex Crichton
1027dbc21cdeSAlex Crichton rep_func.call(store, Span<const Val>(&arg1, 1), Span<Val>(&res1, 1)).unwrap();
1028dbc21cdeSAlex Crichton rep_func.post_return(store).unwrap();
1029dbc21cdeSAlex Crichton rep_func.call(store, Span<const Val>(&arg2, 1), Span<Val>(&res2, 1)).unwrap();
1030dbc21cdeSAlex Crichton rep_func.post_return(store).unwrap();
1031dbc21cdeSAlex Crichton
1032dbc21cdeSAlex Crichton EXPECT_TRUE(res1.is_u32());
1033dbc21cdeSAlex Crichton EXPECT_TRUE(res2.is_u32());
1034dbc21cdeSAlex Crichton EXPECT_EQ(res1.get_u32(), 100);
1035dbc21cdeSAlex Crichton EXPECT_EQ(res2.get_u32(), 101);
1036dbc21cdeSAlex Crichton
1037dbc21cdeSAlex Crichton Val last_rep(false);
1038dbc21cdeSAlex Crichton last_dtor_rep_func.call(store, Span<const Val>(), Span<Val>(&last_rep, 1))
1039dbc21cdeSAlex Crichton .unwrap();
1040dbc21cdeSAlex Crichton last_dtor_rep_func.post_return(store).unwrap();
1041dbc21cdeSAlex Crichton EXPECT_EQ(last_rep.get_u32(), 0);
1042dbc21cdeSAlex Crichton
1043dbc21cdeSAlex Crichton drop_func.call(store, Span<const Val>(&arg1, 1), Span<Val>()).unwrap();
1044dbc21cdeSAlex Crichton drop_func.post_return(store).unwrap();
1045dbc21cdeSAlex Crichton
1046dbc21cdeSAlex Crichton last_dtor_rep_func.call(store, Span<const Val>(), Span<Val>(&last_rep, 1))
1047dbc21cdeSAlex Crichton .unwrap();
1048dbc21cdeSAlex Crichton last_dtor_rep_func.post_return(store).unwrap();
1049dbc21cdeSAlex Crichton EXPECT_EQ(last_rep.get_u32(), 100);
1050dbc21cdeSAlex Crichton
1051dbc21cdeSAlex Crichton arg2.get_resource().drop(store).unwrap();
1052dbc21cdeSAlex Crichton
1053dbc21cdeSAlex Crichton last_dtor_rep_func.call(store, Span<const Val>(), Span<Val>(&last_rep, 1))
1054dbc21cdeSAlex Crichton .unwrap();
1055dbc21cdeSAlex Crichton last_dtor_rep_func.post_return(store).unwrap();
1056dbc21cdeSAlex Crichton EXPECT_EQ(last_rep.get_u32(), 101);
1057dbc21cdeSAlex Crichton }
1058dbc21cdeSAlex Crichton
TEST(component,resources)1059dbc21cdeSAlex Crichton TEST(component, resources) {
1060dbc21cdeSAlex Crichton ResourceHost r1(true, 1, 2);
1061dbc21cdeSAlex Crichton EXPECT_TRUE(r1.owned());
1062dbc21cdeSAlex Crichton EXPECT_EQ(r1.rep(), 1);
1063dbc21cdeSAlex Crichton EXPECT_EQ(r1.type(), 2);
1064dbc21cdeSAlex Crichton
1065dbc21cdeSAlex Crichton ResourceHost r2 = r1;
1066dbc21cdeSAlex Crichton EXPECT_TRUE(r1.owned());
1067dbc21cdeSAlex Crichton EXPECT_EQ(r1.rep(), 1);
1068dbc21cdeSAlex Crichton EXPECT_EQ(r1.type(), 2);
1069dbc21cdeSAlex Crichton EXPECT_TRUE(r2.owned());
1070dbc21cdeSAlex Crichton EXPECT_EQ(r2.rep(), 1);
1071dbc21cdeSAlex Crichton EXPECT_EQ(r2.type(), 2);
1072dbc21cdeSAlex Crichton
1073dbc21cdeSAlex Crichton Engine engine;
1074dbc21cdeSAlex Crichton Store store(engine);
1075dbc21cdeSAlex Crichton ResourceAny r3 = r2.to_any(store).unwrap();
1076dbc21cdeSAlex Crichton EXPECT_TRUE(r3.owned());
1077dbc21cdeSAlex Crichton ResourceType t3 = r3.type();
1078dbc21cdeSAlex Crichton EXPECT_EQ(t3, ResourceType(2));
1079dbc21cdeSAlex Crichton
1080dbc21cdeSAlex Crichton ResourceHost r4 = r3.to_host(store).unwrap();
1081dbc21cdeSAlex Crichton EXPECT_TRUE(r4.owned());
1082dbc21cdeSAlex Crichton EXPECT_EQ(r4.rep(), 1);
1083dbc21cdeSAlex Crichton EXPECT_EQ(r4.type(), 2);
1084dbc21cdeSAlex Crichton
1085dbc21cdeSAlex Crichton EXPECT_FALSE(r3.drop(store));
1086dbc21cdeSAlex Crichton EXPECT_TRUE(r4.to_any(store).unwrap().drop(store));
1087dbc21cdeSAlex Crichton
1088dbc21cdeSAlex Crichton Val v = r4.to_any(store).unwrap();
1089dbc21cdeSAlex Crichton EXPECT_TRUE(v.is_resource());
1090dbc21cdeSAlex Crichton const ResourceAny &r5 = v.get_resource();
1091dbc21cdeSAlex Crichton EXPECT_TRUE(r5.owned());
1092dbc21cdeSAlex Crichton EXPECT_EQ(r5.type(), ResourceType(2));
1093dbc21cdeSAlex Crichton }
1094