package internal_test import ( "fmt" "log" "net/http" "net/http/httptest" "os" "path" "strconv" "testing" "github.com/dapr/components-contrib/metadata" "github.com/stretchr/testify/require" "github.com/dapr/components-contrib/middleware" "github.com/dapr/components-contrib/middleware/http/wasm/basic" "github.com/dapr/components-contrib/middleware/http/wasm/basic/internal/test" ) var guestWasm map[string][]byte const ( guestWasmOutput = "output" ) // TestMain ensures we can read the test wasm prior to running e2e tests. func TestMain(m *testing.M) { wasms := []string{guestWasmOutput} guestWasm = make(map[string][]byte, len(wasms)) for _, name := range wasms { if wasm, err := os.ReadFile(path.Join("e2e-guests", name, "main.wasm")); err != nil { log.Panicln(err) } else { guestWasm[name] = wasm } } os.Exit(m.Run()) } func Test_EndToEnd(t *testing.T) { type testCase struct { name string guest []byte poolSize int test func(t *testing.T, handler http.Handler, log fmt.Stringer) } tests := []testCase{ { name: "consoleLog stdout and stderr", guest: guestWasm[guestWasmOutput], test: func(t *testing.T, handler http.Handler, log fmt.Stringer) { r := httptest.NewRequest(http.MethodGet, "/", nil) w := httptest.NewRecorder() handler.ServeHTTP(w, r) // First, we expect any console logging written inline from // init (main) and the request (rewrite) funcs to info level. // // Then, we expect to see stdout and stderr from both scopes // at debug level. require.Equal(t, `Info(main ConsoleLog) Info(request[0] ConsoleLog) Debug(wasm stdout: main Stdout request[0] Stdout ) Debug(wasm stderr: main Stderr request[0] Stderr ) `, log.String()) }, }, { name: "multiple requests", guest: guestWasm[guestWasmOutput], poolSize: 2, test: func(t *testing.T, handler http.Handler, log fmt.Stringer) { // Service more requests than the pool size to ensure it works properly. for i := 0; i < 3; i++ { r := httptest.NewRequest(http.MethodGet, "/", nil) w := httptest.NewRecorder() handler.ServeHTTP(w, r) } // We expect to see initialization (main) twice, once for each // module in the pool. We expect to see request[1] which shows // round-robin back to the first module in the pool. require.Equal(t, `Info(main ConsoleLog) Info(main ConsoleLog) Info(request[0] ConsoleLog) Debug(wasm stdout: main Stdout main Stdout request[0] Stdout ) Debug(wasm stderr: main Stderr main Stderr request[0] Stderr ) Info(request[0] ConsoleLog) Debug(wasm stdout: request[0] Stdout ) Debug(wasm stderr: request[0] Stderr ) Info(request[1] ConsoleLog) Debug(wasm stdout: request[1] Stdout ) Debug(wasm stderr: request[1] Stderr ) `, log.String()) }, }, } h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { poolSize := "1" if tc.poolSize > 0 { poolSize = strconv.Itoa(tc.poolSize) } wasmPath := path.Join(t.TempDir(), "guest.wasm") require.NoError(t, os.WriteFile(wasmPath, tc.guest, 0o600)) meta := metadata.Base{Properties: map[string]string{"path": wasmPath, "poolSize": poolSize}} l := test.NewLogger() handlerFn, err := basic.NewMiddleware(l).GetHandler(middleware.Metadata{Base: meta}) require.NoError(t, err) tc.test(t, handlerFn(h), l.(fmt.Stringer)) }) } }