mirror of
https://github.com/EchoVault/SugarDB.git
synced 2026-04-22 23:47:09 +08:00
Refactor tests (#171)
- Refactored tests to improve execution time - @kelvinmwinuka
This commit is contained in:
@@ -14,12 +14,18 @@ build-modules-test:
|
||||
test:
|
||||
env RACE=false OUT=internal/modules/admin/testdata make build-modules-test && \
|
||||
env RACE=false OUT=sugardb/testdata make build-modules-test && \
|
||||
CGO_ENABLED=1 go test ./... -coverprofile coverage/coverage.out
|
||||
CGO_ENABLED=1 go test ./... -coverprofile coverage/coverage.out && \
|
||||
rm -rf ./internal/modules/admin/testdata && \
|
||||
rm -rf ./sugardb/testdata && \
|
||||
rm -rf ./sugardb/aof
|
||||
|
||||
test-race:
|
||||
env RACE=true OUT=internal/modules/admin/testdata make build-modules-test && \
|
||||
env RACE=true OUT=sugardb/testdata make build-modules-test && \
|
||||
CGO_ENABLED=1 go test ./... --race
|
||||
CGO_ENABLED=1 go test ./... --race && \
|
||||
rm -rf ./internal/modules/admin/testdata && \
|
||||
rm -rf ./sugardb/testdata && \
|
||||
rm -rf ./sugardb/aof
|
||||
|
||||
testenv-run:
|
||||
docker-compose -f test_env/run/docker-compose.yaml build
|
||||
|
||||
+1752
-1740
File diff suppressed because it is too large
Load Diff
+539
-516
File diff suppressed because it is too large
Load Diff
+658
-605
File diff suppressed because it is too large
Load Diff
+245
-234
@@ -25,261 +25,272 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSugarDB_Hello(t *testing.T) {
|
||||
t.Parallel()
|
||||
func TestSugarDB_Connection(t *testing.T) {
|
||||
t.Run("TestSugarDB_Hello", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
port, err := internal.GetFreePort()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
port, err := internal.GetFreePort()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
conf := DefaultConfig()
|
||||
conf.Port = uint16(port)
|
||||
conf.RequirePass = false
|
||||
conf := DefaultConfig()
|
||||
conf.Port = uint16(port)
|
||||
conf.RequirePass = false
|
||||
|
||||
mockServer := createSugarDBWithConfig(conf)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
mockServer.Start()
|
||||
}()
|
||||
t.Cleanup(func() {
|
||||
mockServer.ShutDown()
|
||||
mockServer := createSugarDBWithConfig(conf)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
mockServer.Start()
|
||||
}()
|
||||
t.Cleanup(func() {
|
||||
mockServer.ShutDown()
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
command []resp.Value
|
||||
wantRes []byte
|
||||
}{
|
||||
{
|
||||
name: "1. Hello",
|
||||
command: []resp.Value{resp.StringValue("HELLO")},
|
||||
wantRes: connection.BuildHelloResponse(
|
||||
internal.ServerInfo{
|
||||
Server: "sugardb",
|
||||
Version: constants.Version,
|
||||
Id: "",
|
||||
Mode: "standalone",
|
||||
Role: "master",
|
||||
Modules: mockServer.ListModules(),
|
||||
},
|
||||
internal.ConnectionInfo{
|
||||
Id: 1,
|
||||
Name: "",
|
||||
Protocol: 2,
|
||||
Database: 0,
|
||||
},
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "2. Hello 2",
|
||||
command: []resp.Value{resp.StringValue("HELLO"), resp.StringValue("2")},
|
||||
wantRes: connection.BuildHelloResponse(
|
||||
internal.ServerInfo{
|
||||
Server: "sugardb",
|
||||
Version: constants.Version,
|
||||
Id: "",
|
||||
Mode: "standalone",
|
||||
Role: "master",
|
||||
Modules: mockServer.ListModules(),
|
||||
},
|
||||
internal.ConnectionInfo{
|
||||
Id: 2,
|
||||
Name: "",
|
||||
Protocol: 2,
|
||||
Database: 0,
|
||||
},
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "3. Hello 3",
|
||||
command: []resp.Value{resp.StringValue("HELLO"), resp.StringValue("3")},
|
||||
wantRes: connection.BuildHelloResponse(
|
||||
internal.ServerInfo{
|
||||
Server: "sugardb",
|
||||
Version: constants.Version,
|
||||
Id: "",
|
||||
Mode: "standalone",
|
||||
Role: "master",
|
||||
Modules: mockServer.ListModules(),
|
||||
},
|
||||
internal.ConnectionInfo{
|
||||
Id: 3,
|
||||
Name: "",
|
||||
Protocol: 3,
|
||||
Database: 0,
|
||||
},
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
for i := 0; i < len(tests); i++ {
|
||||
conn, err := internal.GetConnection("localhost", port)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
client := resp.NewConn(conn)
|
||||
|
||||
if err = client.WriteArray(tests[i].command); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
buf := bufio.NewReader(conn)
|
||||
res, err := internal.ReadMessage(buf)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !bytes.Equal(tests[i].wantRes, res) {
|
||||
t.Errorf("expected byte resposne:\n%s, \n\ngot:\n%s", string(tests[i].wantRes), string(res))
|
||||
return
|
||||
}
|
||||
|
||||
// Close connection
|
||||
_ = conn.Close()
|
||||
}
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
command []resp.Value
|
||||
wantRes []byte
|
||||
}{
|
||||
{
|
||||
name: "1. Hello",
|
||||
command: []resp.Value{resp.StringValue("HELLO")},
|
||||
wantRes: connection.BuildHelloResponse(
|
||||
internal.ServerInfo{
|
||||
Server: "sugardb",
|
||||
Version: constants.Version,
|
||||
Id: "",
|
||||
Mode: "standalone",
|
||||
Role: "master",
|
||||
Modules: mockServer.ListModules(),
|
||||
t.Run("TestSugarDB_SelectDB", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
presetValues map[int]map[string]string
|
||||
database int
|
||||
want map[int][]string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "1. Change database and read new values",
|
||||
presetValues: map[int]map[string]string{
|
||||
0: {"key1": "value-01", "key2": "value-02", "key3": "value-03"},
|
||||
1: {"key1": "value-11", "key2": "value-12", "key3": "value-13"},
|
||||
},
|
||||
internal.ConnectionInfo{
|
||||
Id: 1,
|
||||
Name: "",
|
||||
Protocol: 2,
|
||||
Database: 0,
|
||||
database: 1,
|
||||
want: map[int][]string{
|
||||
0: {"value-01", "value-02", "value-03"},
|
||||
1: {"value-11", "value-12", "value-13"},
|
||||
},
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "2. Hello 2",
|
||||
command: []resp.Value{resp.StringValue("HELLO"), resp.StringValue("2")},
|
||||
wantRes: connection.BuildHelloResponse(
|
||||
internal.ServerInfo{
|
||||
Server: "sugardb",
|
||||
Version: constants.Version,
|
||||
Id: "",
|
||||
Mode: "standalone",
|
||||
Role: "master",
|
||||
Modules: mockServer.ListModules(),
|
||||
},
|
||||
internal.ConnectionInfo{
|
||||
Id: 2,
|
||||
Name: "",
|
||||
Protocol: 2,
|
||||
Database: 0,
|
||||
},
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "3. Hello 3",
|
||||
command: []resp.Value{resp.StringValue("HELLO"), resp.StringValue("3")},
|
||||
wantRes: connection.BuildHelloResponse(
|
||||
internal.ServerInfo{
|
||||
Server: "sugardb",
|
||||
Version: constants.Version,
|
||||
Id: "",
|
||||
Mode: "standalone",
|
||||
Role: "master",
|
||||
Modules: mockServer.ListModules(),
|
||||
},
|
||||
internal.ConnectionInfo{
|
||||
Id: 3,
|
||||
Name: "",
|
||||
Protocol: 3,
|
||||
Database: 0,
|
||||
},
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
for i := 0; i < len(tests); i++ {
|
||||
conn, err := internal.GetConnection("localhost", port)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
client := resp.NewConn(conn)
|
||||
|
||||
if err = client.WriteArray(tests[i].command); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
buf := bufio.NewReader(conn)
|
||||
res, err := internal.ReadMessage(buf)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !bytes.Equal(tests[i].wantRes, res) {
|
||||
t.Errorf("expected byte resposne:\n%s, \n\ngot:\n%s", string(tests[i].wantRes), string(res))
|
||||
return
|
||||
}
|
||||
|
||||
// Close connection
|
||||
_ = conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestSugarDB_SelectDB(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
presetValues map[int]map[string]string
|
||||
database int
|
||||
want map[int][]string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "1. Change database and read new values",
|
||||
presetValues: map[int]map[string]string{
|
||||
0: {"key1": "value-01", "key2": "value-02", "key3": "value-03"},
|
||||
1: {"key1": "value-11", "key2": "value-12", "key3": "value-13"},
|
||||
wantErr: false,
|
||||
},
|
||||
database: 1,
|
||||
want: map[int][]string{
|
||||
0: {"value-01", "value-02", "value-03"},
|
||||
1: {"value-11", "value-12", "value-13"},
|
||||
{
|
||||
name: "2. Error when database parameter is < 0",
|
||||
presetValues: map[int]map[string]string{
|
||||
0: {"key1": "value-01", "key2": "value-02", "key3": "value-03"},
|
||||
},
|
||||
database: -1,
|
||||
want: map[int][]string{
|
||||
0: {"value-01", "value-02", "value-03"},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "2. Error when database parameter is < 0",
|
||||
presetValues: map[int]map[string]string{
|
||||
0: {"key1": "value-01", "key2": "value-02", "key3": "value-03"},
|
||||
},
|
||||
database: -1,
|
||||
want: map[int][]string{
|
||||
0: {"value-01", "value-02", "value-03"},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := createSugarDB()
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if tt.presetValues != nil {
|
||||
for db, data := range tt.presetValues {
|
||||
_ = server.SelectDB(db)
|
||||
if _, err := server.MSet(data); err != nil {
|
||||
t.Errorf("SelectDB() error = %v", err)
|
||||
server := createSugarDB()
|
||||
t.Cleanup(func() {
|
||||
server.ShutDown()
|
||||
})
|
||||
|
||||
if tt.presetValues != nil {
|
||||
for db, data := range tt.presetValues {
|
||||
_ = server.SelectDB(db)
|
||||
if _, err := server.MSet(data); err != nil {
|
||||
t.Errorf("SelectDB() error = %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
_ = server.SelectDB(0)
|
||||
}
|
||||
|
||||
// Check the values for DB 0
|
||||
values, err := server.MGet("key1", "key2", "key3")
|
||||
if err != nil {
|
||||
t.Errorf("SelectDB() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(values, tt.want[0]) {
|
||||
t.Errorf("SelectDB() result-0 = %v, want-0 %v", values, tt.want[0])
|
||||
return
|
||||
}
|
||||
|
||||
err = server.SelectDB(tt.database)
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
t.Errorf("SelectDB() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
_ = server.SelectDB(0)
|
||||
}
|
||||
|
||||
// Check the values for DB 0
|
||||
values, err := server.MGet("key1", "key2", "key3")
|
||||
if err != nil {
|
||||
t.Errorf("SelectDB() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(values, tt.want[0]) {
|
||||
t.Errorf("SelectDB() result-0 = %v, want-0 %v", values, tt.want[0])
|
||||
return
|
||||
}
|
||||
|
||||
err = server.SelectDB(tt.database)
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
if err != nil {
|
||||
t.Errorf("SelectDB() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("SelectDB() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
// Check the values the new DB
|
||||
values, err = server.MGet("key1", "key2", "key3")
|
||||
if err != nil {
|
||||
t.Errorf("SelectDB() error = %v", err)
|
||||
return
|
||||
}
|
||||
// Check the values the new DB
|
||||
values, err = server.MGet("key1", "key2", "key3")
|
||||
if err != nil {
|
||||
t.Errorf("SelectDB() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(values, tt.want[1]) {
|
||||
t.Errorf("SelectDB() result-1 = %v, want-1 %v", values, tt.want[1])
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(values, tt.want[1]) {
|
||||
t.Errorf("SelectDB() result-1 = %v, want-1 %v", values, tt.want[1])
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("TestSugarDB_SetProtocol", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
server := createSugarDB()
|
||||
t.Cleanup(func() {
|
||||
server.ShutDown()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSugarDB_SetProtocol(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := createSugarDB()
|
||||
tests := []struct {
|
||||
name string
|
||||
protocol int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "1. Change protocol to 2",
|
||||
protocol: 2,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "2. Change protocol to 3",
|
||||
protocol: 3,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "3. Return error when protocol is neither 2 or 3",
|
||||
protocol: 4,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := server.SetProtocol(tt.protocol)
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
tests := []struct {
|
||||
name string
|
||||
protocol int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "1. Change protocol to 2",
|
||||
protocol: 2,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "2. Change protocol to 3",
|
||||
protocol: 3,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "3. Return error when protocol is neither 2 or 3",
|
||||
protocol: 4,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := server.SetProtocol(tt.protocol)
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
t.Errorf("SetProtocol() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("SetProtocol() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("SetProtocol() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
// Check if the protocol has been changed
|
||||
if server.connInfo.embedded.Protocol != tt.protocol {
|
||||
t.Errorf("SetProtocol() protocol = %v, wantProtocol %v",
|
||||
server.connInfo.embedded.Protocol, tt.protocol)
|
||||
}
|
||||
})
|
||||
}
|
||||
// Check if the protocol has been changed
|
||||
if server.connInfo.embedded.Protocol != tt.protocol {
|
||||
t.Errorf("SetProtocol() protocol = %v, wantProtocol %v",
|
||||
server.connInfo.embedded.Protocol, tt.protocol)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+2073
-2022
File diff suppressed because it is too large
Load Diff
+1064
-1040
File diff suppressed because it is too large
Load Diff
+908
-891
File diff suppressed because it is too large
Load Diff
+1107
-1099
File diff suppressed because it is too large
Load Diff
+3362
-3359
File diff suppressed because it is too large
Load Diff
+342
-332
@@ -19,349 +19,359 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSugarDB_SUBSTR(t *testing.T) {
|
||||
func TestSugarDB_String(t *testing.T) {
|
||||
server := createSugarDB()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
presetValue interface{}
|
||||
substrFunc func(key string, start int, end int) (string, error)
|
||||
key string
|
||||
start int
|
||||
end int
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Return substring within the range of the string",
|
||||
key: "key1",
|
||||
substrFunc: server.SubStr,
|
||||
presetValue: "Test String One",
|
||||
start: 5,
|
||||
end: 10,
|
||||
want: "String",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Return substring at the end of the string with exact end index",
|
||||
key: "key2",
|
||||
substrFunc: server.SubStr,
|
||||
presetValue: "Test String Two",
|
||||
start: 12,
|
||||
end: 14,
|
||||
want: "Two",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Return substring at the end of the string with end index greater than length",
|
||||
key: "key3",
|
||||
substrFunc: server.SubStr,
|
||||
presetValue: "Test String Three",
|
||||
start: 12,
|
||||
end: 75,
|
||||
want: "Three",
|
||||
},
|
||||
{
|
||||
name: "Return the substring at the start of the string with 0 start index",
|
||||
key: "key4",
|
||||
substrFunc: server.SubStr,
|
||||
presetValue: "Test String Four",
|
||||
start: 0,
|
||||
end: 3,
|
||||
want: "Test",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Return the substring with negative start index.
|
||||
// Substring should begin abs(start) from the end of the string when start is negative.
|
||||
name: "Return the substring with negative start index",
|
||||
key: "key5",
|
||||
substrFunc: server.SubStr,
|
||||
presetValue: "Test String Five",
|
||||
start: -11,
|
||||
end: 10,
|
||||
want: "String",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Return reverse substring with end index smaller than start index.
|
||||
// When end index is smaller than start index, the 2 indices are reversed.
|
||||
name: "Return reverse substring with end index smaller than start index",
|
||||
key: "key6",
|
||||
substrFunc: server.SubStr,
|
||||
presetValue: "Test String Six",
|
||||
start: 4,
|
||||
end: 0,
|
||||
want: "tseT",
|
||||
},
|
||||
{
|
||||
name: "Return substring within the range of the string",
|
||||
key: "key7",
|
||||
substrFunc: server.GetRange,
|
||||
presetValue: "Test String One",
|
||||
start: 5,
|
||||
end: 10,
|
||||
want: "String",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Return substring at the end of the string with exact end index",
|
||||
key: "key8",
|
||||
substrFunc: server.GetRange,
|
||||
presetValue: "Test String Two",
|
||||
start: 12,
|
||||
end: 14,
|
||||
want: "Two",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Return substring at the end of the string with end index greater than length",
|
||||
key: "key9",
|
||||
substrFunc: server.GetRange,
|
||||
presetValue: "Test String Three",
|
||||
start: 12,
|
||||
end: 75,
|
||||
want: "Three",
|
||||
},
|
||||
{
|
||||
name: "Return the substring at the start of the string with 0 start index",
|
||||
key: "key10",
|
||||
substrFunc: server.GetRange,
|
||||
presetValue: "Test String Four",
|
||||
start: 0,
|
||||
end: 3,
|
||||
want: "Test",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Return the substring with negative start index.
|
||||
// Substring should begin abs(start) from the end of the string when start is negative.
|
||||
name: "Return the substring with negative start index",
|
||||
key: "key11",
|
||||
substrFunc: server.GetRange,
|
||||
presetValue: "Test String Five",
|
||||
start: -11,
|
||||
end: 10,
|
||||
want: "String",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Return reverse substring with end index smaller than start index.
|
||||
// When end index is smaller than start index, the 2 indices are reversed.
|
||||
name: "Return reverse substring with end index smaller than start index",
|
||||
key: "key12",
|
||||
substrFunc: server.GetRange,
|
||||
presetValue: "Test String Six",
|
||||
start: 4,
|
||||
end: 0,
|
||||
want: "tseT",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.presetValue != nil {
|
||||
err := presetValue(server, context.Background(), tt.key, tt.presetValue)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Cleanup(func() {
|
||||
server.ShutDown()
|
||||
})
|
||||
|
||||
t.Run("TestSugarDB_SUBSTR", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
presetValue interface{}
|
||||
substrFunc func(key string, start int, end int) (string, error)
|
||||
key string
|
||||
start int
|
||||
end int
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Return substring within the range of the string",
|
||||
key: "substr_key1",
|
||||
substrFunc: server.SubStr,
|
||||
presetValue: "Test String One",
|
||||
start: 5,
|
||||
end: 10,
|
||||
want: "String",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Return substring at the end of the string with exact end index",
|
||||
key: "substr_key2",
|
||||
substrFunc: server.SubStr,
|
||||
presetValue: "Test String Two",
|
||||
start: 12,
|
||||
end: 14,
|
||||
want: "Two",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Return substring at the end of the string with end index greater than length",
|
||||
key: "substr_key3",
|
||||
substrFunc: server.SubStr,
|
||||
presetValue: "Test String Three",
|
||||
start: 12,
|
||||
end: 75,
|
||||
want: "Three",
|
||||
},
|
||||
{
|
||||
name: "Return the substring at the start of the string with 0 start index",
|
||||
key: "substr_key4",
|
||||
substrFunc: server.SubStr,
|
||||
presetValue: "Test String Four",
|
||||
start: 0,
|
||||
end: 3,
|
||||
want: "Test",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Return the substring with negative start index.
|
||||
// Substring should begin abs(start) from the end of the string when start is negative.
|
||||
name: "Return the substring with negative start index",
|
||||
key: "substr_key5",
|
||||
substrFunc: server.SubStr,
|
||||
presetValue: "Test String Five",
|
||||
start: -11,
|
||||
end: 10,
|
||||
want: "String",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Return reverse substring with end index smaller than start index.
|
||||
// When end index is smaller than start index, the 2 indices are reversed.
|
||||
name: "Return reverse substring with end index smaller than start index",
|
||||
key: "substr_key6",
|
||||
substrFunc: server.SubStr,
|
||||
presetValue: "Test String Six",
|
||||
start: 4,
|
||||
end: 0,
|
||||
want: "tseT",
|
||||
},
|
||||
{
|
||||
name: "Return substring within the range of the string",
|
||||
key: "substr_key7",
|
||||
substrFunc: server.GetRange,
|
||||
presetValue: "Test String One",
|
||||
start: 5,
|
||||
end: 10,
|
||||
want: "String",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Return substring at the end of the string with exact end index",
|
||||
key: "substr_key8",
|
||||
substrFunc: server.GetRange,
|
||||
presetValue: "Test String Two",
|
||||
start: 12,
|
||||
end: 14,
|
||||
want: "Two",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Return substring at the end of the string with end index greater than length",
|
||||
key: "substr_key9",
|
||||
substrFunc: server.GetRange,
|
||||
presetValue: "Test String Three",
|
||||
start: 12,
|
||||
end: 75,
|
||||
want: "Three",
|
||||
},
|
||||
{
|
||||
name: "Return the substring at the start of the string with 0 start index",
|
||||
key: "substr_key10",
|
||||
substrFunc: server.GetRange,
|
||||
presetValue: "Test String Four",
|
||||
start: 0,
|
||||
end: 3,
|
||||
want: "Test",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Return the substring with negative start index.
|
||||
// Substring should begin abs(start) from the end of the string when start is negative.
|
||||
name: "Return the substring with negative start index",
|
||||
key: "substr_key11",
|
||||
substrFunc: server.GetRange,
|
||||
presetValue: "Test String Five",
|
||||
start: -11,
|
||||
end: 10,
|
||||
want: "String",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Return reverse substring with end index smaller than start index.
|
||||
// When end index is smaller than start index, the 2 indices are reversed.
|
||||
name: "Return reverse substring with end index smaller than start index",
|
||||
key: "substr_key12",
|
||||
substrFunc: server.GetRange,
|
||||
presetValue: "Test String Six",
|
||||
start: 4,
|
||||
end: 0,
|
||||
want: "tseT",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if tt.presetValue != nil {
|
||||
err := presetValue(server, context.Background(), tt.key, tt.presetValue)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
got, err := tt.substrFunc(tt.key, tt.start, tt.end)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GETRANGE() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
}
|
||||
got, err := tt.substrFunc(tt.key, tt.start, tt.end)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GETRANGE() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("GETRANGE() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("GETRANGE() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
func TestSugarDB_SETRANGE(t *testing.T) {
|
||||
server := createSugarDB()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
presetValue interface{}
|
||||
key string
|
||||
offset int
|
||||
new string
|
||||
want int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test that SETRANGE on non-existent string creates new string",
|
||||
key: "key1",
|
||||
presetValue: "",
|
||||
offset: 10,
|
||||
new: "New String Value",
|
||||
want: len("New String Value"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test SETRANGE with an offset that leads to a longer resulting string",
|
||||
key: "key2",
|
||||
presetValue: "Original String Value",
|
||||
offset: 16,
|
||||
new: "Portion Replaced With This New String",
|
||||
want: len("Original String Portion Replaced With This New String"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "SETRANGE with negative offset prepends the string",
|
||||
key: "key3",
|
||||
presetValue: "This is a preset value",
|
||||
offset: -10,
|
||||
new: "Prepended ",
|
||||
want: len("Prepended This is a preset value"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "SETRANGE with offset that embeds new string inside the old string",
|
||||
key: "key4",
|
||||
presetValue: "This is a preset value",
|
||||
offset: 0,
|
||||
new: "That",
|
||||
want: len("That is a preset value"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "SETRANGE with offset longer than original lengths appends the string",
|
||||
key: "key5",
|
||||
presetValue: "This is a preset value",
|
||||
offset: 100,
|
||||
new: " Appended",
|
||||
want: len("This is a preset value Appended"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "SETRANGE with offset on the last character replaces last character with new string",
|
||||
key: "key6",
|
||||
presetValue: "This is a preset value",
|
||||
offset: len("This is a preset value") - 1,
|
||||
new: " replaced",
|
||||
want: len("This is a preset valu replaced"),
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.presetValue != nil {
|
||||
err := presetValue(server, context.Background(), tt.key, tt.presetValue)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Run("TestSugarDB_SETRANGE", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
presetValue interface{}
|
||||
key string
|
||||
offset int
|
||||
new string
|
||||
want int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test that SETRANGE on non-existent string creates new string",
|
||||
key: "setrange_key1",
|
||||
presetValue: "",
|
||||
offset: 10,
|
||||
new: "New String Value",
|
||||
want: len("New String Value"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test SETRANGE with an offset that leads to a longer resulting string",
|
||||
key: "setrange_key2",
|
||||
presetValue: "Original String Value",
|
||||
offset: 16,
|
||||
new: "Portion Replaced With This New String",
|
||||
want: len("Original String Portion Replaced With This New String"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "SETRANGE with negative offset prepends the string",
|
||||
key: "setrange_key3",
|
||||
presetValue: "This is a preset value",
|
||||
offset: -10,
|
||||
new: "Prepended ",
|
||||
want: len("Prepended This is a preset value"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "SETRANGE with offset that embeds new string inside the old string",
|
||||
key: "setrange_key4",
|
||||
presetValue: "This is a preset value",
|
||||
offset: 0,
|
||||
new: "That",
|
||||
want: len("That is a preset value"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "SETRANGE with offset longer than original lengths appends the string",
|
||||
key: "setrange_key5",
|
||||
presetValue: "This is a preset value",
|
||||
offset: 100,
|
||||
new: " Appended",
|
||||
want: len("This is a preset value Appended"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "SETRANGE with offset on the last character replaces last character with new string",
|
||||
key: "setrange_key6",
|
||||
presetValue: "This is a preset value",
|
||||
offset: len("This is a preset value") - 1,
|
||||
new: " replaced",
|
||||
want: len("This is a preset valu replaced"),
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if tt.presetValue != nil {
|
||||
err := presetValue(server, context.Background(), tt.key, tt.presetValue)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
got, err := server.SetRange(tt.key, tt.offset, tt.new)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("SETRANGE() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
}
|
||||
got, err := server.SetRange(tt.key, tt.offset, tt.new)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("SETRANGE() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("SETRANGE() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("SETRANGE() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
func TestSugarDB_STRLEN(t *testing.T) {
|
||||
server := createSugarDB()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
presetValue interface{}
|
||||
key string
|
||||
want int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Return the correct string length for an existing string",
|
||||
key: "key1",
|
||||
presetValue: "Test String",
|
||||
want: len("Test String"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "If the string does not exist, return 0",
|
||||
key: "key2",
|
||||
presetValue: "",
|
||||
want: 0,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.presetValue != nil {
|
||||
err := presetValue(server, context.Background(), tt.key, tt.presetValue)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Run("TestSugarDB_STRLEN", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
presetValue interface{}
|
||||
key string
|
||||
want int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Return the correct string length for an existing string",
|
||||
key: "strlen_key1",
|
||||
presetValue: "Test String",
|
||||
want: len("Test String"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "If the string does not exist, return 0",
|
||||
key: "strlen_key2",
|
||||
presetValue: "",
|
||||
want: 0,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if tt.presetValue != nil {
|
||||
err := presetValue(server, context.Background(), tt.key, tt.presetValue)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
got, err := server.StrLen(tt.key)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("STRLEN() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
}
|
||||
got, err := server.StrLen(tt.key)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("STRLEN() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("STRLEN() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("STRLEN() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
func TestSugarDB_APPEND(t *testing.T) {
|
||||
server := createSugarDB()
|
||||
tests := []struct {
|
||||
name string
|
||||
presetValue interface{}
|
||||
key string
|
||||
value string
|
||||
want int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test APPEND with no preset value",
|
||||
key: "key1",
|
||||
value: "Hello ",
|
||||
want: 6,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test APPEND with preset value",
|
||||
presetValue: "Hello ",
|
||||
key: "key2",
|
||||
value: "World",
|
||||
want: 11,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test APPEND with integer preset value",
|
||||
key: "key3",
|
||||
presetValue: 10,
|
||||
value: "Hello ",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.presetValue != nil {
|
||||
err := presetValue(server, context.Background(), tt.key, tt.presetValue)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Run("TestSugarDB_APPEND", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
presetValue interface{}
|
||||
key string
|
||||
value string
|
||||
want int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Test APPEND with no preset value",
|
||||
key: "append_key1",
|
||||
value: "Hello ",
|
||||
want: 6,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test APPEND with preset value",
|
||||
presetValue: "Hello ",
|
||||
key: "append_key2",
|
||||
value: "World",
|
||||
want: 11,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test APPEND with integer preset value",
|
||||
key: "append_key3",
|
||||
presetValue: 10,
|
||||
value: "Hello ",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if tt.presetValue != nil {
|
||||
err := presetValue(server, context.Background(), tt.key, tt.presetValue)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
got, err := server.Append(tt.key, tt.value)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("APPEND() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
}
|
||||
got, err := server.Append(tt.key, tt.value)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("APPEND() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("APPEND() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("APPEND() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+21
-13
@@ -212,6 +212,8 @@ func makeCluster(size int) ([]ClientServerPair, error) {
|
||||
}
|
||||
|
||||
func Test_Cluster(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
nodes, err := makeCluster(5)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@@ -274,9 +276,7 @@ func Test_Cluster(t *testing.T) {
|
||||
|
||||
// Yield
|
||||
ticker := time.NewTicker(200 * time.Millisecond)
|
||||
defer func() {
|
||||
ticker.Stop()
|
||||
}()
|
||||
defer ticker.Stop()
|
||||
<-ticker.C
|
||||
|
||||
// Check if the data has been replicated on a quorum (majority of the cluster).
|
||||
@@ -322,10 +322,8 @@ func Test_Cluster(t *testing.T) {
|
||||
|
||||
// Yield
|
||||
ticker := time.NewTicker(200 * time.Millisecond)
|
||||
defer func() {
|
||||
ticker.Stop()
|
||||
}()
|
||||
<-ticker.C
|
||||
ticker.Stop()
|
||||
|
||||
// Check if the data has been replicated on a quorum (majority of the cluster).
|
||||
quorum := int(math.Ceil(float64(len(nodes)/2)) + 1)
|
||||
@@ -963,8 +961,18 @@ func Test_Standalone(t *testing.T) {
|
||||
name: "1. Snapshot in embedded instance",
|
||||
dataDir: path.Join(dataDir, "embedded_instance"),
|
||||
values: map[int]map[string]string{
|
||||
0: {"key5": "value-05", "key6": "value-06", "key7": "value-07", "key8": "value-08"},
|
||||
1: {"key5": "value-15", "key6": "value-16", "key7": "value-17", "key8": "value-18"},
|
||||
0: {
|
||||
"test_snapshot_key5": "value-05",
|
||||
"test_snapshot_key6": "value-06",
|
||||
"test_snapshot_key7": "value-07",
|
||||
"test_snapshot_key8": "value-08",
|
||||
},
|
||||
1: {
|
||||
"test_snapshot_key5": "value-15",
|
||||
"test_snapshot_key6": "value-16",
|
||||
"test_snapshot_key7": "value-17",
|
||||
"test_snapshot_key8": "value-18",
|
||||
},
|
||||
},
|
||||
snapshotFunc: func(mockServer *SugarDB) error {
|
||||
if _, err := mockServer.Save(); err != nil {
|
||||
@@ -1022,7 +1030,7 @@ func Test_Standalone(t *testing.T) {
|
||||
}
|
||||
|
||||
// Yield to allow snapshot to complete sync.
|
||||
ticker := time.NewTicker(20 * time.Millisecond)
|
||||
ticker := time.NewTicker(200 * time.Millisecond)
|
||||
<-ticker.C
|
||||
ticker.Stop()
|
||||
|
||||
@@ -1121,10 +1129,10 @@ func Test_Standalone(t *testing.T) {
|
||||
<-ticker.C
|
||||
|
||||
// Rewrite AOF
|
||||
if _, err := mockServer.RewriteAOF(); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
mockServer.RewriteAOF()
|
||||
|
||||
// Yield
|
||||
<-ticker.C
|
||||
|
||||
// Perform write commands from "after-rewrite"
|
||||
for key, value := range data["after-rewrite"] {
|
||||
|
||||
Reference in New Issue
Block a user