Skip to content

Commit 5afec70

Browse files
authored
Improve and fix error messages (#443)
Simplify, improve and make error messages consistent. Make sure we return all proper user errors and not internal error. Create errors SQL test to test many errors
1 parent f261ee3 commit 5afec70

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2376
-248
lines changed

api/server.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package api
44
import (
55
"context"
66
"fmt"
7+
"github.com/alecthomas/participle/v2"
78
"github.com/squareup/pranadb/pull/exec"
89
"net"
910
"sync"
@@ -151,11 +152,14 @@ func (s *Server) ExecuteStatement(in *service.ExecuteStatementRequest,
151152
func (s *Server) doExecuteStatement(executor exec.PullExecutor, batchSize int, err error,
152153
stream service.PranaDBService_ExecuteStatementServer) error {
153154
if err != nil {
154-
log.Errorf("failed to execute statement %+v", err)
155155
var perr errors.PranaError
156156
if errors.As(err, &perr) {
157157
return perr
158158
}
159+
var participleErr participle.Error
160+
if errors.As(err, &participleErr) {
161+
return errors.NewInvalidStatementError(participleErr.Error())
162+
}
159163
return common.LogInternalError(err)
160164
}
161165

client/client.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const (
2525
minLineWidth = 10
2626
minColWidth = 5
2727
maxLineWidthPropName = "max_line_width"
28+
maxLineWidth = 10000
2829
)
2930

3031
// Client is a simple client used for executing statements against PranaDB, it used by the CLI and elsewhere
@@ -116,7 +117,7 @@ func (c *Client) handleSetCommand(statement string) error {
116117
if propName := parts[1]; propName == maxLineWidthPropName {
117118
propVal := parts[2]
118119
width, err := strconv.Atoi(propVal)
119-
if err != nil || width < minLineWidth {
120+
if err != nil || width < minLineWidth || width > maxLineWidth {
120121
return errors.Errorf("Invalid %s value: %s", maxLineWidthPropName, propVal)
121122
}
122123
c.lock.Lock()

cluster/dragon/dragon.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ func (d *Dragon) ExecuteRemotePullQuery(queryInfo *cluster.QueryExecutionInfo, r
195195
if bytes[0] == 0 {
196196
if time.Now().Sub(start) > pullQueryRetryTimeout {
197197
msg := string(bytes[1:])
198-
return nil, errors.Errorf("failed to execute remote query %s %v", queryInfo.Query, msg)
198+
return nil, errors.Errorf("failed to execute remote query %v", msg)
199199
}
200200
// Retry - the pull engine might not be fully started.... this can occur as the pull engine is not fully
201201
// initialised until after the cluster is active

command/command.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ func (e *Executor) execDescribe(execCtx *execctx.ExecutionContext, tableName str
240240
return nil, errors.WithStack(err)
241241
}
242242
if rows.RowCount() == 0 {
243-
return nil, errors.NewUnknownSourceOrMaterializedViewError(execCtx.Schema.Name, tableName)
243+
return nil, errors.NewUnknownTableError(execCtx.Schema.Name, tableName)
244244
}
245245
if rows.RowCount() != 1 {
246246
panic(fmt.Sprintf("multiple matches for table: '%s.%s'", execCtx.Schema.Name, tableName))

command/create_index_command.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ func (c *CreateIndexCommand) getIndexInfo(ast *parser.CreateIndex) (*common.Inde
147147
if !ok {
148148
tab, ok = c.e.metaController.GetMaterializedView(c.SchemaName(), ast.TableName)
149149
if !ok {
150-
return nil, errors.NewUnknownSourceOrMaterializedViewError(c.SchemaName(), ast.TableName)
150+
return nil, errors.NewUnknownTableError(c.SchemaName(), ast.TableName)
151151
}
152152
}
153153
tabInfo := tab.GetTableInfo()
@@ -164,12 +164,18 @@ func (c *CreateIndexCommand) getIndexInfo(ast *parser.CreateIndex) (*common.Inde
164164
colMap[colName] = colIndex
165165
}
166166
indexCols := make([]int, len(ast.ColumnNames))
167+
indexColMap := make(map[int]struct{}, len(ast.ColumnNames))
167168
for i, colName := range ast.ColumnNames {
168169
colIndex, ok := colMap[colName.Name]
169170
if !ok {
170-
return nil, errors.NewUnknownIndexColumn(c.SchemaName(), ast.TableName, colName.Name)
171+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "Unknown column %s in %s.%s",
172+
colName.Name, c.SchemaName(), ast.TableName)
171173
}
172174
indexCols[i] = colIndex
175+
indexColMap[colIndex] = struct{}{}
176+
}
177+
if len(indexColMap) != len(ast.ColumnNames) {
178+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "Index cannot contain same column multiple times")
173179
}
174180
info := &common.IndexInfo{
175181
SchemaName: c.SchemaName(),

command/create_mv_command.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,11 @@ func (c *CreateMVCommand) Before() error {
9595
return errors.WithStack(err)
9696
}
9797
c.mv = mv
98-
_, ok := c.e.metaController.GetMaterializedView(mv.Info.SchemaName, mv.Info.Name)
99-
if ok {
100-
return errors.NewMaterializedViewAlreadyExistsError(mv.Info.SchemaName, mv.Info.Name)
98+
99+
if err := c.e.metaController.ExistsMvOrSource(c.schema, mv.Info.Name); err != nil {
100+
return err
101101
}
102+
102103
rows, err := c.e.pullEngine.ExecuteQuery("sys",
103104
fmt.Sprintf("select id from tables where schema_name='%s' and name='%s' and kind='%s'", c.mv.Info.SchemaName, c.mv.Info.Name, meta.TableKindMaterializedView))
104105
if err != nil {

command/create_source_command.go

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ func (c *CreateSourceCommand) Before() error {
7676
}
7777

7878
func (c *CreateSourceCommand) validate() error {
79-
_, ok := c.e.metaController.GetSource(c.schemaName, c.sourceInfo.Name)
80-
if ok {
81-
return errors.NewSourceAlreadyExistsError(c.schemaName, c.sourceInfo.Name)
79+
schema := c.e.metaController.GetOrCreateSchema(c.schemaName)
80+
if err := c.e.metaController.ExistsMvOrSource(schema, c.sourceInfo.Name); err != nil {
81+
return err
8282
}
8383
rows, err := c.e.pullEngine.ExecuteQuery("sys",
8484
fmt.Sprintf("select id from tables where schema_name='%s' and name='%s' and kind='%s'", c.sourceInfo.SchemaName, c.sourceInfo.Name, meta.TableKindSource))
@@ -97,18 +97,18 @@ func (c *CreateSourceCommand) validate() error {
9797
}
9898
_, err := c.e.protoRegistry.FindDescriptorByName(protoreflect.FullName(enc.SchemaName))
9999
if err != nil {
100-
return errors.NewPranaErrorf(errors.UnknownTopicEncoding, "proto message %q not registered", enc.SchemaName)
100+
return errors.NewPranaErrorf(errors.InvalidStatement, "Proto message %q not registered", enc.SchemaName)
101101
}
102102
}
103103

104104
for _, sel := range topicInfo.ColSelectors {
105105
if sel.MetaKey == nil && len(sel.Selector) == 0 {
106-
return errors.NewPranaErrorf(errors.InvalidSelector, "invalid column selector %q", sel)
106+
return errors.NewPranaErrorf(errors.InvalidStatement, "Invalid column selector %q", sel)
107107
}
108108
if sel.MetaKey != nil {
109109
f := *sel.MetaKey
110110
if !(f == "header" || f == "key" || f == "timestamp") {
111-
return errors.NewPranaErrorf(errors.InvalidSelector, `invalid metadata key in column selector %q. Valid values are "header", "key", "timestamp".`, sel)
111+
return errors.NewPranaErrorf(errors.InvalidStatement, `Invalid metadata key in column selector %q. Valid values are "header", "key", "timestamp".`, sel)
112112
}
113113
}
114114
}
@@ -210,7 +210,7 @@ func (c *CreateSourceCommand) getSourceInfo(ast *parser.CreateSource) (*common.S
210210
for _, pk := range option.PrimaryKey {
211211
index, ok := colIndex[pk]
212212
if !ok {
213-
return nil, errors.Errorf("invalid primary key column %q", option.PrimaryKey)
213+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "Invalid primary key column %q", option.PrimaryKey)
214214
}
215215
pkCols = append(pkCols, index)
216216
}
@@ -232,17 +232,17 @@ func (c *CreateSourceCommand) getSourceInfo(ast *parser.CreateSource) (*common.S
232232
case opt.HeaderEncoding != "":
233233
headerEncoding = common.KafkaEncodingFromString(opt.HeaderEncoding)
234234
if headerEncoding.Encoding == common.EncodingUnknown {
235-
return nil, errors.NewPranaErrorf(errors.UnknownTopicEncoding, "Unknown topic encoding %s", opt.HeaderEncoding)
235+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "Unknown topic encoding %s", opt.HeaderEncoding)
236236
}
237237
case opt.KeyEncoding != "":
238238
keyEncoding = common.KafkaEncodingFromString(opt.KeyEncoding)
239239
if keyEncoding.Encoding == common.EncodingUnknown {
240-
return nil, errors.NewPranaErrorf(errors.UnknownTopicEncoding, "Unknown topic encoding %s", opt.KeyEncoding)
240+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "Unknown topic encoding %s", opt.KeyEncoding)
241241
}
242242
case opt.ValueEncoding != "":
243243
valueEncoding = common.KafkaEncodingFromString(opt.ValueEncoding)
244244
if valueEncoding.Encoding == common.EncodingUnknown {
245-
return nil, errors.NewPranaErrorf(errors.UnknownTopicEncoding, "Unknown topic encoding %s", opt.ValueEncoding)
245+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "Unknown topic encoding %s", opt.ValueEncoding)
246246
}
247247
case opt.IngestFilter != "":
248248
ingestFilter = opt.IngestFilter
@@ -264,24 +264,34 @@ func (c *CreateSourceCommand) getSourceInfo(ast *parser.CreateSource) (*common.S
264264
}
265265
}
266266
if headerEncoding == common.KafkaEncodingUnknown {
267-
return nil, errors.NewPranaError(errors.InvalidStatement, "headerEncoding is required")
267+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "headerEncoding is required")
268268
}
269269
if keyEncoding == common.KafkaEncodingUnknown {
270-
return nil, errors.NewPranaError(errors.InvalidStatement, "keyEncoding is required")
270+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "keyEncoding is required")
271271
}
272272
if valueEncoding == common.KafkaEncodingUnknown {
273-
return nil, errors.NewPranaError(errors.InvalidStatement, "valueEncoding is required")
273+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "valueEncoding is required")
274274
}
275275
if brokerName == "" {
276-
return nil, errors.NewPranaError(errors.InvalidStatement, "brokerName is required")
276+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "brokerName is required")
277277
}
278278
if topicName == "" {
279-
return nil, errors.NewPranaError(errors.InvalidStatement, "topicName is required")
279+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "topicName is required")
280280
}
281-
lc := len(colSelectors)
282-
if lc > 0 && lc != len(colTypes) {
283-
return nil, errors.NewPranaErrorf(errors.WrongNumberColumnSelectors,
284-
"Number of column selectors (%d) must match number of columns (%d)", lc, len(colTypes))
281+
if len(colSelectors) != len(colTypes) {
282+
return nil, errors.NewPranaErrorf(errors.InvalidStatement,
283+
"Number of column selectors (%d) must match number of columns (%d)", len(colSelectors), len(colTypes))
284+
}
285+
if len(pkCols) == 0 {
286+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "Primary key is required")
287+
}
288+
289+
pkMap := make(map[int]struct{}, len(pkCols))
290+
for _, pkCol := range pkCols {
291+
pkMap[pkCol] = struct{}{}
292+
}
293+
if len(pkMap) != len(pkCols) {
294+
return nil, errors.NewPranaErrorf(errors.InvalidStatement, "Primary key cannot contain same column multiple times")
285295
}
286296

287297
topicInfo := &common.TopicInfo{

command/drop_index_command.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ func (c *DropIndexCommand) getIndexInfo() (*common.IndexInfo, error) {
147147
c.indexName = ast.Drop.Name
148148
c.tableName = ast.Drop.TableName
149149
}
150+
if c.tableName == "" {
151+
return nil, errors.NewInvalidStatementError("Drop index requires a table")
152+
}
150153
indexInfo, ok := c.e.metaController.GetIndex(c.schemaName, c.tableName, c.indexName)
151154
if !ok {
152155
return nil, errors.NewUnknownIndexError(c.schemaName, c.tableName, c.indexName)

command/parser/ast.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,27 @@ func (c *ColumnDef) ToColumnType() (common.ColumnType, error) {
7373
switch c.Type {
7474
case common.TypeDecimal:
7575
if len(c.Parameters) != 2 {
76-
return common.ColumnType{}, participle.Errorf(c.Pos, "expected DECIMAL(precision, scale)")
76+
return common.ColumnType{}, participle.Errorf(c.Pos, "Expected DECIMAL(precision, scale)")
77+
}
78+
prec := c.Parameters[0]
79+
scale := c.Parameters[1]
80+
if prec > 65 || prec < 1 {
81+
return common.ColumnType{}, participle.Errorf(c.Pos, "Decimal precision must be > 0 and <= 65")
82+
}
83+
if scale > 30 || scale < 0 {
84+
return common.ColumnType{}, participle.Errorf(c.Pos, "decimal scale must be >= 0 and <= 30")
85+
}
86+
if scale > prec {
87+
return common.ColumnType{}, participle.Errorf(c.Pos, "Decimal scale must be <= precision")
7788
}
7889
return common.NewDecimalColumnType(c.Parameters[0], c.Parameters[1]), nil
7990
case common.TypeTimestamp:
8091
var fsp int8 = DefaultFSP
8192
if len(c.Parameters) == 1 {
8293
fsp = int8(c.Parameters[0])
94+
if fsp < 0 || fsp > 6 {
95+
return common.ColumnType{}, participle.Errorf(c.Pos, "Timestamp fsp must be >= 0 and <= 6")
96+
}
8397
}
8498
return common.NewTimestampColumnType(fsp), nil
8599
default:

conf/conf_test.go

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -259,41 +259,41 @@ func invalidRaftElectionRTTTooSmall() Config {
259259
}
260260

261261
var invalidConfigs = []configPair{
262-
{"PDB0004 - Invalid configuration: NodeID must be >= 0", invalidNodeIDConf()},
263-
{"PDB0004 - Invalid configuration: NumShards must be >= 1", invalidNumShardsConf()},
264-
{"PDB0004 - Invalid configuration: DataDir must be specified", invalidDatadirConf()},
265-
{"PDB0004 - Invalid configuration: KafkaBrokers must be specified", missingKafkaBrokersConf()},
266-
{"PDB0004 - Invalid configuration: KafkaBroker testbroker, invalid ClientType, must be 1 or 2", invalidBrokerClientTypeConf()},
267-
{"PDB0004 - Invalid configuration: RemotingHeartbeatInterval must be >= 1000000000", invalidRemotingHeartbeatInterval()},
268-
{"PDB0004 - Invalid configuration: RemotingHeartbeatTimeout must be >= 1000000", invalidRemotingHeartbeatTimeout()},
269-
{"PDB0004 - Invalid configuration: APIServerListenAddresses must be specified", invalidAPIServerListenAddress()},
270-
{"PDB0004 - Invalid configuration: NodeID must be in the range 0 (inclusive) to len(RaftAddresses) (exclusive)", NodeIDOutOfRangeConf()},
271-
{"PDB0004 - Invalid configuration: ReplicationFactor must be >= 3", invalidReplicationFactorConfig()},
272-
{"PDB0004 - Invalid configuration: Number of RaftAddresses must be >= ReplicationFactor", invalidRaftAddressesConfig()},
273-
{"PDB0004 - Invalid configuration: Number of RaftAddresses must be same as number of NotifListenerAddresses", raftAndNotifListenerAddressedDifferentLengthConfig()},
274-
{"PDB0004 - Invalid configuration: Number of RaftAddresses must be same as number of APIServerListenAddresses", raftAndAPIServerListenerAddressedDifferentLengthConfig()},
275-
{"PDB0004 - Invalid configuration: DataSnapshotEntries must be >= 10", invalidDataSnapshotEntries()},
276-
{"PDB0004 - Invalid configuration: DataCompactionOverhead must be >= 5", invalidDataCompactionOverhead()},
277-
{"PDB0004 - Invalid configuration: SequenceSnapshotEntries must be >= 10", invalidSequenceSnapshotEntries()},
278-
{"PDB0004 - Invalid configuration: SequenceCompactionOverhead must be >= 5", invalidSequenceCompactionOverhead()},
279-
{"PDB0004 - Invalid configuration: LocksSnapshotEntries must be >= 10", invalidLocksSnapshotEntries()},
280-
{"PDB0004 - Invalid configuration: LocksCompactionOverhead must be >= 5", invalidLocksCompactionOverhead()},
281-
{"PDB0004 - Invalid configuration: DataSnapshotEntries must be >= DataCompactionOverhead", dataCompactionGreaterThanDataSnapshotEntries()},
282-
{"PDB0004 - Invalid configuration: SequenceSnapshotEntries must be >= SequenceCompactionOverhead", sequenceCompactionGreaterThanDataSnapshotEntries()},
283-
{"PDB0004 - Invalid configuration: LocksSnapshotEntries must be >= LocksCompactionOverhead", locksCompactionGreaterThanDataSnapshotEntries()},
284-
{"PDB0004 - Invalid configuration: LifeCycleListenAddress must be specified", invalidLifecycleListenAddress()},
285-
{"PDB0004 - Invalid configuration: StartupEndpointPath must be specified", invalidStartupEndpointPath()},
286-
{"PDB0004 - Invalid configuration: LiveEndpointPath must be specified", invalidLiveEndpointPath()},
287-
{"PDB0004 - Invalid configuration: ReadyEndpointPath must be specified", invalidReadyEndpointPath()},
288-
{"PDB0004 - Invalid configuration: GlobalIngestLimitRowsPerSec must be > 0 or -1", invalidGlobalIngestLimitRowsPerSecZero()},
289-
{"PDB0004 - Invalid configuration: GlobalIngestLimitRowsPerSec must be > 0 or -1", invalidGlobalIngestLimitRowsPerNegative()},
290-
{"PDB0004 - Invalid configuration: RaftRTTMs must be > 0", invalidRaftRTTMsZero()},
291-
{"PDB0004 - Invalid configuration: RaftRTTMs must be > 0", invalidRaftRTTMsNegative()},
292-
{"PDB0004 - Invalid configuration: RaftHeartbeatRTT must be > 0", invalidRaftHeartbeatRTTZero()},
293-
{"PDB0004 - Invalid configuration: RaftHeartbeatRTT must be > 0", invalidRaftHeartbeatRTTNegative()},
294-
{"PDB0004 - Invalid configuration: RaftElectionRTT must be > 0", invalidRaftElectionRTTZero()},
295-
{"PDB0004 - Invalid configuration: RaftElectionRTT must be > 0", invalidRaftElectionRTTNegative()},
296-
{"PDB0004 - Invalid configuration: RaftElectionRTT must be > 2 * RaftHeartbeatRTT", invalidRaftElectionRTTTooSmall()},
262+
{"PDB3000 - Invalid configuration: NodeID must be >= 0", invalidNodeIDConf()},
263+
{"PDB3000 - Invalid configuration: NumShards must be >= 1", invalidNumShardsConf()},
264+
{"PDB3000 - Invalid configuration: DataDir must be specified", invalidDatadirConf()},
265+
{"PDB3000 - Invalid configuration: KafkaBrokers must be specified", missingKafkaBrokersConf()},
266+
{"PDB3000 - Invalid configuration: KafkaBroker testbroker, invalid ClientType, must be 1 or 2", invalidBrokerClientTypeConf()},
267+
{"PDB3000 - Invalid configuration: RemotingHeartbeatInterval must be >= 1000000000", invalidRemotingHeartbeatInterval()},
268+
{"PDB3000 - Invalid configuration: RemotingHeartbeatTimeout must be >= 1000000", invalidRemotingHeartbeatTimeout()},
269+
{"PDB3000 - Invalid configuration: APIServerListenAddresses must be specified", invalidAPIServerListenAddress()},
270+
{"PDB3000 - Invalid configuration: NodeID must be in the range 0 (inclusive) to len(RaftAddresses) (exclusive)", NodeIDOutOfRangeConf()},
271+
{"PDB3000 - Invalid configuration: ReplicationFactor must be >= 3", invalidReplicationFactorConfig()},
272+
{"PDB3000 - Invalid configuration: Number of RaftAddresses must be >= ReplicationFactor", invalidRaftAddressesConfig()},
273+
{"PDB3000 - Invalid configuration: Number of RaftAddresses must be same as number of NotifListenerAddresses", raftAndNotifListenerAddressedDifferentLengthConfig()},
274+
{"PDB3000 - Invalid configuration: Number of RaftAddresses must be same as number of APIServerListenAddresses", raftAndAPIServerListenerAddressedDifferentLengthConfig()},
275+
{"PDB3000 - Invalid configuration: DataSnapshotEntries must be >= 10", invalidDataSnapshotEntries()},
276+
{"PDB3000 - Invalid configuration: DataCompactionOverhead must be >= 5", invalidDataCompactionOverhead()},
277+
{"PDB3000 - Invalid configuration: SequenceSnapshotEntries must be >= 10", invalidSequenceSnapshotEntries()},
278+
{"PDB3000 - Invalid configuration: SequenceCompactionOverhead must be >= 5", invalidSequenceCompactionOverhead()},
279+
{"PDB3000 - Invalid configuration: LocksSnapshotEntries must be >= 10", invalidLocksSnapshotEntries()},
280+
{"PDB3000 - Invalid configuration: LocksCompactionOverhead must be >= 5", invalidLocksCompactionOverhead()},
281+
{"PDB3000 - Invalid configuration: DataSnapshotEntries must be >= DataCompactionOverhead", dataCompactionGreaterThanDataSnapshotEntries()},
282+
{"PDB3000 - Invalid configuration: SequenceSnapshotEntries must be >= SequenceCompactionOverhead", sequenceCompactionGreaterThanDataSnapshotEntries()},
283+
{"PDB3000 - Invalid configuration: LocksSnapshotEntries must be >= LocksCompactionOverhead", locksCompactionGreaterThanDataSnapshotEntries()},
284+
{"PDB3000 - Invalid configuration: LifeCycleListenAddress must be specified", invalidLifecycleListenAddress()},
285+
{"PDB3000 - Invalid configuration: StartupEndpointPath must be specified", invalidStartupEndpointPath()},
286+
{"PDB3000 - Invalid configuration: LiveEndpointPath must be specified", invalidLiveEndpointPath()},
287+
{"PDB3000 - Invalid configuration: ReadyEndpointPath must be specified", invalidReadyEndpointPath()},
288+
{"PDB3000 - Invalid configuration: GlobalIngestLimitRowsPerSec must be > 0 or -1", invalidGlobalIngestLimitRowsPerSecZero()},
289+
{"PDB3000 - Invalid configuration: GlobalIngestLimitRowsPerSec must be > 0 or -1", invalidGlobalIngestLimitRowsPerNegative()},
290+
{"PDB3000 - Invalid configuration: RaftRTTMs must be > 0", invalidRaftRTTMsZero()},
291+
{"PDB3000 - Invalid configuration: RaftRTTMs must be > 0", invalidRaftRTTMsNegative()},
292+
{"PDB3000 - Invalid configuration: RaftHeartbeatRTT must be > 0", invalidRaftHeartbeatRTTZero()},
293+
{"PDB3000 - Invalid configuration: RaftHeartbeatRTT must be > 0", invalidRaftHeartbeatRTTNegative()},
294+
{"PDB3000 - Invalid configuration: RaftElectionRTT must be > 0", invalidRaftElectionRTTZero()},
295+
{"PDB3000 - Invalid configuration: RaftElectionRTT must be > 0", invalidRaftElectionRTTNegative()},
296+
{"PDB3000 - Invalid configuration: RaftElectionRTT must be > 2 * RaftHeartbeatRTT", invalidRaftElectionRTTTooSmall()},
297297
}
298298

299299
func TestValidate(t *testing.T) {

0 commit comments

Comments
 (0)