diff --git a/examples/chat/server_test.go b/examples/chat/server_test.go index 789bf9d74..6cb7e77a4 100644 --- a/examples/chat/server_test.go +++ b/examples/chat/server_test.go @@ -77,15 +77,13 @@ func (db *db) GetImage(ctx context.Context, _ string, image ImageID) ([]byte, er } func TestServer(t *testing.T) { + t.Skip("TODO(mwhittaker): Enable testing of main.") for _, r := range weavertest.AllRunners() { // Use a fake DB since normal implementation does not work with multiple replicas db := &db{} r.Fakes = []weavertest.FakeComponent{weavertest.Fake[SQLStore](db)} r.Test(t, func(t *testing.T, store weaver.Main) { - addr, err := weavertest.ListenerAddress(t, "chat") - if err != nil { - t.Fatal(err) - } + addr := "TODO(mwhittaker): Enable testing of main" // Login expect(t, "login", httpGet(t, addr, "/"), "Login") diff --git a/godeps.txt b/godeps.txt index bf4aac1f9..b5d61a326 100644 --- a/godeps.txt +++ b/godeps.txt @@ -927,7 +927,6 @@ github.com/ServiceWeaver/weaver/weavertest context errors fmt - github.com/ServiceWeaver/weaver github.com/ServiceWeaver/weaver/internal/envelope/conn github.com/ServiceWeaver/weaver/internal/private github.com/ServiceWeaver/weaver/internal/reflection @@ -938,7 +937,6 @@ github.com/ServiceWeaver/weaver/weavertest github.com/ServiceWeaver/weaver/runtime/protos github.com/google/uuid go.opentelemetry.io/otel/sdk/trace - go.opentelemetry.io/otel/trace golang.org/x/exp/maps golang.org/x/sync/errgroup os diff --git a/internal/private/private.go b/internal/private/private.go index 8be12d205..a4224a997 100644 --- a/internal/private/private.go +++ b/internal/private/private.go @@ -42,9 +42,4 @@ type App interface { // Get fetches the component with type t from wlet. Get(requester string, t reflect.Type) (any, error) - - // ListenerAddress returns the address (host:port) of the - // named listener, waiting for the listener to be created - // if necessary. - ListenerAddress(name string) (string, error) } diff --git a/weavertest/deployer.go b/weavertest/deployer.go index 28aea0f94..85b768d5d 100644 --- a/weavertest/deployer.go +++ b/weavertest/deployer.go @@ -122,9 +122,6 @@ func newDeployer(ctx context.Context, wlet *protos.EnvelopeInfo, config *protos. log: logWriter, } - // Force testMain to be local. - d.local["github.com/ServiceWeaver/weaver/weavertest/testMainInterface"] = true - // Fakes need to be local as well. for _, fake := range runner.Fakes { name := fmt.Sprintf("%s/%s", fake.intf.PkgPath(), fake.intf.Name()) @@ -159,7 +156,6 @@ func (d *deployer) start() error { Sections: d.wlet.Sections, SingleProcess: d.wlet.SingleProcess, SingleMachine: d.wlet.SingleMachine, - RunMain: true, } bootstrap := runtime.Bootstrap{ ToWeaveletFile: toWeaveletReader, diff --git a/weavertest/init.go b/weavertest/init.go index 8bccccc15..f02c68e3d 100644 --- a/weavertest/init.go +++ b/weavertest/init.go @@ -16,16 +16,13 @@ package weavertest import ( "context" - "errors" "fmt" "os" "reflect" "runtime" - "sync" "testing" "time" - "github.com/ServiceWeaver/weaver" "github.com/ServiceWeaver/weaver/internal/private" "github.com/ServiceWeaver/weaver/internal/reflection" "github.com/ServiceWeaver/weaver/runtime/logging" @@ -91,58 +88,8 @@ func Fake[T any](impl any) FakeComponent { return FakeComponent{intf: t, impl: impl} } -// private.App object per live test or benchmark. -var ( - appMu sync.Mutex - apps map[testing.TB]private.App -) - -func registerApp(t testing.TB, app private.App) { - appMu.Lock() - defer appMu.Unlock() - if apps == nil { - apps = map[testing.TB]private.App{} - } - apps[t] = app -} - -func unregisterApp(t testing.TB, app private.App) { - appMu.Lock() - defer appMu.Unlock() - delete(apps, t) -} - -func getApp(t testing.TB) private.App { - appMu.Lock() - defer appMu.Unlock() - return apps[t] -} - -// ListenerAddress returns the address (of the form host:port) for the -// listener with the specified name. This call will block waiting for -// the listener to be initialized if necessary. -func ListenerAddress(t testing.TB, name string) (string, error) { - app := getApp(t) - if app == nil { - return "", fmt.Errorf("Service Weaver application is not running") - } - return app.ListenerAddress(name) -} - -//go:generate ../cmd/weaver/weaver generate - -// testMain is the component implementation used in tests. -type testMain struct { - weaver.Implements[testMainInterface] -} - -// testMainInterface is the alternative to weaver.Main we use so that -// we do not conflict with any application provided implementation of -// weaver.Main. -type testMainInterface interface{} - -// Test runs a sub-test of t that tests supplied Service Weaver -// application code. It fails at runtime if body is not a function +// Test runs a sub-test of t that tests the supplied Service Weaver +// application code. It fails at runtime if body is not a function // whose signature looks like: // // func(*testing.T, ComponentType1) @@ -154,17 +101,20 @@ type testMainInterface interface{} // followed by a the list of components. // // func TestFoo(t *testing.T) { -// weavertest.Local.Test(t, func(t *testing.T, foo Foo, bar Bar) { -// // Test foo and bar ... -// }) +// weavertest.Local.Test(t, func(t *testing.T, foo Foo, bar Bar) { +// // Test foo and bar ... +// }) // } +// +// In contrast with weaver.Run, the Test method does not run the Main method of +// any registered weaver.Main component. func (r Runner) Test(t *testing.T, body any) { t.Helper() t.Run(r.Name, func(t *testing.T) { r.sub(t, false, body) }) } -// Bench runs a sub-benchmark of b that benchmarks supplied Service -// Weaver application code. It fails at runtime if body is not a +// Bench runs a sub-benchmark of b that benchmarks the supplied Service +// Weaver application code. It fails at runtime if body is not a // function whose signature looks like: // // func(*testing.B, ComponentType1) @@ -176,12 +126,15 @@ func (r Runner) Test(t *testing.T, body any) { // followed by a the list of components. // // func BenchmarkFoo(b *testing.B) { -// weavertest.Local.Bench(b, func(b *testing.B, foo Foo) { -// for i := 0; i < b.N; i++ { -// ... use foo ... -// } -// }) +// weavertest.Local.Bench(b, func(b *testing.B, foo Foo) { +// for i := 0; i < b.N; i++ { +// // Benchmark foo ... +// } +// }) // } +// +// In contrast with weaver.Run, the Bench method does not run the Main method of +// any registered weaver.Main component. func (r Runner) Bench(b *testing.B, testBody any) { b.Helper() b.Run(r.Name, func(b *testing.B) { r.sub(b, true, testBody) }) @@ -260,7 +213,7 @@ func checkRunFunc(t testing.TB, fn any) (func(context.Context, private.App) erro args[0] = reflect.ValueOf(t) for i := 1; i < n; i++ { argType := fnType.In(i) - comp, err := app.Get("weavertest.testMainInterface", argType) + comp, err := app.Get(t.Name(), argType) if err != nil { return err } @@ -281,31 +234,7 @@ func runWeaver(ctx context.Context, t testing.TB, runner Runner, body func(conte if err != nil { return err } - registerApp(t, app) - t.Cleanup(func() { unregisterApp(t, app) }) - - // Run wait() in a go routine. - sub, cancel := context.WithCancel(ctx) - defer cancel() - result := make(chan error) - go func() { result <- app.Wait(sub) }() - - // Run the test code. - if err := body(ctx, app); err != nil { - return err - } - - // Wait for wait() to finish, but give up after a while in case user Main hangs. - cancel() - select { - case err := <-result: - if err != nil && !errors.Is(err, context.Canceled) { - t.Fatalf("weaver.Main.Main failure: %v", err) - } - case <-time.After(time.Millisecond * 100): - t.Log("weaver.Main.Main not exiting after cancellation") - } - return nil + return body(ctx, app) } // logStacks prints the stacks of live goroutines. This functionality diff --git a/weavertest/weaver_gen.go b/weavertest/weaver_gen.go deleted file mode 100644 index 282bc6a70..000000000 --- a/weavertest/weaver_gen.go +++ /dev/null @@ -1,72 +0,0 @@ -//go:build !ignoreWeaverGen - -package weavertest - -// Code generated by "weaver generate". DO NOT EDIT. -import ( - "context" - "github.com/ServiceWeaver/weaver" - "github.com/ServiceWeaver/weaver/runtime/codegen" - "go.opentelemetry.io/otel/trace" - "reflect" -) -var _ codegen.LatestVersion = codegen.Version[[0][11]struct{}]("You used 'weaver generate' codegen version 0.11.0, but you built your code with an incompatible weaver module version. Try upgrading 'weaver generate' and re-running it.") - -func init() { - codegen.Register(codegen.Registration{ - Name: "github.com/ServiceWeaver/weaver/weavertest/testMainInterface", - Iface: reflect.TypeOf((*testMainInterface)(nil)).Elem(), - Impl: reflect.TypeOf(testMain{}), - LocalStubFn: func(impl any, tracer trace.Tracer) any { - return testMainInterface_local_stub{impl: impl.(testMainInterface), tracer: tracer} - }, - ClientStubFn: func(stub codegen.Stub, caller string) any { return testMainInterface_client_stub{stub: stub} }, - ServerStubFn: func(impl any, addLoad func(uint64, float64)) codegen.Server { - return testMainInterface_server_stub{impl: impl.(testMainInterface), addLoad: addLoad} - }, - RefData: "", - }) -} - -// weaver.Instance checks. -var _ weaver.InstanceOf[testMainInterface] = (*testMain)(nil) - -// weaver.Router checks. -var _ weaver.Unrouted = (*testMain)(nil) - -// Local stub implementations. - -type testMainInterface_local_stub struct { - impl testMainInterface - tracer trace.Tracer -} - -// Check that testMainInterface_local_stub implements the testMainInterface interface. -var _ testMainInterface = (*testMainInterface_local_stub)(nil) - -// Client stub implementations. - -type testMainInterface_client_stub struct { - stub codegen.Stub -} - -// Check that testMainInterface_client_stub implements the testMainInterface interface. -var _ testMainInterface = (*testMainInterface_client_stub)(nil) - -// Server stub implementations. - -type testMainInterface_server_stub struct { - impl testMainInterface - addLoad func(key uint64, load float64) -} - -// Check that testMainInterface_server_stub implements the codegen.Server interface. -var _ codegen.Server = (*testMainInterface_server_stub)(nil) - -// GetStubFn implements the codegen.Server interface. -func (s testMainInterface_server_stub) GetStubFn(method string) func(ctx context.Context, args []byte) ([]byte, error) { - switch method { - default: - return nil - } -}