github.com/tetratelabs/wazero@v1.2.1/internal/gojs/misc_test.go (about) 1 package gojs_test 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "strings" 8 "testing" 9 10 "github.com/tetratelabs/wazero" 11 "github.com/tetratelabs/wazero/experimental" 12 "github.com/tetratelabs/wazero/experimental/logging" 13 "github.com/tetratelabs/wazero/internal/gojs/config" 14 "github.com/tetratelabs/wazero/internal/testing/require" 15 ) 16 17 func Test_exit(t *testing.T) { 18 t.Parallel() 19 20 var log bytes.Buffer 21 loggingCtx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{}, 22 logging.NewHostLoggingListenerFactory(&log, logging.LogScopeProc)) 23 24 stdout, stderr, err := compileAndRun(loggingCtx, "exit", defaultConfig) 25 26 require.EqualError(t, err, `module closed with exit_code(255)`) 27 require.Zero(t, stderr) 28 require.Zero(t, stdout) 29 require.Equal(t, `==> go.runtime.wasmExit(code=255) 30 <== 31 `, log.String()) // Note: gojs doesn't panic on exit, so you see "<==" 32 } 33 34 func Test_goroutine(t *testing.T) { 35 t.Parallel() 36 37 stdout, stderr, err := compileAndRun(testCtx, "goroutine", defaultConfig) 38 39 require.EqualError(t, err, `module closed with exit_code(0)`) 40 require.Zero(t, stderr) 41 require.Equal(t, `producer 42 consumer 43 `, stdout) 44 } 45 46 func Test_mem(t *testing.T) { 47 t.Parallel() 48 49 var log bytes.Buffer 50 loggingCtx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{}, 51 logging.NewHostLoggingListenerFactory(&log, logging.LogScopeMemory)) 52 53 stdout, stderr, err := compileAndRun(loggingCtx, "mem", defaultConfig) 54 55 require.EqualError(t, err, `module closed with exit_code(0)`) 56 require.Zero(t, stderr) 57 require.Zero(t, stdout) 58 59 // The memory view is reset at least once. 60 require.Contains(t, log.String(), `==> go.runtime.resetMemoryDataView() 61 <== 62 `) 63 } 64 65 func Test_stdio(t *testing.T) { 66 t.Parallel() 67 68 input := "stdin\n" 69 stdout, stderr, err := compileAndRun(testCtx, "stdio", func(moduleConfig wazero.ModuleConfig) (wazero.ModuleConfig, *config.Config) { 70 return defaultConfig(moduleConfig.WithStdin(strings.NewReader(input))) 71 }) 72 73 require.Equal(t, "stderr 6\n", stderr) 74 require.EqualError(t, err, `module closed with exit_code(0)`) 75 require.Equal(t, "stdout 6\n", stdout) 76 } 77 78 func Test_stdio_large(t *testing.T) { 79 t.Parallel() 80 81 // Large stdio will trigger GC which will trigger events. 82 var log bytes.Buffer 83 loggingCtx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{}, 84 logging.NewHostLoggingListenerFactory(&log, logging.LogScopePoll)) 85 86 size := 2 * 1024 * 1024 // 2MB 87 input := make([]byte, size) 88 stdout, stderr, err := compileAndRun(loggingCtx, "stdio", func(moduleConfig wazero.ModuleConfig) (wazero.ModuleConfig, *config.Config) { 89 return defaultConfig(moduleConfig.WithStdin(bytes.NewReader(input))) 90 }) 91 92 require.EqualError(t, err, `module closed with exit_code(0)`) 93 require.Equal(t, fmt.Sprintf("stderr %d\n", size), stderr) 94 require.Equal(t, fmt.Sprintf("stdout %d\n", size), stdout) 95 96 // We can't predict the precise ms the timeout event will be, so we partial match. 97 require.Contains(t, log.String(), `==> go.runtime.scheduleTimeoutEvent(ms=`) 98 require.Contains(t, log.String(), `<== (id=1)`) 99 // There may be another timeout event between the first and its clear. 100 require.Contains(t, log.String(), `==> go.runtime.clearTimeoutEvent(id=1) 101 <== 102 `) 103 } 104 105 func Test_gc(t *testing.T) { 106 t.Parallel() 107 108 stdout, stderr, err := compileAndRun(testCtx, "gc", defaultConfig) 109 110 require.EqualError(t, err, `module closed with exit_code(0)`) 111 require.Equal(t, "", stderr) 112 require.Equal(t, "before gc\nafter gc\n", stdout) 113 }