influxdb/testing/bucket_service.go

1047 lines
23 KiB
Go

package testing
import (
"bytes"
"context"
"fmt"
"sort"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/influxdata/platform"
"github.com/influxdata/platform/mock"
)
var bucketCmpOptions = cmp.Options{
cmp.Comparer(func(x, y []byte) bool {
return bytes.Equal(x, y)
}),
cmp.Transformer("Sort", func(in []*platform.Bucket) []*platform.Bucket {
out := append([]*platform.Bucket(nil), in...) // Copy input to avoid mutating it
sort.Slice(out, func(i, j int) bool {
return out[i].ID.String() > out[j].ID.String()
})
return out
}),
}
// BucketFields will include the IDGenerator, and buckets
type BucketFields struct {
IDGenerator platform.IDGenerator
Buckets []*platform.Bucket
Organizations []*platform.Organization
}
// CreateBucket testing
func CreateBucket(
init func(BucketFields, *testing.T) (platform.BucketService, func()),
t *testing.T,
) {
type args struct {
bucket *platform.Bucket
}
type wants struct {
err error
buckets []*platform.Bucket
}
tests := []struct {
name string
fields BucketFields
args args
wants wants
}{
{
name: "create buckets with empty set",
fields: BucketFields{
IDGenerator: mock.NewIDGenerator("id1"),
Buckets: []*platform.Bucket{},
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
},
},
args: args{
bucket: &platform.Bucket{
Name: "name1",
OrganizationID: platform.ID("org1"),
},
},
wants: wants{
buckets: []*platform.Bucket{
{
Name: "name1",
ID: platform.ID("id1"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
},
},
},
},
{
name: "basic create bucket",
fields: BucketFields{
IDGenerator: &mock.IDGenerator{
IDFn: func() platform.ID {
return platform.ID("2")
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("1"),
Name: "bucket1",
OrganizationID: platform.ID("org1"),
},
},
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
{
Name: "otherorg",
ID: platform.ID("org2"),
},
},
},
args: args{
bucket: &platform.Bucket{
Name: "bucket2",
OrganizationID: platform.ID("org2"),
},
},
wants: wants{
buckets: []*platform.Bucket{
{
ID: platform.ID("1"),
Name: "bucket1",
Organization: "theorg",
OrganizationID: platform.ID("org1"),
},
{
ID: platform.ID("2"),
Name: "bucket2",
Organization: "otherorg",
OrganizationID: platform.ID("org2"),
},
},
},
},
{
name: "basic create bucket using org name",
fields: BucketFields{
IDGenerator: &mock.IDGenerator{
IDFn: func() platform.ID {
return platform.ID("2")
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("1"),
Name: "bucket1",
OrganizationID: platform.ID("org1"),
},
},
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
{
Name: "otherorg",
ID: platform.ID("org2"),
},
},
},
args: args{
bucket: &platform.Bucket{
Name: "bucket2",
Organization: "otherorg",
},
},
wants: wants{
buckets: []*platform.Bucket{
{
ID: platform.ID("1"),
Name: "bucket1",
Organization: "theorg",
OrganizationID: platform.ID("org1"),
},
{
ID: platform.ID("2"),
Name: "bucket2",
Organization: "otherorg",
OrganizationID: platform.ID("org2"),
},
},
},
},
{
name: "names should be unique within an organization",
fields: BucketFields{
IDGenerator: &mock.IDGenerator{
IDFn: func() platform.ID {
return platform.ID("2")
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("1"),
Name: "bucket1",
OrganizationID: platform.ID("org1"),
},
},
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
{
Name: "otherorg",
ID: platform.ID("org2"),
},
},
},
args: args{
bucket: &platform.Bucket{
Name: "bucket1",
OrganizationID: platform.ID("org1"),
},
},
wants: wants{
buckets: []*platform.Bucket{
{
ID: platform.ID("1"),
Name: "bucket1",
Organization: "theorg",
OrganizationID: platform.ID("org1"),
},
},
err: fmt.Errorf("bucket with name bucket1 already exists"),
},
},
{
name: "names should not be unique across organizations",
fields: BucketFields{
IDGenerator: &mock.IDGenerator{
IDFn: func() platform.ID {
return platform.ID("2")
},
},
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
{
Name: "otherorg",
ID: platform.ID("org2"),
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("1"),
Name: "bucket1",
OrganizationID: platform.ID("org1"),
},
},
},
args: args{
bucket: &platform.Bucket{
Name: "bucket1",
OrganizationID: platform.ID("org2"),
},
},
wants: wants{
buckets: []*platform.Bucket{
{
ID: platform.ID("1"),
Name: "bucket1",
Organization: "theorg",
OrganizationID: platform.ID("org1"),
},
{
ID: platform.ID("2"),
Name: "bucket1",
Organization: "otherorg",
OrganizationID: platform.ID("org2"),
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, done := init(tt.fields, t)
defer done()
ctx := context.TODO()
err := s.CreateBucket(ctx, tt.args.bucket)
if (err != nil) != (tt.wants.err != nil) {
t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err)
}
if err != nil && tt.wants.err != nil {
if err.Error() != tt.wants.err.Error() {
t.Fatalf("expected error messages to match '%v' got '%v'", tt.wants.err, err.Error())
}
}
defer s.DeleteBucket(ctx, tt.args.bucket.ID)
buckets, _, err := s.FindBuckets(ctx, platform.BucketFilter{})
if err != nil {
t.Fatalf("failed to retrieve buckets: %v", err)
}
if diff := cmp.Diff(buckets, tt.wants.buckets, bucketCmpOptions...); diff != "" {
t.Errorf("buckets are different -got/+want\ndiff %s", diff)
}
})
}
}
// FindBucketByID testing
func FindBucketByID(
init func(BucketFields, *testing.T) (platform.BucketService, func()),
t *testing.T,
) {
type args struct {
id platform.ID
}
type wants struct {
err error
bucket *platform.Bucket
}
tests := []struct {
name string
fields BucketFields
args args
wants wants
}{
{
name: "basic find bucket by id",
fields: BucketFields{
Buckets: []*platform.Bucket{
{
ID: platform.ID("1"),
OrganizationID: platform.ID("org1"),
Name: "bucket1",
},
{
ID: platform.ID("2"),
OrganizationID: platform.ID("org1"),
Name: "bucket2",
},
},
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
},
},
args: args{
id: platform.ID("2"),
},
wants: wants{
bucket: &platform.Bucket{
ID: platform.ID("2"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
Name: "bucket2",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, done := init(tt.fields, t)
defer done()
ctx := context.TODO()
bucket, err := s.FindBucketByID(ctx, tt.args.id)
if (err != nil) != (tt.wants.err != nil) {
t.Fatalf("expected errors to be equal '%v' got '%v'", tt.wants.err, err)
}
if err != nil && tt.wants.err != nil {
if err.Error() != tt.wants.err.Error() {
t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err)
}
}
if diff := cmp.Diff(bucket, tt.wants.bucket, bucketCmpOptions...); diff != "" {
t.Errorf("bucket is different -got/+want\ndiff %s", diff)
}
})
}
}
// FindBuckets testing
func FindBuckets(
init func(BucketFields, *testing.T) (platform.BucketService, func()),
t *testing.T,
) {
type args struct {
ID string
name string
organization string
organizationID string
}
type wants struct {
buckets []*platform.Bucket
err error
}
tests := []struct {
name string
fields BucketFields
args args
wants wants
}{
{
name: "find all buckets",
fields: BucketFields{
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
{
Name: "otherorg",
ID: platform.ID("org2"),
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("test1"),
OrganizationID: platform.ID("org1"),
Name: "abc",
},
{
ID: platform.ID("test2"),
OrganizationID: platform.ID("org2"),
Name: "xyz",
},
},
},
args: args{},
wants: wants{
buckets: []*platform.Bucket{
{
ID: platform.ID("test1"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
Name: "abc",
},
{
ID: platform.ID("test2"),
OrganizationID: platform.ID("org2"),
Organization: "otherorg",
Name: "xyz",
},
},
},
},
{
name: "find buckets by organization name",
fields: BucketFields{
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
{
Name: "otherorg",
ID: platform.ID("org2"),
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("test1"),
OrganizationID: platform.ID("org1"),
Name: "abc",
},
{
ID: platform.ID("test2"),
OrganizationID: platform.ID("org2"),
Name: "xyz",
},
{
ID: platform.ID("test3"),
OrganizationID: platform.ID("org1"),
Name: "123",
},
},
},
args: args{
organization: "theorg",
},
wants: wants{
buckets: []*platform.Bucket{
{
ID: platform.ID("test1"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
Name: "abc",
},
{
ID: platform.ID("test3"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
Name: "123",
},
},
},
},
{
name: "find buckets by organization id",
fields: BucketFields{
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
{
Name: "otherorg",
ID: platform.ID("org2"),
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("test1"),
OrganizationID: platform.ID("org1"),
Name: "abc",
},
{
ID: platform.ID("test2"),
OrganizationID: platform.ID("org2"),
Name: "xyz",
},
{
ID: platform.ID("test3"),
OrganizationID: platform.ID("org1"),
Name: "123",
},
},
},
args: args{
organizationID: "org1",
},
wants: wants{
buckets: []*platform.Bucket{
{
ID: platform.ID("test1"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
Name: "abc",
},
{
ID: platform.ID("test3"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
Name: "123",
},
},
},
},
{
name: "find bucket by id",
fields: BucketFields{
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("test1"),
OrganizationID: platform.ID("org1"),
Name: "abc",
},
{
ID: platform.ID("test2"),
OrganizationID: platform.ID("org1"),
Name: "xyz",
},
},
},
args: args{
ID: "test2",
},
wants: wants{
buckets: []*platform.Bucket{
{
ID: platform.ID("test2"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
Name: "xyz",
},
},
},
},
{
name: "find bucket by name",
fields: BucketFields{
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("test1"),
OrganizationID: platform.ID("org1"),
Name: "abc",
},
{
ID: platform.ID("test2"),
OrganizationID: platform.ID("org1"),
Name: "xyz",
},
},
},
args: args{
name: "xyz",
},
wants: wants{
buckets: []*platform.Bucket{
{
ID: platform.ID("test2"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
Name: "xyz",
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, done := init(tt.fields, t)
defer done()
ctx := context.TODO()
filter := platform.BucketFilter{}
if tt.args.ID != "" {
id := platform.ID(tt.args.ID)
filter.ID = &id
}
if tt.args.organizationID != "" {
id := platform.ID(tt.args.organizationID)
filter.OrganizationID = &id
}
if tt.args.organization != "" {
filter.Organization = &tt.args.organization
}
if tt.args.name != "" {
filter.Name = &tt.args.name
}
buckets, _, err := s.FindBuckets(ctx, filter)
if (err != nil) != (tt.wants.err != nil) {
t.Fatalf("expected errors to be equal '%v' got '%v'", tt.wants.err, err)
}
if err != nil && tt.wants.err != nil {
if err.Error() != tt.wants.err.Error() {
t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err)
}
}
if diff := cmp.Diff(buckets, tt.wants.buckets, bucketCmpOptions...); diff != "" {
t.Errorf("buckets are different -got/+want\ndiff %s", diff)
}
})
}
}
// DeleteBucket testing
func DeleteBucket(
init func(BucketFields, *testing.T) (platform.BucketService, func()),
t *testing.T,
) {
type args struct {
ID string
}
type wants struct {
err error
buckets []*platform.Bucket
}
tests := []struct {
name string
fields BucketFields
args args
wants wants
}{
{
name: "delete buckets using exist id",
fields: BucketFields{
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
},
Buckets: []*platform.Bucket{
{
Name: "A",
ID: platform.ID("abc"),
OrganizationID: platform.ID("org1"),
},
{
Name: "B",
ID: platform.ID("xyz"),
OrganizationID: platform.ID("org1"),
},
},
},
args: args{
ID: "abc",
},
wants: wants{
buckets: []*platform.Bucket{
{
Name: "B",
ID: platform.ID("xyz"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
},
},
},
},
{
name: "delete buckets using id that does not exist",
fields: BucketFields{
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
},
Buckets: []*platform.Bucket{
{
Name: "A",
ID: platform.ID("abc"),
OrganizationID: platform.ID("org1"),
},
{
Name: "B",
ID: platform.ID("xyz"),
OrganizationID: platform.ID("org1"),
},
},
},
args: args{
ID: "123",
},
wants: wants{
err: fmt.Errorf("bucket not found"),
buckets: []*platform.Bucket{
{
Name: "A",
ID: platform.ID("abc"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
},
{
Name: "B",
ID: platform.ID("xyz"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, done := init(tt.fields, t)
defer done()
ctx := context.TODO()
err := s.DeleteBucket(ctx, platform.ID(tt.args.ID))
if (err != nil) != (tt.wants.err != nil) {
t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err)
}
if err != nil && tt.wants.err != nil {
if err.Error() != tt.wants.err.Error() {
t.Fatalf("expected error messages to match '%v' got '%v'", tt.wants.err, err.Error())
}
}
filter := platform.BucketFilter{}
buckets, _, err := s.FindBuckets(ctx, filter)
if err != nil {
t.Fatalf("failed to retrieve buckets: %v", err)
}
if diff := cmp.Diff(buckets, tt.wants.buckets, bucketCmpOptions...); diff != "" {
t.Errorf("buckets are different -got/+want\ndiff %s", diff)
}
})
}
}
// FindBucket testing
func FindBucket(
init func(BucketFields, *testing.T) (platform.BucketService, func()),
t *testing.T,
) {
type args struct {
name string
organizationID string
}
type wants struct {
bucket *platform.Bucket
err error
}
tests := []struct {
name string
fields BucketFields
args args
wants wants
}{
{
name: "find bucket by name",
fields: BucketFields{
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("a"),
OrganizationID: platform.ID("org1"),
Name: "abc",
},
{
ID: platform.ID("b"),
OrganizationID: platform.ID("org1"),
Name: "xyz",
},
},
},
args: args{
name: "abc",
organizationID: "org1",
},
wants: wants{
bucket: &platform.Bucket{
ID: platform.ID("a"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
Name: "abc",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, done := init(tt.fields, t)
defer done()
ctx := context.TODO()
filter := platform.BucketFilter{}
if tt.args.name != "" {
filter.Name = &tt.args.name
}
if tt.args.organizationID != "" {
id := platform.ID(tt.args.organizationID)
filter.OrganizationID = &id
}
bucket, err := s.FindBucket(ctx, filter)
if (err != nil) != (tt.wants.err != nil) {
t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err)
}
if err != nil && tt.wants.err != nil {
if err.Error() != tt.wants.err.Error() {
t.Fatalf("expected error messages to match '%v' got '%v'", tt.wants.err, err.Error())
}
}
if diff := cmp.Diff(bucket, tt.wants.bucket, bucketCmpOptions...); diff != "" {
t.Errorf("buckets are different -got/+want\ndiff %s", diff)
}
})
}
}
// UpdateBucket testing
func UpdateBucket(
init func(BucketFields, *testing.T) (platform.BucketService, func()),
t *testing.T,
) {
type args struct {
name string
id platform.ID
retention int
}
type wants struct {
err error
bucket *platform.Bucket
}
tests := []struct {
name string
fields BucketFields
args args
wants wants
}{
{
name: "update name",
fields: BucketFields{
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("1"),
OrganizationID: platform.ID("org1"),
Name: "bucket1",
},
{
ID: platform.ID("2"),
OrganizationID: platform.ID("org1"),
Name: "bucket2",
},
},
},
args: args{
id: platform.ID("1"),
name: "changed",
},
wants: wants{
bucket: &platform.Bucket{
ID: platform.ID("1"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
Name: "changed",
},
},
},
{
name: "update retention",
fields: BucketFields{
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("1"),
OrganizationID: platform.ID("org1"),
Name: "bucket1",
},
{
ID: platform.ID("2"),
OrganizationID: platform.ID("org1"),
Name: "bucket2",
},
},
},
args: args{
id: platform.ID("1"),
retention: 100,
},
wants: wants{
bucket: &platform.Bucket{
ID: platform.ID("1"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
Name: "bucket1",
RetentionPeriod: 100 * time.Minute,
},
},
},
{
name: "update retention and name",
fields: BucketFields{
Organizations: []*platform.Organization{
{
Name: "theorg",
ID: platform.ID("org1"),
},
},
Buckets: []*platform.Bucket{
{
ID: platform.ID("1"),
OrganizationID: platform.ID("org1"),
Name: "bucket1",
},
{
ID: platform.ID("2"),
OrganizationID: platform.ID("org1"),
Name: "bucket2",
},
},
},
args: args{
id: platform.ID("2"),
retention: 101,
name: "changed",
},
wants: wants{
bucket: &platform.Bucket{
ID: platform.ID("2"),
OrganizationID: platform.ID("org1"),
Organization: "theorg",
Name: "changed",
RetentionPeriod: 101 * time.Minute,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, done := init(tt.fields, t)
defer done()
ctx := context.TODO()
upd := platform.BucketUpdate{}
if tt.args.name != "" {
upd.Name = &tt.args.name
}
if tt.args.retention != 0 {
d := time.Duration(tt.args.retention) * time.Minute
upd.RetentionPeriod = &d
}
bucket, err := s.UpdateBucket(ctx, tt.args.id, upd)
if (err != nil) != (tt.wants.err != nil) {
t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err)
}
if err != nil && tt.wants.err != nil {
if err.Error() != tt.wants.err.Error() {
t.Fatalf("expected error messages to match '%v' got '%v'", tt.wants.err, err.Error())
}
}
if diff := cmp.Diff(bucket, tt.wants.bucket, bucketCmpOptions...); diff != "" {
t.Errorf("bucket is different -got/+want\ndiff %s", diff)
}
})
}
}