diff --git a/message.go b/message.go index 10b9725f..56146e65 100644 --- a/message.go +++ b/message.go @@ -571,7 +571,7 @@ func (m *RedisMessage) ToString() (val string, err error) { } if m.IsInt64() || m.values != nil { typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a string", typeNames[typ])) + return "", fmt.Errorf("redis message type %s is not a string", typeNames[typ]) } return m.string, m.Error() } @@ -645,7 +645,7 @@ func (m *RedisMessage) AsBool() (val bool, err error) { return default: typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a int, string or bool", typeNames[typ])) + return false, fmt.Errorf("redis message type %s is not a int, string or bool", typeNames[typ]) } } @@ -670,7 +670,7 @@ func (m *RedisMessage) ToInt64() (val int64, err error) { return 0, err } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a RESP3 int64", typeNames[typ])) + return 0, fmt.Errorf("redis message type %s is not a RESP3 int64", typeNames[typ]) } // ToBool check if message is a redis RESP3 bool response, and return it @@ -682,7 +682,7 @@ func (m *RedisMessage) ToBool() (val bool, err error) { return false, err } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a RESP3 bool", typeNames[typ])) + return false, fmt.Errorf("redis message type %s is not a RESP3 bool", typeNames[typ]) } // ToFloat64 check if message is a redis RESP3 double response, and return it @@ -694,7 +694,7 @@ func (m *RedisMessage) ToFloat64() (val float64, err error) { return 0, err } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a RESP3 float64", typeNames[typ])) + return 0, fmt.Errorf("redis message type %s is not a RESP3 float64", typeNames[typ]) } // ToArray check if message is a redis array/set response, and return it @@ -706,7 +706,7 @@ func (m *RedisMessage) ToArray() ([]RedisMessage, error) { return nil, err } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a array", typeNames[typ])) + return nil, fmt.Errorf("redis message type %s is not a array", typeNames[typ]) } // AsStrSlice check if message is a redis array/set response, and convert to []string. @@ -853,7 +853,7 @@ func (m *RedisMessage) AsXRead() (ret map[string][]XRangeEntry, err error) { return ret, nil } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a map/array/set or its length is not even", typeNames[typ])) + return nil, fmt.Errorf("redis message type %s is not a map/array/set", typeNames[typ]) } // ZScore is the element type of ZRANGE WITHSCORES, ZDIFF WITHSCORES and ZPOPMAX command response @@ -869,7 +869,7 @@ func toZScore(values []RedisMessage) (s ZScore, err error) { } return s, err } - panic("redis message is not a map/array/set or its length is not 2") + return ZScore{}, fmt.Errorf("redis message is not a map/array/set or its length is not 2") } // AsZScore converts ZPOPMAX and ZPOPMIN command with count 1 response to a single ZScore @@ -925,7 +925,7 @@ func (m *RedisMessage) AsScanEntry() (e ScanEntry, err error) { return e, err } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a scan response or its length is not at least 2", typeNames[typ])) + return ScanEntry{}, fmt.Errorf("redis message type %s is not a scan response or its length is not at least 2", typeNames[typ]) } // AsMap check if message is a redis array/set response, and convert to map[string]RedisMessage @@ -934,10 +934,10 @@ func (m *RedisMessage) AsMap() (map[string]RedisMessage, error) { return nil, err } if (m.IsMap() || m.IsArray()) && len(m.values)%2 == 0 { - return toMap(m.values), nil + return toMap(m.values) } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a map/array/set or its length is not even", typeNames[typ])) + return nil, fmt.Errorf("redis message type %s is not a map/array/set or its length is not even", typeNames[typ]) } // AsStrMap check if message is a redis map/array/set response, and convert to map[string]string. @@ -956,7 +956,7 @@ func (m *RedisMessage) AsStrMap() (map[string]string, error) { return r, nil } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a map/array/set or its length is not even", typeNames[typ])) + return nil, fmt.Errorf("redis message type %s is not a map/array/set or its length is not even", typeNames[typ]) } // AsIntMap check if message is a redis map/array/set response, and convert to map[string]int64. @@ -984,7 +984,7 @@ func (m *RedisMessage) AsIntMap() (map[string]int64, error) { return r, nil } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a map/array/set or its length is not even", typeNames[typ])) + return nil, fmt.Errorf("redis message type %s is not a map/array/set or its length is not even", typeNames[typ]) } type KeyValues struct { @@ -1002,7 +1002,7 @@ func (m *RedisMessage) AsLMPop() (kvs KeyValues, err error) { return } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a LMPOP response", typeNames[typ])) + return KeyValues{}, fmt.Errorf("redis message type %s is not a LMPOP response", typeNames[typ]) } type KeyZScores struct { @@ -1020,7 +1020,7 @@ func (m *RedisMessage) AsZMPop() (kvs KeyZScores, err error) { return } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a ZMPOP response", typeNames[typ])) + return KeyZScores{}, fmt.Errorf("redis message type %s is not a ZMPOP response", typeNames[typ]) } type FtSearchDoc struct { @@ -1098,7 +1098,7 @@ func (m *RedisMessage) AsFtSearch() (total int64, docs []FtSearchDoc, err error) return } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a FT.SEARCH response", typeNames[typ])) + return 0, nil, fmt.Errorf("redis message type %s is not a FT.SEARCH response", typeNames[typ]) } func (m *RedisMessage) AsFtAggregate() (total int64, docs []map[string]string, err error) { @@ -1139,7 +1139,7 @@ func (m *RedisMessage) AsFtAggregate() (total int64, docs []map[string]string, e return } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a FT.AGGREGATE response", typeNames[typ])) + return 0, nil, fmt.Errorf("redis message type %s is not a FT.AGGREGATE response", typeNames[typ]) } func (m *RedisMessage) AsFtAggregateCursor() (cursor, total int64, docs []map[string]string, err error) { @@ -1206,13 +1206,13 @@ func (m *RedisMessage) AsGeosearch() ([]GeoLocation, error) { // ToMap check if message is a redis RESP3 map response, and return it func (m *RedisMessage) ToMap() (map[string]RedisMessage, error) { if m.IsMap() { - return toMap(m.values), nil + return toMap(m.values) } if err := m.Error(); err != nil { return nil, err } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a RESP3 map", typeNames[typ])) + return nil, fmt.Errorf("redis message type %s is not a RESP3 map", typeNames[typ]) } // ToAny turns message into go any value @@ -1251,7 +1251,7 @@ func (m *RedisMessage) ToAny() (any, error) { return vs, nil } typ := m.typ - panic(fmt.Sprintf("redis message type %s is not a supported in ToAny", typeNames[typ])) + return nil, fmt.Errorf("redis message type %s is not a supported in ToAny", typeNames[typ]) } // IsCacheHit check if message is from client side cache @@ -1311,7 +1311,7 @@ func (m *RedisMessage) setExpireAt(pttl int64) { m.ttl[6] = byte(pttl >> 48) } -func toMap(values []RedisMessage) map[string]RedisMessage { +func toMap(values []RedisMessage) (map[string]RedisMessage, error) { r := make(map[string]RedisMessage, len(values)/2) for i := 0; i < len(values); i += 2 { if values[i].typ == typeBlobString || values[i].typ == typeSimpleString { @@ -1319,9 +1319,9 @@ func toMap(values []RedisMessage) map[string]RedisMessage { continue } typ := values[i].typ - panic(fmt.Sprintf("redis message type %s as map key is not supported", typeNames[typ])) + return nil, fmt.Errorf("redis message type %s as map key is not supported", typeNames[typ]) } - return r + return r, nil } func (m *RedisMessage) approximateSize() (s int) { diff --git a/message_test.go b/message_test.go index 0f1220d6..5505998d 100644 --- a/message_test.go +++ b/message_test.go @@ -1286,315 +1286,401 @@ func TestRedisMessage(t *testing.T) { } }) t.Run("ToInt64", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).ToInt64(); err == nil { - t.Fatal("ToInt64 not failed as expected") + // Test case where the message type is '_', which is not a RESP3 int64 + if val, err := (&RedisMessage{typ: '_'}).ToInt64(); err == nil { + t.Fatal("ToInt64 did not fail as expected") + } else if val != 0 { + t.Fatalf("expected 0, got %d", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a RESP3 int64") { - t.Fatal("ToInt64 not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).ToInt64() + // Test case where the message type is 't', which is not a RESP3 int64 + if val, err := (&RedisMessage{typ: 't'}).ToInt64(); err == nil { + t.Fatal("ToInt64 did not fail as expected") + } else if val != 0 { + t.Fatalf("expected 0, got %d", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a RESP3 int64") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("ToBool", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).ToBool(); err == nil { - t.Fatal("ToBool not failed as expected") + // Test case where the message type is '_', which is not a RESP3 bool + if val, err := (&RedisMessage{typ: '_'}).ToBool(); err == nil { + t.Fatal("ToBool did not fail as expected") + } else if val != false { + t.Fatalf("expected false, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a RESP3 bool") { - t.Fatal("ToBool not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).ToBool() + // Test case where the message type is 't', which is not a RESP3 bool + if val, err := (&RedisMessage{typ: 't'}).ToBool(); err == nil { + t.Fatal("ToBool did not fail as expected") + } else if val != false { + t.Fatalf("expected false, got %v", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a RESP3 bool") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsBool", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsBool(); err == nil { - t.Fatal("AsBool not failed as expected") + // Test case where the message type is '_', which is not a RESP3 int, string, or bool + if val, err := (&RedisMessage{typ: '_'}).AsBool(); err == nil { + t.Fatal("AsBool did not fail as expected") + } else if val != false { + t.Fatalf("expected false, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a int, string or bool") { - t.Fatal("AsBool not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).AsBool() + // Test case where the message type is 't', which is not a RESP3 int, string, or bool + if val, err := (&RedisMessage{typ: 't'}).AsBool(); err == nil { + t.Fatal("AsBool did not fail as expected") + } else if val != false { + t.Fatalf("expected false, got %v", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a int, string or bool") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("ToFloat64", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).ToFloat64(); err == nil { - t.Fatal("ToFloat64 not failed as expected") + // Test case where the message type is '_', which is not a RESP3 float64 + if val, err := (&RedisMessage{typ: '_'}).ToFloat64(); err == nil { + t.Fatal("ToFloat64 did not fail as expected") + } else if val != 0 { + t.Fatalf("expected 0, got %f", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a RESP3 float64") { - t.Fatal("ToFloat64 not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).ToFloat64() + // Test case where the message type is 't', which is not a RESP3 float64 + if val, err := (&RedisMessage{typ: 't'}).ToFloat64(); err == nil { + t.Fatal("ToFloat64 did not fail as expected") + } else if val != 0 { + t.Fatalf("expected 0, got %f", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a RESP3 float64") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("ToString", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).ToString(); err == nil { - t.Fatal("ToString not failed as expected") + // Test case where the message type is '_', which is not a RESP3 string + if val, err := (&RedisMessage{typ: '_'}).ToString(); err == nil { + t.Fatal("ToString did not fail as expected") + } else if val != "" { + t.Fatalf("expected empty string, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a string", typeNames[':'])) { - t.Fatal("ToString not panic as expected") - } - }() - (&RedisMessage{typ: ':'}).ToString() + // Test case where the message type is ':', which is not a RESP3 string + if val, err := (&RedisMessage{typ: ':'}).ToString(); err == nil { + t.Fatal("ToString did not fail as expected") + } else if val != "" { + t.Fatalf("expected empty string, got %v", val) + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a string", typeNames[':'])) { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsReader", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsReader(); err == nil { - t.Fatal("AsReader not failed as expected") + // Test case where the message type is '_', which is not a RESP3 string + if val, err := (&RedisMessage{typ: '_'}).AsReader(); err == nil { + t.Fatal("AsReader did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a string", typeNames[':'])) { - t.Fatal("AsReader not panic as expected") - } - }() - (&RedisMessage{typ: ':'}).AsReader() + // Test case where the message type is ':', which is not a RESP3 string + if val, err := (&RedisMessage{typ: ':'}).AsReader(); err == nil { + t.Fatal("AsReader did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a string", typeNames[':'])) { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsBytes", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsBytes(); err == nil { - t.Fatal("AsBytes not failed as expected") + // Test case where the message type is '_', which is not a RESP3 string + if val, err := (&RedisMessage{typ: '_'}).AsBytes(); err == nil { + t.Fatal("AsBytes did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a string", typeNames[':'])) { - t.Fatal("AsBytes not panic as expected") - } - }() - (&RedisMessage{typ: ':'}).AsBytes() + // Test case where the message type is ':', which is not a RESP3 string + if val, err := (&RedisMessage{typ: ':'}).AsBytes(); err == nil { + t.Fatal("AsBytes did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a string", typeNames[':'])) { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("DecodeJSON", func(t *testing.T) { + // Test case where the message type is '_', which is not a RESP3 string if err := (&RedisMessage{typ: '_'}).DecodeJSON(nil); err == nil { - t.Fatal("DecodeJSON not failed as expected") + t.Fatal("DecodeJSON did not fail as expected") } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a string", typeNames[':'])) { - t.Fatal("DecodeJSON not panic as expected") - } - }() - (&RedisMessage{typ: ':'}).DecodeJSON(nil) + // Test case where the message type is ':', which is not a RESP3 string + if err := (&RedisMessage{typ: ':'}).DecodeJSON(nil); err == nil { + t.Fatal("DecodeJSON did not fail as expected") + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a string", typeNames[':'])) { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsInt64", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsInt64(); err == nil { - t.Fatal("AsInt64 not failed as expected") + // Test case where the message type is '_', which is not a RESP3 string + if val, err := (&RedisMessage{typ: '_'}).AsInt64(); err == nil { + t.Fatal("AsInt64 did not fail as expected") + } else if val != 0 { + t.Fatalf("expected 0, got %d", val) + } + + // Test case where the message type is '*', which is not a RESP3 string + if val, err := (&RedisMessage{typ: '*', values: []RedisMessage{{}}}).AsInt64(); err == nil { + t.Fatal("AsInt64 did not fail as expected") + } else if val != 0 { + t.Fatalf("expected 0, got %d", val) + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a string", typeNames['*'])) { + t.Fatalf("unexpected error: %v", err) } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a string", typeNames['*'])) { - t.Fatal("AsInt64 not panic as expected") - } - }() - (&RedisMessage{typ: '*', values: []RedisMessage{{}}}).AsInt64() }) t.Run("AsUint64", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsUint64(); err == nil { - t.Fatal("AsUint64 not failed as expected") + // Test case where the message type is '_', which is not a RESP3 string + if val, err := (&RedisMessage{typ: '_'}).AsUint64(); err == nil { + t.Fatal("AsUint64 did not fail as expected") + } else if val != 0 { + t.Fatalf("expected 0, got %d", val) + } + + // Test case where the message type is '*', which is not a RESP3 string + if val, err := (&RedisMessage{typ: '*', values: []RedisMessage{{}}}).AsUint64(); err == nil { + t.Fatal("AsUint64 did not fail as expected") + } else if val != 0 { + t.Fatalf("expected 0, got %d", val) + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a string", typeNames['*'])) { + t.Fatalf("unexpected error: %v", err) } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a string", typeNames['*'])) { - t.Fatal("AsUint64 not panic as expected") - } - }() - (&RedisMessage{typ: '*', values: []RedisMessage{{}}}).AsUint64() }) t.Run("AsFloat64", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsFloat64(); err == nil { - t.Fatal("AsFloat64 not failed as expected") + // Test case where the message type is '_', which is not a RESP3 string + if val, err := (&RedisMessage{typ: '_'}).AsFloat64(); err == nil { + t.Fatal("AsFloat64 did not fail as expected") + } else if val != 0 { + t.Fatalf("expected 0, got %f", val) + } + + // Test case where the message type is ':', which is not a RESP3 string + if val, err := (&RedisMessage{typ: ':'}).AsFloat64(); err == nil { + t.Fatal("AsFloat64 did not fail as expected") + } else if val != 0 { + t.Fatalf("expected 0, got %f", val) + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a string", typeNames[':'])) { + t.Fatalf("unexpected error: %v", err) } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a string", typeNames[':'])) { - t.Fatal("AsFloat64 not panic as expected") - } - }() - (&RedisMessage{typ: ':'}).AsFloat64() }) t.Run("ToArray", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).ToArray(); err == nil { - t.Fatal("ToArray not failed as expected") + // Test case where the message type is '_', which is not a RESP3 array + if val, err := (&RedisMessage{typ: '_'}).ToArray(); err == nil { + t.Fatal("ToArray did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a array") { - t.Fatal("ToArray not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).ToArray() + // Test case where the message type is 't', which is not a RESP3 array + if val, err := (&RedisMessage{typ: 't'}).ToArray(); err == nil { + t.Fatal("ToArray did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a array") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsStrSlice", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsStrSlice(); err == nil { - t.Fatal("AsStrSlice not failed as expected") + // Test case where the message type is '_', which is not a RESP3 array + if val, err := (&RedisMessage{typ: '_'}).AsStrSlice(); err == nil { + t.Fatal("AsStrSlice did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a array") { - t.Fatal("AsStrSlice not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).AsStrSlice() + // Test case where the message type is 't', which is not a RESP3 array + if val, err := (&RedisMessage{typ: 't'}).AsStrSlice(); err == nil { + t.Fatal("AsStrSlice did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a array") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsIntSlice", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsIntSlice(); err == nil { - t.Fatal("AsIntSlice not failed as expected") + if val, err := (&RedisMessage{typ: '_'}).AsIntSlice(); err == nil { + t.Fatal("AsIntSlice did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a array") { - t.Fatal("AsIntSlice not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).AsIntSlice() + if val, err := (&RedisMessage{typ: 't'}).AsIntSlice(); err == nil { + t.Fatal("AsIntSlice did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a array") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsFloatSlice", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsFloatSlice(); err == nil { - t.Fatal("AsFloatSlice not failed as expected") + if val, err := (&RedisMessage{typ: '_'}).AsFloatSlice(); err == nil { + t.Fatal("AsFloatSlice did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a array") { - t.Fatal("AsFloatSlice not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).AsFloatSlice() + if val, err := (&RedisMessage{typ: 't'}).AsFloatSlice(); err == nil { + t.Fatal("AsFloatSlice did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a array") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsBoolSlice", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsBoolSlice(); err == nil { - t.Fatal("AsBoolSlice not failed as expected") + if val, err := (&RedisMessage{typ: '_'}).AsBoolSlice(); err == nil { + t.Fatal("AsBoolSlice did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a array") { - t.Fatal("AsBoolSlice not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).AsBoolSlice() + if val, err := (&RedisMessage{typ: 't'}).AsBoolSlice(); err == nil { + t.Fatal("AsBoolSlice did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a array") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsMap", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsMap(); err == nil { - t.Fatal("AsMap not failed as expected") + if val, err := (&RedisMessage{typ: '_'}).AsMap(); err == nil { + t.Fatal("AsMap did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a map/array/set or its length is not even") { - t.Fatal("AsMap not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).AsMap() + if val, err := (&RedisMessage{typ: 't'}).AsMap(); err == nil { + t.Fatal("AsMap did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a map/array/set or its length is not even") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsStrMap", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsStrMap(); err == nil { - t.Fatal("AsStrMap not failed as expected") + if val, err := (&RedisMessage{typ: '_'}).AsStrMap(); err == nil { + t.Fatal("AsStrMap did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a map/array/set") { - t.Fatal("AsMap not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).AsStrMap() + if val, err := (&RedisMessage{typ: 't'}).AsStrMap(); err == nil { + t.Fatal("AsStrMap did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a map/array/set") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsIntMap", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).AsIntMap(); err == nil { - t.Fatal("AsIntMap not failed as expected") + if val, err := (&RedisMessage{typ: '_'}).AsIntMap(); err == nil { + t.Fatal("AsIntMap did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a map/array/set") { - t.Fatal("AsMap not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).AsIntMap() + if val, err := (&RedisMessage{typ: 't'}).AsIntMap(); err == nil { + t.Fatal("AsIntMap did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a map/array/set") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("ToMap", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).ToMap(); err == nil { - t.Fatal("ToMap not failed as expected") + if val, err := (&RedisMessage{typ: '_'}).ToMap(); err == nil { + t.Fatal("ToMap did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a RESP3 map") { - t.Fatal("ToMap not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).ToMap() + if val, err := (&RedisMessage{typ: 't'}).ToMap(); err == nil { + t.Fatal("ToMap did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a RESP3 map") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("ToAny", func(t *testing.T) { - if _, err := (&RedisMessage{typ: '_'}).ToAny(); err == nil { - t.Fatal("ToAny not failed as expected") + if val, err := (&RedisMessage{typ: '_'}).ToAny(); err == nil { + t.Fatal("ToAny did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a supported in ToAny") { - t.Fatal("ToAny not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).ToAny() + if val, err := (&RedisMessage{typ: 't'}).ToAny(); err == nil { + t.Fatal("ToAny did not fail as expected") + } else if val != nil { + t.Fatalf("expected nil, got %v", val) + } else if !strings.Contains(err.Error(), "redis message type t is not a supported in ToAny") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsXRangeEntry - no range id", func(t *testing.T) { if _, err := (&RedisMessage{typ: '_'}).AsXRangeEntry(); err == nil { - t.Fatal("AsXRangeEntry not failed as expected") + t.Fatal("AsXRangeEntry did not fail as expected") } if _, err := (&RedisMessage{typ: '*'}).AsXRangeEntry(); err == nil { - t.Fatal("AsXRangeEntry not failed as expected") + t.Fatal("AsXRangeEntry did not fail as expected") } if _, err := (&RedisMessage{typ: '*', values: []RedisMessage{{typ: '_'}, {typ: '%'}}}).AsXRangeEntry(); err == nil { - t.Fatal("AsXRangeEntry not failed as expected") + t.Fatal("AsXRangeEntry did not fail as expected") } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a string", typeNames[':'])) { - t.Fatal("AsXRangeEntry not panic as expected") - } - }() - (&RedisMessage{typ: '*', values: []RedisMessage{{typ: ':'}, {typ: '%'}}}).AsXRangeEntry() + if _, err := (&RedisMessage{typ: '*', values: []RedisMessage{{typ: ':'}, {typ: '%'}}}).AsXRangeEntry(); err == nil { + t.Fatal("AsXRangeEntry did not fail as expected") + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a string", typeNames[':'])) { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsXRangeEntry - no range field values", func(t *testing.T) { if _, err := (&RedisMessage{typ: '_'}).AsXRangeEntry(); err == nil { - t.Fatal("AsXRangeEntry not failed as expected") + t.Fatal("AsXRangeEntry did not fail as expected") } if _, err := (&RedisMessage{typ: '*'}).AsXRangeEntry(); err == nil { - t.Fatal("AsXRangeEntry not failed as expected") + t.Fatal("AsXRangeEntry did not fail as expected") } if _, err := (&RedisMessage{typ: '*', values: []RedisMessage{{typ: '+'}, {typ: '-'}}}).AsXRangeEntry(); err == nil { - t.Fatal("AsXRangeEntry not failed as expected") + t.Fatal("AsXRangeEntry did not fail as expected") } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a map/array/set") { - t.Fatal("AsXRangeEntry not panic as expected") - } - }() - (&RedisMessage{typ: '*', values: []RedisMessage{{typ: '+'}, {typ: 't'}}}).AsXRangeEntry() + if _, err := (&RedisMessage{typ: '*', values: []RedisMessage{{typ: '+'}, {typ: 't'}}}).AsXRangeEntry(); err == nil { + t.Fatal("AsXRangeEntry did not fail as expected") + } else if !strings.Contains(err.Error(), "redis message type t is not a map/array/set") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsXRange", func(t *testing.T) { @@ -1609,48 +1695,50 @@ func TestRedisMessage(t *testing.T) { t.Run("AsXRead", func(t *testing.T) { if _, err := (&RedisMessage{typ: '_'}).AsXRead(); err == nil { - t.Fatal("AsXRead not failed as expected") + t.Fatal("AsXRead did not fail as expected") } + if _, err := (&RedisMessage{typ: '%', values: []RedisMessage{ {typ: '+', string: "stream1"}, {typ: '*', values: []RedisMessage{{typ: '*', values: []RedisMessage{{string: "id1", typ: '+'}}}}}, }}).AsXRead(); err == nil { - t.Fatal("AsXRead not failed as expected") + t.Fatal("AsXRead did not fail as expected") } + if _, err := (&RedisMessage{typ: '*', values: []RedisMessage{ {typ: '*', values: []RedisMessage{ {typ: '+', string: "stream1"}, }}, }}).AsXRead(); err == nil { - t.Fatal("AsXRead not failed as expected") + t.Fatal("AsXRead did not fail as expected") } + if _, err := (&RedisMessage{typ: '*', values: []RedisMessage{ {typ: '*', values: []RedisMessage{ {typ: '+', string: "stream1"}, {typ: '*', values: []RedisMessage{{typ: '*', values: []RedisMessage{{string: "id1", typ: '+'}}}}}, }}, }}).AsXRead(); err == nil { - t.Fatal("AsXRead not failed as expected") + t.Fatal("AsXRead did not fail as expected") } - defer func() { - if !strings.Contains(recover().(string), "redis message type t is not a map/array/set") { - t.Fatal("AsXRangeEntry not panic as expected") - } - }() - (&RedisMessage{typ: 't'}).AsXRead() + if _, err := (&RedisMessage{typ: 't'}).AsXRead(); err == nil { + t.Fatal("AsXRead did not fail as expected") + } else if !strings.Contains(err.Error(), "redis message type t is not a map/array/set") { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsZScore", func(t *testing.T) { if _, err := (&RedisMessage{typ: '_'}).AsZScore(); err == nil { - t.Fatal("AsZScore not failed as expected") + t.Fatal("AsZScore did not fail as expected") + } + + if _, err := (&RedisMessage{typ: '*'}).AsZScore(); err == nil { + t.Fatal("AsZScore did not fail as expected") + } else if !strings.Contains(err.Error(), "redis message is not a map/array/set or its length is not 2") { + t.Fatalf("unexpected error: %v", err) } - defer func() { - if !strings.Contains(recover().(string), "redis message is not a map/array/set or its length is not 2") { - t.Fatal("AsZScore not panic as expected") - } - }() - (&RedisMessage{typ: '*'}).AsZScore() }) t.Run("AsZScores", func(t *testing.T) { @@ -1675,78 +1763,80 @@ func TestRedisMessage(t *testing.T) { t.Run("AsLMPop", func(t *testing.T) { if _, err := (&RedisMessage{typ: '_'}).AsLMPop(); err == nil { - t.Fatal("AsLMPop not failed as expected") + t.Fatal("AsLMPop did not fail as expected") } + if _, err := (&RedisMessage{typ: '*', values: []RedisMessage{ {typ: '+', string: "k"}, {typ: '_'}, }}).AsLMPop(); err == nil { - t.Fatal("AsLMPop not fails as expected") + t.Fatal("AsLMPop did not fail as expected") } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a LMPOP response", typeNames['*'])) { - t.Fatal("AsLMPop not panic as expected") - } - }() - (&RedisMessage{typ: '*', values: []RedisMessage{ + + if _, err := (&RedisMessage{typ: '*', values: []RedisMessage{ {typ: '+', string: "k"}, - }}).AsLMPop() + }}).AsLMPop(); err == nil { + t.Fatal("AsLMPop did not fail as expected") + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a LMPOP response", typeNames['*'])) { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsZMPop", func(t *testing.T) { if _, err := (&RedisMessage{typ: '_'}).AsZMPop(); err == nil { - t.Fatal("AsZMPop not failed as expected") + t.Fatal("AsZMPop did not fail as expected") } + if _, err := (&RedisMessage{typ: '*', values: []RedisMessage{ {typ: '+', string: "k"}, {typ: '_'}, }}).AsZMPop(); err == nil { - t.Fatal("AsZMPop not fails as expected") + t.Fatal("AsZMPop did not fail as expected") } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a ZMPOP response", typeNames['*'])) { - t.Fatal("AsZMPop not panic as expected") - } - }() - (&RedisMessage{typ: '*', values: []RedisMessage{ + + if _, err := (&RedisMessage{typ: '*', values: []RedisMessage{ {typ: '+', string: "k"}, - }}).AsZMPop() + }}).AsZMPop(); err == nil { + t.Fatal("AsZMPop did not fail as expected") + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a ZMPOP response", typeNames['*'])) { + t.Fatalf("unexpected error: %v", err) + } }) t.Run("AsFtSearch", func(t *testing.T) { if _, _, err := (&RedisMessage{typ: '_'}).AsFtSearch(); err == nil { - t.Fatal("AsFtSearch not failed as expected") + t.Fatal("AsFtSearch did not fail as expected") + } + + if _, _, err := (&RedisMessage{typ: '*'}).AsFtSearch(); err == nil { + t.Fatal("AsFtSearch did not fail as expected") + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a FT.SEARCH response", typeNames['*'])) { + t.Fatalf("unexpected error: %v", err) } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a FT.SEARCH response", typeNames['*'])) { - t.Fatal("AsFtSearch not panic as expected") - } - }() - (&RedisMessage{typ: '*', values: []RedisMessage{}}).AsFtSearch() }) t.Run("AsFtAggregate", func(t *testing.T) { if _, _, err := (&RedisMessage{typ: '_'}).AsFtAggregate(); err == nil { - t.Fatal("AsFtAggregate not failed as expected") + t.Fatal("AsFtAggregate did not fail as expected") + } + + if _, _, err := (&RedisMessage{typ: '*'}).AsFtAggregate(); err == nil { + t.Fatal("AsFtAggregate did not fail as expected") + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a FT.AGGREGATE response", typeNames['*'])) { + t.Fatalf("unexpected error: %v", err) } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a FT.AGGREGATE response", typeNames['*'])) { - t.Fatal("AsFtAggregate not panic as expected") - } - }() - (&RedisMessage{typ: '*', values: []RedisMessage{}}).AsFtAggregate() }) t.Run("AsFtAggregateCursor", func(t *testing.T) { if _, _, _, err := (&RedisMessage{typ: '_'}).AsFtAggregateCursor(); err == nil { - t.Fatal("AsFtAggregate not failed as expected") + t.Fatal("AsFtAggregateCursor did not fail as expected") + } + + if _, _, _, err := (&RedisMessage{typ: '*'}).AsFtAggregateCursor(); err == nil { + t.Fatal("AsFtAggregateCursor did not fail as expected") + } else if !strings.Contains(err.Error(), fmt.Sprintf("redis message type %s is not a FT.AGGREGATE response", typeNames['*'])) { + t.Fatalf("unexpected error: %v", err) } - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a FT.AGGREGATE response", typeNames['*'])) { - t.Fatal("AsFtAggregate not panic as expected") - } - }() - (&RedisMessage{typ: '*', values: []RedisMessage{}}).AsFtAggregateCursor() }) t.Run("AsScanEntry", func(t *testing.T) { @@ -1765,22 +1855,16 @@ func TestRedisMessage(t *testing.T) { if ret, _ := (RedisResult{val: RedisMessage{typ: '*', values: []RedisMessage{{string: "0", typ: '+'}, {typ: '_'}}}}).AsScanEntry(); !reflect.DeepEqual(ScanEntry{}, ret) { t.Fatal("AsScanEntry not get value as expected") } - - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s is not a scan response or its length is not at least 2", typeNames['*'])) { - t.Fatal("AsScanEntry not panic as expected") - } - }() - (&RedisMessage{typ: '*', values: []RedisMessage{{typ: ':'}}}).AsScanEntry() }) - t.Run("ToMap with non string key", func(t *testing.T) { - defer func() { - if !strings.Contains(recover().(string), fmt.Sprintf("redis message type %s as map key is not supported", typeNames[':'])) { - t.Fatal("ToMap not panic as expected") - } - }() - (&RedisMessage{typ: '%', values: []RedisMessage{{typ: ':'}, {typ: ':'}}}).ToMap() + t.Run("ToMap with non-string key", func(t *testing.T) { + _, err := (&RedisMessage{typ: '~', values: []RedisMessage{{typ: ':'}, {typ: ':'}}}).ToMap() + if err == nil { + t.Fatal("ToMap did not fail as expected") + } + if !strings.Contains(err.Error(), "redis message type set is not a RESP3 map") { + t.Fatalf("ToMap failed with unexpected error: %v", err) + } }) t.Run("IsCacheHit", func(t *testing.T) {