Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit tests for root.go and getVersion.go #5

Merged
merged 1 commit into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
.tool-versions
.vscode/
dsm-perf-tool
*.env
*.log

# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
Expand Down
105 changes: 105 additions & 0 deletions cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ package cmd
import (
"context"
"crypto/tls"
"encoding/csv"
"encoding/json"
"fmt"
"log"
"math"
"net"
"net/http"
"os"
"os/signal"
"reflect"
"strconv"
"strings"
"syscall"
"time"
Expand Down Expand Up @@ -184,3 +188,104 @@ func GetSobject(kid *string) *sdkms.Sobject {
}
return key
}

func summarizeProfilingData(dataArr profilingDataArr) {
var inQueueData stats.Float64Data
var parseRequestData stats.Float64Data
var sessionLookupData stats.Float64Data
var validateInputData stats.Float64Data
var checkAccessData stats.Float64Data
var operateData stats.Float64Data
var dbFlushData stats.Float64Data
var totalData stats.Float64Data
additionalDataArr := make(map[string]stats.Float64Data)
actionNameMaxLen := len("SessionLookup")
for _, data := range dataArr {
inQueueData = append(inQueueData, float64(data.InQueue))
parseRequestData = append(parseRequestData, float64(data.ParseRequest))
sessionLookupData = append(sessionLookupData, float64(data.SessionLookup))
validateInputData = append(validateInputData, float64(data.ValidateInput))
checkAccessData = append(checkAccessData, float64(data.CheckAccess))
operateData = append(operateData, float64(data.Operate))
dbFlushData = append(dbFlushData, float64(data.DbFlush))
totalData = append(totalData, float64(data.Total))
actionNameMaxLen = Max(actionNameMaxLen, processAdditionalProfilingData(&data.AdditionalProfilingData, &additionalDataArr, actionNameMaxLen, ""))
}
fmt.Printf("%s: %s\n", StrPad("InQueue", actionNameMaxLen, " ", "LEFT"), summarizeData(inQueueData))
fmt.Printf("%s: %s\n", StrPad("ParseRequest", actionNameMaxLen, " ", "LEFT"), summarizeData(parseRequestData))
fmt.Printf("%s: %s\n", StrPad("SessionLookup", actionNameMaxLen, " ", "LEFT"), summarizeData(sessionLookupData))
fmt.Printf("%s: %s\n", StrPad("ValidateInput", actionNameMaxLen, " ", "LEFT"), summarizeData(validateInputData))
fmt.Printf("%s: %s\n", StrPad("CheckAccess", actionNameMaxLen, " ", "LEFT"), summarizeData(checkAccessData))
fmt.Printf("%s: %s\n", StrPad("Operate", actionNameMaxLen, " ", "LEFT"), summarizeData(operateData))
fmt.Printf("%s: %s\n", StrPad("DbFlush", actionNameMaxLen, " ", "LEFT"), summarizeData(dbFlushData))
fmt.Printf("%s: %s\n", StrPad("Total", actionNameMaxLen, " ", "LEFT"), summarizeData(totalData))
for actionName, timeArr := range additionalDataArr {
fmt.Printf("%s: %s\n", StrPad(actionName, actionNameMaxLen, " ", "LEFT"), summarizeData(timeArr))
}
}

func processAdditionalProfilingData(dataArr *[]additionalProfilingData, additionalDataArr *map[string]stats.Float64Data, actionNameMaxLen int, parentActionName string) int {
for _, customProfilingData := range *dataArr {
actionName := parentActionName + "/" + customProfilingData.Action
(*additionalDataArr)[actionName] = append((*additionalDataArr)[actionName], float64(customProfilingData.TookNs))
actionNameMaxLen = Max(actionNameMaxLen, len(actionName))
actionNameMaxLen = Max(actionNameMaxLen, processAdditionalProfilingData(&customProfilingData.SubActions, additionalDataArr, actionNameMaxLen, actionName))
}
return actionNameMaxLen
}

func (dataArr profilingDataArr) getCSVHeaders() (header []string) {
e := reflect.ValueOf(&dataArr[0]).Elem()
for i := 0; i < e.NumField(); i++ {
varName := e.Type().Field(i).Name
header = append(header, varName)
}
return header
}

func (dataArr profilingDataArr) getCSVValues() (values [][]string) {
for _, data := range dataArr {
values = append(values, []string{
strconv.FormatUint(data.InQueue, 10),
strconv.FormatUint(data.ParseRequest, 10),
strconv.FormatUint(data.SessionLookup, 10),
strconv.FormatUint(data.ValidateInput, 10),
strconv.FormatUint(data.CheckAccess, 10),
strconv.FormatUint(data.Operate, 10),
strconv.FormatUint(data.DbFlush, 10),
strconv.FormatUint(data.Total, 10),
})
}
return values
}

