Skip to content

Commit

Permalink
feat: initial plugin API in core
Browse files Browse the repository at this point in the history
  • Loading branch information
mefellows committed Mar 20, 2022
1 parent 6ec7402 commit 445d91b
Show file tree
Hide file tree
Showing 207 changed files with 54,216 additions and 20,698 deletions.
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ deps:
go get github.com/modocache/gover; \
go get github.com/mitchellh/gox; \
cd -
@echo "--- 🐿 Installing plugins"
mkdir -p ~/.pact/plugins/protobuf-0.0.3
wget https://github.com/pactflow/pact-protobuf-plugin/releases/download/v-0.0.3/pact-plugin.json -O ~/.pact/plugins/protobuf-0.0.3/pact-plugin.json
wget https://github.com/pactflow/pact-protobuf-plugin/releases/download/v-0.0.3/pact-protobuf-plugin-linux-x86_64.gz -O ~/.pact/plugins/protobuf-0.0.3/pact-protobuf-plugin-linux-x86_64.gz
gunzip -N ~/.pact/plugins/protobuf-0.0.3/pact-protobuf-plugin-linux-x86_64.gz
chmod +x ~/.pact/plugins/protobuf-0.0.3/pact-protobuf-plugin

goveralls:
goveralls -service="travis-ci" -coverprofile=coverage.txt -repotoken $(COVERALLS_TOKEN)
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ module github.com/pact-foundation/pact-go/v2
go 1.15

