package main import ( "bytes" "crypto/tls" "encoding/json" "errors" "fmt" "io" "net/http" "net/url" "strings" ) // RunTest Executes each individual test case func RunTest(testCase *TestCase) error { var err error var requestUrl string var requestType string var req *http.Request var bodyMap map[string]interface{} tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: testDefinitions.Insecure}, } client := &http.Client{Transport: tr} fmt.Printf("Running test '%s'\n", testCase.Name) // Determine URL if len(testDefinitions.BaseUrl) > 0 { requestUrl, err = url.JoinPath(testDefinitions.BaseUrl, testCase.Path) if err != nil { errMessage := fmt.Sprintf("error combining request URL : '%s'\n", err) return errors.New(errMessage) } } else { requestUrl = testCase.Path } // Populate request body // Get request type, default to GET if len(testCase.Method) == 0 { //return errors.New("no test method specifed, must be either GET or POST") // Assume GET if no method specified requestType = "GET" } else { requestType = testCase.Method } // Create request if len(testCase.Body) > 0 { req, err = http.NewRequest(requestType, requestUrl, bytes.NewBuffer(testCase.Body)) } else { req, err = http.NewRequest(requestType, requestUrl, nil) } if err != nil { errMessage := fmt.Sprintf("error submitting request : '%s'\n", err) return errors.New(errMessage) } // Assemble headers // Global headers first if len(testDefinitions.Headers) > 0 { //fmt.Printf("Adding global headers to request\n") for k, v := range testDefinitions.Headers { // Check for capture tokens that need to be replaced before adding the value key := HeaderReplaceCaptures(k) val := HeaderReplaceCaptures(v) //fmt.Printf("Add global header %s = %s\n", key, val) req.Header.Add(key, val) } } // Then any test case specific headers for k, v := range testCase.Header { // Check for capture tokens that need to be replaced before adding the value key := HeaderReplaceCaptures(k) val := HeaderReplaceCaptures(v) //fmt.Printf("Add header %s = %s\n", key, val) req.Header.Add(key, val) } // Perform request resp, err := client.Do(req) if err != nil { fmt.Println(err) return err } defer resp.Body.Close() // Store response testCase.ResultStatusCode = resp.StatusCode testCase.ResultHeaders = resp.Header fmt.Printf("http_status:\n'%+v'\n", testCase.ResultStatusCode) fmt.Printf("Header response:\n%+v\n", testCase.ResultHeaders) body, err := io.ReadAll(resp.Body) if err != nil { fmt.Println(err) return err } 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{}) } } // Iterate through testDefinitions.CaptureCases and see if there are any that match this test // If we found one, add the appropriate replacement to captureValues for i := range testDefinitions.CaptureCases { if testDefinitions.CaptureCases[i].TestCaseName == testCase.Name { captureData := testDefinitions.CaptureCases[i].CaptureData for k, v := range captureData.Body.Data { //fmt.Printf("Body capture %s = %s\n", k, v) if val, ok := bodyMap[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) } } // Capture anything needed break } } // No errors if we reached this point return nil } // HeaderReplaceCaptures iterates through captureValues to apply any text replacements necessary for input string func HeaderReplaceCaptures(input string) string { for k, v := range captureValues.Data { input = strings.Replace(input, k, v, -1) /* if strings.Contains(input, k) { //fmt.Printf("Found key '%s' in input string '%s', replacing with '%s'\n", k, input, v) } */ } return input }