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  }