Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ testdata/*
.DS_Store
*.tar.gz
*.dic
redis8tests.sh
48 changes: 33 additions & 15 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -3862,30 +3862,48 @@ func (cmd *MapMapStringInterfaceCmd) Val() map[string]interface{} {
return cmd.val
}

// readReply will try to parse the reply from the proto.Reader for both resp2 and resp3
func (cmd *MapMapStringInterfaceCmd) readReply(rd *proto.Reader) (err error) {
n, err := rd.ReadArrayLen()
data, err := rd.ReadReply()
if err != nil {
return err
}
resultMap := map[string]interface{}{}

data := make(map[string]interface{}, n/2)
for i := 0; i < n; i += 2 {
_, err := rd.ReadArrayLen()
if err != nil {
cmd.err = err
}
key, err := rd.ReadString()
if err != nil {
cmd.err = err
switch midResponse := data.(type) {
case map[interface{}]interface{}: // resp3 will return map
for k, v := range midResponse {
stringKey, ok := k.(string)
if !ok {
return fmt.Errorf("redis: invalid map key %#v", k)
}
resultMap[stringKey] = v
}
value, err := rd.ReadString()
if err != nil {
cmd.err = err
case []interface{}: // resp2 will return array of arrays
n := len(midResponse)
for i := 0; i < n; i++ {
finalArr, ok := midResponse[i].([]interface{}) // final array that we need to transform to map
if !ok {
return fmt.Errorf("redis: unexpected response %#v", data)
}
m := len(finalArr)
if m%2 != 0 { // since this should be map, keys should be even number
return fmt.Errorf("redis: unexpected response %#v", data)
}

for j := 0; j < m; j += 2 {
stringKey, ok := finalArr[j].(string) // the first one
if !ok {
return fmt.Errorf("redis: invalid map key %#v", finalArr[i])
}
resultMap[stringKey] = finalArr[j+1] // second one is value
}
}
data[key] = value
default:
return fmt.Errorf("redis: unexpected response %#v", data)
}

cmd.val = data
cmd.val = resultMap
return nil
}

Expand Down
138 changes: 138 additions & 0 deletions commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,23 @@ var _ = Describe("Commands", func() {
Expect(val).NotTo(BeEmpty())
})

It("should ConfigGet Modules", func() {
SkipBeforeRedisMajor(8, "Config doesn't include modules before Redis 8")
expected := map[string]string{
"search-*": "search-min-prefix",
"ts-*": "ts-retention-policy",
"bf-*": "bf-error-rate",
"cf-*": "cf-initial-size",
}

for prefix, lookup := range expected {
val, err := client.ConfigGet(ctx, prefix).Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).NotTo(BeEmpty())
Expect(val[lookup]).NotTo(BeEmpty())
}
})

It("should ConfigResetStat", Label("NonRedisEnterprise"), func() {
r := client.ConfigResetStat(ctx)
Expect(r.Err()).NotTo(HaveOccurred())
Expand All @@ -362,6 +379,127 @@ var _ = Describe("Commands", func() {
Expect(configSet.Val()).To(Equal("OK"))
})

It("should ConfigGet with Modules", Label("NonRedisEnterprise"), func() {
SkipBeforeRedisMajor(8, "config get won't return modules configs before redis 8")
configGet := client.ConfigGet(ctx, "*")
Expect(configGet.Err()).NotTo(HaveOccurred())
Expect(configGet.Val()).To(HaveKey("maxmemory"))
Expect(configGet.Val()).To(HaveKey("search-timeout"))
Expect(configGet.Val()).To(HaveKey("ts-retention-policy"))
Expect(configGet.Val()).To(HaveKey("bf-error-rate"))
Expect(configGet.Val()).To(HaveKey("cf-initial-size"))
})

It("should ConfigSet FT DIALECT", func() {
SkipBeforeRedisMajor(8, "config doesn't include modules before Redis 8")
defaultState, err := client.ConfigGet(ctx, "search-default-dialect").Result()
Expect(err).NotTo(HaveOccurred())

// set to 3
res, err := client.ConfigSet(ctx, "search-default-dialect", "3").Result()
Expect(err).NotTo(HaveOccurred())
Expect(res).To(BeEquivalentTo("OK"))

defDialect, err := client.FTConfigGet(ctx, "DEFAULT_DIALECT").Result()
Expect(err).NotTo(HaveOccurred())
Expect(defDialect).To(BeEquivalentTo(map[string]interface{}{"DEFAULT_DIALECT": "3"}))

resGet, err := client.ConfigGet(ctx, "search-default-dialect").Result()
Expect(err).NotTo(HaveOccurred())
Expect(resGet).To(BeEquivalentTo(map[string]string{"search-default-dialect": "3"}))

// set to 2
res, err = client.ConfigSet(ctx, "search-default-dialect", "2").Result()
Expect(err).NotTo(HaveOccurred())
Expect(res).To(BeEquivalentTo("OK"))

defDialect, err = client.FTConfigGet(ctx, "DEFAULT_DIALECT").Result()
Expect(err).NotTo(HaveOccurred())
Expect(defDialect).To(BeEquivalentTo(map[string]interface{}{"DEFAULT_DIALECT": "2"}))

// set to 1
res, err = client.ConfigSet(ctx, "search-default-dialect", "1").Result()
Expect(err).NotTo(HaveOccurred())
Expect(res).To(BeEquivalentTo("OK"))

defDialect, err = client.FTConfigGet(ctx, "DEFAULT_DIALECT").Result()
Expect(err).NotTo(HaveOccurred())
Expect(defDialect).To(BeEquivalentTo(map[string]interface{}{"DEFAULT_DIALECT": "1"}))

resGet, err = client.ConfigGet(ctx, "search-default-dialect").Result()
Expect(err).NotTo(HaveOccurred())
Expect(resGet).To(BeEquivalentTo(map[string]string{"search-default-dialect": "1"}))

// set to default
res, err = client.ConfigSet(ctx, "search-default-dialect", defaultState["search-default-dialect"]).Result()
Expect(err).NotTo(HaveOccurred())
Expect(res).To(BeEquivalentTo("OK"))
})

It("should ConfigSet fail for ReadOnly", func() {
SkipBeforeRedisMajor(8, "Config doesn't include modules before Redis 8")
_, err := client.ConfigSet(ctx, "search-max-doctablesize", "100000").Result()
Expect(err).To(HaveOccurred())
})

It("should ConfigSet Modules", func() {
SkipBeforeRedisMajor(8, "Config doesn't include modules before Redis 8")
defaults := map[string]string{}
expected := map[string]string{
"search-timeout": "100",
"ts-retention-policy": "2",
"bf-error-rate": "0.13",
"cf-initial-size": "64",
}

// read the defaults to set them back later
for setting, _ := range expected {
val, err := client.ConfigGet(ctx, setting).Result()
Expect(err).NotTo(HaveOccurred())
defaults[setting] = val[setting]
}

// check if new values can be set
for setting, value := range expected {
val, err := client.ConfigSet(ctx, setting, value).Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).NotTo(BeEmpty())
Expect(val).To(Equal("OK"))
}

for setting, value := range expected {
val, err := client.ConfigGet(ctx, setting).Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).NotTo(BeEmpty())
Expect(val[setting]).To(Equal(value))
}

// set back to the defaults
for setting, value := range defaults {
val, err := client.ConfigSet(ctx, setting, value).Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).NotTo(BeEmpty())
Expect(val).To(Equal("OK"))
}
})

It("should Fail ConfigSet Modules", func() {
SkipBeforeRedisMajor(8, "Config doesn't include modules before Redis 8")
expected := map[string]string{
"search-timeout": "-100",
"ts-retention-policy": "-10",
"bf-error-rate": "1.5",
"cf-initial-size": "-10",
}

for setting, value := range expected {
val, err := client.ConfigSet(ctx, setting, value).Result()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(ContainSubstring(setting)))
Expect(val).To(BeEmpty())
}
})

It("should ConfigRewrite", Label("NonRedisEnterprise"), func() {
configRewrite := client.ConfigRewrite(ctx)
Expect(configRewrite.Err()).NotTo(HaveOccurred())
Expand Down
30 changes: 23 additions & 7 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,19 @@ var RCEDocker = false
// Notes the major version of redis we are executing tests.
// This can be used before we change the bsm fork of ginkgo for one,
// which have support for label sets, so we can filter tests per redis major version.
var REDIS_MAJOR_VERSION = 7
var RedisMajorVersion = 7

func SkipBeforeRedisMajor(version int, msg string) {
if RedisMajorVersion < version {
Skip(fmt.Sprintf("(redis major version < %d) %s", version, msg))
}
}

func SkipAfterRedisMajor(version int, msg string) {
if RedisMajorVersion > version {
Skip(fmt.Sprintf("(redis major version > %d) %s", version, msg))
}
}

func registerProcess(port string, p *redisProcess) {
if processes == nil {
Expand All @@ -92,16 +104,20 @@ var _ = BeforeSuite(func() {
RECluster, _ = strconv.ParseBool(os.Getenv("RE_CLUSTER"))
RCEDocker, _ = strconv.ParseBool(os.Getenv("RCE_DOCKER"))

REDIS_MAJOR_VERSION, _ = strconv.Atoi(os.Getenv("REDIS_MAJOR_VERSION"))
if REDIS_MAJOR_VERSION == 0 {
REDIS_MAJOR_VERSION = 7
RedisMajorVersion, _ = strconv.Atoi(os.Getenv("REDIS_MAJOR_VERSION"))

if RedisMajorVersion == 0 {
RedisMajorVersion = 7
}
Expect(REDIS_MAJOR_VERSION).To(BeNumerically(">=", 6))
Expect(REDIS_MAJOR_VERSION).To(BeNumerically("<=", 8))

fmt.Printf("RECluster: %v\n", RECluster)
fmt.Printf("RCEDocker: %v\n", RCEDocker)
fmt.Printf("REDIS_MAJOR_VERSION: %v\n", REDIS_MAJOR_VERSION)
fmt.Printf("REDIS_MAJOR_VERSION: %v\n", RedisMajorVersion)

if RedisMajorVersion < 6 || RedisMajorVersion > 8 {
panic("incorrect or not supported redis major version")
}

if !RECluster && !RCEDocker {

redisMain, err = startRedis(redisPort)
Expand Down
24 changes: 18 additions & 6 deletions search_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -831,20 +831,32 @@ func (c cmdable) FTAlter(ctx context.Context, index string, skipInitialScan bool
return cmd
}

// FTConfigGet - Retrieves the value of a RediSearch configuration parameter.
// Deprecated: FTConfigGet is deprecated in Redis 8.
// All configuration will be done with the CONFIG GET command.
// For more information check [Client.ConfigGet] and [CONFIG GET Documentation]
//
// Retrieves the value of a RediSearch configuration parameter.
// The 'option' parameter specifies the configuration parameter to retrieve.
// For more information, please refer to the Redis documentation:
// [FT.CONFIG GET]: (https://redis.io/commands/ft.config-get/)
// For more information, please refer to the Redis [FT.CONFIG GET] documentation.
//
// [CONFIG GET Documentation]: https://redis.io/commands/config-get/
// [FT.CONFIG GET]: https://redis.io/commands/ft.config-get/
func (c cmdable) FTConfigGet(ctx context.Context, option string) *MapMapStringInterfaceCmd {
cmd := NewMapMapStringInterfaceCmd(ctx, "FT.CONFIG", "GET", option)
_ = c(ctx, cmd)
return cmd
}

// FTConfigSet - Sets the value of a RediSearch configuration parameter.
// Deprecated: FTConfigSet is deprecated in Redis 8.
// All configuration will be done with the CONFIG SET command.
// For more information check [Client.ConfigSet] and [CONFIG SET Documentation]
//
// Sets the value of a RediSearch configuration parameter.
// The 'option' parameter specifies the configuration parameter to set, and the 'value' parameter specifies the new value.
// For more information, please refer to the Redis documentation:
// [FT.CONFIG SET]: (https://redis.io/commands/ft.config-set/)
// For more information, please refer to the Redis [FT.CONFIG SET] documentation.
//
// [CONFIG SET Documentation]: https://redis.io/commands/config-set/
// [FT.CONFIG SET]: https://redis.io/commands/ft.config-set/
func (c cmdable) FTConfigSet(ctx context.Context, option string, value interface{}) *StatusCmd {
cmd := NewStatusCmd(ctx, "FT.CONFIG", "SET", option, value)
_ = c(ctx, cmd)
Expand Down
Loading
Loading