Skip to content

Commit

Permalink
chore(test): add ebitengine/purego for pure go libpact_ffi testing
Browse files Browse the repository at this point in the history
  • Loading branch information
YOU54F committed Jan 27, 2025
1 parent 1e5f758 commit 6205dd8
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 30 deletions.
9 changes: 8 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ jobs:
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm]
go-version: ["1.22", "1.23"]
tags: [libpact_cgo,pact_go]
cgo: [0,1]
variant: [debian]
experimental: [false]
include:
Expand All @@ -75,11 +77,16 @@ jobs:
go-version: 1.23
experimental: true
os: ubuntu-24.04-arm
exclude:
- cgo: 0
tags: pact_go
steps:
- uses: actions/checkout@v4

- name: Test dockerfile
run: make docker_test
env:
GO_VERSION: ${{ matrix.go-version }}
IMAGE_VARIANT: ${{ matrix.variant }}
IMAGE_VARIANT: ${{ matrix.variant }}
TAGS: ${{ matrix.tags }}
CGO_ENABLED: ${{ matrix.cgo }}
23 changes: 20 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,23 @@ GITHUB_REPO := "pactflow/example-provider-golang"
CONTRACT_REQUIRING_VERIFICATION_PUBLISHED_WEBHOOK_UUID := "c76b601e-d66a-4eb1-88a4-6ebc50c0df8b"
PACT_CLI="docker run --rm -v ${PWD}:${PWD} -e PACT_BROKER_BASE_URL -e PACT_BROKER_TOKEN pactfoundation/pact-cli:latest"
PACT_GO_VERSION=2.2.0
PACT_DOWNLOAD_DIR=/tmp
export PACT_DOWNLOAD_DIR=/tmp
ifeq ($(OS),Windows_NT)
PACT_DOWNLOAD_DIR=$$TMP
endif

# if cgo is disabled, we will attempt to use ebitengine/purego
CGO_ENABLED?=1
# you can set tags to pact_go or libpact_cgo.
TAGS?=pact_go

# pact-go doesn't support cgo disabling, so lets just always enable it
ifeq ($(CGO_ENABLED),0)
ifeq ($(TAGS),pact_go)
CGO_ENABLED=1
endif
endif

# Only deploy from master
ifeq ($(GIT_BRANCH),master)
DEPLOY_TARGET=deploy
Expand Down Expand Up @@ -47,8 +59,12 @@ fake_ci_webhook:
## Build/test tasks
## =====================

ifdef TAGS
TEST_TAGS := --tags $(TAGS)
endif

test: .env
go test -v -count=1 .
go test -v -count=1 . $(TEST_TAGS)

## =====================
## Deploy tasks
Expand Down Expand Up @@ -131,6 +147,7 @@ docker_build:

