github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/integration_test/engine/dwarf_test.go (about) 1 package adhoc 2 3 import ( 4 "bufio" 5 _ "embed" 6 "strings" 7 "testing" 8 9 "github.com/tetratelabs/wazero" 10 "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" 11 "github.com/tetratelabs/wazero/internal/platform" 12 "github.com/tetratelabs/wazero/internal/testing/dwarftestdata" 13 "github.com/tetratelabs/wazero/internal/testing/require" 14 ) 15 16 var dwarfTests = map[string]testCase{ 17 "tinygo": {f: testTinyGoDWARF}, 18 "zig": {f: testZigDWARF}, 19 "cc": {f: testCCDWARF}, 20 "rust": {f: testRustDWARF}, 21 } 22 23 func TestEngineCompiler_DWARF(t *testing.T) { 24 if !platform.CompilerSupported() { 25 t.Skip() 26 } 27 runAllTests(t, dwarfTests, wazero.NewRuntimeConfigCompiler(), false) 28 } 29 30 func TestEngineInterpreter_DWARF(t *testing.T) { 31 runAllTests(t, dwarfTests, wazero.NewRuntimeConfigInterpreter(), false) 32 } 33 34 func testTinyGoDWARF(t *testing.T, r wazero.Runtime) { 35 runDWARFTest(t, r, dwarftestdata.TinyGoWasm, `module[] function[_start] failed: wasm error: unreachable 36 wasm stack trace: 37 .runtime._panic(i32) 38 0x18f3: /runtime_tinygowasm.go:70:6 39 .main.c() 40 0x2ff9: /main.go:16:7 41 .main.b() 42 0x2f97: /main.go:12:3 43 .main.a() 44 0x2f39: /main.go:8:3 45 .main.main() 46 0x2149: /main.go:4:3 47 .runtime.run$1() 48 0x1fcb: /scheduler_any.go:25:11 49 .runtime.run$1$gowrapper(i32) 50 0x6f0: /scheduler_any.go:23:2 51 .tinygo_launch(i32) 52 0x23: /task_asyncify_wasm.S:59 53 .runtime.scheduler() 54 0x1ec4: /task_asyncify.go:109:17 (inlined) 55 /scheduler.go:236:11 56 .runtime.run() 57 0x1d92: /scheduler_any.go:28:11 58 ._start() 59 0x1d12: /runtime_wasm_wasi.go:21:5`) 60 } 61 62 func testZigDWARF(t *testing.T, r wazero.Runtime) { 63 runDWARFTest(t, r, dwarftestdata.ZigWasm, `module[] function[_start] failed: wasm error: unreachable 64 wasm stack trace: 65 .builtin.default_panic(i32,i32,i32,i32) 66 0x63: /builtin.zig:889:17 67 .main.main() i32 68 0x25: /main.zig:10:5 (inlined) 69 /main.zig:6:5 (inlined) 70 /main.zig:2:5 71 ._start() 72 0x6a: /start.zig:609:37 (inlined) 73 /start.zig:224:5`) 74 } 75 76 func testCCDWARF(t *testing.T, r wazero.Runtime) { 77 runDWARFTest(t, r, dwarftestdata.ZigCCWasm, `module[] function[_start] failed: wasm error: unreachable 78 wasm stack trace: 79 .a() 80 0x312: /main.c:7:18 81 .__original_main() i32 82 0x47c: /main.c:11:3 83 ._start() 84 ._start.command_export()`) 85 } 86 87 func testRustDWARF(t *testing.T, r wazero.Runtime) { 88 runDWARFTest(t, r, dwarftestdata.RustWasm, `module[] function[_start] failed: wasm error: unreachable 89 wasm stack trace: 90 .__rust_start_panic(i32) i32 91 0xc474: /index.rs:286:39 (inlined) 92 /const_ptr.rs:870:18 (inlined) 93 /index.rs:286:39 (inlined) 94 /mod.rs:1630:46 (inlined) 95 /mod.rs:405:20 (inlined) 96 /mod.rs:1630:46 (inlined) 97 /mod.rs:1548:18 (inlined) 98 /iter.rs:1478:30 (inlined) 99 /count.rs:74:18 100 .rust_panic(i32,i32) 101 0xa3f8: /validations.rs:57:19 (inlined) 102 /validations.rs:57:19 (inlined) 103 /iter.rs:140:15 (inlined) 104 /iter.rs:140:15 (inlined) 105 /iterator.rs:330:13 (inlined) 106 /iterator.rs:377:9 (inlined) 107 /mod.rs:1455:35 108 .std::panicking::rust_panic_with_hook::h93e119628869d575(i32,i32,i32,i32,i32) 109 0x42df: /alloc.rs:244:22 (inlined) 110 /alloc.rs:244:22 (inlined) 111 /alloc.rs:342:9 (inlined) 112 /mod.rs:487:1 (inlined) 113 /mod.rs:487:1 (inlined) 114 /mod.rs:487:1 (inlined) 115 /mod.rs:487:1 (inlined) 116 /mod.rs:487:1 (inlined) 117 /panicking.rs:292:17 (inlined) 118 /panicking.rs:292:17 119 .std::panicking::begin_panic_handler::{{closure}}::h2b8c0798e533b227(i32,i32,i32) 120 0xaa8c: /mod.rs:362:12 (inlined) 121 /mod.rs:1257:22 (inlined) 122 /mod.rs:1235:21 (inlined) 123 /mod.rs:1214:26 124 .std::sys_common::backtrace::__rust_end_short_backtrace::h030a533bc034da65(i32) 125 0xc144: /mod.rs:188:26 126 .rust_begin_unwind(i32) 127 0xb7df: /mod.rs:1629:9 (inlined) 128 /builders.rs:199:17 (inlined) 129 /result.rs:1352:22 (inlined) 130 /builders.rs:187:23 131 .core::panicking::panic_fmt::hb1bfc4175f838eff(i32,i32) 132 0xbd3d: /mod.rs:1384:17 133 .main::main::hfd44f54575e6bfdf() 134 0xad2c: /memchr.rs 135 .core::ops::function::FnOnce::call_once::h87e5f77996df3e28(i32) 136 0xbd61: /mod.rs 137 .std::sys_common::backtrace::__rust_begin_short_backtrace::h7ca17eb6aa97f768(i32) 138 0xbd95: /mod.rs:1504:35 (inlined) 139 /mod.rs:1407:36 140 .std::rt::lang_start::{{closure}}::he4aa401e76315dfe(i32) i32 141 0xae9a: /location.rs:196:6 142 .std::rt::lang_start_internal::h3c39e5d3c278a90f(i32,i32,i32,i32) i32 143 .std::rt::lang_start::h779801844bd22a3c(i32,i32,i32) i32 144 0xab94: /mod.rs:1226:2 145 .__original_main() i32 146 0xc0ae: /methods.rs:1677:13 (inlined) 147 /mod.rs:165:24 (inlined) 148 /mod.rs:165:24 149 ._start() 150 0xc10f: /mod.rs:187 151 ._start.command_export() 152 0xc3de: /iterator.rs:2414:21 (inlined) 153 /map.rs:124:9 (inlined) 154 /accum.rs:42:17 (inlined) 155 /iterator.rs:3347:9 (inlined) 156 /count.rs:135:5 (inlined) 157 /count.rs:135:5 (inlined) 158 /count.rs:71:21`) 159 } 160 161 func runDWARFTest(t *testing.T, r wazero.Runtime, bin []byte, exp string) { 162 if len(bin) == 0 { 163 t.Skip() // Skip if the binary is empty which can happen when xz is not installed on the system 164 } 165 166 _, err := wasi_snapshot_preview1.Instantiate(testCtx, r) 167 require.NoError(t, err) 168 _, err = r.Instantiate(testCtx, bin) 169 require.Error(t, err) 170 171 errStr := err.Error() 172 173 // Since stack traces change where the binary is compiled, we sanitize each line 174 // so that it doesn't contain any file system dependent info. 175 scanner := bufio.NewScanner(strings.NewReader(errStr)) 176 scanner.Split(bufio.ScanLines) 177 var sanitizedLines []string 178 for scanner.Scan() { 179 line := scanner.Text() 180 start, last := strings.Index(line, "/"), strings.LastIndex(line, "/") 181 if start >= 0 { 182 l := len(line) - last 183 buf := []byte(line) 184 copy(buf[start:], buf[last:]) 185 line = string(buf[:start+l]) 186 } 187 sanitizedLines = append(sanitizedLines, line) 188 } 189 190 sanitizedTraces := strings.Join(sanitizedLines, "\n") 191 require.Equal(t, exp, sanitizedTraces) 192 }