// Ensure a DROP SERVER statement can be executed. func TestStatementExecutor_ExecuteStatement_DropServer(t *testing.T) { e := NewStatementExecutor() e.Store.NodeFn = func(id uint64) (*meta.NodeInfo, error) { return &meta.NodeInfo{ ID: 1, Host: "node1", }, nil } // Ensure Raft nodes cannot be dropped. e.Store.PeersFn = func() ([]string, error) { return []string{"node1"}, nil } if res := e.ExecuteStatement(influxql.MustParseStatement(`DROP SERVER 1`)); res.Err != meta.ErrNodeRaft { t.Fatalf("unexpected error: %s", res.Err) } // Ensure non-Raft nodes can be dropped. e.Store.PeersFn = func() ([]string, error) { return []string{"node2"}, nil } e.Store.DeleteNodeFn = func(id uint64, force bool) error { return nil } if res := e.ExecuteStatement(influxql.MustParseStatement(`DROP SERVER 1`)); res.Err != nil { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a SHOW SERVERS statement can be executed. func TestStatementExecutor_ExecuteStatement_ShowServers(t *testing.T) { e := NewStatementExecutor() e.Store.NodesFn = func() ([]meta.NodeInfo, error) { return []meta.NodeInfo{ {ID: 1, Host: "node0"}, {ID: 2, Host: "node1"}, }, nil } e.Store.PeersFn = func() ([]string, error) { return []string{"node0"}, nil } if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW SERVERS`)); res.Err != nil { t.Fatal(res.Err) } else if !reflect.DeepEqual(res.Series, influxql.Rows{ { Columns: []string{"id", "url", "raft"}, Values: [][]interface{}{ {uint64(1), "http://node0", true}, {uint64(2), "http://node1", false}, }, }, }) { t.Fatalf("unexpected rows: %s", spew.Sdump(res.Series)) } }
// Ensure a CREATE RETENTION POLICY statement can be executed. func TestStatementExecutor_ExecuteStatement_CreateRetentionPolicy(t *testing.T) { e := NewStatementExecutor() e.Store.CreateRetentionPolicyFn = func(database string, rpi *meta.RetentionPolicyInfo) (*meta.RetentionPolicyInfo, error) { if database != "foo" { t.Fatalf("unexpected database: %s", database) } else if rpi.Name != "rp0" { t.Fatalf("unexpected name: %s", rpi.Name) } else if rpi.Duration != 2*time.Hour { t.Fatalf("unexpected duration: %v", rpi.Duration) } else if rpi.ReplicaN != 3 { t.Fatalf("unexpected replication factor: %v", rpi.ReplicaN) } return nil, nil } e.Store.SetDefaultRetentionPolicyFn = func(database, name string) error { if database != "foo" { t.Fatalf("unexpected database: %s", database) } else if name != "rp0" { t.Fatalf("unexpected name: %s", name) } return nil } if res := e.ExecuteStatement(influxql.MustParseStatement(`CREATE RETENTION POLICY rp0 ON foo DURATION 2h REPLICATION 3 DEFAULT`)); res.Err != nil { t.Fatal(res.Err) } else if res.Series != nil { t.Fatalf("unexpected rows: %#v", res.Series) } }
// Ensure a SHOW SUBSCRIPTIONS statement can be executed. func TestStatementExecutor_ExecuteStatement_ShowSubscriptions(t *testing.T) { e := NewStatementExecutor() e.Store.DatabasesFn = func() ([]meta.DatabaseInfo, error) { return []meta.DatabaseInfo{ { Name: "db0", RetentionPolicies: []meta.RetentionPolicyInfo{ { Name: "rp0", Subscriptions: []meta.SubscriptionInfo{ {Name: "s0", Mode: "ALL", Destinations: []string{"udp://h0:1234", "udp://h1:1234"}}, {Name: "s1", Mode: "ANY", Destinations: []string{"udp://h2:1234", "udp://h3:1234"}}, }, }, { Name: "rp1", Subscriptions: []meta.SubscriptionInfo{ {Name: "s2", Mode: "ALL", Destinations: []string{"udp://h4:1234", "udp://h5:1234"}}, }, }, }, }, { Name: "db1", RetentionPolicies: []meta.RetentionPolicyInfo{ { Name: "rp2", Subscriptions: []meta.SubscriptionInfo{ {Name: "s3", Mode: "ANY", Destinations: []string{"udp://h6:1234", "udp://h7:1234"}}, }, }, }, }, }, nil } stmt := influxql.MustParseStatement(`SHOW SUBSCRIPTIONS`) if res := e.ExecuteStatement(stmt); res.Err != nil { t.Fatal(res.Err) } else if !reflect.DeepEqual(res.Series, models.Rows{ { Name: "db0", Columns: []string{"retention_policy", "name", "mode", "destinations"}, Values: [][]interface{}{ {"rp0", "s0", "ALL", []string{"udp://h0:1234", "udp://h1:1234"}}, {"rp0", "s1", "ANY", []string{"udp://h2:1234", "udp://h3:1234"}}, {"rp1", "s2", "ALL", []string{"udp://h4:1234", "udp://h5:1234"}}, }, }, { Name: "db1", Columns: []string{"retention_policy", "name", "mode", "destinations"}, Values: [][]interface{}{ {"rp2", "s3", "ANY", []string{"udp://h6:1234", "udp://h7:1234"}}, }, }, }) { t.Fatalf("unexpected rows: %s", spew.Sdump(res.Series)) } }
// Ensure a SHOW GRANTS FOR statement can be executed. func TestStatementExecutor_ExecuteStatement_ShowGrantsFor(t *testing.T) { t.Skip("Intermittent test failure: issue 3028") e := NewStatementExecutor() e.Store.UserPrivilegesFn = func(username string) (map[string]influxql.Privilege, error) { if username != "dejan" { t.Fatalf("unexpected username: %s", username) } return map[string]influxql.Privilege{ "dejan": influxql.ReadPrivilege, "golja": influxql.WritePrivilege, }, nil } if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW GRANTS FOR dejan`)); res.Err != nil { t.Fatal(res.Err) } else if !reflect.DeepEqual(res.Series, influxql.Rows{ { Columns: []string{"database", "privilege"}, Values: [][]interface{}{ {"dejan", "READ"}, {"golja", "WRITE"}, }, }, }) { t.Fatalf("unexpected rows: %s", spew.Sdump(res.Series)) } }
// Ensure a CREATE SUBSCRIPTION statement can be executed. func TestStatementExecutor_ExecuteStatement_CreateSubscription(t *testing.T) { e := NewStatementExecutor() e.Store.CreateSubscriptionFn = func(database, rp, name, mode string, destinations []string) error { if database != "db0" { t.Fatalf("unexpected database: %s", database) } else if rp != "rp0" { t.Fatalf("unexpected rp: %s", rp) } else if name != "s0" { t.Fatalf("unexpected name: %s", name) } else if mode != "ANY" { t.Fatalf("unexpected mode: %s", mode) } else if len(destinations) != 2 { t.Fatalf("unexpected destinations: %s", destinations) } else if destinations[0] != "udp://h0:1234" { t.Fatalf("unexpected destinations[0]: %s", destinations[0]) } else if destinations[1] != "udp://h1:1234" { t.Fatalf("unexpected destinations[1]: %s", destinations[1]) } return nil } stmt := influxql.MustParseStatement(`CREATE SUBSCRIPTION s0 ON db0.rp0 DESTINATIONS ANY 'udp://h0:1234', 'udp://h1:1234'`) if res := e.ExecuteStatement(stmt); res.Err != nil { t.Fatal(res.Err) } else if res.Series != nil { t.Fatalf("unexpected rows: %#v", res.Series) } }
// Ensure a REVOKE statement for admin privilege returns errors from the store. func TestStatementExecutor_ExecuteStatement_RevokeAdmin_Err(t *testing.T) { e := NewStatementExecutor() e.Store.SetAdminPrivilegeFn = func(username string, admin bool) error { return errors.New("marker") } if res := e.ExecuteStatement(influxql.MustParseStatement(`REVOKE ALL PRIVILEGES FROM susy`)); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a SHOW RETENTION POLICIES statement can return an error from the store. func TestStatementExecutor_ExecuteStatement_ShowRetentionPolicies_Err(t *testing.T) { e := NewStatementExecutor() e.Store.DatabaseFn = func(name string) (*meta.DatabaseInfo, error) { return nil, errors.New("marker") } if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW RETENTION POLICIES ON db0`)); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a GRANT statement returns errors from the store. func TestStatementExecutor_ExecuteStatement_Grant_Err(t *testing.T) { e := NewStatementExecutor() e.Store.SetPrivilegeFn = func(username, database string, p influxql.Privilege) error { return errors.New("marker") } if res := e.ExecuteStatement(influxql.MustParseStatement(`GRANT READ ON foo TO susy`)); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a DROP USER statement returns errors from the store. func TestStatementExecutor_ExecuteStatement_DropUser_Err(t *testing.T) { e := NewStatementExecutor() e.Store.DropUserFn = func(name string) error { return errors.New("marker") } if res := e.ExecuteStatement(influxql.MustParseStatement(`DROP USER susy`)); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a SET PASSWORD statement returns errors from the store. func TestStatementExecutor_ExecuteStatement_SetPassword_Err(t *testing.T) { e := NewStatementExecutor() e.Store.UpdateUserFn = func(name, password string) error { return errors.New("marker") } if res := e.ExecuteStatement(influxql.MustParseStatement(`SET PASSWORD FOR susy = 'pass'`)); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a CREATE USER statement returns errors from the store. func TestStatementExecutor_ExecuteStatement_CreateUser_Err(t *testing.T) { e := NewStatementExecutor() e.Store.CreateUserFn = func(name, password string, admin bool) (*meta.UserInfo, error) { return nil, errors.New("marker") } if res := e.ExecuteStatement(influxql.MustParseStatement(`CREATE USER susy WITH PASSWORD 'pass'`)); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a SHOW RETENTION POLICIES statement can return an error if the database doesn't exist. func TestStatementExecutor_ExecuteStatement_ShowRetentionPolicies_ErrDatabaseNotFound(t *testing.T) { e := NewStatementExecutor() e.Store.DatabaseFn = func(name string) (*meta.DatabaseInfo, error) { return nil, nil } if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW RETENTION POLICIES ON db0`)); res.Err != meta.ErrDatabaseNotFound { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a CREATE RETENTION POLICY statement returns errors from the store. func TestStatementExecutor_ExecuteStatement_CreateRetentionPolicy_Err(t *testing.T) { e := NewStatementExecutor() e.Store.CreateRetentionPolicyFn = func(database string, rpi *meta.RetentionPolicyInfo) (*meta.RetentionPolicyInfo, error) { return nil, errors.New("marker") } if res := e.ExecuteStatement(influxql.MustParseStatement(`CREATE RETENTION POLICY rp0 ON foo DURATION 2h REPLICATION 1`)); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a SHOW DATABASES statement returns errors from the store. func TestStatementExecutor_ExecuteStatement_ShowDatabases_Err(t *testing.T) { e := NewStatementExecutor() e.Store.DatabasesFn = func() ([]meta.DatabaseInfo, error) { return nil, errors.New("marker") } if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW DATABASES`)); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a SHOW SUBSCRIPTIONS statement can return an error from the store. func TestStatementExecutor_ExecuteStatement_ShowSubscriptions_Err(t *testing.T) { e := NewStatementExecutor() e.Store.DatabasesFn = func() ([]meta.DatabaseInfo, error) { return nil, errors.New("marker") } stmt := influxql.MustParseStatement(`SHOW SUBSCRIPTIONS`) if res := e.ExecuteStatement(stmt); res.Err == nil || res.Err.Error() != "marker" { t.Fatal(res.Err) } }
// Ensure a DROP SUBSCRIPTION statement can return an error from the store. func TestStatementExecutor_ExecuteStatement_DropSubscription_Err(t *testing.T) { e := NewStatementExecutor() e.Store.DropSubscriptionFn = func(database, rp, name string) error { return errors.New("marker") } stmt := influxql.MustParseStatement(`DROP SUBSCRIPTION s0 ON db0.rp0`) if res := e.ExecuteStatement(stmt); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a CREATE SUBSCRIPTION statement can return an error from the store. func TestStatementExecutor_ExecuteStatement_CreateSubscription_Err(t *testing.T) { e := NewStatementExecutor() e.Store.CreateSubscriptionFn = func(database, rp, name, mode string, destinations []string) error { return errors.New("marker") } stmt := influxql.MustParseStatement(`CREATE SUBSCRIPTION s0 ON db0.rp0 DESTINATIONS ANY 'udp://h0:1234', 'udp://h1:1234'`) if res := e.ExecuteStatement(stmt); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a SHOW SHARD GROUPS statement can be executed. func TestStatementExecutor_ExecuteStatement_ShowShardGroups(t *testing.T) { e := NewStatementExecutor() e.Store.DatabasesFn = func() ([]meta.DatabaseInfo, error) { return []meta.DatabaseInfo{ { Name: "foo", RetentionPolicies: []meta.RetentionPolicyInfo{ { Name: "rpi_foo", Duration: time.Second, ShardGroups: []meta.ShardGroupInfo{ { ID: 66, StartTime: time.Unix(0, 0), EndTime: time.Unix(1, 0), }, }, }, }, }, { Name: "foo", RetentionPolicies: []meta.RetentionPolicyInfo{ { Name: "rpi_foo", Duration: time.Second, ShardGroups: []meta.ShardGroupInfo{ { ID: 77, StartTime: time.Unix(2, 0), EndTime: time.Unix(3, 0), }, }, }, }, }, }, nil } if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW SHARD GROUPS`)); res.Err != nil { t.Fatal(res.Err) } else if !reflect.DeepEqual(res.Series, models.Rows{ { Name: "shard groups", Columns: []string{"id", "database", "retention_policy", "start_time", "end_time", "expiry_time"}, Values: [][]interface{}{ {uint64(66), "foo", "rpi_foo", "1970-01-01T00:00:00Z", "1970-01-01T00:00:01Z", "1970-01-01T00:00:02Z"}, {uint64(77), "foo", "rpi_foo", "1970-01-01T00:00:02Z", "1970-01-01T00:00:03Z", "1970-01-01T00:00:04Z"}, }, }, }) { t.Fatalf("unexpected rows: %s", spew.Sdump(res.Series)) } }
// Ensure a DROP CONTINUOUS QUERY statement can return an error from the store. func TestStatementExecutor_ExecuteStatement_DropContinuousQuery_Err(t *testing.T) { e := NewStatementExecutor() e.Store.DropContinuousQueryFn = func(database, name string) error { return errors.New("marker") } stmt := influxql.MustParseStatement(`DROP CONTINUOUS QUERY cq0 ON db0`) if res := e.ExecuteStatement(stmt); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a SHOW CONTINUOUS QUERIES statement can return an error from the store. func TestStatementExecutor_ExecuteStatement_ShowContinuousQueries_Err(t *testing.T) { e := NewStatementExecutor() e.Store.DatabasesFn = func() ([]meta.DatabaseInfo, error) { return nil, errors.New("marker") } stmt := influxql.MustParseStatement(`SHOW CONTINUOUS QUERIES`) if res := e.ExecuteStatement(stmt); res.Err == nil || res.Err.Error() != "marker" { t.Fatal(res.Err) } }
// Ensure a DROP RETENTION POLICY statement returns errors from the store. func TestStatementExecutor_ExecuteStatement_DropRetentionPolicy_Err(t *testing.T) { e := NewStatementExecutor() e.Store.DropRetentionPolicyFn = func(database, name string) error { return errors.New("marker") } stmt := influxql.MustParseStatement(`DROP RETENTION POLICY rp0 ON foo`) if res := e.ExecuteStatement(stmt); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a CREATE CONTINUOUS QUERY statement can return an error from the store. func TestStatementExecutor_ExecuteStatement_CreateContinuousQuery_Err(t *testing.T) { e := NewStatementExecutor() e.Store.CreateContinuousQueryFn = func(database, name, query string) error { return errors.New("marker") } stmt := influxql.MustParseStatement(`CREATE CONTINUOUS QUERY cq0 ON db0 BEGIN SELECT count(*) INTO db1 FROM db0 GROUP BY time(1h) END`) if res := e.ExecuteStatement(stmt); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a ALTER RETENTION POLICY statement returns errors from the store. func TestStatementExecutor_ExecuteStatement_AlterRetentionPolicy_Err(t *testing.T) { e := NewStatementExecutor() e.Store.UpdateRetentionPolicyFn = func(database, name string, rpu *meta.RetentionPolicyUpdate) error { return errors.New("marker") } stmt := influxql.MustParseStatement(`ALTER RETENTION POLICY rp0 ON foo DURATION 1m REPLICATION 4 DEFAULT`) if res := e.ExecuteStatement(stmt); res.Err == nil || res.Err.Error() != "marker" { t.Fatalf("unexpected error: %s", res.Err) } }
func main() { args := os.Args if len(args) != 2 && len(args) != 3 { log.Fatalln("Usage: " + os.Args[0] + " NUM_PRODUCTIONS [PRODUCTION=statement]") } numProductions, err := strconv.Atoi(args[1]) if err != nil { log.Fatalln(err) } production := "statement" if len(args) == 3 { production = args[2] } grammar, err := rebnf.Parse("influxql.ebnf", nil) if err != nil { log.Fatalln(err) } if _, ok := grammar[production]; !ok { log.Fatalln(production + " is not a known production!") } maxRepetitions := 30 maxRecursionDepth := 15 padding := "???" isDebug := false ctx := rebnf.NewCtx(maxRepetitions, maxRecursionDepth, padding, isDebug) for i := 0; i < numProductions; i++ { buf := new(bytes.Buffer) ctx.Random(buf, grammar, production) line, _ := ioutil.ReadAll(buf) fmt.Println("GENERATED: " + string(line)) if stmt, err := influxql.ParseStatement(string(line)); err != nil { fmt.Fprintln(os.Stderr, "ERROR : "+err.Error()) } else { sanitized := stmt.String() fmt.Println("SANITIZED: " + sanitized) resanitized := influxql.MustParseStatement(sanitized).String() if resanitized != sanitized { fmt.Println("IMPURE : " + resanitized) } } fmt.Println() } }
// Ensure an ALTER RETENTION POLICY statement can execute. func TestStatementExecutor_ExecuteStatement_AlterRetentionPolicy(t *testing.T) { e := NewStatementExecutor() e.Store.UpdateRetentionPolicyFn = func(database, name string, rpu *meta.RetentionPolicyUpdate) error { if database != "foo" { t.Fatalf("unexpected database: %s", database) } else if name != "rp0" { t.Fatalf("unexpected name: %s", name) } else if rpu.Duration != nil && *rpu.Duration != 7*24*time.Hour { t.Fatalf("unexpected duration: %v", *rpu.Duration) } else if rpu.ReplicaN != nil && *rpu.ReplicaN != 2 { t.Fatalf("unexpected replication factor: %v", *rpu.ReplicaN) } return nil } e.Store.SetDefaultRetentionPolicyFn = func(database, name string) error { if database != "foo" { t.Fatalf("unexpected database: %s", database) } else if name != "rp0" { t.Fatalf("unexpected name: %s", name) } return nil } stmt := influxql.MustParseStatement(`ALTER RETENTION POLICY rp0 ON foo DURATION 7d REPLICATION 2 DEFAULT`) if res := e.ExecuteStatement(stmt); res.Err != nil { t.Fatalf("unexpected error: %s", res.Err) } stmt = influxql.MustParseStatement(`ALTER RETENTION POLICY rp0 ON foo DURATION 7d`) if res := e.ExecuteStatement(stmt); res.Err != nil { t.Fatalf("unexpected error: %s", res.Err) } stmt = influxql.MustParseStatement(`ALTER RETENTION POLICY rp0 ON foo REPLICATION 2`) if res := e.ExecuteStatement(stmt); res.Err != nil { t.Fatalf("unexpected error: %s", res.Err) } }
// Ensure a SHOW SHARDS statement can be executed. func TestStatementExecutor_ExecuteStatement_ShowShards(t *testing.T) { e := NewStatementExecutor() e.Store.DatabasesFn = func() ([]meta.DatabaseInfo, error) { return []meta.DatabaseInfo{ { Name: "foo", RetentionPolicies: []meta.RetentionPolicyInfo{ { Duration: time.Second, ShardGroups: []meta.ShardGroupInfo{ { StartTime: time.Unix(0, 0), EndTime: time.Unix(1, 0), Shards: []meta.ShardInfo{ { ID: 1, Owners: []meta.ShardOwner{ {NodeID: 1}, {NodeID: 2}, {NodeID: 3}, }, }, { ID: 2, }, }, }, }, }, }, }, }, nil } if res := e.ExecuteStatement(influxql.MustParseStatement(`SHOW SHARDS`)); res.Err != nil { t.Fatal(res.Err) } else if !reflect.DeepEqual(res.Series, models.Rows{ { Name: "foo", Columns: []string{"id", "start_time", "end_time", "expiry_time", "owners"}, Values: [][]interface{}{ {uint64(1), "1970-01-01T00:00:00Z", "1970-01-01T00:00:01Z", "1970-01-01T00:00:02Z", "1,2,3"}, {uint64(2), "1970-01-01T00:00:00Z", "1970-01-01T00:00:01Z", "1970-01-01T00:00:02Z", ""}, }, }, }) { t.Fatalf("unexpected rows: %s", spew.Sdump(res.Series)) } }
// Ensure a DROP DATABASE statement can be executed. func TestStatementExecutor_ExecuteStatement_DropDatabase(t *testing.T) { e := NewStatementExecutor() e.Store.DropDatabaseFn = func(name string) error { if name != "foo" { t.Fatalf("unexpected name: %s", name) } return nil } if res := e.ExecuteStatement(influxql.MustParseStatement(`DROP DATABASE foo`)); res.Err != nil { t.Fatal(res.Err) } else if res.Series != nil { t.Fatalf("unexpected rows: %#v", res.Series) } }
// Ensure a CREATE DATABASE statement can be executed. func TestStatementExecutor_ExecuteStatement_CreateDatabase(t *testing.T) { e := NewStatementExecutor() e.Store.CreateDatabaseFn = func(name string) (*meta.DatabaseInfo, error) { if name != "foo" { t.Fatalf("unexpected name: %s", name) } return &meta.DatabaseInfo{Name: name}, nil } if res := e.ExecuteStatement(influxql.MustParseStatement(`CREATE DATABASE foo`)); res.Err != nil { t.Fatal(res.Err) } else if res.Series != nil { t.Fatalf("unexpected rows: %#v", res.Series) } }
// Ensure a DROP RETENTION POLICY statement can execute. func TestStatementExecutor_ExecuteStatement_DropRetentionPolicy(t *testing.T) { e := NewStatementExecutor() e.Store.DropRetentionPolicyFn = func(database, name string) error { if database != "foo" { t.Fatalf("unexpected database: %s", database) } else if name != "rp0" { t.Fatalf("unexpected name: %s", name) } return nil } stmt := influxql.MustParseStatement(`DROP RETENTION POLICY rp0 ON foo`) if res := e.ExecuteStatement(stmt); res.Err != nil { t.Fatalf("unexpected error: %s", res.Err) } }