diff --git a/client/binding_test.go b/client/binding_test.go new file mode 100644 index 0000000..1e89be9 --- /dev/null +++ b/client/binding_test.go @@ -0,0 +1,31 @@ +package client + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestInvokeBinding(t *testing.T) { + ctx := context.Background() + client, closer := getTestClient(ctx) + defer closer() + + mIn := make(map[string]string, 0) + mIn["test"] = "value" + + out, mOut, err := client.InvokeBinding(ctx, "serving", "EchoMethod", []byte("ping"), mIn) + assert.Nil(t, err) + assert.NotNil(t, mOut) + assert.NotNil(t, out) +} + +func TestInvokeOutputBinding(t *testing.T) { + ctx := context.Background() + client, closer := getTestClient(ctx) + defer closer() + + err := client.InvokeOutputBinding(ctx, "serving", "EchoMethod", []byte("ping")) + assert.Nil(t, err) +} diff --git a/client/client.go b/client/client.go index a76e7bb..169703b 100644 --- a/client/client.go +++ b/client/client.go @@ -57,12 +57,11 @@ func NewClientWithAddress(address string) (client *Client, err error) { } // NewClientWithConnection instantiates dapr client configured for the specific connection -func NewClientWithConnection(conn *grpc.ClientConn) (client *Client, err error) { - client = &Client{ +func NewClientWithConnection(conn *grpc.ClientConn) *Client { + return &Client{ connection: conn, protoClient: pb.NewDaprClient(conn), } - return } // Client is the dapr client diff --git a/client/client_test.go b/client/client_test.go index 34f8db3..0229d1d 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -5,8 +5,8 @@ import ( "net" "testing" - "github.com/golang/protobuf/ptypes/any" "github.com/golang/protobuf/ptypes/empty" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" "google.golang.org/grpc" @@ -16,35 +16,6 @@ import ( pb "github.com/dapr/go-sdk/dapr/proto/runtime/v1" ) -func getTestClient(ctx context.Context) (*Client, func()) { - buffer := 1024 * 1024 - listener := bufconn.Listen(buffer) - - s := grpc.NewServer() - pb.RegisterAppCallbackServer(s, &testServer{}) - go func() { - if err := s.Serve(listener); err != nil { - panic(err) - } - }() - - conn, _ := grpc.DialContext(ctx, "", grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { - return listener.Dial() - }), grpc.WithInsecure()) - - closer := func() { - listener.Close() - s.Stop() - } - - client, err := NewClientWithConnection(conn) - if err != nil { - panic(err) - } - - return client, closer -} - func TestNewClientWithConnection(t *testing.T) { ctx := context.Background() client, closer := getTestClient(ctx) @@ -60,45 +31,79 @@ func TestNewClientWithoutArgs(t *testing.T) { assert.NotNil(t, err) } -type testServer struct { -} +func getTestClient(ctx context.Context) (client *Client, closer func()) { + l := bufconn.Listen(1024 * 1024) + s := grpc.NewServer() -func (s *testServer) EchoMethod() string { - return "pong" -} - -func (s *testServer) OnInvoke(ctx context.Context, in *commonv1pb.InvokeRequest) (*commonv1pb.InvokeResponse, error) { - var response string - - switch in.Method { - case "EchoMethod": - response = s.EchoMethod() + server := &testDaprServer{ + state: make(map[string][]byte, 0), } - return &commonv1pb.InvokeResponse{ - ContentType: "text/plain; charset=UTF-8", - Data: &any.Any{Value: []byte(response)}, + pb.RegisterDaprServer(s, server) + go func() { + if err := s.Serve(l); err != nil { + panic(err) + } + }() + + d := grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { + return l.Dial() + }) + + c, _ := grpc.DialContext(ctx, "", d, grpc.WithInsecure()) + + closer = func() { + l.Close() + s.Stop() + } + + client = NewClientWithConnection(c) + return +} + +type testDaprServer struct { + state map[string][]byte +} + +func (s *testDaprServer) InvokeService(ctx context.Context, req *pb.InvokeServiceRequest) (*commonv1pb.InvokeResponse, error) { + r := &commonv1pb.InvokeResponse{ + ContentType: req.Message.ContentType, + Data: req.GetMessage().Data, + } + return r, nil +} + +func (s *testDaprServer) GetState(ctx context.Context, req *pb.GetStateRequest) (*pb.GetStateResponse, error) { + return &pb.GetStateResponse{ + Data: s.state[req.Key], + Etag: "v1", }, nil } -func (s *testServer) ListTopicSubscriptions(ctx context.Context, in *empty.Empty) (*pb.ListTopicSubscriptionsResponse, error) { - return &pb.ListTopicSubscriptionsResponse{ - Subscriptions: []*pb.TopicSubscription{ - {Topic: "TopicA"}, - }, - }, nil -} - -func (s *testServer) ListInputBindings(ctx context.Context, in *empty.Empty) (*pb.ListInputBindingsResponse, error) { - return &pb.ListInputBindingsResponse{ - Bindings: []string{"storage"}, - }, nil -} - -func (s *testServer) OnBindingEvent(ctx context.Context, in *pb.BindingEventRequest) (*pb.BindingEventResponse, error) { - return &pb.BindingEventResponse{}, nil -} - -func (s *testServer) OnTopicEvent(ctx context.Context, in *pb.TopicEventRequest) (*empty.Empty, error) { +func (s *testDaprServer) SaveState(ctx context.Context, req *pb.SaveStateRequest) (*empty.Empty, error) { + for _, item := range req.States { + s.state[item.Key] = item.Value + } return &empty.Empty{}, nil } + +func (s *testDaprServer) DeleteState(ctx context.Context, req *pb.DeleteStateRequest) (*empty.Empty, error) { + delete(s.state, req.Key) + return &empty.Empty{}, nil +} + +func (s *testDaprServer) PublishEvent(ctx context.Context, req *pb.PublishEventRequest) (*empty.Empty, error) { + return &empty.Empty{}, nil +} + +func (s *testDaprServer) InvokeBinding(ctx context.Context, req *pb.InvokeBindingRequest) (*pb.InvokeBindingResponse, error) { + r := &pb.InvokeBindingResponse{ + Data: req.Data, + Metadata: req.Metadata, + } + return r, nil +} + +func (s *testDaprServer) GetSecret(ctx context.Context, req *pb.GetSecretRequest) (*pb.GetSecretResponse, error) { + return nil, errors.New("method InvokeService not implemented") +} diff --git a/client/invoke_test.go b/client/invoke_test.go index c64a328..724eb0e 100644 --- a/client/invoke_test.go +++ b/client/invoke_test.go @@ -10,13 +10,21 @@ import ( func TestInvokeServiceWithContent(t *testing.T) { ctx := context.Background() client, closer := getTestClient(ctx) - assert.NotNil(t, closer) defer closer() - assert.NotNil(t, client) - // TODO: fails with rpc error: code = Unimplemented desc = unknown service dapr.proto.runtime.v1.Dapr - // resp, err := client.InvokeServiceWithContent(ctx, "serving", "EchoMethod", - // "text/plain; charset=UTF-8", []byte("ping")) - // assert.Nil(t, err) - // assert.NotNil(t, resp) + resp, err := client.InvokeServiceWithContent(ctx, "serving", "EchoMethod", + "text/plain; charset=UTF-8", []byte("ping")) + assert.Nil(t, err) + assert.NotNil(t, resp) + assert.Equal(t, string(resp), "ping") +} + +func TestInvokeService(t *testing.T) { + ctx := context.Background() + client, closer := getTestClient(ctx) + defer closer() + + resp, err := client.InvokeService(ctx, "serving", "EchoMethod") + assert.Nil(t, err) + assert.Nil(t, resp) } diff --git a/client/pubsub_test.go b/client/pubsub_test.go new file mode 100644 index 0000000..3e58d68 --- /dev/null +++ b/client/pubsub_test.go @@ -0,0 +1,17 @@ +package client + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPublishEvent(t *testing.T) { + ctx := context.Background() + client, closer := getTestClient(ctx) + defer closer() + + err := client.PublishEvent(ctx, "serving", []byte("ping")) + assert.Nil(t, err) +} diff --git a/client/state_test.go b/client/state_test.go index 46d755a..1653937 100644 --- a/client/state_test.go +++ b/client/state_test.go @@ -1,6 +1,7 @@ package client import ( + "context" "testing" "time" @@ -34,3 +35,22 @@ func TestStateOptionsConverter(t *testing.T) { assert.Equal(t, p.RetryPolicy.Interval.Seconds, int64(10)) assert.Equal(t, p.RetryPolicy.Pattern, v1.StateRetryPolicy_RETRY_EXPONENTIAL) } + +func TestSaveStateData(t *testing.T) { + ctx := context.Background() + data := "test" + client, closer := getTestClient(ctx) + defer closer() + + err := client.SaveStateData(ctx, "store", "key1", "", []byte(data)) + assert.Nil(t, err) + + out, etag, err := client.GetState(ctx, "store", "key1") + assert.Nil(t, err) + assert.NotEmpty(t, etag) + assert.NotNil(t, out) + assert.Equal(t, string(out), data) + + err = client.DeleteState(ctx, "store", "key1") + assert.Nil(t, err) +}