@@ -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"
@@ -686,7 +687,14 @@ func TestWasmExport(t *testing.T) {
686687 if tc .command {
687688 // Call _start (the entry point), which calls
688689 // tester.callTestMain, which then runs all the tests.
689- mustCall (mod .ExportedFunction ("_start" ).Call (ctx ))
690+ _ , err := mod .ExportedFunction ("_start" ).Call (ctx )
691+ if err != nil {
692+ if exitErr , ok := err .(* sys.ExitError ); ok && exitErr .ExitCode () == 0 {
693+ // Exited with code 0. Nothing to worry about.
694+ } else {
695+ t .Error ("failed to run _start:" , err )
696+ }
697+ }
690698 } else {
691699 // Run the _initialize call, because this is reactor mode wasm.
692700 mustCall (mod .ExportedFunction ("_initialize" ).Call (ctx ))
@@ -772,12 +780,56 @@ func TestWasmExportJS(t *testing.T) {
772780 }
773781}
774782
783+ // Test whether Go.run() (in wasm_exec.js) normally returns and returns the
784+ // right exit code.
785+ func TestWasmExit (t * testing.T ) {
786+ t .Parallel ()
787+
788+ type testCase struct {
789+ name string
790+ output string
791+ }
792+
793+ tests := []testCase {
794+ {name : "normal" , output : "exit code: 0\n " },
795+ {name : "exit-0" , output : "exit code: 0\n " },
796+ {name : "exit-0-sleep" , output : "slept\n exit code: 0\n " },
797+ {name : "exit-1" , output : "exit code: 1\n " },
798+ {name : "exit-1-sleep" , output : "slept\n exit code: 1\n " },
799+ }
800+ for _ , tc := range tests {
801+ tc := tc
802+ t .Run (tc .name , func (t * testing.T ) {
803+ t .Parallel ()
804+ options := optionsFromTarget ("wasm" , sema )
805+ buildConfig , err := builder .NewConfig (& options )
806+ if err != nil {
807+ t .Fatal (err )
808+ }
809+ buildConfig .Target .Emulator = "node testdata/wasmexit.js {}"
810+ output := & bytes.Buffer {}
811+ _ , err = buildAndRun ("testdata/wasmexit.go" , buildConfig , output , []string {tc .name }, nil , time .Minute , func (cmd * exec.Cmd , result builder.BuildResult ) error {
812+ return cmd .Run ()
813+ })
814+ if err != nil {
815+ t .Error (err )
816+ }
817+ expected := "wasmexit test: " + tc .name + "\n " + tc .output
818+ checkOutputData (t , []byte (expected ), output .Bytes ())
819+ })
820+ }
821+ }
822+
775823// Check whether the output of a test equals the expected output.
776824func checkOutput (t * testing.T , filename string , actual []byte ) {
777825 expectedOutput , err := os .ReadFile (filename )
778826 if err != nil {
779827 t .Fatal ("could not read output file:" , err )
780828 }
829+ checkOutputData (t , expectedOutput , actual )
830+ }
831+
832+ func checkOutputData (t * testing.T , expectedOutput , actual []byte ) {
781833 expectedOutput = bytes .ReplaceAll (expectedOutput , []byte ("\r \n " ), []byte ("\n " ))
782834 actual = bytes .ReplaceAll (actual , []byte ("\r \n " ), []byte ("\n " ))
783835
0 commit comments