From 3c4c56fbb6d6ade6981246d352022a4337ffd408 Mon Sep 17 00:00:00 2001 From: Matt Fellows Date: Wed, 2 Nov 2022 23:16:55 +1100 Subject: [PATCH] fix: verifier works multi-protocol - update tests to to use NewVerifier() - refactor Verifier internals to start a dummy mock server for message pacts, if no HTTP server given - Plugins, HTTP and Messages all supported from same verifier --- .github/workflows/test.yml | 2 +- examples/provider_test.go | 4 ++-- installer/installer.go | 2 +- message/verifier.go | 3 +++ provider/verifier.go | 42 ++++++++++++-------------------------- provider/verify_request.go | 30 ++++++--------------------- 6 files changed, 26 insertions(+), 57 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a42fc31b6..1e19170a9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,7 +9,7 @@ env: APP_REF: ${{ github.ref }} LD_LIBRARY_PATH: /tmp PACT_GO_LIB_DOWNLOAD_PATH: /tmp - LOG_LEVEL: trace + LOG_LEVEL: error COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: diff --git a/examples/provider_test.go b/examples/provider_test.go index 866d0b5ad..de67fa1c9 100644 --- a/examples/provider_test.go +++ b/examples/provider_test.go @@ -30,7 +30,7 @@ func TestV3HTTPProvider(t *testing.T) { // Start provider API in the background go startServer() - verifier := provider.Verifier{} + verifier := provider.NewVerifier() // Authorization middleware // This is your chance to modify the request before it hits your provider @@ -96,7 +96,7 @@ func TestV3MessageProvider(t *testing.T) { log.SetLogLevel("TRACE") var user *User - verifier := provider.Verifier{} + verifier := provider.NewVerifier() // Map test descriptions to message producer (handlers) functionMappings := message.Handlers{ diff --git a/installer/installer.go b/installer/installer.go index da0fe9737..dfd6f802b 100644 --- a/installer/installer.go +++ b/installer/installer.go @@ -341,7 +341,7 @@ const ( var packages = map[string]packageInfo{ FFIPackage: { libName: "libpact_ffi", - version: "0.3.13", + version: "0.3.14", semverRange: ">= 0.3.0, < 1.0.0", }, } diff --git a/message/verifier.go b/message/verifier.go index cd2e7fc43..e9fe5fd36 100644 --- a/message/verifier.go +++ b/message/verifier.go @@ -214,6 +214,7 @@ func CreateMessageHandler(messageHandlers Handlers) proxy.Middleware { log.Printf("[TRACE] message verification handler received request: %+s, %s", body, r.URL.Path) if err != nil { + log.Printf("[ERROR] unable to parse message verification request: %s", err) w.WriteHeader(http.StatusBadRequest) return } @@ -221,6 +222,7 @@ func CreateMessageHandler(messageHandlers Handlers) proxy.Middleware { err = json.Unmarshal(body, &message) if err != nil { + log.Printf("[ERROR] unable to parse message verification request: %s", err) w.WriteHeader(http.StatusBadRequest) return } @@ -238,6 +240,7 @@ func CreateMessageHandler(messageHandlers Handlers) proxy.Middleware { res, metadata, handlerErr := f(message.States) if handlerErr != nil { + log.Printf("[ERROR] error executive message handler %s", err) w.WriteHeader(http.StatusServiceUnavailable) return } diff --git a/provider/verifier.go b/provider/verifier.go index 5bdabee66..eeca236a3 100644 --- a/provider/verifier.go +++ b/provider/verifier.go @@ -17,6 +17,7 @@ import ( "github.com/pact-foundation/pact-go/v2/message" "github.com/pact-foundation/pact-go/v2/models" "github.com/pact-foundation/pact-go/v2/proxy" + "github.com/pact-foundation/pact-go/v2/utils" ) // Verifier is used to verify the provider side of an HTTP API contract @@ -74,44 +75,27 @@ func (v *Verifier) verifyProviderRaw(request VerifyRequest, writer outputWriter) return err } + // Check if a provider has been given. If none, start a dummy service to attach the proxy to + if request.ProviderBaseURL == "" { + log.Println("[DEBUG] setting up a dummy server for verification, as none was provided") + port, err := utils.GetFreePort() + if err != nil { + log.Panic("unable to allocate a port for verification:", err) + } + go v.startDefaultHTTPServer(port) + + request.ProviderBaseURL = fmt.Sprintf("http://localhost:%d", port) + } + err = request.validate(v.handle) if err != nil { return err } - // Get provider address - - // t, err := request.findTransportByScheme("http") - // log.Println("[DEBUG] findTransportByScheme", t) - // if err != nil { - // return err - // } - - // if t != nil { u, err = url.Parse(request.ProviderBaseURL) if err != nil { log.Panic("unable to parse the provider URL", err) } - // } else { - // TODO: don't actually need to do this? I think we can just attach to the proxy itself - // port, err := utils.GetFreePort() - // log.Println("[DEBUG] free port", port) - // if err != nil { - // log.Panic("unable to allocate a port for verification:", err) - // } - - // u = url.URL{ - // Host: fmt.Sprintf("%s:%d", v.Hostname, port), - // Scheme: "http", - // } - - // log.Println("[DEBUG] starting local http server on url", u) - // go v.startDefaultHTTPServer(port) - // } - - if err != nil { - return err - } m := []proxy.Middleware{} diff --git a/provider/verify_request.go b/provider/verify_request.go index 22477f19f..3e77fdb3a 100644 --- a/provider/verify_request.go +++ b/provider/verify_request.go @@ -167,9 +167,9 @@ func (v *VerifyRequest) validate(handle *native.Verifier) error { // TODO: review this // We spin up our own transport for messages, but we need them defined for all others - // if len(v.Transports) == 0 && len(v.MessageHandlers) == 0 { - // return fmt.Errorf("one of 'Transports' or 'ProviderBaseURL' must be provided") - // } + if len(v.Transports) == 0 && len(v.MessageHandlers) == 0 && v.ProviderBaseURL == "" { + return fmt.Errorf("one of 'Transports' or 'ProviderBaseURL' must be provided") + } filterDescription := valueOrFromEnvironment(v.FilterDescription, "PACT_DESCRIPTION") filterState := valueOrFromEnvironment(v.FilterState, "PACT_PROVIDER_STATE") @@ -179,11 +179,6 @@ func (v *VerifyRequest) validate(handle *native.Verifier) error { handle.SetFilterInfo(filterDescription, filterState, filterNoState) } - // TODO: this also needs to take the proxyp address - if v.ProviderStatesSetupURL != "" { - handle.SetProviderState(v.ProviderStatesSetupURL, true, true) - } - // TODO: support these // SetVerificationOptions: 4, @@ -285,14 +280,11 @@ func (v *VerifyRequest) Verify(handle *native.Verifier, writer outputWriter) err for _, transport := range v.Transports { log.Println("[DEBUG] adding transport to verification", transport) handle.AddTransport(transport.Protocol, transport.Port, transport.Path, transport.Scheme) - // handle.AddTransport(transport.Protocol, transport.Port, "/", "http") } - // address := getHost(v.ProviderBaseURL) - // port := getPort(v.ProviderBaseURL) - - // WaitForPort(port, "tcp", address, 10*time.Second, - // fmt.Sprintf(`Timed out waiting for Provider API to start on port %d - are you sure it's running?`, port)) + if v.ProviderStatesSetupURL != "" { + handle.SetProviderState(v.ProviderStatesSetupURL, true, true) + } res := handle.Execute() defer handle.Shutdown() @@ -300,16 +292,6 @@ func (v *VerifyRequest) Verify(handle *native.Verifier, writer outputWriter) err return res } -func (v *VerifyRequest) findTransportByScheme(scheme string) (*Transport, error) { - for _, transport := range v.Transports { - if strings.Index(strings.ToLower(transport.Scheme), scheme) == 0 { - return &transport, nil - } - } - - return nil, nil -} - // Get a port given a URL func getPort(rawURL string) int { parsedURL, err := url.Parse(rawURL)