2015-02-02 21:01:35 +00:00
package main_test
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"path/filepath"
2015-02-09 23:16:25 +00:00
"strconv"
2015-02-28 02:05:30 +00:00
"strings"
2015-02-02 21:01:35 +00:00
"testing"
"time"
2015-02-10 00:35:28 +00:00
"github.com/influxdb/influxdb"
"github.com/influxdb/influxdb/messaging"
2015-02-02 21:01:35 +00:00
main "github.com/influxdb/influxdb/cmd/influxd"
)
2015-02-21 19:54:05 +00:00
const (
// Use a prime batch size, so that internal batching code, which most likely
// uses nice round batches, has to deal with leftover.
batchSize = 4217
)
2015-02-28 02:05:30 +00:00
// tempfile returns a temporary path.
func tempfile ( ) string {
f , _ := ioutil . TempFile ( "" , "influxdb-" )
path := f . Name ( )
f . Close ( )
os . Remove ( path )
return path
}
2015-02-10 03:58:17 +00:00
// urlFor returns a URL with the path and query params correctly appended and set.
func urlFor ( u * url . URL , path string , params url . Values ) * url . URL {
2015-02-26 00:01:06 +00:00
v , _ := url . Parse ( u . String ( ) )
v . Path = path
v . RawQuery = params . Encode ( )
return v
2015-02-10 03:58:17 +00:00
}
2015-02-28 02:05:30 +00:00
// rewriteDbRp returns a copy of old with occurrences of %DB% with the given database,
// and occurences of %RP with the given retention
func rewriteDbRp ( old , database , retention string ) string {
return strings . Replace ( strings . Replace ( old , "%DB%" , database , - 1 ) , "%RP%" , retention , - 1 )
}
// Node represents a node under test, which is both a broker and data node.
type Node struct {
2015-02-10 00:35:28 +00:00
broker * messaging . Broker
server * influxdb . Server
2015-02-10 01:55:07 +00:00
url * url . URL
2015-02-10 01:59:19 +00:00
leader bool
2015-02-10 00:35:28 +00:00
}
2015-02-28 02:05:30 +00:00
// Cluster represents a multi-node cluster.
type Cluster [ ] * Node
2015-02-20 23:11:51 +00:00
2015-02-09 23:16:25 +00:00
// createCombinedNodeCluster creates a cluster of nServers nodes, each of which
// runs as both a Broker and Data node. If any part cluster creation fails,
// the testing is marked as failed.
2015-02-10 00:35:28 +00:00
//
// This function returns a slice of nodes, the first of which will be the leader.
2015-02-28 02:05:30 +00:00
func createCombinedNodeCluster ( t * testing . T , testName , tmpDir string , nNodes , basePort int ) Cluster {
2015-02-09 23:46:55 +00:00
t . Logf ( "Creating cluster of %d nodes for test %s" , nNodes , testName )
if nNodes < 1 {
2015-02-09 23:51:10 +00:00
t . Fatalf ( "Test %s: asked to create nonsense cluster" , testName )
2015-02-09 23:16:25 +00:00
}
2015-02-02 21:01:35 +00:00
2015-02-28 02:05:30 +00:00
nodes := make ( [ ] * Node , 0 )
2015-02-10 00:35:28 +00:00
2015-02-09 23:16:25 +00:00
tmpBrokerDir := filepath . Join ( tmpDir , "broker-integration-test" )
tmpDataDir := filepath . Join ( tmpDir , "data-integration-test" )
2015-02-09 23:27:59 +00:00
t . Logf ( "Test %s: using tmp directory %q for brokers\n" , testName , tmpBrokerDir )
t . Logf ( "Test %s: using tmp directory %q for data nodes\n" , testName , tmpDataDir )
2015-02-09 23:16:25 +00:00
// Sometimes if a test fails, it's because of a log.Fatal() in the program.
2015-02-05 21:06:18 +00:00
// This prevents the defer from cleaning up directories.
// To be safe, nuke them always before starting
_ = os . RemoveAll ( tmpBrokerDir )
_ = os . RemoveAll ( tmpDataDir )
2015-02-02 21:01:35 +00:00
2015-02-09 23:16:25 +00:00
// Create the first node, special case.
2015-02-02 21:01:35 +00:00
c := main . NewConfig ( )
2015-02-09 23:16:25 +00:00
c . Broker . Dir = filepath . Join ( tmpBrokerDir , strconv . Itoa ( basePort ) )
c . Data . Dir = filepath . Join ( tmpDataDir , strconv . Itoa ( basePort ) )
c . Broker . Port = basePort
c . Data . Port = basePort
2015-02-12 00:33:21 +00:00
c . Admin . Enabled = false
2015-02-12 19:23:10 +00:00
c . ReportingDisabled = true
2015-02-09 23:40:21 +00:00
2015-02-10 00:35:28 +00:00
b , s := main . Run ( c , "" , "x.x" , os . Stderr )
if b == nil {
t . Fatalf ( "Test %s: failed to create broker on port %d" , testName , basePort )
}
2015-02-09 23:16:25 +00:00
if s == nil {
2015-02-10 00:35:28 +00:00
t . Fatalf ( "Test %s: failed to create leader data node on port %d" , testName , basePort )
2015-02-09 23:40:21 +00:00
}
2015-02-28 02:05:30 +00:00
nodes = append ( nodes , & Node {
2015-02-10 01:55:07 +00:00
broker : b ,
server : s ,
url : & url . URL { Scheme : "http" , Host : "localhost:" + strconv . Itoa ( basePort ) } ,
2015-02-10 01:59:19 +00:00
leader : true ,
2015-02-10 01:55:07 +00:00
} )
2015-02-09 23:40:21 +00:00
// Create subsequent nodes, which join to first node.
2015-02-09 23:46:55 +00:00
for i := 1 ; i < nNodes ; i ++ {
2015-02-09 23:40:21 +00:00
nextPort := basePort + i
c . Broker . Dir = filepath . Join ( tmpBrokerDir , strconv . Itoa ( nextPort ) )
c . Data . Dir = filepath . Join ( tmpDataDir , strconv . Itoa ( nextPort ) )
c . Broker . Port = nextPort
c . Data . Port = nextPort
2015-02-10 00:35:28 +00:00
b , s := main . Run ( c , "http://localhost:" + strconv . Itoa ( basePort ) , "x.x" , os . Stderr )
if b == nil {
t . Fatalf ( "Test %s: failed to create following broker on port %d" , testName , basePort )
}
2015-02-09 23:40:21 +00:00
if s == nil {
2015-02-10 00:35:28 +00:00
t . Fatalf ( "Test %s: failed to create following data node on port %d" , testName , basePort )
2015-02-09 23:40:21 +00:00
}
2015-02-10 01:55:07 +00:00
2015-02-28 02:05:30 +00:00
nodes = append ( nodes , & Node {
2015-02-10 01:55:07 +00:00
broker : b ,
server : s ,
url : & url . URL { Scheme : "http" , Host : "localhost:" + strconv . Itoa ( nextPort ) } ,
} )
2015-02-09 23:16:25 +00:00
}
2015-02-10 00:35:28 +00:00
return nodes
2015-02-09 23:16:25 +00:00
}
2015-02-02 21:01:35 +00:00
2015-02-10 01:37:17 +00:00
// createDatabase creates a database, and verifies that the creation was successful.
2015-02-28 02:05:30 +00:00
func createDatabase ( t * testing . T , testName string , nodes Cluster , database string ) {
2015-02-10 01:37:17 +00:00
t . Logf ( "Test: %s: creating database %s" , testName , database )
2015-03-04 20:21:39 +00:00
query ( t , nodes [ : 1 ] , "" , "CREATE DATABASE " + database , ` { "results":[ { }]} ` )
2015-02-10 01:37:17 +00:00
}
2015-02-02 21:01:35 +00:00
2015-02-10 01:37:17 +00:00
// createRetentionPolicy creates a retetention policy and verifies that the creation was successful.
2015-02-28 02:05:30 +00:00
// Replication factor is set to equal the number nodes in the cluster.
func createRetentionPolicy ( t * testing . T , testName string , nodes Cluster , database , retention string ) {
t . Logf ( "Creating retention policy %s for database %s" , retention , database )
command := fmt . Sprintf ( "CREATE RETENTION POLICY %s ON %s DURATION 1h REPLICATION %d DEFAULT" , retention , database , len ( nodes ) )
2015-03-04 20:21:39 +00:00
query ( t , nodes [ : 1 ] , "" , command , ` { "results":[ { }]} ` )
2015-02-28 02:05:30 +00:00
}
2015-02-02 21:01:35 +00:00
2015-02-28 02:05:30 +00:00
// deleteDatabase delete a database, and verifies that the deletion was successful.
func deleteDatabase ( t * testing . T , testName string , nodes Cluster , database string ) {
t . Logf ( "Test: %s: deleting database %s" , testName , database )
2015-03-04 20:21:39 +00:00
query ( t , nodes [ : 1 ] , "" , "DROP DATABASE " + database , ` { "results":[ { }]} ` )
2015-02-10 01:37:17 +00:00
}
2015-02-02 21:01:35 +00:00
2015-02-10 03:38:06 +00:00
// writes writes the provided data to the cluster. It verfies that a 200 OK is returned by the server.
2015-02-28 02:05:30 +00:00
func write ( t * testing . T , node * Node , data string ) {
u := urlFor ( node . url , "write" , url . Values { } )
2015-02-02 21:01:35 +00:00
2015-02-28 02:05:30 +00:00
resp , err := http . Post ( u . String ( ) , "application/json" , bytes . NewReader ( [ ] byte ( data ) ) )
2015-02-02 21:01:35 +00:00
if err != nil {
t . Fatalf ( "Couldn't write data: %s" , err )
}
if resp . StatusCode != http . StatusOK {
2015-02-28 02:05:30 +00:00
body , _ := ioutil . ReadAll ( resp . Body )
t . Fatalf ( "Write to database failed. Unexpected status code. expected: %d, actual %d, %s" , http . StatusOK , resp . StatusCode , string ( body ) )
2015-02-02 21:01:35 +00:00
}
2015-02-28 02:05:30 +00:00
// Until races are solved.
time . Sleep ( 3 * time . Second )
2015-02-10 03:38:06 +00:00
}
2015-02-28 02:05:30 +00:00
// query executes the given query against all nodes in the cluster, and verifies no errors occured, and
// ensures the returned data is as expected
2015-03-04 20:21:39 +00:00
func query ( t * testing . T , nodes Cluster , urlDb , query , expected string ) ( string , bool ) {
v := url . Values { "q" : [ ] string { query } }
if urlDb != "" {
v . Set ( "db" , urlDb )
}
2015-02-02 21:01:35 +00:00
// Query the data exists
2015-02-10 03:56:54 +00:00
for _ , n := range nodes {
2015-03-04 20:21:39 +00:00
u := urlFor ( n . url , "query" , v )
2015-02-10 03:56:54 +00:00
resp , err := http . Get ( u . String ( ) )
if err != nil {
2015-02-28 02:05:30 +00:00
t . Fatalf ( "Failed to execute query '%s': %s" , query , err . Error ( ) )
2015-02-10 03:56:54 +00:00
}
defer resp . Body . Close ( )
2015-02-02 21:01:35 +00:00
2015-02-10 03:56:54 +00:00
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
2015-02-28 02:05:30 +00:00
t . Fatalf ( "Couldn't read body of response: %s" , err . Error ( ) )
2015-02-10 03:56:54 +00:00
}
2015-02-02 21:01:35 +00:00
2015-02-28 02:05:30 +00:00
if expected != string ( body ) {
return string ( body ) , false
2015-02-10 03:56:54 +00:00
}
2015-02-10 03:38:06 +00:00
}
2015-02-28 02:05:30 +00:00
return "" , true
2015-02-23 18:01:21 +00:00
}
2015-02-28 02:05:30 +00:00
// runTests_Errors tests some basic error cases.
func runTests_Errors ( t * testing . T , nodes Cluster ) {
t . Logf ( "Running tests against %d-node cluster" , len ( nodes ) )
tests := [ ] struct {
name string
write string // If equal to the empty string, no data is written.
query string // If equal to the blank string, no query is executed.
expected string // If 'query' is equal to the blank string, this is ignored.
} {
{
name : "simple SELECT from non-existent database" ,
write : "" ,
query : ` SELECT * FROM "qux"."bar".cpu ` ,
expected : ` { "results":[ { "error":"database not found: qux"}]} ` ,
} ,
}
2015-02-21 19:54:05 +00:00
2015-02-28 02:05:30 +00:00
for _ , tt := range tests {
if tt . write != "" {
write ( t , nodes [ 0 ] , tt . write )
2015-02-21 19:54:05 +00:00
}
2015-02-28 02:05:30 +00:00
if tt . query != "" {
2015-03-04 20:21:39 +00:00
got , ok := query ( t , nodes , "" , tt . query , tt . expected )
2015-02-28 02:05:30 +00:00
if ! ok {
t . Errorf ( "Test '%s' failed, expected: %s, got: %s" , tt . name , tt . expected , got )
}
2015-02-21 19:54:05 +00:00
}
}
}
2015-03-03 22:53:31 +00:00
// runTests tests write and query of data. Setting testNumbers allows only a subset of tests to be run.
func runTestsData ( t * testing . T , testName string , nodes Cluster , database , retention string , testNums ... int ) {
2015-02-28 02:05:30 +00:00
t . Logf ( "Running tests against %d-node cluster" , len ( nodes ) )
// Start by ensuring database and retention policy exist.
createDatabase ( t , testName , nodes , database )
createRetentionPolicy ( t , testName , nodes , database , retention )
// The tests. Within these tests %DB% and %RP% will be replaced with the database and retention passed into
// this function.
tests := [ ] struct {
reset bool // Delete and recreate the database.
name string // Test name, for easy-to-read test log output.
write string // If equal to the empty string, no data is written.
query string // If equal to the blank string, no query is executed.
2015-03-04 20:21:39 +00:00
queryDb string // If set, is used as the "db" query param.
2015-02-28 02:05:30 +00:00
expected string // If 'query' is equal to the blank string, this is ignored.
} {
2015-03-03 22:02:53 +00:00
// Data read and write tests
2015-02-28 02:05:30 +00:00
{
reset : true ,
name : "single point with timestamp" ,
write : ` { "database" : "%DB%", "retentionPolicy" : "%RP%", "points": [ { "name": "cpu", "timestamp": "2015-02-28T01:03:36.703820946Z", "tags": { "host": "server01"}, "fields": { "value": 100}}]} ` ,
2015-03-04 00:48:40 +00:00
query : ` SELECT * FROM "%DB%"."%RP%".cpu ` ,
2015-02-28 02:05:30 +00:00
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["time","value"],"values":[["2015-02-28T01:03:36.703820946Z",100]]}]}]} ` ,
} ,
2015-03-04 01:11:09 +00:00
{
name : "single string point with timestamp" ,
write : ` { "database" : "%DB%", "retentionPolicy" : "%RP%", "points": [ { "name": "logs", "timestamp": "2015-02-28T01:03:36.703820946Z", "tags": { "host": "server01"}, "fields": { "value": "disk full"}}]} ` ,
query : ` SELECT * FROM "%DB%"."%RP%".logs ` ,
expected : ` { "results":[ { "series":[ { "name":"logs","columns":["time","value"],"values":[["2015-02-28T01:03:36.703820946Z","disk full"]]}]}]} ` ,
} ,
{
name : "single bool point with timestamp" ,
write : ` { "database" : "%DB%", "retentionPolicy" : "%RP%", "points": [ { "name": "status", "timestamp": "2015-02-28T01:03:36.703820946Z", "tags": { "host": "server01"}, "fields": { "value": "true"}}]} ` ,
query : ` SELECT * FROM "%DB%"."%RP%".status ` ,
expected : ` { "results":[ { "series":[ { "name":"status","columns":["time","value"],"values":[["2015-02-28T01:03:36.703820946Z","true"]]}]}]} ` ,
} ,
2015-02-28 02:05:30 +00:00
{
name : "single point, select with now()" ,
query : ` SELECT * FROM "%DB%"."%RP%".cpu WHERE time < now() ` ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["time","value"],"values":[["2015-02-28T01:03:36.703820946Z",100]]}]}]} ` ,
2015-02-02 21:01:35 +00:00
} ,
2015-03-03 22:02:53 +00:00
{
name : "measurement not found" ,
query : ` SELECT value FROM "%DB%"."%RP%".foobarbaz ` ,
expected : ` { "results":[ { "error":"measurement not found"}]} ` ,
} ,
{
name : "field not found" ,
query : ` SELECT abc FROM "%DB%"."%RP%".cpu WHERE time < now() ` ,
expected : ` { "results":[ { "error":"field not found: abc"}]} ` ,
} ,
2015-03-03 22:30:59 +00:00
// WHERE fields queries
{
reset : true ,
2015-03-03 23:02:42 +00:00
name : "WHERE fields" ,
write : ` { "database" : "%DB%", "retentionPolicy" : "%RP%", "points": [ { "name": "cpu", "timestamp": "2015-02-28T01:03:36.703820946Z", "fields": { "alert_id": "alert", "tenant_id": "tenant"}}]} ` ,
query : ` SELECT alert_id FROM "%DB%"."%RP%".cpu WHERE alert_id='alert' ` ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["time","alert_id"],"values":[["2015-02-28T01:03:36.703820946Z","alert"]]}]}]} ` ,
} ,
{
2015-03-03 23:26:02 +00:00
name : "WHERE fields with AND query, all fields in SELECT" ,
2015-03-03 22:30:59 +00:00
write : ` { "database" : "%DB%", "retentionPolicy" : "%RP%", "points": [ { "name": "cpu", "timestamp": "2015-02-28T01:03:36.703820946Z", "fields": { "alert_id": "alert", "tenant_id": "tenant"}}]} ` ,
2015-03-03 23:26:02 +00:00
query : ` SELECT alert_id,tenant_id FROM "%DB%"."%RP%".cpu WHERE alert_id='alert' AND tenant_id='tenant' ` ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["time","alert_id","tenant_id"],"values":[["2015-02-28T01:03:36.703820946Z","alert","tenant"]]}]}]} ` ,
2015-03-03 22:30:59 +00:00
} ,
2015-03-03 23:58:25 +00:00
{
name : "WHERE fields with AND query, all fields in SELECT, one in parenthesis" ,
write : ` { "database" : "%DB%", "retentionPolicy" : "%RP%", "points": [ { "name": "cpu", "timestamp": "2015-02-28T01:03:36.703820946Z", "fields": { "alert_id": "alert", "tenant_id": "tenant"}}]} ` ,
query : ` SELECT alert_id,tenant_id FROM "%DB%"."%RP%".cpu WHERE alert_id='alert' AND (tenant_id='tenant') ` ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["time","alert_id","tenant_id"],"values":[["2015-02-28T01:03:36.703820946Z","alert","tenant"]]}]}]} ` ,
} ,
2015-03-03 23:48:03 +00:00
{
write : ` { "database" : "%DB%" , "retentionPolicy" : "%RP%" , "points" : [ { "name" : "cpu" , "timestamp" : "2009-11-10T23:00:02Z" , "fields" : { "load" : 100 } } ,
{ "name" : "cpu" , "timestamp" : "2009-11-10T23:01:02Z" , "fields" : { "load" : 80 } } ] } ` ,
query : ` select load from "%DB%"."%RP%".cpu where load > 100 ` ,
expected : ` { "results":[ { }]} ` ,
} ,
{
query : ` select load from "%DB%"."%RP%".cpu where load >= 100 ` ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["time","load"],"values":[["2009-11-10T23:00:02Z",100]]}]}]} ` ,
} ,
{
query : ` select load from "%DB%"."%RP%".cpu where load = 100 ` ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["time","load"],"values":[["2009-11-10T23:00:02Z",100]]}]}]} ` ,
} ,
{
query : ` select load from "%DB%"."%RP%".cpu where load <= 100 ` ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["time","load"],"values":[["2009-11-10T23:00:02Z",100],["2009-11-10T23:01:02Z",80]]}]}]} ` ,
} ,
{
query : ` select load from "%DB%"."%RP%".cpu where load > 99 ` ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["time","load"],"values":[["2009-11-10T23:00:02Z",100]]}]}]} ` ,
} ,
{
query : ` select load from "%DB%"."%RP%".cpu where load = 99 ` ,
expected : ` { "results":[ { }]} ` ,
} ,
{
query : ` select load from "%DB%"."%RP%".cpu where load < 99 ` ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["time","load"],"values":[["2009-11-10T23:01:02Z",80]]}]}]} ` ,
} ,
{
query : ` select load from "%DB%"."%RP%".cpu where load < 80 ` ,
expected : ` { "results":[ { }]} ` ,
} ,
{
write : ` { "database" : "%DB%", "retentionPolicy" : "%RP%", "points": [ { "name": "logs", "timestamp": "2009-11-10T23:00:02Z","fields": { "event": "disk full"}}]} ` ,
query : ` select event from "%DB%"."%RP%".logs where event = 'disk full' ` ,
expected : ` { "results":[ { "series":[ { "name":"logs","columns":["time","event"],"values":[["2009-11-10T23:00:02Z","disk full"]]}]}]} ` ,
} ,
{
write : ` { "database" : "%DB%", "retentionPolicy" : "%RP%", "points": [ { "name": "logs", "timestamp": "2009-11-10T23:00:02Z","fields": { "event": "disk full"}}]} ` ,
query : ` select event from "%DB%"."%RP%".logs where event = 'nonsense' ` ,
expected : ` { "results":[ { }]} ` ,
} ,
2015-03-06 01:27:19 +00:00
{
name : "missing measurement with `GROUP BY *`" ,
query : ` select load from "%DB%"."%RP%".missing group by * ` ,
expected : ` { "results":[ { "error":"measurement not found: \"mydb\".\"myrp\".\"missing\""}]} ` ,
} ,
2015-03-03 22:30:59 +00:00
2015-03-04 20:32:24 +00:00
// Metadata display tests
2015-03-04 20:44:56 +00:00
2015-03-04 20:21:39 +00:00
{
reset : true ,
write : ` { "database" : "%DB%" , "retentionPolicy" : "%RP%" , "points" : [
{ "name" : "cpu" , "tags" : { "host" : "server01" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server01" , "region" : "uswest" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server01" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server02" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "gpu" , "tags" : { "host" : "server02" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "gpu" , "tags" : { "host" : "server03" , "region" : "caeast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } }
] } ` ,
query : "SHOW SERIES" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["id","host","region"],"values":[[1,"server01",""],[2,"server01","uswest"],[3,"server01","useast"],[4,"server02","useast"]]}, { "name":"gpu","columns":["id","host","region"],"values":[[5,"server02","useast"],[6,"server03","caeast"]]}]}]} ` ,
} ,
{
query : "SHOW SERIES FROM cpu" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["id","host","region"],"values":[[1,"server01",""],[2,"server01","uswest"],[3,"server01","useast"],[4,"server02","useast"]]}]}]} ` ,
} ,
{
query : "SHOW SERIES WHERE region = 'uswest'" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["id","host","region"],"values":[[2,"server01","uswest"]]}]}]} ` ,
} ,
{
query : "SHOW SERIES WHERE region =~ /ca.*/" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"gpu","columns":["id","host","region"],"values":[[6,"server03","caeast"]]}]}]} ` ,
} ,
{
query : "SHOW SERIES WHERE host !~ /server0[12]/" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"gpu","columns":["id","host","region"],"values":[[6,"server03","caeast"]]}]}]} ` ,
} ,
{
query : "SHOW SERIES FROM cpu WHERE region = 'useast'" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["id","host","region"],"values":[[3,"server01","useast"],[4,"server02","useast"]]}]}]} ` ,
} ,
2015-03-04 20:44:56 +00:00
2015-03-04 20:32:24 +00:00
{
reset : true ,
write : ` { "database" : "%DB%" , "retentionPolicy" : "%RP%" , "points" : [
{ "name" : "cpu" , "tags" : { "host" : "server01" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server01" , "region" : "uswest" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server01" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server02" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "gpu" , "tags" : { "host" : "server02" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "gpu" , "tags" : { "host" : "server02" , "region" : "caeast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "other" , "tags" : { "host" : "server03" , "region" : "caeast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } }
] } ` ,
query : "SHOW MEASUREMENTS LIMIT 2" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"measurements","columns":["name"],"values":[["cpu"],["gpu"]]}]}]} ` ,
} ,
{
query : "SHOW MEASUREMENTS WHERE region =~ /ca.*/" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"measurements","columns":["name"],"values":[["gpu"],["other"]]}]}]} ` ,
} ,
{
query : "SHOW MEASUREMENTS WHERE region !~ /ca.*/" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"measurements","columns":["name"],"values":[["cpu"]]}]}]} ` ,
} ,
2015-03-04 20:21:39 +00:00
2015-03-04 20:44:56 +00:00
{
reset : true ,
write : ` { "database" : "%DB%" , "retentionPolicy" : "%RP%" , "points" : [
{ "name" : "cpu" , "tags" : { "host" : "server01" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server01" , "region" : "uswest" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server01" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server02" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "gpu" , "tags" : { "host" : "server02" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "gpu" , "tags" : { "host" : "server03" , "region" : "caeast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } }
] } ` ,
query : "SHOW TAG KEYS" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["tagKey"],"values":[["host"],["region"]]}, { "name":"gpu","columns":["tagKey"],"values":[["host"],["region"]]}]}]} ` ,
} ,
{
query : "SHOW TAG KEYS FROM cpu" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["tagKey"],"values":[["host"],["region"]]}]}]} ` ,
} ,
{
query : "SHOW TAG KEYS FROM bad" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "error":"measurement \"bad\" not found"}]} ` ,
} ,
2015-03-04 20:54:44 +00:00
{
reset : true ,
write : ` { "database" : "%DB%" , "retentionPolicy" : "%RP%" , "points" : [
{ "name" : "cpu" , "tags" : { "host" : "server01" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server01" , "region" : "uswest" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server01" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server02" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "gpu" , "tags" : { "host" : "server02" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } } ,
{ "name" : "gpu" , "tags" : { "host" : "server03" , "region" : "caeast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "value" : 100 } }
] } ` ,
query : "SHOW TAG VALUES WITH KEY = host" ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"hostTagValues","columns":["host"],"values":[["server01"],["server02"],["server03"]]}]}]} ` ,
} ,
{
query : ` SHOW TAG VALUES WITH KEY = "host" ` ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"hostTagValues","columns":["host"],"values":[["server01"],["server02"],["server03"]]}]}]} ` ,
} ,
{
query : ` SHOW TAG VALUES FROM cpu WITH KEY = host WHERE region = 'uswest' ` ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"hostTagValues","columns":["host"],"values":[["server01"]]}]}]} ` ,
} ,
{
query : ` SHOW TAG VALUES WITH KEY = host WHERE region =~ /ca.*/ ` ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"hostTagValues","columns":["host"],"values":[["server03"]]}]}]} ` ,
} ,
{
query : ` SHOW TAG VALUES WITH KEY = region WHERE host !~ /server0[12]/ ` ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"regionTagValues","columns":["region"],"values":[["caeast"]]}]}]} ` ,
} ,
{
query : ` SHOW TAG VALUES FROM cpu WITH KEY IN (host, region) WHERE region = 'uswest' ` ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"hostTagValues","columns":["host"],"values":[["server01"]]}, { "name":"regionTagValues","columns":["region"],"values":[["uswest"]]}]}]} ` ,
} ,
2015-03-04 21:01:35 +00:00
{
reset : true ,
write : ` { "database" : "%DB%" , "retentionPolicy" : "%RP%" , "points" : [
{ "name" : "cpu" , "tags" : { "host" : "server01" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "field1" : 100 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server01" , "region" : "uswest" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "field1" : 200 , "field2" : 300 , "field3" : 400 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server01" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "field1" : 200 , "field2" : 300 , "field3" : 400 } } ,
{ "name" : "cpu" , "tags" : { "host" : "server02" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "field1" : 200 , "field2" : 300 , "field3" : 400 } } ,
{ "name" : "gpu" , "tags" : { "host" : "server01" , "region" : "useast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "field4" : 200 , "field5" : 300 } } ,
{ "name" : "gpu" , "tags" : { "host" : "server03" , "region" : "caeast" } , "timestamp" : "2009-11-10T23:00:00Z" , "fields" : { "field6" : 200 , "field7" : 300 } }
] } ` ,
query : ` SHOW FIELD KEYS ` ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["fieldKey"],"values":[["field1"],["field2"],["field3"]]}, { "name":"gpu","columns":["fieldKey"],"values":[["field4"],["field5"],["field6"],["field7"]]}]}]} ` ,
} ,
{
query : ` SHOW FIELD KEYS FROM cpu ` ,
queryDb : "%DB%" ,
expected : ` { "results":[ { "series":[ { "name":"cpu","columns":["fieldKey"],"values":[["field1"],["field2"],["field3"]]}]}]} ` ,
} ,
2015-03-03 22:02:53 +00:00
// User control tests
{
name : "show users, no actual users" ,
query : ` SHOW USERS ` ,
expected : ` { "results":[ { "series":[ { "columns":["user","admin"]}]}]} ` ,
} ,
{
query : ` CREATE USER jdoe WITH PASSWORD '1337' ` ,
expected : ` { "results":[ { }]} ` ,
} ,
{
name : "show users, 1 existing user" ,
query : ` SHOW USERS ` ,
expected : ` { "results":[ { "series":[ { "columns":["user","admin"],"values":[["jdoe",false]]}]}]} ` ,
} ,
{
query : ` GRANT ALL PRIVILEGES TO jdoe ` ,
expected : ` { "results":[ { }]} ` ,
} ,
{
name : "show users, existing user as admin" ,
query : ` SHOW USERS ` ,
expected : ` { "results":[ { "series":[ { "columns":["user","admin"],"values":[["jdoe",true]]}]}]} ` ,
} ,
{
name : "grant DB privileges to user" ,
query : ` GRANT READ ON %DB% TO jdoe ` ,
expected : ` { "results":[ { }]} ` ,
} ,
{
query : ` REVOKE ALL PRIVILEGES FROM jdoe ` ,
expected : ` { "results":[ { }]} ` ,
} ,
{
name : "bad create user request" ,
query : ` CREATE USER 0xBAD WITH PASSWORD pwd1337 ` ,
expected : ` { "error":"error parsing query: found 0, expected identifier at line 1, char 13"} ` ,
} ,
{
name : "bad create user request, no name" ,
query : ` CREATE USER WITH PASSWORD pwd1337 ` ,
expected : ` { "error":"error parsing query: found WITH, expected identifier at line 1, char 13"} ` ,
} ,
{
name : "bad create user request, no password" ,
query : ` CREATE USER jdoe ` ,
expected : ` { "error":"error parsing query: found EOF, expected WITH at line 1, char 18"} ` ,
} ,
{
query : ` DROP USER jdoe ` ,
expected : ` { "results":[ { }]} ` ,
} ,
{
name : "delete non existing user" ,
query : ` DROP USER noone ` ,
expected : ` { "results":[ { "error":"user not found"}]} ` ,
} ,
// Continuous query control.
{
name : "create continuous query" ,
query : ` CREATE CONTINUOUS QUERY myquery ON %DB% BEGIN SELECT count() INTO measure1 FROM myseries GROUP BY time(10m) END ` ,
expected : ` { "results":[ { }]} ` ,
} ,
{
query : ` SHOW CONTINUOUS QUERIES ` ,
expected : ` { "results":[ { "series":[ { "name":"%DB%","columns":["name","query"],"values":[["myquery","CREATE CONTINUOUS QUERY myquery ON %DB% BEGIN SELECT count() INTO measure1 FROM myseries GROUP BY time(10m) END"]]}]}]} ` ,
} ,
2015-02-02 21:01:35 +00:00
}
2015-02-09 23:27:59 +00:00
2015-03-03 22:53:31 +00:00
for i , tt := range tests {
// If tests were explicitly requested, only run those tests.
if len ( testNums ) > 0 {
var found bool
for _ , t := range testNums {
if i == t {
found = true
break
}
}
if ! found {
continue
}
}
name := tt . name
if name == "" {
name = tt . query
}
t . Logf ( "Running test %d: %s" , i , name )
2015-02-28 02:05:30 +00:00
if tt . reset {
2015-03-04 20:21:39 +00:00
t . Logf ( ` reseting for test "%s" ` , name )
2015-02-28 02:05:30 +00:00
deleteDatabase ( t , testName , nodes , database )
createDatabase ( t , testName , nodes , database )
createRetentionPolicy ( t , testName , nodes , database , retention )
2015-02-10 03:42:56 +00:00
}
2015-02-10 03:38:06 +00:00
2015-02-28 02:05:30 +00:00
if tt . write != "" {
write ( t , nodes [ 0 ] , rewriteDbRp ( tt . write , database , retention ) )
}
2015-02-09 23:46:55 +00:00
2015-02-28 02:05:30 +00:00
if tt . query != "" {
2015-03-04 20:21:39 +00:00
urlDb := ""
if tt . queryDb != "" {
urlDb = tt . queryDb
}
got , ok := query ( t , nodes , rewriteDbRp ( urlDb , database , retention ) , rewriteDbRp ( tt . query , database , retention ) , rewriteDbRp ( tt . expected , database , retention ) )
2015-02-28 02:05:30 +00:00
if ! ok {
2015-03-03 22:02:53 +00:00
t . Errorf ( ` Test "%s" failed, expected: %s, got: %s ` , name , rewriteDbRp ( tt . expected , database , retention ) , got )
2015-02-28 02:05:30 +00:00
}
}
2015-02-10 03:38:06 +00:00
}
2015-02-09 23:40:21 +00:00
}
2015-02-20 23:11:51 +00:00
2015-02-28 02:05:30 +00:00
func TestSingleServer ( t * testing . T ) {
testName := "single server integration"
2015-02-20 23:11:51 +00:00
if testing . Short ( ) {
2015-02-28 02:05:30 +00:00
t . Skip ( fmt . Sprintf ( "skipping '%s'" , testName ) )
2015-02-20 23:11:51 +00:00
}
2015-02-28 02:05:30 +00:00
dir := tempfile ( )
defer func ( ) {
os . RemoveAll ( dir )
} ( )
2015-02-21 20:07:19 +00:00
2015-02-28 02:05:30 +00:00
nodes := createCombinedNodeCluster ( t , testName , dir , 1 , 8090 )
2015-02-21 20:07:19 +00:00
2015-02-28 02:05:30 +00:00
runTestsData ( t , testName , nodes , "mydb" , "myrp" )
2015-02-21 20:07:19 +00:00
}
2015-02-21 20:21:34 +00:00
2015-02-28 02:05:30 +00:00
func Test3NodeServer ( t * testing . T ) {
2015-03-03 22:06:39 +00:00
t . Skip ( )
2015-02-28 02:05:30 +00:00
testName := "3-node server integration"
2015-02-21 20:21:34 +00:00
if testing . Short ( ) {
2015-02-28 02:05:30 +00:00
t . Skip ( fmt . Sprintf ( "skipping '%s'" , testName ) )
2015-02-21 20:21:34 +00:00
}
2015-02-28 02:05:30 +00:00
dir := tempfile ( )
defer func ( ) {
os . RemoveAll ( dir )
} ( )
nodes := createCombinedNodeCluster ( t , testName , dir , 3 , 8190 )
runTestsData ( t , testName , nodes , "mydb" , "myrp" )
2015-02-21 20:21:34 +00:00
}