@@ -25,6 +25,7 @@ import (
2525 "github.com/tetratelabs/wazero"
2626 "github.com/tetratelabs/wazero/api"
2727 "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
28+ "github.com/tetratelabs/wazero/sys"
2829 "github.com/tinygo-org/tinygo/builder"
2930 "github.com/tinygo-org/tinygo/compileopts"
3031 "github.com/tinygo-org/tinygo/diagnostics"
@@ -683,7 +684,14 @@ func TestWasmExport(t *testing.T) {
683684 if tc .command {
684685 // Call _start (the entry point), which calls
685686 // tester.callTestMain, which then runs all the tests.
686- mustCall (mod .ExportedFunction ("_start" ).Call (ctx ))
687+ _ , err := mod .ExportedFunction ("_start" ).Call (ctx )
688+ if err != nil {
689+ if exitErr , ok := err .(* sys.ExitError ); ok && exitErr .ExitCode () == 0 {
690+ // Exited with code 0. Nothing to worry about.
691+ } else {
692+ t .Error ("failed to run _start:" , err )
693+ }
694+ }
687695 } else {
688696 // Run the _initialize call, because this is reactor mode wasm.
689697 mustCall (mod .ExportedFunction ("_initialize" ).Call (ctx ))
@@ -766,12 +774,56 @@ func TestWasmExportJS(t *testing.T) {
766774 }
767775}
768776
777+ // Test whether Go.run() (in wasm_exec.js) normally returns and returns the
778+ // right exit code.
779+ func TestWasmExit (t * testing.T ) {
780+ t .Parallel ()
781+
782+ type testCase struct {
783+ name string
784+ output string
785+ }
786+
787+ tests := []testCase {
788+ {name : "normal" , output : "exit code: 0\n " },
789+ {name : "exit-0" , output : "exit code: 0\n " },
790+ {name : "exit-0-sleep" , output : "slept\n exit code: 0\n " },
791+ {name : "exit-1" , output : "exit code: 1\n " },
792+ {name : "exit-1-sleep" , output : "slept\n exit code: 1\n " },
793+ }
794+ for _ , tc := range tests {
795+ tc := tc
796+ t .Run (tc .name , func (t * testing.T ) {
797+ t .Parallel ()
798+ options := optionsFromTarget ("wasm" , sema )
799+ buildConfig , err := builder .NewConfig (& options )
800+ if err != nil {
801+ t .Fatal (err )
802+ }
803+ buildConfig .Target .Emulator = "node testdata/wasmexit.js {}"
804+ output := & bytes.Buffer {}
805+ _ , err = buildAndRun ("testdata/wasmexit.go" , buildConfig , output , []string {tc .name }, nil , time .Minute , func (cmd * exec.Cmd , result builder.BuildResult ) error {
806+ return cmd .Run ()
807+ })
808+ if err != nil {
809+ t .Error (err )
810+ }
811+ expected := "wasmexit test: " + tc .name + "\n " + tc .output
812+ checkOutputData (t , []byte (expected ), output .Bytes ())
813+ })
814+ }
815+ }
816+
769817// Check whether the output of a test equals the expected output.
770818func checkOutput (t * testing.T , filename string , actual []byte ) {
771819 expectedOutput , err := os .ReadFile (filename )
772820 if err != nil {
773821 t .Fatal ("could not read output file:" , err )
774822 }
823+ checkOutputData (t , expectedOutput , actual )
824+ }
825+
826+ func checkOutputData (t * testing.T , expectedOutput , actual []byte ) {
775827 expectedOutput = bytes .ReplaceAll (expectedOutput , []byte ("\r \n " ), []byte ("\n " ))
776828 actual = bytes .ReplaceAll (actual , []byte ("\r \n " ), []byte ("\n " ))
777829
0 commit comments