Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/executor/host/tests/run.rs
Line
Count
Source (jump to first uncovered line)
1
// Smoldot
2
// Copyright (C) 2023  Pierre Krieger
3
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5
// This program is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
15
// You should have received a copy of the GNU General Public License
16
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18
use super::super::{
19
    vm, vm::ExecHint, Config, Error, HeapPages, HostVm, HostVmPrototype, NewErr, StartErr,
20
    StorageProofSizeBehavior,
21
};
22
use super::with_core_version_custom_sections;
23
24
#[test]
25
1
fn function_to_run_doesnt_exist() {
26
1
    let module_bytes = with_core_version_custom_sections(
27
1
        wat::parse_str(
28
1
            r#"
29
1
    (module
30
1
        (import "env" "memory" (memory 0))
31
1
        (global (export "__heap_base") i32 (i32.const 0))
32
1
    )
33
1
    "#,
34
1
        )
35
1
        .unwrap(),
36
1
    );
37
38
3
    for 
exec_hint2
in ExecHint::available_engines() {
39
2
        let host_vm = HostVmPrototype::new(Config {
40
2
            allow_unresolved_imports: false,
41
2
            exec_hint,
42
2
            heap_pages: HeapPages::new(1024),
43
2
            module: &module_bytes,
44
2
        })
45
2
        .unwrap();
46
2
47
2
        match host_vm.run_no_param(
48
2
            "functiondoesntexist",
49
2
            StorageProofSizeBehavior::proof_recording_disabled(),
50
2
        ) {
51
2
            Err((StartErr::VirtualMachine(vm::StartErr::FunctionNotFound), _)) => {}
52
0
            _ => unreachable!(),
53
        }
54
    }
55
1
}
56
57
#[test]
58
1
fn function_to_run_invalid_params() {
59
1
    let module_bytes = with_core_version_custom_sections(
60
1
        wat::parse_str(
61
1
            r#"
62
1
    (module
63
1
        (import "env" "memory" (memory 0))
64
1
        (global (export "__heap_base") i32 (i32.const 0))
65
1
        (func (export "hello") (param i32) (result i32) i32.const 0)
66
1
    )
67
1
    "#,
68
1
        )
69
1
        .unwrap(),
70
1
    );
71
72
3
    for 
exec_hint2
in ExecHint::available_engines() {
73
2
        let host_vm = HostVmPrototype::new(Config {
74
2
            allow_unresolved_imports: false,
75
2
            exec_hint,
76
2
            heap_pages: HeapPages::new(1024),
77
2
            module: &module_bytes,
78
2
        })
79
2
        .unwrap();
80
2
81
2
        match host_vm.run_no_param(
82
2
            "hello",
83
2
            StorageProofSizeBehavior::proof_recording_disabled(),
84
2
        ) {
85
2
            Err((StartErr::VirtualMachine(vm::StartErr::InvalidParameters), _)) => {}
86
0
            _ => unreachable!(),
87
        }
88
    }
89
1
}
90
91
#[test]
92
1
fn input_provided_correctly() {
93
1
    /* Source code:
94
1
95
1
        #[no_mangle]
96
1
        extern "C" fn test(_param_ptr: i32, _param_sz: i32) -> i64 {
97
1
            let inparam: &[u8] = unsafe {
98
1
                core::slice::from_raw_parts(
99
1
                    u32::from_ne_bytes(_param_ptr.to_ne_bytes()) as usize as *const u8,
100
1
                    u32::from_ne_bytes(_param_sz.to_ne_bytes()) as usize,
101
1
                )
102
1
            };
103
1
104
1
            if inparam
105
1
                != b"hello world"
106
1
            {
107
1
                core::arch::wasm32::unreachable()
108
1
            }
109
1
110
1
            0
111
1
        }
112
1
    */
113
1
    let module_bytes = with_core_version_custom_sections(
114
1
        wat::parse_str(
115
1
            r#"
116
1
    (module
117
1
        (type (;0;) (func (param i32 i32) (result i32)))
118
1
        (type (;1;) (func (param i32 i32) (result i64)))
119
1
        (type (;2;) (func (param i32 i32 i32) (result i32)))
120
1
        (func (;0;) (type 0) (param i32 i32) (result i32)
121
1
          local.get 0
122
1
          local.get 1
123
1
          i32.const 11
124
1
          call 3
125
1
          i32.const 0
126
1
          i32.ne)
127
1
        (func (;1;) (type 1) (param i32 i32) (result i64)
128
1
          block  ;; label = @1
129
1
            local.get 1
130
1
            i32.const 11
131
1
            i32.ne
132
1
            br_if 0 (;@1;)
133
1
            local.get 0
134
1
            i32.const 1048576
135
1
            call 0
136
1
            br_if 0 (;@1;)
137
1
            i64.const 0
138
1
            return
139
1
          end
140
1
          unreachable
141
1
          unreachable)
142
1
        (func (;2;) (type 2) (param i32 i32 i32) (result i32)
143
1
          (local i32 i32 i32)
144
1
          i32.const 0
145
1
          local.set 3
146
1
          block  ;; label = @1
147
1
            local.get 2
148
1
            i32.eqz
149
1
            br_if 0 (;@1;)
150
1
            block  ;; label = @2
151
1
              loop  ;; label = @3
152
1
                local.get 0
153
1
                i32.load8_u
154
1
                local.tee 4
155
1
                local.get 1
156
1
                i32.load8_u
157
1
                local.tee 5
158
1
                i32.ne
159
1
                br_if 1 (;@2;)
160
1
                local.get 0
161
1
                i32.const 1
162
1
                i32.add
163
1
                local.set 0
164
1
                local.get 1
165
1
                i32.const 1
166
1
                i32.add
167
1
                local.set 1
168
1
                local.get 2
169
1
                i32.const -1
170
1
                i32.add
171
1
                local.tee 2
172
1
                i32.eqz
173
1
                br_if 2 (;@1;)
174
1
                br 0 (;@3;)
175
1
              end
176
1
            end
177
1
            local.get 4
178
1
            local.get 5
179
1
            i32.sub
180
1
            local.set 3
181
1
          end
182
1
          local.get 3)
183
1
        (func (;3;) (type 2) (param i32 i32 i32) (result i32)
184
1
          local.get 0
185
1
          local.get 1
186
1
          local.get 2
187
1
          call 2)
188
1
        (table (;0;) 1 1 funcref)
189
1
        (memory (;0;) 17)
190
1
        (global (;0;) (mut i32) (i32.const 1048576))
191
1
        (global (;1;) i32 (i32.const 1048587))
192
1
        (global (;2;) i32 (i32.const 1048592))
193
1
        (export "memory" (memory 0))
194
1
        (export "test" (func 1))
195
1
        (export "__data_end" (global 1))
196
1
        (export "__heap_base" (global 2))
197
1
        (data (;0;) (i32.const 1048576) "hello world")
198
1
    )
199
1
    "#,
200
1
        )
201
1
        .unwrap(),
202
1
    );
203
204
3
    for 
exec_hint2
in ExecHint::available_engines() {
205
2
        let proto = HostVmPrototype::new(Config {
206
2
            allow_unresolved_imports: false,
207
2
            exec_hint,
208
2
            heap_pages: HeapPages::new(1024),
209
2
            module: &module_bytes,
210
2
        })
211
2
        .unwrap();
212
2
213
2
        let mut vm = HostVm::from(
214
2
            proto
215
2
                .run(
216
2
                    "test",
217
2
                    StorageProofSizeBehavior::proof_recording_disabled(),
218
2
                    b"hello world",
219
2
                )
220
2
                .unwrap(),
221
2
        );
222
4
        loop {
223
4
            match vm {
224
2
                HostVm::ReadyToRun(r) => vm = r.run(),
225
2
                HostVm::Finished(v) => {
226
2
                    assert_eq!(v.value().as_ref(), b"");
227
2
                    break;
228
                }
229
0
                _ => unreachable!(),
230
            }
231
        }
232
    }
233
234
3
    for 
exec_hint2
in ExecHint::available_engines() {
235
2
        let proto = HostVmPrototype::new(Config {
236
2
            allow_unresolved_imports: false,
237
2
            exec_hint,
238
2
            heap_pages: HeapPages::new(1024),
239
2
            module: &module_bytes,
240
2
        })
241
2
        .unwrap();
242
2
243
2
        let mut vm = HostVm::from(
244
2
            proto
245
2
                .run_vectored(
246
2
                    "test",
247
2
                    StorageProofSizeBehavior::proof_recording_disabled(),
248
2
                    [&b"hello "[..], &b"world"[..]].into_iter(),
249
2
                )
250
2
                .unwrap(),
251
2
        );
252
253
4
        loop {
254
4
            match vm {
255
2
                HostVm::ReadyToRun(r) => vm = r.run(),
256
2
                HostVm::Finished(v) => {
257
2
                    assert_eq!(v.value().as_ref(), b"");
258
2
                    break;
259
                }
260
0
                _ => unreachable!(),
261
            }
262
        }
263
    }
264
265
3
    for 
exec_hint2
in ExecHint::available_engines() {
266
2
        let proto = HostVmPrototype::new(Config {
267
2
            allow_unresolved_imports: false,
268
2
            exec_hint,
269
2
            heap_pages: HeapPages::new(1024),
270
2
            module: &module_bytes,
271
2
        })
272
2
        .unwrap();
273
2
274
2
        let mut vm = HostVm::from(
275
2
            proto
276
2
                .run(
277
2
                    "test",
278
2
                    StorageProofSizeBehavior::proof_recording_disabled(),
279
2
                    b"unexpected input",
280
2
                )
281
2
                .unwrap(),
282
2
        );
283
        loop {
284
2
            match vm {
285
2
                HostVm::ReadyToRun(r) => vm = r.run(),
286
                HostVm::Error {
287
                    error: Error::Trap(_),
288
                    ..
289
                } => {
290
2
                    break;
291
                }
292
0
                _ => unreachable!(),
293
            }
294
        }
295
    }
296
1
}
297
298
#[test]
299
1
fn large_input_provided_correctly() {
300
1
    /* Source code:
301
1
302
1
        #[no_mangle]
303
1
        extern "C" fn test(_param_ptr: i32, _param_sz: i32) -> i64 {
304
1
            let inparam: &[u8] = unsafe {
305
1
                core::slice::from_raw_parts(
306
1
                    u32::from_ne_bytes(_param_ptr.to_ne_bytes()) as usize as *const u8,
307
1
                    u32::from_ne_bytes(_param_sz.to_ne_bytes()) as usize,
308
1
                )
309
1
            };
310
1
311
1
            if inparam.len() != 395718 {
312
1
                core::arch::wasm32::unreachable()
313
1
            }
314
1
315
1
            for byte in inparam {
316
1
                if *byte != 0x7a {
317
1
                    core::arch::wasm32::unreachable()
318
1
                }
319
1
            }
320
1
321
1
            0
322
1
        }
323
1
    */
324
1
    let module_bytes = with_core_version_custom_sections(
325
1
        wat::parse_str(
326
1
            r#"(module
327
1
                (type (;0;) (func (param i32 i32) (result i64)))
328
1
                (func (;0;) (type 0) (param i32 i32) (result i64)
329
1
                  (local i32)
330
1
                  block  ;; label = @1
331
1
                    block  ;; label = @2
332
1
                      local.get 1
333
1
                      i32.const 395718
334
1
                      i32.ne
335
1
                      br_if 0 (;@2;)
336
1
                      i32.const 0
337
1
                      local.set 1
338
1
                      loop  ;; label = @3
339
1
                        local.get 1
340
1
                        i32.const 395718
341
1
                        i32.eq
342
1
                        br_if 2 (;@1;)
343
1
                        local.get 0
344
1
                        local.get 1
345
1
                        i32.add
346
1
                        local.set 2
347
1
                        local.get 1
348
1
                        i32.const 1
349
1
                        i32.add
350
1
                        local.set 1
351
1
                        local.get 2
352
1
                        i32.load8_u
353
1
                        i32.const 122
354
1
                        i32.eq
355
1
                        br_if 0 (;@3;)
356
1
                      end
357
1
                    end
358
1
                    unreachable
359
1
                    unreachable
360
1
                  end
361
1
                  i64.const 0)
362
1
                (table (;0;) 1 1 funcref)
363
1
                (memory (;0;) 16)
364
1
                (global (;0;) (mut i32) (i32.const 1048576))
365
1
                (global (;1;) i32 (i32.const 1048576))
366
1
                (global (;2;) i32 (i32.const 1048576))
367
1
                (export "memory" (memory 0))
368
1
                (export "test" (func 0))
369
1
                (export "__data_end" (global 1))
370
1
                (export "__heap_base" (global 2))
371
1
            )
372
1
    "#,
373
1
        )
374
1
        .unwrap(),
375
1
    );
