2018-04-13 18:22:33 +00:00
package server
import (
2018-04-13 21:34:57 +00:00
"bytes"
"context"
2021-01-04 15:19:22 +00:00
"fmt"
2018-04-13 21:34:57 +00:00
"io/ioutil"
2018-04-13 18:22:33 +00:00
"net/http"
"net/http/httptest"
2021-01-04 15:19:22 +00:00
"strings"
2018-04-13 18:22:33 +00:00
"testing"
2018-04-13 21:34:57 +00:00
"github.com/bouk/httprouter"
2021-01-04 15:19:22 +00:00
"github.com/influxdata/chronograf/log"
2018-04-13 21:34:57 +00:00
"github.com/influxdata/chronograf/mocks"
2018-04-13 18:22:33 +00:00
"github.com/influxdata/chronograf"
)
func TestService_Influx ( t * testing . T ) {
type fields struct {
SourcesStore chronograf . SourcesStore
2018-04-13 21:34:57 +00:00
TimeSeries TimeSeriesClient
2018-04-13 18:22:33 +00:00
}
type args struct {
w * httptest . ResponseRecorder
r * http . Request
}
2018-04-13 21:34:57 +00:00
type want struct {
StatusCode int
ContentType string
Body string
}
2018-04-13 18:22:33 +00:00
tests := [ ] struct {
2018-04-13 21:34:57 +00:00
name string
fields fields
args args
ID string
want want
} {
{
name : "Proxies request to Influxdb" ,
fields : fields {
SourcesStore : & mocks . SourcesStore {
GetF : func ( ctx context . Context , ID int ) ( chronograf . Source , error ) {
return chronograf . Source {
ID : 1337 ,
URL : "http://any.url" ,
} , nil
} ,
} ,
TimeSeries : & mocks . TimeSeries {
ConnectF : func ( ctx context . Context , src * chronograf . Source ) error {
return nil
} ,
QueryF : func ( ctx context . Context , query chronograf . Query ) ( chronograf . Response , error ) {
return mocks . NewResponse (
` { "results":[ { "statement_id":0,"series":[ { "name":"cpu","columns":["key","value"],"values":[["cpu","cpu-total"],["cpu","cpu0"],["cpu","cpu1"],["cpu","cpu2"],["cpu","cpu3"],["host","pineapples-MBP"],["host","pineapples-MacBook-Pro.local"]]}]}]} ` ,
nil ,
) ,
nil
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"POST" ,
"http://any.url" ,
ioutil . NopCloser (
bytes . NewReader ( [ ] byte (
2018-08-08 18:54:17 +00:00
` { "db":"bob", "rp":"joe", "uuid": "bob", "query":"SELECT mean(\"usage_user\") FROM cpu WHERE \"cpu\" = 'cpu-total' AND time > now() - 10m GROUP BY host;"} ` ,
2018-04-13 21:34:57 +00:00
) ) ,
) ,
) ,
} ,
ID : "1" ,
want : want {
StatusCode : http . StatusOK ,
ContentType : "application/json" ,
2018-08-08 18:54:17 +00:00
Body : ` { "results" : { "results" : [ { "statement_id" : 0 , "series" : [ { "name" : "cpu" , "columns" : [ "key" , "value" ] , "values" : [ [ "cpu" , "cpu-total" ] , [ "cpu" , "cpu0" ] , [ "cpu" , "cpu1" ] , [ "cpu" , "cpu2" ] , [ "cpu" , "cpu3" ] , [ "host" , "pineapples-MBP" ] , [ "host" , "pineapples-MacBook-Pro.local" ] ] } ] } ] } , "uuid" : "bob" }
2018-04-13 21:34:57 +00:00
` ,
} ,
} ,
}
for _ , tt := range tests {
tt . args . r = tt . args . r . WithContext ( httprouter . WithParams (
context . Background ( ) ,
httprouter . Params {
{
Key : "id" ,
Value : tt . ID ,
} ,
} ,
) )
h := & Service {
Store : & mocks . Store {
SourcesStore : tt . fields . SourcesStore ,
} ,
TimeSeriesClient : tt . fields . TimeSeries ,
}
h . Influx ( tt . args . w , tt . args . r )
resp := tt . args . w . Result ( )
contentType := resp . Header . Get ( "Content-Type" )
body , _ := ioutil . ReadAll ( resp . Body )
if resp . StatusCode != tt . want . StatusCode {
t . Errorf ( "%q. Influx() = got %v, want %v" , tt . name , resp . StatusCode , tt . want . StatusCode )
}
if contentType != tt . want . ContentType {
t . Errorf ( "%q. Influx() = got %v, want %v" , tt . name , contentType , tt . want . ContentType )
}
if string ( body ) != tt . want . Body {
t . Errorf ( "%q. Influx() =\ngot ***%v***\nwant ***%v***\n" , tt . name , string ( body ) , tt . want . Body )
}
}
2018-04-13 18:22:33 +00:00
}
2021-01-04 15:19:22 +00:00
// TestService_Influx_UseCommand test preprocessing of use command
func TestService_Influx_UseCommand ( t * testing . T ) {
tests := [ ] struct {
name string
db string
rp string
} {
{
name : "/* no command */" ,
} ,
{
name : "USE mydb" ,
db : "mydb" ,
} ,
{
name : "USE mydb.myrp" ,
db : "mydb" ,
rp : "myrp" ,
} ,
{
name : ` use "mydb" ` ,
db : "mydb" ,
} ,
{
name : ` use "mydb.myrp" ` ,
db : "mydb.myrp" ,
} ,
{
name : ` USE "mydb"."myrp" ` ,
db : "mydb" ,
rp : "myrp" ,
} ,
}
h := & Service {
Store : & mocks . Store {
SourcesStore : & mocks . SourcesStore {
GetF : func ( ctx context . Context , ID int ) ( chronograf . Source , error ) {
return chronograf . Source {
ID : 1337 ,
URL : "http://any.url" ,
} , nil
} ,
} ,
} ,
TimeSeriesClient : & mocks . TimeSeries {
ConnectF : func ( ctx context . Context , src * chronograf . Source ) error {
return nil
} ,
QueryF : func ( ctx context . Context , query chronograf . Query ) ( chronograf . Response , error ) {
return mocks . NewResponse (
fmt . Sprintf ( ` { "db":"%s","rp":"%s"} ` , query . DB , query . RP ) ,
nil ,
) ,
nil
} ,
} ,
Logger : log . New ( log . ErrorLevel ) ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
prefixCommand := strings . ReplaceAll ( tt . name , "\"" , "\\\"" )
w := httptest . NewRecorder ( )
r := httptest . NewRequest (
"POST" ,
"http://any.url" ,
ioutil . NopCloser (
bytes . NewReader ( [ ] byte (
` { "uuid": "tst", "query":" ` + prefixCommand + ` ; DROP MEASUREMENT test"} ` ,
) ) ,
) ,
)
r = r . WithContext ( httprouter . WithParams (
context . Background ( ) ,
httprouter . Params {
{
Key : "id" ,
Value : "1" ,
} ,
} ,
) )
h . Influx ( w , r )
resp := w . Result ( )
body , _ := ioutil . ReadAll ( resp . Body )
want := fmt . Sprintf ( ` { "results": { "db":"%s","rp":"%s"},"uuid":"tst"} ` , tt . db , tt . rp )
got := strings . TrimSpace ( string ( body ) )
if got != want {
t . Errorf ( "%q. Influx() =\ngot ***%v***\nwant ***%v***\n" , tt . name , got , want )
}
} )
}
}