From dddbdbfb5fe5f53567a71c4d24b5a4c12631b01a Mon Sep 17 00:00:00 2001 From: Alain Jobart Date: Thu, 6 Aug 2015 17:46:45 -0700 Subject: [PATCH] Adding unit tests for the go client. We don't need to fork vtgateclienttest, we can just execute it in process. The test cases are meant to be the blue print of all the client implementation unit tests. --- go/cmd/vtgateclienttest/goclient_test.go | 61 +++++++++++++++++++ .../vtgateclienttest/gorpc_goclient_test.go | 45 ++++++++++++++ go/cmd/vtgateclienttest/grpc_goclient_test.go | 37 +++++++++++ go/cmd/vtgateclienttest/main.go | 18 ++++-- 4 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 go/cmd/vtgateclienttest/goclient_test.go create mode 100644 go/cmd/vtgateclienttest/gorpc_goclient_test.go create mode 100644 go/cmd/vtgateclienttest/grpc_goclient_test.go diff --git a/go/cmd/vtgateclienttest/goclient_test.go b/go/cmd/vtgateclienttest/goclient_test.go new file mode 100644 index 0000000000..2db7636d77 --- /dev/null +++ b/go/cmd/vtgateclienttest/goclient_test.go @@ -0,0 +1,61 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "encoding/json" + "testing" + "time" + + "github.com/youtube/vitess/go/vt/callerid" + "github.com/youtube/vitess/go/vt/topo" + "github.com/youtube/vitess/go/vt/vtgate/vtgateconn" + "golang.org/x/net/context" +) + +// This file contains the reference test for clients. It tests +// all the corner cases of the API, and makes sure the go client +// is full featured. +// +// It can be used as a template by other languages for their test suites. +// +// TODO(team) add more unit test cases. + +// testCallerID adds a caller ID to a context, and makes sure the server +// gets it. +func testCallerID(t *testing.T, conn *vtgateconn.VTGateConn) { + t.Log("testCallerID") + ctx := context.Background() + callerID := callerid.NewEffectiveCallerID("test_principal", "test_component", "test_subcomponent") + ctx = callerid.NewContext(ctx, callerID, nil) + + data, err := json.Marshal(callerID) + if err != nil { + t.Errorf("failed to marshal callerid: %v", err) + return + } + query := callerIDPrefix + string(data) + + // test Execute forwards the callerID + if _, err := conn.Execute(ctx, query, nil, topo.TYPE_MASTER); err != nil { + t.Errorf("failed to pass callerid: %v", err) + } + + // FIXME(alainjobart) add all function calls +} + +func testGoClient(t *testing.T, protocol, addr string) { + // Create a client connecting to the server + ctx := context.Background() + conn, err := vtgateconn.DialProtocol(ctx, protocol, addr, 30*time.Second) + if err != nil { + t.Fatalf("dial failed: %v", err) + } + + testCallerID(t, conn) + + // and clean up + conn.Close() +} diff --git a/go/cmd/vtgateclienttest/gorpc_goclient_test.go b/go/cmd/vtgateclienttest/gorpc_goclient_test.go new file mode 100644 index 0000000000..11e7639320 --- /dev/null +++ b/go/cmd/vtgateclienttest/gorpc_goclient_test.go @@ -0,0 +1,45 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "net" + "net/http" + "testing" + + "github.com/youtube/vitess/go/rpcplus" + "github.com/youtube/vitess/go/rpcwrap/bsonrpc" + "github.com/youtube/vitess/go/vt/vtgate/gorpcvtgateservice" + + // import the gorpc client, it will register itself + _ "github.com/youtube/vitess/go/vt/vtgate/gorpcvtgateconn" +) + +// TestGoRPCGoClient tests the go client using goRPC +func TestGoRPCGoClient(t *testing.T) { + service := createService() + + // listen on a random port + listener, err := net.Listen("tcp", ":0") + if err != nil { + t.Fatalf("Cannot listen: %v", err) + } + defer listener.Close() + + // Create a Go Rpc server and listen on the port + server := rpcplus.NewServer() + server.Register(gorpcvtgateservice.New(service)) + + // create the HTTP server, serve the server from it + handler := http.NewServeMux() + bsonrpc.ServeCustomRPC(handler, server, false) + httpServer := http.Server{ + Handler: handler, + } + go httpServer.Serve(listener) + + // and run the test suite + testGoClient(t, "gorpc", listener.Addr().String()) +} diff --git a/go/cmd/vtgateclienttest/grpc_goclient_test.go b/go/cmd/vtgateclienttest/grpc_goclient_test.go new file mode 100644 index 0000000000..92b046afa6 --- /dev/null +++ b/go/cmd/vtgateclienttest/grpc_goclient_test.go @@ -0,0 +1,37 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "net" + "testing" + + "google.golang.org/grpc" + + "github.com/youtube/vitess/go/vt/vtgate/grpcvtgateservice" + + // import the grpc client, it will register itself + _ "github.com/youtube/vitess/go/vt/vtgate/grpcvtgateconn" +) + +// TestGRPCGoClient tests the go client using gRPC +func TestGRPCGoClient(t *testing.T) { + service := createService() + + // listen on a random port + listener, err := net.Listen("tcp", ":0") + if err != nil { + t.Fatalf("Cannot listen: %v", err) + } + defer listener.Close() + + // Create a gRPC server and listen on the port + server := grpc.NewServer() + grpcvtgateservice.RegisterForTest(server, service) + go server.Serve(listener) + + // and run the test suite + testGoClient(t, "grpc", listener.Addr().String()) +} diff --git a/go/cmd/vtgateclienttest/main.go b/go/cmd/vtgateclienttest/main.go index 42db938bb1..961a9f6e0a 100644 --- a/go/cmd/vtgateclienttest/main.go +++ b/go/cmd/vtgateclienttest/main.go @@ -13,12 +13,23 @@ import ( "github.com/youtube/vitess/go/exit" "github.com/youtube/vitess/go/vt/servenv" "github.com/youtube/vitess/go/vt/vtgate" + "github.com/youtube/vitess/go/vt/vtgate/vtgateservice" ) func init() { servenv.RegisterDefaultFlags() } +// createService creates the implementation chain of all the test cases +func createService() vtgateservice.VTGateService { + var s vtgateservice.VTGateService + s = newTerminalClient() + s = newSuccessClient(s) + s = newErrorClient(s) + s = newCallerIDClient(s) + return s +} + func main() { defer exit.Recover() @@ -26,12 +37,9 @@ func main() { servenv.Init() // The implementation chain. - c := newCallerIDClient( - newErrorClient( - newSuccessClient( - newTerminalClient()))) + s := createService() for _, f := range vtgate.RegisterVTGates { - f(c) + f(s) } servenv.RunDefault()