func saveProfilingDataToCSV(dataArr profilingDataArr) {
csvFile, err := os.CreateTemp(".", "profilingData.*.csv")
if err != nil {
log.Fatalf("Fatal error: %v\n", err)
}
w := csv.NewWriter(csvFile)
headers := dataArr.getCSVHeaders()
values := dataArr.getCSVValues()
if err := w.Write(headers); err != nil {
log.Fatalf("Fatal error: %v\n", err)
}
if err := w.WriteAll(values); err != nil {
log.Fatalf("Fatal error: %v\n", err)
}

fmt.Println("Saved profiling data to:", csvFile.Name())
}

func parseProfilingDataStrArr(profilingDataStrArr []profilingDataStr) profilingDataArr {
var dataArr profilingDataArr
for _, profilingDataStr := range profilingDataStrArr {
var profilingData profilingData
err := json.Unmarshal([]byte(string(profilingDataStr)), &profilingData)
if err != nil {
log.Fatalf("Fatal error: %v\n", err)
}
dataArr = append(dataArr, profilingData)
}
return dataArr
}
61 changes: 61 additions & 0 deletions cmd/getVersion_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* Copyright (c) Fortanix, Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package cmd

import (
"encoding/json"
"net/http"
"net/http/httptest"
"net/url"
"testing"

"github.com/fortanix/sdkms-client-go/sdkms"
"github.com/stretchr/testify/assert"
)

func TestTestSetupCmd(t *testing.T) {
resetRootCmdStatus()
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/sys/v1/version" {
t.Errorf("Expected to request '/sys/v1/version', got: %s", r.URL.Path)
}
w.WriteHeader(http.StatusOK)
resp := sdkms.VersionResponse{
Version: "1234",
APIVersion: "1234",
ServerMode: "httptest",
}
respBytes, err := json.Marshal(resp)
if err != nil {
t.Fatal("Error encoding fake version response:", err)
}
w.Write(respBytes)
}))
defer server.Close()
// Parse the URL
parsedServerURL, err := url.Parse(server.URL)
if err != nil {
t.Fatal("Error parsing test server URL:", err)
}
testServerHost := parsedServerURL.Hostname()
testServerPort := parsedServerURL.Port()
if testServerPort == "" {
testServerPort = "443"
}

args := []string{
"--server", testServerHost,
"--port", testServerPort,
"--insecure",
"version",
"--count", "1",
}

rootCmd.SetArgs(args)
err = ExecuteCmd()
assert.NoError(t, err)
}
107 changes: 0 additions & 107 deletions cmd/loadTest.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,12 @@
package cmd

import (
"encoding/csv"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"reflect"
"strconv"
"sync"
"time"

"github.com/fortanix/sdkms-client-go/sdkms"
"github.com/montanaflynn/stats"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -211,104 +205,3 @@ func loadTest(name string, setup setupFunc, test testFunc, cleanup cleanupFunc)
}
fmt.Print("\n\n")
}

func summarizeProfilingData(dataArr profilingDataArr) {
var inQueueData stats.Float64Data
var parseRequestData stats.Float64Data
var sessionLookupData stats.Float64Data
var validateInputData stats.Float64Data
var checkAccessData stats.Float64Data
var operateData stats.Float64Data
var dbFlushData stats.Float64Data
var totalData stats.Float64Data
additionalDataArr := make(map[string]stats.Float64Data)
actionNameMaxLen := len("SessionLookup")
for _, data := range dataArr {
inQueueData = append(inQueueData, float64(data.InQueue))
parseRequestData = append(parseRequestData, float64(data.ParseRequest))
sessionLookupData = append(sessionLookupData, float64(data.SessionLookup))
validateInputData = append(validateInputData, float64(data.ValidateInput))
checkAccessData = append(checkAccessData, float64(data.CheckAccess))
operateData = append(operateData, float64(data.Operate))
dbFlushData = append(dbFlushData, float64(data.DbFlush))
totalData = append(totalData, float64(data.Total))
actionNameMaxLen = Max(actionNameMaxLen, processAdditionalProfilingData(&data.AdditionalProfilingData, &additionalDataArr, actionNameMaxLen, ""))
}
fmt.Printf("%s: %s\n", StrPad("InQueue", actionNameMaxLen, " ", "LEFT"), summarizeData(inQueueData))
fmt.Printf("%s: %s\n", StrPad("ParseRequest", actionNameMaxLen, " ", "LEFT"), summarizeData(parseRequestData))
fmt.Printf("%s: %s\n", StrPad("SessionLookup", actionNameMaxLen, " ", "LEFT"), summarizeData(sessionLookupData))
fmt.Printf("%s: %s\n", StrPad("ValidateInput", actionNameMaxLen, " ", "LEFT"), summarizeData(validateInputData))
fmt.Printf("%s: %s\n", StrPad("CheckAccess", actionNameMaxLen, " ", "LEFT"), summarizeData(checkAccessData))
fmt.Printf("%s: %s\n", StrPad("Operate", actionNameMaxLen, " ", "LEFT"), summarizeData(operateData))
fmt.Printf("%s: %s\n", StrPad("DbFlush", actionNameMaxLen, " ", "LEFT"), summarizeData(dbFlushData))
fmt.Printf("%s: %s\n", StrPad("Total", actionNameMaxLen, " ", "LEFT"), summarizeData(totalData))
for actionName, timeArr := range additionalDataArr {
fmt.Printf("%s: %s\n", StrPad(actionName, actionNameMaxLen, " ", "LEFT"), summarizeData(timeArr))
}
}

