1// +build postgres 2 3package praefect 4 5import ( 6 "context" 7 "net" 8 "path/filepath" 9 "testing" 10 11 "github.com/stretchr/testify/require" 12 "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/config" 13 "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore" 14 "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/grpc-proxy/proxy" 15 "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/protoregistry" 16 "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" 17 "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" 18 "google.golang.org/grpc" 19 "google.golang.org/grpc/codes" 20 "google.golang.org/grpc/status" 21) 22 23func TestRepositoryExistsStreamInterceptor(t *testing.T) { 24 errServedByGitaly := status.Error(codes.Unknown, "request passed to Gitaly") 25 26 for _, tc := range []struct { 27 desc string 28 routeToGitaly bool 29 repository *gitalypb.Repository 30 response *gitalypb.RepositoryExistsResponse 31 error error 32 }{ 33 { 34 desc: "missing repository", 35 error: errMissingRepository, 36 }, 37 { 38 desc: "missing storage name", 39 repository: &gitalypb.Repository{RelativePath: "relative-path"}, 40 error: errMissingStorageName, 41 }, 42 { 43 desc: "missing relative path", 44 repository: &gitalypb.Repository{StorageName: "virtual-storage"}, 45 error: errMissingRelativePath, 46 }, 47 { 48 desc: "invalid virtual storage", 49 repository: &gitalypb.Repository{StorageName: "invalid virtual storage", RelativePath: "relative-path"}, 50 response: &gitalypb.RepositoryExistsResponse{Exists: false}, 51 }, 52 { 53 desc: "invalid relative path", 54 repository: &gitalypb.Repository{StorageName: "virtual-storage", RelativePath: "invalid relative path"}, 55 response: &gitalypb.RepositoryExistsResponse{Exists: false}, 56 }, 57 { 58 desc: "repository found", 59 repository: &gitalypb.Repository{StorageName: "virtual-storage", RelativePath: "relative-path"}, 60 response: &gitalypb.RepositoryExistsResponse{Exists: true}, 61 }, 62 { 63 desc: "routed to gitaly", 64 routeToGitaly: true, 65 error: errServedByGitaly, 66 }, 67 } { 68 t.Run(tc.desc, func(t *testing.T) { 69 db := getDB(t) 70 rs := datastore.NewPostgresRepositoryStore(db, map[string][]string{"virtual-storage": {"storage"}}) 71 72 ctx, cancel := testhelper.Context() 73 defer cancel() 74 75 require.NoError(t, rs.CreateRepository(ctx, "virtual-storage", "relative-path", "storage", nil, nil, false, false)) 76 77 electionStrategy := config.ElectionStrategyPerRepository 78 if tc.routeToGitaly { 79 electionStrategy = config.ElectionStrategySQL 80 } 81 82 tmp := testhelper.TempDir(t) 83 84 ln, err := net.Listen("unix", filepath.Join(tmp, "praefect")) 85 require.NoError(t, err) 86 87 srv := NewGRPCServer( 88 config.Config{ 89 Failover: config.Failover{ 90 ElectionStrategy: electionStrategy, 91 }, 92 }, 93 testhelper.DiscardTestEntry(t), 94 protoregistry.GitalyProtoPreregistered, 95 func(ctx context.Context, fullMethodName string, peeker proxy.StreamPeeker) (*proxy.StreamParameters, error) { 96 return nil, errServedByGitaly 97 }, 98 nil, 99 nil, 100 nil, 101 rs, 102 nil, 103 nil, 104 nil, 105 ) 106 defer srv.Stop() 107 108 go func() { srv.Serve(ln) }() 109 110 clientConn, err := grpc.DialContext(ctx, "unix://"+ln.Addr().String(), grpc.WithInsecure()) 111 require.NoError(t, err) 112 113 client := gitalypb.NewRepositoryServiceClient(clientConn) 114 _, err = client.RepositorySize(ctx, &gitalypb.RepositorySizeRequest{Repository: tc.repository}) 115 require.Equal(t, errServedByGitaly, err, "other RPCs should be passed through") 116 117 resp, err := client.RepositoryExists(ctx, &gitalypb.RepositoryExistsRequest{Repository: tc.repository}) 118 require.Equal(t, tc.error, err) 119 require.Equal(t, tc.response, resp) 120 }) 121 } 122} 123