diff --git a/README.md b/README.md index e9b741d35..6b429a310 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ DSL for the consumer project, and interaction playback and verification for the [![Coverage Status](https://coveralls.io/repos/github/pact-foundation/pact-go/badge.svg?branch=HEAD)](https://coveralls.io/github/pact-foundation/pact-go?branch=HEAD) [![Go Report Card](https://goreportcard.com/badge/github.com/pact-foundation/pact-go)](https://goreportcard.com/report/github.com/pact-foundation/pact-go) [![GoDoc](https://godoc.org/github.com/pact-foundation/pact-go?status.svg)](https://godoc.org/github.com/pact-foundation/pact-go) +[![Build status](https://ci.appveyor.com/api/projects/status/lg02mfcmvr3e8w5n?svg=true)](https://ci.appveyor.com/project/mefellows/pact-go) ## Introduction diff --git a/appveyor.yml b/appveyor.yml index e4b8fb596..9d8c55bc7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,41 +1,42 @@ -version: "{build}" - -# fix lineendings in Windows -# init: - # - git config --global core.autocrlf input - -# Source Config -clone_folder: c:\gopath\src\github.com\pact-foundation\pact-go - -# Build host - -environment: - GOPATH: c:\gopath - GOVERSION: 1.8 - # PACT_INTEGRATED_TESTS: 0 - PACT_BROKER_HOST: "https://test.pact.dius.com.au" - PACT_BROKER_USERNAME: "dXfltyFMgNOFZAxr8io9wJ37iUpY42M" - PACT_BROKER_PASSWORD: "O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1" - -init: - - git config --global core.autocrlf input - -# Build - -install: - # Install the specific Go version. - - rmdir c:\go /s /q - - appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.msi - # Download the latest pact standalone - - msiexec /i go%GOVERSION%.windows-amd64.msi /q - - choco install bzr - - set Path=c:\go\bin;c:\gopath\bin;C:\Program Files (x86)\Bazaar\;C:\Program Files\Mercurial\%Path% - - go version - - go env - -build: false -deploy: false - -test_script: - - go build -o /tmp/pact-go github.com/pact-foundation/pact-go - - for /f "" %%G in ('go list github.com/pact-foundation/pact-go/... ^| find /i /v "/vendor/" ^| find /i /v "examples"') do ( go test -v %%G & IF ERRORLEVEL == 1 EXIT 1) \ No newline at end of file +version: "{build}" + +# fix lineendings in Windows +# init: + # - git config --global core.autocrlf input + +# Source Config +clone_folder: c:\gopath\src\github.com\pact-foundation\pact-go + +# Build host + + +environment: + GOPATH: c:\gopath + GOVERSION: 1.8 + PACT_INTEGRATED_TESTS: 1 + PACT_BROKER_HOST: "https://test.pact.dius.com.au" + PACT_BROKER_USERNAME: "dXfltyFMgNOFZAxr8io9wJ37iUpY42M" + PACT_BROKER_PASSWORD: "O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1" + +init: + - git config --global core.autocrlf input + +# Build + +install: + # Install the specific Go version. + - rmdir c:\go /s /q + - appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.msi + # Download the latest pact standalone + - msiexec /i go%GOVERSION%.windows-amd64.msi /q + - choco install bzr + - set Path=c:\go\bin;c:\gopath\bin;C:\Program Files (x86)\Bazaar\;C:\Program Files\Mercurial\%Path% + - go version + - go env + +build: false +deploy: false + +test_script: + - go build -o /tmp/pact-go github.com/pact-foundation/pact-go + - c:\gopath\src\github.com\pact-foundation\pact-go\scripts\pact.ps1 \ No newline at end of file diff --git a/examples/gin/provider/user_service_test.go b/examples/gin/provider/user_service_test.go index 0818b003d..fcba89437 100644 --- a/examples/gin/provider/user_service_test.go +++ b/examples/gin/provider/user_service_test.go @@ -1,97 +1,98 @@ -package provider - -import ( - "fmt" - "os" - "testing" - - "github.com/gin-gonic/gin" - "github.com/pact-foundation/pact-go/dsl" - examples "github.com/pact-foundation/pact-go/examples/types" - "github.com/pact-foundation/pact-go/types" - "github.com/pact-foundation/pact-go/utils" -) - -// The actual Provider test itself -func TestPact_Provider(t *testing.T) { - go startInstrumentedProvider() - - pact := createPact() - - // Verify the Provider with local Pact Files - err := pact.VerifyProvider(types.VerifyRequest{ - ProviderBaseURL: fmt.Sprintf("http://localhost:%d", port), - PactURLs: []string{fmt.Sprintf("%s/billy-bobby.json", pactDir)}, - ProviderStatesSetupURL: fmt.Sprintf("http://localhost:%d/setup", port), - }) - - if err != nil { - t.Fatal("Error:", err) - } -} - -// Starts the provider API with hooks for provider states. -// This essentially mirrors the main.go file, with extra routes added. -func startInstrumentedProvider() { - router := gin.Default() - router.POST("/users/login", UserLogin) - router.POST("/setup", providerStateSetup) - - router.Run(fmt.Sprintf(":%d", port)) -} - -// Set current provider state route. -func providerStateSetup(c *gin.Context) { - var state types.ProviderState - if c.BindJSON(&state) == nil { - // Setup database for different states - if state.State == "User billy exists" { - userRepository = billyExists - } else if state.State == "User billy is unauthorized" { - userRepository = billyUnauthorized - } else { - userRepository = billyDoesNotExist - } - } -} - -// Configuration / Test Data -var dir, _ = os.Getwd() -var pactDir = fmt.Sprintf("%s/../../pacts", dir) -var logDir = fmt.Sprintf("%s/log", dir) -var port, _ = utils.GetFreePort() - -// Provider States data sets -var billyExists = &examples.UserRepository{ - Users: map[string]*examples.User{ - "billy": &examples.User{ - Name: "billy", - Username: "billy", - Password: "issilly", - }, - }, -} - -var billyDoesNotExist = &examples.UserRepository{} - -var billyUnauthorized = &examples.UserRepository{ - Users: map[string]*examples.User{ - "billy": &examples.User{ - Name: "billy", - Username: "billy", - Password: "issilly1", - }, - }, -} - -// Setup the Pact client. -func createPact() dsl.Pact { - // Create Pact connecting to local Daemon - return dsl.Pact{ - Port: 6666, - Consumer: "billy", - Provider: "bobby", - LogDir: logDir, - PactDir: pactDir, - } -} +package provider + +import ( + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/gin-gonic/gin" + "github.com/pact-foundation/pact-go/dsl" + examples "github.com/pact-foundation/pact-go/examples/types" + "github.com/pact-foundation/pact-go/types" + "github.com/pact-foundation/pact-go/utils" +) + +// The actual Provider test itself +func TestPact_Provider(t *testing.T) { + go startInstrumentedProvider() + + pact := createPact() + + // Verify the Provider with local Pact Files + err := pact.VerifyProvider(types.VerifyRequest{ + ProviderBaseURL: fmt.Sprintf("http://localhost:%d", port), + PactURLs: []string{filepath.ToSlash(fmt.Sprintf("%s/billy-bobby.json", pactDir))}, + ProviderStatesSetupURL: fmt.Sprintf("http://localhost:%d/setup", port), + }) + + if err != nil { + t.Fatal("Error:", err) + } +} + +// Starts the provider API with hooks for provider states. +// This essentially mirrors the main.go file, with extra routes added. +func startInstrumentedProvider() { + router := gin.Default() + router.POST("/users/login", UserLogin) + router.POST("/setup", providerStateSetup) + + router.Run(fmt.Sprintf(":%d", port)) +} + +// Set current provider state route. +func providerStateSetup(c *gin.Context) { + var state types.ProviderState + if c.BindJSON(&state) == nil { + // Setup database for different states + if state.State == "User billy exists" { + userRepository = billyExists + } else if state.State == "User billy is unauthorized" { + userRepository = billyUnauthorized + } else { + userRepository = billyDoesNotExist + } + } +} + +// Configuration / Test Data +var dir, _ = os.Getwd() +var pactDir = fmt.Sprintf("%s/../../pacts", dir) +var logDir = fmt.Sprintf("%s/log", dir) +var port, _ = utils.GetFreePort() + +// Provider States data sets +var billyExists = &examples.UserRepository{ + Users: map[string]*examples.User{ + "billy": &examples.User{ + Name: "billy", + Username: "billy", + Password: "issilly", + }, + }, +} + +var billyDoesNotExist = &examples.UserRepository{} + +var billyUnauthorized = &examples.UserRepository{ + Users: map[string]*examples.User{ + "billy": &examples.User{ + Name: "billy", + Username: "billy", + Password: "issilly1", + }, + }, +} + +// Setup the Pact client. +func createPact() dsl.Pact { + // Create Pact connecting to local Daemon + return dsl.Pact{ + Port: 6666, + Consumer: "billy", + Provider: "bobby", + LogDir: logDir, + PactDir: pactDir, + } +} diff --git a/examples/go-kit/provider/cmd/usersvc/main.go b/examples/go-kit/provider/cmd/usersvc/main.go index 67ac84c9c..66227f640 100644 --- a/examples/go-kit/provider/cmd/usersvc/main.go +++ b/examples/go-kit/provider/cmd/usersvc/main.go @@ -10,7 +10,7 @@ import ( "github.com/go-kit/kit/log" - "golang.org/x/net/context" + "context" usersvc "github.com/pact-foundation/pact-go/examples/go-kit/provider" ) @@ -24,8 +24,7 @@ func main() { var logger log.Logger { logger = log.NewLogfmtLogger(os.Stderr) - logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC) - logger = log.NewContext(logger).With("caller", log.DefaultCaller) + logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller) } var ctx context.Context @@ -41,7 +40,7 @@ func main() { var h http.Handler { - h = usersvc.MakeHTTPHandler(ctx, s, log.NewContext(logger).With("component", "HTTP")) + h = usersvc.MakeHTTPHandler(ctx, s, log.With(logger, "component", "HTTP")) } errs := make(chan error) diff --git a/examples/go-kit/provider/endpoints.go b/examples/go-kit/provider/endpoints.go index 2faf3ca21..305d0752d 100644 --- a/examples/go-kit/provider/endpoints.go +++ b/examples/go-kit/provider/endpoints.go @@ -4,8 +4,9 @@ import ( "encoding/json" "net/http" + "context" + "github.com/go-kit/kit/endpoint" - "golang.org/x/net/context" ) // Endpoints is a container to hold all of our Transport routes (HTTP, RPC etc.). diff --git a/examples/go-kit/provider/transport.go b/examples/go-kit/provider/transport.go index b9ebe2c61..1e949dfb3 100644 --- a/examples/go-kit/provider/transport.go +++ b/examples/go-kit/provider/transport.go @@ -4,10 +4,11 @@ import ( "encoding/json" "net/http" + "context" + "github.com/go-kit/kit/log" httptransport "github.com/go-kit/kit/transport/http" "github.com/gorilla/mux" - "golang.org/x/net/context" ) // Request // Response types @@ -31,7 +32,6 @@ func MakeHTTPHandler(ctx context.Context, s Service, logger log.Logger) http.Han e := MakeServerEndpoints(s) r.Methods("POST").Path("/users/login").Handler(httptransport.NewServer( - ctx, e.LoginEndpoint, decodeUserRequest, encodeResponse, @@ -63,21 +63,26 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { } func codeFrom(err error) int { - if e, ok := err.(httptransport.Error); ok { - switch e.Err { - case ErrNotFound: - return http.StatusNotFound - case ErrUnauthorized: - return http.StatusUnauthorized - } - switch e.Domain { - case httptransport.DomainDecode: - return http.StatusBadRequest - case httptransport.DomainDo: - return http.StatusServiceUnavailable - default: - return http.StatusInternalServerError - } + switch err { + case ErrNotFound: + return http.StatusNotFound + case ErrNotFound: + return http.StatusNotFound + case ErrUnauthorized: + return http.StatusUnauthorized + default: + return http.StatusInternalServerError } - return http.StatusInternalServerError + // if e, ok := err.(httptransport.Error); ok { + // switch e.Err {domaind + // switch e.Domain { + // case httptransport.DomainDecode: + // return http.StatusBadRequest + // case httptransport.DomainDo: + // return http.StatusServiceUnavailable + // default: + // return http.StatusInternalServerError + // } + // } + // return http.StatusInternalServerError } diff --git a/examples/go-kit/provider/user_service_test.go b/examples/go-kit/provider/user_service_test.go index 589c72d6a..a628ff1d0 100644 --- a/examples/go-kit/provider/user_service_test.go +++ b/examples/go-kit/provider/user_service_test.go @@ -1,145 +1,145 @@ -package provider - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "os" - "os/signal" - "syscall" - "testing" - - "github.com/go-kit/kit/log" - - "golang.org/x/net/context" - - "github.com/gorilla/mux" - "github.com/pact-foundation/pact-go/dsl" - "github.com/pact-foundation/pact-go/types" - "github.com/pact-foundation/pact-go/utils" -) - -var dir, _ = os.Getwd() -var pactDir = fmt.Sprintf("%s/../../pacts", dir) -var logDir = fmt.Sprintf("%s/log", dir) -var port, _ = utils.GetFreePort() - -// Provider States data sets -var billyExists = &UserRepository{ - users: map[string]*User{ - "billy": &User{ - Name: "billy", - username: "billy", - password: "issilly", - }, - }, -} - -var billyDoesNotExist = &UserRepository{} - -var billyUnauthorized = &UserRepository{ - users: map[string]*User{ - "billy": &User{ - Name: "billy", - username: "billy", - password: "issilly1", - }, - }, -} - -// The actual Provider test itself -func TestPact_Provider(t *testing.T) { - go startInstrumentedProvider() - - pact := createPact() - - // Verify the Provider with local Pact Files - err := pact.VerifyProvider(types.VerifyRequest{ - ProviderBaseURL: fmt.Sprintf("http://localhost:%d", port), - PactURLs: []string{fmt.Sprintf("%s/billy-bobby.json", pactDir)}, - ProviderStatesSetupURL: fmt.Sprintf("http://localhost:%d/setup", port), - }) - - if err != nil { - t.Fatal("Error:", err) - } -} - -// Setup the Pact client. -func createPact() dsl.Pact { - // Create Pact connecting to local Daemon - pactDaemonPort := 6666 - return dsl.Pact{ - Port: pactDaemonPort, - Consumer: "billy", - Provider: "bobby", - LogDir: logDir, - PactDir: pactDir, - } -} - -// Starts the provider API with hooks for provider states. -// This essentially mirrors the main.go file, with extra routes added. -func startInstrumentedProvider() { - ctx := context.Background() - var logger log.Logger - { - logger = log.NewLogfmtLogger(os.Stderr) - logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC) - logger = log.NewContext(logger).With("caller", log.DefaultCaller) - } - var s Service - { - s = NewInmemService() - s = LoggingMiddleware(logger)(s) - } - - h := MakeHTTPHandler(ctx, s, logger) - router := h.(*mux.Router) - - // Bolt on 2 extra endpoints to configure Provider states - // http://docs.pact.io/documentation/provider_states.html - router.Methods("POST").Path("/setup").HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - logger.Log("[DEBUG] provider API: states setup") - w.Header().Add("Content-Type", "application/json") - - var state types.ProviderState - - body, err := ioutil.ReadAll(req.Body) - logger.Log(string(body)) - req.Body.Close() - if err != nil { - return - } - - json.Unmarshal(body, &state) - - svc := s.(*loggingMiddleware).next.(*userService) - - // Setup database for different states - if state.State == "User billy exists" { - svc.userDatabase = billyExists - } else if state.State == "User billy is unauthorized" { - svc.userDatabase = billyUnauthorized - } else { - svc.userDatabase = billyDoesNotExist - } - - logger.Log("[DEBUG] configured provider state: ", state.State) - }) - - errs := make(chan error) - go func() { - c := make(chan os.Signal) - signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) - errs <- fmt.Errorf("%s", <-c) - }() - - go func() { - logger.Log(fmt.Sprintf("[DEBUG] starting service on :%d", port)) - errs <- http.ListenAndServe(fmt.Sprintf(":%d", port), h) - }() - - logger.Log("Exit", <-errs) -} +package provider + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os" + "os/signal" + "path/filepath" + "syscall" + "testing" + + "github.com/go-kit/kit/log" + + "context" + + "github.com/gorilla/mux" + "github.com/pact-foundation/pact-go/dsl" + "github.com/pact-foundation/pact-go/types" + "github.com/pact-foundation/pact-go/utils" +) + +var dir, _ = os.Getwd() +var pactDir = fmt.Sprintf("%s/../../pacts", dir) +var logDir = fmt.Sprintf("%s/log", dir) +var port, _ = utils.GetFreePort() + +// Provider States data sets +var billyExists = &UserRepository{ + users: map[string]*User{ + "billy": &User{ + Name: "billy", + username: "billy", + password: "issilly", + }, + }, +} + +var billyDoesNotExist = &UserRepository{} + +var billyUnauthorized = &UserRepository{ + users: map[string]*User{ + "billy": &User{ + Name: "billy", + username: "billy", + password: "issilly1", + }, + }, +} + +// The actual Provider test itself +func TestPact_Provider(t *testing.T) { + go startInstrumentedProvider() + + pact := createPact() + + // Verify the Provider with local Pact Files + err := pact.VerifyProvider(types.VerifyRequest{ + ProviderBaseURL: fmt.Sprintf("http://localhost:%d", port), + PactURLs: []string{filepath.ToSlash(fmt.Sprintf("%s/billy-bobby.json", pactDir))}, + ProviderStatesSetupURL: fmt.Sprintf("http://localhost:%d/setup", port), + }) + + if err != nil { + t.Fatal("Error:", err) + } +} + +// Setup the Pact client. +func createPact() dsl.Pact { + // Create Pact connecting to local Daemon + pactDaemonPort := 6666 + return dsl.Pact{ + Port: pactDaemonPort, + Consumer: "billy", + Provider: "bobby", + LogDir: logDir, + PactDir: pactDir, + } +} + +// Starts the provider API with hooks for provider states. +// This essentially mirrors the main.go file, with extra routes added. +func startInstrumentedProvider() { + ctx := context.Background() + var logger log.Logger + { + logger = log.NewLogfmtLogger(os.Stderr) + logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller) + } + var s Service + { + s = NewInmemService() + s = LoggingMiddleware(logger)(s) + } + + h := MakeHTTPHandler(ctx, s, logger) + router := h.(*mux.Router) + + // Bolt on 2 extra endpoints to configure Provider states + // http://docs.pact.io/documentation/provider_states.html + router.Methods("POST").Path("/setup").HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + logger.Log("[DEBUG] provider API: states setup") + w.Header().Add("Content-Type", "application/json") + + var state types.ProviderState + + body, err := ioutil.ReadAll(req.Body) + logger.Log(string(body)) + req.Body.Close() + if err != nil { + return + } + + json.Unmarshal(body, &state) + + svc := s.(*loggingMiddleware).next.(*userService) + + // Setup database for different states + if state.State == "User billy exists" { + svc.userDatabase = billyExists + } else if state.State == "User billy is unauthorized" { + svc.userDatabase = billyUnauthorized + } else { + svc.userDatabase = billyDoesNotExist + } + + logger.Log("[DEBUG] configured provider state: ", state.State) + }) + + errs := make(chan error) + go func() { + c := make(chan os.Signal) + signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) + errs <- fmt.Errorf("%s", <-c) + }() + + go func() { + logger.Log(fmt.Sprintf("[DEBUG] starting service on :%d", port)) + errs <- http.ListenAndServe(fmt.Sprintf(":%d", port), h) + }() + + logger.Log("Exit", <-errs) +} diff --git a/examples/mux/provider/user_service_test.go b/examples/mux/provider/user_service_test.go index 88df9b48c..f8f4e51fe 100644 --- a/examples/mux/provider/user_service_test.go +++ b/examples/mux/provider/user_service_test.go @@ -1,123 +1,124 @@ -package provider - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "log" - "net" - "net/http" - "os" - "testing" - - "github.com/pact-foundation/pact-go/dsl" - examples "github.com/pact-foundation/pact-go/examples/types" - "github.com/pact-foundation/pact-go/types" - "github.com/pact-foundation/pact-go/utils" -) - -// The actual Provider test itself -func TestPact_Provider(t *testing.T) { - go startInstrumentedProvider() - - pact := createPact() - - // Verify the Provider with local Pact Files - err := pact.VerifyProvider(types.VerifyRequest{ - ProviderBaseURL: fmt.Sprintf("http://localhost:%d", port), - PactURLs: []string{fmt.Sprintf("%s/billy-bobby.json", pactDir)}, - ProviderStatesSetupURL: fmt.Sprintf("http://localhost:%d/setup", port), - }) - - if err != nil { - t.Fatal("Error:", err) - } -} - -// Starts the provider API with hooks for provider states. -// This essentially mirrors the main.go file, with extra routes added. -func startInstrumentedProvider() { - mux := http.NewServeMux() - mux.HandleFunc("/users/login", UserLogin) - mux.HandleFunc("/setup", providerStateSetupFunc) - - ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) - if err != nil { - log.Fatal(err) - } - defer ln.Close() - - log.Printf("API starting: port %d (%s)", port, ln.Addr()) - log.Printf("API terminating: %v", http.Serve(ln, mux)) - -} - -// Set current provider state route. -var providerStateSetupFunc = func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - var state types.ProviderState - - body, err := ioutil.ReadAll(r.Body) - defer r.Body.Close() - - if err != nil { - w.WriteHeader(http.StatusServiceUnavailable) - return - } - - err = json.Unmarshal(body, &state) - if err != nil { - w.WriteHeader(http.StatusServiceUnavailable) - return - } - - // Setup database for different states - if state.State == "User billy exists" { - userRepository = billyExists - } else if state.State == "User billy is unauthorized" { - userRepository = billyUnauthorized - } else { - userRepository = billyDoesNotExist - } -} - -// Configuration / Test Data -var dir, _ = os.Getwd() -var pactDir = fmt.Sprintf("%s/../../pacts", dir) -var logDir = fmt.Sprintf("%s/log", dir) -var port, _ = utils.GetFreePort() - -// Provider States data sets -var billyExists = &examples.UserRepository{ - Users: map[string]*examples.User{ - "billy": &examples.User{ - Name: "billy", - Username: "billy", - Password: "issilly", - }, - }, -} - -var billyDoesNotExist = &examples.UserRepository{} - -var billyUnauthorized = &examples.UserRepository{ - Users: map[string]*examples.User{ - "billy": &examples.User{ - Name: "billy", - Username: "billy", - Password: "issilly1", - }, - }, -} - -// Setup the Pact client. -func createPact() dsl.Pact { - // Create Pact connecting to local Daemon - return dsl.Pact{ - Port: 6666, - Consumer: "billy", - Provider: "bobby", - LogDir: logDir, - PactDir: pactDir, - } -} +package provider + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net" + "net/http" + "os" + "path/filepath" + "testing" + + "github.com/pact-foundation/pact-go/dsl" + examples "github.com/pact-foundation/pact-go/examples/types" + "github.com/pact-foundation/pact-go/types" + "github.com/pact-foundation/pact-go/utils" +) + +// The actual Provider test itself +func TestPact_Provider(t *testing.T) { + go startInstrumentedProvider() + + pact := createPact() + + // Verify the Provider with local Pact Files + err := pact.VerifyProvider(types.VerifyRequest{ + ProviderBaseURL: fmt.Sprintf("http://localhost:%d", port), + PactURLs: []string{filepath.ToSlash(fmt.Sprintf("%s/billy-bobby.json", pactDir))}, + ProviderStatesSetupURL: fmt.Sprintf("http://localhost:%d/setup", port), + }) + + if err != nil { + t.Fatal("Error:", err) + } +} + +// Starts the provider API with hooks for provider states. +// This essentially mirrors the main.go file, with extra routes added. +func startInstrumentedProvider() { + mux := http.NewServeMux() + mux.HandleFunc("/users/login", UserLogin) + mux.HandleFunc("/setup", providerStateSetupFunc) + + ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + log.Fatal(err) + } + defer ln.Close() + + log.Printf("API starting: port %d (%s)", port, ln.Addr()) + log.Printf("API terminating: %v", http.Serve(ln, mux)) + +} + +// Set current provider state route. +var providerStateSetupFunc = func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + var state types.ProviderState + + body, err := ioutil.ReadAll(r.Body) + defer r.Body.Close() + + if err != nil { + w.WriteHeader(http.StatusServiceUnavailable) + return + } + + err = json.Unmarshal(body, &state) + if err != nil { + w.WriteHeader(http.StatusServiceUnavailable) + return + } + + // Setup database for different states + if state.State == "User billy exists" { + userRepository = billyExists + } else if state.State == "User billy is unauthorized" { + userRepository = billyUnauthorized + } else { + userRepository = billyDoesNotExist + } +} + +// Configuration / Test Data +var dir, _ = os.Getwd() +var pactDir = fmt.Sprintf("%s/../../pacts", dir) +var logDir = fmt.Sprintf("%s/log", dir) +var port, _ = utils.GetFreePort() + +// Provider States data sets +var billyExists = &examples.UserRepository{ + Users: map[string]*examples.User{ + "billy": &examples.User{ + Name: "billy", + Username: "billy", + Password: "issilly", + }, + }, +} + +var billyDoesNotExist = &examples.UserRepository{} + +var billyUnauthorized = &examples.UserRepository{ + Users: map[string]*examples.User{ + "billy": &examples.User{ + Name: "billy", + Username: "billy", + Password: "issilly1", + }, + }, +} + +// Setup the Pact client. +func createPact() dsl.Pact { + // Create Pact connecting to local Daemon + return dsl.Pact{ + Port: 6666, + Consumer: "billy", + Provider: "bobby", + LogDir: logDir, + PactDir: pactDir, + } +} diff --git a/scripts/pact.ps1 b/scripts/pact.ps1 new file mode 100644 index 000000000..4429e1bc0 --- /dev/null +++ b/scripts/pact.ps1 @@ -0,0 +1,67 @@ +$pactDir="$env:TEMP\pact" +rmdir -Recurse -Force $pactDir + +Write-Verbose "Creating ${pactDir}" +New-Item -Force -ItemType Directory $pactDir + +Write-Verbose "Creating pact-go binary" +go build -o "$pactDir\pact-go.exe" "github.com\pact-foundation\pact-go" + +Write-Verbose "Creating pact daemon (downloading Ruby binaries)" + +$downloadDir=$env:TEMP +$downloadDirMockService = "$pactDir\pact-mock-service" +$downloadDirPRoviderVerifier = "$pactDir\pact-provider-verifier" +$url = "https://github.com/pact-foundation/pact-ruby-standalone/releases/download/v1.2.5/pact-1.2.5-win32.zip" + +Write-Verbose "Downloading $url" +$zip = "$downloadDir\pact.zip" +if (!(Test-Path "$zip")) { + $downloader = new-object System.Net.WebClient + $downloader.DownloadFile($url, $zip) +} + +Write-Verbose "Extracting $zip" +Add-Type -AssemblyName System.IO.Compression.FileSystem +[System.IO.Compression.ZipFile]::ExtractToDirectory("$zip", $downloadDirMockService) +[System.IO.Compression.ZipFile]::ExtractToDirectory("$zip", $downloadDirPRoviderVerifier) + +Write-Verbose "Moving binaries into position" +mv $downloadDirMockService/pact/* $pactDir/pact-mock-service/ +mv $downloadDirPRoviderVerifier/pact/* $pactDir/pact-provider-verifier/ +Get-ChildItem $pactDir + +Write-Verbose "Starting pact daemon in background" +Start-Process -FilePath "$pactDir\pact-go.exe" -ArgumentList "daemon -v -l DEBUG" -RedirectStandardOutput "pact.log" -RedirectStandardError "pact-error.log" + +Write-Verbose "Running tests" +$env:PACT_INTEGRATED_TESTS=1 +$env:PACT_BROKER_HOST="https://test.pact.dius.com.au" +$env:PACT_BROKER_USERNAME="dXfltyFMgNOFZAxr8io9wJ37iUpY42M" +$env:PACT_BROKER_PASSWORD="O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1" +go test github.com/pact-foundation/pact-go + +$packages = go list github.com/pact-foundation/pact-go/... | where {$_ -inotmatch 'vendor'} | where {$_ -inotmatch 'vendor'} +$curDir=$pwd +foreach ($package in $packages) { + Write-Verbose "Running tests for $package" + go test -v $package +} + +Write-Verbose "Testing examples" +$examples=@("github.com/pact-foundation/pact-go/examples/consumer/goconsumer", "github.com/pact-foundation/pact-go/examples/go-kit/provider", "github.com/pact-foundation/pact-go/examples/mux/provider") +foreach ($example in $examples) { + Write-Verbose "Installing dependencies for example: $example" + cd "$env:GOPATH\src\$example" + go get ./... + Write-Verbose "Running tests for $example" + go test -v . +} + +cd $curDir +Write-Verbose "Shutting down pact processes :)" + +Stop-Process -Name ruby +Stop-Process -Name pact-go + +Write-Verbose "Done!" \ No newline at end of file