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