2015-01-22 22:23:55 +00:00
|
|
|
package client_test
|
|
|
|
|
|
|
|
import (
|
2015-01-23 00:18:24 +00:00
|
|
|
"encoding/json"
|
2015-01-29 21:07:43 +00:00
|
|
|
"fmt"
|
2015-01-22 23:40:32 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
2015-01-23 22:49:23 +00:00
|
|
|
"net/url"
|
2015-01-22 22:23:55 +00:00
|
|
|
"testing"
|
2015-01-29 18:10:13 +00:00
|
|
|
"time"
|
2015-01-22 22:23:55 +00:00
|
|
|
|
2015-01-23 00:18:24 +00:00
|
|
|
"github.com/influxdb/influxdb"
|
2015-01-22 22:23:55 +00:00
|
|
|
"github.com/influxdb/influxdb/client"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestNewClient(t *testing.T) {
|
|
|
|
config := client.Config{}
|
|
|
|
_, err := client.NewClient(config)
|
|
|
|
if err != nil {
|
2015-01-22 23:40:32 +00:00
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
2015-01-22 22:23:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-22 23:40:32 +00:00
|
|
|
func TestClient_Ping(t *testing.T) {
|
|
|
|
ts := emptyTestServer()
|
|
|
|
defer ts.Close()
|
|
|
|
|
2015-01-23 22:49:23 +00:00
|
|
|
u, _ := url.Parse(ts.URL)
|
|
|
|
config := client.Config{URL: *u}
|
2015-01-22 23:40:32 +00:00
|
|
|
c, err := client.NewClient(config)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
|
|
|
}
|
2015-01-26 21:12:58 +00:00
|
|
|
d, version, err := c.Ping()
|
2015-01-22 23:40:32 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
|
|
|
}
|
|
|
|
if d == 0 {
|
|
|
|
t.Fatalf("expected a duration greater than zero. actual %v", d)
|
|
|
|
}
|
2015-01-26 21:12:58 +00:00
|
|
|
if version != "x.x" {
|
|
|
|
t.Fatalf("unexpected version. expected %s, actual %v", "x.x", version)
|
|
|
|
}
|
2015-01-22 23:40:32 +00:00
|
|
|
}
|
|
|
|
|
2015-01-22 22:23:55 +00:00
|
|
|
func TestClient_Query(t *testing.T) {
|
2015-01-23 00:18:24 +00:00
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
var data influxdb.Results
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
_ = json.NewEncoder(w).Encode(data)
|
|
|
|
}))
|
|
|
|
defer ts.Close()
|
|
|
|
|
2015-01-23 22:49:23 +00:00
|
|
|
u, _ := url.Parse(ts.URL)
|
|
|
|
config := client.Config{URL: *u}
|
2015-01-22 22:23:55 +00:00
|
|
|
c, err := client.NewClient(config)
|
|
|
|
if err != nil {
|
2015-01-22 23:40:32 +00:00
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
2015-01-22 22:23:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
query := client.Query{}
|
|
|
|
_, err = c.Query(query)
|
|
|
|
if err != nil {
|
2015-01-22 23:40:32 +00:00
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
2015-01-22 22:23:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-23 18:05:04 +00:00
|
|
|
func TestClient_BasicAuth(t *testing.T) {
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
u, p, ok := r.BasicAuth()
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
t.Errorf("basic auth failed")
|
|
|
|
}
|
|
|
|
if u != "username" {
|
|
|
|
t.Errorf("unexpected username, expected %q, actual %q", "username", u)
|
|
|
|
}
|
|
|
|
if p != "password" {
|
|
|
|
t.Errorf("unexpected password, expected %q, actual %q", "password", p)
|
|
|
|
}
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
|
|
}))
|
|
|
|
defer ts.Close()
|
|
|
|
|
2015-01-23 22:49:23 +00:00
|
|
|
u, _ := url.Parse(ts.URL)
|
|
|
|
u.User = url.UserPassword("username", "password")
|
|
|
|
config := client.Config{URL: *u, Username: "username", Password: "password"}
|
2015-01-23 18:05:04 +00:00
|
|
|
c, err := client.NewClient(config)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
|
|
|
}
|
|
|
|
|
2015-01-26 21:12:58 +00:00
|
|
|
_, _, err = c.Ping()
|
2015-01-23 18:05:04 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-22 22:23:55 +00:00
|
|
|
func TestClient_Write(t *testing.T) {
|
2015-01-23 20:37:53 +00:00
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
var data influxdb.Results
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
_ = json.NewEncoder(w).Encode(data)
|
|
|
|
}))
|
|
|
|
defer ts.Close()
|
|
|
|
|
2015-01-23 22:49:23 +00:00
|
|
|
u, _ := url.Parse(ts.URL)
|
|
|
|
config := client.Config{URL: *u}
|
2015-01-22 22:23:55 +00:00
|
|
|
c, err := client.NewClient(config)
|
|
|
|
if err != nil {
|
2015-01-22 23:40:32 +00:00
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
2015-01-22 22:23:55 +00:00
|
|
|
}
|
|
|
|
|
2015-03-06 17:29:32 +00:00
|
|
|
bp := client.BatchPoints{}
|
|
|
|
_, err = c.Write(bp)
|
2015-01-22 22:23:55 +00:00
|
|
|
if err != nil {
|
2015-01-22 23:40:32 +00:00
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
2015-01-22 22:23:55 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-22 23:40:32 +00:00
|
|
|
|
2015-02-11 20:31:15 +00:00
|
|
|
func TestClient_UserAgent(t *testing.T) {
|
|
|
|
receivedUserAgent := ""
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
receivedUserAgent = r.UserAgent()
|
|
|
|
|
|
|
|
var data influxdb.Results
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
_ = json.NewEncoder(w).Encode(data)
|
|
|
|
}))
|
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
_, err := http.Get(ts.URL)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
defaultUserAgent := receivedUserAgent
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
userAgent string
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Empty user agent",
|
|
|
|
userAgent: "",
|
|
|
|
expected: defaultUserAgent,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Custom user agent",
|
|
|
|
userAgent: "Test Influx Client",
|
|
|
|
expected: "Test Influx Client",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
u, _ := url.Parse(ts.URL)
|
|
|
|
config := client.Config{URL: *u, UserAgent: test.userAgent}
|
|
|
|
c, err := client.NewClient(config)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
receivedUserAgent = ""
|
|
|
|
query := client.Query{}
|
|
|
|
_, err = c.Query(query)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
|
|
|
}
|
|
|
|
if receivedUserAgent != test.expected {
|
|
|
|
t.Fatalf("Unexpected user agent. expected %v, actual %v", test.expected, receivedUserAgent)
|
|
|
|
}
|
|
|
|
|
|
|
|
receivedUserAgent = ""
|
2015-03-06 17:29:32 +00:00
|
|
|
bp := client.BatchPoints{}
|
|
|
|
_, err = c.Write(bp)
|
2015-02-11 20:31:15 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
|
|
|
}
|
|
|
|
if receivedUserAgent != test.expected {
|
|
|
|
t.Fatalf("Unexpected user agent. expected %v, actual %v", test.expected, receivedUserAgent)
|
|
|
|
}
|
|
|
|
|
|
|
|
receivedUserAgent = ""
|
|
|
|
_, _, err = c.Ping()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
|
|
|
}
|
|
|
|
if receivedUserAgent != test.expected {
|
|
|
|
t.Fatalf("Unexpected user agent. expected %v, actual %v", test.expected, receivedUserAgent)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-29 21:07:43 +00:00
|
|
|
func TestPoint_UnmarshalEpoch(t *testing.T) {
|
|
|
|
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 p client.Point
|
|
|
|
err := json.Unmarshal(data, &p)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. exptected: %v, actual: %v", nil, err)
|
|
|
|
}
|
2015-03-06 18:20:30 +00:00
|
|
|
if !p.Timestamp.Equal(test.expected) {
|
|
|
|
t.Fatalf("Unexpected time. expected: %v, actual: %v", test.expected, p.Timestamp)
|
2015-01-29 21:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPoint_UnmarshalRFC(t *testing.T) {
|
2015-01-30 18:28:15 +00:00
|
|
|
now := time.Now().UTC()
|
2015-01-29 21:07:43 +00:00
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
rfc string
|
|
|
|
now time.Time
|
|
|
|
expected time.Time
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "RFC3339Nano",
|
|
|
|
rfc: time.RFC3339Nano,
|
|
|
|
now: now,
|
|
|
|
expected: now,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "RFC3339",
|
|
|
|
rfc: time.RFC3339,
|
|
|
|
now: now.Round(time.Second),
|
|
|
|
expected: now.Round(time.Second),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Logf("testing %q\n", test.name)
|
|
|
|
ts := test.now.Format(test.rfc)
|
|
|
|
data := []byte(fmt.Sprintf(`{"timestamp": %q}`, ts))
|
|
|
|
t.Logf("json: %s", string(data))
|
|
|
|
var p client.Point
|
|
|
|
err := json.Unmarshal(data, &p)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. exptected: %v, actual: %v", nil, err)
|
|
|
|
}
|
2015-03-06 18:20:30 +00:00
|
|
|
if !p.Timestamp.Equal(test.expected) {
|
|
|
|
t.Fatalf("Unexpected time. expected: %v, actual: %v", test.expected, p.Timestamp)
|
2015-01-29 21:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-29 18:10:13 +00:00
|
|
|
func TestEpochToTime(t *testing.T) {
|
|
|
|
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)},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Logf("testing %q\n", test.name)
|
|
|
|
tm, e := client.EpochToTime(test.epoch, test.precision)
|
|
|
|
if e != nil {
|
|
|
|
t.Fatalf("unexpected error: expected %v, actual: %v", nil, e)
|
|
|
|
}
|
|
|
|
if tm != test.expected {
|
|
|
|
t.Fatalf("unexpected time: expected %v, actual %v", test.expected, tm)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-22 23:40:32 +00:00
|
|
|
// helper functions
|
|
|
|
|
|
|
|
func emptyTestServer() *httptest.Server {
|
|
|
|
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2015-01-26 21:12:58 +00:00
|
|
|
w.Header().Set("X-Influxdb-Version", "x.x")
|
2015-01-22 23:40:32 +00:00
|
|
|
return
|
|
|
|
}))
|
|
|
|
}
|
2015-03-06 17:29:32 +00:00
|
|
|
|
|
|
|
// Ensure that data with epoch timestamps can be decoded.
|
|
|
|
func TestBatchPoints_Normal(t *testing.T) {
|
|
|
|
var bp client.BatchPoints
|
|
|
|
data := []byte(`
|
|
|
|
{
|
|
|
|
"database": "foo",
|
|
|
|
"retentionPolicy": "bar",
|
|
|
|
"points": [
|
|
|
|
{
|
|
|
|
"name": "cpu",
|
|
|
|
"tags": {
|
|
|
|
"host": "server01"
|
|
|
|
},
|
|
|
|
"timestamp": 14244733039069373,
|
|
|
|
"precision": "n",
|
|
|
|
"values": {
|
|
|
|
"value": 4541770385657154000
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "cpu",
|
|
|
|
"tags": {
|
|
|
|
"host": "server01"
|
|
|
|
},
|
|
|
|
"timestamp": 14244733039069380,
|
|
|
|
"precision": "n",
|
|
|
|
"values": {
|
|
|
|
"value": 7199311900554737000
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
`)
|
|
|
|
|
|
|
|
if err := json.Unmarshal(data, &bp); err != nil {
|
|
|
|
t.Errorf("failed to unmarshal nanosecond data: %s", err.Error())
|
|
|
|
}
|
|
|
|
}
|