github.com/hdt3213/godis@v1.2.9/database/hash_test.go (about) 1 package database 2 3 import ( 4 "fmt" 5 "github.com/hdt3213/godis/lib/utils" 6 "github.com/hdt3213/godis/redis/protocol" 7 "github.com/hdt3213/godis/redis/protocol/asserts" 8 "strconv" 9 "testing" 10 ) 11 12 func TestHSet(t *testing.T) { 13 testDB.Flush() 14 size := 100 15 16 // test hset 17 key := utils.RandString(10) 18 values := make(map[string][]byte, size) 19 for i := 0; i < size; i++ { 20 value := utils.RandString(10) 21 field := strconv.Itoa(i) 22 values[field] = []byte(value) 23 result := testDB.Exec(nil, utils.ToCmdLine("hset", key, field, value)) 24 if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(1) { 25 t.Error(fmt.Sprintf("expected %d, actually %d", 1, intResult.Code)) 26 } 27 } 28 29 // test hget, hexists and hstrlen 30 for field, v := range values { 31 actual := testDB.Exec(nil, utils.ToCmdLine("hget", key, field)) 32 expected := protocol.MakeBulkReply(v) 33 if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) { 34 t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(actual.ToBytes()))) 35 } 36 actual = testDB.Exec(nil, utils.ToCmdLine("hexists", key, field)) 37 if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(1) { 38 t.Error(fmt.Sprintf("expected %d, actually %d", 1, intResult.Code)) 39 } 40 41 actual = testDB.Exec(nil, utils.ToCmdLine("hstrlen", key, field)) 42 if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(len(v)) { 43 t.Error(fmt.Sprintf("expected %d, actually %d", int64(len(v)), intResult.Code)) 44 } 45 } 46 47 // test hlen 48 actual := testDB.Exec(nil, utils.ToCmdLine("hlen", key)) 49 if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(len(values)) { 50 t.Error(fmt.Sprintf("expected %d, actually %d", len(values), intResult.Code)) 51 } 52 } 53 54 func TestHDel(t *testing.T) { 55 testDB.Flush() 56 size := 100 57 58 // set values 59 key := utils.RandString(10) 60 fields := make([]string, size) 61 for i := 0; i < size; i++ { 62 value := utils.RandString(10) 63 field := strconv.Itoa(i) 64 fields[i] = field 65 testDB.Exec(nil, utils.ToCmdLine("hset", key, field, value)) 66 } 67 68 // test HDel 69 args := []string{key} 70 args = append(args, fields...) 71 actual := testDB.Exec(nil, utils.ToCmdLine2("hdel", args...)) 72 if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(len(fields)) { 73 t.Error(fmt.Sprintf("expected %d, actually %d", len(fields), intResult.Code)) 74 } 75 76 actual = testDB.Exec(nil, utils.ToCmdLine("hlen", key)) 77 if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(0) { 78 t.Error(fmt.Sprintf("expected %d, actually %d", 0, intResult.Code)) 79 } 80 } 81 82 func TestHMSet(t *testing.T) { 83 testDB.Flush() 84 size := 100 85 86 // test hset 87 key := utils.RandString(10) 88 fields := make([]string, size) 89 values := make([]string, size) 90 setArgs := []string{key} 91 for i := 0; i < size; i++ { 92 fields[i] = utils.RandString(10) 93 values[i] = utils.RandString(10) 94 setArgs = append(setArgs, fields[i], values[i]) 95 } 96 result := testDB.Exec(nil, utils.ToCmdLine2("hmset", setArgs...)) 97 if _, ok := result.(*protocol.OkReply); !ok { 98 t.Error(fmt.Sprintf("expected ok, actually %s", string(result.ToBytes()))) 99 } 100 101 // test HMGet 102 getArgs := []string{key} 103 getArgs = append(getArgs, fields...) 104 actual := testDB.Exec(nil, utils.ToCmdLine2("hmget", getArgs...)) 105 expected := protocol.MakeMultiBulkReply(utils.ToCmdLine(values...)) 106 if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) { 107 t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(actual.ToBytes()))) 108 } 109 } 110 111 func TestHGetAll(t *testing.T) { 112 testDB.Flush() 113 size := 100 114 key := utils.RandString(10) 115 fields := make([]string, size) 116 valueSet := make(map[string]bool, size) 117 valueMap := make(map[string]string) 118 all := make([]string, 0) 119 for i := 0; i < size; i++ { 120 fields[i] = utils.RandString(10) 121 value := utils.RandString(10) 122 all = append(all, fields[i], value) 123 valueMap[fields[i]] = value 124 valueSet[value] = true 125 execHSet(testDB, utils.ToCmdLine(key, fields[i], value)) 126 } 127 128 // test HGetAll 129 result := testDB.Exec(nil, utils.ToCmdLine("hgetall", key)) 130 multiBulk, ok := result.(*protocol.MultiBulkReply) 131 if !ok { 132 t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes()))) 133 } 134 if 2*len(fields) != len(multiBulk.Args) { 135 t.Error(fmt.Sprintf("expected %d items , actually %d ", 2*len(fields), len(multiBulk.Args))) 136 } 137 for i := range fields { 138 field := string(multiBulk.Args[2*i]) 139 actual := string(multiBulk.Args[2*i+1]) 140 expected, ok := valueMap[field] 141 if !ok { 142 t.Error(fmt.Sprintf("unexpected field %s", field)) 143 continue 144 } 145 if actual != expected { 146 t.Error(fmt.Sprintf("expected %s, actually %s", expected, actual)) 147 } 148 } 149 150 // test HKeys 151 result = testDB.Exec(nil, utils.ToCmdLine("hkeys", key)) 152 multiBulk, ok = result.(*protocol.MultiBulkReply) 153 if !ok { 154 t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes()))) 155 } 156 if len(fields) != len(multiBulk.Args) { 157 t.Error(fmt.Sprintf("expected %d items , actually %d ", len(fields), len(multiBulk.Args))) 158 } 159 for _, v := range multiBulk.Args { 160 field := string(v) 161 if _, ok := valueMap[field]; !ok { 162 t.Error(fmt.Sprintf("unexpected field %s", field)) 163 } 164 } 165 166 // test HVals 167 result = testDB.Exec(nil, utils.ToCmdLine("hvals", key)) 168 multiBulk, ok = result.(*protocol.MultiBulkReply) 169 if !ok { 170 t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes()))) 171 } 172 if len(fields) != len(multiBulk.Args) { 173 t.Error(fmt.Sprintf("expected %d items , actually %d ", len(fields), len(multiBulk.Args))) 174 } 175 for _, v := range multiBulk.Args { 176 value := string(v) 177 _, ok := valueSet[value] 178 if !ok { 179 t.Error(fmt.Sprintf("unexpected value %s", value)) 180 } 181 } 182 183 // test HRandField 184 // test HRandField count of 0 is handled correctly -- "emptyarray" 185 result = testDB.Exec(nil, utils.ToCmdLine("hrandfield", key, "0")) 186 multiBulk, ok = result.(*protocol.MultiBulkReply) 187 if !ok { 188 resultBytes := string(result.ToBytes()) 189 if resultBytes != "*0\r\n" { 190 t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", resultBytes)) 191 } 192 } 193 194 // test HRandField count > size 195 result = testDB.Exec(nil, utils.ToCmdLine("hrandfield", key, strconv.Itoa(size+100))) 196 multiBulk, ok = result.(*protocol.MultiBulkReply) 197 if !ok { 198 t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes()))) 199 } 200 if len(fields) != len(multiBulk.Args) { 201 t.Error(fmt.Sprintf("expected %d items , actually %d ", len(fields), len(multiBulk.Args))) 202 } 203 204 // test HRandField count > size withvalues 205 result = testDB.Exec(nil, utils.ToCmdLine("hrandfield", key, strconv.Itoa(size+100), "withvalues")) 206 multiBulk, ok = result.(*protocol.MultiBulkReply) 207 if !ok { 208 t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes()))) 209 } 210 if 2*len(fields) != len(multiBulk.Args) { 211 t.Error(fmt.Sprintf("expected %d items , actually %d ", 2*len(fields), len(multiBulk.Args))) 212 } 213 214 // test HRandField count < size 215 result = testDB.Exec(nil, utils.ToCmdLine("hrandfield", key, strconv.Itoa(-size-10))) 216 multiBulk, ok = result.(*protocol.MultiBulkReply) 217 if !ok { 218 t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes()))) 219 } 220 if len(fields)+10 != len(multiBulk.Args) { 221 t.Error(fmt.Sprintf("expected %d items , actually %d ", len(fields)+10, len(multiBulk.Args))) 222 } 223 224 // test HRandField count < size withvalues 225 result = testDB.Exec(nil, utils.ToCmdLine("hrandfield", key, strconv.Itoa(-size-10), "withvalues")) 226 multiBulk, ok = result.(*protocol.MultiBulkReply) 227 if !ok { 228 t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes()))) 229 } 230 if 2*(len(fields)+10) != len(multiBulk.Args) { 231 t.Error(fmt.Sprintf("expected %d items , actually %d ", 2*(len(fields)+10), len(multiBulk.Args))) 232 } 233 } 234 235 func TestHIncrBy(t *testing.T) { 236 testDB.Flush() 237 238 key := utils.RandString(10) 239 result := testDB.Exec(nil, utils.ToCmdLine("hincrby", key, "a", "1")) 240 if bulkResult, _ := result.(*protocol.BulkReply); string(bulkResult.Arg) != "1" { 241 t.Error(fmt.Sprintf("expected %s, actually %s", "1", string(bulkResult.Arg))) 242 } 243 result = testDB.Exec(nil, utils.ToCmdLine("hincrby", key, "a", "1")) 244 if bulkResult, _ := result.(*protocol.BulkReply); string(bulkResult.Arg) != "2" { 245 t.Error(fmt.Sprintf("expected %s, actually %s", "2", string(bulkResult.Arg))) 246 } 247 248 result = testDB.Exec(nil, utils.ToCmdLine("hincrbyfloat", key, "b", "1.2")) 249 if bulkResult, _ := result.(*protocol.BulkReply); string(bulkResult.Arg) != "1.2" { 250 t.Error(fmt.Sprintf("expected %s, actually %s", "1.2", string(bulkResult.Arg))) 251 } 252 result = testDB.Exec(nil, utils.ToCmdLine("hincrbyfloat", key, "b", "1.2")) 253 if bulkResult, _ := result.(*protocol.BulkReply); string(bulkResult.Arg) != "2.4" { 254 t.Error(fmt.Sprintf("expected %s, actually %s", "2.4", string(bulkResult.Arg))) 255 } 256 } 257 258 func TestHSetNX(t *testing.T) { 259 testDB.Flush() 260 key := utils.RandString(10) 261 field := utils.RandString(10) 262 value := utils.RandString(10) 263 result := testDB.Exec(nil, utils.ToCmdLine("hsetnx", key, field, value)) 264 asserts.AssertIntReply(t, result, 1) 265 value2 := utils.RandString(10) 266 result = testDB.Exec(nil, utils.ToCmdLine("hsetnx", key, field, value2)) 267 asserts.AssertIntReply(t, result, 0) 268 result = testDB.Exec(nil, utils.ToCmdLine("hget", key, field)) 269 asserts.AssertBulkReply(t, result, value) 270 } 271 272 func TestUndoHDel(t *testing.T) { 273 testDB.Flush() 274 key := utils.RandString(10) 275 field := utils.RandString(10) 276 value := utils.RandString(10) 277 278 testDB.Exec(nil, utils.ToCmdLine("hset", key, field, value)) 279 cmdLine := utils.ToCmdLine("hdel", key, field) 280 undoCmdLines := undoHDel(testDB, cmdLine[1:]) 281 testDB.Exec(nil, cmdLine) 282 for _, cmdLine := range undoCmdLines { 283 testDB.Exec(nil, cmdLine) 284 } 285 result := testDB.Exec(nil, utils.ToCmdLine("hget", key, field)) 286 asserts.AssertBulkReply(t, result, value) 287 } 288 289 func TestUndoHSet(t *testing.T) { 290 testDB.Flush() 291 key := utils.RandString(10) 292 field := utils.RandString(10) 293 value := utils.RandString(10) 294 value2 := utils.RandString(10) 295 296 testDB.Exec(nil, utils.ToCmdLine("hset", key, field, value)) 297 cmdLine := utils.ToCmdLine("hset", key, field, value2) 298 undoCmdLines := undoHSet(testDB, cmdLine[1:]) 299 testDB.Exec(nil, cmdLine) 300 for _, cmdLine := range undoCmdLines { 301 testDB.Exec(nil, cmdLine) 302 } 303 result := testDB.Exec(nil, utils.ToCmdLine("hget", key, field)) 304 asserts.AssertBulkReply(t, result, value) 305 } 306 307 func TestUndoHMSet(t *testing.T) { 308 testDB.Flush() 309 key := utils.RandString(10) 310 field1 := utils.RandString(10) 311 field2 := utils.RandString(10) 312 value := utils.RandString(10) 313 value2 := utils.RandString(10) 314 315 testDB.Exec(nil, utils.ToCmdLine("hmset", key, field1, value, field2, value)) 316 cmdLine := utils.ToCmdLine("hmset", key, field1, value2, field2, value2) 317 undoCmdLines := undoHMSet(testDB, cmdLine[1:]) 318 testDB.Exec(nil, cmdLine) 319 for _, cmdLine := range undoCmdLines { 320 testDB.Exec(nil, cmdLine) 321 } 322 result := testDB.Exec(nil, utils.ToCmdLine("hget", key, field1)) 323 asserts.AssertBulkReply(t, result, value) 324 result = testDB.Exec(nil, utils.ToCmdLine("hget", key, field2)) 325 asserts.AssertBulkReply(t, result, value) 326 } 327 328 func TestUndoHIncr(t *testing.T) { 329 testDB.Flush() 330 key := utils.RandString(10) 331 field := utils.RandString(10) 332 333 testDB.Exec(nil, utils.ToCmdLine("hset", key, field, "1")) 334 cmdLine := utils.ToCmdLine("hinctby", key, field, "2") 335 undoCmdLines := undoHIncr(testDB, cmdLine[1:]) 336 testDB.Exec(nil, cmdLine) 337 for _, cmdLine := range undoCmdLines { 338 testDB.Exec(nil, cmdLine) 339 } 340 result := testDB.Exec(nil, utils.ToCmdLine("hget", key, field)) 341 asserts.AssertBulkReply(t, result, "1") 342 }