-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0ccc0c7
commit 69df546
Showing
7 changed files
with
334 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package tests | ||
|
||
import ( | ||
"time" | ||
) | ||
|
||
var getTestCases = []Meta{ | ||
{ | ||
Name: "Get on non-existing key", | ||
Input: []string{"GET k"}, | ||
Output: []interface{}{"(nil)"}, | ||
}, | ||
{ | ||
Name: "Get on existing key", | ||
Input: []string{"SET k v", "GET k"}, | ||
Output: []interface{}{"OK", "v"}, | ||
Cleanup: []string{"k"}, | ||
}, | ||
{ | ||
Name: "Get with expiration", | ||
Input: []string{"SET k v EX 2", "GET k", "GET k"}, | ||
Output: []interface{}{"OK", "v", "(nil)"}, | ||
Delays: []time.Duration{0, 0, 3 * time.Second}, | ||
Cleanup: []string{"k"}, | ||
}, | ||
} | ||
|
||
func init() { | ||
RegisterTests(getTestCases) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package tests | ||
|
||
import ( | ||
"log" | ||
"testing" | ||
"time" | ||
|
||
"github.com/dicedb/dice/config" | ||
"github.com/dicedb/dice/integration_tests/commands/tests/parsers" | ||
"github.com/dicedb/dice/integration_tests/commands/tests/servers" | ||
"gotest.tools/v3/assert" | ||
) | ||
|
||
func init() { | ||
parser := config.NewConfigParser() | ||
if err := parser.ParseDefaults(config.DiceConfig); err != nil { | ||
log.Fatalf("failed to load configuration: %v", err) | ||
} | ||
} | ||
|
||
func TestHttpCommands(t *testing.T) { | ||
exec := servers.NewHTTPCommandExecutor() | ||
allTests := GetAllTests() | ||
|
||
for _, test := range allTests { | ||
t.Run(test.Name, func(t *testing.T) { | ||
|
||
// Setup commands | ||
if len(test.Setup) > 0 { | ||
for _, setup := range test.Setup { | ||
for idx, cmd := range setup.Input { | ||
output, _ := parsers.HttpCommandExecuter(exec, cmd) | ||
assert.Equal(t, setup.Output[idx], output) | ||
} | ||
} | ||
} | ||
|
||
for idx, cmd := range test.Input { | ||
if len(test.Delays) > 0 { | ||
time.Sleep(test.Delays[idx]) | ||
} | ||
output, _ := parsers.HttpCommandExecuter(exec, cmd) | ||
if len(test.Assert) > 0 { | ||
SwitchAsserts(t, test.Assert[idx], test.Output[idx], output) | ||
} else { | ||
assert.Equal(t, test.Output[idx], output) | ||
} | ||
} | ||
}) | ||
if len(test.Cleanup) > 0 { | ||
// join all the keys to be cleaned up | ||
keys := "" | ||
for _, key := range test.Cleanup { | ||
keys += key | ||
} | ||
parsers.HttpCommandExecuter(exec, `DEL `+keys) | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,46 @@ | ||
package parsers | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/dicedb/dice/integration_tests/commands/tests/servers" | ||
) | ||
|
||
func ParseResponse(response interface{}) interface{} { | ||
// convert the output to the int64 if it is float64 | ||
switch response.(type) { | ||
Check failure on line 11 in integration_tests/commands/tests/parsers/http.go GitHub Actions / lint
|
||
case float64: | ||
return int64(response.(float64)) | ||
case nil: | ||
return "(nil)" | ||
default: | ||
return response | ||
} | ||
} | ||
|
||
func HttpCommandExecuter(exec *servers.HTTPCommandExecutor, cmd string) (interface{}, error) { | ||
// convert the command to a HTTPCommand | ||
// cmd starts with Command and Body is values after that | ||
tokens := strings.Split(cmd, " ") | ||
command := tokens[0] | ||
body := make(map[string]interface{}) | ||
if len(tokens) > 1 { | ||
// convert the tokens []string to []interface{} | ||
values := make([]interface{}, len(tokens[1:])) | ||
for i, v := range tokens[1:] { | ||
values[i] = v | ||
} | ||
body["values"] = values | ||
} else { | ||
body["values"] = []interface{}{} | ||
} | ||
diceHttpCmd := servers.HTTPCommand{ | ||
Command: strings.ToLower(command), | ||
Body: body, | ||
} | ||
res, err := exec.FireCommand(diceHttpCmd) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return ParseResponse(res), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,145 @@ | ||
package servers | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"log" | ||
"net/http" | ||
"strings" | ||
"sync" | ||
"time" | ||
|
||
"github.com/dicedb/dice/internal/server/utils" | ||
|
||
"github.com/dicedb/dice/config" | ||
derrors "github.com/dicedb/dice/internal/errors" | ||
"github.com/dicedb/dice/internal/querymanager" | ||
"github.com/dicedb/dice/internal/server" | ||
"github.com/dicedb/dice/internal/shard" | ||
dstore "github.com/dicedb/dice/internal/store" | ||
) | ||
|
||
type CommandExecutor interface { | ||
FireCommand(cmd string) interface{} | ||
Name() string | ||
} | ||
|
||
type HTTPCommandExecutor struct { | ||
httpClient *http.Client | ||
baseURL string | ||
} | ||
|
||
|
||
|
||
func NewHTTPCommandExecutor() *HTTPCommandExecutor { | ||
return &HTTPCommandExecutor{ | ||
baseURL: "http://localhost:8083", | ||
httpClient: &http.Client{ | ||
Timeout: time.Second * 100, | ||
}, | ||
} | ||
} | ||
|
||
type HTTPCommand struct { | ||
Command string | ||
Body map[string]interface{} | ||
} | ||
|
||
func (cmd HTTPCommand) IsEmptyCommand() bool { | ||
return cmd.Command == "" | ||
} | ||
|
||
func (e *HTTPCommandExecutor) FireCommand(cmd HTTPCommand) (interface{}, error) { | ||
command := strings.ToUpper(cmd.Command) | ||
var body []byte | ||
if cmd.Body != nil { | ||
var err error | ||
body, err = json.Marshal(cmd.Body) | ||
// Handle error during JSON marshaling | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
ctx := context.Background() | ||
req, err := http.NewRequestWithContext(ctx, "POST", e.baseURL+"/"+command, bytes.NewBuffer(body)) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create request: %w", err) | ||
} | ||
req.Header.Set("Content-Type", "application/json") | ||
|
||
resp, err := e.httpClient.Do(req) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
defer resp.Body.Close() | ||
|
||
if cmd.Command != "Q.WATCH" { | ||
var result utils.HTTPResponse | ||
err = json.NewDecoder(resp.Body).Decode(&result) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return result.Data, nil | ||
} | ||
var result interface{} | ||
err = json.NewDecoder(resp.Body).Decode(&result) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
func (e *HTTPCommandExecutor) Name() string { | ||
return "HTTP" | ||
} | ||
|
||
func RunHTTPServer(ctx context.Context, wg *sync.WaitGroup, opt TestServerOptions) { | ||
config.DiceConfig.Network.IOBufferLength = 16 | ||
config.DiceConfig.Persistence.WriteAOFOnCleanup = false | ||
|
||
globalErrChannel := make(chan error) | ||
watchChan := make(chan dstore.QueryWatchEvent, config.DiceConfig.Performance.WatchChanBufSize) | ||
shardManager := shard.NewShardManager(1, watchChan, nil, globalErrChannel) | ||
queryWatcherLocal := querymanager.NewQueryManager() | ||
config.DiceConfig.HTTP.Port = opt.Port | ||
// Initialize the HTTPServer | ||
testServer := server.NewHTTPServer(shardManager, nil) | ||
// Inform the user that the server is starting | ||
fmt.Println("Starting the test server on port", config.DiceConfig.HTTP.Port) | ||
shardManagerCtx, cancelShardManager := context.WithCancel(ctx) | ||
wg.Add(1) | ||
go func() { | ||
defer wg.Done() | ||
shardManager.Run(shardManagerCtx) | ||
}() | ||
|
||
wg.Add(1) | ||
go func() { | ||
defer wg.Done() | ||
queryWatcherLocal.Run(ctx, watchChan) | ||
}() | ||
|
||
// Start the server in a goroutine | ||
wg.Add(1) | ||
go func() { | ||
defer wg.Done() | ||
err := testServer.Run(ctx) | ||
if err != nil { | ||
cancelShardManager() | ||
if errors.Is(err, derrors.ErrAborted) { | ||
return | ||
} | ||
if err.Error() != "http: Server closed" { | ||
log.Fatalf("Http test server encountered an error: %v", err) | ||
} | ||
log.Printf("Http test server encountered an error: %v", err) | ||
} | ||
}() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters