mirror of
https://github.com/redis/go-redis.git
synced 2026-10-28 08:24:54 +08:00
fix(cmd): accept nil HGetEXOptions/HSetEXOptions (#4214)
HGetEXWithArgs and HSetEXWithArgs panicked with a nil pointer dereference when the options were nil. Treat nil like empty options, as SDiffCard and SUnionCard do, so the commands match HGetEX and HSetEX. Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com>
This commit is contained in:
1 parent
470a926a08
commit
7f1c98cdf7
2 files changed
+97
No files matched your search
@@ -549,6 +549,9 @@ type HGetEXOptions struct {
|
||||
}
|
||||
|
||||
func (c cmdable) HGetEXWithArgs(ctx context.Context, key string, options *HGetEXOptions, fields ...string) *StringSliceCmd {
|
||||
if options == nil {
|
||||
options = &HGetEXOptions{}
|
||||
}
|
||||
args := []interface{}{"HGETEX", key}
|
||||
if options.ExpirationType != "" {
|
||||
args = append(args, string(options.ExpirationType))
|
||||
@@ -602,6 +605,9 @@ func (c cmdable) HSetEX(ctx context.Context, key string, fieldsAndValues ...stri
|
||||
}
|
||||
|
||||
func (c cmdable) HSetEXWithArgs(ctx context.Context, key string, options *HSetEXOptions, fieldsAndValues ...string) *IntCmd {
|
||||
if options == nil {
|
||||
options = &HSetEXOptions{}
|
||||
}
|
||||
args := []interface{}{"HSETEX", key}
|
||||
if options.Condition != "" {
|
||||
args = append(args, string(options.Condition))
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestHGetEXWithArgsArgs checks that HGetEXWithArgs builds HGETEX with and
|
||||
// without options. Nil options send the same command as HGetEX.
|
||||
func TestHGetEXWithArgsArgs(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
options *HGetEXOptions
|
||||
want []interface{}
|
||||
}{
|
||||
{
|
||||
name: "nil_options",
|
||||
want: []interface{}{"HGETEX", "key", "FIELDS", 2, "f1", "f2"},
|
||||
},
|
||||
{
|
||||
name: "empty_options",
|
||||
options: &HGetEXOptions{},
|
||||
want: []interface{}{"HGETEX", "key", "FIELDS", 2, "f1", "f2"},
|
||||
},
|
||||
{
|
||||
name: "ex",
|
||||
options: &HGetEXOptions{ExpirationType: HGetEXExpirationEX, ExpirationVal: 60},
|
||||
want: []interface{}{"HGETEX", "key", "EX", int64(60), "FIELDS", 2, "f1", "f2"},
|
||||
},
|
||||
{
|
||||
name: "persist",
|
||||
options: &HGetEXOptions{ExpirationType: HGetEXExpirationPERSIST},
|
||||
want: []interface{}{"HGETEX", "key", "PERSIST", "FIELDS", 2, "f1", "f2"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var captured Cmder
|
||||
cmd := captureCmdable(&captured).HGetEXWithArgs(ctx, "key", tt.options, "f1", "f2")
|
||||
if !reflect.DeepEqual(cmd.Args(), tt.want) {
|
||||
t.Errorf("args mismatch\n got: %#v\nwant: %#v", cmd.Args(), tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestHSetEXWithArgsArgs checks that HSetEXWithArgs builds HSETEX with and
|
||||
// without options. Nil options send the same command as HSetEX.
|
||||
func TestHSetEXWithArgsArgs(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
options *HSetEXOptions
|
||||
want []interface{}
|
||||
}{
|
||||
{
|
||||
name: "nil_options",
|
||||
want: []interface{}{"HSETEX", "key", "FIELDS", 1, "f1", "v1"},
|
||||
},
|
||||
{
|
||||
name: "empty_options",
|
||||
options: &HSetEXOptions{},
|
||||
want: []interface{}{"HSETEX", "key", "FIELDS", 1, "f1", "v1"},
|
||||
},
|
||||
{
|
||||
name: "fnx_ex",
|
||||
options: &HSetEXOptions{Condition: HSetEXFNX, ExpirationType: HSetEXExpirationEX, ExpirationVal: 60},
|
||||
want: []interface{}{"HSETEX", "key", "FNX", "EX", int64(60), "FIELDS", 1, "f1", "v1"},
|
||||
},
|
||||
{
|
||||
name: "keepttl",
|
||||
options: &HSetEXOptions{ExpirationType: HSetEXExpirationKEEPTTL},
|
||||
want: []interface{}{"HSETEX", "key", "KEEPTTL", "FIELDS", 1, "f1", "v1"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var captured Cmder
|
||||
cmd := captureCmdable(&captured).HSetEXWithArgs(ctx, "key", tt.options, "f1", "v1")
|
||||
if !reflect.DeepEqual(cmd.Args(), tt.want) {
|
||||
t.Errorf("args mismatch\n got: %#v\nwant: %#v", cmd.Args(), tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user