influxdb/chronograf/server/databases_test.go

649 lines
17 KiB
Go

package server
import (
"context"
"encoding/json"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
"github.com/influxdata/httprouter"
"github.com/influxdata/influxdb/v2/chronograf"
"github.com/influxdata/influxdb/v2/chronograf/mocks"
)
func TestService_GetDatabases(t *testing.T) {
type fields struct {
SourcesStore chronograf.SourcesStore
ServersStore chronograf.ServersStore
LayoutsStore chronograf.LayoutsStore
UsersStore chronograf.UsersStore
DashboardsStore chronograf.DashboardsStore
TimeSeriesClient TimeSeriesClient
Logger chronograf.Logger
UseAuth bool
Databases chronograf.Databases
}
type args struct {
w http.ResponseWriter
r *http.Request
}
tests := []struct {
name string
fields fields
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Service{
Store: &Store{
SourcesStore: tt.fields.SourcesStore,
ServersStore: tt.fields.ServersStore,
LayoutsStore: tt.fields.LayoutsStore,
UsersStore: tt.fields.UsersStore,
DashboardsStore: tt.fields.DashboardsStore,
},
TimeSeriesClient: tt.fields.TimeSeriesClient,
Logger: tt.fields.Logger,
UseAuth: tt.fields.UseAuth,
Databases: tt.fields.Databases,
}
h.GetDatabases(tt.args.w, tt.args.r)
})
}
}
func TestService_NewDatabase(t *testing.T) {
type fields struct {
SourcesStore chronograf.SourcesStore
ServersStore chronograf.ServersStore
LayoutsStore chronograf.LayoutsStore
UsersStore chronograf.UsersStore
DashboardsStore chronograf.DashboardsStore
TimeSeriesClient TimeSeriesClient
Logger chronograf.Logger
UseAuth bool
Databases chronograf.Databases
}
type args struct {
w http.ResponseWriter
r *http.Request
}
tests := []struct {
name string
fields fields
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Service{
Store: &Store{
SourcesStore: tt.fields.SourcesStore,
ServersStore: tt.fields.ServersStore,
LayoutsStore: tt.fields.LayoutsStore,
UsersStore: tt.fields.UsersStore,
DashboardsStore: tt.fields.DashboardsStore,
},
TimeSeriesClient: tt.fields.TimeSeriesClient,
Logger: tt.fields.Logger,
UseAuth: tt.fields.UseAuth,
Databases: tt.fields.Databases,
}
h.NewDatabase(tt.args.w, tt.args.r)
})
}
}
func TestService_DropDatabase(t *testing.T) {
type fields struct {
SourcesStore chronograf.SourcesStore
ServersStore chronograf.ServersStore
LayoutsStore chronograf.LayoutsStore
UsersStore chronograf.UsersStore
DashboardsStore chronograf.DashboardsStore
TimeSeriesClient TimeSeriesClient
Logger chronograf.Logger
UseAuth bool
Databases chronograf.Databases
}
type args struct {
w http.ResponseWriter
r *http.Request
}
tests := []struct {
name string
fields fields
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Service{
Store: &Store{
SourcesStore: tt.fields.SourcesStore,
ServersStore: tt.fields.ServersStore,
LayoutsStore: tt.fields.LayoutsStore,
UsersStore: tt.fields.UsersStore,
DashboardsStore: tt.fields.DashboardsStore,
},
TimeSeriesClient: tt.fields.TimeSeriesClient,
Logger: tt.fields.Logger,
UseAuth: tt.fields.UseAuth,
Databases: tt.fields.Databases,
}
h.DropDatabase(tt.args.w, tt.args.r)
})
}
}
func TestService_RetentionPolicies(t *testing.T) {
type fields struct {
SourcesStore chronograf.SourcesStore
ServersStore chronograf.ServersStore
LayoutsStore chronograf.LayoutsStore
UsersStore chronograf.UsersStore
DashboardsStore chronograf.DashboardsStore
TimeSeriesClient TimeSeriesClient
Logger chronograf.Logger
UseAuth bool
Databases chronograf.Databases
}
type args struct {
w http.ResponseWriter
r *http.Request
}
tests := []struct {
name string
fields fields
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Service{
Store: &Store{
SourcesStore: tt.fields.SourcesStore,
ServersStore: tt.fields.ServersStore,
LayoutsStore: tt.fields.LayoutsStore,
UsersStore: tt.fields.UsersStore,
DashboardsStore: tt.fields.DashboardsStore,
},
TimeSeriesClient: tt.fields.TimeSeriesClient,
Logger: tt.fields.Logger,
UseAuth: tt.fields.UseAuth,
Databases: tt.fields.Databases,
}
h.RetentionPolicies(tt.args.w, tt.args.r)
})
}
}
func TestService_NewRetentionPolicy(t *testing.T) {
type fields struct {
SourcesStore chronograf.SourcesStore
ServersStore chronograf.ServersStore
LayoutsStore chronograf.LayoutsStore
UsersStore chronograf.UsersStore
DashboardsStore chronograf.DashboardsStore
TimeSeriesClient TimeSeriesClient
Logger chronograf.Logger
UseAuth bool
Databases chronograf.Databases
}
type args struct {
w http.ResponseWriter
r *http.Request
}
tests := []struct {
name string
fields fields
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Service{
Store: &Store{
SourcesStore: tt.fields.SourcesStore,
ServersStore: tt.fields.ServersStore,
LayoutsStore: tt.fields.LayoutsStore,
UsersStore: tt.fields.UsersStore,
DashboardsStore: tt.fields.DashboardsStore,
},
TimeSeriesClient: tt.fields.TimeSeriesClient,
Logger: tt.fields.Logger,
UseAuth: tt.fields.UseAuth,
Databases: tt.fields.Databases,
}
h.NewRetentionPolicy(tt.args.w, tt.args.r)
})
}
}
func TestService_UpdateRetentionPolicy(t *testing.T) {
type fields struct {
SourcesStore chronograf.SourcesStore
ServersStore chronograf.ServersStore
LayoutsStore chronograf.LayoutsStore
UsersStore chronograf.UsersStore
DashboardsStore chronograf.DashboardsStore
TimeSeriesClient TimeSeriesClient
Logger chronograf.Logger
UseAuth bool
Databases chronograf.Databases
}
type args struct {
w http.ResponseWriter
r *http.Request
}
tests := []struct {
name string
fields fields
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Service{
Store: &Store{
SourcesStore: tt.fields.SourcesStore,
ServersStore: tt.fields.ServersStore,
LayoutsStore: tt.fields.LayoutsStore,
UsersStore: tt.fields.UsersStore,
DashboardsStore: tt.fields.DashboardsStore,
},
TimeSeriesClient: tt.fields.TimeSeriesClient,
Logger: tt.fields.Logger,
UseAuth: tt.fields.UseAuth,
Databases: tt.fields.Databases,
}
h.UpdateRetentionPolicy(tt.args.w, tt.args.r)
})
}
}
func TestService_DropRetentionPolicy(t *testing.T) {
type fields struct {
SourcesStore chronograf.SourcesStore
ServersStore chronograf.ServersStore
LayoutsStore chronograf.LayoutsStore
UsersStore chronograf.UsersStore
DashboardsStore chronograf.DashboardsStore
TimeSeriesClient TimeSeriesClient
Logger chronograf.Logger
UseAuth bool
Databases chronograf.Databases
}
type args struct {
w http.ResponseWriter
r *http.Request
}
tests := []struct {
name string
fields fields
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Service{
Store: &Store{
SourcesStore: tt.fields.SourcesStore,
ServersStore: tt.fields.ServersStore,
LayoutsStore: tt.fields.LayoutsStore,
UsersStore: tt.fields.UsersStore,
DashboardsStore: tt.fields.DashboardsStore,
},
TimeSeriesClient: tt.fields.TimeSeriesClient,
Logger: tt.fields.Logger,
UseAuth: tt.fields.UseAuth,
Databases: tt.fields.Databases,
}
h.DropRetentionPolicy(tt.args.w, tt.args.r)
})
}
}
func TestService_Measurements(t *testing.T) {
type fields struct {
SourcesStore chronograf.SourcesStore
Logger chronograf.Logger
Databases chronograf.Databases
}
type args struct {
queryParams map[string]string
}
type wants struct {
statusCode int
body string
}
tests := []struct {
name string
fields fields
args args
wants wants
}{
{
name: "Gets 100 measurements when no limit or offset provided",
fields: fields{
SourcesStore: &mocks.SourcesStore{
GetF: func(ctx context.Context, srcID int) (chronograf.Source, error) {
return chronograf.Source{
ID: 0,
}, nil
},
},
Databases: &mocks.Databases{
ConnectF: func(context.Context, *chronograf.Source) error {
return nil
},
GetMeasurementsF: func(ctx context.Context, db string, limit, offset int) ([]chronograf.Measurement, error) {
return []chronograf.Measurement{
{
Name: "pineapple",
},
{
Name: "cubeapple",
},
{
Name: "pinecube",
},
}, nil
},
},
},
args: args{
queryParams: map[string]string{},
},
wants: wants{
statusCode: 200,
body: `{"measurements":[{"name":"pineapple"},{"name":"cubeapple"},{"name":"pinecube"}],"links":{"self":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=100\u0026offset=0","first":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=100\u0026offset=0","next":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=100\u0026offset=100"}}
`,
},
},
{
name: "Fails when invalid limit value provided",
fields: fields{
SourcesStore: &mocks.SourcesStore{
GetF: func(ctx context.Context, srcID int) (chronograf.Source, error) {
return chronograf.Source{
ID: 0,
}, nil
},
},
},
args: args{
queryParams: map[string]string{
"limit": "joe",
},
},
wants: wants{
statusCode: 422,
body: `{"code":422,"message":"strconv.Atoi: parsing \"joe\": invalid syntax"}`,
},
},
{
name: "Fails when invalid offset value provided",
fields: fields{
SourcesStore: &mocks.SourcesStore{
GetF: func(ctx context.Context, srcID int) (chronograf.Source, error) {
return chronograf.Source{
ID: 0,
}, nil
},
},
},
args: args{
queryParams: map[string]string{
"offset": "bob",
},
},
wants: wants{
statusCode: 422,
body: `{"code":422,"message":"strconv.Atoi: parsing \"bob\": invalid syntax"}`,
},
},
{
name: "Overrides limit less than or equal to 0 with limit 100",
fields: fields{
SourcesStore: &mocks.SourcesStore{
GetF: func(ctx context.Context, srcID int) (chronograf.Source, error) {
return chronograf.Source{
ID: 0,
}, nil
},
},
Databases: &mocks.Databases{
ConnectF: func(context.Context, *chronograf.Source) error {
return nil
},
GetMeasurementsF: func(ctx context.Context, db string, limit, offset int) ([]chronograf.Measurement, error) {
return []chronograf.Measurement{
{
Name: "pineapple",
},
{
Name: "cubeapple",
},
{
Name: "pinecube",
},
}, nil
},
},
},
args: args{
queryParams: map[string]string{
"limit": "0",
},
},
wants: wants{
statusCode: 200,
body: `{"measurements":[{"name":"pineapple"},{"name":"cubeapple"},{"name":"pinecube"}],"links":{"self":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=100\u0026offset=0","first":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=100\u0026offset=0","next":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=100\u0026offset=100"}}
`,
},
},
{
name: "Overrides offset less than 0 with offset 0",
fields: fields{
SourcesStore: &mocks.SourcesStore{
GetF: func(ctx context.Context, srcID int) (chronograf.Source, error) {
return chronograf.Source{
ID: 0,
}, nil
},
},
Databases: &mocks.Databases{
ConnectF: func(context.Context, *chronograf.Source) error {
return nil
},
GetMeasurementsF: func(ctx context.Context, db string, limit, offset int) ([]chronograf.Measurement, error) {
return []chronograf.Measurement{
{
Name: "pineapple",
},
{
Name: "cubeapple",
},
{
Name: "pinecube",
},
}, nil
},
},
},
args: args{
queryParams: map[string]string{
"offset": "-1337",
},
},
wants: wants{
statusCode: 200,
body: `{"measurements":[{"name":"pineapple"},{"name":"cubeapple"},{"name":"pinecube"}],"links":{"self":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=100\u0026offset=0","first":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=100\u0026offset=0","next":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=100\u0026offset=100"}}
`,
},
},
{
name: "Provides a prev link when offset exceeds limit",
fields: fields{
SourcesStore: &mocks.SourcesStore{
GetF: func(ctx context.Context, srcID int) (chronograf.Source, error) {
return chronograf.Source{
ID: 0,
}, nil
},
},
Databases: &mocks.Databases{
ConnectF: func(context.Context, *chronograf.Source) error {
return nil
},
GetMeasurementsF: func(ctx context.Context, db string, limit, offset int) ([]chronograf.Measurement, error) {
return []chronograf.Measurement{
{
Name: "pineapple",
},
{
Name: "cubeapple",
},
{
Name: "pinecube",
},
{
Name: "billietta",
},
{
Name: "bobbetta",
},
{
Name: "bobcube",
},
}, nil
},
},
},
args: args{
queryParams: map[string]string{
"limit": "2",
"offset": "4",
},
},
wants: wants{
statusCode: 200,
body: `{"measurements":[{"name":"pineapple"},{"name":"cubeapple"},{"name":"pinecube"},{"name":"billietta"},{"name":"bobbetta"},{"name":"bobcube"}],"links":{"self":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=2\u0026offset=4","first":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=2\u0026offset=0","next":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=2\u0026offset=6","prev":"/chronograf/v1/sources/0/dbs/pineapples/measurements?limit=2\u0026offset=2"}}
`,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
logger := &chronograf.NoopLogger{}
h := &Service{
Store: &mocks.Store{
SourcesStore: tt.fields.SourcesStore,
},
Logger: logger,
Databases: tt.fields.Databases,
}
w := httptest.NewRecorder()
r := httptest.NewRequest(
"GET",
"http://any.url",
nil,
)
r = r.WithContext(context.WithValue(
context.TODO(),
httprouter.ParamsKey,
httprouter.Params{
{
Key: "id",
Value: "0",
},
{
Key: "db",
Value: "pineapples",
},
}))
q := r.URL.Query()
for key, value := range tt.args.queryParams {
q.Add(key, value)
}
r.URL.RawQuery = q.Encode()
h.Measurements(w, r)
resp := w.Result()
body, err := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()
if err != nil {
t.Error("TestService_Measurements not able to retrieve body")
}
var msmts measurementsResponse
if err := json.Unmarshal(body, &msmts); err != nil {
t.Error("TestService_Measurements not able to unmarshal JSON response")
}
if tt.wants.statusCode != resp.StatusCode {
t.Errorf("%q. StatusCode:\nwant\n%v\ngot\n%v", tt.name, tt.wants.statusCode, resp.StatusCode)
}
if tt.wants.body != string(body) {
t.Errorf("%q. Body:\nwant\n*%s*\ngot\n*%s*", tt.name, tt.wants.body, string(body))
}
})
}
}
func TestValidDatabaseRequest(t *testing.T) {
type args struct {
d *chronograf.Database
}
tests := []struct {
name string
args args
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := ValidDatabaseRequest(tt.args.d); (err != nil) != tt.wantErr {
t.Errorf("ValidDatabaseRequest() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestValidRetentionPolicyRequest(t *testing.T) {
type args struct {
rp *chronograf.RetentionPolicy
}
tests := []struct {
name string
args args
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := ValidRetentionPolicyRequest(tt.args.rp); (err != nil) != tt.wantErr {
t.Errorf("ValidRetentionPolicyRequest() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}