2015-11-09 13:47:03 +00:00
|
|
|
package cli_test
|
2015-02-03 17:22:50 +00:00
|
|
|
|
|
|
|
import (
|
2015-11-12 17:04:02 +00:00
|
|
|
"bufio"
|
|
|
|
"bytes"
|
2015-11-13 11:38:35 +00:00
|
|
|
"net"
|
2015-06-09 15:36:07 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"net/url"
|
2015-11-13 11:38:35 +00:00
|
|
|
"strconv"
|
2015-02-03 17:22:50 +00:00
|
|
|
"testing"
|
|
|
|
|
2015-06-09 15:36:07 +00:00
|
|
|
"github.com/influxdb/influxdb/client"
|
2015-11-09 13:47:03 +00:00
|
|
|
"github.com/influxdb/influxdb/cmd/influx/cli"
|
2015-11-12 17:04:02 +00:00
|
|
|
"github.com/peterh/liner"
|
2015-02-03 17:22:50 +00:00
|
|
|
)
|
|
|
|
|
2015-11-13 11:38:35 +00:00
|
|
|
const (
|
|
|
|
CLIENT_VERSION = "y.y"
|
|
|
|
SERVER_VERSION = "x.x"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestNewCLI(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
c := cli.New(CLIENT_VERSION)
|
|
|
|
|
|
|
|
if c == nil {
|
|
|
|
t.Fatal("CommandLine shouldn't be nil.")
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.ClientVersion != CLIENT_VERSION {
|
|
|
|
t.Fatalf("CommandLine version is %s but should be %s", c.ClientVersion, CLIENT_VERSION)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRunCLI(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
ts := emptyTestServer()
|
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
u, _ := url.Parse(ts.URL)
|
|
|
|
h, p, _ := net.SplitHostPort(u.Host)
|
|
|
|
c := cli.New(CLIENT_VERSION)
|
|
|
|
c.Host = h
|
|
|
|
c.Port, _ = strconv.Atoi(p)
|
|
|
|
c.Run()
|
|
|
|
}
|
|
|
|
|
2015-12-17 12:42:30 +00:00
|
|
|
func TestRunCLI_ExecuteInsert(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
ts := emptyTestServer()
|
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
u, _ := url.Parse(ts.URL)
|
|
|
|
h, p, _ := net.SplitHostPort(u.Host)
|
|
|
|
c := cli.New(CLIENT_VERSION)
|
|
|
|
c.Host = h
|
|
|
|
c.Port, _ = strconv.Atoi(p)
|
|
|
|
c.Precision = "ms"
|
|
|
|
c.Execute = "INSERT sensor,floor=1 value=2"
|
|
|
|
c.Run()
|
|
|
|
}
|
|
|
|
|
2015-11-13 11:38:35 +00:00
|
|
|
func TestConnect(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
ts := emptyTestServer()
|
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
u, _ := url.Parse(ts.URL)
|
|
|
|
cmd := "connect " + u.Host
|
|
|
|
c := cli.CommandLine{}
|
|
|
|
|
|
|
|
// assert connection is established
|
|
|
|
if err := c.Connect(cmd); err != nil {
|
|
|
|
t.Fatalf("There was an error while connecting to %s: %s", u.Path, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// assert server version is populated
|
|
|
|
if c.ServerVersion != SERVER_VERSION {
|
|
|
|
t.Fatalf("Server version is %s but should be %s.", c.ServerVersion, SERVER_VERSION)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetAuth(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
c := cli.New(CLIENT_VERSION)
|
|
|
|
config := client.NewConfig()
|
|
|
|
client, _ := client.NewClient(config)
|
|
|
|
c.Client = client
|
|
|
|
u := "userx"
|
|
|
|
p := "pwdy"
|
|
|
|
c.SetAuth("auth " + u + " " + p)
|
|
|
|
|
|
|
|
// validate CLI configuration
|
|
|
|
if c.Username != u {
|
|
|
|
t.Fatalf("Username is %s but should be %s", c.Username, u)
|
|
|
|
}
|
|
|
|
if c.Password != p {
|
|
|
|
t.Fatalf("Password is %s but should be %s", c.Password, p)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetPrecision(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
c := cli.New(CLIENT_VERSION)
|
|
|
|
config := client.NewConfig()
|
|
|
|
client, _ := client.NewClient(config)
|
|
|
|
c.Client = client
|
|
|
|
|
|
|
|
// validate set non-default precision
|
|
|
|
p := "ns"
|
|
|
|
c.SetPrecision("precision " + p)
|
|
|
|
if c.Precision != p {
|
|
|
|
t.Fatalf("Precision is %s but should be %s", c.Precision, p)
|
|
|
|
}
|
|
|
|
|
|
|
|
// validate set default precision which equals empty string
|
|
|
|
p = "rfc3339"
|
|
|
|
c.SetPrecision("precision " + p)
|
|
|
|
if c.Precision != "" {
|
|
|
|
t.Fatalf("Precision is %s but should be empty", c.Precision)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetFormat(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
c := cli.New(CLIENT_VERSION)
|
|
|
|
config := client.NewConfig()
|
|
|
|
client, _ := client.NewClient(config)
|
|
|
|
c.Client = client
|
|
|
|
|
|
|
|
// validate set non-default format
|
|
|
|
f := "json"
|
|
|
|
c.SetFormat("format " + f)
|
|
|
|
if c.Format != f {
|
|
|
|
t.Fatalf("Format is %s but should be %s", c.Format, f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetWriteConsistency(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
c := cli.New(CLIENT_VERSION)
|
|
|
|
config := client.NewConfig()
|
|
|
|
client, _ := client.NewClient(config)
|
|
|
|
c.Client = client
|
|
|
|
|
|
|
|
// set valid write consistency
|
|
|
|
consistency := "all"
|
|
|
|
c.SetWriteConsistency("consistency " + consistency)
|
|
|
|
if c.WriteConsistency != consistency {
|
|
|
|
t.Fatalf("WriteConsistency is %s but should be %s", c.WriteConsistency, consistency)
|
|
|
|
}
|
|
|
|
|
|
|
|
// set different valid write consistency and validate change
|
|
|
|
consistency = "quorum"
|
|
|
|
c.SetWriteConsistency("consistency " + consistency)
|
|
|
|
if c.WriteConsistency != consistency {
|
|
|
|
t.Fatalf("WriteConsistency is %s but should be %s", c.WriteConsistency, consistency)
|
|
|
|
}
|
|
|
|
|
|
|
|
// set invalid write consistency and verify there was no change
|
|
|
|
invalidConsistency := "invalid_consistency"
|
|
|
|
c.SetWriteConsistency("consistency " + invalidConsistency)
|
|
|
|
if c.WriteConsistency == invalidConsistency {
|
|
|
|
t.Fatalf("WriteConsistency is %s but should be %s", c.WriteConsistency, consistency)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-03 17:22:50 +00:00
|
|
|
func TestParseCommand_CommandsExist(t *testing.T) {
|
2015-04-15 21:50:04 +00:00
|
|
|
t.Parallel()
|
2015-11-09 13:47:03 +00:00
|
|
|
c := cli.CommandLine{}
|
2015-02-03 17:22:50 +00:00
|
|
|
tests := []struct {
|
|
|
|
cmd string
|
|
|
|
}{
|
|
|
|
{cmd: "gopher"},
|
|
|
|
{cmd: "connect"},
|
|
|
|
{cmd: "help"},
|
|
|
|
{cmd: "pretty"},
|
|
|
|
{cmd: "use"},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
|
|
|
if !c.ParseCommand(test.cmd) {
|
|
|
|
t.Fatalf(`Command failed for %q.`, test.cmd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-12 17:04:02 +00:00
|
|
|
func TestParseCommand_BlankCommand(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
c := cli.CommandLine{}
|
|
|
|
tests := []struct {
|
|
|
|
cmd string
|
|
|
|
}{
|
|
|
|
{cmd: ""}, // test that a blank command doesn't work
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
|
|
|
if c.ParseCommand(test.cmd) {
|
|
|
|
t.Fatalf(`Command failed for %q.`, test.cmd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-03 17:22:50 +00:00
|
|
|
func TestParseCommand_TogglePretty(t *testing.T) {
|
2015-04-15 21:50:04 +00:00
|
|
|
t.Parallel()
|
2015-11-09 13:47:03 +00:00
|
|
|
c := cli.CommandLine{}
|
2015-02-03 17:22:50 +00:00
|
|
|
if c.Pretty {
|
|
|
|
t.Fatalf(`Pretty should be false.`)
|
|
|
|
}
|
|
|
|
c.ParseCommand("pretty")
|
|
|
|
if !c.Pretty {
|
|
|
|
t.Fatalf(`Pretty should be true.`)
|
|
|
|
}
|
|
|
|
c.ParseCommand("pretty")
|
|
|
|
if c.Pretty {
|
|
|
|
t.Fatalf(`Pretty should be false.`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseCommand_Exit(t *testing.T) {
|
2015-04-15 21:50:04 +00:00
|
|
|
t.Parallel()
|
2015-02-03 17:22:50 +00:00
|
|
|
tests := []struct {
|
|
|
|
cmd string
|
|
|
|
}{
|
|
|
|
{cmd: "exit"},
|
|
|
|
{cmd: " exit"},
|
|
|
|
{cmd: "exit "},
|
|
|
|
{cmd: "Exit "},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
2015-11-12 17:04:02 +00:00
|
|
|
c := cli.CommandLine{Quit: make(chan struct{}, 1)}
|
|
|
|
c.ParseCommand(test.cmd)
|
|
|
|
// channel should be closed
|
|
|
|
if _, ok := <-c.Quit; ok {
|
2015-02-03 17:22:50 +00:00
|
|
|
t.Fatalf(`Command "exit" failed for %q.`, test.cmd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-02-28 15:25:46 +00:00
|
|
|
|
|
|
|
func TestParseCommand_Use(t *testing.T) {
|
2015-04-15 21:50:04 +00:00
|
|
|
t.Parallel()
|
2015-11-09 13:47:03 +00:00
|
|
|
c := cli.CommandLine{}
|
2015-02-28 15:25:46 +00:00
|
|
|
tests := []struct {
|
|
|
|
cmd string
|
|
|
|
}{
|
|
|
|
{cmd: "use db"},
|
|
|
|
{cmd: " use db"},
|
|
|
|
{cmd: "use db "},
|
2015-07-14 22:10:01 +00:00
|
|
|
{cmd: "use db;"},
|
2015-07-17 17:57:01 +00:00
|
|
|
{cmd: "use db; "},
|
2015-02-28 15:25:46 +00:00
|
|
|
{cmd: "Use db"},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
if !c.ParseCommand(test.cmd) {
|
|
|
|
t.Fatalf(`Command "use" failed for %q.`, test.cmd)
|
|
|
|
}
|
2015-07-14 22:10:01 +00:00
|
|
|
|
|
|
|
if c.Database != "db" {
|
|
|
|
t.Fatalf(`Command "use" changed database to %q. Expected db`, c.Database)
|
|
|
|
}
|
2015-02-28 15:25:46 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-09 15:36:07 +00:00
|
|
|
|
2015-09-02 15:11:47 +00:00
|
|
|
func TestParseCommand_Consistency(t *testing.T) {
|
|
|
|
t.Parallel()
|
2015-11-09 13:47:03 +00:00
|
|
|
c := cli.CommandLine{}
|
2015-09-02 15:11:47 +00:00
|
|
|
tests := []struct {
|
|
|
|
cmd string
|
|
|
|
}{
|
|
|
|
{cmd: "consistency one"},
|
|
|
|
{cmd: " consistency one"},
|
|
|
|
{cmd: "consistency one "},
|
|
|
|
{cmd: "consistency one;"},
|
|
|
|
{cmd: "consistency one; "},
|
|
|
|
{cmd: "Consistency one"},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
if !c.ParseCommand(test.cmd) {
|
|
|
|
t.Fatalf(`Command "consistency" failed for %q.`, test.cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.WriteConsistency != "one" {
|
|
|
|
t.Fatalf(`Command "consistency" changed consistency to %q. Expected one`, c.WriteConsistency)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-09 15:36:07 +00:00
|
|
|
func TestParseCommand_Insert(t *testing.T) {
|
|
|
|
t.Parallel()
|
2015-11-13 11:38:35 +00:00
|
|
|
ts := emptyTestServer()
|
2015-06-09 15:36:07 +00:00
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
u, _ := url.Parse(ts.URL)
|
2015-08-06 16:46:25 +00:00
|
|
|
config := client.Config{URL: *u}
|
2015-06-09 15:36:07 +00:00
|
|
|
c, err := client.NewClient(config)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
|
|
|
}
|
2015-11-09 13:47:03 +00:00
|
|
|
m := cli.CommandLine{Client: c}
|
2015-06-09 15:36:07 +00:00
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
cmd string
|
|
|
|
}{
|
|
|
|
{cmd: "INSERT cpu,host=serverA,region=us-west value=1.0"},
|
2015-06-23 17:11:19 +00:00
|
|
|
{cmd: " INSERT cpu,host=serverA,region=us-west value=1.0"},
|
|
|
|
{cmd: "INSERT cpu,host=serverA,region=us-west value=1.0"},
|
|
|
|
{cmd: "insert cpu,host=serverA,region=us-west value=1.0 "},
|
|
|
|
{cmd: "insert"},
|
|
|
|
{cmd: "Insert "},
|
|
|
|
{cmd: "insert c"},
|
|
|
|
{cmd: "insert int"},
|
2015-06-09 15:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
if !m.ParseCommand(test.cmd) {
|
|
|
|
t.Fatalf(`Command "insert" failed for %q.`, test.cmd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseCommand_InsertInto(t *testing.T) {
|
|
|
|
t.Parallel()
|
2015-11-13 11:38:35 +00:00
|
|
|
ts := emptyTestServer()
|
2015-06-09 15:36:07 +00:00
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
u, _ := url.Parse(ts.URL)
|
2015-08-06 16:46:25 +00:00
|
|
|
config := client.Config{URL: *u}
|
2015-06-09 15:36:07 +00:00
|
|
|
c, err := client.NewClient(config)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
|
|
|
|
}
|
2015-11-09 13:47:03 +00:00
|
|
|
m := cli.CommandLine{Client: c}
|
2015-06-09 15:36:07 +00:00
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
cmd, db, rp string
|
|
|
|
}{
|
2015-06-09 22:45:26 +00:00
|
|
|
{
|
|
|
|
cmd: `INSERT INTO test cpu,host=serverA,region=us-west value=1.0`,
|
|
|
|
db: "",
|
|
|
|
rp: "test",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cmd: ` INSERT INTO .test cpu,host=serverA,region=us-west value=1.0`,
|
|
|
|
db: "",
|
|
|
|
rp: "test",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cmd: `INSERT INTO "test test" cpu,host=serverA,region=us-west value=1.0`,
|
|
|
|
db: "",
|
|
|
|
rp: "test test",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cmd: `Insert iNTO test.test cpu,host=serverA,region=us-west value=1.0`,
|
|
|
|
db: "test",
|
|
|
|
rp: "test",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cmd: `insert into "test test" cpu,host=serverA,region=us-west value=1.0`,
|
|
|
|
db: "test",
|
|
|
|
rp: "test test",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cmd: `insert into "d b"."test test" cpu,host=serverA,region=us-west value=1.0`,
|
|
|
|
db: "d b",
|
|
|
|
rp: "test test",
|
|
|
|
},
|
2015-06-09 15:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
if !m.ParseCommand(test.cmd) {
|
|
|
|
t.Fatalf(`Command "insert into" failed for %q.`, test.cmd)
|
|
|
|
}
|
|
|
|
if m.Database != test.db {
|
|
|
|
t.Fatalf(`Command "insert into" db parsing failed, expected: %q, actual: %q`, test.db, m.Database)
|
|
|
|
}
|
|
|
|
if m.RetentionPolicy != test.rp {
|
|
|
|
t.Fatalf(`Command "insert into" rp parsing failed, expected: %q, actual: %q`, test.rp, m.RetentionPolicy)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-11-07 03:20:28 +00:00
|
|
|
|
|
|
|
func TestParseCommand_History(t *testing.T) {
|
|
|
|
t.Parallel()
|
2015-11-12 17:04:02 +00:00
|
|
|
c := cli.CommandLine{Line: liner.NewLiner()}
|
|
|
|
defer c.Line.Close()
|
|
|
|
|
|
|
|
// append one entry to history
|
|
|
|
c.Line.AppendHistory("abc")
|
|
|
|
|
2015-11-07 03:20:28 +00:00
|
|
|
tests := []struct {
|
|
|
|
cmd string
|
|
|
|
}{
|
|
|
|
{cmd: "history"},
|
|
|
|
{cmd: " history"},
|
|
|
|
{cmd: "history "},
|
|
|
|
{cmd: "History "},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
if !c.ParseCommand(test.cmd) {
|
|
|
|
t.Fatalf(`Command "history" failed for %q.`, test.cmd)
|
|
|
|
}
|
|
|
|
}
|
2015-11-12 17:04:02 +00:00
|
|
|
|
|
|
|
// buf size should be at least 1
|
|
|
|
var buf bytes.Buffer
|
|
|
|
c.Line.WriteHistory(&buf)
|
|
|
|
if buf.Len() < 1 {
|
|
|
|
t.Fatal("History is borked")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseCommand_HistoryWithBlankCommand(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
c := cli.CommandLine{Line: liner.NewLiner()}
|
|
|
|
defer c.Line.Close()
|
|
|
|
|
|
|
|
// append one entry to history
|
|
|
|
c.Line.AppendHistory("x")
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
cmd string
|
|
|
|
}{
|
|
|
|
{cmd: "history"},
|
|
|
|
{cmd: " history"},
|
|
|
|
{cmd: "history "},
|
|
|
|
{cmd: "History "},
|
|
|
|
{cmd: ""}, // shouldn't be persisted in history
|
|
|
|
{cmd: " "}, // shouldn't be persisted in history
|
|
|
|
}
|
|
|
|
|
|
|
|
// don't validate because blank commands are never executed
|
|
|
|
for _, test := range tests {
|
|
|
|
c.ParseCommand(test.cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// buf shall not contain empty commands
|
|
|
|
var buf bytes.Buffer
|
|
|
|
c.Line.WriteHistory(&buf)
|
|
|
|
scanner := bufio.NewScanner(&buf)
|
|
|
|
for scanner.Scan() {
|
|
|
|
if scanner.Text() == "" || scanner.Text() == " " {
|
|
|
|
t.Fatal("Empty commands should not be persisted in history.")
|
|
|
|
}
|
|
|
|
}
|
2015-11-07 03:20:28 +00:00
|
|
|
}
|
2015-11-13 11:38:35 +00:00
|
|
|
|
|
|
|
// helper methods
|
|
|
|
|
|
|
|
func emptyTestServer() *httptest.Server {
|
|
|
|
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.Header().Set("X-Influxdb-Version", SERVER_VERSION)
|
|
|
|
return
|
|
|
|
}))
|
|
|
|
}
|