Skip to content

Commit

Permalink
Merge pull request #291 from pact-foundation/example/avro
Browse files Browse the repository at this point in the history
feat: add an Avro example
  • Loading branch information
mefellows committed Jul 18, 2023
2 parents b54ab72 + cc8e0d9 commit 6de0413
Show file tree
Hide file tree
Showing 9 changed files with 222 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/test.yml
Expand Up @@ -31,6 +31,10 @@ jobs:
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}
- uses: actions/setup-java@v3 # Needed for the Avro example
with:
distribution: 'zulu'
java-version: '17'
- name: Test
run: APP_BRANCH=${APP_REF:11} DOCKER_GATEWAY_HOST=172.17.0.1 DOCKER_HOST_HTTP="http://172.17.0.1" make
- name: Install goveralls
Expand Down
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -46,6 +46,7 @@ download_plugins:
~/.pact/bin/pact-plugin-cli -y install https://github.com/pactflow/pact-protobuf-plugin/releases/tag/v-0.3.4
~/.pact/bin/pact-plugin-cli -y install https://github.com/pact-foundation/pact-plugins/releases/tag/csv-plugin-0.0.1
~/.pact/bin/pact-plugin-cli -y install https://github.com/mefellows/pact-matt-plugin/releases/tag/v0.0.9
~/.pact/bin/pact-plugin-cli -y install https://github.com/austek/pact-avro-plugin/releases/tag/v0.0.3

cli:
@if [ ! -d pact/bin ]; then\
Expand Down
103 changes: 103 additions & 0 deletions examples/avro/avro_consumer_test.go
@@ -0,0 +1,103 @@
//go:build consumer
// +build consumer

package avro

import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"testing"

"github.com/pact-foundation/pact-go/v2/consumer"

"path/filepath"

"github.com/stretchr/testify/assert"
)

var dir, _ = os.Getwd()

func TestAvroHTTP(t *testing.T) {
mockProvider, err := consumer.NewV4Pact(consumer.MockHTTPProviderConfig{
Consumer: "AvroConsumer",
Provider: "AvroProvider",
PactDir: filepath.ToSlash(fmt.Sprintf("%s/../pacts", dir)),
})
assert.NoError(t, err)

dir, _ := os.Getwd()
path := fmt.Sprintf("%s/user.avsc", dir)

avroResponse := `{
"pact:avro": "` + path + `",
"pact:record-name": "User",
"pact:content-type": "avro/binary",
"id": "matching(number, 1)",
"username": "notEmpty('matt')"
}`

// Set up our expected interactions.
err = mockProvider.
AddInteraction().
UponReceiving("A request to do get some Avro stuff").
UsingPlugin(consumer.PluginConfig{
Plugin: "avro",
Version: "0.0.2",
}).
WithRequest("GET", "/avro").
WillRespondWith(200, func(res *consumer.V4InteractionWithPluginResponseBuilder) {
res.PluginContents("avro/binary", avroResponse)
}).
ExecuteTest(t, func(msc consumer.MockServerConfig) error {
resp, err := callServiceHTTP(msc)

assert.Equal(t, int64(1), resp.ID)
assert.Equal(t, "matt", resp.Username) // ??????!

return err
})
assert.NoError(t, err)
}

func callServiceHTTP(msc consumer.MockServerConfig) (*User, error) {
client := &http.Client{}
req := &http.Request{
Method: "GET",
URL: &url.URL{
Host: fmt.Sprintf("%s:%d", msc.Host, msc.Port),
Scheme: "http",
Path: "/avro",
},
Header: make(http.Header),
}

req.Header.Set("Content-Type", "avro/binary;record=User")

res, err := client.Do(req)

if err != nil {
return nil, err
}

bytes, err := ioutil.ReadAll(res.Body)

if err != nil {
return nil, err
}

codec := getCodec()
native, _, err := codec.NativeFromBinary(bytes)
if err != nil {
return nil, err
}

user := &User{
ID: native.(map[string]interface{})["id"].(int64),
Username: native.(map[string]interface{})["username"].(string),
}

return user, err
}
71 changes: 71 additions & 0 deletions examples/avro/avro_provider_test.go
@@ -0,0 +1,71 @@
//go:build provider
// +build provider