docker_test: docker_build
docker run \
-e PACT_FILE=pact.json \
-e CGO_ENABLED=$(CGO_ENABLED) \
-e TAGS=$(TAGS) \
--rm \
pactflow/example-provider-golang-$(IMAGE_VARIANT)
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/ebitengine/purego v0.8.2 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I=
github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
Expand Down
8 changes: 5 additions & 3 deletions lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ import (
func test_provider(port int) int {
verifier := C.pactffi_verifier_new()
C.pactffi_verifier_set_provider_info(verifier, C.CString("pactflow-example-provider-golang"), C.CString("http"), C.CString("localhost"), C.ushort(port), C.CString("/"))
C.pactffi_verifier_add_file_source(verifier, C.CString(os.Getenv("PACT_FILE")))
pactFile := os.Getenv("PACT_FILE")
if pactFile == "" {
pactFile = "pact.json"
}
C.pactffi_verifier_add_file_source(verifier, C.CString(pactFile))

defer C.pactffi_verifier_shutdown(verifier)
result := C.pactffi_verifier_execute(verifier)
Expand All @@ -34,15 +38,13 @@ func test_provider(port int) int {
return int(result)
}


type interactionPart int

const (
INTERACTION_PART_REQUEST interactionPart = iota
INTERACTION_PART_RESPONSE
)


func free(str *C.char) {
C.free(unsafe.Pointer(str))
}
68 changes: 68 additions & 0 deletions lib_pure.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//go:build !cgo
// +build !cgo

// Package native contains the c bindings into the Pact Reference types.

package main

import (
"fmt"
"os"
"path/filepath"
"runtime"

"github.com/ebitengine/purego"
)

func getSystemLibrary() string {
switch runtime.GOOS {
case "darwin":
return "libpact_ffi.dylib"
case "linux":
return "libpact_ffi.so"
case "windows":
return "pact_ffi.dll"
default:
panic(fmt.Errorf("GOOS=%s is not supported", runtime.GOOS))
}
}

type (
size_t uintptr
)

var pactffi_verifier_new func() uintptr
var pactffi_verifier_shutdown func(uintptr)
var pactffi_verifier_set_provider_info func(uintptr, string, string, string, uint16, string)
var pactffi_verifier_add_file_source func(uintptr, string)
var pactffi_verifier_execute func(uintptr) int32

func init() {
libpact_ffi, err := openLibrary(filepath.Join(os.Getenv("PACT_DOWNLOAD_DIR"), getSystemLibrary()))
if err != nil {
panic(err)
}
purego.RegisterLibFunc(&pactffi_verifier_new, libpact_ffi, "pactffi_verifier_new")
purego.RegisterLibFunc(&pactffi_verifier_set_provider_info, libpact_ffi, "pactffi_verifier_set_provider_info")
purego.RegisterLibFunc(&pactffi_verifier_add_file_source, libpact_ffi, "pactffi_verifier_add_file_source")
purego.RegisterLibFunc(&pactffi_verifier_execute, libpact_ffi, "pactffi_verifier_execute")
purego.RegisterLibFunc(&pactffi_verifier_shutdown, libpact_ffi, "pactffi_verifier_shutdown")
}

func test_provider(port int) int {
verifier := pactffi_verifier_new()
pactffi_verifier_set_provider_info(verifier, "pactflow-example-provider-golang", "http", "localhost", uint16(port), "/")
pactFile := os.Getenv("PACT_FILE")
if pactFile == "" {
pactFile = "pact.json"
}
pactffi_verifier_add_file_source(verifier, pactFile)
result := pactffi_verifier_execute(verifier)
pactffi_verifier_shutdown(verifier)
if result != 0 {
fmt.Printf("Result is not 0: %d", result)
} else {
fmt.Print("Result success")
}
return int(result)
}
11 changes: 11 additions & 0 deletions lib_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//go:build (darwin || linux) && !cgo
// +build darwin linux
// +build !cgo

package main

import "github.com/ebitengine/purego"

func openLibrary(name string) (uintptr, error) {
return purego.Dlopen(name, purego.RTLD_NOW|purego.RTLD_GLOBAL)
}
11 changes: 11 additions & 0 deletions lib_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//go:build windows && !cgo
// +build windows,!cgo

package main

import "golang.org/x/sys/windows"

func openLibrary(name string) (uintptr, error) {
handle, err := windows.LoadLibrary(name)
return uintptr(handle), err
}
12 changes: 12 additions & 0 deletions test_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import (
"fmt"
"github.com/gin-gonic/gin"
)

func startProvider(port int) {
router := gin.Default()
router.GET("/product/:id", GetProduct)
router.Run(fmt.Sprintf(":%d", port))
}
18 changes: 7 additions & 11 deletions user_service_libpact_ffi_test.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
//go:build libpact_cgo
// +build libpact_cgo

package main

import (
"testing"
// "github.com/pact-foundation/pact-go/v2/provider"

"github.com/pact-foundation/pact-go/v2/utils"
)

func TestLibPactFfiProvider(t *testing.T) {
go startProvider()
var port, _ = utils.GetFreePort()
go startProvider(port)

var res = test_provider(port)
if res != 0 {
t.Fatalf("%v", res)
}

}

// func startProvider() {
// router := gin.Default()
// router.GET("/product/:id", GetProduct)
// router.Run(fmt.Sprintf(":%d", port))
// }

// Configuration / Test Data
// var port, _ = utils.GetFreePort()
22 changes: 10 additions & 12 deletions user_service_pact_go_test.go
Original file line number Diff line number Diff line change
@@ -1,37 +1,35 @@
//go:build pact_go
// +build pact_go

package main

import (
"fmt"
"os"
"testing"

"github.com/gin-gonic/gin"
"github.com/pact-foundation/pact-go/v2/provider"
"github.com/pact-foundation/pact-go/v2/utils"
)

func TestPactGoProvider(t *testing.T) {
go startProvider()
var port, _ = utils.GetFreePort()
go startProvider(port)

verifier := provider.NewVerifier()
verifyRequest := provider.VerifyRequest{
Provider: "pactflow-example-provider-golang",
ProviderBaseURL: fmt.Sprintf("http://127.0.0.1:%d", port),
}
verifyRequest.PactFiles = []string{os.Getenv("PACT_FILE")}
pactFile := os.Getenv("PACT_FILE")
if pactFile == "" {
pactFile = "pact.json"
}
verifyRequest.PactFiles = []string{pactFile}

err := verifier.VerifyProvider(t, verifyRequest)
if err != nil {
t.Fatalf("%v", err)
}

}

func startProvider() {
router := gin.Default()
router.GET("/product/:id", GetProduct)
router.Run(fmt.Sprintf(":%d", port))
}

// Configuration / Test Data
var port, _ = utils.GetFreePort()

0 comments on commit 6205dd8

Please sign in to comment.