Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/c-api/tests/component/values.cc
1692 views
1
#include "utils.h"
2
3
#include <gtest/gtest.h>
4
#include <wasmtime.h>
5
6
#include <array>
7
#include <format>
8
#include <optional>
9
#include <span>
10
#include <variant>
11
12
static std::string echo_component(std::string_view type, std::string_view func,
13
std::string_view host_params) {
14
return std::format(
15
R"END(
16
(component
17
(type $Foo' {})
18
(import "foo" (type $Foo (eq $Foo')))
19
(import "do" (func $do (param "a" $Foo) (result $Foo)))
20
(core module $libc
21
(memory (export "memory") 1)
22
{}
23
)
24
(core instance $libc (instantiate $libc))
25
(core func $do_lower (canon lower (func $do) (memory $libc "memory") (realloc (func $libc "realloc"))))
26
27
(core module $doer
28
(import "host" "do" (func $do {}))
29
(import "libc" "memory" (memory 1))
30
(import "libc" "realloc" (func $realloc (param i32 i32 i32 i32) (result i32)))
31
32
(func (export "call")
33
{})
34
)
35
(core instance $doer (instantiate $doer
36
(with "host" (instance (export "do" (func $do_lower))))
37
(with "libc" (instance $libc))
38
))
39
40
(func $call
41
(param "a" $Foo)
42
(result $Foo)
43
(canon lift
44
(core func $doer "call")
45
(memory $libc "memory")
46
(realloc (func $libc "realloc")))
47
)
48
49
(export "call" (func $call))
50
)
51
)END",
52
type, REALLOC_AND_FREE, host_params, func);
53
}
54
55
struct Context {
56
wasm_engine_t *engine;
57
wasmtime_store_t *store;
58
wasmtime_context_t *context;
59
wasmtime_component_t *component;
60
wasmtime_component_instance_t instance;
61
wasmtime_component_func_t func;
62
};
63
64
static Context create(std::string_view type, std::string_view body,
65
std::string_view host_params,
66
wasmtime_component_func_callback_t callback) {
67
auto component_text = echo_component(type, body, host_params);
68
const auto engine = wasm_engine_new();
69
EXPECT_NE(engine, nullptr);
70
71
const auto store = wasmtime_store_new(engine, nullptr, nullptr);
72
const auto context = wasmtime_store_context(store);
73
74
wasmtime_component_t *component = nullptr;
75
76
auto err = wasmtime_component_new(
77
engine, reinterpret_cast<const uint8_t *>(component_text.data()),
78
component_text.size(), &component);
79
80
CHECK_ERR(err);
81
82
auto f = wasmtime_component_get_export_index(component, nullptr, "call",
83
strlen("call"));
84
85
EXPECT_NE(f, nullptr);
86
87
const auto linker = wasmtime_component_linker_new(engine);
88
const auto root = wasmtime_component_linker_root(linker);
89
90
wasmtime_component_linker_instance_add_func(root, "do", strlen("do"),
91
callback, nullptr, nullptr);
92
93
wasmtime_component_linker_instance_delete(root);
94
95
wasmtime_component_instance_t instance = {};
96
err = wasmtime_component_linker_instantiate(linker, context, component,
97
&instance);
98
CHECK_ERR(err);
99
100
wasmtime_component_linker_delete(linker);
101
102
wasmtime_component_func_t func = {};
103
const auto found =
104
wasmtime_component_instance_get_func(&instance, context, f, &func);
105
EXPECT_TRUE(found);
106
EXPECT_NE(func.store_id, 0);
107
108
wasmtime_component_export_index_delete(f);
109
110
return Context{
111
.engine = engine,
112
.store = store,
113
.context = context,
114
.component = component,
115
.instance = instance,
116
.func = func,
117
};
118
}
119
120
static void destroy(Context &ctx) {
121
wasmtime_component_delete(ctx.component);
122
wasmtime_store_delete(ctx.store);
123
wasm_engine_delete(ctx.engine);
124
}
125
126
TEST(component, value_record) {
127
static const auto check = [](const wasmtime_component_val_t &val, uint64_t x,
128
uint64_t y) {
129
EXPECT_EQ(val.kind, WASMTIME_COMPONENT_RECORD);
130
131
EXPECT_EQ(val.of.record.size, 2);
132
const auto entries = val.of.record.data;
133
134
EXPECT_EQ((std::string_view{entries[0].name.data, entries[0].name.size}),
135
"x");
136
EXPECT_EQ(entries[0].val.kind, WASMTIME_COMPONENT_U64);
137
EXPECT_EQ(entries[0].val.of.u64, x);
138
139
EXPECT_EQ((std::string_view{entries[1].name.data, entries[1].name.size}),
140
"y");
141
EXPECT_EQ(entries[1].val.kind, WASMTIME_COMPONENT_U64);
142
EXPECT_EQ(entries[1].val.of.u64, y);
143
};
144
145
static const auto make = [](uint64_t x,
146
uint64_t y) -> wasmtime_component_val_t {
147
auto ret = wasmtime_component_val_t{
148
.kind = WASMTIME_COMPONENT_RECORD,
149
};
150
151
wasmtime_component_valrecord_new_uninit(&ret.of.record, 2);
152
153
const auto entries = ret.of.record.data;
154
wasm_name_new_from_string(&entries[0].name, "x");
155
entries[0].val.kind = WASMTIME_COMPONENT_U64;
156
entries[0].val.of.u64 = x;
157
wasm_name_new_from_string(&entries[1].name, "y");
158
entries[1].val.kind = WASMTIME_COMPONENT_U64;
159
entries[1].val.of.u64 = y;
160
161
return ret;
162
};
163
164
auto ctx = create(
165
R"((record (field "x" u64) (field "y" u64)))", R"(
166
(param $x i64)
167
(param $y i64)
168
(result i32)
169
(local $res i32)
170
local.get $x
171
local.get $y
172
(call $realloc
173
(i32.const 0)
174
(i32.const 0)
175
(i32.const 4)
176
(i32.const 16))
177
local.tee $res
178
call $do
179
local.get $res
180
)",
181
"(param i64 i64 i32)",
182
+[](void *, wasmtime_context_t *, const wasmtime_component_val_t *args,
183
size_t args_len, wasmtime_component_val_t *rets,
184
size_t rets_len) -> wasmtime_error_t * {
185
EXPECT_EQ(args_len, 1);
186
check(args[0], 1, 2);
187
188
EXPECT_EQ(rets_len, 1);
189
rets[0] = make(3, 4);
190
191
return nullptr;
192
});
193
194
auto arg = make(1, 2);
195
auto res = wasmtime_component_val_t{};
196
197
auto err =
198
wasmtime_component_func_call(&ctx.func, ctx.context, &arg, 1, &res, 1);
199
CHECK_ERR(err);
200
201
err = wasmtime_component_func_post_return(&ctx.func, ctx.context);
202
CHECK_ERR(err);
203
204
check(res, 3, 4);
205
206
wasmtime_component_val_delete(&arg);
207
wasmtime_component_val_delete(&res);
208
209
destroy(ctx);
210
}
211
212
TEST(component, value_string) {
213
static const auto check = [](const wasmtime_component_val_t &val,
214
std::string_view text) {
215
EXPECT_EQ(val.kind, WASMTIME_COMPONENT_STRING);
216
EXPECT_EQ((std::string_view{val.of.string.data, val.of.string.size}), text);
217
};
218
219
static const auto make =
220
[](std::string_view text) -> wasmtime_component_val_t {
221
auto str = wasm_name_t{};
222
wasm_name_new_from_string(&str, text.data());
223
224
return wasmtime_component_val_t{
225
.kind = WASMTIME_COMPONENT_STRING,
226
.of = {.string = str},
227
};
228
};
229
230
auto ctx = create(
231
R"(string)", R"(
232
(param $x i32)
233
(param $y i32)
234
(result i32)
235
(local $res i32)
236
local.get $x
237
local.get $y
238
(call $realloc
239
(i32.const 0)
240
(i32.const 0)
241
(i32.const 4)
242
(i32.const 8))
243
local.tee $res
244
call $do
245
local.get $res
246
)",
247
"(param i32 i32 i32)",
248
+[](void *, wasmtime_context_t *, const wasmtime_component_val_t *args,
249
size_t args_len, wasmtime_component_val_t *rets,
250
size_t rets_len) -> wasmtime_error_t * {
251
EXPECT_EQ(args_len, 1);
252
check(args[0], "hello from A!");
253
254
EXPECT_EQ(rets_len, 1);
255
rets[0] = make("hello from B!");
256
257
return nullptr;
258
});
259
260
auto arg = make("hello from A!");
261
auto res = wasmtime_component_val_t{};
262
263
auto err =
264
wasmtime_component_func_call(&ctx.func, ctx.context, &arg, 1, &res, 1);
265
CHECK_ERR(err);
266
267
err = wasmtime_component_func_post_return(&ctx.func, ctx.context);
268
CHECK_ERR(err);
269
270
check(res, "hello from B!");
271
272
wasmtime_component_val_delete(&arg);
273
wasmtime_component_val_delete(&res);
274
275
destroy(ctx);
276
}
277
278
TEST(component, value_list) {
279
static const auto check = [](const wasmtime_component_val_t &val,
280
std::vector<uint32_t> data) {
281
EXPECT_EQ(val.kind, WASMTIME_COMPONENT_LIST);
282
auto vals = std::span{val.of.list.data, val.of.list.size};
283
EXPECT_EQ(vals.size(), data.size());
284
for (auto i = 0; i < data.size(); i++) {
285
EXPECT_EQ(vals[i].kind, WASMTIME_COMPONENT_U32);
286
EXPECT_EQ(vals[i].of.u32, data[i]);
287
}
288
};
289
290
static const auto make =
291
[](std::vector<uint32_t> data) -> wasmtime_component_val_t {
292
auto ret = wasmtime_component_val_t{
293
.kind = WASMTIME_COMPONENT_LIST,
294
};
295
296
wasmtime_component_vallist_new_uninit(&ret.of.list, data.size());
297
298
for (auto i = 0; i < data.size(); i++) {
299
ret.of.list.data[i] = wasmtime_component_val_t{
300
.kind = WASMTIME_COMPONENT_U32,
301
.of = {.u32 = data[i]},
302
};
303
}
304
305
return ret;
306
};
307
308
auto ctx = create(
309
R"((list u32))", R"(
310
(param $x i32)
311
(param $y i32)
312
(result i32)
313
(local $res i32)
314
local.get $x
315
local.get $y
316
(call $realloc
317
(i32.const 0)
318
(i32.const 0)
319
(i32.const 4)
320
(i32.const 8))
321
local.tee $res
322
call $do
323
local.get $res
324
)",
325
"(param i32 i32 i32)",
326
+[](void *, wasmtime_context_t *, const wasmtime_component_val_t *args,
327
size_t args_len, wasmtime_component_val_t *rets,
328
size_t rets_len) -> wasmtime_error_t * {
329
EXPECT_EQ(args_len, 1);
330
check(args[0], {1, 2, 3});
331
332
EXPECT_EQ(rets_len, 1);
333
rets[0] = make({4, 5, 6, 7});
334
335
return nullptr;
336
});
337
338
auto arg = make({1, 2, 3});
339
auto res = wasmtime_component_val_t{};
340
341
auto err =
342
wasmtime_component_func_call(&ctx.func, ctx.context, &arg, 1, &res, 1);
343
CHECK_ERR(err);
344
345
err = wasmtime_component_func_post_return(&ctx.func, ctx.context);
346
CHECK_ERR(err);
347
348
check(res, {4, 5, 6, 7});
349
350
wasmtime_component_val_delete(&arg);
351
wasmtime_component_val_delete(&res);
352
353
destroy(ctx);
354
}
355
356
TEST(component, value_tuple) {
357
static const auto check = [](const wasmtime_component_val_t &val,
358
std::vector<uint32_t> data) {
359
EXPECT_EQ(val.kind, WASMTIME_COMPONENT_TUPLE);
360
auto vals = std::span{val.of.tuple.data, val.of.tuple.size};
361
EXPECT_EQ(vals.size(), data.size());
362
for (auto i = 0; i < data.size(); i++) {
363
EXPECT_EQ(vals[i].kind, WASMTIME_COMPONENT_U32);
364
EXPECT_EQ(vals[i].of.u32, data[i]);
365
}
366
};
367
368
static const auto make =
369
[](std::vector<uint32_t> data) -> wasmtime_component_val_t {
370
auto ret = wasmtime_component_val_t{
371
.kind = WASMTIME_COMPONENT_TUPLE,
372
};
373
374
wasmtime_component_valtuple_new_uninit(&ret.of.tuple, data.size());
375
376
for (auto i = 0; i < data.size(); i++) {
377
ret.of.list.data[i] = wasmtime_component_val_t{
378
.kind = WASMTIME_COMPONENT_U32,
379
.of = {.u32 = data[i]},
380
};
381
}
382
383
return ret;
384
};
385
386
auto ctx = create(
387
R"((tuple u32 u32 u32))", R"(
388
(param $x i32)
389
(param $y i32)
390
(param $z i32)
391
(result i32)
392
(local $res i32)
393
local.get $x
394
local.get $y
395
local.get $z
396
(call $realloc
397
(i32.const 0)
398
(i32.const 0)
399
(i32.const 4)
400
(i32.const 12))
401
local.tee $res
402
call $do
403
local.get $res
404
)",
405
"(param i32 i32 i32 i32)",
406
+[](void *, wasmtime_context_t *, const wasmtime_component_val_t *args,
407
size_t args_len, wasmtime_component_val_t *rets,
408
size_t rets_len) -> wasmtime_error_t * {
409
EXPECT_EQ(args_len, 1);
410
check(args[0], {1, 2, 3});
411
412
EXPECT_EQ(rets_len, 1);
413
rets[0] = make({4, 5, 6});
414
415
return nullptr;
416
});
417
418
auto arg = make({1, 2, 3});
419
auto res = wasmtime_component_val_t{};
420
421
auto err =
422
wasmtime_component_func_call(&ctx.func, ctx.context, &arg, 1, &res, 1);
423
CHECK_ERR(err);
424
425
err = wasmtime_component_func_post_return(&ctx.func, ctx.context);
426
CHECK_ERR(err);
427
428
check(res, {4, 5, 6});
429
430
wasmtime_component_val_delete(&arg);
431
wasmtime_component_val_delete(&res);
432
433
destroy(ctx);
434
}
435
436
TEST(component, value_variant) {
437
static const auto check_aa = [](const wasmtime_component_val_t &val,
438
uint32_t value) {
439
EXPECT_EQ(val.kind, WASMTIME_COMPONENT_VARIANT);
440
EXPECT_EQ((std::string_view{val.of.variant.discriminant.data,
441
val.of.variant.discriminant.size}),
442
"aa");
443
444
EXPECT_NE(val.of.variant.val, nullptr);
445
446
EXPECT_EQ(val.of.variant.val->kind, WASMTIME_COMPONENT_U32);
447
EXPECT_EQ(val.of.variant.val->of.u32, value);
448
};
449
450
static const auto check_bb = [](const wasmtime_component_val_t &val,
451
std::string_view value) {
452
EXPECT_EQ(val.kind, WASMTIME_COMPONENT_VARIANT);
453
EXPECT_EQ((std::string_view{val.of.variant.discriminant.data,
454
val.of.variant.discriminant.size}),
455
"bb");
456
457
EXPECT_NE(val.of.variant.val, nullptr);
458
459
EXPECT_EQ(val.of.variant.val->kind, WASMTIME_COMPONENT_STRING);
460
EXPECT_EQ((std::string_view{val.of.variant.val->of.string.data,
461
val.of.variant.val->of.string.size}),
462
value);
463
};
464
465
static const auto make_aa = [](uint32_t value) -> wasmtime_component_val_t {
466
auto ret = wasmtime_component_val_t{
467
.kind = WASMTIME_COMPONENT_VARIANT,
468
};
469
470
wasm_name_new_from_string(&ret.of.variant.discriminant, "aa");
471
472
ret.of.variant.val = wasmtime_component_val_new();
473
ret.of.variant.val->kind = WASMTIME_COMPONENT_U32;
474
ret.of.variant.val->of.u32 = value;
475
476
return ret;
477
};
478
479
static const auto make_bb =
480
[](std::string_view value) -> wasmtime_component_val_t {
481
auto ret = wasmtime_component_val_t{
482
.kind = WASMTIME_COMPONENT_VARIANT,
483
};
484
485
wasm_name_new_from_string(&ret.of.variant.discriminant, "bb");
486
487
ret.of.variant.val = wasmtime_component_val_new();
488
ret.of.variant.val->kind = WASMTIME_COMPONENT_STRING;
489
wasm_name_new(&ret.of.variant.val->of.string, value.size(), value.data());
490
491
return ret;
492
};
493
494
auto ctx = create(
495
R"(
496
(variant
497
(case "aa" u32)
498
(case "bb" string)
499
)
500
)",
501
R"(
502
(param $x i32)
503
(param $y i32)
504
(param $z i32)
505
(result i32)
506
(local $res i32)
507
local.get $x
508
local.get $y
509
local.get $z
510
(call $realloc
511
(i32.const 0)
512
(i32.const 0)
513
(i32.const 4)
514
(i32.const 12))
515
local.tee $res
516
call $do
517
local.get $res
518
)",
519
"(param i32 i32 i32 i32)",
520
+[](void *, wasmtime_context_t *, const wasmtime_component_val_t *args,
521
size_t args_len, wasmtime_component_val_t *rets,
522
size_t rets_len) -> wasmtime_error_t * {
523
EXPECT_EQ(args_len, 1);
524
check_aa(args[0], 123);
525
526
EXPECT_EQ(rets_len, 1);
527
rets[0] = make_bb("textt");
528
529
return nullptr;
530
});
531
532
auto arg = make_aa(123);
533
auto res = wasmtime_component_val_t{};
534
535
auto err =
536
wasmtime_component_func_call(&ctx.func, ctx.context, &arg, 1, &res, 1);
537
CHECK_ERR(err);
538
539
err = wasmtime_component_func_post_return(&ctx.func, ctx.context);
540
CHECK_ERR(err);
541
542
check_bb(res, "textt");
543
544
wasmtime_component_val_delete(&arg);
545
wasmtime_component_val_delete(&res);
546
547
destroy(ctx);
548
}
549
550
TEST(component, value_enum) {
551
static const auto check = [](const wasmtime_component_val_t &val,
552
std::string_view text) {
553
EXPECT_EQ(val.kind, WASMTIME_COMPONENT_ENUM);
554
EXPECT_EQ(
555
(std::string_view{val.of.enumeration.data, val.of.enumeration.size}),
556
text);
557
};
558
559
static const auto make =
560
[](std::string_view text) -> wasmtime_component_val_t {
561
auto ret = wasmtime_component_val_t{
562
.kind = WASMTIME_COMPONENT_ENUM,
563
};
564
565
wasm_name_new(&ret.of.enumeration, text.size(), text.data());
566
567
return ret;
568
};
569
570
auto ctx = create(
571
R"((enum "aa" "bb"))", R"(
572
(param $x i32)
573
(result i32)
574
local.get $x
575
call $do
576
)",
577
"(param i32) (result i32)",
578
+[](void *, wasmtime_context_t *, const wasmtime_component_val_t *args,
579
size_t args_len, wasmtime_component_val_t *rets,
580
size_t rets_len) -> wasmtime_error_t * {
581
EXPECT_EQ(args_len, 1);
582
check(args[0], "aa");
583
584
EXPECT_EQ(rets_len, 1);
585
rets[0] = make("bb");
586
587
return nullptr;
588
});
589
590
auto arg = make("aa");
591
auto res = wasmtime_component_val_t{};
592
593
auto err =
594
wasmtime_component_func_call(&ctx.func, ctx.context, &arg, 1, &res, 1);
595
CHECK_ERR(err);
596
597
err = wasmtime_component_func_post_return(&ctx.func, ctx.context);
598
CHECK_ERR(err);
599
600
check(res, "bb");
601
602
wasmtime_component_val_delete(&arg);
603
wasmtime_component_val_delete(&res);
604
605
destroy(ctx);
606
}
607
608
TEST(component, value_option) {
609
static const auto check = [](const wasmtime_component_val_t &val,
610
std::optional<uint32_t> value) {
611
EXPECT_EQ(val.kind, WASMTIME_COMPONENT_OPTION);
612
613
if (value.has_value()) {
614
EXPECT_NE(val.of.option, nullptr);
615
EXPECT_EQ(val.of.option->kind, WASMTIME_COMPONENT_U32);
616
EXPECT_EQ(val.of.option->of.u32, *value);
617
} else {
618
EXPECT_EQ(val.of.option, nullptr);
619
}
620
};
621
622
static const auto make =
623
[](std::optional<uint32_t> value) -> wasmtime_component_val_t {
624
auto ret = wasmtime_component_val_t{
625
.kind = WASMTIME_COMPONENT_OPTION,
626
.of = {.option = nullptr},
627
};
628
629
if (value.has_value()) {
630
ret.of.option = wasmtime_component_val_new();
631
*ret.of.option = wasmtime_component_val_t{
632
.kind = WASMTIME_COMPONENT_U32,
633
.of = {.u32 = *value},
634
};
635
}
636
637
return ret;
638
};
639
640
auto ctx = create(
641
R"((option u32))", R"(
642
(param $x i32)
643
(param $y i32)
644
(result i32)
645
(local $res i32)
646
local.get $x
647
local.get $y
648
(call $realloc
649
(i32.const 0)
650
(i32.const 0)
651
(i32.const 4)
652
(i32.const 8))
653
local.tee $res
654
call $do
655
local.get $res
656
)",
657
"(param i32 i32 i32)",
658
+[](void *, wasmtime_context_t *, const wasmtime_component_val_t *args,
659
size_t args_len, wasmtime_component_val_t *rets,
660
size_t rets_len) -> wasmtime_error_t * {
661
EXPECT_EQ(args_len, 1);
662
check(args[0], 123);
663
664
EXPECT_EQ(rets_len, 1);
665
rets[0] = make({});
666
667
return nullptr;
668
});
669
670
auto arg = make(123);
671
auto res = wasmtime_component_val_t{};
672
673
auto err =
674
wasmtime_component_func_call(&ctx.func, ctx.context, &arg, 1, &res, 1);
675
CHECK_ERR(err);
676
677
err = wasmtime_component_func_post_return(&ctx.func, ctx.context);
678
CHECK_ERR(err);
679
680
check(res, {});
681
682
wasmtime_component_val_delete(&arg);
683
wasmtime_component_val_delete(&res);
684
685
destroy(ctx);
686
}
687
688
TEST(component, value_result) {
689
static const auto check = [](const wasmtime_component_val_t &val,
690
bool expected_is_ok, uint32_t expected_value) {
691
EXPECT_EQ(val.kind, WASMTIME_COMPONENT_RESULT);
692
693
EXPECT_EQ(val.of.result.is_ok, expected_is_ok);
694
EXPECT_NE(val.of.result.val, nullptr);
695
696
EXPECT_EQ(val.of.result.val->kind, WASMTIME_COMPONENT_U32);
697
EXPECT_EQ(val.of.result.val->of.u32, expected_value);
698
};
699
700
static const auto make = [](bool is_ok,
701
uint32_t value) -> wasmtime_component_val_t {
702
auto ret = wasmtime_component_val_t{
703
.kind = WASMTIME_COMPONENT_RESULT,
704
};
705
706
const auto inner = wasmtime_component_val_new();
707
inner->kind = WASMTIME_COMPONENT_U32;
708
inner->of.u32 = value;
709
710
ret.of.result = {
711
.is_ok = is_ok,
712
.val = inner,
713
};
714
715
return ret;
716
};
717
718
auto ctx = create(
719
R"((result u32 (error u32)))", R"(
720
(param $x i32)
721
(param $y i32)
722
(result i32)
723
(local $res i32)
724
local.get $x
725
local.get $y
726
(call $realloc
727
(i32.const 0)
728
(i32.const 0)
729
(i32.const 4)
730
(i32.const 8))
731
local.tee $res
732
call $do
733
local.get $res
734
)",
735
"(param i32 i32 i32)",
736
+[](void *, wasmtime_context_t *, const wasmtime_component_val_t *args,
737
size_t args_len, wasmtime_component_val_t *rets,
738
size_t rets_len) -> wasmtime_error_t * {
739
EXPECT_EQ(args_len, 1);
740
check(args[0], true, 123);
741
742
EXPECT_EQ(rets_len, 1);
743
rets[0] = make(false, 456);
744
745
return nullptr;
746
});
747
748
auto arg = make(true, 123);
749
auto res = wasmtime_component_val_t{};
750
751
auto err =
752
wasmtime_component_func_call(&ctx.func, ctx.context, &arg, 1, &res, 1);
753
CHECK_ERR(err);
754
755
err = wasmtime_component_func_post_return(&ctx.func, ctx.context);
756
CHECK_ERR(err);
757
758
check(res, false, 456);
759
760
wasmtime_component_val_delete(&arg);
761
wasmtime_component_val_delete(&res);
762
763
destroy(ctx);
764
}
765
766
TEST(component, value_flags) {
767
static const auto check = [](const wasmtime_component_val_t &val,
768
std::vector<std::string> data) {
769
EXPECT_EQ(val.kind, WASMTIME_COMPONENT_FLAGS);
770
auto flags = std::span{val.of.flags.data, val.of.flags.size};
771
EXPECT_EQ(flags.size(), data.size());
772
for (auto i = 0; i < data.size(); i++) {
773
EXPECT_EQ((std::string_view{flags[i].data, flags[i].size}), data[i]);
774
}
775
};
776
777
static const auto make =
778
[](std::vector<std::string> data) -> wasmtime_component_val_t {
779
auto ret = wasmtime_component_val_t{
780
.kind = WASMTIME_COMPONENT_FLAGS,
781
};
782
783
wasmtime_component_valflags_new_uninit(&ret.of.flags, data.size());
784
785
for (auto i = 0; i < data.size(); i++) {
786
wasm_name_new(&ret.of.flags.data[i], data[i].size(), data[i].data());
787
}
788
789
return ret;
790
};
791
792
auto ctx = create(
793
R"((flags "aa" "bb"))", R"(
794
(param $x i32)
795
(result i32)
796
local.get $x
797
call $do
798
)",
799
"(param i32) (result i32)",
800
+[](void *, wasmtime_context_t *, const wasmtime_component_val_t *args,
801
size_t args_len, wasmtime_component_val_t *rets,
802
size_t rets_len) -> wasmtime_error_t * {
803
EXPECT_EQ(args_len, 1);
804
check(args[0], {"aa"});
805
806
EXPECT_EQ(rets_len, 1);
807
rets[0] = make({"aa", "bb"});
808
809
return nullptr;
810
});
811
812
auto arg = make({"aa"});
813
auto res = wasmtime_component_val_t{};
814
815
auto err =
816
wasmtime_component_func_call(&ctx.func, ctx.context, &arg, 1, &res, 1);
817
CHECK_ERR(err);
818
819
err = wasmtime_component_func_post_return(&ctx.func, ctx.context);
820
CHECK_ERR(err);
821
822
check(res, {"aa", "bb"});
823
824
wasmtime_component_val_delete(&arg);
825
wasmtime_component_val_delete(&res);
826
827
destroy(ctx);
828
}
829
830
TEST(component, value_list_inner) {
831
{
832
auto x = wasmtime_component_val_t{
833
.kind = WASMTIME_COMPONENT_LIST,
834
};
835
wasmtime_component_vallist_new_empty(&x.of.list);
836
EXPECT_EQ(x.of.list.data, nullptr);
837
EXPECT_EQ(x.of.list.size, 0);
838
839
wasmtime_component_vallist_new_uninit(&x.of.list, 1);
840
EXPECT_NE(x.of.list.data, nullptr);
841
EXPECT_EQ(x.of.list.size, 1);
842
843
wasmtime_component_vallist_delete(&x.of.list);
844
845
auto items = std::array{
846
wasmtime_component_val_t{
847
.kind = WASMTIME_COMPONENT_U32,
848
.of = {.u32 = 123},
849
},
850
};
851
852
wasmtime_component_vallist_new(&x.of.list, items.size(), items.data());
853
EXPECT_NE(x.of.list.data, nullptr);
854
EXPECT_EQ(x.of.list.size, 1);
855
856
EXPECT_EQ(x.of.list.data[0].kind, WASMTIME_COMPONENT_U32);
857
EXPECT_EQ(x.of.list.data[0].of.u32, 123);
858
859
auto clone = wasmtime_component_val_t{
860
.kind = WASMTIME_COMPONENT_LIST,
861
};
862
863
wasmtime_component_vallist_copy(&clone.of.list, &x.of.list);
864
wasmtime_component_vallist_delete(&x.of.list);
865
866
EXPECT_NE(clone.of.list.data, nullptr);
867
EXPECT_EQ(clone.of.list.size, 1);
868
869
EXPECT_EQ(clone.of.list.data[0].kind, WASMTIME_COMPONENT_U32);
870
EXPECT_EQ(clone.of.list.data[0].of.u32, 123);
871
872
wasmtime_component_vallist_delete(&clone.of.list);
873
}
874
}
875
876