package avro

import (
"fmt"
"log"
"net/http"

"os"
"path/filepath"
"testing"

"github.com/pact-foundation/pact-go/v2/provider"
"github.com/pact-foundation/pact-go/v2/utils"
"github.com/stretchr/testify/assert"
)

var dir, _ = os.Getwd()
var pactDir = fmt.Sprintf("%s/../pacts", dir)

func TestAvroHTTPProvider(t *testing.T) {
httpPort, _ := utils.GetFreePort()

// Start provider API in the background
go startHTTPProvider(httpPort)

verifier := provider.NewVerifier()

// Verify the Provider with local Pact Files
err := verifier.VerifyProvider(t, provider.VerifyRequest{
ProviderBaseURL: fmt.Sprintf("http://127.0.0.1:%d", httpPort),
Provider: "AvroProvider",
PactFiles: []string{
filepath.ToSlash(fmt.Sprintf("%s/AvroConsumer-AvroProvider.json", pactDir)),
},
})

assert.NoError(t, err)
}

func startHTTPProvider(port int) {
mux := http.NewServeMux()

mux.HandleFunc("/avro", func(w http.ResponseWriter, req *http.Request) {
w.Header().Add("Content-Type", "avro/binary;record=User")

user := &User{
ID: 1,
Username: "matt",
// Username: "sally", // matching rules not supported?
}

codec := getCodec()
binary, err := codec.BinaryFromNative(nil, map[string]interface{}{
"id": user.ID,
"username": user.Username,
})
if err != nil {
log.Println("ERROR: ", err)
w.WriteHeader(500)
} else {
fmt.Fprintf(w, string(binary))
w.WriteHeader(200)
}
})

log.Printf("started HTTP server on port: %d\n", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf("127.0.0.1:%d", port), mux))
}
21 changes: 21 additions & 0 deletions examples/avro/codec.go
@@ -0,0 +1,21 @@
package avro

import (
"io/ioutil"

"github.com/linkedin/goavro/v2"
)

func getCodec() *goavro.Codec {
schema, err := ioutil.ReadFile("user.avsc")
if err != nil {
panic(err)
}

codec, err := goavro.NewCodec(string(schema))
if err != nil {
panic(err)
}

return codec
}
9 changes: 9 additions & 0 deletions examples/avro/user.avsc
@@ -0,0 +1,9 @@
{
"type": "record",
"name": "User",
"namespace": "io.pact",
"fields" : [
{"name": "id", "type": "long"},
{"name": "username", "type": "string"}
]
}
6 changes: 6 additions & 0 deletions examples/avro/user.go
@@ -0,0 +1,6 @@
package avro

type User struct {
ID int64 `json:"id"`
Username string `json:"username"`
}
2 changes: 2 additions & 0 deletions go.mod
Expand Up @@ -7,6 +7,7 @@ require (
github.com/hashicorp/go-getter v1.7.1
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/logutils v1.0.0
github.com/linkedin/goavro/v2 v2.12.0
github.com/spf13/afero v1.9.5
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.3
Expand All @@ -25,6 +26,7 @@ require (
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/s2a-go v0.1.4 // indirect
github.com/google/uuid v1.3.0 // indirect
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Expand Up @@ -848,7 +848,9 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
Expand Down Expand Up @@ -971,6 +973,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/linkedin/goavro/v2 v2.12.0 h1:rIQQSj8jdAUlKQh6DttK8wCRv4t4QO09g1C4aBWXslg=
github.com/linkedin/goavro/v2 v2.12.0/go.mod h1:KXx+erlq+RPlGSPmLF7xGo6SAbh8sCQ53x064+ioxhk=
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o=
Expand Down Expand Up @@ -1031,6 +1035,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
Expand Down

0 comments on commit 6de0413

Please sign in to comment.