diff options
author | HÃ¥kon Hallingstad <hakon@verizonmedia.com> | 2021-11-24 11:20:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-24 11:20:03 +0100 |
commit | bdd3bf47dde7a047f77dc2832ab7c92ba629e54e (patch) | |
tree | a82de9353a84053d05d429d5e353d5e6899763f2 /client | |
parent | a0e159641f8361ee2fc1b39836b8a8f9364e9e3d (diff) | |
parent | 189a392bc8fc18f8c7ac80a89c6deb741e66a1a6 (diff) |
Merge pull request #20181 from vespa-engine/revert-20098-jonmv/vespa-cli-test-runner
Revert "Allow overriding creds paths, and add dummy test command"
Diffstat (limited to 'client')
27 files changed, 28 insertions, 1069 deletions
diff --git a/client/go/cmd/config.go b/client/go/cmd/config.go index 966080dbdc2..750664e51b1 100644 --- a/client/go/cmd/config.go +++ b/client/go/cmd/config.go @@ -133,16 +133,10 @@ func (c *Config) Write() error { } func (c *Config) CertificatePath(app vespa.ApplicationID) (string, error) { - if override, ok := os.LookupEnv("VESPA_CLI_DATA_PLANE_CERT_FILE"); ok { - return override, nil - } return c.applicationFilePath(app, "data-plane-public-cert.pem") } func (c *Config) PrivateKeyPath(app vespa.ApplicationID) (string, error) { - if override, ok := os.LookupEnv("VESPA_CLI_DATA_PLANE_KEY_FILE"); ok { - return override, nil - } return c.applicationFilePath(app, "data-plane-private-key.pem") } diff --git a/client/go/cmd/curl.go b/client/go/cmd/curl.go index 2496ddc3abc..bd9fad1b47e 100644 --- a/client/go/cmd/curl.go +++ b/client/go/cmd/curl.go @@ -46,7 +46,7 @@ $ vespa curl -t local -- -v /search/?yql=query fatalErr(err) return } - service := getService("query", 0, "") + service := getService("query", 0) url := joinURL(service.BaseURL, args[len(args)-1]) rawArgs := args[:len(args)-1] c, err := curl.RawArgs(url, rawArgs...) diff --git a/client/go/cmd/document.go b/client/go/cmd/document.go index 84c384e701e..cd0170684cf 100644 --- a/client/go/cmd/document.go +++ b/client/go/cmd/document.go @@ -118,7 +118,7 @@ var documentGetCmd = &cobra.Command{ }, } -func documentService() *vespa.Service { return getService("document", 0, "") } +func documentService() *vespa.Service { return getService("document", 0) } func operationOptions() vespa.OperationOptions { return vespa.OperationOptions{ diff --git a/client/go/cmd/document_test.go b/client/go/cmd/document_test.go index f3a5fbe9543..649aca8703a 100644 --- a/client/go/cmd/document_test.go +++ b/client/go/cmd/document_test.go @@ -161,5 +161,5 @@ func assertDocumentServerError(t *testing.T, status int, errorMessage string) { } func documentServiceURL(client *mockHttpClient) string { - return getService("document", 0, "").BaseURL + return getService("document", 0).BaseURL } diff --git a/client/go/cmd/helpers.go b/client/go/cmd/helpers.go index 89ea87f198e..79ba1fcef26 100644 --- a/client/go/cmd/helpers.go +++ b/client/go/cmd/helpers.go @@ -6,7 +6,6 @@ package cmd import ( "crypto/tls" - "encoding/json" "fmt" "io/ioutil" "log" @@ -130,21 +129,19 @@ func getTargetType() string { return target } -func getService(service string, sessionOrRunID int64, cluster string) *vespa.Service { +func getService(service string, sessionOrRunID int64) *vespa.Service { t := getTarget() timeout := time.Duration(waitSecsArg) * time.Second if timeout > 0 { log.Printf("Waiting up to %d %s for service to become available ...", color.Cyan(waitSecsArg), color.Cyan("seconds")) } - s, err := t.Service(service, timeout, sessionOrRunID, cluster) + s, err := t.Service(service, timeout, sessionOrRunID) if err != nil { fatalErr(err, "Invalid service: ", service) } return s } -func getEndpointsOverride() string { return os.Getenv("VESPA_CLI_ENDPOINTS") } - func getSystem() string { return os.Getenv("VESPA_CLI_CLOUD_SYSTEM") } func getSystemName() string { @@ -178,17 +175,15 @@ func getTarget() vespa.Target { case "local": return vespa.LocalTarget() case "cloud": + deployment := deploymentFromArgs() cfg, err := LoadConfig() if err != nil { fatalErr(err, "Could not load config") return nil } - deployment := deploymentFromArgs() - endpoints := getEndpointsFromEnv() - var apiKey []byte = nil apiKey, err = ioutil.ReadFile(cfg.APIKeyPath(deployment.Application.Tenant)) - if !vespa.Auth0AccessTokenEnabled() && endpoints == nil { + if !vespa.Auth0AccessTokenEnabled() { if err != nil { fatalErrHint(err, "Deployment to cloud requires an API key. Try 'vespa api-key'") } @@ -233,15 +228,14 @@ func getTarget() vespa.Target { }, cfg.AuthConfigPath(), getSystemName(), - cloudAuth, - endpoints) + cloudAuth) } fatalErrHint(fmt.Errorf("Invalid target: %s", targetType), "Valid targets are 'local', 'cloud' or an URL") return nil } func waitForService(service string, sessionOrRunID int64) { - s := getService(service, sessionOrRunID, "") + s := getService(service, sessionOrRunID) timeout := time.Duration(waitSecsArg) * time.Second if timeout > 0 { log.Printf("Waiting up to %d %s for service to become ready ...", color.Cyan(waitSecsArg), color.Cyan("seconds")) @@ -277,32 +271,3 @@ func getDeploymentOpts(cfg *Config, pkg vespa.ApplicationPackage, target vespa.T } return opts } - -func getEndpointsFromEnv() map[string]string { - endpointsString := getEndpointsOverride() - if endpointsString == "" { - return nil - } - - var endpoints endpoints - urlsByCluster := make(map[string]string) - if err := json.Unmarshal([]byte(endpointsString), &endpoints); err != nil { - fatalErrHint(err, "Endpoints must be valid JSON") - } - if len(endpoints.Endpoints) == 0 { - fatalErr(fmt.Errorf("endpoints must be non-empty")) - } - for _, endpoint := range endpoints.Endpoints { - urlsByCluster[endpoint.Cluster] = endpoint.URL - } - return urlsByCluster -} - -type endpoints struct { - Endpoints []endpoint `json:"endpoints"` -} - -type endpoint struct { - Cluster string `json:"cluster"` - URL string `json:"url"` -} diff --git a/client/go/cmd/query.go b/client/go/cmd/query.go index 6638c275330..76688438fb4 100644 --- a/client/go/cmd/query.go +++ b/client/go/cmd/query.go @@ -39,7 +39,7 @@ can be set by the syntax [parameter-name]=[value].`, } func query(arguments []string) { - service := getService("query", 0, "") + service := getService("query", 0) url, _ := url.Parse(service.BaseURL + "/search/") urlQuery := url.Query() for i := 0; i < len(arguments); i++ { diff --git a/client/go/cmd/query_test.go b/client/go/cmd/query_test.go index 55046ae49ba..ec6c3063906 100644 --- a/client/go/cmd/query_test.go +++ b/client/go/cmd/query_test.go @@ -75,5 +75,5 @@ func assertQueryServiceError(t *testing.T, status int, errorMessage string) { } func queryServiceURL(client *mockHttpClient) string { - return getService("query", 0, "").BaseURL + return getService("query", 0).BaseURL } diff --git a/client/go/cmd/test.go b/client/go/cmd/test.go deleted file mode 100644 index 4c6d9ec265d..00000000000 --- a/client/go/cmd/test.go +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -// vespa test command -// Author: jonmv - -package cmd - -import ( - "bytes" - "encoding/json" - "fmt" - "github.com/spf13/cobra" - "github.com/vespa-engine/vespa/client/go/util" - "github.com/vespa-engine/vespa/client/go/vespa" - "io/ioutil" - "math" - "net/http" - "net/url" - "os" - "path" - "path/filepath" - "strings" - "time" -) - -func init() { - rootCmd.AddCommand(testCmd) -} - -// TODO: add link to test doc at cloud.vespa.ai -var testCmd = &cobra.Command{ - Use: "test [tests directory or test file]", - Short: "Run a test suite, or a single test", - Long: `Run a test suite, or a single test - -Runs all JSON test files in the specified directory, or the single JSON -test file specified. - -If no directory or file is specified, the working directory is used instead.`, - Example: `$ vespa test src/test/application/tests/system-test -$ vespa test src/test/application/tests/system-test/feed-and-query.json`, - Args: cobra.MaximumNArgs(1), - DisableAutoGenTag: true, - Run: func(cmd *cobra.Command, args []string) { - target := getTarget() - testPath := "." - if len(args) > 0 { - testPath = args[0] - } - if count, failed := runTests(testPath, target); len(failed) != 0 { - fmt.Fprintf(stdout, "\nFailed %d of %d tests:\n", len(failed), count) - for _, test := range failed { - fmt.Fprintln(stdout, test) - } - exitFunc(3) - } else if count == 0 { - fmt.Fprintf(stdout, "Failed to find any tests at '%v'\n", testPath) - exitFunc(3) - } else { - fmt.Fprintf(stdout, "%d tests completed successfully\n", count) - } - }, -} - -func runTests(rootPath string, target vespa.Target) (int, []string) { - count := 0 - failed := make([]string, 0) - if stat, err := os.Stat(rootPath); err != nil { - fatalErr(err, "Failed reading specified test path") - } else if stat.IsDir() { - tests, err := os.ReadDir(rootPath) - if err != nil { - fatalErr(err, "Failed reading specified test directory") - } - for _, test := range tests { - if !test.IsDir() && filepath.Ext(test.Name()) == ".json" { - testPath := path.Join(rootPath, test.Name()) - failure := runTest(testPath, target) - if failure != "" { - failed = append(failed, failure) - } - count++ - } - } - } else if strings.HasSuffix(stat.Name(), ".json") { - failure := runTest(rootPath, target) - if failure != "" { - failed = append(failed, failure) - } - count++ - } - return count, failed -} - -// Runs the test at the given path, and returns the specified test name if the test fails -func runTest(testPath string, target vespa.Target) string { - var test test - testBytes, err := ioutil.ReadFile(testPath) - if err != nil { - fatalErr(err, fmt.Sprintf("Failed to read test file at '%s'", testPath)) - } - if err = json.Unmarshal(testBytes, &test); err != nil { - fatalErr(err, fmt.Sprintf("Failed to parse test file at '%s", testPath)) - } - - testName := test.Name - if test.Name == "" { - testName = testPath - } - fmt.Fprintf(stdout, "Running %s:", testName) - - defaultParameters, err := getParameters(test.Defaults.ParametersRaw, path.Dir(testPath)) - if err != nil { - fatalErr(err, fmt.Sprintf("Invalid default parameters for '%s'", testName)) - } - - if len(test.Assertions) == 0 { - fatalErr(fmt.Errorf("a test must have at least one assertion, but none were found in '%s'", testPath)) - } - for i, assertion := range test.Assertions { - assertionName := assertion.Name - if assertionName == "" { - assertionName = fmt.Sprintf("assertion %d", i) - } - failure, err := verify(assertion, path.Dir(testPath), test.Defaults.Cluster, defaultParameters, target) - if err != nil { - fatalErr(err, fmt.Sprintf("\nError verifying %s", assertionName)) - } - if failure != "" { - fmt.Fprintf(stdout, "\nFailed verifying %s:\n%s\n", assertionName, failure) - return fmt.Sprintf("%v: %v", testName, assertionName) - } - if i == 0 { - fmt.Fprintf(stdout, " ") - } - fmt.Fprint(stdout, ".") - } - fmt.Fprintln(stdout, " OK!") - return "" -} - -// Asserts specified response is obtained for request, or returns a failure message, or an error if this fails -func verify(assertion assertion, testsPath string, defaultCluster string, defaultParameters map[string]string, target vespa.Target) (string, error) { - requestBody, err := getBody(assertion.Request.BodyRaw, testsPath) - if err != nil { - return "", err - } - - parameters, err := getParameters(assertion.Request.ParametersRaw, testsPath) - if err != nil { - return "", err - } - for name, value := range defaultParameters { - if _, present := parameters[name]; !present { - parameters[name] = value - } - } - - cluster := assertion.Request.Cluster - if cluster == "" { - cluster = defaultCluster - } - - service, err := target.Service("query", 0, 0, cluster) - if err != nil { - return "", err - } - - method := assertion.Request.Method - if method == "" { - method = "GET" - } - - pathAndQuery := assertion.Request.URI - if pathAndQuery == "" { - pathAndQuery = "/search/" - } - requestUrl, err := url.ParseRequestURI(service.BaseURL + pathAndQuery) - if err != nil { - return "", err - } - query := requestUrl.Query() - for name, value := range parameters { - query.Add(name, value) - } - requestUrl.RawQuery = query.Encode() - - header := http.Header{} - header.Add("Content-Type", "application/json") // TODO: Not guaranteed to be true ... - - request := &http.Request{ - URL: requestUrl, - Method: method, - Header: header, - Body: ioutil.NopCloser(bytes.NewReader(requestBody)), - } - defer request.Body.Close() - - response, err := service.Do(request, 600*time.Second) // Vespa should provide a response within the given request timeout - if err != nil { - return "", err - } - defer response.Body.Close() - - statusCode := assertion.Response.Code - if statusCode == 0 { - statusCode = 200 - } - if statusCode != response.StatusCode { - return fmt.Sprintf("Expected status code (%d) does not match actual (%d). Response body:\n%s", statusCode, response.StatusCode, util.ReaderToJSON(response.Body)), nil - } - - responseBodySpecBytes, err := getBody(assertion.Response.BodyRaw, testsPath) - if err != nil { - return "", err - } - if responseBodySpecBytes == nil { - return "", nil - } - var responseBodySpec interface{} - err = json.Unmarshal(responseBodySpecBytes, &responseBodySpec) - if err != nil { - return "", err - } - - responseBodyBytes, err := ioutil.ReadAll(response.Body) - if err != nil { - return "", err - } - var responseBody interface{} - err = json.Unmarshal(responseBodyBytes, &responseBody) - if err != nil { - return "", fmt.Errorf("got non-JSON response; %w:\n%s", err, string(responseBodyBytes)) - } - - failure, err := compare(responseBodySpec, responseBody, "") - if failure != "" { - responsePretty, _ := json.MarshalIndent(responseBody, "", " ") - failure = failure + " Response body:\n" + string(responsePretty) - } - return failure, err -} - -func compare(expected interface{}, actual interface{}, path string) (string, error) { - typeMatch := false - valueMatch := false - switch u := expected.(type) { - case nil: - typeMatch = actual == nil - valueMatch = actual == nil - case bool: - v, ok := actual.(bool) - typeMatch = ok - valueMatch = ok && u == v - case float64: - v, ok := actual.(float64) - typeMatch = ok - valueMatch = ok && math.Abs(u-v) < 1e-9 - case string: - v, ok := actual.(string) - typeMatch = ok - valueMatch = ok && (u == v) - case []interface{}: - v, ok := actual.([]interface{}) - typeMatch = ok - if ok { - if len(u) == len(v) { - for i, e := range u { - result, err := compare(e, v[i], fmt.Sprintf("%s/%d", path, i)) - if result != "" || err != nil { - return result, err - } - } - valueMatch = true - } else { - return fmt.Sprintf("Expected number of elements at %s (%d) does not match actual (%d).", path, len(u), len(v)), nil - } - } - case map[string]interface{}: - v, ok := actual.(map[string]interface{}) - typeMatch = ok - if ok { - for n, e := range u { - childPath := fmt.Sprintf("%s/%s", path, strings.ReplaceAll(strings.ReplaceAll(n, "~", "~0"), "/", "~1")) - f, ok := v[n] - if !ok { - return fmt.Sprintf("Expected field at %s not present in actual data.", childPath), nil - } - result, err := compare(e, f, childPath) - if result != "" || err != nil { - return result, err - } - } - valueMatch = true - } - default: - return "", fmt.Errorf("unexpected expected JSON type for value '%v'", expected) - } - - if !(typeMatch && valueMatch) { - if path == "" { - path = "root" - } - expectedJson, _ := json.MarshalIndent(expected, "", " ") - actualJson, _ := json.MarshalIndent(actual, "", " ") - return fmt.Sprintf("Expected JSON at %s (%s) does not match actual (%s).", path, expectedJson, actualJson), nil - } - return "", nil -} - -func getParameters(parametersRaw []byte, testsPath string) (map[string]string, error) { - if parametersRaw != nil { - var parametersPath string - if err := json.Unmarshal(parametersRaw, ¶metersPath); err == nil { - resolvedParametersPath := path.Join(testsPath, parametersPath) - parametersRaw, err = ioutil.ReadFile(resolvedParametersPath) - if err != nil { - fatalErr(err, fmt.Sprintf("Failed to read request parameters file at '%s'", resolvedParametersPath)) - } - } - var parameters map[string]string - if err := json.Unmarshal(parametersRaw, ¶meters); err != nil { - return nil, fmt.Errorf("request parameters must be JSON with only string values: %w", err) - } - return parameters, nil - } - return make(map[string]string), nil -} - -func getBody(bodyRaw []byte, testsPath string) ([]byte, error) { - var bodyPath string - if err := json.Unmarshal(bodyRaw, &bodyPath); err == nil { - resolvedBodyPath := path.Join(testsPath, bodyPath) - bodyRaw, err = ioutil.ReadFile(resolvedBodyPath) - if err != nil { - fatalErr(err, fmt.Sprintf("Failed to read body file at '%s'", resolvedBodyPath)) - } - } - return bodyRaw, nil -} - -type test struct { - Name string `json:"name"` - Defaults defaults `json:"defaults"` - Assertions []assertion `json:"assertions"` -} - -type defaults struct { - Cluster string `json:"cluster"` - ParametersRaw json.RawMessage `json:"parameters"` -} - -type assertion struct { - Name string `json:"name"` - Request request `json:"request"` - Response response `json:"response"` -} - -type request struct { - Cluster string `json:"cluster"` - Method string `json:"method"` - URI string `json:"uri"` - ParametersRaw json.RawMessage `json:"parameters"` - BodyRaw json.RawMessage `json:"body"` -} - -type response struct { - Code int `json:"code"` - BodyRaw json.RawMessage `json:"body"` -} diff --git a/client/go/cmd/test_test.go b/client/go/cmd/test_test.go deleted file mode 100644 index 9d92e285750..00000000000 --- a/client/go/cmd/test_test.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -// test command tests -// Author: jonmv - -package cmd - -import ( - "github.com/vespa-engine/vespa/client/go/util" - "github.com/vespa-engine/vespa/client/go/vespa" - "io/ioutil" - "net/http" - "net/url" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestSuite(t *testing.T) { - client := &mockHttpClient{} - searchResponse, _ := ioutil.ReadFile("testdata/tests/response.json") - client.NextStatus(200) - client.NextStatus(200) - for i := 0; i < 9; i++ { - client.NextResponse(200, string(searchResponse)) - } - - expectedBytes, _ := ioutil.ReadFile("testdata/tests/expected-suite.out") - outBytes, errBytes := execute(command{args: []string{"test", "testdata/tests/system-test"}}, t, client) - assert.Equal(t, string(expectedBytes), outBytes) - assert.Equal(t, "", errBytes) - - baseUrl := "http://127.0.0.1:8080" - urlWithQuery := baseUrl + "/search/?presentation.timing=true&query=artist%3A+foo&timeout=3.4s" - requests := []*http.Request{createFeedRequest(baseUrl), createFeedRequest(baseUrl), createSearchRequest(urlWithQuery), createSearchRequest(urlWithQuery)} - for i := 0; i < 7; i++ { - requests = append(requests, createSearchRequest(baseUrl+"/search/")) - } - assertRequests(requests, client, t) -} - -func TestTestWithoutAssertions(t *testing.T) { - client := &mockHttpClient{} - _, errBytes := execute(command{args: []string{"test", "testdata/tests/system-test/foo/query.json"}}, t, client) - assert.Equal(t, "a test must have at least one assertion, but none were found in 'testdata/tests/system-test/foo/query.json'\n", errBytes) -} - -func TestSuiteWithoutTests(t *testing.T) { - client := &mockHttpClient{} - outBytes, errBytes := execute(command{args: []string{"test", "testdata/tests/staging-test"}}, t, client) - assert.Equal(t, "Failed to find any tests at 'testdata/tests/staging-test'\n", outBytes) - assert.Equal(t, "", errBytes) -} - -func TestSingleTest(t *testing.T) { - client := &mockHttpClient{} - searchResponse, _ := ioutil.ReadFile("testdata/tests/response.json") - client.NextStatus(200) - client.NextStatus(200) - client.NextResponse(200, string(searchResponse)) - client.NextResponse(200, string(searchResponse)) - - expectedBytes, _ := ioutil.ReadFile("testdata/tests/expected.out") - outBytes, errBytes := execute(command{args: []string{"test", "testdata/tests/system-test/test.json"}}, t, client) - assert.Equal(t, string(expectedBytes), outBytes) - assert.Equal(t, "", errBytes) - - baseUrl := "http://127.0.0.1:8080" - rawUrl := baseUrl + "/search/?presentation.timing=true&query=artist%3A+foo&timeout=3.4s" - assertRequests([]*http.Request{createFeedRequest(baseUrl), createFeedRequest(baseUrl), createSearchRequest(rawUrl), createSearchRequest(rawUrl)}, client, t) -} - -func TestSingleTestWithCloudAndEndpoints(t *testing.T) { - cmd := command{args: []string{"test", "testdata/tests/system-test/test.json", "-t", "cloud", "-a", "t.a.i"}} - cmd.homeDir = filepath.Join(t.TempDir(), ".vespa") - os.MkdirAll(cmd.homeDir, 0700) - keyFile := filepath.Join(cmd.homeDir, "key") - certFile := filepath.Join(cmd.homeDir, "cert") - - os.Setenv("VESPA_CLI_DATA_PLANE_KEY_FILE", keyFile) - os.Setenv("VESPA_CLI_DATA_PLANE_CERT_FILE", certFile) - os.Setenv("VESPA_CLI_ENDPOINTS", "{\"endpoints\":[{\"cluster\":\"container\",\"url\":\"https://url\"}]}") - - kp, _ := vespa.CreateKeyPair() - ioutil.WriteFile(keyFile, kp.PrivateKey, 0600) - ioutil.WriteFile(certFile, kp.Certificate, 0600) - - client := &mockHttpClient{} - searchResponse, _ := ioutil.ReadFile("testdata/tests/response.json") - client.NextStatus(200) - client.NextStatus(200) - client.NextResponse(200, string(searchResponse)) - client.NextResponse(200, string(searchResponse)) - - expectedBytes, _ := ioutil.ReadFile("testdata/tests/expected.out") - outBytes, errBytes := execute(cmd, t, client) - assert.Equal(t, string(expectedBytes), outBytes) - assert.Equal(t, "", errBytes) - - baseUrl := "https://url" - rawUrl := baseUrl + "/search/?presentation.timing=true&query=artist%3A+foo&timeout=3.4s" - assertRequests([]*http.Request{createFeedRequest(baseUrl), createFeedRequest(baseUrl), createSearchRequest(rawUrl), createSearchRequest(rawUrl)}, client, t) -} - -func createFeedRequest(urlPrefix string) *http.Request { - return createRequest("POST", - urlPrefix+"/document/v1/test/music/docid/doc?timeout=3.4s", - "{\"fields\":{\"artist\":\"Foo Fighters\"}}") -} - -func createSearchRequest(rawUrl string) *http.Request { - return createRequest("GET", rawUrl, "") -} - -func createRequest(method string, uri string, body string) *http.Request { - requestUrl, _ := url.ParseRequestURI(uri) - return &http.Request{ - URL: requestUrl, - Method: method, - Header: nil, - Body: ioutil.NopCloser(strings.NewReader(body)), - } -} - -func assertRequests(requests []*http.Request, client *mockHttpClient, t *testing.T) { - if assert.Equal(t, len(requests), len(client.requests)) { - for i, e := range requests { - a := client.requests[i] - assert.Equal(t, e.URL.String(), a.URL.String()) - assert.Equal(t, e.Method, a.Method) - assert.Equal(t, util.ReaderToJSON(e.Body), util.ReaderToJSON(a.Body)) - } - } -} diff --git a/client/go/cmd/testdata/tests/body.json b/client/go/cmd/testdata/tests/body.json deleted file mode 100644 index 767330b1a2d..00000000000 --- a/client/go/cmd/testdata/tests/body.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "root": { - "id": "toplevel", - "coverage": { - "full": true - }, - "fields": { - "totalCount" : 1 - }, - "children": [{}] - } -}
\ No newline at end of file diff --git a/client/go/cmd/testdata/tests/expected-suite.out b/client/go/cmd/testdata/tests/expected-suite.out deleted file mode 100644 index 0fb8b897f4f..00000000000 --- a/client/go/cmd/testdata/tests/expected-suite.out +++ /dev/null @@ -1,269 +0,0 @@ -Running testdata/tests/system-test/test.json: .... OK! -Running testdata/tests/system-test/wrong-bool-value.json: -Failed verifying assertion 0: -Expected JSON at /root/coverage/full (false) does not match actual (true). Response body: -{ - "root": { - "children": [ - { - "fields": { - "artist": "Foo Fighters", - "documentid": "id:test:music::doc", - "sddocname": "music" - }, - "id": "id:test:music::doc", - "relevance": 0.38186238359951247, - "source": "music" - } - ], - "coverage": { - "coverage": 100, - "documents": 1, - "full": true, - "nodes": 1, - "results": 1, - "resultsFull": 1 - }, - "fields": { - "totalCount": 1 - }, - "id": "toplevel", - "relevance": 1 - }, - "timing": { - "querytime": 0.003, - "searchtime": 0.004, - "summaryfetchtime": 0 - } -} -Running testdata/tests/system-test/wrong-element-count.json: -Failed verifying assertion 0: -Expected number of elements at /root/children (0) does not match actual (1). Response body: -{ - "root": { - "children": [ - { - "fields": { - "artist": "Foo Fighters", - "documentid": "id:test:music::doc", - "sddocname": "music" - }, - "id": "id:test:music::doc", - "relevance": 0.38186238359951247, - "source": "music" - } - ], - "coverage": { - "coverage": 100, - "documents": 1, - "full": true, - "nodes": 1, - "results": 1, - "resultsFull": 1 - }, - "fields": { - "totalCount": 1 - }, - "id": "toplevel", - "relevance": 1 - }, - "timing": { - "querytime": 0.003, - "searchtime": 0.004, - "summaryfetchtime": 0 - } -} -Running testdata/tests/system-test/wrong-field-name.json: -Failed verifying assertion 0: -Expected field at /root/fields/totalCountDracula not present in actual data. Response body: -{ - "root": { - "children": [ - { - "fields": { - "artist": "Foo Fighters", - "documentid": "id:test:music::doc", - "sddocname": "music" - }, - "id": "id:test:music::doc", - "relevance": 0.38186238359951247, - "source": "music" - } - ], - "coverage": { - "coverage": 100, - "documents": 1, - "full": true, - "nodes": 1, - "results": 1, - "resultsFull": 1 - }, - "fields": { - "totalCount": 1 - }, - "id": "toplevel", - "relevance": 1 - }, - "timing": { - "querytime": 0.003, - "searchtime": 0.004, - "summaryfetchtime": 0 - } -} -Running testdata/tests/system-test/wrong-float-value.json: -Failed verifying assertion 0: -Expected JSON at /root/children/0/relevance (0.381862373599) does not match actual (0.38186238359951247). Response body: -{ - "root": { - "children": [ - { - "fields": { - "artist": "Foo Fighters", - "documentid": "id:test:music::doc", - "sddocname": "music" - }, - "id": "id:test:music::doc", - "relevance": 0.38186238359951247, - "source": "music" - } - ], - "coverage": { - "coverage": 100, - "documents": 1, - "full": true, - "nodes": 1, - "results": 1, - "resultsFull": 1 - }, - "fields": { - "totalCount": 1 - }, - "id": "toplevel", - "relevance": 1 - }, - "timing": { - "querytime": 0.003, - "searchtime": 0.004, - "summaryfetchtime": 0 - } -} -Running testdata/tests/system-test/wrong-int-value.json: -Failed verifying assertion 0: -Expected JSON at /root/fields/totalCount (2) does not match actual (1). Response body: -{ - "root": { - "children": [ - { - "fields": { - "artist": "Foo Fighters", - "documentid": "id:test:music::doc", - "sddocname": "music" - }, - "id": "id:test:music::doc", - "relevance": 0.38186238359951247, - "source": "music" - } - ], - "coverage": { - "coverage": 100, - "documents": 1, - "full": true, - "nodes": 1, - "results": 1, - "resultsFull": 1 - }, - "fields": { - "totalCount": 1 - }, - "id": "toplevel", - "relevance": 1 - }, - "timing": { - "querytime": 0.003, - "searchtime": 0.004, - "summaryfetchtime": 0 - } -} -Running testdata/tests/system-test/wrong-null-value.json: -Failed verifying assertion 0: -Expected field at /boot not present in actual data. Response body: -{ - "root": { - "children": [ - { - "fields": { - "artist": "Foo Fighters", - "documentid": "id:test:music::doc", - "sddocname": "music" - }, - "id": "id:test:music::doc", - "relevance": 0.38186238359951247, - "source": "music" - } - ], - "coverage": { - "coverage": 100, - "documents": 1, - "full": true, - "nodes": 1, - "results": 1, - "resultsFull": 1 - }, - "fields": { - "totalCount": 1 - }, - "id": "toplevel", - "relevance": 1 - }, - "timing": { - "querytime": 0.003, - "searchtime": 0.004, - "summaryfetchtime": 0 - } -} -Running testdata/tests/system-test/wrong-string-value.json: -Failed verifying assertion 0: -Expected JSON at /root/children/0/fields/artist ("Boo Fighters") does not match actual ("Foo Fighters"). Response body: -{ - "root": { - "children": [ - { - "fields": { - "artist": "Foo Fighters", - "documentid": "id:test:music::doc", - "sddocname": "music" - }, - "id": "id:test:music::doc", - "relevance": 0.38186238359951247, - "source": "music" - } - ], - "coverage": { - "coverage": 100, - "documents": 1, - "full": true, - "nodes": 1, - "results": 1, - "resultsFull": 1 - }, - "fields": { - "totalCount": 1 - }, - "id": "toplevel", - "relevance": 1 - }, - "timing": { - "querytime": 0.003, - "searchtime": 0.004, - "summaryfetchtime": 0 - } -} - -Failed 7 of 8 tests: -testdata/tests/system-test/wrong-bool-value.json: assertion 0 -testdata/tests/system-test/wrong-element-count.json: assertion 0 -testdata/tests/system-test/wrong-field-name.json: assertion 0 -testdata/tests/system-test/wrong-float-value.json: assertion 0 -testdata/tests/system-test/wrong-int-value.json: assertion 0 -testdata/tests/system-test/wrong-null-value.json: assertion 0 -testdata/tests/system-test/wrong-string-value.json: assertion 0 diff --git a/client/go/cmd/testdata/tests/expected.out b/client/go/cmd/testdata/tests/expected.out deleted file mode 100644 index f012ee30e95..00000000000 --- a/client/go/cmd/testdata/tests/expected.out +++ /dev/null @@ -1,2 +0,0 @@ -Running testdata/tests/system-test/test.json: .... OK! -1 tests completed successfully diff --git a/client/go/cmd/testdata/tests/response.json b/client/go/cmd/testdata/tests/response.json deleted file mode 100644 index 48368b935a8..00000000000 --- a/client/go/cmd/testdata/tests/response.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "root": { - "children": [ - { - "fields": { - "artist": "Foo Fighters", - "documentid": "id:test:music::doc", - "sddocname": "music" - }, - "id": "id:test:music::doc", - "relevance": 0.38186238359951247, - "source": "music" - } - ], - "coverage": { - "coverage": 100, - "documents": 1, - "full": true, - "nodes": 1, - "results": 1, - "resultsFull": 1 - }, - "fields": { - "totalCount": 1 - }, - "id": "toplevel", - "relevance": 1 - }, - "timing": { - "querytime": 0.003, - "searchtime": 0.004, - "summaryfetchtime": 0 - } -}
\ No newline at end of file diff --git a/client/go/cmd/testdata/tests/staging-test/not-json b/client/go/cmd/testdata/tests/staging-test/not-json deleted file mode 100644 index b6fc4c620b6..00000000000 --- a/client/go/cmd/testdata/tests/staging-test/not-json +++ /dev/null @@ -1 +0,0 @@ -hello
\ No newline at end of file diff --git a/client/go/cmd/testdata/tests/system-test/foo/body.json b/client/go/cmd/testdata/tests/system-test/foo/body.json deleted file mode 100644 index 0bbf626eafe..00000000000 --- a/client/go/cmd/testdata/tests/system-test/foo/body.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "fields": { - "artist": "Foo Fighters" - } -}
\ No newline at end of file diff --git a/client/go/cmd/testdata/tests/system-test/foo/query.json b/client/go/cmd/testdata/tests/system-test/foo/query.json deleted file mode 100644 index 25b8c5b0039..00000000000 --- a/client/go/cmd/testdata/tests/system-test/foo/query.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "query": "artist: foo" -} diff --git a/client/go/cmd/testdata/tests/system-test/test.json b/client/go/cmd/testdata/tests/system-test/test.json deleted file mode 100644 index 5aac76d29ff..00000000000 --- a/client/go/cmd/testdata/tests/system-test/test.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "defaults": { - "cluster": "container", - "parameters": { - "timeout": "3.4s" - } - }, - "assertions": [ - { - "name": "feed music", - "request": { - "method": "POST", - "body": "foo/body.json", - "uri": "/document/v1/test/music/docid/doc" - } - }, - { - "name": "re-feed music", - "request": { - "method": "POST", - "body": { - "fields": { - "artist": "Foo Fighters" - } - }, - "uri": "/document/v1/test/music/docid/doc" - } - }, - { - "name": "query for foo", - "request": { - "uri": "/search/?presentation.timing=true", - "parameters": { - "query": "artist: foo" - } - }, - "response": { - "code": 200, - "body": "../body.json" - } - }, - { - "name": "query for foo again", - "request": { - "uri": "/search/?presentation.timing=true", - "parameters": "foo/query.json" - }, - "response": { - "body": { - "root": { - "children": [ - { - "fields": { - "artist": "Foo Fighters" - }, - "relevance": 0.381862383599 - } - ] - } - } - } - } - ] -} diff --git a/client/go/cmd/testdata/tests/system-test/wrong-bool-value.json b/client/go/cmd/testdata/tests/system-test/wrong-bool-value.json deleted file mode 100644 index ae6f9de8de8..00000000000 --- a/client/go/cmd/testdata/tests/system-test/wrong-bool-value.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "assertions": [ - { - "response": { - "body": { - "root": { - "coverage": { - "full": false - } - } - } - } - } - ] -} diff --git a/client/go/cmd/testdata/tests/system-test/wrong-element-count.json b/client/go/cmd/testdata/tests/system-test/wrong-element-count.json deleted file mode 100644 index 77c687fa919..00000000000 --- a/client/go/cmd/testdata/tests/system-test/wrong-element-count.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "assertions": [ - { - "response": { - "body": { - "root": { - "children": [] - } - } - } - } - ] -} diff --git a/client/go/cmd/testdata/tests/system-test/wrong-field-name.json b/client/go/cmd/testdata/tests/system-test/wrong-field-name.json deleted file mode 100644 index d020141ed12..00000000000 --- a/client/go/cmd/testdata/tests/system-test/wrong-field-name.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "assertions": [ - { - "response": { - "body": { - "root": { - "fields": { - "totalCountDracula" : 1 - } - } - } - } - } - ] -} diff --git a/client/go/cmd/testdata/tests/system-test/wrong-float-value.json b/client/go/cmd/testdata/tests/system-test/wrong-float-value.json deleted file mode 100644 index 804f2582176..00000000000 --- a/client/go/cmd/testdata/tests/system-test/wrong-float-value.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "assertions": [ - { - "response": { - "body": { - "root": { - "children": [ - { - "relevance": 0.381862373599 - } - ] - } - } - } - } - ] -} diff --git a/client/go/cmd/testdata/tests/system-test/wrong-int-value.json b/client/go/cmd/testdata/tests/system-test/wrong-int-value.json deleted file mode 100644 index 3cbf8acd1d8..00000000000 --- a/client/go/cmd/testdata/tests/system-test/wrong-int-value.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "assertions": [ - { - "response": { - "body": { - "root": { - "fields": { - "totalCount" : 2 - } - } - } - } - } - ] -} diff --git a/client/go/cmd/testdata/tests/system-test/wrong-null-value.json b/client/go/cmd/testdata/tests/system-test/wrong-null-value.json deleted file mode 100644 index 11425df7ad4..00000000000 --- a/client/go/cmd/testdata/tests/system-test/wrong-null-value.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "assertions": [ - { - "response": { - "body": { - "boot": null - } - } - } - ] -} diff --git a/client/go/cmd/testdata/tests/system-test/wrong-string-value.json b/client/go/cmd/testdata/tests/system-test/wrong-string-value.json deleted file mode 100644 index 2cf0a5fdb38..00000000000 --- a/client/go/cmd/testdata/tests/system-test/wrong-string-value.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "assertions": [ - { - "response": { - "body": { - "root": { - "children": [ - { - "fields": { - "artist": "Boo Fighters" - } - } - ] - } - } - } - } - ] -} diff --git a/client/go/vespa/deploy.go b/client/go/vespa/deploy.go index c1cc868e16f..252a646bcfc 100644 --- a/client/go/vespa/deploy.go +++ b/client/go/vespa/deploy.go @@ -73,7 +73,7 @@ func (d DeploymentOpts) String() string { func (d *DeploymentOpts) IsCloud() bool { return d.Target.Type() == cloudTargetType } func (d *DeploymentOpts) url(path string) (*url.URL, error) { - service, err := d.Target.Service(deployService, 0, 0, "") + service, err := d.Target.Service(deployService, 0, 0) if err != nil { return nil, err } diff --git a/client/go/vespa/target.go b/client/go/vespa/target.go index 0b3223c0d2e..093cb2b5cad 100644 --- a/client/go/vespa/target.go +++ b/client/go/vespa/target.go @@ -39,6 +39,7 @@ type Service struct { BaseURL string Name string TLSOptions TLSOptions + Target *Target } // Target represents a Vespa platform, running named Vespa services. @@ -47,7 +48,7 @@ type Target interface { Type() string // Service returns the service for given name. If timeout is non-zero, wait for the service to converge. - Service(name string, timeout time.Duration, sessionOrRunID int64, cluster string) (*Service, error) + Service(name string, timeout time.Duration, sessionOrRunID int64) (*Service, error) // PrintLog writes the logs of this deployment using given options to control output. PrintLog(options LogOptions) error @@ -128,7 +129,7 @@ func (s *Service) Description() string { func (t *customTarget) Type() string { return t.targetType } -func (t *customTarget) Service(name string, timeout time.Duration, sessionOrRunID int64, cluster string) (*Service, error) { +func (t *customTarget) Service(name string, timeout time.Duration, sessionID int64) (*Service, error) { if timeout > 0 && name != deployService { if err := t.waitForConvergence(timeout); err != nil { return nil, err @@ -170,7 +171,7 @@ func (t *customTarget) urlWithPort(serviceName string) (string, error) { } func (t *customTarget) waitForConvergence(timeout time.Duration) error { - deployer, err := t.Service(deployService, 0, 0, "") + deployer, err := t.Service(deployService, 0, 0) if err != nil { return err } @@ -240,8 +241,8 @@ func (t *cloudTarget) resolveEndpoint(cluster string) (string, error) { func (t *cloudTarget) Type() string { return t.targetType } -func (t *cloudTarget) Service(name string, timeout time.Duration, runID int64, cluster string) (*Service, error) { - if name != deployService && t.urlsByCluster == nil { +func (t *cloudTarget) Service(name string, timeout time.Duration, runID int64) (*Service, error) { + if name != deployService { if err := t.waitForEndpoints(timeout, runID); err != nil { return nil, err } @@ -250,13 +251,13 @@ func (t *cloudTarget) Service(name string, timeout time.Duration, runID int64, c case deployService: return &Service{Name: name, BaseURL: t.apiURL}, nil case queryService: - queryURL, err := t.resolveEndpoint(cluster) + queryURL, err := t.resolveEndpoint("") if err != nil { return nil, err } return &Service{Name: name, BaseURL: queryURL, TLSOptions: t.tlsOptions}, nil case documentService: - documentURL, err := t.resolveEndpoint(cluster) + documentURL, err := t.resolveEndpoint("") if err != nil { return nil, err } @@ -488,7 +489,7 @@ func CustomTarget(baseURL string) Target { // CloudTarget creates a Target for the Vespa Cloud platform. func CloudTarget(apiURL string, deployment Deployment, apiKey []byte, tlsOptions TLSOptions, logOptions LogOptions, - authConfigPath string, systemName string, cloudAuth string, urlsByCluster map[string]string) Target { + authConfigPath string, systemName string, cloudAuth string) Target { return &cloudTarget{ apiURL: apiURL, targetType: cloudTargetType, @@ -499,7 +500,6 @@ func CloudTarget(apiURL string, deployment Deployment, apiKey []byte, tlsOptions authConfigPath: authConfigPath, systemName: systemName, cloudAuth: cloudAuth, - urlsByCluster: urlsByCluster, } } diff --git a/client/go/vespa/target_test.go b/client/go/vespa/target_test.go index 0cfe9f1962c..9d2418897e3 100644 --- a/client/go/vespa/target_test.go +++ b/client/go/vespa/target_test.go @@ -82,11 +82,11 @@ func TestCustomTargetWait(t *testing.T) { defer srv.Close() target := CustomTarget(srv.URL) - _, err := target.Service("query", time.Millisecond, 42, "") + _, err := target.Service("query", time.Millisecond, 42) assert.NotNil(t, err) vc.deploymentConverged = true - _, err = target.Service("query", time.Millisecond, 42, "") + _, err = target.Service("query", time.Millisecond, 42) assert.Nil(t, err) assertServiceWait(t, 200, target, "deploy") @@ -104,11 +104,11 @@ func TestCloudTargetWait(t *testing.T) { target := createCloudTarget(t, srv.URL, &logWriter) assertServiceWait(t, 200, target, "deploy") - _, err := target.Service("query", time.Millisecond, 42, "") + _, err := target.Service("query", time.Millisecond, 42) assert.NotNil(t, err) vc.deploymentConverged = true - _, err = target.Service("query", time.Millisecond, 42, "") + _, err = target.Service("query", time.Millisecond, 42) assert.Nil(t, err) assertServiceWait(t, 500, target, "query") @@ -152,7 +152,7 @@ func createCloudTarget(t *testing.T, url string, logWriter io.Writer) Target { target := CloudTarget("https://example.com", Deployment{ Application: ApplicationID{Tenant: "t1", Application: "a1", Instance: "i1"}, Zone: ZoneID{Environment: "dev", Region: "us-north-1"}, - }, apiKey, TLSOptions{KeyPair: x509KeyPair}, LogOptions{Writer: logWriter}, "", "", "", nil) + }, apiKey, TLSOptions{KeyPair: x509KeyPair}, LogOptions{Writer: logWriter}, "", "", "") if ct, ok := target.(*cloudTarget); ok { ct.apiURL = url } else { @@ -162,13 +162,13 @@ func createCloudTarget(t *testing.T, url string, logWriter io.Writer) Target { } func assertServiceURL(t *testing.T, url string, target Target, service string) { - s, err := target.Service(service, 0, 42, "") + s, err := target.Service(service, 0, 42) assert.Nil(t, err) assert.Equal(t, url, s.BaseURL) } func assertServiceWait(t *testing.T, expectedStatus int, target Target, service string) { - s, err := target.Service(service, 0, 42, "") + s, err := target.Service(service, 0, 42) assert.Nil(t, err) status, err := s.Wait(0) |