func TestNewPointNaN(t *testing.T) { test(t, `cpu value=NaN 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{}, tsdb.Fields{ "value": math.NaN(), }, time.Unix(1, 0)), ) test(t, `cpu value=nAn 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{}, tsdb.Fields{ "value": math.NaN(), }, time.Unix(1, 0)), ) test(t, `nan value=NaN`, tsdb.NewPoint( "nan", tsdb.Tags{}, tsdb.Fields{ "value": math.NaN(), }, time.Unix(0, 0)), ) }
func TestParsePointWithStringField(t *testing.T) { test(t, `cpu,host=serverA,region=us-east value=1.0,str="foo",str2="bar" 1000000000`, tsdb.NewPoint("cpu", tsdb.Tags{ "host": "serverA", "region": "us-east", }, tsdb.Fields{ "value": 1.0, "str": "foo", "str2": "bar", }, time.Unix(1, 0)), ) test(t, `cpu,host=serverA,region=us-east str="foo \" bar" 1000000000`, tsdb.NewPoint("cpu", tsdb.Tags{ "host": "serverA", "region": "us-east", }, tsdb.Fields{ "str": `foo " bar`, }, time.Unix(1, 0)), ) }
func TestParsePointEscapedStringsAndCommas(t *testing.T) { // non-escaped comma and quotes test(t, `cpu,host=serverA,region=us-east value="{Hello\"{,}\" World}" 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{ "host": "serverA", "region": "us-east", }, tsdb.Fields{ "value": `{Hello"{,}" World}`, }, time.Unix(1, 0)), ) // escaped comma and quotes test(t, `cpu,host=serverA,region=us-east value="{Hello\"{\,}\" World}" 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{ "host": "serverA", "region": "us-east", }, tsdb.Fields{ "value": `{Hello"{\,}" World}`, }, time.Unix(1, 0)), ) }
func TestParsePointWithStringWithCommas(t *testing.T) { // escaped comma test(t, `cpu,host=serverA,region=us-east value=1.0,str="foo\,bar" 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{ "host": "serverA", "region": "us-east", }, tsdb.Fields{ "value": 1.0, "str": `foo\,bar`, // commas in string value }, time.Unix(1, 0)), ) // non-escaped comma test(t, `cpu,host=serverA,region=us-east value=1.0,str="foo,bar" 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{ "host": "serverA", "region": "us-east", }, tsdb.Fields{ "value": 1.0, "str": "foo,bar", // commas in string value }, time.Unix(1, 0)), ) }
func TestDropMeasurementStatement(t *testing.T) { store, executor := testStoreAndExecutor("") defer os.RemoveAll(store.Path()) pt := tsdb.NewPoint( "cpu", map[string]string{"host": "server"}, map[string]interface{}{"value": 1.0}, time.Unix(1, 2), ) pt2 := tsdb.NewPoint( "memory", map[string]string{"host": "server"}, map[string]interface{}{"value": 1.0}, time.Unix(1, 2), ) if err := store.WriteToShard(shardID, []tsdb.Point{pt, pt2}); err != nil { t.Fatal(err) } got := executeAndGetJSON("show series", executor) exepected := `[{"series":[{"name":"cpu","columns":["_key","host"],"values":[["cpu,host=server","server"]]},{"name":"memory","columns":["_key","host"],"values":[["memory,host=server","server"]]}]}]` if exepected != got { t.Fatalf("exp: %s\ngot: %s", exepected, got) } got = executeAndGetJSON("drop measurement memory", executor) exepected = `[{}]` if exepected != got { t.Fatalf("exp: %s\ngot: %s", exepected, got) } validateDrop := func() { got = executeAndGetJSON("show series", executor) exepected = `[{"series":[{"name":"cpu","columns":["_key","host"],"values":[["cpu,host=server","server"]]}]}]` if exepected != got { t.Fatalf("exp: %s\ngot: %s", exepected, got) } got = executeAndGetJSON("show measurements", executor) exepected = `[{"series":[{"name":"measurements","columns":["name"],"values":[["cpu"]]}]}]` if exepected != got { t.Fatalf("exp: %s\ngot: %s", exepected, got) } got = executeAndGetJSON("select * from memory", executor) exepected = `[{}]` if exepected != got { t.Fatalf("exp: %s\ngot: %s", exepected, got) } } validateDrop() store.Close() store, executor = testStoreAndExecutor(store.Path()) validateDrop() }
func TestShardWriteAddNewField(t *testing.T) { tmpDir, _ := ioutil.TempDir("", "shard_test") defer os.RemoveAll(tmpDir) tmpShard := path.Join(tmpDir, "shard") tmpWal := path.Join(tmpDir, "wal") index := tsdb.NewDatabaseIndex() opts := tsdb.NewEngineOptions() opts.Config.WALDir = filepath.Join(tmpDir, "wal") sh := tsdb.NewShard(1, index, tmpShard, tmpWal, opts) if err := sh.Open(); err != nil { t.Fatalf("error openeing shard: %s", err.Error()) } defer sh.Close() pt := tsdb.NewPoint( "cpu", map[string]string{"host": "server"}, map[string]interface{}{"value": 1.0}, time.Unix(1, 2), ) err := sh.WritePoints([]tsdb.Point{pt}) if err != nil { t.Fatalf(err.Error()) } pt = tsdb.NewPoint( "cpu", map[string]string{"host": "server"}, map[string]interface{}{"value": 1.0, "value2": 2.0}, time.Unix(1, 2), ) err = sh.WritePoints([]tsdb.Point{pt}) if err != nil { t.Fatalf(err.Error()) } if index.SeriesN() != 1 { t.Fatalf("series wasn't in index") } seriesTags := index.Series(string(pt.Key())).Tags if len(seriesTags) != len(pt.Tags()) || pt.Tags()["host"] != seriesTags["host"] { t.Fatalf("tags weren't properly saved to series index: %v, %v", pt.Tags(), seriesTags) } if !reflect.DeepEqual(index.Measurement("cpu").TagKeys(), []string{"host"}) { t.Fatalf("tag key wasn't saved to measurement index") } if len(index.Measurement("cpu").FieldNames()) != 2 { t.Fatalf("field names wasn't saved to measurement index") } }
func TestWritePointsAndExecuteQuery(t *testing.T) { store, executor := testStoreAndExecutor("") defer os.RemoveAll(store.Path()) // Write first point. if err := store.WriteToShard(shardID, []tsdb.Point{tsdb.NewPoint( "cpu", map[string]string{"host": "server"}, map[string]interface{}{"value": 1.0}, time.Unix(1, 2), )}); err != nil { t.Fatalf(err.Error()) } // Write second point. if err := store.WriteToShard(shardID, []tsdb.Point{tsdb.NewPoint( "cpu", map[string]string{"host": "server"}, map[string]interface{}{"value": 1.0}, time.Unix(2, 3), )}); err != nil { t.Fatalf(err.Error()) } got := executeAndGetJSON("SELECT * FROM cpu", executor) exepected := `[{"series":[{"name":"cpu","columns":["time","host","value"],"values":[["1970-01-01T00:00:01.000000002Z","server",1],["1970-01-01T00:00:02.000000003Z","server",1]]}]}]` if exepected != got { t.Fatalf("\nexp: %s\ngot: %s", exepected, got) } got = executeAndGetJSON("SELECT * FROM cpu GROUP BY *", executor) exepected = `[{"series":[{"name":"cpu","tags":{"host":"server"},"columns":["time","value"],"values":[["1970-01-01T00:00:01.000000002Z",1],["1970-01-01T00:00:02.000000003Z",1]]}]}]` if exepected != got { t.Fatalf("\nexp: %s\ngot: %s", exepected, got) } store.Close() conf := store.EngineOptions.Config store = tsdb.NewStore(store.Path()) store.EngineOptions.Config = conf if err := store.Open(); err != nil { t.Fatalf(err.Error()) } executor.Store = store executor.ShardMapper = &testShardMapper{store: store} got = executeAndGetJSON("SELECT * FROM cpu GROUP BY *", executor) if exepected != got { t.Fatalf("\nexp: %s\ngot: %s", exepected, got) } }
func TestDropDatabase(t *testing.T) { store, executor := testStoreAndExecutor("") defer os.RemoveAll(store.Path()) pt := tsdb.NewPoint( "cpu", map[string]string{"host": "server"}, map[string]interface{}{"value": 1.0}, time.Unix(1, 2), ) if err := store.WriteToShard(shardID, []tsdb.Point{pt}); err != nil { t.Fatal(err) } got := executeAndGetJSON("SELECT * FROM cpu GROUP BY *", executor) expected := `[{"series":[{"name":"cpu","tags":{"host":"server"},"columns":["time","value"],"values":[["1970-01-01T00:00:01.000000002Z",1]]}]}]` if expected != got { t.Fatalf("exp: %s\ngot: %s", expected, got) } var name string me := &metaExec{fn: func(stmt influxql.Statement) *influxql.Result { name = stmt.(*influxql.DropDatabaseStatement).Name return &influxql.Result{} }} executor.MetaStatementExecutor = me // verify the database is there on disk dbPath := filepath.Join(store.Path(), "foo") if _, err := os.Stat(dbPath); err != nil { t.Fatalf("execpted database dir %s to exist", dbPath) } got = executeAndGetJSON("drop database foo", executor) expected = `[{}]` if got != expected { t.Fatalf("exp: %s\ngot: %s", expected, got) } if name != "foo" { t.Fatalf("expected the MetaStatementExecutor to be called with database name foo, but got %s", name) } if _, err := os.Stat(dbPath); !os.IsNotExist(err) { t.Fatalf("expected database dir %s to be gone", dbPath) } store.Close() conf := store.EngineOptions.Config store = tsdb.NewStore(store.Path()) store.EngineOptions.Config = conf store.Open() executor.Store = store executor.ShardMapper = &testShardMapper{store: store} if err := store.WriteToShard(shardID, []tsdb.Point{pt}); err == nil || err.Error() != "shard not found" { t.Fatalf("expected shard to not be found") } }
func TestParsePointWithTags(t *testing.T) { test(t, "cpu,host=serverA,region=us-east value=1.0 1000000000", tsdb.NewPoint("cpu", tsdb.Tags{"host": "serverA", "region": "us-east"}, tsdb.Fields{"value": 1.0}, time.Unix(1, 0))) }
func TestParsePointToString(t *testing.T) { line := `cpu,host=serverA,region=us-east bool=false,float=11,float2=12.123,int=10i,str="string val" 1000000000` pts, err := tsdb.ParsePoints([]byte(line)) if err != nil { t.Fatalf(`ParsePoints() failed. got %s`, err) } if exp := 1; len(pts) != exp { t.Errorf("ParsePoint() len mismatch: got %v, exp %v", len(pts), exp) } pt := pts[0] got := pt.String() if line != got { t.Errorf("ParsePoint() to string mismatch:\n got %v\n exp %v", got, line) } pt = tsdb.NewPoint("cpu", tsdb.Tags{"host": "serverA", "region": "us-east"}, tsdb.Fields{"int": 10, "float": float64(11.0), "float2": float64(12.123), "bool": false, "str": "string val"}, time.Unix(1, 0)) got = pt.String() if line != got { t.Errorf("NewPoint() to string mismatch:\n got %v\n exp %v", got, line) } }
// benchmarkWritePoints benchmarks writing new series to a shard. // mCnt - measurement count // tkCnt - tag key count // tvCnt - tag value count (values per tag) // pntCnt - points per series. # of series = mCnt * (tvCnt ^ tkCnt) func benchmarkWritePoints(b *testing.B, mCnt, tkCnt, tvCnt, pntCnt int) { // Generate test series (measurements + unique tag sets). series := genTestSeries(mCnt, tkCnt, tvCnt) // Create index for the shard to use. index := tsdb.NewDatabaseIndex() // Generate point data to write to the shard. points := []tsdb.Point{} for _, s := range series { for val := 0.0; val < float64(pntCnt); val++ { p := tsdb.NewPoint(s.Measurement, s.Series.Tags, map[string]interface{}{"value": val}, time.Now()) points = append(points, p) } } // Stop & reset timers and mem-stats before the main benchmark loop. b.StopTimer() b.ResetTimer() // Run the benchmark loop. for n := 0; n < b.N; n++ { tmpDir, _ := ioutil.TempDir("", "shard_test") tmpShard := path.Join(tmpDir, "shard") tmpWal := path.Join(tmpDir, "wal") shard := tsdb.NewShard(1, index, tmpShard, tmpWal, tsdb.NewEngineOptions()) shard.Open() b.StartTimer() // Call the function being benchmarked. chunkedWrite(shard, points) b.StopTimer() shard.Close() os.RemoveAll(tmpDir) } }
func TestNewPointUnhandledType(t *testing.T) { // nil value pt := tsdb.NewPoint("cpu", nil, tsdb.Fields{"value": nil}, time.Unix(0, 0)) if exp := `cpu value= 0`; pt.String() != exp { t.Errorf("NewPoint().String() mismatch.\ngot %v\nexp %v", pt.String(), exp) } // unsupported type gets stored as string now := time.Unix(0, 0).UTC() pt = tsdb.NewPoint("cpu", nil, tsdb.Fields{"value": now}, time.Unix(0, 0)) if exp := `cpu value="1970-01-01 00:00:00 +0000 UTC" 0`; pt.String() != exp { t.Errorf("NewPoint().String() mismatch.\ngot %v\nexp %v", pt.String(), exp) } if exp := "1970-01-01 00:00:00 +0000 UTC"; pt.Fields()["value"] != exp { t.Errorf("NewPoint().String() mismatch.\ngot %v\nexp %v", pt.String(), exp) } }
func TestNewPointEscaped(t *testing.T) { // commas pt := tsdb.NewPoint("cpu,main", tsdb.Tags{"tag,bar": "value"}, tsdb.Fields{"name,bar": 1.0}, time.Unix(0, 0)) if exp := `cpu\,main,tag\,bar=value name\,bar=1 0`; pt.String() != exp { t.Errorf("NewPoint().String() mismatch.\ngot %v\nexp %v", pt.String(), exp) } // spaces pt = tsdb.NewPoint("cpu main", tsdb.Tags{"tag bar": "value"}, tsdb.Fields{"name bar": 1.0}, time.Unix(0, 0)) if exp := `cpu\ main,tag\ bar=value name\ bar=1 0`; pt.String() != exp { t.Errorf("NewPoint().String() mismatch.\ngot %v\nexp %v", pt.String(), exp) } // equals pt = tsdb.NewPoint("cpu=main", tsdb.Tags{"tag=bar": "value=foo"}, tsdb.Fields{"name=bar": 1.0}, time.Unix(0, 0)) if exp := `cpu=main,tag\=bar=value\=foo name\=bar=1 0`; pt.String() != exp { t.Errorf("NewPoint().String() mismatch.\ngot %v\nexp %v", pt.String(), exp) } }
func TestDropSeriesStatement(t *testing.T) { store, executor := testStoreAndExecutor("") defer os.RemoveAll(store.Path()) pt := tsdb.NewPoint( "cpu", map[string]string{"host": "server"}, map[string]interface{}{"value": 1.0}, time.Unix(1, 2), ) err := store.WriteToShard(shardID, []tsdb.Point{pt}) if err != nil { t.Fatalf(err.Error()) } got := executeAndGetJSON("SELECT * FROM cpu GROUP BY *", executor) exepected := `[{"series":[{"name":"cpu","tags":{"host":"server"},"columns":["time","value"],"values":[["1970-01-01T00:00:01.000000002Z",1]]}]}]` if exepected != got { t.Fatalf("exp: %s\ngot: %s", exepected, got) } got = executeAndGetJSON("drop series from cpu", executor) got = executeAndGetJSON("SELECT * FROM cpu GROUP BY *", executor) exepected = `[{}]` if exepected != got { t.Fatalf("exp: %s\ngot: %s", exepected, got) } got = executeAndGetJSON("show tag keys from cpu", executor) exepected = `[{"series":[{"name":"cpu","columns":["tagKey"]}]}]` if exepected != got { t.Fatalf("exp: %s\ngot: %s", exepected, got) } store.Close() conf := store.EngineOptions.Config store = tsdb.NewStore(store.Path()) store.EngineOptions.Config = conf store.Open() executor.Store = store got = executeAndGetJSON("select * from cpu", executor) exepected = `[{}]` if exepected != got { t.Fatalf("exp: %s\ngot: %s", exepected, got) } got = executeAndGetJSON("show tag keys from cpu", executor) exepected = `[{"series":[{"name":"cpu","columns":["tagKey"]}]}]` if exepected != got { t.Fatalf("exp: %s\ngot: %s", exepected, got) } }
func TestNewPointFloatScientific(t *testing.T) { test(t, `cpu value=6.632243e+06 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{}, tsdb.Fields{ "value": float64(6632243), }, time.Unix(1, 0)), ) }
func TestNewPointLargeInteger(t *testing.T) { test(t, `cpu value=6632243i 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{}, tsdb.Fields{ "value": 6632243, // if incorrectly encoded as a float, it would show up as 6.632243e+06 }, time.Unix(1, 0)), ) }
func TestNewPointNegativeFloat(t *testing.T) { test(t, `cpu value=-0.64 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{}, tsdb.Fields{ "value": -0.64, }, time.Unix(1, 0)), ) }
func TestNewPointFloatNoDecimal(t *testing.T) { test(t, `cpu value=1. 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{}, tsdb.Fields{ "value": 1.0, }, time.Unix(1, 0)), ) }
// Ensure writing a point and updating it results in only a single point. func TestWritePointsAndExecuteQuery_Update(t *testing.T) { store, executor := testStoreAndExecutor("") defer os.RemoveAll(store.Path()) // Write original point. if err := store.WriteToShard(1, []tsdb.Point{tsdb.NewPoint( "temperature", map[string]string{}, map[string]interface{}{"value": 100.0}, time.Unix(0, 0), )}); err != nil { t.Fatalf(err.Error()) } // Restart store. store.Close() conf := store.EngineOptions.Config store = tsdb.NewStore(store.Path()) store.EngineOptions.Config = conf if err := store.Open(); err != nil { t.Fatalf(err.Error()) } executor.Store = store executor.ShardMapper = &testShardMapper{store: store} // Rewrite point with new value. if err := store.WriteToShard(1, []tsdb.Point{tsdb.NewPoint( "temperature", map[string]string{}, map[string]interface{}{"value": 200.0}, time.Unix(0, 0), )}); err != nil { t.Fatalf(err.Error()) } got := executeAndGetJSON("select * from temperature", executor) exp := `[{"series":[{"name":"temperature","columns":["time","value"],"values":[["1970-01-01T00:00:00Z",200]]}]}]` if exp != got { t.Fatalf("\n\nexp: %s\ngot: %s", exp, got) } }
func TestParsePointWithStringWithBackslash(t *testing.T) { test(t, `cpu value="test\\\"" 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{}, tsdb.Fields{ "value": `test\"`, }, time.Unix(1, 0)), ) test(t, `cpu value="test\\" 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{}, tsdb.Fields{ "value": `test\`, }, time.Unix(1, 0)), ) test(t, `cpu value="test\\\"" 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{}, tsdb.Fields{ "value": `test\"`, }, time.Unix(1, 0)), ) test(t, `cpu value="test\"" 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{}, tsdb.Fields{ "value": `test"`, }, time.Unix(1, 0)), ) }
func TestParsePointUnicodeString(t *testing.T) { test(t, `cpu,host=serverA,region=us-east value="wè" 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{ "host": "serverA", "region": "us-east", }, tsdb.Fields{ "value": "wè", }, time.Unix(1, 0)), ) }
func TestParsePointQuotedTags(t *testing.T) { test(t, `cpu,"host"="serverA",region=us-east value=1.0 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{ `"host"`: `"serverA"`, "region": "us-east", }, tsdb.Fields{ "value": 1.0, }, time.Unix(1, 0)), ) }
func TestParsePointWithStringWithNewline(t *testing.T) { test(t, "cpu,host=serverA,region=us-east value=1.0,str=\"foo\nbar\" 1000000000", tsdb.NewPoint( "cpu", tsdb.Tags{ "host": "serverA", "region": "us-east", }, tsdb.Fields{ "value": 1.0, "str": "foo\nbar", // newline in string value }, time.Unix(1, 0)), ) }
func TestParsePointQuotedMeasurement(t *testing.T) { // non-escaped comma test(t, `"cpu",host=serverA,region=us-east value=1.0 1000000000`, tsdb.NewPoint( `"cpu"`, tsdb.Tags{ "host": "serverA", "region": "us-east", }, tsdb.Fields{ "value": 1.0, }, time.Unix(1, 0)), ) }
func TestParsePointWithStringWithEquals(t *testing.T) { test(t, `cpu,host=serverA,region=us-east str="foo=bar",value=1.0 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{ "host": "serverA", "region": "us-east", }, tsdb.Fields{ "value": 1.0, "str": "foo=bar", // spaces in string value }, time.Unix(1, 0)), ) }
func benchmarkStoreOpen(b *testing.B, mCnt, tkCnt, tvCnt, pntCnt, shardCnt int) { // Generate test series (measurements + unique tag sets). series := genTestSeries(mCnt, tkCnt, tvCnt) // Generate point data to write to the shards. points := []tsdb.Point{} for _, s := range series { for val := 0.0; val < float64(pntCnt); val++ { p := tsdb.NewPoint(s.Measurement, s.Series.Tags, map[string]interface{}{"value": val}, time.Now()) points = append(points, p) } } // Create a temporary directory for the test data. dir, _ := ioutil.TempDir("", "store_test") // Create the store. store := tsdb.NewStore(dir) // Open the store. if err := store.Open(); err != nil { b.Fatalf("benchmarkStoreOpen: %s", err) } // Create requested number of shards in the store & write points. for shardID := 0; shardID < shardCnt; shardID++ { if err := store.CreateShard("mydb", "myrp", uint64(shardID)); err != nil { b.Fatalf("benchmarkStoreOpen: %s", err) } // Write points to the shard. chunkedWriteStoreShard(store, shardID, points) } // Close the store. if err := store.Close(); err != nil { b.Fatalf("benchmarkStoreOpen: %s", err) } // Run the benchmark loop. b.ResetTimer() for n := 0; n < b.N; n++ { store := tsdb.NewStore(dir) if err := store.Open(); err != nil { b.Fatalf("benchmarkStoreOpen: %s", err) } b.StopTimer() store.Close() b.StartTimer() } }
// Ensure the shard will automatically flush the WAL after a threshold has been reached. func TestShard_Autoflush_FlushInterval(t *testing.T) { path, _ := ioutil.TempDir("", "shard_test") defer os.RemoveAll(path) // Open shard with a high size threshold, small time threshold. sh := tsdb.NewShard(1, tsdb.NewDatabaseIndex(), filepath.Join(path, "shard"), filepath.Join(path, "wal"), tsdb.EngineOptions{ EngineVersion: b1.Format, MaxWALSize: 10 * 1024 * 1024, // 10MB WALFlushInterval: 100 * time.Millisecond, WALPartitionFlushDelay: 1 * time.Millisecond, }) if err := sh.Open(); err != nil { t.Fatal(err) } defer sh.Close() // Write some points. for i := 0; i < 100; i++ { if err := sh.WritePoints([]tsdb.Point{tsdb.NewPoint( fmt.Sprintf("cpu%d", i), map[string]string{"host": "server"}, map[string]interface{}{"value": 1.0}, time.Unix(1, 2), )}); err != nil { t.Fatal(err) } } // Wait for time-based flush. time.Sleep(100 * time.Millisecond) // Make sure we have series buckets created outside the WAL. if n, err := sh.SeriesCount(); err != nil { t.Fatal(err) } else if n < 10 { t.Fatalf("not enough series, expected at least 10, got %d", n) } }
func TestParsePointWithBoolField(t *testing.T) { test(t, `cpu,host=serverA,region=us-east true=true,t=t,T=T,TRUE=TRUE,True=True,false=false,f=f,F=F,FALSE=FALSE,False=False 1000000000`, tsdb.NewPoint( "cpu", tsdb.Tags{ "host": "serverA", "region": "us-east", }, tsdb.Fields{ "t": true, "T": true, "true": true, "True": true, "TRUE": true, "f": false, "F": false, "false": false, "False": false, "FALSE": false, }, time.Unix(1, 0)), ) }
func (p *Point) MarshalString() string { return tsdb.NewPoint(p.Measurement, p.Tags, p.Fields, p.Time).String() }
func TestParsePointUnescape(t *testing.T) { test(t, `foo\,bar value=1i`, tsdb.NewPoint( "foo,bar", // comma in the name tsdb.Tags{}, tsdb.Fields{ "value": 1, }, time.Unix(0, 0))) // commas in measuremnt name test(t, `cpu\,main,regions=east\,west value=1.0`, tsdb.NewPoint( "cpu,main", // comma in the name tsdb.Tags{ "regions": "east,west", }, tsdb.Fields{ "value": 1.0, }, time.Unix(0, 0))) // spaces in measurement name test(t, `cpu\ load,region=east value=1.0`, tsdb.NewPoint( "cpu load", // space in the name tsdb.Tags{ "region": "east", }, tsdb.Fields{ "value": 1.0, }, time.Unix(0, 0))) // commas in tag names test(t, `cpu,region\,zone=east value=1.0`, tsdb.NewPoint("cpu", tsdb.Tags{ "region,zone": "east", // comma in the tag name }, tsdb.Fields{ "value": 1.0, }, time.Unix(0, 0))) // spaces in tag names test(t, `cpu,region\ zone=east value=1.0`, tsdb.NewPoint("cpu", tsdb.Tags{ "region zone": "east", // comma in the tag name }, tsdb.Fields{ "value": 1.0, }, time.Unix(0, 0))) // commas in tag values test(t, `cpu,regions=east\,west value=1.0`, tsdb.NewPoint("cpu", tsdb.Tags{ "regions": "east,west", // comma in the tag value }, tsdb.Fields{ "value": 1.0, }, time.Unix(0, 0))) // spaces in tag values test(t, `cpu,regions=east\ west value=1.0`, tsdb.NewPoint("cpu", tsdb.Tags{ "regions": "east west", // comma in the tag value }, tsdb.Fields{ "value": 1.0, }, time.Unix(0, 0))) // commas in field names test(t, `cpu,regions=east value\,ms=1.0`, tsdb.NewPoint("cpu", tsdb.Tags{ "regions": "east", }, tsdb.Fields{ "value,ms": 1.0, // comma in the field name }, time.Unix(0, 0))) // spaces in field names test(t, `cpu,regions=east value\ ms=1.0`, tsdb.NewPoint("cpu", tsdb.Tags{ "regions": "east", }, tsdb.Fields{ "value ms": 1.0, // comma in the field name }, time.Unix(0, 0))) // commas in field values test(t, `cpu,regions=east value="1,0"`, tsdb.NewPoint("cpu", tsdb.Tags{ "regions": "east", }, tsdb.Fields{ "value": "1,0", // comma in the field value }, time.Unix(0, 0))) // random character escaped test(t, `cpu,regions=eas\t value=1.0`, tsdb.NewPoint( "cpu", tsdb.Tags{ "regions": "eas\\t", }, tsdb.Fields{ "value": 1.0, }, time.Unix(0, 0))) // field name using escape char. test(t, `cpu \a=1i`, tsdb.NewPoint( "cpu", tsdb.Tags{}, tsdb.Fields{ "\\a": 1, // Left as parsed since it's not a known escape sequence. }, time.Unix(0, 0))) // measurement, tag and tag value with equals test(t, `cpu=load,equals\=foo=tag\=value value=1i`, tsdb.NewPoint( "cpu=load", // Not escaped tsdb.Tags{ "equals=foo": "tag=value", // Tag and value unescaped }, tsdb.Fields{ "value": 1, }, time.Unix(0, 0))) }