2015-01-20 17:50:13 +00:00
|
|
|
package httpd_test
|
2014-11-19 17:12:46 +00:00
|
|
|
|
|
|
|
import (
|
2014-11-20 18:05:53 +00:00
|
|
|
"bytes"
|
2015-01-05 23:47:12 +00:00
|
|
|
"encoding/base64"
|
2015-01-28 08:45:21 +00:00
|
|
|
"encoding/json"
|
2015-01-29 19:28:13 +00:00
|
|
|
"fmt"
|
2014-11-20 11:25:08 +00:00
|
|
|
"io/ioutil"
|
2014-11-19 17:12:46 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
2014-12-29 23:12:51 +00:00
|
|
|
"net/url"
|
2015-01-20 17:50:13 +00:00
|
|
|
"os"
|
2015-01-28 16:50:14 +00:00
|
|
|
"reflect"
|
2014-11-20 11:25:08 +00:00
|
|
|
"strings"
|
2014-11-19 17:12:46 +00:00
|
|
|
"testing"
|
2015-01-29 19:28:13 +00:00
|
|
|
"time"
|
2014-12-30 15:50:15 +00:00
|
|
|
|
2014-11-19 17:12:46 +00:00
|
|
|
"github.com/influxdb/influxdb"
|
2015-01-20 17:50:13 +00:00
|
|
|
"github.com/influxdb/influxdb/httpd"
|
2015-01-28 16:50:14 +00:00
|
|
|
"github.com/influxdb/influxdb/influxql"
|
2015-01-20 17:50:13 +00:00
|
|
|
"github.com/influxdb/influxdb/messaging"
|
2014-11-19 17:12:46 +00:00
|
|
|
)
|
|
|
|
|
2014-11-26 22:10:56 +00:00
|
|
|
func init() {
|
|
|
|
influxdb.BcryptCost = 4
|
|
|
|
}
|
|
|
|
|
2015-01-29 19:28:13 +00:00
|
|
|
func TestBatchWrite_UnmarshalEpoch(t *testing.T) {
|
2015-01-30 06:37:45 +00:00
|
|
|
t.Skip()
|
2015-01-29 19:28:13 +00:00
|
|
|
now := time.Now()
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
epoch int64
|
|
|
|
precision string
|
|
|
|
expected time.Time
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "nanoseconds",
|
|
|
|
epoch: now.UnixNano(),
|
|
|
|
precision: "n",
|
|
|
|
expected: now,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "microseconds",
|
|
|
|
epoch: now.Round(time.Microsecond).UnixNano() / int64(time.Microsecond),
|
|
|
|
precision: "u",
|
|
|
|
expected: now.Round(time.Microsecond),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "milliseconds",
|
|
|
|
epoch: now.Round(time.Millisecond).UnixNano() / int64(time.Millisecond),
|
|
|
|
precision: "ms",
|
|
|
|
expected: now.Round(time.Millisecond),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "seconds",
|
|
|
|
epoch: now.Round(time.Second).UnixNano() / int64(time.Second),
|
|
|
|
precision: "s",
|
|
|
|
expected: now.Round(time.Second),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "minutes",
|
|
|
|
epoch: now.Round(time.Minute).UnixNano() / int64(time.Minute),
|
|
|
|
precision: "m",
|
|
|
|
expected: now.Round(time.Minute),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "hours",
|
|
|
|
epoch: now.Round(time.Hour).UnixNano() / int64(time.Hour),
|
|
|
|
precision: "h",
|
|
|
|
expected: now.Round(time.Hour),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "max int64",
|
|
|
|
epoch: 9223372036854775807,
|
|
|
|
precision: "n",
|
|
|
|
expected: time.Unix(0, 9223372036854775807),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "100 years from now",
|
|
|
|
epoch: now.Add(time.Hour * 24 * 365 * 100).UnixNano(),
|
|
|
|
precision: "n",
|
|
|
|
expected: now.Add(time.Hour * 24 * 365 * 100),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Logf("testing %q\n", test.name)
|
|
|
|
data := []byte(fmt.Sprintf(`{"timestamp": %d, "precision":"%s"}`, test.epoch, test.precision))
|
|
|
|
t.Logf("json: %s", string(data))
|
|
|
|
var br httpd.BatchWrite
|
|
|
|
err := json.Unmarshal(data, &br)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. exptected: %v, actual: %v", nil, err)
|
|
|
|
}
|
|
|
|
if br.Timestamp != test.expected {
|
|
|
|
t.Fatalf("Unexpected time. expected: %v, actual: %v", test.expected, br.Timestamp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBatchWrite_UnmarshalRFC(t *testing.T) {
|
2015-01-30 06:37:45 +00:00
|
|
|
t.Skip()
|
2015-01-29 19:28:13 +00:00
|
|
|
now := time.Now()
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
rfc string
|
2015-01-29 19:32:31 +00:00
|
|
|
now time.Time
|
2015-01-29 19:28:13 +00:00
|
|
|
expected time.Time
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "RFC3339Nano",
|
|
|
|
rfc: time.RFC3339Nano,
|
2015-01-29 19:32:31 +00:00
|
|
|
now: now,
|
2015-01-29 19:28:13 +00:00
|
|
|
expected: now,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "RFC3339",
|
|
|
|
rfc: time.RFC3339,
|
2015-01-29 19:32:31 +00:00
|
|
|
now: now.Round(time.Second),
|
2015-01-29 19:28:13 +00:00
|
|
|
expected: now.Round(time.Second),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Logf("testing %q\n", test.name)
|
2015-01-29 19:32:31 +00:00
|
|
|
ts := test.now.Format(test.rfc)
|
2015-01-29 19:28:13 +00:00
|
|
|
data := []byte(fmt.Sprintf(`{"timestamp": %q}`, ts))
|
|
|
|
t.Logf("json: %s", string(data))
|
|
|
|
var br httpd.BatchWrite
|
|
|
|
err := json.Unmarshal(data, &br)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. exptected: %v, actual: %v", nil, err)
|
|
|
|
}
|
|
|
|
if br.Timestamp != test.expected {
|
|
|
|
t.Fatalf("Unexpected time. expected: %v, actual: %v", test.expected, br.Timestamp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-21 14:27:59 +00:00
|
|
|
func TestHandler_Databases(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
srvr.CreateDatabase("bar")
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-26 16:28:08 +00:00
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, map[string]string{"q": "SHOW DATABASES"}, nil, "")
|
2014-11-21 14:27:59 +00:00
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-28 07:40:49 +00:00
|
|
|
} else if body != `{"results":[{"rows":[{"columns":["name"],"values":[["bar"],["foo"]]}]}]}` {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-23 23:07:16 +00:00
|
|
|
func TestHandler_DatabasesPrettyPrinted(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
srvr.CreateDatabase("bar")
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-26 16:28:08 +00:00
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, map[string]string{"q": "SHOW DATABASES", "pretty": "true"}, nil, "")
|
2015-01-23 23:07:16 +00:00
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{
|
|
|
|
"results": [
|
|
|
|
{
|
|
|
|
"rows": [
|
|
|
|
{
|
|
|
|
"columns": [
|
2015-01-28 07:40:49 +00:00
|
|
|
"name"
|
2015-01-23 23:07:16 +00:00
|
|
|
],
|
2015-01-27 20:27:29 +00:00
|
|
|
"values": [
|
|
|
|
[
|
|
|
|
"bar"
|
|
|
|
],
|
|
|
|
[
|
|
|
|
"foo"
|
|
|
|
]
|
2015-01-23 23:07:16 +00:00
|
|
|
]
|
2015-01-27 20:27:29 +00:00
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}` {
|
2015-01-23 23:07:16 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-21 14:27:59 +00:00
|
|
|
func TestHandler_CreateDatabase(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 19:16:26 +00:00
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, map[string]string{"q": "CREATE DATABASE foo"}, nil, "")
|
2015-01-14 19:45:07 +00:00
|
|
|
if status != http.StatusOK {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"results":[{}]}` {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_CreateDatabase_BadRequest_NoName(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 19:48:54 +00:00
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, map[string]string{"q": "CREATE DATABASE"}, nil, "")
|
2014-11-21 14:27:59 +00:00
|
|
|
if status != http.StatusBadRequest {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_CreateDatabase_Conflict(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 19:48:54 +00:00
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, map[string]string{"q": "CREATE DATABASE foo"}, nil, "")
|
2015-01-14 00:50:01 +00:00
|
|
|
if status != http.StatusInternalServerError {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"results":[{"error":"database exists"}]}` {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_DeleteDatabase(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 19:16:26 +00:00
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, map[string]string{"q": "DROP DATABASE foo"}, nil, "")
|
2015-01-14 19:45:07 +00:00
|
|
|
if status != http.StatusOK {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"results":[{}]}` {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_DeleteDatabase_NotFound(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 19:48:54 +00:00
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, map[string]string{"q": "DROP DATABASE bar"}, nil, "")
|
2015-01-13 20:12:28 +00:00
|
|
|
if status != http.StatusInternalServerError {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"results":[{"error":"database not found"}]}` {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-20 11:25:08 +00:00
|
|
|
func TestHandler_RetentionPolicies(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
2014-12-23 06:18:05 +00:00
|
|
|
srvr.CreateRetentionPolicy("foo", influxdb.NewRetentionPolicy("bar"))
|
2014-11-20 16:02:21 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
2014-11-19 18:30:39 +00:00
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-26 16:28:08 +00:00
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, map[string]string{"q": "SHOW RETENTION POLICIES foo"}, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2014-11-20 11:25:08 +00:00
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-28 00:35:32 +00:00
|
|
|
} else if body != `{"results":[{"rows":[{"columns":["name","duration","replicaN"],"values":[["bar","168h0m0s",1]]}]}]}` {
|
2014-11-20 11:25:08 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
2014-11-19 18:30:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-21 14:27:59 +00:00
|
|
|
func TestHandler_RetentionPolicies_DatabaseNotFound(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-26 16:28:08 +00:00
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, map[string]string{"q": "SHOW RETENTION POLICIES foo"}, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-14 04:50:29 +00:00
|
|
|
if status != http.StatusInternalServerError {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"results":[{"error":"database not found"}]}` {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-20 18:05:53 +00:00
|
|
|
func TestHandler_CreateRetentionPolicy(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 20:12:28 +00:00
|
|
|
query := map[string]string{"q": "CREATE RETENTION POLICY bar ON foo DURATION 1h REPLICATION 1"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-14 19:45:07 +00:00
|
|
|
if status != http.StatusOK {
|
2014-11-20 18:05:53 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"results":[{}]}` {
|
2014-11-20 18:05:53 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-28 19:27:05 +00:00
|
|
|
func TestHandler_CreateRetentionPolicyAsDefault(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
query := map[string]string{"q": "CREATE RETENTION POLICY bar ON foo DURATION 1h REPLICATION 1 DEFAULT"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
} else if body != `{"results":[{}]}` {
|
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
|
|
|
|
rp, err := srvr.DefaultRetentionPolicy("foo")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if rp.Name != "bar" {
|
|
|
|
t.Fatalf("default retention policy mismatch:\n exp=%s\n got=%s\n", "bar", rp.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-21 14:27:59 +00:00
|
|
|
func TestHandler_CreateRetentionPolicy_DatabaseNotFound(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 20:12:28 +00:00
|
|
|
query := map[string]string{"q": "CREATE RETENTION POLICY bar ON foo DURATION 1h REPLICATION 1"}
|
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 20:12:28 +00:00
|
|
|
if status != http.StatusInternalServerError {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-20 18:05:53 +00:00
|
|
|
func TestHandler_CreateRetentionPolicy_Conflict(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 20:12:28 +00:00
|
|
|
query := map[string]string{"q": "CREATE RETENTION POLICY bar ON foo DURATION 1h REPLICATION 1"}
|
|
|
|
MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 20:12:28 +00:00
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
|
|
|
|
|
|
|
if status != http.StatusInternalServerError {
|
2014-11-20 18:05:53 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_CreateRetentionPolicy_BadRequest(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 20:12:28 +00:00
|
|
|
query := map[string]string{"q": "CREATE RETENTION POLICY bar ON foo DURATION ***BAD*** REPLICATION 1"}
|
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2014-11-20 18:05:53 +00:00
|
|
|
if status != http.StatusBadRequest {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-20 22:48:25 +00:00
|
|
|
func TestHandler_UpdateRetentionPolicy(t *testing.T) {
|
2015-01-09 04:58:33 +00:00
|
|
|
t.Skip()
|
2014-11-20 22:48:25 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
2014-12-23 06:18:05 +00:00
|
|
|
srvr.CreateRetentionPolicy("foo", influxdb.NewRetentionPolicy("bar"))
|
2014-11-20 22:48:25 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-14 05:22:36 +00:00
|
|
|
query := map[string]string{"q": "ALTER RETENTION POLICY bar ON foo REPLICATION 42 DURATION 1m"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2014-12-23 06:18:05 +00:00
|
|
|
// Verify updated policy.
|
2015-01-14 05:22:36 +00:00
|
|
|
p, _ := srvr.RetentionPolicy("foo", "bar")
|
2015-01-14 19:45:07 +00:00
|
|
|
if status != http.StatusOK {
|
2014-11-20 22:48:25 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2014-11-26 22:10:56 +00:00
|
|
|
} else if body != "" {
|
2014-11-20 22:48:25 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
2015-01-14 05:22:36 +00:00
|
|
|
} else if p.ReplicaN != 42 {
|
|
|
|
t.Fatalf("unexpected replication factor: %d", p.ReplicaN)
|
2014-11-20 22:48:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-21 14:27:59 +00:00
|
|
|
func TestHandler_UpdateRetentionPolicy_BadRequest(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
2014-12-23 06:18:05 +00:00
|
|
|
srvr.CreateRetentionPolicy("foo", influxdb.NewRetentionPolicy("bar"))
|
2014-11-21 14:27:59 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-13 20:12:28 +00:00
|
|
|
query := map[string]string{"q": "ALTER RETENTION POLICY bar ON foo DURATION ***BAD*** REPLICATION 1"}
|
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2014-12-23 06:18:05 +00:00
|
|
|
// Verify response.
|
2014-11-21 14:27:59 +00:00
|
|
|
if status != http.StatusBadRequest {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_UpdateRetentionPolicy_DatabaseNotFound(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-13 20:12:28 +00:00
|
|
|
query := map[string]string{"q": "ALTER RETENTION POLICY bar ON foo DURATION 1h REPLICATION 1"}
|
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 20:12:28 +00:00
|
|
|
// Verify response.
|
|
|
|
if status != http.StatusInternalServerError {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-20 22:48:25 +00:00
|
|
|
func TestHandler_UpdateRetentionPolicy_NotFound(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
2015-01-13 20:12:28 +00:00
|
|
|
srvr.CreateRetentionPolicy("foo", influxdb.NewRetentionPolicy("bar"))
|
2014-11-20 22:48:25 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-13 20:12:28 +00:00
|
|
|
query := map[string]string{"q": "ALTER RETENTION POLICY qux ON foo DURATION 1h REPLICATION 1"}
|
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 20:12:28 +00:00
|
|
|
// Verify response.
|
|
|
|
if status != http.StatusInternalServerError {
|
2014-11-20 22:48:25 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-20 19:01:55 +00:00
|
|
|
func TestHandler_DeleteRetentionPolicy(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
2014-12-23 06:18:05 +00:00
|
|
|
srvr.CreateRetentionPolicy("foo", influxdb.NewRetentionPolicy("bar"))
|
2014-11-20 19:01:55 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-14 05:22:36 +00:00
|
|
|
query := map[string]string{"q": "DROP RETENTION POLICY bar ON foo"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
|
|
|
|
2015-01-14 19:45:07 +00:00
|
|
|
if status != http.StatusOK {
|
2014-11-20 19:01:55 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"results":[{}]}` {
|
2014-11-20 19:01:55 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-21 14:27:59 +00:00
|
|
|
func TestHandler_DeleteRetentionPolicy_DatabaseNotFound(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-14 05:22:36 +00:00
|
|
|
query := map[string]string{"q": "DROP RETENTION POLICY bar ON qux"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-14 05:22:36 +00:00
|
|
|
if status != http.StatusInternalServerError {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"results":[{"error":"database not found"}]}` {
|
2014-11-21 14:27:59 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-20 19:01:55 +00:00
|
|
|
func TestHandler_DeleteRetentionPolicy_NotFound(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-14 05:22:36 +00:00
|
|
|
query := map[string]string{"q": "DROP RETENTION POLICY bar ON foo"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-14 05:22:36 +00:00
|
|
|
if status != http.StatusInternalServerError {
|
2014-11-20 19:01:55 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"results":[{"error":"retention policy not found"}]}` {
|
2014-11-20 19:01:55 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
2014-11-20 11:25:08 +00:00
|
|
|
}
|
|
|
|
|
2014-11-20 23:50:15 +00:00
|
|
|
func TestHandler_Ping(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 18:55:40 +00:00
|
|
|
status, _ := MustHTTP("GET", s.URL+`/ping`, nil, nil, "")
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-22 20:54:19 +00:00
|
|
|
if status != http.StatusNoContent {
|
2014-11-20 23:50:15 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-08 18:39:33 +00:00
|
|
|
func TestHandler_Users_NoUsers(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-27 03:11:48 +00:00
|
|
|
query := map[string]string{"q": "SHOW USERS"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-08 18:39:33 +00:00
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-28 00:48:17 +00:00
|
|
|
} else if body != `{"results":[{"rows":[{"columns":["user","admin"]}]}]}` {
|
2014-12-08 18:39:33 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_Users_OneUser(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
2014-12-23 06:18:05 +00:00
|
|
|
srvr.CreateUser("jdoe", "1337", true)
|
2014-12-08 18:39:33 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-27 03:11:48 +00:00
|
|
|
query := map[string]string{"q": "SHOW USERS"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-08 18:39:33 +00:00
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-28 00:48:17 +00:00
|
|
|
} else if body != `{"results":[{"rows":[{"columns":["user","admin"],"values":[["jdoe",true]]}]}]}` {
|
2014-12-08 18:39:33 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_Users_MultipleUsers(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
2014-12-23 06:18:05 +00:00
|
|
|
srvr.CreateUser("jdoe", "1337", false)
|
|
|
|
srvr.CreateUser("mclark", "1337", true)
|
|
|
|
srvr.CreateUser("csmith", "1337", false)
|
2014-12-08 18:39:33 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-27 03:11:48 +00:00
|
|
|
query := map[string]string{"q": "SHOW USERS"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-12-08 18:39:33 +00:00
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-28 00:48:17 +00:00
|
|
|
} else if body != `{"results":[{"rows":[{"columns":["user","admin"],"values":[["csmith",false],["jdoe",false],["mclark",true]]}]}]}` {
|
2014-12-08 18:39:33 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-23 06:18:05 +00:00
|
|
|
func TestHandler_CreateUser(t *testing.T) {
|
2014-11-26 14:36:43 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-19 20:01:32 +00:00
|
|
|
query := map[string]string{"q": `CREATE USER testuser WITH PASSWORD '1337'`}
|
2015-01-14 05:52:46 +00:00
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2015-01-14 19:45:07 +00:00
|
|
|
if status != http.StatusOK {
|
2014-11-26 14:36:43 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"results":[{}]}` {
|
2014-11-26 14:36:43 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-23 06:18:05 +00:00
|
|
|
func TestHandler_CreateUser_BadRequest(t *testing.T) {
|
2014-11-26 14:36:43 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-14 05:52:46 +00:00
|
|
|
query := map[string]string{"q": "CREATE USER 0xBAD WITH PASSWORD pwd1337"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2014-11-26 14:36:43 +00:00
|
|
|
if status != http.StatusBadRequest {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"error":"error parsing query: found 0, expected identifier at line 1, char 13"}` {
|
2014-11-26 14:36:43 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-14 05:52:46 +00:00
|
|
|
func TestHandler_CreateUser_BadRequest_NoName(t *testing.T) {
|
2014-11-26 14:36:43 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-14 05:52:46 +00:00
|
|
|
query := map[string]string{"q": "CREATE USER WITH PASSWORD pwd1337"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
|
|
|
if status != http.StatusBadRequest {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"error":"error parsing query: found WITH, expected identifier at line 1, char 13"}` {
|
2015-01-14 05:52:46 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_CreateUser_BadRequest_NoPassword(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
query := map[string]string{"q": "CREATE USER jdoe"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
|
|
|
if status != http.StatusBadRequest {
|
2014-11-26 16:02:17 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"error":"error parsing query: found EOF, expected WITH at line 1, char 18"}` {
|
2014-11-26 16:02:17 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-23 06:18:05 +00:00
|
|
|
func TestHandler_UpdateUser(t *testing.T) {
|
2015-01-09 04:58:33 +00:00
|
|
|
t.Skip()
|
2014-11-26 22:10:56 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
2014-12-23 06:18:05 +00:00
|
|
|
srvr.CreateUser("jdoe", "1337", false)
|
2014-11-26 22:10:56 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2014-12-23 06:18:05 +00:00
|
|
|
// Save original password hash.
|
|
|
|
hash := srvr.User("jdoe").Hash
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2014-12-23 06:18:05 +00:00
|
|
|
// Update user password.
|
2015-01-13 18:55:40 +00:00
|
|
|
status, body := MustHTTP("PUT", s.URL+`/users/jdoe`, nil, nil, `{"password": "7331"}`)
|
2015-01-14 19:45:07 +00:00
|
|
|
if status != http.StatusOK {
|
2014-11-26 22:10:56 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
} else if body != `` {
|
|
|
|
t.Fatalf("unexpected body: %s", body)
|
2014-12-23 06:18:05 +00:00
|
|
|
} else if srvr.User("jdoe").Hash == hash {
|
2014-11-26 22:10:56 +00:00
|
|
|
t.Fatalf("expected password hash to change")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-23 06:18:05 +00:00
|
|
|
func TestHandler_UpdateUser_PasswordBadRequest(t *testing.T) {
|
2015-01-09 04:58:33 +00:00
|
|
|
t.Skip()
|
2014-11-26 22:10:56 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
2014-12-23 06:18:05 +00:00
|
|
|
srvr.CreateUser("jdoe", "1337", false)
|
2014-11-26 22:10:56 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-13 18:55:40 +00:00
|
|
|
status, body := MustHTTP("PUT", s.URL+`/users/jdoe`, nil, nil, `{"password": 10}`)
|
2014-11-26 22:10:56 +00:00
|
|
|
if status != http.StatusBadRequest {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2014-12-21 17:45:50 +00:00
|
|
|
} else if body != `json: cannot unmarshal number into Go value of type string` {
|
2014-11-26 22:10:56 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-23 06:18:05 +00:00
|
|
|
func TestHandler_DeleteUser(t *testing.T) {
|
2014-11-26 22:10:56 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
2014-12-23 06:18:05 +00:00
|
|
|
srvr.CreateUser("jdoe", "1337", false)
|
2014-11-26 22:10:56 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-14 05:57:59 +00:00
|
|
|
query := map[string]string{"q": "DROP USER jdoe"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2015-01-14 19:45:07 +00:00
|
|
|
if status != http.StatusOK {
|
2014-12-05 18:31:12 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"results":[{}]}` {
|
2014-12-05 18:31:12 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-23 06:18:05 +00:00
|
|
|
func TestHandler_DeleteUser_UserNotFound(t *testing.T) {
|
2014-12-05 18:31:12 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
2014-12-21 17:45:50 +00:00
|
|
|
|
2015-01-14 05:57:59 +00:00
|
|
|
query := map[string]string{"q": "DROP USER jdoe"}
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
|
|
|
if status != http.StatusInternalServerError {
|
2014-12-05 18:31:12 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2015-01-27 20:27:29 +00:00
|
|
|
} else if body != `{"results":[{"error":"user not found"}]}` {
|
2014-12-05 18:31:12 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 15:50:15 +00:00
|
|
|
func TestHandler_DataNodes(t *testing.T) {
|
2015-01-09 04:58:33 +00:00
|
|
|
t.Skip()
|
2015-01-10 15:48:50 +00:00
|
|
|
srvr := OpenUninitializedServer(NewMessagingClient())
|
2014-12-30 15:50:15 +00:00
|
|
|
srvr.CreateDataNode(MustParseURL("http://localhost:1000"))
|
|
|
|
srvr.CreateDataNode(MustParseURL("http://localhost:2000"))
|
|
|
|
srvr.CreateDataNode(MustParseURL("http://localhost:3000"))
|
2014-12-29 23:12:51 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-13 18:55:40 +00:00
|
|
|
status, body := MustHTTP("GET", s.URL+`/data_nodes`, nil, nil, "")
|
2014-12-29 23:12:51 +00:00
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
} else if body != `[{"id":1,"url":"http://localhost:1000"},{"id":2,"url":"http://localhost:2000"},{"id":3,"url":"http://localhost:3000"}]` {
|
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 15:50:15 +00:00
|
|
|
func TestHandler_CreateDataNode(t *testing.T) {
|
2015-01-09 04:58:33 +00:00
|
|
|
t.Skip()
|
2015-01-10 15:48:50 +00:00
|
|
|
srvr := OpenUninitializedServer(NewMessagingClient())
|
2014-12-29 23:12:51 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-13 18:55:40 +00:00
|
|
|
status, body := MustHTTP("POST", s.URL+`/data_nodes`, nil, nil, `{"url":"http://localhost:1000"}`)
|
2015-01-14 19:45:07 +00:00
|
|
|
if status != http.StatusOK {
|
2014-12-29 23:12:51 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
} else if body != `{"id":1,"url":"http://localhost:1000"}` {
|
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 15:50:15 +00:00
|
|
|
func TestHandler_CreateDataNode_BadRequest(t *testing.T) {
|
2015-01-09 04:58:33 +00:00
|
|
|
t.Skip()
|
2014-12-29 23:12:51 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-13 18:55:40 +00:00
|
|
|
status, body := MustHTTP("POST", s.URL+`/data_nodes`, nil, nil, `{"name":`)
|
2014-12-29 23:12:51 +00:00
|
|
|
if status != http.StatusBadRequest {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
} else if body != `unexpected EOF` {
|
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 15:50:15 +00:00
|
|
|
func TestHandler_CreateDataNode_InternalServerError(t *testing.T) {
|
2015-01-09 04:58:33 +00:00
|
|
|
t.Skip()
|
2014-12-29 23:12:51 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-13 18:55:40 +00:00
|
|
|
status, body := MustHTTP("POST", s.URL+`/data_nodes`, nil, nil, `{"url":""}`)
|
2014-12-29 23:12:51 +00:00
|
|
|
if status != http.StatusInternalServerError {
|
2014-12-30 22:52:44 +00:00
|
|
|
t.Fatalf("unexpected status: %d, %s", status, body)
|
2014-12-30 15:50:15 +00:00
|
|
|
} else if body != `data node url required` {
|
2014-12-29 23:12:51 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 15:50:15 +00:00
|
|
|
func TestHandler_DeleteDataNode(t *testing.T) {
|
2015-01-09 04:58:33 +00:00
|
|
|
t.Skip()
|
2014-12-29 23:12:51 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
2014-12-30 15:50:15 +00:00
|
|
|
srvr.CreateDataNode(MustParseURL("http://localhost:1000"))
|
2014-12-29 23:12:51 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-13 18:55:40 +00:00
|
|
|
status, body := MustHTTP("DELETE", s.URL+`/data_nodes/1`, nil, nil, "")
|
2015-01-14 19:45:07 +00:00
|
|
|
if status != http.StatusOK {
|
2014-12-29 23:12:51 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
} else if body != `` {
|
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 15:50:15 +00:00
|
|
|
func TestHandler_DeleteUser_DataNodeNotFound(t *testing.T) {
|
2015-01-09 04:58:33 +00:00
|
|
|
t.Skip()
|
2014-12-29 23:12:51 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-13 18:55:40 +00:00
|
|
|
status, body := MustHTTP("DELETE", s.URL+`/data_nodes/10000`, nil, nil, "")
|
2014-12-29 23:12:51 +00:00
|
|
|
if status != http.StatusNotFound {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
2014-12-30 15:50:15 +00:00
|
|
|
} else if body != `data node not found` {
|
2014-12-29 23:12:51 +00:00
|
|
|
t.Fatalf("unexpected body: %s", body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-05 23:47:12 +00:00
|
|
|
// Perform a subset of endpoint testing, with authentication enabled.
|
|
|
|
|
|
|
|
func TestHandler_AuthenticatedCreateAdminUser(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewAuthenticatedHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
// Attempting to create a non-admin user should fail.
|
2015-01-21 19:29:51 +00:00
|
|
|
query := map[string]string{"q": "CREATE USER maeve WITH PASSWORD 'pass'"}
|
2015-01-14 06:45:03 +00:00
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2015-01-05 23:47:12 +00:00
|
|
|
if status != http.StatusUnauthorized {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creating the first admin user, without supplying authentication
|
|
|
|
// credentials should be OK.
|
2015-01-21 19:29:51 +00:00
|
|
|
query = map[string]string{"q": "CREATE USER orla WITH PASSWORD 'pass' WITH ALL PRIVILEGES"}
|
2015-01-14 06:45:03 +00:00
|
|
|
status, _ = MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2015-01-14 19:45:07 +00:00
|
|
|
if status != http.StatusOK {
|
2015-01-05 23:47:12 +00:00
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creating a second admin user, without supplying authentication
|
|
|
|
// credentials should fail.
|
2015-01-21 19:29:51 +00:00
|
|
|
query = map[string]string{"q": "CREATE USER louise WITH PASSWORD 'pass' WITH ALL PRIVILEGES"}
|
2015-01-14 06:45:03 +00:00
|
|
|
status, _ = MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2015-01-05 23:47:12 +00:00
|
|
|
if status != http.StatusUnauthorized {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_AuthenticatedDatabases_Unauthorized(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewAuthenticatedHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-26 16:28:08 +00:00
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, map[string]string{"q": "SHOW DATABASES"}, nil, "")
|
2015-01-05 23:47:12 +00:00
|
|
|
if status != http.StatusUnauthorized {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_AuthenticatedDatabases_AuthorizedQueryParams(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateUser("lisa", "password", true)
|
|
|
|
s := NewAuthenticatedHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-26 16:28:08 +00:00
|
|
|
query := map[string]string{"q": "SHOW DATABASES", "u": "lisa", "p": "password"}
|
2015-01-14 06:45:03 +00:00
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
2015-01-05 23:47:12 +00:00
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-14 06:45:03 +00:00
|
|
|
func TestHandler_AuthenticatedDatabases_UnauthorizedQueryParams(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateUser("lisa", "password", true)
|
|
|
|
s := NewAuthenticatedHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-26 16:28:08 +00:00
|
|
|
query := map[string]string{"q": "SHOW DATABASES", "u": "lisa", "p": "wrong"}
|
2015-01-14 06:45:03 +00:00
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
|
|
|
if status != http.StatusUnauthorized {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-05 23:47:12 +00:00
|
|
|
func TestHandler_AuthenticatedDatabases_AuthorizedBasicAuth(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateUser("lisa", "password", true)
|
|
|
|
s := NewAuthenticatedHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
auth := make(map[string]string)
|
|
|
|
auth["Authorization"] = "Basic " + base64.StdEncoding.EncodeToString([]byte("lisa:password"))
|
2015-01-26 16:28:08 +00:00
|
|
|
query := map[string]string{"q": "SHOW DATABASES"}
|
2015-01-14 06:45:03 +00:00
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, auth, "")
|
2015-01-05 23:47:12 +00:00
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-14 06:45:03 +00:00
|
|
|
func TestHandler_AuthenticatedDatabases_UnauthorizedBasicAuth(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateUser("lisa", "password", true)
|
|
|
|
s := NewAuthenticatedHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
auth := make(map[string]string)
|
|
|
|
auth["Authorization"] = "Basic " + base64.StdEncoding.EncodeToString([]byte("lisa:wrong"))
|
2015-01-26 16:28:08 +00:00
|
|
|
query := map[string]string{"q": "SHOW DATABASES"}
|
2015-01-14 06:45:03 +00:00
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, auth, "")
|
|
|
|
if status != http.StatusUnauthorized {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-30 02:26:28 +00:00
|
|
|
func TestHandler_GrantAdmin(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
// Create a cluster admin that will grant admin to "john".
|
|
|
|
srvr.CreateUser("lisa", "password", true)
|
|
|
|
// Create user that will be granted cluster admin.
|
|
|
|
srvr.CreateUser("john", "password", false)
|
|
|
|
s := NewAuthenticatedHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
auth := make(map[string]string)
|
|
|
|
auth["Authorization"] = "Basic " + base64.StdEncoding.EncodeToString([]byte("lisa:password"))
|
|
|
|
query := map[string]string{"q": "GRANT ALL PRIVILEGES TO john"}
|
|
|
|
|
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, auth, "")
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
|
|
|
|
if u := srvr.User("john"); !u.Admin {
|
|
|
|
t.Fatal(`expected user "john" to be admin`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-30 03:02:58 +00:00
|
|
|
func TestHandler_GrantDBPrivilege(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
// Create a cluster admin that will grant privilege to "john".
|
|
|
|
srvr.CreateUser("lisa", "password", true)
|
|
|
|
// Create user that will be granted a privilege.
|
|
|
|
srvr.CreateUser("john", "password", false)
|
|
|
|
s := NewAuthenticatedHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
auth := make(map[string]string)
|
|
|
|
auth["Authorization"] = "Basic " + base64.StdEncoding.EncodeToString([]byte("lisa:password"))
|
|
|
|
query := map[string]string{"q": "GRANT READ ON foo TO john"}
|
|
|
|
|
|
|
|
status, _ := MustHTTP("GET", s.URL+`/query`, query, auth, "")
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
|
|
|
|
u := srvr.User("john")
|
|
|
|
if p, ok := u.Privileges["foo"]; !ok {
|
|
|
|
t.Fatal(`expected john to have privileges on foo but he has none`)
|
|
|
|
} else if p != influxql.ReadPrivilege {
|
|
|
|
t.Fatalf(`expected john to have read privilege on foo but he has %s`, p.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-30 02:56:23 +00:00
|
|
|
func TestHandler_RevokeAdmin(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
// Create a cluster admin that will revoke admin from "john".
|
|
|
|
srvr.CreateUser("lisa", "password", true)
|
|
|
|
// Create user that will have cluster admin revoked.
|
|
|
|
srvr.CreateUser("john", "password", true)
|
|
|
|
s := NewAuthenticatedHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
auth := make(map[string]string)
|
|
|
|
auth["Authorization"] = "Basic " + base64.StdEncoding.EncodeToString([]byte("lisa:password"))
|
|
|
|
query := map[string]string{"q": "REVOKE ALL PRIVILEGES FROM john"}
|
|
|
|
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, auth, "")
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Log(body)
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
|
|
|
|
if u := srvr.User("john"); u.Admin {
|
|
|
|
t.Fatal(`expected user "john" not to be admin`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_RevokeDBPrivilege(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
// Create a cluster admin that will revoke privilege from "john".
|
|
|
|
srvr.CreateUser("lisa", "password", true)
|
|
|
|
// Create user that will have privilege revoked.
|
|
|
|
srvr.CreateUser("john", "password", false)
|
|
|
|
u := srvr.User("john")
|
|
|
|
u.Privileges["foo"] = influxql.ReadPrivilege
|
|
|
|
s := NewAuthenticatedHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
auth := make(map[string]string)
|
|
|
|
auth["Authorization"] = "Basic " + base64.StdEncoding.EncodeToString([]byte("lisa:password"))
|
|
|
|
query := map[string]string{"q": "REVOKE READ ON foo FROM john"}
|
|
|
|
|
|
|
|
status, body := MustHTTP("GET", s.URL+`/query`, query, auth, "")
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Log(body)
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := u.Privileges["foo"]; ok {
|
|
|
|
t.Fatal(`expected user "john" not to have privileges on foo`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-14 21:08:53 +00:00
|
|
|
func TestHandler_serveWriteSeries(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
srvr.CreateRetentionPolicy("foo", influxdb.NewRetentionPolicy("bar"))
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
2015-01-14 21:49:37 +00:00
|
|
|
status, _ := MustHTTP("POST", s.URL+`/write`, nil, nil, `{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "cpu", "tags": {"host": "server01"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}}]}`)
|
2015-01-14 21:08:53 +00:00
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Fatalf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-15 21:58:21 +00:00
|
|
|
func TestHandler_serveWriteSeries_noDatabaseExists(t *testing.T) {
|
2015-01-15 20:09:52 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
status, body := MustHTTP("POST", s.URL+`/write`, nil, nil, `{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "cpu", "tags": {"host": "server01"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}}]}`)
|
|
|
|
|
2015-01-15 21:58:21 +00:00
|
|
|
expectedStatus := http.StatusNotFound
|
|
|
|
if status != expectedStatus {
|
|
|
|
t.Fatalf("unexpected status: expected: %d, actual: %d", expectedStatus, status)
|
2015-01-15 20:09:52 +00:00
|
|
|
}
|
|
|
|
|
2015-01-15 21:58:21 +00:00
|
|
|
response := `{"error":"database not found: \"foo\""}`
|
2015-01-15 20:09:52 +00:00
|
|
|
if body != response {
|
|
|
|
t.Fatalf("unexpected body: expected %s, actual %s", response, body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_serveWriteSeries_invalidJSON(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
status, body := MustHTTP("POST", s.URL+`/write`, nil, nil, `{"database" : foo", "retentionPolicy" : "bar", "points": [{"name": "cpu", "tags": {"host": "server01"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}}]}`)
|
|
|
|
|
|
|
|
if status != http.StatusInternalServerError {
|
|
|
|
t.Fatalf("unexpected status: expected: %d, actual: %d", http.StatusInternalServerError, status)
|
|
|
|
}
|
|
|
|
|
|
|
|
response := `{"error":"invalid character 'o' in literal false (expecting 'a')"}`
|
|
|
|
if body != response {
|
|
|
|
t.Fatalf("unexpected body: expected %s, actual %s", response, body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-15 21:58:21 +00:00
|
|
|
func TestHandler_serveWriteSeries_noDatabaseSpecified(t *testing.T) {
|
2015-01-15 21:42:38 +00:00
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
status, body := MustHTTP("POST", s.URL+`/write`, nil, nil, `{}`)
|
|
|
|
|
|
|
|
if status != http.StatusInternalServerError {
|
|
|
|
t.Fatalf("unexpected status: expected: %d, actual: %d", http.StatusInternalServerError, status)
|
|
|
|
}
|
|
|
|
|
2015-01-15 21:58:21 +00:00
|
|
|
response := `{"error":"database is required"}`
|
2015-01-15 21:42:38 +00:00
|
|
|
if body != response {
|
|
|
|
t.Fatalf("unexpected body: expected %s, actual %s", response, body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-28 04:36:19 +00:00
|
|
|
func TestHandler_serveShowSeries(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
srvr.CreateRetentionPolicy("foo", influxdb.NewRetentionPolicy("bar"))
|
2015-01-28 16:50:14 +00:00
|
|
|
srvr.SetDefaultRetentionPolicy("foo", "bar")
|
2015-01-28 04:36:19 +00:00
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
status, body := MustHTTP("POST", s.URL+`/write`, nil, nil, `{"database" : "foo", "retentionPolicy" : "bar", "points": [
|
|
|
|
{"name": "cpu", "tags": {"host": "server01"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "cpu", "tags": {"host": "server01", "region": "uswest"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "cpu", "tags": {"host": "server01", "region": "useast"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "cpu", "tags": {"host": "server02", "region": "useast"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "gpu", "tags": {"host": "server02", "region": "useast"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}}
|
|
|
|
]}`)
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Log(body)
|
|
|
|
t.Fatalf("unexpected status after write: %d", status)
|
|
|
|
}
|
|
|
|
|
2015-01-28 08:45:21 +00:00
|
|
|
var tests = []struct {
|
|
|
|
q string
|
2015-01-28 16:50:14 +00:00
|
|
|
r *influxdb.Results
|
2015-01-28 08:45:21 +00:00
|
|
|
err string
|
|
|
|
}{
|
|
|
|
// SHOW SERIES
|
|
|
|
{
|
|
|
|
q: `SHOW SERIES`,
|
2015-01-28 16:50:14 +00:00
|
|
|
r: &influxdb.Results{
|
|
|
|
Results: []*influxdb.Result{
|
|
|
|
&influxdb.Result{
|
|
|
|
Rows: []*influxql.Row{
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "cpu",
|
|
|
|
Columns: []string{"host", "region"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"server01", ""}),
|
|
|
|
str2iface([]string{"server01", "uswest"}),
|
|
|
|
str2iface([]string{"server01", "useast"}),
|
|
|
|
str2iface([]string{"server02", "useast"}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "gpu",
|
|
|
|
Columns: []string{"host", "region"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"server02", "useast"}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2015-01-28 15:37:25 +00:00
|
|
|
},
|
2015-01-28 16:50:14 +00:00
|
|
|
// SHOW SERIES ... LIMIT
|
|
|
|
// {
|
|
|
|
// q: `SHOW SERIES LIMIT 1`,
|
|
|
|
// r: &influxdb.Results{
|
|
|
|
// Results: []*influxdb.Result{
|
|
|
|
// &influxdb.Result{
|
|
|
|
// Rows: []*influxql.Row{
|
|
|
|
// &influxql.Row{
|
|
|
|
// Name: "cpu",
|
|
|
|
// Columns: []string{"host", "region"},
|
|
|
|
// Values: [][]interface{}{
|
|
|
|
// str2iface([]string{"server01", ""}),
|
|
|
|
// str2iface([]string{"server01", "uswest"}),
|
|
|
|
// str2iface([]string{"server01", "useast"}),
|
|
|
|
// str2iface([]string{"server02", "useast"}),
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// SHOW SERIES FROM
|
2015-01-28 15:37:25 +00:00
|
|
|
{
|
2015-01-28 16:50:14 +00:00
|
|
|
q: `SHOW SERIES FROM cpu`,
|
|
|
|
r: &influxdb.Results{
|
|
|
|
Results: []*influxdb.Result{
|
|
|
|
&influxdb.Result{
|
|
|
|
Rows: []*influxql.Row{
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "cpu",
|
|
|
|
Columns: []string{"host", "region"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"server01", ""}),
|
|
|
|
str2iface([]string{"server01", "uswest"}),
|
|
|
|
str2iface([]string{"server01", "useast"}),
|
|
|
|
str2iface([]string{"server02", "useast"}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
// SHOW SERIES WHERE
|
|
|
|
{
|
|
|
|
q: `SHOW SERIES WHERE region = 'uswest'`,
|
|
|
|
r: &influxdb.Results{
|
|
|
|
Results: []*influxdb.Result{
|
|
|
|
&influxdb.Result{
|
|
|
|
Rows: []*influxql.Row{
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "cpu",
|
|
|
|
Columns: []string{"host", "region"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"server01", "uswest"}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
// SHOW SERIES FROM ... WHERE
|
|
|
|
{
|
|
|
|
q: `SHOW SERIES FROM cpu WHERE region = 'useast'`,
|
|
|
|
r: &influxdb.Results{
|
|
|
|
Results: []*influxdb.Result{
|
|
|
|
&influxdb.Result{
|
|
|
|
Rows: []*influxql.Row{
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "cpu",
|
|
|
|
Columns: []string{"host", "region"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"server01", "useast"}),
|
|
|
|
str2iface([]string{"server02", "useast"}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2015-01-28 08:45:21 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tt := range tests {
|
|
|
|
query := map[string]string{"db": "foo", "q": tt.q}
|
|
|
|
status, body = MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Logf("query #%d: %s", i, tt.q)
|
|
|
|
t.Log(body)
|
|
|
|
t.Errorf("unexpected status: %d", status)
|
|
|
|
}
|
2015-01-28 04:36:19 +00:00
|
|
|
|
2015-01-28 08:45:21 +00:00
|
|
|
r := &influxdb.Results{}
|
|
|
|
if err := json.Unmarshal([]byte(body), r); err != nil {
|
|
|
|
t.Logf("query #%d: %s", i, tt.q)
|
|
|
|
t.Log(body)
|
2015-01-28 16:50:14 +00:00
|
|
|
t.Error(err)
|
2015-01-28 08:45:21 +00:00
|
|
|
}
|
|
|
|
|
2015-01-28 16:50:14 +00:00
|
|
|
if !reflect.DeepEqual(tt.err, errstring(r.Err)) {
|
|
|
|
t.Errorf("%d. %s: error mismatch:\n exp=%s\n got=%s\n\n", i, tt.q, tt.err, r.Err)
|
|
|
|
} else if tt.err == "" && !reflect.DeepEqual(tt.r, r) {
|
|
|
|
t.Log(body)
|
|
|
|
t.Errorf("%d. %s: result mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.q, tt.r, r)
|
2015-01-28 08:45:21 +00:00
|
|
|
}
|
2015-01-28 04:36:19 +00:00
|
|
|
}
|
2015-01-28 08:45:21 +00:00
|
|
|
}
|
2015-01-28 04:36:19 +00:00
|
|
|
|
2015-01-28 08:45:21 +00:00
|
|
|
// str2iface converts an array of strings to an array of interfaces.
|
|
|
|
func str2iface(strs []string) []interface{} {
|
2015-01-28 16:50:14 +00:00
|
|
|
a := make([]interface{}, 0, len(strs))
|
2015-01-28 08:45:21 +00:00
|
|
|
for _, s := range strs {
|
|
|
|
a = append(a, interface{}(s))
|
|
|
|
}
|
|
|
|
return a
|
2015-01-28 04:36:19 +00:00
|
|
|
}
|
|
|
|
|
2015-01-28 05:51:09 +00:00
|
|
|
func TestHandler_serveShowMeasurements(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
srvr.CreateRetentionPolicy("foo", influxdb.NewRetentionPolicy("bar"))
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
status, body := MustHTTP("POST", s.URL+`/write`, nil, nil, `{"database" : "foo", "retentionPolicy" : "bar", "points": [
|
|
|
|
{"name": "cpu", "tags": {"host": "server01"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "cpu", "tags": {"host": "server01", "region": "uswest"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "cpu", "tags": {"host": "server01", "region": "useast"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "cpu", "tags": {"host": "server02", "region": "useast"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "gpu", "tags": {"host": "server02", "region": "useast"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}}
|
|
|
|
]}`)
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Log(body)
|
|
|
|
t.Fatalf("unexpected status after write: %d", status)
|
|
|
|
}
|
|
|
|
|
2015-01-28 15:37:25 +00:00
|
|
|
var tests = []struct {
|
|
|
|
q string
|
|
|
|
r string
|
|
|
|
err string
|
|
|
|
}{
|
|
|
|
// SHOW SERIES
|
|
|
|
{
|
|
|
|
q: `SHOW MEASUREMENTS LIMIT 2`,
|
|
|
|
r: `{"results":[{"rows":[{"name":"cpu","columns":["host","region"]},{"name":"gpu","columns":["host","region"]}]}]}`,
|
|
|
|
},
|
2015-01-28 05:51:09 +00:00
|
|
|
}
|
|
|
|
|
2015-01-28 15:37:25 +00:00
|
|
|
for i, tt := range tests {
|
|
|
|
query := map[string]string{"db": "foo", "q": tt.q}
|
|
|
|
status, body = MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Logf("query #%d: %s", i, tt.q)
|
|
|
|
t.Log(body)
|
|
|
|
t.Errorf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
|
|
|
|
r := &influxdb.Results{}
|
|
|
|
if err := json.Unmarshal([]byte(body), r); err != nil {
|
|
|
|
t.Logf("query #%d: %s", i, tt.q)
|
|
|
|
t.Log(body)
|
|
|
|
t.Error("error marshaling result: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if body != tt.r {
|
|
|
|
t.Errorf("result mismatch\n exp: %s\n got: %s\n", tt.r, body)
|
|
|
|
}
|
|
|
|
}
|
2015-01-28 05:51:09 +00:00
|
|
|
}
|
|
|
|
|
2015-01-29 01:26:15 +00:00
|
|
|
func TestHandler_serveShowTagKeys(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
srvr.CreateRetentionPolicy("foo", influxdb.NewRetentionPolicy("bar"))
|
|
|
|
srvr.SetDefaultRetentionPolicy("foo", "bar")
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
status, body := MustHTTP("POST", s.URL+`/write`, nil, nil, `{"database" : "foo", "retentionPolicy" : "bar", "points": [
|
|
|
|
{"name": "cpu", "tags": {"host": "server01"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "cpu", "tags": {"host": "server01", "region": "uswest"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "cpu", "tags": {"host": "server01", "region": "useast"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "cpu", "tags": {"host": "server02", "region": "useast"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "gpu", "tags": {"host": "server02", "region": "useast"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}}
|
|
|
|
]}`)
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Log(body)
|
|
|
|
t.Fatalf("unexpected status after write: %d", status)
|
|
|
|
}
|
|
|
|
|
|
|
|
var tests = []struct {
|
|
|
|
q string
|
|
|
|
r *influxdb.Results
|
|
|
|
err string
|
|
|
|
}{
|
|
|
|
// SHOW TAG KEYS
|
|
|
|
{
|
|
|
|
q: `SHOW TAG KEYS`,
|
|
|
|
r: &influxdb.Results{
|
|
|
|
Results: []*influxdb.Result{
|
|
|
|
&influxdb.Result{
|
|
|
|
Rows: []*influxql.Row{
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "cpu",
|
2015-01-29 02:31:23 +00:00
|
|
|
Columns: []string{"tagKey"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"host"}),
|
|
|
|
str2iface([]string{"region"}),
|
|
|
|
},
|
2015-01-29 01:26:15 +00:00
|
|
|
},
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "gpu",
|
2015-01-29 02:31:23 +00:00
|
|
|
Columns: []string{"tagKey"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"host"}),
|
|
|
|
str2iface([]string{"region"}),
|
|
|
|
},
|
2015-01-29 01:26:15 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
// SHOW TAG KEYS FROM...
|
|
|
|
{
|
|
|
|
q: `SHOW TAG KEYS FROM cpu`,
|
|
|
|
r: &influxdb.Results{
|
|
|
|
Results: []*influxdb.Result{
|
|
|
|
&influxdb.Result{
|
|
|
|
Rows: []*influxql.Row{
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "cpu",
|
2015-01-29 02:31:23 +00:00
|
|
|
Columns: []string{"tagKey"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"host"}),
|
|
|
|
str2iface([]string{"region"}),
|
|
|
|
},
|
2015-01-29 01:26:15 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for i, tt := range tests {
|
|
|
|
query := map[string]string{"db": "foo", "q": tt.q}
|
|
|
|
status, body = MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Logf("query #%d: %s", i, tt.q)
|
|
|
|
t.Log(body)
|
|
|
|
t.Errorf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
|
|
|
|
r := &influxdb.Results{}
|
|
|
|
if err := json.Unmarshal([]byte(body), r); err != nil {
|
|
|
|
t.Logf("query #%d: %s", i, tt.q)
|
|
|
|
t.Log(body)
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(tt.err, errstring(r.Err)) {
|
2015-01-29 20:00:15 +00:00
|
|
|
t.Errorf("%d. %s: error mismatch:\n exp=%s\n got=%s\n\n", i, tt.q, tt.err, r.Err)
|
|
|
|
} else if tt.err == "" && !reflect.DeepEqual(tt.r, r) {
|
|
|
|
b, _ := json.Marshal(tt.r)
|
|
|
|
t.Log(string(b))
|
|
|
|
t.Log(body)
|
|
|
|
t.Errorf("%d. %s: result mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.q, tt.r, r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandler_serveShowTagValues(t *testing.T) {
|
|
|
|
srvr := OpenServer(NewMessagingClient())
|
|
|
|
srvr.CreateDatabase("foo")
|
|
|
|
srvr.CreateRetentionPolicy("foo", influxdb.NewRetentionPolicy("bar"))
|
|
|
|
srvr.SetDefaultRetentionPolicy("foo", "bar")
|
|
|
|
s := NewHTTPServer(srvr)
|
|
|
|
defer s.Close()
|
|
|
|
|
|
|
|
status, body := MustHTTP("POST", s.URL+`/write`, nil, nil, `{"database" : "foo", "retentionPolicy" : "bar", "points": [
|
|
|
|
{"name": "cpu", "tags": {"host": "server01"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "cpu", "tags": {"host": "server01", "region": "uswest"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "cpu", "tags": {"host": "server01", "region": "useast"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "cpu", "tags": {"host": "server02", "region": "useast"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}},
|
|
|
|
{"name": "gpu", "tags": {"host": "server02", "region": "useast"},"timestamp": "2009-11-10T23:00:00Z","values": {"value": 100}}
|
|
|
|
]}`)
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Log(body)
|
|
|
|
t.Fatalf("unexpected status after write: %d", status)
|
|
|
|
}
|
|
|
|
|
|
|
|
var tests = []struct {
|
|
|
|
q string
|
|
|
|
r *influxdb.Results
|
|
|
|
err string
|
|
|
|
}{
|
|
|
|
// SHOW TAG VALUES
|
|
|
|
{
|
|
|
|
q: `SHOW TAG VALUES WITH KEY = host`,
|
|
|
|
r: &influxdb.Results{
|
|
|
|
Results: []*influxdb.Result{
|
|
|
|
&influxdb.Result{
|
|
|
|
Rows: []*influxql.Row{
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "cpu",
|
|
|
|
Columns: []string{"tagValue"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"server01"}),
|
|
|
|
str2iface([]string{"server02"}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "gpu",
|
|
|
|
Columns: []string{"tagValue"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"server02"}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
// SHOW TAG VALUES FROM ...
|
|
|
|
{
|
|
|
|
q: `SHOW TAG VALUES FROM cpu WITH KEY = host`,
|
|
|
|
r: &influxdb.Results{
|
|
|
|
Results: []*influxdb.Result{
|
|
|
|
&influxdb.Result{
|
|
|
|
Rows: []*influxql.Row{
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "cpu",
|
|
|
|
Columns: []string{"tagValue"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"server01"}),
|
|
|
|
str2iface([]string{"server02"}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
// SHOW TAG VALUES FROM ... WHERE ...
|
|
|
|
{
|
|
|
|
q: `SHOW TAG VALUES FROM cpu WITH KEY = host WHERE region = 'uswest'`,
|
|
|
|
r: &influxdb.Results{
|
|
|
|
Results: []*influxdb.Result{
|
|
|
|
&influxdb.Result{
|
|
|
|
Rows: []*influxql.Row{
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "cpu",
|
|
|
|
Columns: []string{"tagValue"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"server01"}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
// SHOW TAG VALUES FROM ... WITH KEY IN ... WHERE ...
|
|
|
|
{
|
|
|
|
q: `SHOW TAG VALUES FROM cpu WITH KEY IN (host, region) WHERE region = 'uswest'`,
|
|
|
|
r: &influxdb.Results{
|
|
|
|
Results: []*influxdb.Result{
|
|
|
|
&influxdb.Result{
|
|
|
|
Rows: []*influxql.Row{
|
|
|
|
&influxql.Row{
|
|
|
|
Name: "cpu",
|
|
|
|
Columns: []string{"tagValue"},
|
|
|
|
Values: [][]interface{}{
|
|
|
|
str2iface([]string{"server01"}),
|
|
|
|
str2iface([]string{"uswest"}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for i, tt := range tests {
|
|
|
|
query := map[string]string{"db": "foo", "q": tt.q}
|
|
|
|
status, body = MustHTTP("GET", s.URL+`/query`, query, nil, "")
|
|
|
|
|
|
|
|
if status != http.StatusOK {
|
|
|
|
t.Logf("query #%d: %s", i, tt.q)
|
|
|
|
t.Log(body)
|
|
|
|
t.Errorf("unexpected status: %d", status)
|
|
|
|
}
|
|
|
|
|
|
|
|
r := &influxdb.Results{}
|
|
|
|
if err := json.Unmarshal([]byte(body), r); err != nil {
|
|
|
|
t.Logf("query #%d: %s", i, tt.q)
|
|
|
|
t.Log(body)
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(tt.err, errstring(r.Err)) {
|
2015-01-29 01:26:15 +00:00
|
|
|
t.Errorf("%d. %s: error mismatch:\n exp=%s\n got=%s\n\n", i, tt.q, tt.err, r.Err)
|
|
|
|
} else if tt.err == "" && !reflect.DeepEqual(tt.r, r) {
|
2015-01-29 02:31:23 +00:00
|
|
|
b, _ := json.Marshal(tt.r)
|
|
|
|
t.Log(string(b))
|
2015-01-29 01:26:15 +00:00
|
|
|
t.Log(body)
|
|
|
|
t.Errorf("%d. %s: result mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.q, tt.r, r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-29 19:28:13 +00:00
|
|
|
// batchWrite JSON Unmarshal tests
|
|
|
|
|
2015-01-05 23:47:12 +00:00
|
|
|
// Utility functions for this test suite.
|
|
|
|
|
2015-01-13 19:16:26 +00:00
|
|
|
func MustHTTP(verb, path string, params, headers map[string]string, body string) (int, string) {
|
|
|
|
req, err := http.NewRequest(verb, path, bytes.NewBuffer([]byte(body)))
|
2014-11-20 18:05:53 +00:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2015-01-05 23:47:12 +00:00
|
|
|
|
2015-01-13 19:16:26 +00:00
|
|
|
if params != nil {
|
|
|
|
q := url.Values{}
|
|
|
|
for k, v := range params {
|
|
|
|
q.Set(k, v)
|
|
|
|
}
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
}
|
|
|
|
|
2015-01-05 23:47:12 +00:00
|
|
|
for k, v := range headers {
|
|
|
|
req.Header.Set(k, v)
|
|
|
|
}
|
2015-01-06 00:01:24 +00:00
|
|
|
req.Header.Set("Content-Type", "application/json")
|
2014-12-23 06:18:05 +00:00
|
|
|
|
2014-11-20 18:05:53 +00:00
|
|
|
client := &http.Client{}
|
|
|
|
resp, err := client.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
2014-12-23 06:18:05 +00:00
|
|
|
|
|
|
|
b, err := ioutil.ReadAll(resp.Body)
|
|
|
|
return resp.StatusCode, strings.TrimRight(string(b), "\n")
|
2014-11-20 18:05:53 +00:00
|
|
|
}
|
|
|
|
|
2014-12-29 23:12:51 +00:00
|
|
|
// MustParseURL parses a string into a URL. Panic on error.
|
|
|
|
func MustParseURL(s string) *url.URL {
|
|
|
|
u, err := url.Parse(s)
|
|
|
|
if err != nil {
|
|
|
|
panic(err.Error())
|
|
|
|
}
|
|
|
|
return u
|
|
|
|
}
|
|
|
|
|
2014-11-19 17:12:46 +00:00
|
|
|
// Server is a test HTTP server that wraps a handler
|
2014-11-20 16:02:21 +00:00
|
|
|
type HTTPServer struct {
|
2014-11-19 17:12:46 +00:00
|
|
|
*httptest.Server
|
2015-01-20 17:50:13 +00:00
|
|
|
Handler *httpd.Handler
|
2014-11-19 17:12:46 +00:00
|
|
|
}
|
|
|
|
|
2014-11-20 16:02:21 +00:00
|
|
|
func NewHTTPServer(s *Server) *HTTPServer {
|
2015-01-22 01:13:51 +00:00
|
|
|
h := httpd.NewHandler(s.Server, false, "X.X")
|
2014-11-20 16:02:21 +00:00
|
|
|
return &HTTPServer{httptest.NewServer(h), h}
|
2014-11-19 17:12:46 +00:00
|
|
|
}
|
|
|
|
|
2015-01-05 23:47:12 +00:00
|
|
|
func NewAuthenticatedHTTPServer(s *Server) *HTTPServer {
|
2015-01-22 01:13:51 +00:00
|
|
|
h := httpd.NewHandler(s.Server, true, "X.X")
|
2015-01-05 23:47:12 +00:00
|
|
|
return &HTTPServer{httptest.NewServer(h), h}
|
|
|
|
}
|
|
|
|
|
2014-11-20 16:02:21 +00:00
|
|
|
func (s *HTTPServer) Close() {
|
2014-11-19 17:12:46 +00:00
|
|
|
s.Server.Close()
|
|
|
|
}
|
2015-01-20 17:50:13 +00:00
|
|
|
|
|
|
|
// Server is a wrapping test struct for influxdb.Server.
|
|
|
|
type Server struct {
|
|
|
|
*influxdb.Server
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewServer returns a new test server instance.
|
|
|
|
func NewServer() *Server {
|
2015-01-22 01:13:51 +00:00
|
|
|
return &Server{influxdb.NewServer()}
|
2015-01-20 17:50:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// OpenServer returns a new, open test server instance.
|
|
|
|
func OpenServer(client influxdb.MessagingClient) *Server {
|
|
|
|
s := OpenUninitializedServer(client)
|
|
|
|
if err := s.Initialize(&url.URL{Host: "127.0.0.1:8080"}); err != nil {
|
|
|
|
panic(err.Error())
|
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
// OpenUninitializedServer returns a new, uninitialized, open test server instance.
|
|
|
|
func OpenUninitializedServer(client influxdb.MessagingClient) *Server {
|
|
|
|
s := NewServer()
|
|
|
|
if err := s.Open(tempfile()); err != nil {
|
|
|
|
panic(err.Error())
|
|
|
|
}
|
|
|
|
if err := s.SetClient(client); err != nil {
|
|
|
|
panic(err.Error())
|
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO corylanou: evaluate how much of this should be in this package
|
|
|
|
// vs. how much should be a mocked out interface
|
|
|
|
// MessagingClient represents a test client for the messaging broker.
|
|
|
|
type MessagingClient struct {
|
|
|
|
index uint64
|
|
|
|
c chan *messaging.Message
|
|
|
|
|
|
|
|
PublishFunc func(*messaging.Message) (uint64, error)
|
|
|
|
CreateReplicaFunc func(replicaID uint64) error
|
|
|
|
DeleteReplicaFunc func(replicaID uint64) error
|
|
|
|
SubscribeFunc func(replicaID, topicID uint64) error
|
|
|
|
UnsubscribeFunc func(replicaID, topicID uint64) error
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewMessagingClient returns a new instance of MessagingClient.
|
|
|
|
func NewMessagingClient() *MessagingClient {
|
|
|
|
c := &MessagingClient{c: make(chan *messaging.Message, 1)}
|
|
|
|
c.PublishFunc = c.send
|
|
|
|
c.CreateReplicaFunc = func(replicaID uint64) error { return nil }
|
|
|
|
c.DeleteReplicaFunc = func(replicaID uint64) error { return nil }
|
|
|
|
c.SubscribeFunc = func(replicaID, topicID uint64) error { return nil }
|
|
|
|
c.UnsubscribeFunc = func(replicaID, topicID uint64) error { return nil }
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
// Publish attaches an autoincrementing index to the message.
|
|
|
|
// This function also execute's the client's PublishFunc mock function.
|
|
|
|
func (c *MessagingClient) Publish(m *messaging.Message) (uint64, error) {
|
|
|
|
c.index++
|
|
|
|
m.Index = c.index
|
|
|
|
return c.PublishFunc(m)
|
|
|
|
}
|
|
|
|
|
|
|
|
// send sends the message through to the channel.
|
|
|
|
// This is the default value of PublishFunc.
|
|
|
|
func (c *MessagingClient) send(m *messaging.Message) (uint64, error) {
|
|
|
|
c.c <- m
|
|
|
|
return m.Index, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates a new replica with a given ID on the broker.
|
|
|
|
func (c *MessagingClient) CreateReplica(replicaID uint64) error {
|
|
|
|
return c.CreateReplicaFunc(replicaID)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Deletes an existing replica with a given ID from the broker.
|
|
|
|
func (c *MessagingClient) DeleteReplica(replicaID uint64) error {
|
|
|
|
return c.DeleteReplicaFunc(replicaID)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Subscribe adds a subscription to a replica for a topic on the broker.
|
|
|
|
func (c *MessagingClient) Subscribe(replicaID, topicID uint64) error {
|
|
|
|
return c.SubscribeFunc(replicaID, topicID)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unsubscribe removes a subscrition from a replica for a topic on the broker.
|
|
|
|
func (c *MessagingClient) Unsubscribe(replicaID, topicID uint64) error {
|
|
|
|
return c.UnsubscribeFunc(replicaID, topicID)
|
|
|
|
}
|
|
|
|
|
|
|
|
// C returns a channel for streaming message.
|
|
|
|
func (c *MessagingClient) C() <-chan *messaging.Message { return c.c }
|
|
|
|
|
|
|
|
// tempfile returns a temporary path.
|
|
|
|
func tempfile() string {
|
|
|
|
f, _ := ioutil.TempFile("", "influxdb-")
|
|
|
|
path := f.Name()
|
|
|
|
f.Close()
|
|
|
|
os.Remove(path)
|
|
|
|
return path
|
|
|
|
}
|
2015-01-28 08:45:21 +00:00
|
|
|
|
|
|
|
// errstring converts an error to its string representation.
|
|
|
|
func errstring(err error) string {
|
|
|
|
if err != nil {
|
|
|
|
return err.Error()
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|