require (
github.com/golang/protobuf v1.3.3 // indirect
github.com/golang/protobuf v1.5.0
github.com/hashicorp/go-getter v1.5.3
github.com/hashicorp/go-version v1.3.0
github.com/hashicorp/logutils v1.0.0
github.com/spf13/afero v1.6.0
github.com/spf13/cobra v1.1.3
github.com/stretchr/testify v1.7.0
golang.org/x/tools v0.1.2 // indirect
google.golang.org/protobuf v1.27.1
)
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,14 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
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=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
Expand Down Expand Up @@ -322,6 +325,7 @@ golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
Expand Down Expand Up @@ -349,6 +353,9 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
Expand Down
85 changes: 85 additions & 0 deletions internal/native/mock_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ struct InteractionHandle {
unsigned int interaction_ref;
};
typedef enum InteractionPart {
InteractionPart_Request,
InteractionPart_Response,
} InteractionPart;
/// Wraps a Pact model struct
typedef struct PactHandle PactHandle;
struct PactHandle {
Expand Down Expand Up @@ -147,6 +152,10 @@ void pactffi_with_pact_metadata(PactHandle pact, const char *namespace, const ch
//int pactffi_log_to_file(const char *file_name, int level_filter);
//char* pactffi_fetch_log_buffer();
int pactffi_using_plugin(PactHandle pact, const char *plugin_name, const char *plugin_version);
void pactffi_cleanup_plugins(PactHandle pact);
int pactffi_interaction_contents(InteractionHandle interaction, int interaction_part, const char *content_type, const char *contents);
*/
import "C"

Expand Down Expand Up @@ -448,6 +457,40 @@ func (m *MockServer) WithMetadata(namespace, k, v string) *MockServer {
return m
}

// NewInteraction initialises a new interaction for the current contract
func (m *MockServer) UsingPlugin(pluginName string, pluginVersion string) error {
cPluginName := C.CString(pluginName)
defer free(cPluginName)
cPluginVersion := C.CString(pluginVersion)
defer free(cPluginVersion)

r := C.pactffi_using_plugin(m.pact.handle, cPluginName, cPluginVersion)

// 1 - A general panic was caught.
// 2 - Failed to load the plugin.
// 3 - Pact Handle is not valid.
res := int(r)
switch res {
case 1:
return ErrPluginGenericPanic
case 2:
return ErrPluginFailed
case 3:
return ErrHandleNotFound
default:
if res != 0 {
return fmt.Errorf("an unknown error (code: %v) occurred when adding a plugin for the test. Received error code:", res)
}
}

return nil
}

// NewInteraction initialises a new interaction for the current contract
func (m *MockServer) CleanupPlugins(pluginName string, pluginVersion string) {
C.pactffi_cleanup_plugins(m.pact.handle)
}

// NewInteraction initialises a new interaction for the current contract
func (m *MockServer) NewInteraction(description string) *Interaction {
cDescription := C.CString(description)
Expand All @@ -461,6 +504,45 @@ func (m *MockServer) NewInteraction(description string) *Interaction {
return i
}

// NewInteraction initialises a new interaction for the current contract
// TODO: why specify the name and version twice?
func (i *Interaction) WithPluginInteractionContents(interactionPart interactionType, contentType string, contents string) error {
cContentType := C.CString(contentType)
defer free(cContentType)
cContents := C.CString(contents)
defer free(cContents)

r := C.pactffi_interaction_contents(i.handle, C.int(interactionPart), cContentType, cContents)

// 1 - A general panic was caught.
// 2 - The mock server has already been started.
// 3 - The interaction handle is invalid.
// 4 - The content type is not valid.
// 5 - The contents JSON is not valid JSON.
// 6 - The plugin returned an error.
res := int(r)
switch res {
case 1:
return ErrPluginGenericPanic
case 2:
return ErrPluginMockServerStarted
case 3:
return ErrPluginInteractionHandleInvalid
case 4:
return ErrPluginInvalidContentType
case 5:
return ErrPluginInvalidJson
case 6:
return ErrPluginSpecificError
default:
if res != 0 {
return fmt.Errorf("an unknown error (code: %v) occurred when adding a plugin for the test. Received error code:", res)
}
}

return nil
}

func (i *Interaction) UponReceiving(description string) *Interaction {
cDescription := C.CString(description)
defer free(cDescription)
Expand Down Expand Up @@ -761,6 +843,9 @@ var (

// ErrNoInteractions indicates no Interactions have been registered to a mock server, and cannot be started/stopped until at least one is added
ErrNoInteractions = fmt.Errorf("no interactions have been registered for the mock server")

// ErrPluginFailed indicates the plugin could not be started
ErrPluginFailed = fmt.Errorf("the plugin could not be started")
)

// Log Errors
Expand Down
55 changes: 55 additions & 0 deletions internal/native/mock_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"net/http"
"testing"

"github.com/golang/protobuf/proto"
"github.com/pact-foundation/pact-go/v2/log"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -161,6 +163,59 @@ func TestHandleBasedHTTPTests(t *testing.T) {
assert.NoError(t, err)
}

func TestPluginInteraction(t *testing.T) {
tmpPactFolder, err := ioutil.TempDir("", "pact-go")
assert.NoError(t, err)
log.SetLogLevel("trace")

m := NewHTTPMockServer("test-plugin-consumer", "test-plugin-provider")

// Protobuf plugin test
m.UsingPlugin("protobuf", "0.0.3")
m.WithSpecificationVersion(SPECIFICATION_VERSION_V4)

i := m.NewInteraction("some plugin interaction")

protobufInteraction := `{
"pact:proto": "/Users/matthewfellows/go/src/github.com/pact-foundation/pact-go/internal/native/plugin.proto",
"pact:message-type": "InitPluginRequest",
"pact:content-type": "application/protobuf",
"implementation": "notEmpty('pact-go-driver')",
"version": "matching(semver, '0.0.0')"
}`

i.UponReceiving("some interaction").
Given("plugin state").
WithRequest("GET", "/protobuf").
WithStatus(200).
WithPluginInteractionContents(INTERACTION_PART_RESPONSE, "application/protobuf", protobufInteraction)

port, err := m.Start("0.0.0.0:0", false)
assert.NoError(t, err)
defer m.CleanupMockServer(port)

res, err := http.Get(fmt.Sprintf("http://0.0.0.0:%d/protobuf", port))
assert.NoError(t, err)

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

initPluginRequest := &InitPluginRequest{}
proto.Unmarshal(bytes, initPluginRequest)
assert.NoError(t, err)

assert.Equal(t, initPluginRequest.Implementation, "pact-go-driver", initPluginRequest.Version, "0.0.0")

mismatches := m.MockServerMismatchedRequests(port)
if len(mismatches) != 0 {
assert.Len(t, mismatches, 0)
t.Log(mismatches)
}

err = m.WritePactFile(port, tmpPactFolder)
assert.NoError(t, err)
}

var pactSimple = `{
"consumer": {
"name": "consumer"
Expand Down

0 comments on commit 445d91b

Please sign in to comment.