From 269d39deefb1770b44a58400fa575410dc8fe267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Mac=C3=ADk?= Date: Fri, 12 Oct 2018 13:01:18 +0200 Subject: [PATCH 1/3] test: Create contract tests for interaction with Auth service. --- .make/test.mk | 46 +++ test/contracts/.gitignore | 3 + test/contracts/auth/auth_api_status.go | 59 ++++ test/contracts/auth/auth_api_user.go | 263 ++++++++++++++++++ test/contracts/auth/consumer-contracts.sh | 6 + test/contracts/auth/contract_test.go | 30 ++ test/contracts/auth/publish-contracts.sh | 19 ++ test/contracts/auth/setenv.sh | 11 + .../contracts/auth/verify-contracts-broker.sh | 10 + test/contracts/auth/verify-contracts.sh | 7 + 10 files changed, 454 insertions(+) create mode 100644 test/contracts/.gitignore create mode 100644 test/contracts/auth/auth_api_status.go create mode 100644 test/contracts/auth/auth_api_user.go create mode 100755 test/contracts/auth/consumer-contracts.sh create mode 100644 test/contracts/auth/contract_test.go create mode 100755 test/contracts/auth/publish-contracts.sh create mode 100755 test/contracts/auth/setenv.sh create mode 100755 test/contracts/auth/verify-contracts-broker.sh create mode 100755 test/contracts/auth/verify-contracts.sh diff --git a/.make/test.mk b/.make/test.mk index 2a7fe7e..3647ec0 100644 --- a/.make/test.mk +++ b/.make/test.mk @@ -117,6 +117,14 @@ ALL_PKGS_EXCLUDE_PATTERN = 'vendor\|app\|tool\/cli\|design\|client\|test' GOANALYSIS_PKGS_EXCLUDE_PATTERN="vendor|app|client|tool/cli" GOANALYSIS_DIRS=$(shell go list -f {{.Dir}} ./... | grep -v -E $(GOANALYSIS_PKGS_EXCLUDE_PATTERN)) +# Folder with contract tests +CONTRACT_TESTS=$(CUR_DIR)/test/contracts + +# Configuration of contract tests +PACT_VERSION ?= 1.0.0 +PACT_BROKER_URL ?= http://pact-broker-pact-broker.193b.starter-ca-central-1.openshiftapps.com +PACT_PROVIDER_BASE_URL ?= https://auth.openshift.io + #------------------------------------------------------------------------------- # Normal test targets # @@ -159,6 +167,7 @@ test-templates-flags: test-unit: test-templates-flags prebuild-check clean-coverage-unit $(COV_PATH_UNIT) .PHONY: test-unit-no-coverage + ## Runs the unit tests and WITHOUT producing coverage files for each package. test-unit-no-coverage: test-templates-flags prebuild-check $(SOURCES) $(call log-info,"Running test: $@") @@ -183,6 +192,43 @@ test-integration-no-coverage: prebuild-check migrate-database $(SOURCES) $(eval TEST_PACKAGES:=$(shell go list ./... | grep -v $(ALL_PKGS_EXCLUDE_PATTERN))) F8_DEVELOPER_MODE_ENABLED=1 F8_RESOURCE_DATABASE=1 F8_RESOURCE_UNIT_TEST=0 F8_POSTGRES_DATABASE=postgres go test -v $(TEST_PACKAGES) +.PHONY: test-contract-auth-consumer +## Runs the consumer side contract tests of the Auth service and produces pact files. +test-contract-auth-consumers: + cd $(CONTRACT_TESTS)/auth && \ + PACT_DIR=$(CONTRACT_TESTS)/pacts \ + ./consumer-contracts.sh + +.PHONY: test-contract-auth-publish +## Publishes the generated files to a Pact broker. +test-contract-auth-publish: + cd $(CONTRACT_TESTS)/auth && \ + PACT_VERSION=$(PACT_VERSION) \ + PACT_BROKER_URL=$(PACT_BROKER_URL) \ + ./publish-contracts.sh + +.PHONY: test-contract-auth-verify +## Verifies the contracts against the living provider. The pact files are taken from pact directory. +test-contract-auth-verify: + cd $(CONTRACT_TESTS)/auth && \ + PACT_PROVIDER_BASE_URL=$(PACT_PROVIDER_BASE_URL) \ + ./verify-contracts.sh + +.PHONY: test-contract-auth-verify-broker +## Verifies the contracts against the living provider. The pact files are taken from the Pact broker. +test-contract-auth-verify-broker: + cd $(CONTRACT_TESTS)/auth && \ + PACT_VERSION=$(PACT_VERSION) \ + PACT_BROKER_URL=$(PACT_BROKER_URL) \ + PACT_PROVIDER_BASE_URL=$(PACT_PROVIDER_BASE_URL) \ + ./verify-contracts-broker.sh + +.PHONY: clean-test-contract-auth +## Runs the consumer side contract tests and produces pact files. +clean-test-contract-auth: + cd $(CONTRACT_TESTS)/auth && \ + rm -rvf pacts log logs + .PHONY: test-remote ## Runs the remote tests and produces coverage files for each package. test-remote: prebuild-check clean-coverage-remote $(COV_PATH_REMOTE) diff --git a/test/contracts/.gitignore b/test/contracts/.gitignore new file mode 100644 index 0000000..e804e82 --- /dev/null +++ b/test/contracts/.gitignore @@ -0,0 +1,3 @@ +**/*log +**/*logs +**/*pacts \ No newline at end of file diff --git a/test/contracts/auth/auth_api_status.go b/test/contracts/auth/auth_api_status.go new file mode 100644 index 0000000..6cf52dd --- /dev/null +++ b/test/contracts/auth/auth_api_status.go @@ -0,0 +1,59 @@ +// Package contracts contains a runnable Consumer Pact test example. +package contracts + +import ( + "fmt" + "log" + "net/http" + "testing" + + "github.com/pact-foundation/pact-go/dsl" +) + +// AuthAPIStatus defines contract of /api/status endpoint +func AuthAPIStatus(t *testing.T, pact *dsl.Pact) { + // Pass in test case + var test = func() error { + u := fmt.Sprintf("http://localhost:%d/api/status", pact.Server.Port) + req, err := http.NewRequest("GET", u, nil) + + req.Header.Set("Content-Type", "application/json") + if err != nil { + return err + } + + _, err = http.DefaultClient.Do(req) + if err != nil { + return err + } + return err + } + + type STATUS struct { + buildTime string `json:"buildTime" pact:"example=2018-10-05T10:03:04Z"` + commit string `json:"commit" pact:"example=0f9921980549b2baeb43f6f16cbe794f430f498c"` + configurationStatus string `json:"configurationStatus" pact:"example=OK"` + databaseStatus string `json:"databaseStatus" pact:"example=OK"` + startTime string `json:"startTime" pact:"example=2018-10-09T15:04:50Z"` + } + + // Set up our expected interactions. + pact. + AddInteraction(). + UponReceiving("A request to get status"). + WithRequest(dsl.Request{ + Method: "GET", + Path: dsl.String("/api/status"), + Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json")}, + }). + WillRespondWith(dsl.Response{ + Status: 200, + Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/vnd.status+json")}, + Body: dsl.Match(STATUS{}), + }) + + // Verify + if err := pact.Verify(test); err != nil { + log.Fatalf("Error on Verify: %v", err) + } +} diff --git a/test/contracts/auth/auth_api_user.go b/test/contracts/auth/auth_api_user.go new file mode 100644 index 0000000..6f646b1 --- /dev/null +++ b/test/contracts/auth/auth_api_user.go @@ -0,0 +1,263 @@ +// Package contracts contains a runnable Consumer Pact test example. +package contracts + +import ( + "fmt" + "log" + "net/http" + "os" + "testing" + + "github.com/pact-foundation/pact-go/dsl" +) + +type Data struct { + Attributes struct { + Bio string `json:"bio" pact:"example=n/a"` + Cluster string `json:"cluster" pact:"example=https://api.starter-us-east-2a.openshift.com/"` + Company string `json:"company" pact:"example=n/a"` + ContextInformation struct { + RecentContexts []struct { + User string `json:"user" pact:"example=c46445eb-2448-4c91-916a-2c1de3e6f63e"` + } `json:"recentContexts"` + RecentSpaces []string `json:"recentSpaces"` + } `json:"contextInformation"` + CreatedAt string `json:"created-at" pact:"example=2018-03-16T14:34:31.615511Z"` + Email string `json:"email" pact:"example=osio-ci+ee10@redhat.com"` + EmailPrivate bool `json:"emailPrivate" pact:"example=false"` + EmailVerified bool `json:"emailVerified" pact:"example=true"` + FeatureLevel string `json:"featureLevel" pact:"example=internal"` + FullName string `json:"fullName" pact:"example=Osio10 Automated Tests"` + IdentityID string `json:"identityID" pact:"example=c46445eb-2448-4c91-916a-2c1de3e6f63e"` + ImageURL string `json:"imageURL" pact:"example=n/a"` + ProviderType string `json:"providerType" pact:"example=kc"` + RegistrationCompleted bool `json:"registrationCompleted" pact:"example=true"` + UpdatedAt string `json:"updated-at" pact:"example=2018-05-30T11:05:23.513612Z"` + URL string `json:"url" pact:"example=n/a"` + UserID string `json:"userID" pact:"example=5f41b66e-6f84-42b3-ab5f-8d9ef21149b1"` + Username string `json:"username" pact:"example=osio-ci-ee10"` + } `json:"attributes"` + ID string `json:"id" pact:"example=c46445eb-2448-4c91-916a-2c1de3e6f63e"` + Links struct { + Related string `json:"related" pact:"example=https://auth.openshift.io/api/users/c46445eb-2448-4c91-916a-2c1de3e6f63e"` + Self string `json:"self" pact:"example=https://auth.openshift.io/api/users/c46445eb-2448-4c91-916a-2c1de3e6f63e"` + } `json:"links"` + Type string `json:"type" pact:"example=identities"` +} + +type User struct { + data Data `json:"data"` +} + +type Users struct { + data []Data `json:"data"` +} + +type InvalidToken struct { + Errors []struct { + Code string `json:"code" pact:"example=token_validation_failed"` + Detail string `json:"detail" pact:"example=token is invalid"` + ID string `json:"id" pact:"example=76J0ww+6"` + Status string `json:"status" pact:"example=401"` + Title string `json:"title" pact:"example=Unauthorized"` + } `json:"errors"` +} + +type MissingToken struct { + Errors []struct { + Code string `json:"code" pact:"example=jwt_security_error"` + Detail string `json:"detail" pact:"example=missing header \"Authorization\""` + ID string `json:"id" pact:"example=FRzHbogQ"` + Status string `json:"status" pact:"example=401"` + Title string `json:"title" pact:"example=Unauthorized"` + } `json:"errors"` +} + +const JWSRegex = "[a-zA-Z0-9\\-_]+?\\.?[a-zA-Z0-9\\-_]+?\\.?([a-zA-Z0-9\\-_]+)?" + +// AuthAPIUserByNameConsumer defines contract of /api/users?filter[username]= endpoint +func AuthAPIUserByNameConsumer(t *testing.T, pact *dsl.Pact) { + userName := os.Getenv("OSIO_USERNAME") + + // Pass in test case + var test = func() error { + url := fmt.Sprintf("http://localhost:%d/api/users?filter[username]=%s", pact.Server.Port, userName) + req, err := http.NewRequest("GET", url, nil) + + req.Header.Set("Content-Type", "application/json") + if err != nil { + return err + } + + _, err = http.DefaultClient.Do(req) + if err != nil { + return err + } + return err + } + + // Set up our expected interactions. + pact. + AddInteraction(). + UponReceiving("A request to get user's information by name"). + WithRequest(dsl.Request{ + Method: "GET", + Path: dsl.String("/api/users"), + Query: dsl.MapMatcher{ + "filter[username]": dsl.Term( + userName, + ".*", + ), + }, + Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json")}, + }). + WillRespondWith(dsl.Response{ + Status: 200, + Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/vnd.api+json")}, + Body: dsl.Match(Users{}), + }) + + // Verify + if err := pact.Verify(test); err != nil { + log.Fatalf("Error on Verify: %v", err) + } +} + +// AuthAPIUserByIDConsumer defines contract of /api/users/ endpoint +func AuthAPIUserByIDConsumer(t *testing.T, pact *dsl.Pact) { + userID := os.Getenv("OSIO_USER_ID") + + // Pass in test case + var test = func() error { + url := fmt.Sprintf("http://localhost:%d/api/users/%s", pact.Server.Port, userID) + req, err := http.NewRequest("GET", url, nil) + + req.Header.Set("Content-Type", "application/json") + if err != nil { + return err + } + + _, err = http.DefaultClient.Do(req) + if err != nil { + return err + } + return err + } + + // Set up our expected interactions. + pact. + AddInteraction(). + UponReceiving("A request to get user's information by ID"). + WithRequest(dsl.Request{ + Method: "GET", + Path: dsl.Term( + fmt.Sprintf("/api/users/%s", userID), + "/api/users/.*", + ), + Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json")}, + }). + WillRespondWith(dsl.Response{ + Status: 200, + Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/vnd.api+json")}, + Body: dsl.Match(User{}), + }) + + // Verify + if err := pact.Verify(test); err != nil { + log.Fatalf("Error on Verify: %v", err) + } +} + +// AuthAPIUserInvalidToken defines contract of /api/user endpoint with invalid auth token +func AuthAPIUserInvalidToken(t *testing.T, pact *dsl.Pact) { + + // Base64 encoded '{"alg":"RS256","kid":"1aA2bBc3CDDdEEefff7gGHH_ii9jJjkkkLl2mmm4NNO","typ":"JWT"}somerandombytes' + var invalidToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFhQTJiQmMzQ0REZEVFZWZmZjdnR0hIX2lpOWpKamtra0xsMm1tbTROTk8iLCJ0eXAiOiJKV1QifXNvbWVyYW5kb21ieXRlcw" + + // Pass in test case + var test = func() error { + url := fmt.Sprintf("http://localhost:%d/api/user", pact.Server.Port) + req, err := http.NewRequest("GET", url, nil) + + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", invalidToken)) + if err != nil { + return err + } + + _, err = http.DefaultClient.Do(req) + if err != nil { + return err + } + return err + } + + // Set up our expected interactions. + pact. + AddInteraction(). + UponReceiving("A request to get user's information with invalid auth token "). + WithRequest(dsl.Request{ + Method: "GET", + Path: dsl.String("/api/user"), + Headers: dsl.MapMatcher{ + "Content-Type": dsl.String("application/json"), + "Authorization": dsl.Term( + fmt.Sprintf("Bearer %s", invalidToken), + fmt.Sprintf("^Bearer %s$", JWSRegex), + ), + }, + }). + WillRespondWith(dsl.Response{ + Status: 401, + Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/vnd.api+json")}, + Body: dsl.Match(InvalidToken{}), + }) + + // Verify + if err := pact.Verify(test); err != nil { + log.Fatalf("Error on Verify: %v", err) + } +} + +// AuthAPIUserNoToken defines contract of /api/user endpoint with invalid auth token +func AuthAPIUserNoToken(t *testing.T, pact *dsl.Pact) { + + // Pass in test case + var test = func() error { + url := fmt.Sprintf("http://localhost:%d/api/user", pact.Server.Port) + req, err := http.NewRequest("GET", url, nil) + + req.Header.Set("Content-Type", "application/json") + if err != nil { + return err + } + + _, err = http.DefaultClient.Do(req) + if err != nil { + return err + } + return err + } + + // Set up our expected interactions. + pact. + AddInteraction(). + UponReceiving("A request to get user's information with no auth token "). + WithRequest(dsl.Request{ + Method: "GET", + Path: dsl.String("/api/user"), + Headers: dsl.MapMatcher{ + "Content-Type": dsl.String("application/json"), + }, + }). + WillRespondWith(dsl.Response{ + Status: 401, + Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/vnd.api+json")}, + Body: dsl.Match(MissingToken{}), + }) + + // Verify + if err := pact.Verify(test); err != nil { + log.Fatalf("Error on Verify: %v", err) + } +} diff --git a/test/contracts/auth/consumer-contracts.sh b/test/contracts/auth/consumer-contracts.sh new file mode 100755 index 0000000..12be9cd --- /dev/null +++ b/test/contracts/auth/consumer-contracts.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +. ./setenv.sh + +# run test +go test -v -run 'Test*' diff --git a/test/contracts/auth/contract_test.go b/test/contracts/auth/contract_test.go new file mode 100644 index 0000000..ba439b1 --- /dev/null +++ b/test/contracts/auth/contract_test.go @@ -0,0 +1,30 @@ +// Package contracts contains a runnable Consumer Pact test example. +package contracts + +import ( + "os" + "testing" + + "github.com/pact-foundation/pact-go/dsl" +) + +// TestAuthAPI runs all user related tests +func TestAuthAPI(t *testing.T) { + // Create Pact connecting to local Daemon + pact := &dsl.Pact{ + Consumer: os.Getenv("PACT_CONSUMER"), + Provider: os.Getenv("PACT_PROVIDER"), + Host: "localhost", + PactFileWriteMode: "merge", + } + defer pact.Teardown() + + // Test interactions + AuthAPIStatus(t, pact) + AuthAPIUserByNameConsumer(t, pact) + AuthAPIUserByIDConsumer(t, pact) + + // Negative tests + AuthAPIUserInvalidToken(t, pact) + AuthAPIUserNoToken(t, pact) +} diff --git a/test/contracts/auth/publish-contracts.sh b/test/contracts/auth/publish-contracts.sh new file mode 100755 index 0000000..f0ec0c8 --- /dev/null +++ b/test/contracts/auth/publish-contracts.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +. ./setenv.sh + +for PACT_FILE in $(find "$PACT_DIR" -name "*.json"); do + echo "Publishing $PACT_FILE to a Pact broker at $PACT_BROKER_URL" + + PACT_CONSUMER=$(jq '.["consumer"]["name"]' "$PACT_FILE" | tr -d '"') + PACT_PROVIDER=$(jq '.["provider"]["name"]' "$PACT_FILE" | tr -d '"') + + result=$(curl -L --silent -XPUT -H "Content-Type: application/json" -d@$PACT_FILE "$PACT_BROKER_URL/pacts/provider/$PACT_PROVIDER/consumer/$PACT_CONSUMER/version/$PACT_VERSION") + + if [[ $result = *'"consumer":{"name":"'$PACT_CONSUMER'"},"provider":{"name":"'$PACT_PROVIDER'"}'* ]]; then + echo "Pact successfully published." + else + echo "Unable to publish pact:" + echo "$result" + fi +done diff --git a/test/contracts/auth/setenv.sh b/test/contracts/auth/setenv.sh new file mode 100755 index 0000000..6f36acd --- /dev/null +++ b/test/contracts/auth/setenv.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -a + +# Add the current directory to Go path. +GOPATH="$GOPATH:$(pwd)" + +# A directory to save pact files +PACT_DIR="${PACT_DIR:-pacts}" +PACT_CONSUMER="${PACT_CONSUMER:-Fabric8TenantService}" +PACT_PROVIDER="${PACT_PROVIDER:-Fabric8AuthService}" diff --git a/test/contracts/auth/verify-contracts-broker.sh b/test/contracts/auth/verify-contracts-broker.sh new file mode 100755 index 0000000..2f6b93b --- /dev/null +++ b/test/contracts/auth/verify-contracts-broker.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +. ./setenv.sh + +for PACT_FILE in $(find "$PACT_DIR" -name "*.json"); do + PACT_CONSUMER=$(jq '.["consumer"]["name"]' "$PACT_FILE" | tr -d '"') + PACT_PROVIDER=$(jq '.["provider"]["name"]' "$PACT_FILE" | tr -d '"') + + pact-provider-verifier "$PACT_BROKER_URL/pacts/provider/$PACT_PROVIDER/consumer/$PACT_CONSUMER/versions/$PACT_VERSION" --provider-base-url "$PACT_PROVIDER_BASE_URL" +done diff --git a/test/contracts/auth/verify-contracts.sh b/test/contracts/auth/verify-contracts.sh new file mode 100755 index 0000000..356a1e3 --- /dev/null +++ b/test/contracts/auth/verify-contracts.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +. ./setenv.sh + +for PACT_FILE in $(find "$PACT_DIR" -name "*.json"); do + pact-provider-verifier "$PACT_FILE" --provider-base-url "$PACT_PROVIDER_BASE_URL" +done From abc66b74bf98fd27c38749da663c7c61028924ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Mac=C3=ADk?= Date: Mon, 15 Oct 2018 15:51:47 +0200 Subject: [PATCH 2/3] Enable Basic Auth for pact broker. --- test/contracts/auth/publish-contracts.sh | 4 +++- test/contracts/auth/setenv.sh | 6 ++++++ test/contracts/auth/verify-contracts-broker.sh | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/test/contracts/auth/publish-contracts.sh b/test/contracts/auth/publish-contracts.sh index f0ec0c8..ba19fd9 100755 --- a/test/contracts/auth/publish-contracts.sh +++ b/test/contracts/auth/publish-contracts.sh @@ -2,13 +2,15 @@ . ./setenv.sh +PACT_BROKER_BASIC_AUTH=$(echo -n "${PACT_BROKER_USERNAME}:${PACT_BROKER_PASSWORD}" | base64) + for PACT_FILE in $(find "$PACT_DIR" -name "*.json"); do echo "Publishing $PACT_FILE to a Pact broker at $PACT_BROKER_URL" PACT_CONSUMER=$(jq '.["consumer"]["name"]' "$PACT_FILE" | tr -d '"') PACT_PROVIDER=$(jq '.["provider"]["name"]' "$PACT_FILE" | tr -d '"') - result=$(curl -L --silent -XPUT -H "Content-Type: application/json" -d@$PACT_FILE "$PACT_BROKER_URL/pacts/provider/$PACT_PROVIDER/consumer/$PACT_CONSUMER/version/$PACT_VERSION") + result=$(curl --silent -XPUT -H "Content-Type: application/json" -H "Authorization: Basic ${PACT_BROKER_BASIC_AUTH}" -d@$PACT_FILE "$PACT_BROKER_URL/pacts/provider/$PACT_PROVIDER/consumer/$PACT_CONSUMER/version/$PACT_VERSION") if [[ $result = *'"consumer":{"name":"'$PACT_CONSUMER'"},"provider":{"name":"'$PACT_PROVIDER'"}'* ]]; then echo "Pact successfully published." diff --git a/test/contracts/auth/setenv.sh b/test/contracts/auth/setenv.sh index 6f36acd..ff92cc6 100755 --- a/test/contracts/auth/setenv.sh +++ b/test/contracts/auth/setenv.sh @@ -9,3 +9,9 @@ GOPATH="$GOPATH:$(pwd)" PACT_DIR="${PACT_DIR:-pacts}" PACT_CONSUMER="${PACT_CONSUMER:-Fabric8TenantService}" PACT_PROVIDER="${PACT_PROVIDER:-Fabric8AuthService}" + +PACT_BROKER_URL="${PACT_BROKER_URL:-http://pact-broker-pact-broker.193b.starter-ca-central-1.openshiftapps.com}" +PACT_BROKER_USERNAME="${PACT_BROKER_USERNAME:-pact_broker}" +PACT_BROKER_PASSWORD="${PACT_BROKER_PASSWORD:-}" + +PACT_PROVIDER_BASE_URL="${PACT_PROVIDER_BASE_URL:-https://auth.openshift.io}" diff --git a/test/contracts/auth/verify-contracts-broker.sh b/test/contracts/auth/verify-contracts-broker.sh index 2f6b93b..461eec4 100755 --- a/test/contracts/auth/verify-contracts-broker.sh +++ b/test/contracts/auth/verify-contracts-broker.sh @@ -6,5 +6,5 @@ for PACT_FILE in $(find "$PACT_DIR" -name "*.json"); do PACT_CONSUMER=$(jq '.["consumer"]["name"]' "$PACT_FILE" | tr -d '"') PACT_PROVIDER=$(jq '.["provider"]["name"]' "$PACT_FILE" | tr -d '"') - pact-provider-verifier "$PACT_BROKER_URL/pacts/provider/$PACT_PROVIDER/consumer/$PACT_CONSUMER/versions/$PACT_VERSION" --provider-base-url "$PACT_PROVIDER_BASE_URL" + pact-provider-verifier "$PACT_BROKER_URL/pacts/provider/$PACT_PROVIDER/consumer/$PACT_CONSUMER/versions/$PACT_VERSION" --broker-username="$PACT_BROKER_USERNAME" --broker-password="$PACT_BROKER_PASSWORD" --provider-base-url "$PACT_PROVIDER_BASE_URL" done From f3037640d75385c835c05c0226e9cf629c30b702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Mac=C3=ADk?= Date: Thu, 18 Oct 2018 12:03:11 +0200 Subject: [PATCH 3/3] Parametrize pact broker password, make publishing part of the consumer tests. --- .make/test.mk | 2 ++ test/contracts/.gitignore | 3 ++- test/contracts/auth/auth_api_user.go | 9 +++++---- test/contracts/auth/consumer-contracts.sh | 5 +++++ test/contracts/auth/contract_test.go | 1 + test/contracts/auth/setenv.sh | 8 ++++++-- 6 files changed, 21 insertions(+), 7 deletions(-) diff --git a/.make/test.mk b/.make/test.mk index 3647ec0..c6938f0 100644 --- a/.make/test.mk +++ b/.make/test.mk @@ -197,6 +197,8 @@ test-integration-no-coverage: prebuild-check migrate-database $(SOURCES) test-contract-auth-consumers: cd $(CONTRACT_TESTS)/auth && \ PACT_DIR=$(CONTRACT_TESTS)/pacts \ + PACT_VERSION=$(PACT_VERSION) \ + PACT_BROKER_URL=$(PACT_BROKER_URL) \ ./consumer-contracts.sh .PHONY: test-contract-auth-publish diff --git a/test/contracts/.gitignore b/test/contracts/.gitignore index e804e82..0d4e497 100644 --- a/test/contracts/.gitignore +++ b/test/contracts/.gitignore @@ -1,3 +1,4 @@ **/*log **/*logs -**/*pacts \ No newline at end of file +**/*pacts +.password \ No newline at end of file diff --git a/test/contracts/auth/auth_api_user.go b/test/contracts/auth/auth_api_user.go index 6f646b1..f8d0045 100644 --- a/test/contracts/auth/auth_api_user.go +++ b/test/contracts/auth/auth_api_user.go @@ -73,7 +73,8 @@ type MissingToken struct { } `json:"errors"` } -const JWSRegex = "[a-zA-Z0-9\\-_]+?\\.?[a-zA-Z0-9\\-_]+?\\.?([a-zA-Z0-9\\-_]+)?" +const jwsRegex = "[a-zA-Z0-9\\-_]+?\\.?[a-zA-Z0-9\\-_]+?\\.?([a-zA-Z0-9\\-_]+)?" +const userNameRegex = "[a-zA-Z\\-0-9]+" // AuthAPIUserByNameConsumer defines contract of /api/users?filter[username]= endpoint func AuthAPIUserByNameConsumer(t *testing.T, pact *dsl.Pact) { @@ -106,7 +107,7 @@ func AuthAPIUserByNameConsumer(t *testing.T, pact *dsl.Pact) { Query: dsl.MapMatcher{ "filter[username]": dsl.Term( userName, - ".*", + userNameRegex, ), }, Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json")}, @@ -152,7 +153,7 @@ func AuthAPIUserByIDConsumer(t *testing.T, pact *dsl.Pact) { Method: "GET", Path: dsl.Term( fmt.Sprintf("/api/users/%s", userID), - "/api/users/.*", + fmt.Sprintf("/api/users/%s", userNameRegex), ), Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json")}, }). @@ -203,7 +204,7 @@ func AuthAPIUserInvalidToken(t *testing.T, pact *dsl.Pact) { "Content-Type": dsl.String("application/json"), "Authorization": dsl.Term( fmt.Sprintf("Bearer %s", invalidToken), - fmt.Sprintf("^Bearer %s$", JWSRegex), + fmt.Sprintf("^Bearer %s$", jwsRegex), ), }, }). diff --git a/test/contracts/auth/consumer-contracts.sh b/test/contracts/auth/consumer-contracts.sh index 12be9cd..c1d4c69 100755 --- a/test/contracts/auth/consumer-contracts.sh +++ b/test/contracts/auth/consumer-contracts.sh @@ -4,3 +4,8 @@ # run test go test -v -run 'Test*' +TEST_EXIT=$? + +if [ "$TEST_EXIT" == "0" ]; then + ./publish-contracts.sh +fi \ No newline at end of file diff --git a/test/contracts/auth/contract_test.go b/test/contracts/auth/contract_test.go index ba439b1..40604ce 100644 --- a/test/contracts/auth/contract_test.go +++ b/test/contracts/auth/contract_test.go @@ -14,6 +14,7 @@ func TestAuthAPI(t *testing.T) { pact := &dsl.Pact{ Consumer: os.Getenv("PACT_CONSUMER"), Provider: os.Getenv("PACT_PROVIDER"), + PactDir: os.Getenv("PACT_DIR"), Host: "localhost", PactFileWriteMode: "merge", } diff --git a/test/contracts/auth/setenv.sh b/test/contracts/auth/setenv.sh index ff92cc6..66494d3 100755 --- a/test/contracts/auth/setenv.sh +++ b/test/contracts/auth/setenv.sh @@ -6,12 +6,16 @@ set -a GOPATH="$GOPATH:$(pwd)" # A directory to save pact files -PACT_DIR="${PACT_DIR:-pacts}" +PACT_DIR="${PACT_DIR:-$(pwd)/pacts}" PACT_CONSUMER="${PACT_CONSUMER:-Fabric8TenantService}" PACT_PROVIDER="${PACT_PROVIDER:-Fabric8AuthService}" PACT_BROKER_URL="${PACT_BROKER_URL:-http://pact-broker-pact-broker.193b.starter-ca-central-1.openshiftapps.com}" PACT_BROKER_USERNAME="${PACT_BROKER_USERNAME:-pact_broker}" -PACT_BROKER_PASSWORD="${PACT_BROKER_PASSWORD:-}" +if [ -z "$PACT_BROKER_PASSWORD" ]; then + if [ -f .password ]; then + PACT_BROKER_PASSWORD="$(cat .password)" + fi +fi PACT_PROVIDER_BASE_URL="${PACT_PROVIDER_BASE_URL:-https://auth.openshift.io}"