From e1a1e5a49d9ac220773c5aafd87113c0011de342 Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Wed, 3 Jan 2024 11:55:56 +1100 Subject: [PATCH] implement hasKeys check --- check_results.go | 81 ++++++++++++++++++++++++++++++++++++++++++++++-- load_input.go | 19 +++++++++--- main.go | 28 +++++++++++++++++ run_tests.go | 15 +++------ structs.go | 3 +- tests.json | 4 +-- 6 files changed, 129 insertions(+), 21 deletions(-) diff --git a/check_results.go b/check_results.go index 1528c2f..8e624d6 100644 --- a/check_results.go +++ b/check_results.go @@ -8,16 +8,40 @@ import ( ) func CheckResults(testCase *TestCase) (bool, error) { + var result bool = true // Check headers - result, err := HeaderContains(testCase) + headerContains, err := HeaderContains(testCase) + if err != nil { + return result, err + } + result = result && headerContains + + headerEquals, err := HeaderEquals(testCase) + if err != nil { + return result, err + } + result = result && headerEquals + + // Check body + bodyContains, err := BodyContains(testCase) + if err != nil { + return result, err + } + result = result && bodyContains + + bodyHasKeys, err := BodyHasKeys(testCase) + if err != nil { + return result, err + } + result = result && bodyHasKeys return result, err } func HeaderContains(testCase *TestCase) (bool, error) { for k, v := range testCase.Expect.Header.Contains { - fmt.Printf("Header contains check '%s'='%s'\n", k, v) + //fmt.Printf("Header contains check '%s'='%s'\n", k, v) if k == "http_status" { // http status is a special case statusCode, err := strconv.Atoi(v) @@ -52,3 +76,56 @@ func HeaderContains(testCase *TestCase) (bool, error) { return true, nil } + +func HeaderEquals(testCase *TestCase) (bool, error) { + + for k, v := range testCase.Expect.Header.Equals { + fmt.Printf("Header equals check '%s'='%s'\n", k, v) + + // TODO + } + + return true, nil +} + +func BodyContains(testCase *TestCase) (bool, error) { + for k, v := range testCase.Expect.Body.Contains { + //fmt.Printf("Body contains check '%s'='%s'\n", k, v) + + // If the body response was json then we stored it already when running the test + if val, ok := testCase.ResultBodyMap[k]; ok { + // TODO handle values other than string using a switch + //fmt.Printf("Found key in body with response '%s'\n", val) + + // Check that the value matched + if strings.Contains(val.(string), v) { + fmt.Printf("Key matches, success\n") + } else { + fmt.Printf("Body Contains check failed on key '%s'. Expected value '%s' but found '%s'\n", k, v, val) + return false, nil + } + + } else { + // body did not contain the key we were looking for so return false + return false, nil + } + + // TODO + } + + return true, nil +} + +func BodyHasKeys(testCase *TestCase) (bool, error) { + for _, key := range testCase.Expect.Body.HasKeys { + // If the body response was json then we stored it already when running the test + if _, ok := testCase.ResultBodyMap[key]; ok { + fmt.Printf("Confirmed body has key '%s'\n", key) + } else { + fmt.Printf("Body HasKeys test failed, expected key '%s' not found\n", key) + return false, nil + } + } + + return true, nil +} diff --git a/load_input.go b/load_input.go index 97e247b..52a3b42 100644 --- a/load_input.go +++ b/load_input.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "reflect" "github.com/iancoleman/orderedmap" ) @@ -229,13 +230,18 @@ func ReadHeaderTestCases(input orderedmap.OrderedMap, result *HeaderTests) { func ReadBodyTestCases(input orderedmap.OrderedMap, result *BodyTests) { result.Contains = make(map[string]string) result.Equals = make(map[string]string) - result.HasKeys = make(map[string]string) // TODO : Use tags in struct rather than hard coding all the different check types // using https://stackoverflow.com/a/23840419 as an idea // Contains check if val, ok := input.Get("contains"); ok { + // Confirm this is an ordered map + if _, ok := val.(orderedmap.OrderedMap); !ok { + error := fmt.Sprintf("Unexpected json definition for Body Contains check. Type is '%v' but expected Object.\n", reflect.TypeOf(val)) + panic(error) + } + containsMap := val.(orderedmap.OrderedMap) result.Contains = OrderedToStringMap(containsMap) } @@ -247,9 +253,14 @@ func ReadBodyTestCases(input orderedmap.OrderedMap, result *BodyTests) { } // Has Keys check - if val, ok := input.Get("haskeys"); ok { - equalsMap := val.(orderedmap.OrderedMap) - result.HasKeys = OrderedToStringMap(equalsMap) + if val, ok := input.Get("hasKeys"); ok { + // This is an array not a map + + hasKeysArray := val.([]interface{}) + result.HasKeys = OrderedToStringSlice(hasKeysArray) + + //equalsMap := val.(orderedmap.OrderedMap) + //result.HasKeys = OrderedToStringMap(equalsMap) } // TODO : remaining tests diff --git a/main.go b/main.go index 4f52d93..c043213 100644 --- a/main.go +++ b/main.go @@ -89,3 +89,31 @@ func OrderedToStringMap(input orderedmap.OrderedMap) map[string]string { return result } + +func OrderedToStringSlice(input []interface{}) []string { + result := []string{} + //vs := testsInterface.([]interface{}) + //fmt.Printf("Listing %d test definitions\n", len(vs)) + + for i := range input { + //fmt.Printf("Reading '%s'\n", input[i]) + + switch vType := input[i].(type) { + case string: + result = append(result, input[i].(string)) + default: + fmt.Printf("OrderedToStringSlice received unexpected value type, %T\n", vType) + } + + /* + v := vInterface.(orderedmap.OrderedMap) + keys := v.Keys() + fmt.Printf("Test %d\n", i) + for j := range keys { + fmt.Printf("[%d] : %s\n", j, keys[j]) + } + */ + } + + return result +} diff --git a/run_tests.go b/run_tests.go index a651b50..5d1a0b1 100644 --- a/run_tests.go +++ b/run_tests.go @@ -18,7 +18,7 @@ func RunTest(testCase *TestCase) error { var requestUrl string var requestType string var req *http.Request - var bodyMap map[string]interface{} + //var bodyMap map[string]interface{} tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: testDefinitions.Insecure}, @@ -110,21 +110,14 @@ func RunTest(testCase *TestCase) error { testCase.ResultBody = string(body) fmt.Printf("Body response:\n%s\n", testCase.ResultBody) - /* - // Something to store results in - ResultStatusCode int - ResultHeaders map[string]string - ResultBody string - */ - // We have no idea what the response will look like so use an interface and unmarshal manually as needed if len(body) > 0 { var b interface{} json.Unmarshal(body, &b) if b != nil { - bodyMap = b.(map[string]interface{}) + testCase.ResultBodyMap = b.(map[string]interface{}) + //bodyMap = b.(map[string]interface{}) } - } // Iterate through testDefinitions.CaptureCases and see if there are any that match this test @@ -136,7 +129,7 @@ func RunTest(testCase *TestCase) error { for k, v := range captureData.Body.Data { //fmt.Printf("Body capture %s = %s\n", k, v) - if val, ok := bodyMap[k]; ok { + if val, ok := testCase.ResultBodyMap[k]; ok { // TODO handle values other than string using a switch //fmt.Printf("Found matching capture in body with value : '%v', storing replacement with key '%s'\n", val, v) captureValues.Data[v] = val.(string) diff --git a/structs.go b/structs.go index b2897de..0d24252 100644 --- a/structs.go +++ b/structs.go @@ -24,6 +24,7 @@ type TestCase struct { ResultStatusCode int ResultHeaders map[string][]string ResultBody string + ResultBodyMap map[string]interface{} } type CaptureCase struct { @@ -62,7 +63,7 @@ type HeaderTests struct { type BodyTests struct { Contains map[string]string Equals map[string]string - HasKeys map[string]string + HasKeys []string PathEquals string PathContains map[string]string } diff --git a/tests.json b/tests.json index f995c9a..44b7a69 100644 --- a/tests.json +++ b/tests.json @@ -17,9 +17,7 @@ } }, "body": { - "contains": { - "access_token":"*" - } + "hasKeys": ["access_token"] } } },