diff --git a/internal/e2e/cli_client_test.go b/internal/e2e/cli_client_test.go index 9abe696b0..323ee8425 100644 --- a/internal/e2e/cli_client_test.go +++ b/internal/e2e/cli_client_test.go @@ -12,12 +12,13 @@ import ( "testing" "time" - "github.com/ory/herodot" - "github.com/ory/x/cmdx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" grpcHealthV1 "google.golang.org/grpc/health/grpc_health_v1" + "github.com/ory/herodot" + "github.com/ory/x/cmdx" + gprclient "github.com/ory/keto/cmd/client" cliexpand "github.com/ory/keto/cmd/expand" clirelationtuple "github.com/ory/keto/cmd/relationtuple" @@ -30,19 +31,19 @@ type cliClient struct { c *cmdx.CommandExecuter } -func (g *cliClient) queryNamespaces(t *testing.T) (res ketoapi.GetNamespacesResponse) { +func (g *cliClient) queryNamespaces(t testing.TB) (res ketoapi.GetNamespacesResponse) { t.Skip("not implemented for the CLI") return } var _ client = (*cliClient)(nil) -func (g *cliClient) oplCheckSyntax(t *testing.T, _ []byte) []*ketoapi.ParseError { +func (g *cliClient) oplCheckSyntax(t testing.TB, content []byte) []*ketoapi.ParseError { t.Skip("not implemented as a command yet") return []*ketoapi.ParseError{} } -func (g *cliClient) createTuple(t *testing.T, r *ketoapi.RelationTuple) { +func (g *cliClient) createTuple(t testing.TB, r *ketoapi.RelationTuple) { tupleEnc, err := json.Marshal(r) require.NoError(t, err) @@ -78,7 +79,7 @@ func (g *cliClient) assembleQueryFlags(q *ketoapi.RelationQuery, opts []x.Pagina return flags } -func (g *cliClient) queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { +func (g *cliClient) queryTuple(t testing.TB, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { out := g.c.ExecNoErr(t, append(g.assembleQueryFlags(q, opts), "relation-tuple", "get")...) var resp ketoapi.GetResponse @@ -87,13 +88,13 @@ func (g *cliClient) queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ...x return &resp } -func (g *cliClient) queryTupleErr(t *testing.T, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { +func (g *cliClient) queryTupleErr(t testing.TB, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { stdErr := g.c.ExecExpectedErr(t, append(g.assembleQueryFlags(q, opts), "relation-tuple", "get")...) assert.Contains(t, stdErr, expected.GRPCCodeField.String()) assert.Contains(t, stdErr, expected.Error()) } -func (g *cliClient) check(t *testing.T, r *ketoapi.RelationTuple) bool { +func (g *cliClient) check(t testing.TB, r *ketoapi.RelationTuple) bool { var sub string if r.SubjectID != nil { sub = *r.SubjectID @@ -106,23 +107,23 @@ func (g *cliClient) check(t *testing.T, r *ketoapi.RelationTuple) bool { return res.Allowed } -func (g *cliClient) batchCheckErr(t *testing.T, requestTuples []*ketoapi.RelationTuple, expected herodot.DefaultError) { +func (g *cliClient) batchCheckErr(t testing.TB, requestTuples []*ketoapi.RelationTuple, expected herodot.DefaultError) { t.Skip("not implemented for the CLI") } -func (g *cliClient) batchCheck(t *testing.T, requestTuples []*ketoapi.RelationTuple) []checkResponse { +func (g *cliClient) batchCheck(t testing.TB, r []*ketoapi.RelationTuple) []checkResponse { t.Skip("not implemented for the CLI") return nil } -func (g *cliClient) expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { +func (g *cliClient) expand(t testing.TB, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { out := g.c.ExecNoErr(t, "expand", r.Relation, r.Namespace, r.Object, "--"+cliexpand.FlagMaxDepth, fmt.Sprintf("%d", depth), "--"+cmdx.FlagFormat, string(cmdx.FormatJSON)) res := ketoapi.Tree[*ketoapi.RelationTuple]{} require.NoError(t, json.Unmarshal([]byte(out), &res)) return &res } -func (g *cliClient) waitUntilLive(t *testing.T) { +func (g *cliClient) waitUntilLive(t testing.TB) { flags := make([]string, len(g.c.PersistentArgs)) copy(flags, g.c.PersistentArgs) @@ -140,7 +141,7 @@ func (g *cliClient) waitUntilLive(t *testing.T) { require.Equal(t, grpcHealthV1.HealthCheckResponse_SERVING.String()+"\n", out) } -func (g *cliClient) deleteTuple(t *testing.T, r *ketoapi.RelationTuple) { +func (g *cliClient) deleteTuple(t testing.TB, r *ketoapi.RelationTuple) { tupleEnc, err := json.Marshal(r) require.NoError(t, err) @@ -149,6 +150,6 @@ func (g *cliClient) deleteTuple(t *testing.T, r *ketoapi.RelationTuple) { assert.Len(t, stderr, 0, stdout) } -func (g *cliClient) deleteAllTuples(t *testing.T, q *ketoapi.RelationQuery) { +func (g *cliClient) deleteAllTuples(t testing.TB, q *ketoapi.RelationQuery) { _ = g.c.ExecNoErr(t, append(g.assembleQueryFlags(q, nil), "relation-tuple", "delete-all", "--force")...) } diff --git a/internal/e2e/e2e_benchmark_test.go b/internal/e2e/e2e_benchmark_test.go new file mode 100644 index 000000000..1cd7d8ecc --- /dev/null +++ b/internal/e2e/e2e_benchmark_test.go @@ -0,0 +1,76 @@ +package e2e + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/ory/keto/internal/namespace" + "github.com/ory/keto/internal/x/dbx" + "github.com/ory/keto/ketoapi" + "github.com/ory/x/pointerx" +) + +func BenchmarkE2E(b *testing.B) { + + dsn := dbx.GetSqlite(b, dbx.SQLiteMemory) + ctx, reg, namespaceTestMgr, getAddr := newInitializedReg(b, dsn, map[string]interface{}{"log.level": "panic"}) + closeServer := startServer(ctx, b, reg) + b.Cleanup(closeServer) + + _, _, readAddr := getAddr(b, "read") + _, _, writeAddr := getAddr(b, "write") + _, _, oplAddr := getAddr(b, "opl") + + for _, cl := range []client{ + newGrpcClient(b, ctx, + readAddr, + writeAddr, + oplAddr, + ), + &restClient{ + readURL: "http://" + readAddr, + writeURL: "http://" + writeAddr, + oplSyntaxURL: "http://" + oplAddr, + }, + &sdkClient{ + readRemote: readAddr, + writeRemote: writeAddr, + syntaxRemote: oplAddr, + }, + } { + + b.Run(fmt.Sprintf("client=%T", cl), func(b *testing.B) { + n := &namespace.Namespace{Name: "test"} + namespaceTestMgr.add(b, n) + cl.waitUntilLive(b) + b.ResetTimer() + for i := 0; i < b.N; i++ { + tuple := &ketoapi.RelationTuple{ + Namespace: n.Name, + Object: fmt.Sprintf("object %d for client %T", i, cl), + Relation: "access", + SubjectID: pointerx.Ptr("client"), + } + cl.createTuple(b, tuple) + + resp := cl.queryTuple(b, &ketoapi.RelationQuery{Namespace: &tuple.Namespace}) + require.Len(b, resp.RelationTuples, 1) + assert.Equal(b, tuple, resp.RelationTuples[0]) + + assert.True(b, cl.check(b, tuple)) + batchResult := cl.batchCheck(b, []*ketoapi.RelationTuple{tuple}) + require.Len(b, batchResult, 1) + assert.True(b, batchResult[0].allowed) + assert.Empty(b, batchResult[0].errorMessage) + + cl.deleteTuple(b, tuple) + resp = cl.queryTuple(b, &ketoapi.RelationQuery{Namespace: &tuple.Namespace}) + require.Len(b, resp.RelationTuples, 0) + } + }) + } + +} diff --git a/internal/e2e/full_suit_test.go b/internal/e2e/full_suit_test.go index d16eeac49..3e5af4b18 100644 --- a/internal/e2e/full_suit_test.go +++ b/internal/e2e/full_suit_test.go @@ -10,13 +10,14 @@ import ( "testing" "time" - "github.com/ory/herodot" - "github.com/ory/x/cmdx" - prometheus "github.com/ory/x/prometheusx" "github.com/spf13/cobra" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/ory/herodot" + "github.com/ory/x/cmdx" + prometheus "github.com/ory/x/prometheusx" + "github.com/ory/keto/cmd" cliclient "github.com/ory/keto/cmd/client" "github.com/ory/keto/internal/relationtuple" @@ -28,21 +29,21 @@ import ( type ( transactClient interface { client - transactTuples(t *testing.T, ins []*ketoapi.RelationTuple, del []*ketoapi.RelationTuple) + transactTuples(t testing.TB, ins []*ketoapi.RelationTuple, del []*ketoapi.RelationTuple) } client interface { - createTuple(t *testing.T, r *ketoapi.RelationTuple) - deleteTuple(t *testing.T, r *ketoapi.RelationTuple) - deleteAllTuples(t *testing.T, q *ketoapi.RelationQuery) - queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse - queryTupleErr(t *testing.T, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) - check(t *testing.T, r *ketoapi.RelationTuple) bool - batchCheck(t *testing.T, r []*ketoapi.RelationTuple) []checkResponse - batchCheckErr(t *testing.T, requestTuples []*ketoapi.RelationTuple, expected herodot.DefaultError) - expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] - oplCheckSyntax(t *testing.T, content []byte) []*ketoapi.ParseError - waitUntilLive(t *testing.T) - queryNamespaces(t *testing.T) ketoapi.GetNamespacesResponse + createTuple(t testing.TB, r *ketoapi.RelationTuple) + deleteTuple(t testing.TB, r *ketoapi.RelationTuple) + deleteAllTuples(t testing.TB, q *ketoapi.RelationQuery) + queryTuple(t testing.TB, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse + queryTupleErr(t testing.TB, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) + check(t testing.TB, r *ketoapi.RelationTuple) bool + batchCheck(t testing.TB, r []*ketoapi.RelationTuple) []checkResponse + batchCheckErr(t testing.TB, requestTuples []*ketoapi.RelationTuple, expected herodot.DefaultError) + expand(t testing.TB, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] + oplCheckSyntax(t testing.TB, content []byte) []*ketoapi.ParseError + waitUntilLive(t testing.TB) + queryNamespaces(t testing.TB) ketoapi.GetNamespacesResponse } ) diff --git a/internal/e2e/grpc_client_test.go b/internal/e2e/grpc_client_test.go index 8f09994d6..448358dab 100644 --- a/internal/e2e/grpc_client_test.go +++ b/internal/e2e/grpc_client_test.go @@ -14,7 +14,6 @@ import ( rts "github.com/ory/keto/proto/ory/keto/relation_tuples/v1alpha2" - "github.com/ory/herodot" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" @@ -22,6 +21,8 @@ import ( grpcHealthV1 "google.golang.org/grpc/health/grpc_health_v1" "google.golang.org/grpc/status" + "github.com/ory/herodot" + "github.com/ory/keto/internal/x" ) @@ -30,7 +31,7 @@ type grpcClient struct { ctx context.Context } -func newGrpcClient(t *testing.T, ctx context.Context, readRemote, writeRemote, oplSyntaxRemote string) *grpcClient { +func newGrpcClient(t testing.TB, ctx context.Context, readRemote, writeRemote, oplSyntaxRemote string) *grpcClient { read, err := grpc.NewClient(readRemote, grpc.WithTransportCredentials(insecure.NewCredentials())) require.NoError(t, err) t.Cleanup(func() { read.Close() }) @@ -54,7 +55,7 @@ func newGrpcClient(t *testing.T, ctx context.Context, readRemote, writeRemote, o } } -func (g *grpcClient) queryNamespaces(t *testing.T) (apiResponse ketoapi.GetNamespacesResponse) { +func (g *grpcClient) queryNamespaces(t testing.TB) (apiResponse ketoapi.GetNamespacesResponse) { client := rts.NewNamespacesServiceClient(g.read) res, err := client.ListNamespaces(g.ctx, &rts.ListNamespacesRequest{}) require.NoError(t, err) @@ -65,7 +66,7 @@ func (g *grpcClient) queryNamespaces(t *testing.T) (apiResponse ketoapi.GetNames var _ transactClient = (*grpcClient)(nil) -func (g *grpcClient) createTuple(t *testing.T, r *ketoapi.RelationTuple) { +func (g *grpcClient) createTuple(t testing.TB, r *ketoapi.RelationTuple) { g.transactTuples(t, []*ketoapi.RelationTuple{r}, nil) } @@ -83,7 +84,7 @@ func (*grpcClient) createQuery(q *ketoapi.RelationQuery) *rts.RelationQuery { return query } -func (g *grpcClient) queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { +func (g *grpcClient) queryTuple(t testing.TB, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { c := rts.NewReadServiceClient(g.read) pagination := x.GetPaginationOptions(opts...) @@ -106,7 +107,7 @@ func (g *grpcClient) queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ... } } -func (g *grpcClient) queryTupleErr(t *testing.T, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { +func (g *grpcClient) queryTupleErr(t testing.TB, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { c := rts.NewReadServiceClient(g.read) pagination := x.GetPaginationOptions(opts...) @@ -121,7 +122,7 @@ func (g *grpcClient) queryTupleErr(t *testing.T, expected herodot.DefaultError, assert.Equal(t, expected.GRPCCodeField, s.Code(), "%+v", err) } -func (g *grpcClient) check(t *testing.T, r *ketoapi.RelationTuple) bool { +func (g *grpcClient) check(t testing.TB, r *ketoapi.RelationTuple) bool { c := rts.NewCheckServiceClient(g.read) req := &rts.CheckRequest{ @@ -147,8 +148,7 @@ type checkResponse struct { errorMessage string } -func (g *grpcClient) batchCheckErr(t *testing.T, requestTuples []*ketoapi.RelationTuple, - expected herodot.DefaultError) { +func (g *grpcClient) batchCheckErr(t testing.TB, requestTuples []*ketoapi.RelationTuple, expected herodot.DefaultError) { _, err := g.doBatchCheck(t, requestTuples) require.Error(t, err) @@ -158,7 +158,7 @@ func (g *grpcClient) batchCheckErr(t *testing.T, requestTuples []*ketoapi.Relati assert.Contains(t, s.Message(), expected.Reason()) } -func (g *grpcClient) batchCheck(t *testing.T, requestTuples []*ketoapi.RelationTuple) []checkResponse { +func (g *grpcClient) batchCheck(t testing.TB, requestTuples []*ketoapi.RelationTuple) []checkResponse { resp, err := g.doBatchCheck(t, requestTuples) require.NoError(t, err) @@ -173,7 +173,7 @@ func (g *grpcClient) batchCheck(t *testing.T, requestTuples []*ketoapi.RelationT return checkResponses } -func (g *grpcClient) doBatchCheck(_ *testing.T, requestTuples []*ketoapi.RelationTuple) (*rts.BatchCheckResponse, error) { +func (g *grpcClient) doBatchCheck(_ testing.TB, requestTuples []*ketoapi.RelationTuple) (*rts.BatchCheckResponse, error) { c := rts.NewCheckServiceClient(g.read) @@ -199,7 +199,7 @@ func (g *grpcClient) doBatchCheck(_ *testing.T, requestTuples []*ketoapi.Relatio return c.BatchCheck(g.ctx, req) } -func (g *grpcClient) expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { +func (g *grpcClient) expand(t testing.TB, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { c := rts.NewExpandServiceClient(g.read) resp, err := c.Expand(g.ctx, &rts.ExpandRequest{ @@ -211,7 +211,7 @@ func (g *grpcClient) expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *ket return ketoapi.TreeFromProto[*ketoapi.RelationTuple](resp.Tree) } -func (g *grpcClient) waitUntilLive(t *testing.T) { +func (g *grpcClient) waitUntilLive(t testing.TB) { require.EventuallyWithT(t, func(t *assert.CollectT) { c := grpcHealthV1.NewHealthClient(g.read) @@ -221,11 +221,11 @@ func (g *grpcClient) waitUntilLive(t *testing.T) { }, 2*time.Second, 10*time.Millisecond) } -func (g *grpcClient) deleteTuple(t *testing.T, r *ketoapi.RelationTuple) { +func (g *grpcClient) deleteTuple(t testing.TB, r *ketoapi.RelationTuple) { g.transactTuples(t, nil, []*ketoapi.RelationTuple{r}) } -func (g *grpcClient) deleteAllTuples(t *testing.T, q *ketoapi.RelationQuery) { +func (g *grpcClient) deleteAllTuples(t testing.TB, q *ketoapi.RelationQuery) { c := rts.NewWriteServiceClient(g.write) query := &rts.RelationQuery{ Namespace: q.Namespace, @@ -244,7 +244,7 @@ func (g *grpcClient) deleteAllTuples(t *testing.T, q *ketoapi.RelationQuery) { require.NoError(t, err) } -func (g *grpcClient) transactTuples(t *testing.T, ins []*ketoapi.RelationTuple, del []*ketoapi.RelationTuple) { +func (g *grpcClient) transactTuples(t testing.TB, ins []*ketoapi.RelationTuple, del []*ketoapi.RelationTuple) { c := rts.NewWriteServiceClient(g.write) deltas := make([]*rts.RelationTupleDelta, len(ins)+len(del)) @@ -268,7 +268,7 @@ func (g *grpcClient) transactTuples(t *testing.T, ins []*ketoapi.RelationTuple, require.NoError(t, err) } -func (g *grpcClient) oplCheckSyntax(t *testing.T, content []byte) (parseErrors []*ketoapi.ParseError) { +func (g *grpcClient) oplCheckSyntax(t testing.TB, content []byte) (parseErrors []*ketoapi.ParseError) { c := opl.NewSyntaxServiceClient(g.oplSyntax) res, err := c.Check(g.ctx, &opl.CheckRequest{Content: content}) diff --git a/internal/e2e/helpers.go b/internal/e2e/helpers.go index cd175f92f..30dc345b6 100644 --- a/internal/e2e/helpers.go +++ b/internal/e2e/helpers.go @@ -14,9 +14,10 @@ import ( "github.com/stretchr/testify/assert" - "github.com/ory/x/configx" "github.com/spf13/pflag" + "github.com/ory/x/configx" + "github.com/ory/keto/internal/driver/config" "github.com/ory/keto/internal/namespace" @@ -32,7 +33,7 @@ type namespaceTestManager struct { nspaces []*namespace.Namespace } -func (m *namespaceTestManager) add(t *testing.T, nn ...*namespace.Namespace) { +func (m *namespaceTestManager) add(t testing.TB, nn ...*namespace.Namespace) { m.nspaces = append(m.nspaces, nn...) require.NoError(t, m.reg.Config(m.ctx).Set(config.KeyNamespaces, m.nspaces)) diff --git a/internal/e2e/rest_client_test.go b/internal/e2e/rest_client_test.go index d92f47cd9..0736d5bae 100644 --- a/internal/e2e/rest_client_test.go +++ b/internal/e2e/rest_client_test.go @@ -13,12 +13,13 @@ import ( "testing" "time" - "github.com/ory/herodot" - "github.com/ory/x/healthx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + "github.com/ory/herodot" + "github.com/ory/x/healthx" + "github.com/ory/keto/internal/check" "github.com/ory/keto/internal/expand" client2 "github.com/ory/keto/internal/httpclient" @@ -34,7 +35,7 @@ type restClient struct { readURL, writeURL, oplSyntaxURL string } -func (rc *restClient) queryNamespaces(t *testing.T) (res ketoapi.GetNamespacesResponse) { +func (rc *restClient) queryNamespaces(t testing.TB) (res ketoapi.GetNamespacesResponse) { body, code := rc.makeRequest(t, http.MethodGet, "/namespaces", "", rc.readURL) assert.Equal(t, http.StatusOK, code, body) require.NoError(t, json.Unmarshal([]byte(body), &res)) @@ -42,7 +43,7 @@ func (rc *restClient) queryNamespaces(t *testing.T) (res ketoapi.GetNamespacesRe return } -func (rc *restClient) oplCheckSyntax(t *testing.T, content []byte) []*ketoapi.ParseError { +func (rc *restClient) oplCheckSyntax(t testing.TB, content []byte) []*ketoapi.ParseError { body, code := rc.makeRequest(t, http.MethodPost, schema.RouteBase, string(content), rc.oplSyntaxURL) assert.Equal(t, http.StatusOK, code, body) var response ketoapi.CheckOPLSyntaxResponse @@ -51,7 +52,7 @@ func (rc *restClient) oplCheckSyntax(t *testing.T, content []byte) []*ketoapi.Pa return response.Errors } -func (rc *restClient) makeRequest(t *testing.T, method, path, body string, baseURL string) (string, int) { +func (rc *restClient) makeRequest(t testing.TB, method, path, body string, baseURL string) (string, int) { var b io.Reader if body != "" { b = bytes.NewBufferString(body) @@ -69,7 +70,7 @@ func (rc *restClient) makeRequest(t *testing.T, method, path, body string, baseU return string(respBody), resp.StatusCode } -func (rc *restClient) createTuple(t *testing.T, r *ketoapi.RelationTuple) { +func (rc *restClient) createTuple(t testing.TB, r *ketoapi.RelationTuple) { tEnc, err := json.Marshal(r) require.NoError(t, err) @@ -77,17 +78,17 @@ func (rc *restClient) createTuple(t *testing.T, r *ketoapi.RelationTuple) { assert.Equal(t, http.StatusCreated, code, body) } -func (rc *restClient) deleteTuple(t *testing.T, r *ketoapi.RelationTuple) { +func (rc *restClient) deleteTuple(t testing.TB, r *ketoapi.RelationTuple) { body, code := rc.makeRequest(t, http.MethodDelete, relationtuple.WriteRouteBase+"?"+r.ToURLQuery().Encode(), "", rc.writeURL) require.Equal(t, http.StatusNoContent, code, body) } -func (rc *restClient) deleteAllTuples(t *testing.T, q *ketoapi.RelationQuery) { +func (rc *restClient) deleteAllTuples(t testing.TB, q *ketoapi.RelationQuery) { body, code := rc.makeRequest(t, http.MethodDelete, relationtuple.WriteRouteBase+"?"+q.ToURLQuery().Encode(), "", rc.writeURL) require.Equal(t, http.StatusNoContent, code, body) } -func (rc *restClient) queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { +func (rc *restClient) queryTuple(t testing.TB, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { urlQuery := q.ToURLQuery() pagination := x.GetPaginationOptions(opts...) @@ -107,7 +108,7 @@ func (rc *restClient) queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts .. return &dec } -func (rc *restClient) queryTupleErr(t *testing.T, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { +func (rc *restClient) queryTupleErr(t testing.TB, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { urlQuery := q.ToURLQuery() pagination := x.GetPaginationOptions(opts...) @@ -126,7 +127,7 @@ func (rc *restClient) queryTupleErr(t *testing.T, expected herodot.DefaultError, assert.Equal(t, expected.Error(), gjson.Get(body, "error.message").String(), body) } -func (rc *restClient) check(t *testing.T, r *ketoapi.RelationTuple) bool { +func (rc *restClient) check(t testing.TB, r *ketoapi.RelationTuple) bool { q := r.ToURLQuery() bodyGet, codeGet := rc.makeRequest(t, http.MethodGet, fmt.Sprintf("%s?%s", check.RouteBase, q.Encode()), "", rc.readURL) @@ -153,8 +154,7 @@ func (rc *restClient) check(t *testing.T, r *ketoapi.RelationTuple) bool { return false } -func (rc *restClient) batchCheckErr(t *testing.T, requestTuples []*ketoapi.RelationTuple, - expected herodot.DefaultError) { +func (rc *restClient) batchCheckErr(t testing.TB, requestTuples []*ketoapi.RelationTuple, expected herodot.DefaultError) { req := client2.BatchCheckPermissionBody{ Tuples: tuplesToRelationships(requestTuples), @@ -166,7 +166,7 @@ func (rc *restClient) batchCheckErr(t *testing.T, requestTuples []*ketoapi.Relat assert.Contains(t, body, expected.Reason()) } -func (rc *restClient) batchCheck(t *testing.T, requestTuples []*ketoapi.RelationTuple) []checkResponse { +func (rc *restClient) batchCheck(t testing.TB, requestTuples []*ketoapi.RelationTuple) []checkResponse { req := client2.BatchCheckPermissionBody{ Tuples: tuplesToRelationships(requestTuples), } @@ -188,7 +188,7 @@ func (rc *restClient) batchCheck(t *testing.T, requestTuples []*ketoapi.Relation return responseChecks } -func (rc *restClient) expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { +func (rc *restClient) expand(t testing.TB, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { query := r.ToURLQuery() query.Set("max-depth", fmt.Sprintf("%d", depth)) @@ -201,7 +201,7 @@ func (rc *restClient) expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *ke return tree } -func healthReady(t *testing.T, readURL string) bool { +func healthReady(t testing.TB, readURL string) bool { req, err := http.NewRequest("GET", readURL+healthx.ReadyCheckPath, nil) require.NoError(t, err) resp, err := http.DefaultClient.Do(req) @@ -212,7 +212,7 @@ func healthReady(t *testing.T, readURL string) bool { return resp.StatusCode == http.StatusOK } -func (rc *restClient) waitUntilLive(t *testing.T) { +func (rc *restClient) waitUntilLive(t testing.TB) { // wait for /health/ready for !healthReady(t, rc.readURL) { time.Sleep(10 * time.Millisecond) diff --git a/internal/e2e/sdk_client_test.go b/internal/e2e/sdk_client_test.go index 4274ad67b..0be15d221 100644 --- a/internal/e2e/sdk_client_test.go +++ b/internal/e2e/sdk_client_test.go @@ -10,11 +10,12 @@ import ( "testing" "time" - "github.com/ory/herodot" - "github.com/ory/x/pointerx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/ory/herodot" + "github.com/ory/x/pointerx" + httpclient "github.com/ory/keto/internal/httpclient" "github.com/ory/keto/internal/x" "github.com/ory/keto/ketoapi" @@ -31,13 +32,13 @@ var _ client = (*sdkClient)(nil) var requestTimeout = 5 * time.Second -func (c *sdkClient) requestCtx(t *testing.T) context.Context { +func (c *sdkClient) requestCtx(t testing.TB) context.Context { ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) t.Cleanup(cancel) return ctx } -func (c *sdkClient) oplCheckSyntax(t *testing.T, content []byte) (parseErrors []*ketoapi.ParseError) { +func (c *sdkClient) oplCheckSyntax(t testing.TB, content []byte) (parseErrors []*ketoapi.ParseError) { res, _, err := c.getOPLSyntaxClient(). RelationshipApi. CheckOplSyntax(c.requestCtx(t)). @@ -83,7 +84,7 @@ func (c *sdkClient) getOPLSyntaxClient() *httpclient.APIClient { return c.sc } -func (c *sdkClient) createTuple(t *testing.T, r *ketoapi.RelationTuple) { +func (c *sdkClient) createTuple(t testing.TB, r *ketoapi.RelationTuple) { payload := httpclient.CreateRelationshipBody{ Namespace: pointerx.Ptr(r.Namespace), Object: pointerx.Ptr(r.Object), @@ -123,7 +124,7 @@ func withSubject[P interface { return params } -func (c *sdkClient) deleteTuple(t *testing.T, r *ketoapi.RelationTuple) { +func (c *sdkClient) deleteTuple(t testing.TB, r *ketoapi.RelationTuple) { request := c.getWriteClient().RelationshipApi. DeleteRelationships(c.requestCtx(t)). Namespace(r.Namespace). @@ -135,7 +136,7 @@ func (c *sdkClient) deleteTuple(t *testing.T, r *ketoapi.RelationTuple) { require.NoError(t, err) } -func (c *sdkClient) deleteAllTuples(t *testing.T, q *ketoapi.RelationQuery) { +func (c *sdkClient) deleteAllTuples(t testing.TB, q *ketoapi.RelationQuery) { request := c.getWriteClient().RelationshipApi.DeleteRelationships(c.requestCtx(t)) if q.Namespace != nil { request = request.Namespace(*q.Namespace) @@ -182,7 +183,7 @@ func compileParams(req httpclient.RelationshipApiApiGetRelationshipsRequest, q * return req } -func (c *sdkClient) queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { +func (c *sdkClient) queryTuple(t testing.TB, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) *ketoapi.GetResponse { request := c.getReadClient().RelationshipApi.GetRelationships(c.requestCtx(t)) request = compileParams(request, q, opts) @@ -214,7 +215,7 @@ func (c *sdkClient) queryTuple(t *testing.T, q *ketoapi.RelationQuery, opts ...x return getResp } -func (c *sdkClient) queryTupleErr(t *testing.T, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { +func (c *sdkClient) queryTupleErr(t testing.TB, expected herodot.DefaultError, q *ketoapi.RelationQuery, opts ...x.PaginationOptionSetter) { request := c.getReadClient().RelationshipApi.GetRelationships(c.requestCtx(t)) request = compileParams(request, q, opts) _, _, err := request.Execute() @@ -229,7 +230,7 @@ func (c *sdkClient) queryTupleErr(t *testing.T, expected herodot.DefaultError, q } } -func (c *sdkClient) check(t *testing.T, r *ketoapi.RelationTuple) bool { +func (c *sdkClient) check(t testing.TB, r *ketoapi.RelationTuple) bool { request := c.getReadClient().PermissionApi.CheckPermission(c.requestCtx(t)). Namespace(r.Namespace). Object(r.Object). @@ -242,7 +243,7 @@ func (c *sdkClient) check(t *testing.T, r *ketoapi.RelationTuple) bool { return resp.GetAllowed() } -func (c *sdkClient) batchCheckErr(t *testing.T, requestTuples []*ketoapi.RelationTuple, expected herodot.DefaultError) { +func (c *sdkClient) batchCheckErr(t testing.TB, requestTuples []*ketoapi.RelationTuple, expected herodot.DefaultError) { request := c.getReadClient().PermissionApi.BatchCheckPermission(c.requestCtx(t)). BatchCheckPermissionBody(httpclient.BatchCheckPermissionBody{ @@ -260,7 +261,7 @@ func (c *sdkClient) batchCheckErr(t *testing.T, requestTuples []*ketoapi.Relatio } } -func (c *sdkClient) batchCheck(t *testing.T, requestTuples []*ketoapi.RelationTuple) []checkResponse { +func (c *sdkClient) batchCheck(t testing.TB, requestTuples []*ketoapi.RelationTuple) []checkResponse { request := c.getReadClient().PermissionApi.BatchCheckPermission(c.requestCtx(t)). BatchCheckPermissionBody(httpclient.BatchCheckPermissionBody{ Tuples: tuplesToRelationships(requestTuples), @@ -304,7 +305,7 @@ func tuplesToRelationships(tuples []*ketoapi.RelationTuple) []httpclient.Relatio return relationships } -func buildTree(t *testing.T, mt *httpclient.ExpandedPermissionTree) *ketoapi.Tree[*ketoapi.RelationTuple] { +func buildTree(t testing.TB, mt *httpclient.ExpandedPermissionTree) *ketoapi.Tree[*ketoapi.RelationTuple] { result := &ketoapi.Tree[*ketoapi.RelationTuple]{ Type: ketoapi.TreeNodeType(mt.Type), } @@ -332,7 +333,7 @@ func buildTree(t *testing.T, mt *httpclient.ExpandedPermissionTree) *ketoapi.Tre return result } -func (c *sdkClient) expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { +func (c *sdkClient) expand(t testing.TB, r *ketoapi.SubjectSet, depth int) *ketoapi.Tree[*ketoapi.RelationTuple] { request := c.getReadClient().PermissionApi.ExpandPermissions(c.requestCtx(t)). Namespace(r.Namespace). Object(r.Object). @@ -345,7 +346,7 @@ func (c *sdkClient) expand(t *testing.T, r *ketoapi.SubjectSet, depth int) *keto return buildTree(t, resp) } -func (c *sdkClient) waitUntilLive(t *testing.T) { +func (c *sdkClient) waitUntilLive(t testing.TB) { resp, _, err := c.getReadClient().MetadataApi.IsReady(c.requestCtx(t)).Execute() for err != nil { resp, _, err = c.getReadClient().MetadataApi.IsReady(c.requestCtx(t)).Execute() @@ -353,7 +354,7 @@ func (c *sdkClient) waitUntilLive(t *testing.T) { require.Equal(t, "ok", resp.Status) } -func (c *sdkClient) queryNamespaces(t *testing.T) (response ketoapi.GetNamespacesResponse) { +func (c *sdkClient) queryNamespaces(t testing.TB) (response ketoapi.GetNamespacesResponse) { res, _, err := c.getReadClient().RelationshipApi.ListRelationshipNamespaces(c.requestCtx(t)).Execute() require.NoError(t, err) require.NoError(t, convert(res, &response))