influxdb/testing/onboarding.go

236 lines
6.3 KiB
Go

package testing
import (
"context"
"testing"
"time"
"github.com/google/go-cmp/cmp"
platform "github.com/influxdata/influxdb/v2"
platform2 "github.com/influxdata/influxdb/v2/kit/platform"
"github.com/influxdata/influxdb/v2/kit/platform/errors"
"github.com/influxdata/influxdb/v2/mock"
)
var onboardCmpOptions = cmp.Options{
cmp.Comparer(func(x, y *platform.OnboardingResults) bool {
if x == nil && y == nil {
return true
}
if x != nil && y == nil || y != nil && x == nil {
return false
}
return x.User.Name == y.User.Name && x.User.OAuthID == y.User.OAuthID && x.User.Status == y.User.Status &&
x.Org.Name == y.Org.Name && x.Org.Description == y.Org.Description &&
x.Bucket.Type == y.Bucket.Type && x.Bucket.Description == y.Bucket.Description && x.Bucket.RetentionPolicyName == y.Bucket.RetentionPolicyName && x.Bucket.RetentionPeriod == y.Bucket.RetentionPeriod && x.Bucket.Name == y.Bucket.Name &&
(x.Auth != nil && y.Auth != nil && cmp.Equal(x.Auth.Permissions, y.Auth.Permissions)) // its possible auth wont exist on the basic service level
}),
}
// OnboardingFields will include the IDGenerator, TokenGenerator
// and IsOnboarding
type OnboardingFields struct {
IDGenerator platform2.IDGenerator
TokenGenerator platform.TokenGenerator
TimeGenerator platform.TimeGenerator
IsOnboarding bool
}
// OnboardInitialUser testing
func OnboardInitialUser(
init func(OnboardingFields, *testing.T) (platform.OnboardingService, func()),
t *testing.T,
) {
type args struct {
request *platform.OnboardingRequest
}
type wants struct {
errCode string
results *platform.OnboardingResults
}
tests := []struct {
name string
fields OnboardingFields
args args
wants wants
}{
{
name: "denied",
fields: OnboardingFields{
IDGenerator: &loopIDGenerator{
s: []string{oneID, twoID, threeID, fourID},
},
TokenGenerator: mock.NewTokenGenerator(oneToken, nil),
IsOnboarding: false,
},
wants: wants{
errCode: errors.EConflict,
},
},
{
name: "missing username",
fields: OnboardingFields{
IDGenerator: &loopIDGenerator{
s: []string{oneID, twoID, threeID, fourID},
},
TokenGenerator: mock.NewTokenGenerator(oneToken, nil),
IsOnboarding: true,
},
args: args{
request: &platform.OnboardingRequest{
Org: "org1",
Bucket: "bucket1",
},
},
wants: wants{
errCode: errors.EUnprocessableEntity,
},
},
{
name: "missing org",
fields: OnboardingFields{
IDGenerator: &loopIDGenerator{
s: []string{oneID, twoID, threeID, fourID},
},
TokenGenerator: mock.NewTokenGenerator(oneToken, nil),
IsOnboarding: true,
},
args: args{
request: &platform.OnboardingRequest{
User: "admin",
Bucket: "bucket1",
},
},
wants: wants{
errCode: errors.EUnprocessableEntity,
},
},
{
name: "missing bucket",
fields: OnboardingFields{
IDGenerator: &loopIDGenerator{
s: []string{oneID, twoID, threeID, fourID},
},
TokenGenerator: mock.NewTokenGenerator(oneToken, nil),
IsOnboarding: true,
},
args: args{
request: &platform.OnboardingRequest{
User: "admin",
Org: "org1",
},
},
wants: wants{
errCode: errors.EUnprocessableEntity,
},
},
{
name: "valid onboarding json should create a user, org, bucket, and authorization",
fields: OnboardingFields{
IDGenerator: &loopIDGenerator{
s: []string{oneID, twoID, threeID, fourID},
},
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
TokenGenerator: mock.NewTokenGenerator(oneToken, nil),
IsOnboarding: true,
},
args: args{
request: &platform.OnboardingRequest{
User: "admin",
Org: "org1",
Bucket: "bucket1",
Password: "password1",
RetentionPeriodSeconds: 3600 * 24 * 7, // 1 week
},
},
wants: wants{
results: &platform.OnboardingResults{
User: &platform.User{
ID: MustIDBase16(oneID),
Name: "admin",
Status: platform.Active,
},
Org: &platform.Organization{
ID: MustIDBase16(twoID),
Name: "org1",
CRUDLog: platform.CRUDLog{
CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
},
},
Bucket: &platform.Bucket{
ID: MustIDBase16(threeID),
Name: "bucket1",
OrgID: MustIDBase16(twoID),
RetentionPeriod: time.Hour * 24 * 7,
CRUDLog: platform.CRUDLog{
CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
},
},
Auth: &platform.Authorization{
ID: MustIDBase16(fourID),
Token: oneToken,
Status: platform.Active,
UserID: MustIDBase16(oneID),
Description: "admin's Token",
OrgID: MustIDBase16(twoID),
Permissions: platform.OperPermissions(),
CRUDLog: platform.CRUDLog{
CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, done := init(tt.fields, t)
defer done()
ctx := context.Background()
results, err := s.OnboardInitialUser(ctx, tt.args.request)
if (err != nil) != (tt.wants.errCode != "") {
t.Logf("Error: %v", err)
t.Fatalf("expected error code '%s' got '%v'", tt.wants.errCode, err)
}
if err != nil && tt.wants.errCode != "" {
if code := errors.ErrorCode(err); code != tt.wants.errCode {
t.Logf("Error: %v", err)
t.Fatalf("expected error code to match '%s' got '%v'", tt.wants.errCode, code)
}
}
if diff := cmp.Diff(results, tt.wants.results, onboardCmpOptions); diff != "" {
t.Errorf("onboarding results are different -got/+want\ndiff %s", diff)
}
})
}
}
const (
oneID = "020f755c3c082000"
twoID = "020f755c3c082001"
threeID = "020f755c3c082002"
fourID = "020f755c3c082003"
fiveID = "020f755c3c082004"
sixID = "020f755c3c082005"
oneToken = "020f755c3c082008"
)
type loopIDGenerator struct {
s []string
p int
}
func (g *loopIDGenerator) ID() platform2.ID {
if g.p == len(g.s) {
g.p = 0
}
id := MustIDBase16(g.s[g.p])
g.p++
return id
}