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