Skip to content

Commit

Permalink
refactor test
Browse files Browse the repository at this point in the history
  • Loading branch information
xwa153 authored and JadhavPoonam committed Jul 28, 2023
1 parent 884b79d commit dacbda0
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 33 deletions.
66 changes: 66 additions & 0 deletions agent/grpc-external/services/resource/testing/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,42 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/acl/resolver"
svc "github.com/hashicorp/consul/agent/grpc-external/services/resource"
internal "github.com/hashicorp/consul/agent/grpc-internal"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/internal/storage/inmem"
"github.com/hashicorp/consul/proto-public/pbresource"
"github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/go-uuid"
)

func randomACLIdentity(t *testing.T) structs.ACLIdentity {
id, err := uuid.GenerateUUID()
require.NoError(t, err)

return &structs.ACLToken{AccessorID: id}
}

func AuthorizerFrom(t *testing.T, policyStrs ...string) resolver.Result {
policies := []*acl.Policy{}
for _, policyStr := range policyStrs {
policy, err := acl.NewPolicyFromSource(policyStr, nil, nil)
require.NoError(t, err)
policies = append(policies, policy)
}

authz, err := acl.NewPolicyAuthorizerWithDefaults(acl.DenyAll(), policies, nil)
require.NoError(t, err)

return resolver.Result{
Authorizer: authz,
ACLIdentity: randomACLIdentity(t),
}
}

// RunResourceService runs a Resource Service for the duration of the test and
// returns a client to interact with it. ACLs will be disabled.
func RunResourceService(t *testing.T, registerFns ...func(resource.Registry)) pbresource.ResourceServiceClient {
Expand Down Expand Up @@ -57,3 +84,42 @@ func RunResourceService(t *testing.T, registerFns ...func(resource.Registry)) pb

return pbresource.NewResourceServiceClient(conn)
}

func RunResourceServiceWithACL(t *testing.T, aclResolver svc.ACLResolver, registerFns ...func(resource.Registry)) pbresource.ResourceServiceClient {
t.Helper()

backend, err := inmem.NewBackend()
require.NoError(t, err)

ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)
go backend.Run(ctx)

registry := resource.NewRegistry()
for _, fn := range registerFns {
fn(registry)
}

server := grpc.NewServer()

svc.NewServer(svc.Config{
Backend: backend,
Registry: registry,
Logger: testutil.Logger(t),
ACLResolver: aclResolver,
}).Register(server)

pipe := internal.NewPipeListener()
go server.Serve(pipe)
t.Cleanup(server.Stop)

conn, err := grpc.Dial("",
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithContextDialer(pipe.DialContext),
grpc.WithBlock(),
)
require.NoError(t, err)
t.Cleanup(func() { _ = conn.Close() })

return pbresource.NewResourceServiceClient(conn)
}
106 changes: 73 additions & 33 deletions internal/resource/http/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,34 @@ import (
"testing"

"github.com/hashicorp/go-hclog"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"

"github.com/hashicorp/consul/acl"
resourceSvc "github.com/hashicorp/consul/agent/grpc-external/services/resource"
svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing"

"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/internal/resource/demo"
"github.com/hashicorp/consul/proto-public/pbresource"
pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2"
"github.com/hashicorp/consul/sdk/testutil"
)

func TestResourceHandler(t *testing.T) {
client := svctest.RunResourceService(t, demo.RegisterTypes)
const testACLToken = acl.AnonymousTokenID

func parseToken(req *http.Request, token *string) {
*token = req.Header.Get("x-Consul-Token")
}

func TestResourceHandler_InputValidation(t *testing.T) {
type testCase struct {
description string
request *http.Request
response *httptest.ResponseRecorder
expectedResponseCode int
}
client := svctest.RunResourceService(t, demo.RegisterTypes)
resourceHandler := resourceHandler{
resource.Registration{
Type: demo.TypeV2Artist,
Expand All @@ -31,43 +46,66 @@ func TestResourceHandler(t *testing.T) {
hclog.NewNullLogger(),
}

t.Run("should return bad request due to missing resource name", func(t *testing.T) {
rsp := httptest.NewRecorder()
req := httptest.NewRequest("PUT", "/?partition=default&peer_name=local&namespace=default", strings.NewReader(`
{
"metadata": {
"foo": "bar"
},
"data": {
"name": "Keith Urban",
"genre": "GENRE_COUNTRY"
testCases := []testCase{
{
description: "missing resource name",
request: httptest.NewRequest("PUT", "/?partition=default&peer_name=local&namespace=default", strings.NewReader(`
{
"metadata": {
"foo": "bar"
},
"data": {
"name": "Keith Urban",
"genre": "GENRE_COUNTRY"
}
}
}
`))
`)),
response: httptest.NewRecorder(),
expectedResponseCode: http.StatusBadRequest,
},
{
description: "wrong schema",
request: httptest.NewRequest("PUT", "/?partition=default&peer_name=local&namespace=default", strings.NewReader(`
{
"metadata": {
"foo": "bar"
},
"tada": {
"name": "Keith Urban",
"genre": "GENRE_COUNTRY"
}
}
`)),
response: httptest.NewRecorder(),
expectedResponseCode: http.StatusBadRequest,
},
}

resourceHandler.ServeHTTP(rsp, req)
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
resourceHandler.ServeHTTP(tc.response, tc.request)

require.Equal(t, http.StatusBadRequest, rsp.Result().StatusCode)
})
require.Equal(t, tc.expectedResponseCode, tc.response.Result().StatusCode)
})
}
}

t.Run("should return bad request due to wrong schema", func(t *testing.T) {
rsp := httptest.NewRecorder()
req := httptest.NewRequest("PUT", "/?partition=default&peer_name=local&namespace=default", strings.NewReader(`
{
"metadata": {
"foo": "bar"
},
"tada": {
"name": "Keith Urban",
"genre": "GENRE_COUNTRY"
}
}
`))
func TestResourceWriteHandler(t *testing.T) {
aclResolver := &resourceSvc.MockACLResolver{}
aclResolver.On("ResolveTokenAndDefaultMeta", testACLToken, mock.Anything, mock.Anything).
Return(svctest.AuthorizerFrom(t, demo.ArtistV2WritePolicy), nil)

resourceHandler.ServeHTTP(rsp, req)
client := svctest.RunResourceServiceWithACL(t, aclResolver, demo.RegisterTypes)

require.Equal(t, http.StatusBadRequest, rsp.Result().StatusCode)
})
resourceHandler := resourceHandler{
resource.Registration{
Type: demo.TypeV2Artist,
Proto: &pbdemov2.Artist{},
},
client,
parseToken,
hclog.NewNullLogger(),
}

t.Run("should write to the resource backend", func(t *testing.T) {
rsp := httptest.NewRecorder()
Expand All @@ -83,6 +121,8 @@ func TestResourceHandler(t *testing.T) {
}
`))

req.Header.Add("x-consul-token", testACLToken)

resourceHandler.ServeHTTP(rsp, req)

require.Equal(t, http.StatusOK, rsp.Result().StatusCode)
Expand Down

0 comments on commit dacbda0

Please sign in to comment.