diff --git a/README.md b/README.md index 2a150ff..ee0846f 100644 --- a/README.md +++ b/README.md @@ -256,8 +256,6 @@ The method `store_respsonse_qjson` takes only **string** as value. This qjson-st ### Get Data from Custom Store The data from the custom store is retrieved using the `datastore `Template function. `key`must be used in any store method before it is requested. If the key is unset, the datastore function returns an empty **string**. Use the special key `-` to return the entire datastore. -You can also use the slice and map notation for getting certain values out of the slice or map directly: `mySlice[3]` would return -the value at index `3` of the slice that is stored with the key `mySlice` in the datastore. ### Get Data from Sequential Store diff --git a/api_testcase.go b/api_testcase.go index d2b40d1..b1c580e 100644 --- a/api_testcase.go +++ b/api_testcase.go @@ -23,9 +23,10 @@ const ( // Case defines the structure of our single testcase // It gets read in by our config reader at the moment the mainfest.json gets parsed type Case struct { - Name string `json:"name"` - RequestData *util.GenericJson `json:"request"` - ResponseData util.GenericJson `json:"response"` + Name string `json:"name"` + RequestData *util.GenericJson `json:"request"` + TypedResponseData *CaseResponse `json:"response"` + responseData util.GenericJson ContinueOnFailure bool `json:"continue_on_failure"` Store map[string]interface{} `json:"store"` // init datastore before testrun StoreResponse map[string]string `json:"store_response_qjson"` // store qjson parsed response in datastore @@ -49,6 +50,11 @@ type Case struct { ServerURL string } +type CaseResponse struct { + Statuscode int `json:"statuscode"` + Body util.GenericJson `json:"body"` +} + func (testCase Case) runAPITestCase() (success bool) { if testCase.LogVerbosity != nil && *testCase.LogVerbosity > FylrConfig.Apitest.LogVerbosity { defer FylrConfig.SetLogVerbosity(FylrConfig.Apitest.LogVerbosity) @@ -63,6 +69,22 @@ func (testCase Case) runAPITestCase() (success bool) { log.Infof(" [%2d] ''", testCase.index) } + //Marshal external datastructure in our internal used reponseData + jsonResponse, err := json.Marshal(testCase.TypedResponseData) + if err != nil { + err = fmt.Errorf("error marshaling TypedResponseData: %s", err) + r.SaveToReportLog(fmt.Sprintf("Error during execution: %s", err)) + log.Errorf(" [%2d] %s", testCase.index, err) + return false + } + err = json.Unmarshal(jsonResponse, &testCase.responseData) + if err != nil { + err = fmt.Errorf("error unmarshaling into responseData: %s", err) + r.SaveToReportLog(fmt.Sprintf("Error during execution: %s", err)) + log.Errorf(" [%2d] %s", testCase.index, err) + return false + } + r.NewChild(testCase.Name) start := time.Now() @@ -74,7 +96,7 @@ func (testCase Case) runAPITestCase() (success bool) { log.Errorf(" [%2d] %s", testCase.index, err) return false } - err := testCase.dataStore.SetMap(testCase.Store) + err = testCase.dataStore.SetMap(testCase.Store) if err != nil { err = fmt.Errorf("error setting datastore map:%s", err) r.SaveToReportLog(fmt.Sprintf("Error during execution: %s", err)) @@ -373,10 +395,10 @@ func (testCase Case) loadRequest() (req api.Request, err error) { func (testCase Case) loadResponse() (res api.Response, err error) { // unspecified response is interpreted as status_code 200 - if testCase.ResponseData == nil { + if testCase.responseData == nil { return api.NewResponse(200, nil, bytes.NewReader([]byte(""))) } - spec, err := testCase.loadResponseSerialization(testCase.ResponseData) + spec, err := testCase.loadResponseSerialization(testCase.responseData) if err != nil { return res, fmt.Errorf("error loading response spec: %s", err) } diff --git a/api_testcase_test.go b/api_testcase_test.go index 77286c4..6870790 100644 --- a/api_testcase_test.go +++ b/api_testcase_test.go @@ -413,62 +413,8 @@ func TestHeaderFromDatastoreWithMap(t *testing.T) { test.runAPITestCase() r.GetTestResult(report.ParseJSONResult) - if r.DidFail() { - t.Errorf("Did fail but it should not") - } - -} - -func TestHeaderFromDatastoreWithSlice(t *testing.T) { - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, `{"Auth": "%s"}`, r.Header.Get("AuthHeader")) - })) - defer ts.Close() - - testManifest := []byte(` - { - "name": "CollectTest", - "request":{ - "endpoint": "suggest", - "method": "GET", - "header_from_store":{ - "authHeader":"hallo[3]" - } - }, - "response":{ - "body": { - "Auth": "es index" - } - } - } -`) - - filesystem.Fs = afero.NewMemMapFs() - afero.WriteFile(filesystem.Fs, "manifest.json", []byte(testManifest), 644) - - r := report.NewReport() - - var test Case - err := json.Unmarshal(testManifest, &test) - if err != nil { - t.Fatal(err) - } - test.reporter = r - test.ServerURL = ts.URL - - test.dataStore = api.NewStore() - test.dataStore.Set("hallo[]", "du index") - test.dataStore.Set("hallo[]", "sie index") - test.dataStore.Set("hallo[]", "er index") - test.dataStore.Set("hallo[]", "es index") - test.dataStore.Set("hallo[]", "mama index") - - test.runAPITestCase() - - r.GetTestResult(report.ParseJSONResult) - if r.DidFail() { - t.Errorf("Did fail but it should not") + if !r.DidFail() { + t.Errorf("Did not fail but it should") } } diff --git a/api_testsuite.go b/api_testsuite.go index 04d58e9..856d777 100644 --- a/api_testsuite.go +++ b/api_testsuite.go @@ -57,11 +57,11 @@ func NewTestSuite( manifest, err := suite.loadManifest() if err != nil { - return suite, fmt.Errorf("error loading manifest: %s. File: %s", err, manifestPath) + return suite, fmt.Errorf("error loading manifest: %s", err) } if err = cjson.Unmarshal(manifest, &suite); err != nil { - return suite, fmt.Errorf("error unmarshaling manifest: %s. File: %s", err, manifestPath) + return suite, fmt.Errorf("error unmarshaling manifest '%s': %s", manifestPath, err) } //Append suite manifest path to name, so we know in an automatic setup where the test is loaded from @@ -70,7 +70,7 @@ func NewTestSuite( // init store err = suite.datastore.SetMap(suite.Store) if err != nil { - err = fmt.Errorf("error setting datastore map: %s. File: %s", err, manifestPath) + err = fmt.Errorf("error setting datastore map:%s", err) } return suite, nil @@ -237,7 +237,7 @@ func (ats Suite) loadManifest() (res []byte, err error) { loader := template.NewLoader(ats.datastore) manifestFile, err := filesystem.Fs.Open(ats.manifestPath) if err != nil { - return res, fmt.Errorf("error opening manifestPath: %s. File: %s", err, ats.manifestPath) + return res, fmt.Errorf("error opening manifestPath: %s", err) } defer manifestFile.Close() diff --git a/lib/api/datastore.go b/lib/api/datastore.go index 51b290f..fd3938f 100644 --- a/lib/api/datastore.go +++ b/lib/api/datastore.go @@ -137,7 +137,7 @@ func (this *Datastore) Set(index string, value interface{}) error { return nil } -func (this Datastore) Get(index string) (res interface{}, err error) { +func (this Datastore) Get(index string) (interface{}, error) { // strings are evalulated as int, so // that we can support "-" notations @@ -146,57 +146,24 @@ func (this Datastore) Get(index string) (res interface{}, err error) { return this.storage, nil } - var dsMapRegex = regexp.MustCompile(`^(.*?)\[(.+?)\]$`) - - if rego := dsMapRegex.FindStringSubmatch(index); len(rego) > 0 { - //we have a map or slice - useIndex := rego[1] - mapIndex := rego[2] - - tmpRes, ok := this.storage[useIndex] - if !ok { - log.Errorf("datastore: key: %s not found.", useIndex) - return "", nil + idx, err := strconv.Atoi(index) + if err == nil { + if idx < 0 { + idx = idx + len(this.responseJson) } - - tmpResMap, ok := tmpRes.(map[string]interface{}) - if ok { - //We have a map - return tmpResMap[mapIndex], nil - } - - tmpResSlice, ok := tmpRes.([]interface{}) - if ok { - //We have a slice - mapIdx, err := strconv.Atoi(mapIndex) - if err != nil { - log.Errorf("datastore: could not convert key to int: %s", mapIndex) - return "", nil - } - - return tmpResSlice[mapIdx], nil + if idx >= len(this.responseJson) || idx < 0 { + // index out of range + return "", DatastoreIndexOutOfBoundsError{error: fmt.Sprintf("datastore.Get: idx out of range: %d, current length: %d", idx, len(this.responseJson))} } + return this.responseJson[idx], nil + } - } else { + res, ok := this.storage[index] - idx, err := strconv.Atoi(index) - if err == nil { - if idx < 0 { - idx = idx + len(this.responseJson) - } - if idx >= len(this.responseJson) || idx < 0 { - // index out of range - return "", DatastoreIndexOutOfBoundsError{error: fmt.Sprintf("datastore.Get: idx out of range: %d, current length: %d", idx, len(this.responseJson))} - } - return this.responseJson[idx], nil - } - var ok bool - res, ok = this.storage[index] - if ok { - return res, nil - } + // logging.Warnf("datastore: %s", store.storage) + if !ok { + // logging.Warnf("datastore: key: %s not found.", index) + return "", nil } - - log.Errorf("datastore: key: %s not found.", index) - return "", nil + return res, nil }