package transport import ( "context" "net" "strings" "testing" "time" pb "git.sendico.io/tech/sxchnge/notifications/interface/notifications/v1" "git.sendico.io/tech/sxchnge/notifications/model" "git.sendico.io/tech/sxchnge/shared/database/record" merrors "git.sendico.io/tech/sxchnge/shared/errors" "go.mongodb.org/mongo-driver/v2/bson" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/status" "google.golang.org/grpc/test/bufconn" ) type fakeAPI struct{} func (fakeAPI) Send(_ context.Context, caller string, r model.Request) (*model.Notification, error) { if caller != "product" { return nil, merrors.Unauthorized("missing caller") } return &model.Notification{Base: storable.Base{ID: bson.NewObjectID(), CreatedAt: time.Now(), UpdatedAt: time.Now()}, UserID: r.UserID, State: model.Queued, Email: model.Email{Address: r.Address, Text: "sensitive"}, ExpiresAt: time.Now().Add(time.Hour)}, nil } func (fakeAPI) Get(context.Context, string, string) (*model.Notification, error) { return nil, merrors.NoData("private details") } func TestGRPCWithoutAuthenticationAndMapping(t *testing.T) { listener := bufconn.Listen(1 << 20) server := grpc.NewServer() pb.RegisterNotificationsServiceServer(server, New(fakeAPI{})) go func() { _ = server.Serve(listener) }() defer server.Stop() conn, err := grpc.NewClient("passthrough:///buf", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { return listener.Dial() })) if err != nil { t.Fatal(err) } defer conn.Close() client := pb.NewNotificationsServiceClient(conn) req := &pb.SendRequest{UserId: "u", Targets: []*pb.Target{{Destination: &pb.Target_Email{Email: &pb.EmailTarget{Address: "user@example.com"}}}}} ctx := context.Background() result, err := client.Send(ctx, req) if err != nil { t.Fatal(err) } if result.Notification.UserId != "u" || strings.Contains(result.String(), "sensitive") || strings.Contains(result.String(), "user@example.com") { t.Fatal(result) } req.Targets[0].Destination = &pb.Target_Telegram{Telegram: &pb.TelegramTarget{ChatId: "123"}} if _, err = client.Send(ctx, req); status.Code(err) != codes.Unimplemented { t.Fatal(err) } if _, err = client.Get(ctx, &pb.GetRequest{Id: "id"}); status.Code(err) != codes.NotFound { t.Fatal(err) } } func TestCancellationStatus(t *testing.T) { if status.Code(rpcError(merrors.OpaqueWrap(merrors.ErrServiceUnavailable, context.Canceled, "storage"))) != codes.Canceled { t.Fatal("cancellation lost at transport boundary") } if status.Code(rpcError(context.DeadlineExceeded)) != codes.DeadlineExceeded { t.Fatal("deadline lost at transport boundary") } }