Skip to content

Commit

Permalink
feat: print result in format
Browse files Browse the repository at this point in the history
- Refactor code to have types to carry test config and results.
- Add support to print test result in Json.
  • Loading branch information
Taowyoo committed May 7, 2024
1 parent 72d6142 commit 14f5266
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 60 deletions.
75 changes: 53 additions & 22 deletions cmd/loadTest.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package cmd
import (
"fmt"
"log"
"os"
"sync"
"time"

Expand Down Expand Up @@ -51,26 +52,33 @@ const (
testStage
)

type setupFunc func(client *sdkms.Client) (interface{}, error)
type setupFunc func(client *sdkms.Client, testConfig *TestConfig) (interface{}, error)
type testFunc func(client *sdkms.Client, stage loadTestStage, arg interface{}) (interface{}, time.Duration, profilingMetricStr, error)
type cleanupFunc func(client *sdkms.Client)

func loadTest(name string, setup setupFunc, test testFunc, cleanup cleanupFunc) {
testConfig := &TestConfig{}
testConfig.TestName = name
testConfig.WarmupDuration = warmupDuration
testConfig.TestDuration = testDuration
testConfig.TargetQPS = queriesPerSecond
testConfig.Connections = connections
testConfig.CreateSession = createSession

fmt.Printf(" Load test: %v\n", name)
fmt.Printf(" Server: %v:%v\n", serverName, serverPort)
fmt.Printf(" Target QPS: %v\n", queriesPerSecond)
fmt.Printf(" Connections: %v\n", connections)
fmt.Printf(" Test Duration: %v\n", testDuration)
testTime := time.Now()

fmt.Printf("Load test: %v\n", name)
fmt.Printf("Server: %v:%v\n", serverName, serverPort)
fmt.Printf("Target QPS: %v\n", queriesPerSecond)
fmt.Printf("Connections: %v\n", connections)
fmt.Printf("Test Duration: %v\n", testDuration)
fmt.Printf("Warmup Duration: %v\n", warmupDuration)
fmt.Println()

testConfig := TestConfig{
TestName: name,
ServerName: serverName,
ServerPort: serverPort,
VerifyTls: !insecureTLS,
Connections: connections,
CreateSession: createSession,
WarmupDuration: warmupDuration,
TestDuration: testDuration,
TargetQPS: queriesPerSecond,
}

type testMetric struct {
t time.Time
d time.Duration
Expand Down Expand Up @@ -105,7 +113,7 @@ func loadTest(name string, setup setupFunc, test testFunc, cleanup cleanupFunc)
defer wg1.Done()

client := sdkmsClient()
arg, err := setup(&client)
arg, err := setup(&client, &testConfig)
if err != nil {
log.Fatalf("Fatal error: %v\n", err)
}
Expand Down Expand Up @@ -176,18 +184,41 @@ func loadTest(name string, setup setupFunc, test testFunc, cleanup cleanupFunc)
sendDuration := lastTick.Sub(t0)
testDuration := t1.Sub(t0)

fmt.Printf(" Warmup: %v queries, %v\n", len(warmups), summarizeTimings(warmups))
fmt.Printf(" Test: %v queries, %v\n", len(tests), summarizeTimings(tests))
fmt.Printf(" Test duration: %v (%0.2f QPS)\n", testDuration, float64(len(tests))/testDuration.Seconds())
fmt.Printf(" Send duration: %v (%0.2f QPS)\n", sendDuration, float64(len(tests))/sendDuration.Seconds())
fmt.Printf("Profiling data: %v examples\n", len(profilingMetricStrArr))

if len(profilingMetricStrArr) != 0 {
dataArr := parseProfilingMetricStrArr(profilingMetricStrArr)
summarizeProfilingMetrics(dataArr)
if storeProfilingData {
saveProfilingMetricsToCSV(dataArr)
}
}
fmt.Print("\n\n")
testResult := TestResult{
Warmup: StatisticFromDurations(warmups, warmupDuration),
Test: StatisticFromDurations(tests, testDuration),
ActualTestDuration: testDuration,
SendDuration: sendDuration,
ProfilingResults: &ProfilingStatistics{},
}

testSummary := &TestSummary{
TestTime: testTime,
Config: &testConfig,
Result: &testResult,
}

switch outputFormat {
case Plain:
err := testSummary.WritePlain(os.Stdout)
if err != nil {
log.Fatalf("failed to write test summary in plain: %v\n", err)
}
case JSON:
err := testSummary.WriteJson(os.Stdout)
if err != nil {
log.Fatalf("failed to write test summary in json: %v\n", err)
}
case YAML:
log.Fatalf("write test summary in yaml is not yet supported\n")
default:
log.Fatalf("unreachable: unacceptable output format option: %v\n", outputFormat)
}
}
5 changes: 4 additions & 1 deletion cmd/loadTestAsymmetricCrypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ func asymmetricCryptoLoadTest() {
// get basic info of the given sobject
key := GetSobject(&keyID)

setup := func(client *sdkms.Client) (interface{}, error) {
setup := func(client *sdkms.Client, testConfig *TestConfig) (interface{}, error) {
if testConfig.Sobject != nil {
testConfig.Sobject = key
}
if createSession {
_, err := client.AuthenticateWithAPIKey(context.Background(), apiKey)
return nil, err
Expand Down
29 changes: 22 additions & 7 deletions cmd/loadTestGenerateKey.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,24 @@ func loadTestGenerateKey() {
keySize = 2048
}
}
setup := func(client *sdkms.Client) (interface{}, error) {
_, err := client.AuthenticateWithAPIKey(context.Background(), apiKey)
return nil, err
setup := func(client *sdkms.Client, testConfig *TestConfig) (interface{}, error) {
if createSession {
_, err := client.AuthenticateWithAPIKey(context.Background(), apiKey)
if err != nil {
return nil, err
}
}
client.Auth = sdkms.APIKey(apiKey)

// Create one example key to fill the test config
if testConfig.Sobject != nil {
key, _, _, err := generateKey(client)
if err != nil {
return nil, err
}
testConfig.Sobject = key
}
return nil, nil
}
cleanup := func(client *sdkms.Client) {
client.TerminateSession(context.Background())
Expand All @@ -59,7 +74,7 @@ func loadTestGenerateKey() {
if stage == warmupStage {
return nil, 0, "", nil
}
d, p, err := generateKey(client)
_, d, p, err := generateKey(client)
return nil, d, p, err
}
name := fmt.Sprintf("generate %v key", keyType)
Expand All @@ -69,7 +84,7 @@ func loadTestGenerateKey() {
loadTest(name, setup, test, cleanup)
}

func generateKey(client *sdkms.Client) (time.Duration, profilingMetricStr, error) {
func generateKey(client *sdkms.Client) (*sdkms.Sobject, time.Duration, profilingMetricStr, error) {
req := sdkms.SobjectRequest{
Transient: someBool(true),
ObjType: convertObjectType(keyType),
Expand All @@ -80,13 +95,13 @@ func generateKey(client *sdkms.Client) (time.Duration, profilingMetricStr, error
ctx := context.WithValue(context.Background(), responseHeaderKey, http.Header{})

t0 := time.Now()
_, err := client.CreateSobject(ctx, req)
key, err := client.CreateSobject(ctx, req)
d := time.Since(t0)

header := ctx.Value(responseHeaderKey).(http.Header)
p := profilingMetricStr(header.Get("Profiling-Data"))

return d, p, err
return key, d, p, err
}

func someBool(x bool) *bool { return &x }
Expand Down
8 changes: 7 additions & 1 deletion cmd/loadTestInvokePlugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@ func invokePluginLoadTest() {
log.Fatalf("Plugin input must be valid JSON: %v\n", err)
}

setup := func(client *sdkms.Client) (interface{}, error) {
setup := func(client *sdkms.Client, testConfig *TestConfig) (interface{}, error) {
if testConfig.Plugin != nil {
testConfig.Plugin = plugin
}
if testConfig.PluginInput != nil {
testConfig.PluginInput = &input
}
if createSession {
_, err := client.AuthenticateWithAPIKey(context.Background(), apiKey)
return nil, err
Expand Down
5 changes: 4 additions & 1 deletion cmd/loadTestSignVerify.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ func signVerifyLoadTest() {
// get basic info of the given sobject
key := GetSobject(&signKeyID)

setup := func(client *sdkms.Client) (interface{}, error) {
setup := func(client *sdkms.Client, testConfig *TestConfig) (interface{}, error) {
if testConfig.Sobject != nil {
testConfig.Sobject = key
}
if createSession {
_, err := client.AuthenticateWithAPIKey(context.Background(), apiKey)
return nil, err
Expand Down
5 changes: 4 additions & 1 deletion cmd/loadTestSymmetricCrypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ func symmetricCryptoLoadTest() {
// get basic info of the given sobject
key := GetSobject(&keyID)

setup := func(client *sdkms.Client) (interface{}, error) {
setup := func(client *sdkms.Client, testConfig *TestConfig) (interface{}, error) {
if testConfig.Sobject != nil {
testConfig.Sobject = key
}
if createSession {
_, err := client.AuthenticateWithAPIKey(context.Background(), apiKey)
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion cmd/loadTestVersion.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func init() {
}

func versionLoadTest() {
setup := func(client *sdkms.Client) (interface{}, error) {
setup := func(client *sdkms.Client, testConfig *TestConfig) (interface{}, error) {
return nil, nil
}
cleanup := func(client *sdkms.Client) {}
Expand Down
Loading

0 comments on commit 14f5266

Please sign in to comment.