wa-lang.org/wazero@v1.0.2/imports/go/example/stars_test.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"os"
     8  	"os/exec"
     9  	"path"
    10  	"testing"
    11  
    12  	"wa-lang.org/wazero"
    13  	gojs "wa-lang.org/wazero/imports/go"
    14  	"wa-lang.org/wazero/internal/platform"
    15  	"wa-lang.org/wazero/internal/testing/maintester"
    16  	"wa-lang.org/wazero/internal/testing/require"
    17  	"wa-lang.org/wazero/sys"
    18  )
    19  
    20  // Test_main ensures the following will work:
    21  //
    22  //	go run stars.go
    23  func Test_main(t *testing.T) {
    24  	stdout, stderr := maintester.TestMain(t, main, "stars")
    25  	require.Equal(t, "", stderr)
    26  	require.Equal(t, "wazero has 9999999 stars. Does that include you?\n", stdout)
    27  }
    28  
    29  // TestMain compiles the wasm on-demand, which uses the runner's Go as opposed
    30  // to a binary checked in, which would be pinned to one version. This is
    31  // separate from Test_main to show that compilation doesn't dominate the
    32  // execution time.
    33  func TestMain(m *testing.M) {
    34  	// Notably our scratch containers don't have go, so don't fail tests.
    35  	if err := compileFromGo(); err != nil {
    36  		log.Println("Skipping tests due to:", err)
    37  		os.Exit(0)
    38  	}
    39  	os.Exit(m.Run())
    40  }
    41  
    42  // compileFromGo compiles "stars/main.go" on demand as the binary generated is
    43  // too big (>7MB) to check into the source tree.
    44  func compileFromGo() error {
    45  	cmd := exec.Command("go", "build", "-o", "main.wasm", ".")
    46  	cmd.Dir = "stars"
    47  	cmd.Env = append(os.Environ(), "GOARCH=wasm", "GOOS=js", "GOWASM=satconv,signext")
    48  	if out, err := cmd.CombinedOutput(); err != nil {
    49  		return fmt.Errorf("go build: %v\n%s", err, out)
    50  	}
    51  	return nil
    52  }
    53  
    54  // Benchmark_main is in the example for GOOS=js to re-use compilation caching
    55  // infrastructure. This is only used to sporadically check the impact of
    56  // internal changes as in general, it is known that GOOS=js will be slow due to
    57  // JavaScript emulation.
    58  func Benchmark_main(b *testing.B) {
    59  	// Don't benchmark with interpreter as we know it will be slow.
    60  	if !platform.CompilerSupported() {
    61  		b.Skip()
    62  	}
    63  
    64  	ctx := context.Background()
    65  
    66  	// Create a new WebAssembly Runtime.
    67  	r := wazero.NewRuntime(ctx)
    68  	defer r.Close(ctx) // This closes everything this Runtime created.
    69  
    70  	bin, err := os.ReadFile(path.Join("stars", "main.wasm"))
    71  	if err != nil {
    72  		b.Fatal(err)
    73  	}
    74  	compiled, err := r.CompileModule(ctx, bin)
    75  	if err != nil {
    76  		b.Fatal(err)
    77  	}
    78  
    79  	// Instead of making real HTTP calls, return fake data.
    80  	ctx = gojs.WithRoundTripper(ctx, &fakeGitHub{})
    81  	cfg := wazero.NewModuleConfig()
    82  
    83  	b.Run("gojs.Run", func(b *testing.B) {
    84  		for i := 0; i < b.N; i++ {
    85  			err = gojs.Run(ctx, r, compiled, cfg)
    86  			if exitErr, ok := err.(*sys.ExitError); ok && exitErr.ExitCode() != 0 {
    87  				b.Fatal(err)
    88  			} else if !ok {
    89  				b.Fatal(err)
    90  			}
    91  		}
    92  	})
    93  }