Skip to content

Commit

Permalink
Merge branch 'master' into iamskp11/dice-db/issue/486/support-json-ar…
Browse files Browse the repository at this point in the history
…r-index-command
  • Loading branch information
iamskp11 committed Dec 4, 2024
2 parents e24b1a1 + 66a9f33 commit 5a8ea7f
Show file tree
Hide file tree
Showing 28 changed files with 837 additions and 239 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Although DiceDB is a drop-in replacement of Redis, which means almost no learnin
The easiest way to get started with DiceDB is using [Docker](https://www.docker.com/) by running the following command.

```bash
docker run -p 7379:7379 dicedb/dicedb --enable-multithreading --enable-watch
docker run -p 7379:7379 dicedb/dicedb --enable-watch
```

The above command will start the DiceDB server running locally on the port `7379` and you can connect
Expand All @@ -60,10 +60,10 @@ To run DiceDB for local development or running from source, you will need
```bash
git clone https://github.com/dicedb/dice
cd dice
go run main.go --enable-multithreading --enable-watch
go run main.go --enable-watch
```

You can skip passing the two flags if you are not working with multi-threading or `.WATCH` features.
You can skip passing the flag if you are not working with `.WATCH` feature.

1. Install GoLangCI

Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/get-started/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ We are looking for Early Design Partners, so, if you want to evaluate DiceDB, [b
The easiest way to get started with DiceDB is using [Docker](https://www.docker.com/) by running the following command.

```bash
docker run -p 7379:7379 dicedb/dicedb --enable-multithreading --enable-watch
docker run -p 7379:7379 dicedb/dicedb --enable-watch
```

The above command will start the DiceDB server running locally on the port `7379` and you can connect
Expand Down
6 changes: 3 additions & 3 deletions docs/src/content/docs/get-started/reactive-hello-world.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ But, before we start, make sure you have

### Starting DiceDB

Start the DiceDB server with the two flags `--enable-multithreading` and `--enable-watch`
to enable multi-threading and watch mode, respectively. Your command would look something
Start the DiceDB server with the flag `--enable-watch`
to enable watch mode. Your command would look something
like this

```bash
docker run -p 7379:7379 dicedb/dicedb --enable-multithreading --enable-watch
docker run -p 7379:7379 dicedb/dicedb --enable-watch
```

Also, connect to the database using the CLI as mentioned in the above installation steps or
Expand Down
7 changes: 4 additions & 3 deletions integration_tests/commands/http/bloom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package http
import (
"testing"

diceerrors "github.com/dicedb/dice/internal/errors"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -82,7 +83,7 @@ func TestBloomFilter(t *testing.T) {
Body: map[string]interface{}{"key": "bf", "values": []interface{}{0.01, 2000}},
},
},
expected: []interface{}{"OK", "ERR item exists"},
expected: []interface{}{"OK", diceerrors.ErrKeyExists.Error()},
},
}

Expand Down Expand Up @@ -199,7 +200,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) {
Body: map[string]interface{}{"key": "bf"},
},
},
expected: []interface{}{"ERR not found"},
expected: []interface{}{diceerrors.ErrKeyNotFound.Error()},
},
{
name: "BF.RESERVE with a very high error rate",
Expand Down Expand Up @@ -281,7 +282,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) {
Body: map[string]interface{}{"key": "bf", "values": []interface{}{0.01, 2000}},
},
},
expected: []interface{}{"OK", "ERR item exists"},
expected: []interface{}{"OK", diceerrors.ErrKeyExists.Error()},
},
{
name: "BF.INFO after multiple additions",
Expand Down
2 changes: 1 addition & 1 deletion integration_tests/commands/http/jsondebug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestJSONDEBUG(t *testing.T) {
{Command: "JSON.SET", Body: map[string]interface{}{"key": "k1", "path": "$", "json": map[string]interface{}{"a": 1}}},
{Command: "JSON.DEBUG", Body: map[string]interface{}{"values": []interface{}{"MEMORY", "k1"}}},
},
expected: []interface{}{"OK", float64(89)},
expected: []interface{}{"OK", float64(72)},
},
{
name: "jsondebug with a valid path",
Expand Down
7 changes: 4 additions & 3 deletions integration_tests/commands/resp/bloom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"
"time"

diceerrors "github.com/dicedb/dice/internal/errors"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -42,7 +43,7 @@ func TestBFReserveAddInfoExists(t *testing.T) {
{
name: "BF.RESERVE on existent filter returns error",
cmds: []string{"BF.RESERVE bf 0.01 1000", "BF.RESERVE bf 0.01 1000"},
expect: []interface{}{"OK", "ERR item exists"},
expect: []interface{}{"OK", diceerrors.ErrKeyExists.Error()},
delays: []time.Duration{0, 0},
cleanUp: []string{"DEL bf"},
},
Expand Down Expand Up @@ -135,7 +136,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) {
{
name: "BF.INFO on a non-existent filter",
cmds: []string{"BF.INFO bf"},
expect: []interface{}{"ERR not found"},
expect: []interface{}{diceerrors.ErrKeyNotFound.Error()},
delays: []time.Duration{0},
cleanUp: []string{"del bf"},
},
Expand Down Expand Up @@ -170,7 +171,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) {
{
name: "BF.RESERVE with duplicate filter name",
cmds: []string{"BF.RESERVE bf 0.01 1000", "BF.RESERVE bf 0.01 2000"},
expect: []interface{}{"OK", "ERR item exists"},
expect: []interface{}{"OK", diceerrors.ErrKeyExists.Error()},
delays: []time.Duration{0, 0},
cleanUp: []string{"del bf"},
},
Expand Down
192 changes: 148 additions & 44 deletions integration_tests/commands/resp/dump_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package resp

import (
"encoding/base64"
"testing"

"github.com/dicedb/dice/testutils"
Expand All @@ -11,7 +10,7 @@ import (
func TestDumpRestore(t *testing.T) {
conn := getLocalConnection()
defer conn.Close()

simpleJSON := `{"name":"John","age":30}`
testCases := []struct {
name string
commands []string
Expand All @@ -20,57 +19,31 @@ func TestDumpRestore(t *testing.T) {
{
name: "DUMP and RESTORE string value",
commands: []string{
"SET mykey hello",
"DUMP mykey",
"DEL mykey",
"RESTORE mykey 2 CQAAAAAFaGVsbG//AEeXk742Rcc=",
"GET mykey",
"SET foo bar",
"DUMP foo",
"DEL foo",
"RESTORE foo 2 CQAAAAADYmFy/72GUVF+ClKv",
"GET foo",
},
expected: []interface{}{
"OK",
func(result interface{}) bool {
dumped, ok := result.(string)
if !ok {
return false
}
decoded, err := base64.StdEncoding.DecodeString(dumped)
if err != nil {
return false
}
return len(decoded) > 11 &&
decoded[0] == 0x09 &&
decoded[1] == 0x00 &&
string(decoded[6:11]) == "hello" &&
decoded[11] == 0xFF
},
"CQAAAAADYmFy/72GUVF+ClKv",
int64(1),
"OK",
"hello",
"bar",
},
},
{
name: "DUMP and RESTORE integer value",
commands: []string{
"SET intkey 42",
"DUMP intkey",
"DEL intkey",
"RESTORE intkey 2 CcAAAAAAAAAAKv9S/ymRDY3rXg==",
"set foo 12345",
"DUMP foo",
"DEL foo",
"RESTORE foo 2 CQUAAAAAAAAwOf8OqbusYAl2pQ==",
},
expected: []interface{}{
"OK",
func(result interface{}) bool {
dumped, ok := result.(string)
if !ok {
return false
}
decoded, err := base64.StdEncoding.DecodeString(dumped)
if err != nil {
return false
}
return len(decoded) > 2 &&
decoded[0] == 0x09 &&
decoded[1] == 0xC0
},
"CQUAAAAAAAAwOf8OqbusYAl2pQ==",
int64(1),
"OK",
},
Expand All @@ -84,26 +57,157 @@ func TestDumpRestore(t *testing.T) {
"(nil)",
},
},
{
name: "DUMP JSON",
commands: []string{
`JSON.SET foo $ ` + simpleJSON,
"DUMP foo",
"del foo",
"restore foo 2 CQMAAAAYeyJhZ2UiOjMwLCJuYW1lIjoiSm9obiJ9/6PVaIgw0n+C",
"JSON.GET foo $..name",
},
expected: []interface{}{
"OK",
"skip",
int64(1),
"OK",
`"John"`,
},
},
{
name: "DUMP Set",
commands: []string{
"sadd foo bar baz bazz",
"dump foo",
"del foo",
"restore foo 2 CQYAAAAAAAAAAwAAAANiYXIAAAADYmF6AAAABGJhenr/DSf4vHxjdYo=",
"smembers foo",
},
expected: []interface{}{
int64(3),
"skip",
int64(1),
"OK",
[]interface{}{"bar", "baz", "bazz"},
},
},
{
name: "DUMP bytearray",
commands: []string{
"setbit foo 1 1",
"dump foo",
"del foo",
"restore foo 2 CQQAAAAAAAAAAUD/g00L5pRbaJI=",
"get foo",
},
expected: []interface{}{
int64(0),
"CQQAAAAAAAAAAUD/g00L5pRbaJI=",
int64(1),
"OK",
"@",
},
},
{
name: "DUMP sorted set",
commands: []string{
"zadd foo 1 bar 2 bazz",
"dump foo",
"del foo",
"restore foo 2 CQgAAAAAAAAAAgAAAAAAAAADYmFyP/AAAAAAAAAAAAAAAAAABGJhenpAAAAAAAAAAP/POOElibTuYQ==",
"zrange foo 0 2",
},
expected: []interface{}{
int64(2),
"skip",
int64(1),
"OK",
[]interface{}{"bar", "bazz"},
},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
FireCommand(conn, "FLUSHALL")
FireCommand(conn, "del foo")
for i, cmd := range tc.commands {
result := FireCommand(conn, cmd)
expected := tc.expected[i]

if expected == "skip" {
// when order of elements define the dump value, we test the restore function and skip dump
continue
}
switch exp := expected.(type) {
case string:
assert.Equal(t, exp, result)
case []interface{}:
assert.True(t, testutils.UnorderedEqual(exp, result))
case func(interface{}) bool:
assert.True(t, exp(result), cmd)
default:
assert.Equal(t, expected, result)
}
}
})
}
FireCommand(conn, "FLUSHDB")
}

func TestDumpRestoreBF(t *testing.T) {
conn := getLocalConnection()
defer conn.Close()
res := FireCommand(conn, "bf.add foo bar")
assert.Equal(t, int64(1), res)

dumpValue := FireCommand(conn, "dump foo")
FireCommand(conn, "del foo")

res = FireCommand(conn, "restore foo 0 "+dumpValue.(string))
assert.Equal(t, "OK", res)
res = FireCommand(conn, "bf.exists foo bazz")
assert.Equal(t, int64(0), res)

FireCommand(conn, "FLUSHDB")
}

func TestDumpRestoreCMS(t *testing.T) {
conn := getLocalConnection()
defer conn.Close()

// Add a value to the CMS
FireCommand(conn, "CMS.INITBYPROB foo 0.1 0.01")
res := FireCommand(conn, "cms.incrby foo bar 42")
assert.Equal(t, []interface{}([]interface{}{int64(42)}), res)

// Dump the serialized value
dumpValue := FireCommand(conn, "dump foo")
FireCommand(conn, "del foo") // Delete the CMS

// Restore the CMS from the dumped value
res = FireCommand(conn, "restore foo 0 "+dumpValue.(string))
assert.Equal(t, "OK", res)

// Check the value for a key in the restored CMS
res = FireCommand(conn, "cms.query foo bar")
assert.Equal(t, []interface{}([]interface{}{int64(42)}), res)

// Check that another key not in the CMS returns 0
res = FireCommand(conn, "cms.query foo bar")
assert.Equal(t, []interface{}([]interface{}{int64(42)}), res)

FireCommand(conn, "FLUSHDB")
}

func TestDumpRestoreDeque(t *testing.T) {
conn := getLocalConnection()
defer conn.Close()
res := FireCommand(conn, "lpush foo bar")
assert.Equal(t, int64(1), res)
dumpValue := FireCommand(conn, "dump foo")
res = FireCommand(conn, "del foo")
assert.Equal(t, int64(1), res)
res = FireCommand(conn, "restore foo 0 "+dumpValue.(string))
assert.Equal(t, "OK", res)
res = FireCommand(conn, "lpop foo")
assert.Equal(t, "bar", res)

FireCommand(conn, "FLUSHDB")
}
2 changes: 1 addition & 1 deletion integration_tests/commands/resp/jsondebug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestJSONDEBUG(t *testing.T) {
`JSON.SET k1 $ {"a":1}`,
"JSON.DEBUG MEMORY k1",
},
expected: []interface{}{"OK", int64(89)},
expected: []interface{}{"OK", int64(72)},
},
{
name: "jsondebug with a valid path",
Expand Down
Loading

0 comments on commit 5a8ea7f

Please sign in to comment.