func TestRelease(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() p, q := pipetransport.New() if *logMessages { p = logtransport.New(nil, p) } c := rpc.NewConn(p) hf := new(HandleFactory) d := rpc.NewConn(q, rpc.MainInterface(testcapnp.HandleFactory_ServerToClient(hf).Client)) defer d.Wait() defer c.Close() client := testcapnp.HandleFactory{Client: c.Bootstrap(ctx)} r, err := client.NewHandle(ctx, nil).Struct() if err != nil { t.Fatal("NewHandle:", err) } handle := r.Handle() if n := hf.numHandles(); n != 1 { t.Fatalf("numHandles = %d; want 1", n) } if err := handle.Client.Close(); err != nil { t.Error("handle.Client.Close():", err) } flushConn(ctx, c) if n := hf.numHandles(); n != 0 { t.Errorf("numHandles = %d; want 0", n) } }
func TestCancel(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() p, q := pipetransport.New() if *logMessages { p = logtransport.New(nil, p) } c := rpc.NewConn(p) notify := make(chan struct{}) hanger := testcapnp.Hanger_ServerToClient(Hanger{notify: notify}) d := rpc.NewConn(q, rpc.MainInterface(hanger.Client)) defer d.Wait() defer c.Close() client := testcapnp.Hanger{Client: c.Bootstrap(ctx)} subctx, subcancel := context.WithCancel(ctx) promise := client.Hang(subctx, func(r testcapnp.Hanger_hang_Params) error { return nil }) <-notify subcancel() _, err := promise.Struct() <-notify // test will deadlock if cancel not delivered if err != context.Canceled { t.Errorf("promise.Get() error: %v; want %v", err, context.Canceled) } }
func TestIssue3(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() p, q := pipetransport.New() if *logMessages { p = logtransport.New(nil, p) } log := testLogger{t} c := rpc.NewConn(p, rpc.ConnLog(log)) echoSrv := testcapnp.Echoer_ServerToClient(new(SideEffectEchoer)) d := rpc.NewConn(q, rpc.MainInterface(echoSrv.Client), rpc.ConnLog(log)) defer d.Wait() defer c.Close() client := testcapnp.Echoer{Client: c.Bootstrap(ctx)} localCap := testcapnp.CallOrder_ServerToClient(new(CallOrder)) echo := client.Echo(ctx, func(p testcapnp.Echoer_echo_Params) error { return p.SetCap(localCap) }) // This should not deadlock. _, err := echo.Struct() if err != nil { t.Error("Echo error:", err) } }
func TestPromisedCapability(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() p, q := pipetransport.New() if *logMessages { p = logtransport.New(nil, p) } c := rpc.NewConn(p) delay := make(chan struct{}) echoSrv := testcapnp.Echoer_ServerToClient(&DelayEchoer{delay: delay}) d := rpc.NewConn(q, rpc.MainInterface(echoSrv.Client)) defer d.Wait() defer c.Close() client := testcapnp.Echoer{Client: c.Bootstrap(ctx)} echo := client.Echo(ctx, func(p testcapnp.Echoer_echo_Params) error { return p.SetCap(testcapnp.CallOrder{Client: client.Client}) }) pipeline := echo.Cap() call0 := callseq(ctx, pipeline.Client, 0) call1 := callseq(ctx, pipeline.Client, 1) close(delay) check := func(promise testcapnp.CallOrder_getCallSequence_Results_Promise, n uint32) { r, err := promise.Struct() if err != nil { t.Errorf("call%d error: %v", n, err) } if r.N() != n { t.Errorf("call%d = %d; want %d", n, r.N(), n) } } check(call0, 0) check(call1, 1) }
func BenchmarkPingPong(b *testing.B) { p, q := pipetransport.New() if *logMessages { p = logtransport.New(nil, p) } log := testLogger{b} c := rpc.NewConn(p, rpc.ConnLog(log)) d := rpc.NewConn(q, rpc.ConnLog(log), rpc.BootstrapFunc(bootstrapPingPong)) defer d.Wait() defer c.Close() ctx, cancel := context.WithCancel(context.Background()) defer cancel() client := testcapnp.PingPong{Client: c.Bootstrap(ctx)} b.ResetTimer() for i := 0; i < b.N; i++ { promise := client.EchoNum(ctx, func(p testcapnp.PingPong_echoNum_Params) error { p.SetN(42) return nil }) result, err := promise.Struct() if err != nil { b.Errorf("EchoNum(42) failed on iteration %d: %v", i, err) break } if result.N() != 42 { b.Errorf("EchoNum(42) = %d; want 42", result.N()) break } } }
func newTestConn(t *testing.T, options ...rpc.ConnOption) (*rpc.Conn, rpc.Transport) { p, q := pipetransport.New() if *logMessages { p = logtransport.New(nil, p) } c := rpc.NewConn(p, options...) return c, q }
func newUnpairedConn(t *testing.T, options ...rpc.ConnOption) (*rpc.Conn, rpc.Transport) { p, q := pipetransport.New() if *logMessages { p = logtransport.New(nil, p) } newopts := make([]rpc.ConnOption, len(options), len(options)+1) copy(newopts, options) newopts = append(newopts, rpc.ConnLog(testLogger{t})) c := rpc.NewConn(p, newopts...) return c, q }
func TestEmbargo(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() p, q := pipetransport.New() if *logMessages { p = logtransport.New(nil, p) } log := testLogger{t} c := rpc.NewConn(p, rpc.ConnLog(log)) echoSrv := testcapnp.Echoer_ServerToClient(new(Echoer)) d := rpc.NewConn(q, rpc.MainInterface(echoSrv.Client), rpc.ConnLog(log)) defer d.Wait() defer c.Close() client := testcapnp.Echoer{Client: c.Bootstrap(ctx)} localCap := testcapnp.CallOrder_ServerToClient(new(CallOrder)) earlyCall := callseq(ctx, client.Client, 0) echo := client.Echo(ctx, func(p testcapnp.Echoer_echo_Params) error { return p.SetCap(localCap) }) pipeline := echo.Cap() call0 := callseq(ctx, pipeline.Client, 0) call1 := callseq(ctx, pipeline.Client, 1) _, err := earlyCall.Struct() if err != nil { t.Errorf("earlyCall error: %v", err) } call2 := callseq(ctx, pipeline.Client, 2) _, err = echo.Struct() if err != nil { t.Errorf("echo.Get() error: %v", err) } call3 := callseq(ctx, pipeline.Client, 3) call4 := callseq(ctx, pipeline.Client, 4) call5 := callseq(ctx, pipeline.Client, 5) check := func(promise testcapnp.CallOrder_getCallSequence_Results_Promise, n uint32) { r, err := promise.Struct() if err != nil { t.Errorf("call%d error: %v", n, err) } if r.N() != n { t.Errorf("call%d = %d; want %d", n, r.N(), n) } } check(call0, 0) check(call1, 1) check(call2, 2) check(call3, 3) check(call4, 4) check(call5, 5) }
func TestReleaseAlias(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() p, q := pipetransport.New() if *logMessages { p = logtransport.New(nil, p) } c := rpc.NewConn(p) hf := singletonHandleFactory() d := rpc.NewConn(q, rpc.MainInterface(testcapnp.HandleFactory_ServerToClient(hf).Client)) defer d.Wait() defer c.Close() client := testcapnp.HandleFactory{Client: c.Bootstrap(ctx)} r1, err := client.NewHandle(ctx, func(r testcapnp.HandleFactory_newHandle_Params) error { return nil }).Struct() if err != nil { t.Fatal("NewHandle #1:", err) } handle1 := r1.Handle() r2, err := client.NewHandle(ctx, func(r testcapnp.HandleFactory_newHandle_Params) error { return nil }).Struct() if err != nil { t.Fatal("NewHandle #2:", err) } handle2 := r2.Handle() if n := hf.numHandles(); n != 1 { t.Fatalf("after creation, numHandles = %d; want 1", n) } if err := handle1.Client.Close(); err != nil { t.Error("handle1.Client.Close():", err) } flushConn(ctx, c) if n := hf.numHandles(); n != 1 { t.Errorf("after handle1.Client.Close(), numHandles = %d; want 1", n) } if err := handle2.Client.Close(); err != nil { t.Error("handle2.Client.Close():", err) } flushConn(ctx, c) if n := hf.numHandles(); n != 0 { t.Errorf("after handle1.Close() and handle2.Close(), numHandles = %d; want 0", n) } }