github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/unstructured/redis_config_test.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 This file is part of KubeBlocks project 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package unstructured 21 22 import ( 23 "reflect" 24 "strings" 25 "testing" 26 27 "github.com/stretchr/testify/require" 28 29 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 30 "github.com/1aal/kubeblocks/test/testdata" 31 ) 32 33 func TestRedisConfig(t *testing.T) { 34 c, err := LoadConfig("test", "", appsv1alpha1.RedisCfg) 35 require.Nil(t, err) 36 37 tests := []struct { 38 keyArgs []string 39 valueArgs string 40 wantErr bool 41 testKey map[string]string 42 }{{ 43 keyArgs: []string{"port"}, 44 valueArgs: "6379", 45 wantErr: false, 46 testKey: map[string]string{ 47 "port": "6379", 48 }, 49 }, { 50 keyArgs: []string{"client-output-buffer-limit", "normal"}, 51 valueArgs: "0 0 0", 52 wantErr: false, 53 testKey: map[string]string{ 54 "client-output-buffer-limit": "normal 0 0 0", 55 }, 56 }, { 57 keyArgs: []string{"client-output-buffer-limit", "pubsub"}, 58 valueArgs: "256mb 64mb 60", 59 wantErr: false, 60 testKey: map[string]string{ 61 "client-output-buffer-limit pubsub": "256mb 64mb 60", 62 }, 63 }, { 64 keyArgs: []string{"client-output-buffer-limit", "normal"}, 65 valueArgs: "128mb 32mb 0", 66 wantErr: false, 67 testKey: map[string]string{ 68 "client-output-buffer-limit normal": "128mb 32mb 0", 69 "client-output-buffer-limit pubsub": "256mb 64mb 60", 70 "port": "6379", 71 }, 72 }} 73 for _, tt := range tests { 74 t.Run("config_test", func(t *testing.T) { 75 if err := c.Update(strings.Join(tt.keyArgs, " "), tt.valueArgs); (err != nil) != tt.wantErr { 76 t.Errorf("Update() error = %v, wantErr %v", err, tt.wantErr) 77 } 78 79 for key, value := range tt.testKey { 80 v, _ := c.GetString(key) 81 if v != value { 82 t.Errorf("GetString() param = %v, expected %v", key, value) 83 } 84 } 85 }) 86 } 87 } 88 89 func TestRedisConfigGetAllParameters(t *testing.T) { 90 type mockfn = func() ConfigObject 91 92 tests := []struct { 93 name string 94 fn mockfn 95 want map[string]interface{} 96 }{{ 97 name: "multi field update test", 98 fn: func() ConfigObject { 99 c, _ := LoadConfig("test", "", appsv1alpha1.RedisCfg) 100 _ = c.Update("port", "123") 101 _ = c.Update("a b", "123 234") 102 _ = c.Update("a c", "345") 103 _ = c.Update("a d", "1 2") 104 _ = c.Update("a d e", "1 2") 105 return c 106 }, 107 want: map[string]interface{}{ 108 "port": "123", 109 "a b 123": "234", 110 "a c 345": "", 111 "a d 1": "2", 112 "a d e": "1 2", 113 }, 114 }, { 115 name: "multi field update and delete test", 116 fn: func() ConfigObject { 117 c, _ := LoadConfig("test", "", appsv1alpha1.RedisCfg) 118 _ = c.Update("port", "123") 119 _ = c.Update("a b", "123 234") 120 _ = c.Update("a c", "345") 121 _ = c.Update("a d", "1 2") 122 _ = c.Update("a d e", "1 2") 123 _ = c.RemoveKey("a d e") 124 _ = c.RemoveKey("a b") 125 _ = c.RemoveKey("port") 126 return c 127 }, 128 want: map[string]interface{}{ 129 "a c": "345", 130 "a d": "1 2", 131 }, 132 }} 133 for _, tt := range tests { 134 t.Run(tt.name, func(t *testing.T) { 135 r := tt.fn() 136 if got := r.GetAllParameters(); !reflect.DeepEqual(got, tt.want) { 137 t.Errorf("GetAllParameters() = %v, want %v", got, tt.want) 138 } 139 }) 140 } 141 } 142 143 func TestRedisConfig_Marshal(t *testing.T) { 144 testDataFn := func(file string) string { 145 b, _ := testdata.GetTestDataFileContent(file) 146 return string(b) 147 } 148 149 commentsConfig := `# Lists may also be compressed. 150 # Compress depth is the number of quicklist ziplist nodes from *each* side of 151 # the list to *exclude* from compression. The head and tail of the list 152 # are always uncompressed for fast push/pop operations. Settings are: 153 # 0: disable all list compression 154 # 1: depth 1 means "don't start compressing until after 1 node into the list, 155 # going from either the head or tail" 156 # So: [head]->node->node->...->node->[tail] 157 # [head], [tail] will always be uncompressed; inner nodes will compress. 158 # 2: [head]->[next]->node->node->...->node->[prev]->[tail] 159 # 2 here means: don't compress head or head->next or tail->prev or tail, 160 # but compress all nodes between them. 161 # 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail] 162 # etc. 163 list-compress-depth 0 164 165 # Sets have a special encoding in just one case: when a set is composed 166 # of just strings that happen to be integers in radix 10 in the range 167 # of 64 bit signed integers. 168 # The following configuration setting sets the limit in the size of the 169 # set in order to use this special memory saving encoding. 170 set-max-intset-entries 512 171 172 # Similarly to hashes and lists, sorted sets are also specially encoded in 173 # order to save a lot of space. This encoding is only used when the length and 174 # elements of a sorted set are below the following limits: 175 zset-max-listpack-entries 128 176 zset-max-listpack-value 64` 177 178 tests := []struct { 179 name string 180 input string 181 want string 182 updated map[string]interface{} 183 wantErr bool 184 }{{ 185 name: "redis_cont_test", 186 input: testDataFn("config_encoding/redis.conf"), 187 want: testDataFn("config_encoding/redis.conf"), 188 }, { 189 name: "redis_cont_test", 190 input: commentsConfig, 191 want: commentsConfig, 192 updated: map[string]interface{}{ 193 "zset-max-listpack-entries": 128, 194 }, 195 }} 196 for _, tt := range tests { 197 t.Run(tt.name, func(t *testing.T) { 198 config, err := LoadConfig(tt.name, tt.input, appsv1alpha1.RedisCfg) 199 if (err != nil) != tt.wantErr { 200 t.Errorf("Marshal() error = %v, wantErr %v", err, tt.wantErr) 201 return 202 } 203 for key, value := range tt.updated { 204 require.Nil(t, config.Update(key, value)) 205 } 206 got, err := config.Marshal() 207 require.Nil(t, err) 208 if got != tt.want { 209 t.Errorf("Marshal() got = %v, want %v", got, tt.want) 210 } 211 }) 212 } 213 }