func processAdditionalProfilingData(dataArr *[]additionalProfilingData, additionalDataArr *map[string]stats.Float64Data, actionNameMaxLen int, parentActionName string) int {
for _, customProfilingData := range *dataArr {
actionName := parentActionName + "/" + customProfilingData.Action
(*additionalDataArr)[actionName] = append((*additionalDataArr)[actionName], float64(customProfilingData.TookNs))
actionNameMaxLen = Max(actionNameMaxLen, len(actionName))
actionNameMaxLen = Max(actionNameMaxLen, processAdditionalProfilingData(&customProfilingData.SubActions, additionalDataArr, actionNameMaxLen, actionName))
}
return actionNameMaxLen
}

func (dataArr profilingDataArr) getCSVHeaders() (header []string) {
e := reflect.ValueOf(&dataArr[0]).Elem()
for i := 0; i < e.NumField(); i++ {
varName := e.Type().Field(i).Name
header = append(header, varName)
}
return header
}

func (dataArr profilingDataArr) getCSVValues() (values [][]string) {
for _, data := range dataArr {
values = append(values, []string{
strconv.FormatUint(data.InQueue, 10),
strconv.FormatUint(data.ParseRequest, 10),
strconv.FormatUint(data.SessionLookup, 10),
strconv.FormatUint(data.ValidateInput, 10),
strconv.FormatUint(data.CheckAccess, 10),
strconv.FormatUint(data.Operate, 10),
strconv.FormatUint(data.DbFlush, 10),
strconv.FormatUint(data.Total, 10),
})
}
return values
}

func saveProfilingDataToCSV(dataArr profilingDataArr) {
csvFile, err := ioutil.TempFile(".", "profilingData.*.csv")
if err != nil {
log.Fatalf("Fatal error: %v\n", err)
}
w := csv.NewWriter(csvFile)
headers := dataArr.getCSVHeaders()
values := dataArr.getCSVValues()
if err := w.Write(headers); err != nil {
log.Fatalf("Fatal error: %v\n", err)
}
if err := w.WriteAll(values); err != nil {
log.Fatalf("Fatal error: %v\n", err)
}

fmt.Println("Saved profiling data to:", csvFile.Name())
}

func parseProfilingDataStrArr(profilingDataStrArr []profilingDataStr) profilingDataArr {
var dataArr profilingDataArr
for _, profilingDataStr := range profilingDataStrArr {
var profilingData profilingData
err := json.Unmarshal([]byte(string(profilingDataStr)), &profilingData)
if err != nil {
log.Fatalf("Fatal error: %v\n", err)
}
dataArr = append(dataArr, profilingData)
}
return dataArr
}
25 changes: 13 additions & 12 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@
package cmd

import (
"fmt"
"os"
"time"

"github.com/spf13/cobra"
)

const defaultServerName = "sdkms.test.fortanix.com"
const defaultServerPort = uint16(443)
const defaultTlsNotVerify = false
const defaultRequestTimeout = 60 * time.Second
const defaultIdleConnectionTimeout = 0 * time.Second

var serverName string
var serverPort uint16
var insecureTLS bool
Expand All @@ -26,18 +30,15 @@ var rootCmd = &cobra.Command{
Long: `DSM performance tool`,
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
func ExecuteCmd() error {
return rootCmd.Execute()
}

func init() {
rootCmd.PersistentFlags().StringVarP(&serverName, "server", "s", "sdkms.test.fortanix.com", "DSM server host name")
rootCmd.PersistentFlags().Uint16VarP(&serverPort, "port", "p", 443, "DSM server port")
rootCmd.PersistentFlags().BoolVar(&insecureTLS, "insecure", false, "Do not validate server's TLS certificate")
rootCmd.PersistentFlags().DurationVar(&requestTimeout, "request-timeout", 60*time.Second, "HTTP request timeout, 0 means no timeout")
rootCmd.PersistentFlags().DurationVar(&idleConnectionTimeout, "idle-connection-timeout", 0, "Idle connection timeout, 0 means no timeout (default behavior)")
rootCmd.PersistentFlags().StringVarP(&serverName, "server", "s", defaultServerName, "DSM server host name")
rootCmd.PersistentFlags().Uint16VarP(&serverPort, "port", "p", defaultServerPort, "DSM server port")
rootCmd.PersistentFlags().BoolVar(&insecureTLS, "insecure", defaultTlsNotVerify, "Do not validate server's TLS certificate")
rootCmd.PersistentFlags().DurationVar(&requestTimeout, "request-timeout", defaultRequestTimeout, "HTTP request timeout, 0 means no timeout")
rootCmd.PersistentFlags().DurationVar(&idleConnectionTimeout, "idle-connection-timeout", defaultIdleConnectionTimeout, "Idle connection timeout, 0 means no timeout (default behavior)")

}
Loading