376
1
377
395k
    let input_data = (0..395718).map(|_| 0x7a
).collect::<Vec<_>>()1
;
378
379
3
    for 
exec_hint2
in ExecHint::available_engines() {
380
2
        let proto = HostVmPrototype::new(Config {
381
2
            allow_unresolved_imports: false,
382
2
            exec_hint,
383
2
            heap_pages: HeapPages::new(1024),
384
2
            module: &module_bytes,
385
2
        })
386
2
        .unwrap();
387
2
388
2
        let mut vm = HostVm::from(
389
2
            proto
390
2
                .run(
391
2
                    "test",
392
2
                    StorageProofSizeBehavior::proof_recording_disabled(),
393
2
                    &input_data,
394
2
                )
395
2
                .unwrap(),
396
2
        );
397
4
        loop {
398
4
            match vm {
399
2
                HostVm::ReadyToRun(r) => vm = r.run(),
400
2
                HostVm::Finished(v) => {
401
2
                    assert_eq!(v.value().as_ref(), b"");
402
2
                    break;
403
                }
404
0
                _ => unreachable!(),
405
            }
406
        }
407
    }
408
1
}
409
410
#[test]
411
1
fn return_value_works() {
412
1
    /* Source code:
413
1
414
1
        static OUT: &[u8] = b"hello world";
415
1
416
1
        #[no_mangle]
417
1
        extern "C" fn test(_: i32, _: i32) -> i64 {
418
1
            let ptr = OUT.as_ptr() as usize as u32;
419
1
            let sz = OUT.len() as u32;
420
1
421
1
            i64::from_ne_bytes((u64::from(sz) << 32 | u64::from(ptr)).to_ne_bytes())
422
1
        }
423
1
    */
424
1
    let module_bytes = with_core_version_custom_sections(
425
1
        wat::parse_str(
426
1
            r#"
427
1
    (module
428
1
        (type (;0;) (func (param i32 i32) (result i64)))
429
1
        (func (;0;) (type 0) (param i32 i32) (result i64)
430
1
            i32.const 1048576
431
1
            i64.extend_i32_u
432
1
            i64.const 47244640256
433
1
            i64.or)
434
1
        (table (;0;) 1 1 funcref)
435
1
        (memory (;0;) 17)
436
1
        (global (;0;) (mut i32) (i32.const 1048576))
437
1
        (global (;1;) i32 (i32.const 1048587))
438
1
        (global (;2;) i32 (i32.const 1048592))
439
1
        (export "memory" (memory 0))
440
1
        (export "test" (func 0))
441
1
        (export "__data_end" (global 1))
442
1
        (export "__heap_base" (global 2))
443
1
        (data (;0;) (i32.const 1048576) "hello world")
444
1
    )
445
1
    "#,
446
1
        )
447
1
        .unwrap(),
448
1
    );
449
450
3
    for 
exec_hint2
in ExecHint::available_engines() {
451
2
        let proto = HostVmPrototype::new(Config {
452
2
            allow_unresolved_imports: false,
453
2
            exec_hint,
454
2
            heap_pages: HeapPages::new(1024),
455
2
            module: &module_bytes,
456
2
        })
457
2
        .unwrap();
458
2
459
2
        let mut vm = HostVm::from(
460
2
            proto
461
2
                .run(
462
2
                    "test",
463
2
                    StorageProofSizeBehavior::proof_recording_disabled(),
464
2
                    &[],
465
2
                )
466
2
                .unwrap(),
467
2
        );
468
4
        loop {
469
4
            match vm {
470
2
                HostVm::ReadyToRun(r) => vm = r.run(),
471
2
                HostVm::Finished(out) => {
472
2
                    assert_eq!(out.value().as_ref(), b"hello world");
473
2
                    break;
474
                }
475
0
                _ => unreachable!(),
476
            }
477
        }
478
    }
479
1
}
480
481
#[test]
482
1
fn bad_return_value() {
483
1
    /* Source code:
484
1
485
1
        #[no_mangle]
486
1
        extern "C" fn test(_: i32, _: i32) -> i32 {
487
1
            0
488
1
        }
489
1
    */
490
1
    let module_bytes = with_core_version_custom_sections(
491
1
        wat::parse_str(
492
1
            r#"
493
1
    (module
494
1
        (type (;0;) (func (param i32 i32) (result i32)))
495
1
        (func (;0;) (type 0) (param i32 i32) (result i32)
496
1
            i32.const 0)
497
1
        (table (;0;) 1 1 funcref)
498
1
        (memory (;0;) 16)
499
1
        (global (;0;) (mut i32) (i32.const 1048576))
500
1
        (global (;1;) i32 (i32.const 1048576))
501
1
        (global (;2;) i32 (i32.const 1048576))
502
1
        (export "memory" (memory 0))
503
1
        (export "test" (func 0))
504
1
        (export "__data_end" (global 1))
505
1
        (export "__heap_base" (global 2))
506
1
    )
507
1
    "#,
508
1
        )
509
1
        .unwrap(),
510
1
    );
511
512
3
    for 
exec_hint2
in ExecHint::available_engines() {
513
2
        let proto = HostVmPrototype::new(Config {
514
2
            allow_unresolved_imports: false,
515
2
            exec_hint,
516
2
            heap_pages: HeapPages::new(1024),
517
2
            module: &module_bytes,
518
2
        })
519
2
        .unwrap();
520
2
521
2
        let mut vm = HostVm::from(
522
2
            proto
523
2
                .run(
524
2
                    "test",
525
2
                    StorageProofSizeBehavior::proof_recording_disabled(),
526
2
                    &[],
527
2
                )
528
2
                .unwrap(),
529
2
        );
530
        loop {
531
2
            match vm {
532
2
                HostVm::ReadyToRun(r) => vm = r.run(),
533
                HostVm::Error {
534
                    error: Error::BadReturnValue { .. },
535
                    ..
536
                } => {
537
2
                    break;
538
                }
539
0
                _ => unreachable!(),
540
            }
541
        }
542
    }
543
1
}
544
545
#[test]
546
1
fn returned_ptr_out_of_range() {
547
1
    /* Source code:
548
1
549
1
        #[no_mangle]
550
1
        extern "C" fn test(_: i32, _: i32) -> i64 {
551
1
            let ptr = 0xffff_fff0usize as u32;
552
1
            let sz = 5 as u32;
553
1
554
1
            i64::from_ne_bytes((u64::from(sz) << 32 | u64::from(ptr)).to_ne_bytes())
555
1
        }
556
1
    */
557
1
    let module_bytes = with_core_version_custom_sections(
558
1
        wat::parse_str(
559
1
            r#"
560
1
    (module
561
1
        (type (;0;) (func (param i32 i32) (result i64)))
562
1
        (func (;0;) (type 0) (param i32 i32) (result i64)
563
1
            i64.const 25769803760)
564
1
        (table (;0;) 1 1 funcref)
565
1
        (memory (;0;) 16)
566
1
        (global (;0;) (mut i32) (i32.const 1048576))
567
1
        (global (;1;) i32 (i32.const 1048576))
568
1
        (global (;2;) i32 (i32.const 1048576))
569
1
        (export "memory" (memory 0))
570
1
        (export "test" (func 0))
571
1
        (export "__data_end" (global 1))
572
1
        (export "__heap_base" (global 2))
573
1
    )
574
1
    "#,
575
1
        )
576
1
        .unwrap(),
577
1
    );
578
579
3
    for 
exec_hint2
in ExecHint::available_engines() {
580
2
        let proto = HostVmPrototype::new(Config {
581
2
            allow_unresolved_imports: false,
582
2
            exec_hint,
583
2
            heap_pages: HeapPages::new(1024),
584
2
            module: &module_bytes,
585
2
        })
586
2
        .unwrap();
587
2
588
2
        let mut vm = HostVm::from(
589
2
            proto
590
2
                .run(
591
2
                    "test",
592
2
                    StorageProofSizeBehavior::proof_recording_disabled(),
593
2
                    &[],
594
2
                )
595
2
                .unwrap(),
596
2
        );
597
        loop {
598
2
            match vm {
599
2
                HostVm::ReadyToRun(r) => vm = r.run(),
600
                HostVm::Error {
601
                    error: Error::ReturnedPtrOutOfRange { .. },
602
                    ..
603
                } => {
604
2
                    break;
605
                }
606
0
                _ => unreachable!(),
607
            }
608
        }
609
    }
610
1
}
611
612
#[test]
613
1
fn returned_size_out_of_range() {
614
1
    /* Source code:
615
1
616
1
        #[no_mangle]
617
1
        extern "C" fn test(_: i32, _: i32) -> i64 {
618
1
            let ptr = 5 as u32;
619
1
            let sz = 0xffff_fff0usize as u32;
620
1
621
1
            i64::from_ne_bytes((u64::from(sz) << 32 | u64::from(ptr)).to_ne_bytes())
622
1
        }
623
1
    */
624
1
    let module_bytes = with_core_version_custom_sections(
625
1
        wat::parse_str(
626
1
            r#"
627
1
    (module
628
1
        (type (;0;) (func (param i32 i32) (result i64)))
629
1
        (func (;0;) (type 0) (param i32 i32) (result i64)
630
1
            i64.const -68719476731)
631
1
        (table (;0;) 1 1 funcref)
632
1
        (memory (;0;) 16)
633
1
        (global (;0;) (mut i32) (i32.const 1048576))
634
1
        (global (;1;) i32 (i32.const 1048576))
635
1
        (global (;2;) i32 (i32.const 1048576))
636
1
        (export "memory" (memory 0))
637
1
        (export "test" (func 0))
638
1
        (export "__data_end" (global 1))
639
1
        (export "__heap_base" (global 2))
640
1
    )
641
1
    "#,
642
1
        )
643
1
        .unwrap(),
644
1
    );
645
646
3
    for 
exec_hint2
in ExecHint::available_engines() {
647
2
        let proto = HostVmPrototype::new(Config {
648
2
            allow_unresolved_imports: false,
649
2
            exec_hint,
650
2
            heap_pages: HeapPages::new(1024),
651
2
            module: &module_bytes,
652
2
        })
653
2
        .unwrap();
654
2
655
2
        let mut vm = HostVm::from(
656
2
            proto
657
2
                .run(
658
2
                    "test",
659
2
                    StorageProofSizeBehavior::proof_recording_disabled(),
660
2
                    &[],
661
2
                )
662
2
                .unwrap(),
663
2
        );
664
        loop {
665
2
            match vm {
666
2
                HostVm::ReadyToRun(r) => vm = r.run(),
667
                HostVm::Error {
668
                    error: Error::ReturnedPtrOutOfRange { .. },
669
                    ..
670
                } => {
671
2
                    break;
672
                }
673
0
                _ => unreachable!(),
674
            }
675
        }
676
    }
677
1
}
678
679
#[test]
680
1
fn unresolved_host_function_called() {
681
1
    /* Source code:
682
1
        extern {
683
1
            fn host_function_that_doesnt_exist();
684
1
        }
685
1
686
1
        #[no_mangle]
687
1
        extern "C" fn test(_: i32, _: i32) -> i64 {
688
1
            unsafe {
689
1
                host_function_that_doesnt_exist()
690
1
            }
691
1
692
1
            0
693
1
        }
694
1
    */
695
1
    let module_bytes = with_core_version_custom_sections(
696
1
        wat::parse_str(
697
1
            r#"
698
1
    (module
699
1
        (type (;0;) (func))
700
1
        (type (;1;) (func (param i32 i32) (result i64)))
701
1
        (import "env" "host_function_that_doesnt_exist" (func (;0;) (type 0)))
702
1
        (func (;1;) (type 1) (param i32 i32) (result i64)
703
1
          call 0
704
1
          i64.const 0)
705
1
        (table (;0;) 1 1 funcref)
706
1
        (memory (;0;) 16)
707
1
        (global (;0;) (mut i32) (i32.const 1048576))
708
1
        (global (;1;) i32 (i32.const 1048576))
709
1
        (global (;2;) i32 (i32.const 1048576))
710
1
        (export "memory" (memory 0))
711
1
        (export "test" (func 1))
712
1
        (export "__data_end" (global 1))
713
1
        (export "__heap_base" (global 2))
714
1
    )
715
1
    "#,
716
1
        )
717
1
        .unwrap(),
718
1
    );
719
720
3
    for 
exec_hint2
in ExecHint::available_engines() {
721
2
        match HostVmPrototype::new(Config {
722
2
            allow_unresolved_imports: false,
723
2
            exec_hint,
724
2
            heap_pages: HeapPages::new(1024),
725
2
            module: &module_bytes,
726
2
        }) {
727
2
            Err(NewErr::VirtualMachine(vm::NewErr::UnresolvedFunctionImport { .. })) => {}
728
0
            _ => panic!(),
729
        }
730
731
2
        let proto = HostVmPrototype::new(Config {
732
2
            allow_unresolved_imports: true,
733
2
            exec_hint,
734
2
            heap_pages: HeapPages::new(1024),
735
2
            module: &module_bytes,
736
2
        })
737
2
        .unwrap();
738
2
739
2
        let mut vm = HostVm::from(
740
2
            proto
741
2
                .run(
742
2
                    "test",
743
2
                    StorageProofSizeBehavior::proof_recording_disabled(),
744
2
                    &[],
745
2
                )
746
2
                .unwrap(),
747
2
        );
748
        loop {
749
2
            match vm {
750
2
                HostVm::ReadyToRun(r) => vm = r.run(),
751
                HostVm::Error {
752
                    error: Error::UnresolvedFunctionCalled { .. },
753
                    ..
754
                } => {
755
2
                    break;
756
                }
757
0
                _ => unreachable!(),
758
            }
759
        }
760
    }
761
1
}
762
763
// TODO: consider more tests for the other errors here, or add them on a host-function case-by-case basis