diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index e42782c94..2d383450b 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -14,11 +14,6 @@ jobs: fail-fast: false matrix: go-version: [ - # 1.19.x, # Ended 06 Sep 2023 - # 1.20.x, # Ended 06 Feb 2024 - # 1.21.x, # Ended 13 Aug 2024 - # 1.22.x, # Ended 11 Feb 2025 - 1.23.x, 1.24.x, 1.25.x, ] @@ -41,8 +36,7 @@ jobs: # working-directory: somedir # Optional: golangci-lint command line arguments. - # ignore the lib.go file as it only contains cgo annotations - args: --exclude-files internal/native/lib.go --timeout 2m + args: --timeout 2m # Optional: show only new issues if it's a pull request. The default value is `false`. # only-new-issues: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 208f06684..e7662e2cb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,16 +13,24 @@ on: description: 'Skip alpine provider tests' required: false default: 'false' - + log_level: + description: 'Log level' + type: choice + required: true + default: 'INFO' + options: + - 'INFO' + - 'DEBUG' + - 'TRACE' env: PACT_BROKER_BASE_URL: https://testdemo.pactflow.io PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }} REACT_APP_API_BASE_URL: http://localhost:8080 APP_SHA: ${{ github.sha }} APP_REF: ${{ github.ref }} - LD_LIBRARY_PATH: /tmp - PACT_GO_LIB_DOWNLOAD_PATH: /tmp - LOG_LEVEL: debug + # PACT_GO_LIB_DOWNLOAD_PATH: /tmp + # PACT_LD_LIBRARY_PATH: /tmp + LOG_LEVEL: ${{ github.event.inputs.log_level || 'INFO' }} COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: @@ -31,17 +39,11 @@ jobs: fail-fast: false matrix: go-version: [ # https://endoflife.date/go - # 1.17.x, # Ended 02 Aug 2022 - # 1.18.x, # Ended 01 Feb 2023 - # 1.19.x, # Ended 06 Sep 2023 - # 1.20.x, # Ended 06 Feb 2024 - # 1.21.x, # Ended 13 Aug 2024 - # 1.22.x, # Ended 11 Feb 2025 - 1.23.x, 1.24.x, 1.25.x, ] - os: [ubuntu-latest, macos-13, macos-14, windows-latest] + os: [ubuntu-latest, macos-15, macos-15-intel, windows-latest] + cgo: [0,1] runs-on: ${{ matrix.os }} steps: - name: Checkout code @@ -54,16 +56,23 @@ jobs: with: distribution: 'zulu' java-version: '17' + - name: "Set CGO_ENABLED: ${{ matrix.cgo }}" + if: matrix.os == 'windows-latest' + run: | + "CGO_ENABLED=${{ matrix.cgo }}" >> $env:GITHUB_ENV + - name: "Set CGO_ENABLED: ${{ matrix.cgo }}" + if: matrix.os != 'windows-latest' + run: | + echo "CGO_ENABLED=${{ matrix.cgo }}" >> $GITHUB_ENV - if: matrix.os == 'macos-14' run: brew install protobuf - name: Test if: matrix.os == 'ubuntu-latest' run: APP_BRANCH=${APP_REF:11} DOCKER_GATEWAY_HOST=172.17.0.1 DOCKER_HOST_HTTP="http://172.17.0.1" make - - name: Set CGO_LDFLAGS / pact_ffi lib on PATH - if: matrix.os == 'windows-latest' - run: | - "CGO_LDFLAGS=-L$env:TMP" >> $env:GITHUB_ENV - "$env:TMP" >> $env:GITHUB_PATH + # - name: Set PACT_LD_LIBRARY_PATH + # if: matrix.os == 'windows-latest' + # run: | + # "PACT_LD_LIBRARY_PATH=$env:TMP" >> $env:GITHUB_ENV - name: Test (unit) if: matrix.os != 'ubuntu-latest' run: make test @@ -78,26 +87,23 @@ jobs: run: goveralls -coverprofile=coverage.txt -service=github -parallel - uses: actions/upload-artifact@v5 with: - name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.go-version }}-${{ matrix.os }}.zip + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.go-version }}-${{ matrix.os }}-${{matrix.cgo}}.zip path: ~/.pact/plugins/**/plugin.log if: ${{ always() }} test-containers: continue-on-error: ${{ matrix.experimental }} runs-on: ${{ matrix.os }} - name: ${{ matrix.os }}-${{ matrix.variant }}-${{ matrix.go-version }}-test-container + name: ${{ matrix.os }}-${{ matrix.variant }}-${{ matrix.go-version }}-test-container-cgo-${{ matrix.cgo }} strategy: fail-fast: false matrix: os: [ubuntu-latest, ubuntu-24.04-arm] - go-version: ["1.23", "1.24", "1.25"] + go-version: ["1.24", "1.25"] variant: [debian] experimental: [false] + cgo: [0,1] include: - - variant: alpine - go-version: 1.23 - experimental: true - os: ubuntu-latest - variant: alpine go-version: 1.24 experimental: true @@ -106,10 +112,6 @@ jobs: go-version: 1.25 experimental: true os: ubuntu-latest - - variant: alpine - go-version: 1.23 - experimental: true - os: ubuntu-24.04-arm - variant: alpine go-version: 1.24 experimental: true @@ -133,6 +135,7 @@ jobs: env: GO_VERSION: ${{ matrix.go-version }} IMAGE_VARIANT: ${{ matrix.variant }} + CGO_ENABLED: ${{ matrix.cgo }} finish: needs: [test,test-containers] diff --git a/Dockerfile.alpine b/Dockerfile.alpine index 2a332ce7e..b9291ac6e 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -1,5 +1,5 @@ -ARG VERSION=1.23 -FROM golang:${VERSION}-alpine +ARG GO_VERSION=1.24 +FROM golang:${GO_VERSION}-alpine RUN apk add --no-cache curl gcc musl-dev gzip openjdk17-jre bash protoc protobuf-dev make file diff --git a/Dockerfile.debian b/Dockerfile.debian index d8da299b3..a86f67aac 100644 --- a/Dockerfile.debian +++ b/Dockerfile.debian @@ -1,5 +1,5 @@ -ARG VERSION=latest -FROM golang:${VERSION} +ARG GO_VERSION=latest +FROM golang:${GO_VERSION} RUN apt-get update && apt-get install -y openjdk-21-jre file protobuf-compiler COPY . /go/src/github.com/pact-foundation/pact-go diff --git a/Makefile b/Makefile index d52206c69..cf064c782 100755 --- a/Makefile +++ b/Makefile @@ -9,15 +9,21 @@ PLUGIN_PACT_CSV_VERSION=0.0.6 PLUGIN_PACT_MATT_VERSION=0.1.1 PLUGIN_PACT_AVRO_VERSION=0.0.6 -GO_VERSION?=1.23 +GO_VERSION?=1.24 IMAGE_VARIANT?=debian ci:: docker deps clean bin test pact -PACT_DOWNLOAD_DIR=/tmp -ifeq ($(OS),Windows_NT) - PACT_DOWNLOAD_DIR=$$TMP +# PACT_DOWNLOAD_DIR=/tmp +# ifeq ($(OS),Windows_NT) +# PACT_DOWNLOAD_DIR=$$TMP +# endif + +CGO_ENABLED?=1 +ifeq ($(CGO_ENABLED),0) + SKIP_RACE=true endif SKIP_RACE?=false RACE?=-race +SKIP_SIGNAL_HANDLERS?=false ifeq ($(SKIP_RACE),true) RACE= endif @@ -49,6 +55,7 @@ docker_test: docker_build -e LOG_LEVEL=INFO \ -e SKIP_PROVIDER_TESTS=$(SKIP_PROVIDER_TESTS) \ -e SKIP_RACE=$(SKIP_RACE) \ + -e CGO_ENABLED=$(CGO_ENABLED) \ --rm \ -it \ pactfoundation/pact-go-test-$(IMAGE_VARIANT) \ @@ -58,6 +65,7 @@ docker_pact: docker_build -e LOG_LEVEL=INFO \ -e SKIP_PROVIDER_TESTS=$(SKIP_PROVIDER_TESTS) \ -e SKIP_RACE=$(SKIP_RACE) \ + -e CGO_ENABLED=$(CGO_ENABLED) \ --rm \ pactfoundation/pact-go-test-$(IMAGE_VARIANT) \ /bin/sh -c "make pact_local" @@ -66,6 +74,7 @@ docker_test_all: docker_build -e LOG_LEVEL=INFO \ -e SKIP_PROVIDER_TESTS=$(SKIP_PROVIDER_TESTS) \ -e SKIP_RACE=$(SKIP_RACE) \ + -e CGO_ENABLED=$(CGO_ENABLED) \ --rm \ pactfoundation/pact-go-test-$(IMAGE_VARIANT) \ /bin/sh -c "make test && make pact_local" @@ -117,18 +126,18 @@ cli: install: bin echo "--- 🐿 Installing Pact FFI dependencies" - ./build/pact-go -l DEBUG install --libDir $(PACT_DOWNLOAD_DIR) + ./build/pact-go -l DEBUG install pact: clean install docker @echo "--- 🔨 Running Pact examples" - go test -v -tags=consumer -count=1 github.com/pact-foundation/pact-go/v2/examples/... + ./build/pact-go test -v -tags=consumer -count=1 github.com/pact-foundation/pact-go/v2/examples/... make publish - go test -v -timeout=30s -tags=provider -count=1 github.com/pact-foundation/pact-go/v2/examples/... + ./build/pact-go test -v -timeout=30s -tags=provider -count=1 github.com/pact-foundation/pact-go/v2/examples/... pact_local: clean download_plugins install @echo "--- 🔨 Running Pact examples" - go test -v -tags=consumer -count=1 github.com/pact-foundation/pact-go/v2/examples/... + ./build/pact-go test -v -tags=consumer -count=1 github.com/pact-foundation/pact-go/v2/examples/... if [ "$(SKIP_PROVIDER_TESTS)" != "true" ]; then \ - SKIP_PUBLISH=true go test -v -timeout=30s -tags=provider -count=1 github.com/pact-foundation/pact-go/v2/examples/...; \ + SKIP_PUBLISH=true ./build/pact-go test -v -timeout=30s -tags=provider -count=1 github.com/pact-foundation/pact-go/v2/examples/...; \ fi publish: @@ -151,7 +160,7 @@ test: deps install @echo "mode: count" > coverage.txt @for d in $$(go list ./... | grep -v vendor | grep -v examples); \ do \ - go test -v $(RACE) -coverprofile=profile.out $(PROVIDER_TEST_TAGS) -covermode=atomic $$d; \ + ./build/pact-go test -v $(RACE) -coverprofile=profile.out $(PROVIDER_TEST_TAGS) -covermode=atomic $$d; \ if [ $$? != 0 ]; then \ exit 1; \ fi; \ @@ -164,7 +173,7 @@ test: deps install testrace: - go test $(RACE) $(TEST) $(TESTARGS) + ./build/pact-go test $(RACE) $(TEST) $(TESTARGS) updatedeps: go get -d -v -p 2 ./... @@ -182,5 +191,5 @@ protos: .PHONY: grpc-test grpc-test: rm -rf ./examples/pacts - go test -v -tags=consumer -count=1 github.com/pact-foundation/pact-go/v2/examples/grpc - go test -v -timeout=30s -tags=provider -count=1 github.com/pact-foundation/pact-go/v2/examples/grpc + ./build/pact-go test -v -tags=consumer -count=1 github.com/pact-foundation/pact-go/v2/examples/grpc + ./build/pact-go test -v -timeout=30s -tags=provider -count=1 github.com/pact-foundation/pact-go/v2/examples/grpc diff --git a/README.md b/README.md index 3ab2ab1c3..84ab7e067 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,8 @@ go install github.com/pact-foundation/pact-go/v2 pact-go -l DEBUG install # 🚀 now write some tests! +pact-go test +# pact-go test is a wrapper around go test, and sets the PACT_LD_LIBRARY_PATH environment variable to the pact required libraries ``` If the `pact-go` command above is not found, make sure that `$GOPATH/bin` is in your path. I.e., @@ -100,56 +102,14 @@ export PATH=$PATH:$GOPATH/bin You can also keep the library versions up to date by running the `version.CheckVersion()` function. -Set `PACT_GO_LIB_DOWNLOAD_PATH` env var if you have installed the library in a non-standard location. - -
Pre-Requisites - -### Pre-Requisites - -- `cgo` - - Pact relies on C shared libraries compiled from Rust - - `CGO_ENABLED=1` (check with `go env`) - -#### Linux - -- Install `gcc` package - -#### MacOS - -- Install the Xcode Command line tools - -By default, pact-go install will attempt to install in `/usr/local/lib`. - -Note this is not user-writable, so `pact-go install` must be run with `sudo`. - -An alternative is to install to `/tmp` via `pact-go -l DEBUG install --libDir /tmp` - -#### Windows - -- Install `gcc` - - `choco install mingw` - - `scoop install mingw` - -- Add location of the pact-go installed shared library to - - `PATH` - - `CGO_LDFLAGS` - -##### Powershell - -- `$env:Path += ";$env:TMP"` -- `$env:CGO_LDFLAGS = "-L$env:TMP"` - -- Command Prompt -- `set PATH="%PATH%;%TMP%"` -- `set CGO_LDFLAGS="-L%TMP%"` - -
+- Set `PACT_GO_LIB_DOWNLOAD_PATH` env var if you have installed the library in a non-standard location. +- Set `PACT_LD_LIBRARY_PATH` env var if you have installed the library in a non-standard location and are running `go test` directly without the `pact-go test` wrapper.
Manual Installation Instructions ### Manual -Download the latest `Pact FFI Library` [library] for your OS, and install onto a standard library search path (we suggest: `/usr/local/lib` on MacOS/Linux): +Download the latest `Pact FFI Library` [library] for your OS. Ensure you have the correct extension for your OS: @@ -160,13 +120,12 @@ Ensure you have the correct extension for your OS: ```sh wget https://github.com/pact-foundation/pact-reference/releases/download/libpact_ffi-v0.4.21/libpact_ffi-macos-x86_64.dylib.gz gunzip libpact_ffi-macos-x86_64.dylib.gz -mv libpact_ffi-macos-x86_64.dylib /usr/local/lib/libpact_ffi.dylib ``` Test the installation: ```sh -pact-go help +PACT_LD_LIBRARY_PATH=${PATH_TO_LIB} pact-go check ```
diff --git a/command/check.go b/command/check.go index 01eb52c06..cbc86161f 100644 --- a/command/check.go +++ b/command/check.go @@ -27,7 +27,7 @@ var checkCmd = &cobra.Command{ log.Println("[INFO] set lib dir target to", libDir) i.SetLibDir(libDir) } - + if err = i.CheckPackageInstall(); err != nil { log.Println("[DEBUG] error from CheckPackageInstall:", err) log.Println("[ERROR] Your Pact library installation is out of date. Run `pact-go install` to correct") diff --git a/command/install.go b/command/install.go index 55436d039..5dfebbaef 100644 --- a/command/install.go +++ b/command/install.go @@ -37,6 +37,8 @@ var installCmd = &cobra.Command{ log.Println("[ERROR] Your Pact library installation is out of date and we were unable to download a newer one for you:", err) os.Exit(1) } + + i.SetConfigLibDir(i.GetActualLibDir()) }, } diff --git a/command/test.go b/command/test.go new file mode 100644 index 000000000..7e5c7b80d --- /dev/null +++ b/command/test.go @@ -0,0 +1,72 @@ +package command + +import ( + "log" + "os" + "os/exec" + "syscall" + + "github.com/pact-foundation/pact-go/v2/installer" + "github.com/spf13/cobra" +) + +var testCmd = &cobra.Command{ + Use: "test", + Short: "Run go test with Pact library path configured", + Long: "Wrapper for 'go test' that sets PACT_LD_LIBRARY_PATH to the configured library directory", + DisableFlagParsing: true, + Run: func(cmd *cobra.Command, args []string) { + setLogLevel(verbose, logLevel) + + // Get the configured library directory + libDir := installer.GetConfigLibDir() + if libDir == "" { + log.Println("[WARN] No library directory configured. Run 'pact-go install -d ' to set one.") + // check PACT_LD_LIBRARY_PATH env var + if envLibDir := os.Getenv("PACT_LD_LIBRARY_PATH"); envLibDir != "" { + libDir = envLibDir + log.Printf("[INFO] Using PACT_LD_LIBRARY_PATH from environment: %s", libDir) + } else { + log.Println("[ERROR] No library directory configured and PACT_LD_LIBRARY_PATH is not set. Cannot run tests.") + os.Exit(1) + } + } + + // Set the PACT_LD_LIBRARY_PATH environment variable + err := os.Setenv("PACT_LD_LIBRARY_PATH", libDir) + if err != nil { + log.Printf("[ERROR] Failed to set PACT_LD_LIBRARY_PATH: %v", err) + os.Exit(1) + } + + log.Printf("[INFO] Running go test with PACT_LD_LIBRARY_PATH=%s", libDir) + + // Prepare the go test command + goTestArgs := append([]string{"test"}, args...) + goCmd := exec.Command("go", goTestArgs...) + + // Pass through environment variables + goCmd.Env = os.Environ() + + // Set up stdout, stderr, and stdin + goCmd.Stdout = os.Stdout + goCmd.Stderr = os.Stderr + goCmd.Stdin = os.Stdin + + // Execute the command and exit with the same exit code + if err := goCmd.Run(); err != nil { + if exitError, ok := err.(*exec.ExitError); ok { + // Exit with the same code as go test + if status, ok := exitError.Sys().(syscall.WaitStatus); ok { + os.Exit(status.ExitStatus()) + } + } + log.Printf("[ERROR] Failed to run go test: %v", err) + os.Exit(1) + } + }, +} + +func init() { + RootCmd.AddCommand(testCmd) +} diff --git a/examples/avro/avro_provider_test.go b/examples/avro/avro_provider_test.go index c7f957436..4b6d6e68a 100644 --- a/examples/avro/avro_provider_test.go +++ b/examples/avro/avro_provider_test.go @@ -62,7 +62,7 @@ func startHTTPProvider(port int) { log.Println("ERROR: ", err) w.WriteHeader(500) } else { - fmt.Fprintf(w, string(binary)) + w.Write(binary) w.WriteHeader(200) } }) diff --git a/examples/provider_test.go b/examples/provider_test.go index bd3ca53f9..e02a031f9 100644 --- a/examples/provider_test.go +++ b/examples/provider_test.go @@ -27,7 +27,7 @@ var requestFilterCalled = false var stateHandlerCalled = false func TestV3HTTPProvider(t *testing.T) { - log.SetLogLevel("TRACE") + log.SetLogLevel("INFO") version.CheckVersion() // Start provider API in the background @@ -138,7 +138,7 @@ func TestV3HTTPProvider(t *testing.T) { } func TestV3MessageProvider(t *testing.T) { - log.SetLogLevel("TRACE") + log.SetLogLevel("INFO") var user *User verifier := provider.NewVerifier() diff --git a/go.mod b/go.mod index 2911662e7..a5261f6b9 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,11 @@ module github.com/pact-foundation/pact-go/v2 -go 1.23.0 +go 1.24.0 toolchain go1.24.5 require ( + github.com/ebitengine/purego v0.9.0 github.com/golang/protobuf v1.5.4 github.com/hashicorp/go-version v1.7.0 github.com/hashicorp/logutils v1.0.0 @@ -12,6 +13,7 @@ require ( github.com/spf13/afero v1.15.0 github.com/spf13/cobra v1.10.1 github.com/stretchr/testify v1.11.1 + golang.org/x/sys v0.37.0 google.golang.org/grpc v1.73.0 google.golang.org/protobuf v1.36.10 gopkg.in/yaml.v3 v3.0.1 @@ -26,7 +28,6 @@ require ( github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/spf13/pflag v1.0.9 // indirect golang.org/x/net v0.38.0 // indirect - golang.org/x/sys v0.31.0 // indirect golang.org/x/text v0.28.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/go.sum b/go.sum index a013e203f..e2efd6d08 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,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.9.0 h1:mh0zpKBIXDceC63hpvPuGLiJ8ZAa3DfrFTudmfi8A4k= +github.com/ebitengine/purego v0.9.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -12,8 +14,8 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6 github.com/golang/snappy v0.0.1/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/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= @@ -30,10 +32,6 @@ 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.13.1 h1:4qZ5M0QzQFDRqccsroJlgOJznqAS/TpdvXg55h429+I= -github.com/linkedin/goavro/v2 v2.13.1/go.mod h1:KXx+erlq+RPlGSPmLF7xGo6SAbh8sCQ53x064+ioxhk= -github.com/linkedin/goavro/v2 v2.14.0 h1:aNO/js65U+Mwq4yB5f1h01c3wiM458qtRad1DN0CMUI= -github.com/linkedin/goavro/v2 v2.14.0/go.mod h1:KXx+erlq+RPlGSPmLF7xGo6SAbh8sCQ53x064+ioxhk= github.com/linkedin/goavro/v2 v2.14.1 h1:/8VjDpd38PRsy02JS0jflAu7JZPfJcGTwqWgMkFS2iI= github.com/linkedin/goavro/v2 v2.14.1/go.mod h1:KXx+erlq+RPlGSPmLF7xGo6SAbh8sCQ53x064+ioxhk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -42,70 +40,40 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= -github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= -github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= -github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= -github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 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.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= -go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= -go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= -go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= -go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= -go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= -go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= -go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= -go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= -go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= +go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= +go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= +go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= +go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= +go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= +go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= -google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= -google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= -google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/installer/installer.go b/installer/installer.go index 30965e1fa..da91ae437 100644 --- a/installer/installer.go +++ b/installer/installer.go @@ -88,6 +88,29 @@ func (i *Installer) SetLibDir(dir string) { i.libDir = dir } +// SetConfigLibDir stores the libDir in the config +func (i *Installer) SetConfigLibDir(dir string) { + // print debug log + log.Printf("[DEBUG] setting config lib dir to %s", dir) + c := i.config.readConfig() + c.LibDir = dir + if err := i.config.writeConfig(c); err != nil { + log.Printf("[ERROR] failed to write config: %v", err) + } +} + +// GetConfigLibDir retrieves the libDir from config +func GetConfigLibDir() string { + c := &configuration{} + config := c.readConfig() + return config.LibDir +} + +// GetActualLibDir returns the actual library directory being used +func (i *Installer) GetActualLibDir() string { + return i.getLibDir() +} + // Force installs over the top func (i *Installer) Force(force bool) { i.force = force @@ -133,8 +156,13 @@ func (i *Installer) getLibDir() string { if env != "" { return env } + homeDir, err := os.UserHomeDir() + if err != nil { + log.Printf("[WARN] Could not determine home directory: %v", err) + return "" + } - return "/usr/local/lib" + return filepath.Join(homeDir, ".pact", "pact-go", "libs") } // CheckPackageInstall discovers any existing packages, and checks installation of a given binary using semver-compatible checks @@ -446,6 +474,7 @@ type packageMetadata struct { type pactConfig struct { Libraries map[string]packageMetadata + LibDir string `yaml:"libDir,omitempty"` } type configReader interface { diff --git a/installer/installer_test.go b/installer/installer_test.go index dd6c85492..5729cda9e 100644 --- a/installer/installer_test.go +++ b/installer/installer_test.go @@ -18,7 +18,7 @@ func TestNativeLibPath(t *testing.T) { libFilePath := filepath.Join(lib, "lib.go") file, err := os.ReadFile(libFilePath) assert.NoError(t, err) - assert.Contains(t, string(file), "-lpact_ffi") + assert.Contains(t, string(file), "libpact_ffi") } // 1. Be able to specify the path of the binary in advance diff --git a/internal/native/lib.go b/internal/native/lib.go index d4324ff52..b7007ad1a 100644 --- a/internal/native/lib.go +++ b/internal/native/lib.go @@ -1,11 +1,600 @@ // Package native contains the c bindings into the Pact Reference types. package native -/* -#cgo darwin,arm64 LDFLAGS: -L/tmp -L/usr/local/lib -Wl,-rpath -Wl,/tmp -Wl,-rpath -Wl,/usr/local/lib -lpact_ffi -#cgo darwin,amd64 LDFLAGS: -L/tmp -L/usr/local/lib -Wl,-rpath -Wl,/tmp -Wl,-rpath -Wl,/usr/local/lib -lpact_ffi -#cgo windows,amd64 LDFLAGS: -lpact_ffi -#cgo linux,amd64 LDFLAGS: -L/tmp -L/opt/pact/lib -L/usr/local/lib -Wl,-rpath -Wl,/opt/pact/lib -Wl,-rpath -Wl,/tmp -Wl,-rpath -Wl,/usr/local/lib -lpact_ffi -#cgo linux,arm64 LDFLAGS: -L/tmp -L/opt/pact/lib -L/usr/local/lib -Wl,-rpath -Wl,/opt/pact/lib -Wl,-rpath -Wl,/tmp -Wl,-rpath -Wl,/usr/local/lib -lpact_ffi -*/ -import "C" +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "unsafe" + + "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_version func() string +var pactffi_init func(string) +var pactffi_init_with_log_level func(string) +var pactffi_enable_ansi_support func() +var pactffi_log_message func(string, string, string) +var pactffi_match_message func(uintptr, uintptr) uintptr +var pactffi_mismatches_get_iter func(uintptr) uintptr +var pactffi_mismatches_delete func(uintptr) +var pactffi_mismatches_iter_next func(uintptr) uintptr +var pactffi_mismatches_iter_delete func(uintptr) +var pactffi_mismatch_to_json func(uintptr) string +var pactffi_mismatch_type func(uintptr) string +var pactffi_mismatch_summary func(uintptr) string +var pactffi_mismatch_description func(uintptr) string +var pactffi_mismatch_ansi_description func(uintptr) string +var pactffi_get_error_message func(string, int32) int32 +var pactffi_log_to_stdout func(int32) int32 +var pactffi_log_to_stderr func(int32) int32 +var pactffi_log_to_file func(string, int32) int32 +var pactffi_log_to_buffer func(int32) int32 +var pactffi_logger_init func() +var pactffi_logger_attach_sink func(string, int32) int32 +var pactffi_logger_apply func() int32 +var pactffi_fetch_log_buffer func(string) string +var pactffi_parse_pact_json func(string) uintptr +var pactffi_pact_model_delete func(uintptr) +var pactffi_pact_model_interaction_iterator func(uintptr) uintptr +var pactffi_pact_spec_version func(uintptr) int32 +var pactffi_pact_interaction_delete func(uintptr) +var pactffi_async_message_new func() uintptr +var pactffi_async_message_delete func(uintptr) +var pactffi_async_message_get_contents func(uintptr) uintptr +var pactffi_async_message_get_contents_str func(uintptr) string +var pactffi_async_message_set_contents_str func(uintptr, string, string) +var pactffi_async_message_get_contents_length func(uintptr) size_t +var pactffi_async_message_get_contents_bin func(uintptr) uintptr +var pactffi_async_message_set_contents_bin func(uintptr, uintptr, size_t, string) +var pactffi_async_message_get_description func(uintptr) string +var pactffi_async_message_set_description func(uintptr, string) int32 +var pactffi_async_message_get_provider_state func(uintptr, uint32) uintptr +var pactffi_async_message_get_provider_state_iter func(uintptr) uintptr +var pactffi_consumer_get_name func(uintptr) string +var pactffi_pact_get_consumer func(uintptr) uintptr +var pactffi_pact_consumer_delete func(uintptr) +var pactffi_message_contents_get_contents_str func(uintptr) string +var pactffi_message_contents_set_contents_str func(uintptr, string, string) +var pactffi_message_contents_get_contents_length func(uintptr) size_t +var pactffi_message_contents_get_contents_bin func(uintptr) uintptr +var pactffi_message_contents_set_contents_bin func(uintptr, uintptr, size_t, string) +var pactffi_message_contents_get_metadata_iter func(uintptr) uintptr +var pactffi_message_contents_get_matching_rule_iter func(uintptr, int32) uintptr +var pactffi_request_contents_get_matching_rule_iter func(uintptr, int32) uintptr +var pactffi_response_contents_get_matching_rule_iter func(uintptr, int32) uintptr +var pactffi_message_contents_get_generators_iter func(uintptr, int32) uintptr +var pactffi_request_contents_get_generators_iter func(uintptr, int32) uintptr +var pactffi_response_contents_get_generators_iter func(uintptr, int32) uintptr +var pactffi_parse_matcher_definition func(string) uintptr +var pactffi_matcher_definition_error func(uintptr) string +var pactffi_matcher_definition_value func(uintptr) string +var pactffi_matcher_definition_delete func(uintptr) +var pactffi_matcher_definition_generator func(uintptr) uintptr +var pactffi_matcher_definition_value_type func(uintptr) int32 +var pactffi_matching_rule_iter_delete func(uintptr) +var pactffi_matcher_definition_iter func(uintptr) uintptr +var pactffi_matching_rule_iter_next func(uintptr) uintptr +var pactffi_matching_rule_id func(uintptr) uint16 +var pactffi_matching_rule_value func(uintptr) string +var pactffi_matching_rule_pointer func(uintptr) uintptr +var pactffi_matching_rule_reference_name func(uintptr) string +var pactffi_validate_datetime func(string, string) int32 +var pactffi_generator_to_json func(uintptr) string +var pactffi_generator_generate_string func(uintptr, string) string +var pactffi_generator_generate_integer func(uintptr, string) uint16 +var pactffi_generators_iter_delete func(uintptr) +var pactffi_generators_iter_next func(uintptr) uintptr +var pactffi_generators_iter_pair_delete func(uintptr) +var pactffi_sync_http_new func() uintptr +var pactffi_sync_http_delete func(uintptr) +var pactffi_sync_http_get_request func(uintptr) uintptr +var pactffi_sync_http_get_request_contents func(uintptr) string +var pactffi_sync_http_set_request_contents func(uintptr, string, string) +var pactffi_sync_http_get_request_contents_length func(uintptr) size_t +var pactffi_sync_http_get_request_contents_bin func(uintptr) uintptr +var pactffi_sync_http_set_request_contents_bin func(uintptr, uintptr, size_t, string) +var pactffi_sync_http_get_response func(uintptr) uintptr +var pactffi_sync_http_get_response_contents func(uintptr) string +var pactffi_sync_http_set_response_contents func(uintptr, string, string) +var pactffi_sync_http_get_response_contents_length func(uintptr) size_t +var pactffi_sync_http_get_response_contents_bin func(uintptr) uintptr +var pactffi_sync_http_set_response_contents_bin func(uintptr, uintptr, size_t, string) +var pactffi_sync_http_get_description func(uintptr) string +var pactffi_sync_http_set_description func(uintptr, string) int32 +var pactffi_sync_http_get_provider_state func(uintptr, uint32) uintptr +var pactffi_sync_http_get_provider_state_iter func(uintptr) uintptr +var pactffi_pact_interaction_as_synchronous_http func(uintptr) uintptr +var pactffi_pact_interaction_as_message func(uintptr) uintptr +var pactffi_pact_interaction_as_asynchronous_message func(uintptr) uintptr +var pactffi_pact_interaction_as_synchronous_message func(uintptr) uintptr +var pactffi_pact_message_iter_delete func(uintptr) +var pactffi_pact_message_iter_next func(uintptr) uintptr +var pactffi_pact_sync_message_iter_next func(uintptr) uintptr +var pactffi_pact_sync_message_iter_delete func(uintptr) +var pactffi_pact_sync_http_iter_next func(uintptr) uintptr +var pactffi_pact_sync_http_iter_delete func(uintptr) +var pactffi_pact_interaction_iter_next func(uintptr) uintptr +var pactffi_pact_interaction_iter_delete func(uintptr) +var pactffi_matching_rule_to_json func(uintptr) string +var pactffi_matching_rules_iter_delete func(uintptr) +var pactffi_matching_rules_iter_next func(uintptr) uintptr +var pactffi_matching_rules_iter_pair_delete func(uintptr) +var pactffi_message_new func() uintptr +var pactffi_message_new_from_json func(uint32, string, int32) uintptr +var pactffi_message_new_from_body func(string, string) uintptr +var pactffi_message_delete func(uintptr) +var pactffi_message_get_contents func(uintptr) string +var pactffi_message_set_contents func(uintptr, string, string) +var pactffi_message_get_contents_length func(uintptr) size_t +var pactffi_message_get_contents_bin func(uintptr) uintptr +var pactffi_message_set_contents_bin func(uintptr, uintptr, size_t, string) +var pactffi_message_get_description func(uintptr) string +var pactffi_message_set_description func(uintptr, string) int32 +var pactffi_message_get_provider_state func(uintptr, uint32) uintptr +var pactffi_message_get_provider_state_iter func(uintptr) uintptr +var pactffi_provider_state_iter_next func(uintptr) uintptr +var pactffi_provider_state_iter_delete func(uintptr) +var pactffi_message_find_metadata func(uintptr, string) string +var pactffi_message_insert_metadata func(uintptr, string, string) int32 +var pactffi_message_metadata_iter_next func(uintptr) uintptr +var pactffi_message_get_metadata_iter func(uintptr) uintptr +var pactffi_message_metadata_iter_delete func(uintptr) +var pactffi_message_metadata_pair_delete func(uintptr) +var pactffi_message_pact_new_from_json func(string, string) uintptr +var pactffi_message_pact_delete func(uintptr) +var pactffi_message_pact_get_consumer func(uintptr) uintptr +var pactffi_message_pact_get_provider func(uintptr) uintptr +var pactffi_message_pact_get_message_iter func(uintptr) uintptr +var pactffi_message_pact_message_iter_next func(uintptr) uintptr +var pactffi_message_pact_message_iter_delete func(uintptr) +var pactffi_message_pact_find_metadata func(uintptr, string, string) string +var pactffi_message_pact_get_metadata_iter func(uintptr) uintptr +var pactffi_message_pact_metadata_iter_next func(uintptr) uintptr +var pactffi_message_pact_metadata_iter_delete func(uintptr) +var pactffi_message_pact_metadata_triple_delete func(uintptr) +var pactffi_provider_get_name func(uintptr) string +var pactffi_pact_get_provider func(uintptr) uintptr +var pactffi_pact_provider_delete func(uintptr) +var pactffi_provider_state_get_name func(uintptr) string +var pactffi_provider_state_get_param_iter func(uintptr) uintptr +var pactffi_provider_state_param_iter_next func(uintptr) uintptr +var pactffi_provider_state_delete func(uintptr) +var pactffi_provider_state_param_iter_delete func(uintptr) +var pactffi_provider_state_param_pair_delete func(uintptr) +var pactffi_sync_message_new func() uintptr +var pactffi_sync_message_delete func(uintptr) +var pactffi_sync_message_get_request_contents_str func(uintptr) string +var pactffi_sync_message_set_request_contents_str func(uintptr, string, string) +var pactffi_sync_message_get_request_contents_length func(uintptr) size_t +var pactffi_sync_message_get_request_contents_bin func(uintptr) uintptr +var pactffi_sync_message_set_request_contents_bin func(uintptr, uintptr, size_t, string) +var pactffi_sync_message_get_request_contents func(uintptr) uintptr +var pactffi_sync_message_get_number_responses func(uintptr) size_t +var pactffi_sync_message_get_response_contents_str func(uintptr, size_t) string +var pactffi_sync_message_set_response_contents_str func(uintptr, size_t, string, string) +var pactffi_sync_message_get_response_contents_length func(uintptr, size_t) size_t +var pactffi_sync_message_get_response_contents_bin func(uintptr, size_t) uintptr +var pactffi_sync_message_set_response_contents_bin func(uintptr, size_t, uintptr, size_t, string) +var pactffi_sync_message_get_response_contents func(uintptr, size_t) uintptr +var pactffi_sync_message_get_description func(uintptr) string +var pactffi_sync_message_set_description func(uintptr, string) int32 +var pactffi_sync_message_get_provider_state func(uintptr, uint32) uintptr +var pactffi_sync_message_get_provider_state_iter func(uintptr) uintptr +var pactffi_string_delete func(string) +var pactffi_create_mock_server func(string, string, bool) int32 +var pactffi_get_tls_ca_certificate func() string +var pactffi_create_mock_server_for_pact func(uintptr, string, bool) int32 +var pactffi_create_mock_server_for_transport func(uintptr, string, uint16, string, string) int32 +var pactffi_mock_server_matched func(int32) bool +var pactffi_mock_server_mismatches func(int32) string +var pactffi_cleanup_mock_server func(int32) bool +var pactffi_write_pact_file func(int32, string, bool) int32 +var pactffi_mock_server_logs func(int32) string +var pactffi_generate_datetime_string func(string) uintptr +var pactffi_check_regex func(string, string) bool +var pactffi_generate_regex_value func(string) uintptr +var pactffi_free_string func(uintptr) +var pactffi_new_pact func(string, string) uintptr +var pactffi_pact_handle_to_pointer func(uint16) uintptr +var pactffi_new_interaction func(uintptr, string) uintptr +var pactffi_new_message_interaction func(uintptr, string) uintptr +var pactffi_new_sync_message_interaction func(uintptr, string) uintptr +var pactffi_upon_receiving func(uintptr, string) bool +var pactffi_given func(uintptr, string) bool +var pactffi_interaction_test_name func(uint32, string) uint32 +var pactffi_given_with_param func(uintptr, string, string, string) bool +var pactffi_given_with_params func(uintptr, string, string) int32 +var pactffi_with_request func(uintptr, string, string) bool +var pactffi_with_query_parameter func(uintptr, string, int, string) bool +var pactffi_with_query_parameter_v2 func(uintptr, string, int, string) bool +var pactffi_with_specification func(uintptr, int32) bool +var pactffi_handle_get_pact_spec_version func(uint16) int32 +var pactffi_with_pact_metadata func(uintptr, string, string, string) bool +var pactffi_with_header func(uintptr, int32, string, int, string) bool +var pactffi_with_header_v2 func(uintptr, int32, string, int, string) bool +var pactffi_set_header func(uint32, int32, string, string) bool +var pactffi_response_status func(uintptr, uint16) bool +var pactffi_response_status_v2 func(uintptr, string) bool +var pactffi_with_body func(uintptr, int32, string, string) bool +var pactffi_with_binary_body func(uint32, int32, string, string, size_t) bool +var pactffi_with_binary_file func(uintptr, int32, string, string, size_t) bool +var pactffi_with_matching_rules func(uint32, int32, string) bool +var pactffi_with_multipart_file_v2 func(uint32, int32, string, string, string, string) uintptr +var pactffi_with_multipart_file func(uintptr, int32, string, string, string) uintptr +var pactffi_pact_handle_get_message_iter func(uintptr) uintptr +var pactffi_pact_handle_get_sync_message_iter func(uintptr) uintptr +var pactffi_pact_handle_get_sync_http_iter func(uint16) uintptr +var pactffi_new_message_pact func(string, string) uintptr +var pactffi_new_message func(uint16, string) uint32 +var pactffi_with_metadata func(uintptr, string, string, int) bool +var pactffi_message_expects_to_receive func(uintptr, string) +var pactffi_message_given func(uintptr, string) +var pactffi_message_given_with_param func(uintptr, string, string, string) +var pactffi_message_with_contents func(uintptr, string, uintptr, size_t) +var pactffi_message_with_metadata func(uintptr, string, string) +var pactffi_message_with_metadata_v2 func(uint32, string, string) +var pactffi_message_reify func(uint32) string +var pactffi_write_message_pact_file func(uintptr, string, bool) int32 +var pactffi_with_message_pact_metadata func(uintptr, string, string, string) +var pactffi_pact_handle_write_file func(uint16, string, bool) int32 +var pactffi_new_async_message func(uint16, string) uint32 +var pactffi_free_pact_handle func(uint16) uint32 +var pactffi_free_message_pact_handle func(uint16) uint32 +var pactffi_verify func(string) int32 +var pactffi_verifier_new func() uintptr +var pactffi_verifier_new_for_application func(string, string) uintptr +var pactffi_verifier_shutdown func(uintptr) +var pactffi_verifier_set_provider_info func(uintptr, string, string, string, uint16, string) +var pactffi_verifier_add_provider_transport func(uintptr, string, uint16, string, string) +var pactffi_verifier_set_filter_info func(uintptr, string, string, uint8) +var pactffi_verifier_set_provider_state func(uintptr, string, uint8, uint8) +var pactffi_verifier_set_verification_options func(uintptr, uint8, uint64) int32 +var pactffi_verifier_set_coloured_output func(uintptr, uint8) int32 +var pactffi_verifier_set_no_pacts_is_error func(uintptr, uint8) int32 +var pactffi_verifier_set_publish_options func(uintptr, string, string, []*byte, uint16, string) int32 +var pactffi_verifier_set_consumer_filters func(uintptr, []*byte, uint16) +var pactffi_verifier_add_custom_header func(uintptr, string, string) +var pactffi_verifier_add_file_source func(uintptr, string) +var pactffi_verifier_add_directory_source func(uintptr, string) +var pactffi_verifier_url_source func(uintptr, string, string, string, string) +var pactffi_verifier_broker_source func(uintptr, string, string, string, string) +var pactffi_verifier_broker_source_with_selectors func(uintptr, string, string, string, string, uint8, string, []*byte, uint16, string, []*byte, uint16, []*byte, uint16) +var pactffi_verifier_execute func(uintptr) int32 +var pactffi_verifier_cli_args func() string +var pactffi_verifier_logs func(uintptr) string +var pactffi_verifier_logs_for_provider func(string) string +var pactffi_verifier_output func(uintptr, uint8) string +var pactffi_verifier_json func(uintptr) string +var pactffi_using_plugin func(uintptr, string, string) uint32 +var pactffi_cleanup_plugins func(uintptr) +var pactffi_interaction_contents func(uintptr, int32, string, string) uint32 +var pactffi_matches_string_value func(uintptr, string, string, uint8) string +var pactffi_matches_u64_value func(uintptr, uint64, uint64, uint8) string +var pactffi_matches_i64_value func(uintptr, int64, int64, uint8) string +var pactffi_matches_f64_value func(uintptr, float64, float64, uint8) string +var pactffi_matches_bool_value func(uintptr, uint8, uint8, uint8) string +var pactffi_matches_binary_value func(uintptr, uintptr, uint64, uintptr, uint64, uint8) string +var pactffi_matches_json_value func(uintptr, string, string, uint8) string + +func init() { + libpact_ffi, err := openLibrary(filepath.Join(os.Getenv("PACT_LD_LIBRARY_PATH"), getSystemLibrary())) + if err != nil { + panic(err) + } + purego.RegisterLibFunc(&pactffi_version, libpact_ffi, "pactffi_version") + purego.RegisterLibFunc(&pactffi_init, libpact_ffi, "pactffi_init") + purego.RegisterLibFunc(&pactffi_init_with_log_level, libpact_ffi, "pactffi_init_with_log_level") + purego.RegisterLibFunc(&pactffi_enable_ansi_support, libpact_ffi, "pactffi_enable_ansi_support") + purego.RegisterLibFunc(&pactffi_log_message, libpact_ffi, "pactffi_log_message") + purego.RegisterLibFunc(&pactffi_match_message, libpact_ffi, "pactffi_match_message") + purego.RegisterLibFunc(&pactffi_mismatches_get_iter, libpact_ffi, "pactffi_mismatches_get_iter") + purego.RegisterLibFunc(&pactffi_mismatches_delete, libpact_ffi, "pactffi_mismatches_delete") + purego.RegisterLibFunc(&pactffi_mismatches_iter_next, libpact_ffi, "pactffi_mismatches_iter_next") + purego.RegisterLibFunc(&pactffi_mismatches_iter_delete, libpact_ffi, "pactffi_mismatches_iter_delete") + purego.RegisterLibFunc(&pactffi_mismatch_to_json, libpact_ffi, "pactffi_mismatch_to_json") + purego.RegisterLibFunc(&pactffi_mismatch_type, libpact_ffi, "pactffi_mismatch_type") + purego.RegisterLibFunc(&pactffi_mismatch_summary, libpact_ffi, "pactffi_mismatch_summary") + purego.RegisterLibFunc(&pactffi_mismatch_description, libpact_ffi, "pactffi_mismatch_description") + purego.RegisterLibFunc(&pactffi_mismatch_ansi_description, libpact_ffi, "pactffi_mismatch_ansi_description") + purego.RegisterLibFunc(&pactffi_get_error_message, libpact_ffi, "pactffi_get_error_message") + purego.RegisterLibFunc(&pactffi_log_to_stdout, libpact_ffi, "pactffi_log_to_stdout") + purego.RegisterLibFunc(&pactffi_log_to_stderr, libpact_ffi, "pactffi_log_to_stderr") + purego.RegisterLibFunc(&pactffi_log_to_file, libpact_ffi, "pactffi_log_to_file") + purego.RegisterLibFunc(&pactffi_log_to_buffer, libpact_ffi, "pactffi_log_to_buffer") + purego.RegisterLibFunc(&pactffi_logger_init, libpact_ffi, "pactffi_logger_init") + purego.RegisterLibFunc(&pactffi_logger_attach_sink, libpact_ffi, "pactffi_logger_attach_sink") + purego.RegisterLibFunc(&pactffi_logger_apply, libpact_ffi, "pactffi_logger_apply") + purego.RegisterLibFunc(&pactffi_fetch_log_buffer, libpact_ffi, "pactffi_fetch_log_buffer") + purego.RegisterLibFunc(&pactffi_parse_pact_json, libpact_ffi, "pactffi_parse_pact_json") + purego.RegisterLibFunc(&pactffi_pact_model_delete, libpact_ffi, "pactffi_pact_model_delete") + purego.RegisterLibFunc(&pactffi_pact_model_interaction_iterator, libpact_ffi, "pactffi_pact_model_interaction_iterator") + purego.RegisterLibFunc(&pactffi_pact_spec_version, libpact_ffi, "pactffi_pact_spec_version") + purego.RegisterLibFunc(&pactffi_pact_interaction_delete, libpact_ffi, "pactffi_pact_interaction_delete") + purego.RegisterLibFunc(&pactffi_async_message_new, libpact_ffi, "pactffi_async_message_new") + purego.RegisterLibFunc(&pactffi_async_message_delete, libpact_ffi, "pactffi_async_message_delete") + purego.RegisterLibFunc(&pactffi_async_message_get_contents, libpact_ffi, "pactffi_async_message_get_contents") + purego.RegisterLibFunc(&pactffi_async_message_get_contents_str, libpact_ffi, "pactffi_async_message_get_contents_str") + purego.RegisterLibFunc(&pactffi_async_message_set_contents_str, libpact_ffi, "pactffi_async_message_set_contents_str") + purego.RegisterLibFunc(&pactffi_async_message_get_contents_length, libpact_ffi, "pactffi_async_message_get_contents_length") + purego.RegisterLibFunc(&pactffi_async_message_get_contents_bin, libpact_ffi, "pactffi_async_message_get_contents_bin") + purego.RegisterLibFunc(&pactffi_async_message_set_contents_bin, libpact_ffi, "pactffi_async_message_set_contents_bin") + purego.RegisterLibFunc(&pactffi_async_message_get_description, libpact_ffi, "pactffi_async_message_get_description") + purego.RegisterLibFunc(&pactffi_async_message_set_description, libpact_ffi, "pactffi_async_message_set_description") + purego.RegisterLibFunc(&pactffi_async_message_get_provider_state, libpact_ffi, "pactffi_async_message_get_provider_state") + purego.RegisterLibFunc(&pactffi_async_message_get_provider_state_iter, libpact_ffi, "pactffi_async_message_get_provider_state_iter") + purego.RegisterLibFunc(&pactffi_consumer_get_name, libpact_ffi, "pactffi_consumer_get_name") + purego.RegisterLibFunc(&pactffi_pact_get_consumer, libpact_ffi, "pactffi_pact_get_consumer") + purego.RegisterLibFunc(&pactffi_pact_consumer_delete, libpact_ffi, "pactffi_pact_consumer_delete") + purego.RegisterLibFunc(&pactffi_message_contents_get_contents_str, libpact_ffi, "pactffi_message_contents_get_contents_str") + purego.RegisterLibFunc(&pactffi_message_contents_set_contents_str, libpact_ffi, "pactffi_message_contents_set_contents_str") + purego.RegisterLibFunc(&pactffi_message_contents_get_contents_length, libpact_ffi, "pactffi_message_contents_get_contents_length") + purego.RegisterLibFunc(&pactffi_message_contents_get_contents_bin, libpact_ffi, "pactffi_message_contents_get_contents_bin") + purego.RegisterLibFunc(&pactffi_message_contents_set_contents_bin, libpact_ffi, "pactffi_message_contents_set_contents_bin") + purego.RegisterLibFunc(&pactffi_message_contents_get_metadata_iter, libpact_ffi, "pactffi_message_contents_get_metadata_iter") + purego.RegisterLibFunc(&pactffi_message_contents_get_matching_rule_iter, libpact_ffi, "pactffi_message_contents_get_matching_rule_iter") + purego.RegisterLibFunc(&pactffi_request_contents_get_matching_rule_iter, libpact_ffi, "pactffi_request_contents_get_matching_rule_iter") + purego.RegisterLibFunc(&pactffi_response_contents_get_matching_rule_iter, libpact_ffi, "pactffi_response_contents_get_matching_rule_iter") + purego.RegisterLibFunc(&pactffi_message_contents_get_generators_iter, libpact_ffi, "pactffi_message_contents_get_generators_iter") + purego.RegisterLibFunc(&pactffi_request_contents_get_generators_iter, libpact_ffi, "pactffi_request_contents_get_generators_iter") + purego.RegisterLibFunc(&pactffi_response_contents_get_generators_iter, libpact_ffi, "pactffi_response_contents_get_generators_iter") + purego.RegisterLibFunc(&pactffi_parse_matcher_definition, libpact_ffi, "pactffi_parse_matcher_definition") + purego.RegisterLibFunc(&pactffi_matcher_definition_error, libpact_ffi, "pactffi_matcher_definition_error") + purego.RegisterLibFunc(&pactffi_matcher_definition_value, libpact_ffi, "pactffi_matcher_definition_value") + purego.RegisterLibFunc(&pactffi_matcher_definition_delete, libpact_ffi, "pactffi_matcher_definition_delete") + purego.RegisterLibFunc(&pactffi_matcher_definition_generator, libpact_ffi, "pactffi_matcher_definition_generator") + purego.RegisterLibFunc(&pactffi_matcher_definition_value_type, libpact_ffi, "pactffi_matcher_definition_value_type") + purego.RegisterLibFunc(&pactffi_matching_rule_iter_delete, libpact_ffi, "pactffi_matching_rule_iter_delete") + purego.RegisterLibFunc(&pactffi_matcher_definition_iter, libpact_ffi, "pactffi_matcher_definition_iter") + purego.RegisterLibFunc(&pactffi_matching_rule_iter_next, libpact_ffi, "pactffi_matching_rule_iter_next") + purego.RegisterLibFunc(&pactffi_matching_rule_id, libpact_ffi, "pactffi_matching_rule_id") + purego.RegisterLibFunc(&pactffi_matching_rule_value, libpact_ffi, "pactffi_matching_rule_value") + purego.RegisterLibFunc(&pactffi_matching_rule_pointer, libpact_ffi, "pactffi_matching_rule_pointer") + purego.RegisterLibFunc(&pactffi_matching_rule_reference_name, libpact_ffi, "pactffi_matching_rule_reference_name") + purego.RegisterLibFunc(&pactffi_validate_datetime, libpact_ffi, "pactffi_validate_datetime") + purego.RegisterLibFunc(&pactffi_generator_to_json, libpact_ffi, "pactffi_generator_to_json") + purego.RegisterLibFunc(&pactffi_generator_generate_string, libpact_ffi, "pactffi_generator_generate_string") + purego.RegisterLibFunc(&pactffi_generator_generate_integer, libpact_ffi, "pactffi_generator_generate_integer") + purego.RegisterLibFunc(&pactffi_generators_iter_delete, libpact_ffi, "pactffi_generators_iter_delete") + purego.RegisterLibFunc(&pactffi_generators_iter_next, libpact_ffi, "pactffi_generators_iter_next") + purego.RegisterLibFunc(&pactffi_generators_iter_pair_delete, libpact_ffi, "pactffi_generators_iter_pair_delete") + purego.RegisterLibFunc(&pactffi_sync_http_new, libpact_ffi, "pactffi_sync_http_new") + purego.RegisterLibFunc(&pactffi_sync_http_delete, libpact_ffi, "pactffi_sync_http_delete") + purego.RegisterLibFunc(&pactffi_sync_http_get_request, libpact_ffi, "pactffi_sync_http_get_request") + purego.RegisterLibFunc(&pactffi_sync_http_get_request_contents, libpact_ffi, "pactffi_sync_http_get_request_contents") + purego.RegisterLibFunc(&pactffi_sync_http_set_request_contents, libpact_ffi, "pactffi_sync_http_set_request_contents") + purego.RegisterLibFunc(&pactffi_sync_http_get_request_contents_length, libpact_ffi, "pactffi_sync_http_get_request_contents_length") + purego.RegisterLibFunc(&pactffi_sync_http_get_request_contents_bin, libpact_ffi, "pactffi_sync_http_get_request_contents_bin") + purego.RegisterLibFunc(&pactffi_sync_http_set_request_contents_bin, libpact_ffi, "pactffi_sync_http_set_request_contents_bin") + purego.RegisterLibFunc(&pactffi_sync_http_get_response, libpact_ffi, "pactffi_sync_http_get_response") + purego.RegisterLibFunc(&pactffi_sync_http_get_response_contents, libpact_ffi, "pactffi_sync_http_get_response_contents") + purego.RegisterLibFunc(&pactffi_sync_http_set_response_contents, libpact_ffi, "pactffi_sync_http_set_response_contents") + purego.RegisterLibFunc(&pactffi_sync_http_get_response_contents_length, libpact_ffi, "pactffi_sync_http_get_response_contents_length") + purego.RegisterLibFunc(&pactffi_sync_http_get_response_contents_bin, libpact_ffi, "pactffi_sync_http_get_response_contents_bin") + purego.RegisterLibFunc(&pactffi_sync_http_set_response_contents_bin, libpact_ffi, "pactffi_sync_http_set_response_contents_bin") + purego.RegisterLibFunc(&pactffi_sync_http_get_description, libpact_ffi, "pactffi_sync_http_get_description") + purego.RegisterLibFunc(&pactffi_sync_http_set_description, libpact_ffi, "pactffi_sync_http_set_description") + purego.RegisterLibFunc(&pactffi_sync_http_get_provider_state, libpact_ffi, "pactffi_sync_http_get_provider_state") + purego.RegisterLibFunc(&pactffi_sync_http_get_provider_state_iter, libpact_ffi, "pactffi_sync_http_get_provider_state_iter") + purego.RegisterLibFunc(&pactffi_pact_interaction_as_synchronous_http, libpact_ffi, "pactffi_pact_interaction_as_synchronous_http") + purego.RegisterLibFunc(&pactffi_pact_interaction_as_message, libpact_ffi, "pactffi_pact_interaction_as_message") + purego.RegisterLibFunc(&pactffi_pact_interaction_as_asynchronous_message, libpact_ffi, "pactffi_pact_interaction_as_asynchronous_message") + purego.RegisterLibFunc(&pactffi_pact_interaction_as_synchronous_message, libpact_ffi, "pactffi_pact_interaction_as_synchronous_message") + purego.RegisterLibFunc(&pactffi_pact_message_iter_delete, libpact_ffi, "pactffi_pact_message_iter_delete") + purego.RegisterLibFunc(&pactffi_pact_message_iter_next, libpact_ffi, "pactffi_pact_message_iter_next") + purego.RegisterLibFunc(&pactffi_pact_sync_message_iter_next, libpact_ffi, "pactffi_pact_sync_message_iter_next") + purego.RegisterLibFunc(&pactffi_pact_sync_message_iter_delete, libpact_ffi, "pactffi_pact_sync_message_iter_delete") + purego.RegisterLibFunc(&pactffi_pact_sync_http_iter_next, libpact_ffi, "pactffi_pact_sync_http_iter_next") + purego.RegisterLibFunc(&pactffi_pact_sync_http_iter_delete, libpact_ffi, "pactffi_pact_sync_http_iter_delete") + purego.RegisterLibFunc(&pactffi_pact_interaction_iter_next, libpact_ffi, "pactffi_pact_interaction_iter_next") + purego.RegisterLibFunc(&pactffi_pact_interaction_iter_delete, libpact_ffi, "pactffi_pact_interaction_iter_delete") + purego.RegisterLibFunc(&pactffi_matching_rule_to_json, libpact_ffi, "pactffi_matching_rule_to_json") + purego.RegisterLibFunc(&pactffi_matching_rules_iter_delete, libpact_ffi, "pactffi_matching_rules_iter_delete") + purego.RegisterLibFunc(&pactffi_matching_rules_iter_next, libpact_ffi, "pactffi_matching_rules_iter_next") + purego.RegisterLibFunc(&pactffi_matching_rules_iter_pair_delete, libpact_ffi, "pactffi_matching_rules_iter_pair_delete") + purego.RegisterLibFunc(&pactffi_message_new, libpact_ffi, "pactffi_message_new") + purego.RegisterLibFunc(&pactffi_message_new_from_json, libpact_ffi, "pactffi_message_new_from_json") + purego.RegisterLibFunc(&pactffi_message_new_from_body, libpact_ffi, "pactffi_message_new_from_body") + purego.RegisterLibFunc(&pactffi_message_delete, libpact_ffi, "pactffi_message_delete") + purego.RegisterLibFunc(&pactffi_message_get_contents, libpact_ffi, "pactffi_message_get_contents") + purego.RegisterLibFunc(&pactffi_message_set_contents, libpact_ffi, "pactffi_message_set_contents") + purego.RegisterLibFunc(&pactffi_message_get_contents_length, libpact_ffi, "pactffi_message_get_contents_length") + purego.RegisterLibFunc(&pactffi_message_get_contents_bin, libpact_ffi, "pactffi_message_get_contents_bin") + purego.RegisterLibFunc(&pactffi_message_set_contents_bin, libpact_ffi, "pactffi_message_set_contents_bin") + purego.RegisterLibFunc(&pactffi_message_get_description, libpact_ffi, "pactffi_message_get_description") + purego.RegisterLibFunc(&pactffi_message_set_description, libpact_ffi, "pactffi_message_set_description") + purego.RegisterLibFunc(&pactffi_message_get_provider_state, libpact_ffi, "pactffi_message_get_provider_state") + purego.RegisterLibFunc(&pactffi_message_get_provider_state_iter, libpact_ffi, "pactffi_message_get_provider_state_iter") + purego.RegisterLibFunc(&pactffi_provider_state_iter_next, libpact_ffi, "pactffi_provider_state_iter_next") + purego.RegisterLibFunc(&pactffi_provider_state_iter_delete, libpact_ffi, "pactffi_provider_state_iter_delete") + purego.RegisterLibFunc(&pactffi_message_find_metadata, libpact_ffi, "pactffi_message_find_metadata") + purego.RegisterLibFunc(&pactffi_message_insert_metadata, libpact_ffi, "pactffi_message_insert_metadata") + purego.RegisterLibFunc(&pactffi_message_metadata_iter_next, libpact_ffi, "pactffi_message_metadata_iter_next") + purego.RegisterLibFunc(&pactffi_message_get_metadata_iter, libpact_ffi, "pactffi_message_get_metadata_iter") + purego.RegisterLibFunc(&pactffi_message_metadata_iter_delete, libpact_ffi, "pactffi_message_metadata_iter_delete") + purego.RegisterLibFunc(&pactffi_message_metadata_pair_delete, libpact_ffi, "pactffi_message_metadata_pair_delete") + purego.RegisterLibFunc(&pactffi_message_pact_new_from_json, libpact_ffi, "pactffi_message_pact_new_from_json") + purego.RegisterLibFunc(&pactffi_message_pact_delete, libpact_ffi, "pactffi_message_pact_delete") + purego.RegisterLibFunc(&pactffi_message_pact_get_consumer, libpact_ffi, "pactffi_message_pact_get_consumer") + purego.RegisterLibFunc(&pactffi_message_pact_get_provider, libpact_ffi, "pactffi_message_pact_get_provider") + purego.RegisterLibFunc(&pactffi_message_pact_get_message_iter, libpact_ffi, "pactffi_message_pact_get_message_iter") + purego.RegisterLibFunc(&pactffi_message_pact_message_iter_next, libpact_ffi, "pactffi_message_pact_message_iter_next") + purego.RegisterLibFunc(&pactffi_message_pact_message_iter_delete, libpact_ffi, "pactffi_message_pact_message_iter_delete") + purego.RegisterLibFunc(&pactffi_message_pact_find_metadata, libpact_ffi, "pactffi_message_pact_find_metadata") + purego.RegisterLibFunc(&pactffi_message_pact_get_metadata_iter, libpact_ffi, "pactffi_message_pact_get_metadata_iter") + purego.RegisterLibFunc(&pactffi_message_pact_metadata_iter_next, libpact_ffi, "pactffi_message_pact_metadata_iter_next") + purego.RegisterLibFunc(&pactffi_message_pact_metadata_iter_delete, libpact_ffi, "pactffi_message_pact_metadata_iter_delete") + purego.RegisterLibFunc(&pactffi_message_pact_metadata_triple_delete, libpact_ffi, "pactffi_message_pact_metadata_triple_delete") + purego.RegisterLibFunc(&pactffi_provider_get_name, libpact_ffi, "pactffi_provider_get_name") + purego.RegisterLibFunc(&pactffi_pact_get_provider, libpact_ffi, "pactffi_pact_get_provider") + purego.RegisterLibFunc(&pactffi_pact_provider_delete, libpact_ffi, "pactffi_pact_provider_delete") + purego.RegisterLibFunc(&pactffi_provider_state_get_name, libpact_ffi, "pactffi_provider_state_get_name") + purego.RegisterLibFunc(&pactffi_provider_state_get_param_iter, libpact_ffi, "pactffi_provider_state_get_param_iter") + purego.RegisterLibFunc(&pactffi_provider_state_param_iter_next, libpact_ffi, "pactffi_provider_state_param_iter_next") + purego.RegisterLibFunc(&pactffi_provider_state_delete, libpact_ffi, "pactffi_provider_state_delete") + purego.RegisterLibFunc(&pactffi_provider_state_param_iter_delete, libpact_ffi, "pactffi_provider_state_param_iter_delete") + purego.RegisterLibFunc(&pactffi_provider_state_param_pair_delete, libpact_ffi, "pactffi_provider_state_param_pair_delete") + purego.RegisterLibFunc(&pactffi_sync_message_new, libpact_ffi, "pactffi_sync_message_new") + purego.RegisterLibFunc(&pactffi_sync_message_delete, libpact_ffi, "pactffi_sync_message_delete") + purego.RegisterLibFunc(&pactffi_sync_message_get_request_contents_str, libpact_ffi, "pactffi_sync_message_get_request_contents_str") + purego.RegisterLibFunc(&pactffi_sync_message_set_request_contents_str, libpact_ffi, "pactffi_sync_message_set_request_contents_str") + purego.RegisterLibFunc(&pactffi_sync_message_get_request_contents_length, libpact_ffi, "pactffi_sync_message_get_request_contents_length") + purego.RegisterLibFunc(&pactffi_sync_message_get_request_contents_bin, libpact_ffi, "pactffi_sync_message_get_request_contents_bin") + purego.RegisterLibFunc(&pactffi_sync_message_set_request_contents_bin, libpact_ffi, "pactffi_sync_message_set_request_contents_bin") + purego.RegisterLibFunc(&pactffi_sync_message_get_request_contents, libpact_ffi, "pactffi_sync_message_get_request_contents") + purego.RegisterLibFunc(&pactffi_sync_message_get_number_responses, libpact_ffi, "pactffi_sync_message_get_number_responses") + purego.RegisterLibFunc(&pactffi_sync_message_get_response_contents_str, libpact_ffi, "pactffi_sync_message_get_response_contents_str") + purego.RegisterLibFunc(&pactffi_sync_message_set_response_contents_str, libpact_ffi, "pactffi_sync_message_set_response_contents_str") + purego.RegisterLibFunc(&pactffi_sync_message_get_response_contents_length, libpact_ffi, "pactffi_sync_message_get_response_contents_length") + purego.RegisterLibFunc(&pactffi_sync_message_get_response_contents_bin, libpact_ffi, "pactffi_sync_message_get_response_contents_bin") + purego.RegisterLibFunc(&pactffi_sync_message_set_response_contents_bin, libpact_ffi, "pactffi_sync_message_set_response_contents_bin") + purego.RegisterLibFunc(&pactffi_sync_message_get_response_contents, libpact_ffi, "pactffi_sync_message_get_response_contents") + purego.RegisterLibFunc(&pactffi_sync_message_get_description, libpact_ffi, "pactffi_sync_message_get_description") + purego.RegisterLibFunc(&pactffi_sync_message_set_description, libpact_ffi, "pactffi_sync_message_set_description") + purego.RegisterLibFunc(&pactffi_sync_message_get_provider_state, libpact_ffi, "pactffi_sync_message_get_provider_state") + purego.RegisterLibFunc(&pactffi_sync_message_get_provider_state_iter, libpact_ffi, "pactffi_sync_message_get_provider_state_iter") + purego.RegisterLibFunc(&pactffi_string_delete, libpact_ffi, "pactffi_string_delete") + purego.RegisterLibFunc(&pactffi_create_mock_server, libpact_ffi, "pactffi_create_mock_server") + purego.RegisterLibFunc(&pactffi_get_tls_ca_certificate, libpact_ffi, "pactffi_get_tls_ca_certificate") + purego.RegisterLibFunc(&pactffi_create_mock_server_for_pact, libpact_ffi, "pactffi_create_mock_server_for_pact") + purego.RegisterLibFunc(&pactffi_create_mock_server_for_transport, libpact_ffi, "pactffi_create_mock_server_for_transport") + purego.RegisterLibFunc(&pactffi_mock_server_matched, libpact_ffi, "pactffi_mock_server_matched") + purego.RegisterLibFunc(&pactffi_mock_server_mismatches, libpact_ffi, "pactffi_mock_server_mismatches") + purego.RegisterLibFunc(&pactffi_cleanup_mock_server, libpact_ffi, "pactffi_cleanup_mock_server") + purego.RegisterLibFunc(&pactffi_write_pact_file, libpact_ffi, "pactffi_write_pact_file") + purego.RegisterLibFunc(&pactffi_mock_server_logs, libpact_ffi, "pactffi_mock_server_logs") + purego.RegisterLibFunc(&pactffi_generate_datetime_string, libpact_ffi, "pactffi_generate_datetime_string") + purego.RegisterLibFunc(&pactffi_check_regex, libpact_ffi, "pactffi_check_regex") + purego.RegisterLibFunc(&pactffi_generate_regex_value, libpact_ffi, "pactffi_generate_regex_value") + purego.RegisterLibFunc(&pactffi_free_string, libpact_ffi, "pactffi_free_string") + purego.RegisterLibFunc(&pactffi_new_pact, libpact_ffi, "pactffi_new_pact") + purego.RegisterLibFunc(&pactffi_pact_handle_to_pointer, libpact_ffi, "pactffi_pact_handle_to_pointer") + purego.RegisterLibFunc(&pactffi_new_interaction, libpact_ffi, "pactffi_new_interaction") + purego.RegisterLibFunc(&pactffi_new_message_interaction, libpact_ffi, "pactffi_new_message_interaction") + purego.RegisterLibFunc(&pactffi_new_sync_message_interaction, libpact_ffi, "pactffi_new_sync_message_interaction") + purego.RegisterLibFunc(&pactffi_upon_receiving, libpact_ffi, "pactffi_upon_receiving") + purego.RegisterLibFunc(&pactffi_given, libpact_ffi, "pactffi_given") + purego.RegisterLibFunc(&pactffi_interaction_test_name, libpact_ffi, "pactffi_interaction_test_name") + purego.RegisterLibFunc(&pactffi_given_with_param, libpact_ffi, "pactffi_given_with_param") + purego.RegisterLibFunc(&pactffi_given_with_params, libpact_ffi, "pactffi_given_with_params") + purego.RegisterLibFunc(&pactffi_with_request, libpact_ffi, "pactffi_with_request") + purego.RegisterLibFunc(&pactffi_with_query_parameter, libpact_ffi, "pactffi_with_query_parameter") + purego.RegisterLibFunc(&pactffi_with_query_parameter_v2, libpact_ffi, "pactffi_with_query_parameter_v2") + purego.RegisterLibFunc(&pactffi_with_specification, libpact_ffi, "pactffi_with_specification") + purego.RegisterLibFunc(&pactffi_handle_get_pact_spec_version, libpact_ffi, "pactffi_handle_get_pact_spec_version") + purego.RegisterLibFunc(&pactffi_with_pact_metadata, libpact_ffi, "pactffi_with_pact_metadata") + purego.RegisterLibFunc(&pactffi_with_header, libpact_ffi, "pactffi_with_header") + purego.RegisterLibFunc(&pactffi_with_header_v2, libpact_ffi, "pactffi_with_header_v2") + purego.RegisterLibFunc(&pactffi_set_header, libpact_ffi, "pactffi_set_header") + purego.RegisterLibFunc(&pactffi_response_status, libpact_ffi, "pactffi_response_status") + purego.RegisterLibFunc(&pactffi_response_status_v2, libpact_ffi, "pactffi_response_status_v2") + purego.RegisterLibFunc(&pactffi_with_body, libpact_ffi, "pactffi_with_body") + purego.RegisterLibFunc(&pactffi_with_binary_body, libpact_ffi, "pactffi_with_binary_body") + purego.RegisterLibFunc(&pactffi_with_binary_file, libpact_ffi, "pactffi_with_binary_file") + purego.RegisterLibFunc(&pactffi_with_matching_rules, libpact_ffi, "pactffi_with_matching_rules") + purego.RegisterLibFunc(&pactffi_with_multipart_file_v2, libpact_ffi, "pactffi_with_multipart_file_v2") + purego.RegisterLibFunc(&pactffi_with_multipart_file, libpact_ffi, "pactffi_with_multipart_file") + purego.RegisterLibFunc(&pactffi_pact_handle_get_message_iter, libpact_ffi, "pactffi_pact_handle_get_message_iter") + purego.RegisterLibFunc(&pactffi_pact_handle_get_sync_message_iter, libpact_ffi, "pactffi_pact_handle_get_sync_message_iter") + purego.RegisterLibFunc(&pactffi_pact_handle_get_sync_http_iter, libpact_ffi, "pactffi_pact_handle_get_sync_http_iter") + purego.RegisterLibFunc(&pactffi_new_message_pact, libpact_ffi, "pactffi_new_message_pact") + purego.RegisterLibFunc(&pactffi_new_message, libpact_ffi, "pactffi_new_message") + purego.RegisterLibFunc(&pactffi_with_metadata, libpact_ffi, "pactffi_with_metadata") + purego.RegisterLibFunc(&pactffi_message_expects_to_receive, libpact_ffi, "pactffi_message_expects_to_receive") + purego.RegisterLibFunc(&pactffi_message_given, libpact_ffi, "pactffi_message_given") + purego.RegisterLibFunc(&pactffi_message_given_with_param, libpact_ffi, "pactffi_message_given_with_param") + purego.RegisterLibFunc(&pactffi_message_with_contents, libpact_ffi, "pactffi_message_with_contents") + purego.RegisterLibFunc(&pactffi_message_with_metadata, libpact_ffi, "pactffi_message_with_metadata") + purego.RegisterLibFunc(&pactffi_message_with_metadata_v2, libpact_ffi, "pactffi_message_with_metadata_v2") + purego.RegisterLibFunc(&pactffi_message_reify, libpact_ffi, "pactffi_message_reify") + purego.RegisterLibFunc(&pactffi_write_message_pact_file, libpact_ffi, "pactffi_write_message_pact_file") + purego.RegisterLibFunc(&pactffi_with_message_pact_metadata, libpact_ffi, "pactffi_with_message_pact_metadata") + purego.RegisterLibFunc(&pactffi_pact_handle_write_file, libpact_ffi, "pactffi_pact_handle_write_file") + purego.RegisterLibFunc(&pactffi_new_async_message, libpact_ffi, "pactffi_new_async_message") + purego.RegisterLibFunc(&pactffi_free_pact_handle, libpact_ffi, "pactffi_free_pact_handle") + purego.RegisterLibFunc(&pactffi_free_message_pact_handle, libpact_ffi, "pactffi_free_message_pact_handle") + purego.RegisterLibFunc(&pactffi_verify, libpact_ffi, "pactffi_verify") + purego.RegisterLibFunc(&pactffi_verifier_new, libpact_ffi, "pactffi_verifier_new") + purego.RegisterLibFunc(&pactffi_verifier_new_for_application, libpact_ffi, "pactffi_verifier_new_for_application") + purego.RegisterLibFunc(&pactffi_verifier_shutdown, libpact_ffi, "pactffi_verifier_shutdown") + purego.RegisterLibFunc(&pactffi_verifier_set_provider_info, libpact_ffi, "pactffi_verifier_set_provider_info") + purego.RegisterLibFunc(&pactffi_verifier_add_provider_transport, libpact_ffi, "pactffi_verifier_add_provider_transport") + purego.RegisterLibFunc(&pactffi_verifier_set_filter_info, libpact_ffi, "pactffi_verifier_set_filter_info") + purego.RegisterLibFunc(&pactffi_verifier_set_provider_state, libpact_ffi, "pactffi_verifier_set_provider_state") + purego.RegisterLibFunc(&pactffi_verifier_set_verification_options, libpact_ffi, "pactffi_verifier_set_verification_options") + purego.RegisterLibFunc(&pactffi_verifier_set_coloured_output, libpact_ffi, "pactffi_verifier_set_coloured_output") + purego.RegisterLibFunc(&pactffi_verifier_set_no_pacts_is_error, libpact_ffi, "pactffi_verifier_set_no_pacts_is_error") + purego.RegisterLibFunc(&pactffi_verifier_set_publish_options, libpact_ffi, "pactffi_verifier_set_publish_options") + purego.RegisterLibFunc(&pactffi_verifier_set_consumer_filters, libpact_ffi, "pactffi_verifier_set_consumer_filters") + purego.RegisterLibFunc(&pactffi_verifier_add_custom_header, libpact_ffi, "pactffi_verifier_add_custom_header") + purego.RegisterLibFunc(&pactffi_verifier_add_file_source, libpact_ffi, "pactffi_verifier_add_file_source") + purego.RegisterLibFunc(&pactffi_verifier_add_directory_source, libpact_ffi, "pactffi_verifier_add_directory_source") + purego.RegisterLibFunc(&pactffi_verifier_url_source, libpact_ffi, "pactffi_verifier_url_source") + purego.RegisterLibFunc(&pactffi_verifier_broker_source, libpact_ffi, "pactffi_verifier_broker_source") + purego.RegisterLibFunc(&pactffi_verifier_broker_source_with_selectors, libpact_ffi, "pactffi_verifier_broker_source_with_selectors") + purego.RegisterLibFunc(&pactffi_verifier_execute, libpact_ffi, "pactffi_verifier_execute") + purego.RegisterLibFunc(&pactffi_verifier_cli_args, libpact_ffi, "pactffi_verifier_cli_args") + purego.RegisterLibFunc(&pactffi_verifier_logs, libpact_ffi, "pactffi_verifier_logs") + purego.RegisterLibFunc(&pactffi_verifier_logs_for_provider, libpact_ffi, "pactffi_verifier_logs_for_provider") + purego.RegisterLibFunc(&pactffi_verifier_output, libpact_ffi, "pactffi_verifier_output") + purego.RegisterLibFunc(&pactffi_verifier_json, libpact_ffi, "pactffi_verifier_json") + purego.RegisterLibFunc(&pactffi_using_plugin, libpact_ffi, "pactffi_using_plugin") + purego.RegisterLibFunc(&pactffi_cleanup_plugins, libpact_ffi, "pactffi_cleanup_plugins") + purego.RegisterLibFunc(&pactffi_interaction_contents, libpact_ffi, "pactffi_interaction_contents") + purego.RegisterLibFunc(&pactffi_matches_string_value, libpact_ffi, "pactffi_matches_string_value") + purego.RegisterLibFunc(&pactffi_matches_u64_value, libpact_ffi, "pactffi_matches_u64_value") + purego.RegisterLibFunc(&pactffi_matches_i64_value, libpact_ffi, "pactffi_matches_i64_value") + purego.RegisterLibFunc(&pactffi_matches_f64_value, libpact_ffi, "pactffi_matches_f64_value") + purego.RegisterLibFunc(&pactffi_matches_bool_value, libpact_ffi, "pactffi_matches_bool_value") + purego.RegisterLibFunc(&pactffi_matches_binary_value, libpact_ffi, "pactffi_matches_binary_value") + purego.RegisterLibFunc(&pactffi_matches_json_value, libpact_ffi, "pactffi_matches_json_value") +} + +// func main() { + +// print(pactffi_version()) +// pactffi_log_to_stdout(4) +// // pactffi_log_to_file("pact.log", 5) + +// var verifier_handle = pactffi_verifier_new_for_application("pact-purego", "0.0.1") +// pactffi_verifier_set_provider_info(verifier_handle, "grpc-provider", "http", "localhost", 1234, "/") +// pactffi_verifier_add_file_source(verifier_handle, "no_pact.json") +// // pactffi_verifier_add_file_source(verifier_handle, "pact.json") +// // pactffi_verifier_add_file_source(verifier_handle, "../pacts/Consumer-Alice Service.json") +// // pactffi_verifier_add_file_source(verifier_handle, "../pacts/grpc-consumer-perl-area-calculator-provider.json") +// pactffi_verifier_execute(verifier_handle) +// pactffi_verifier_shutdown(verifier_handle) +// } + +// hasSuffix tests whether the string s ends with suffix. +func hasSuffix(s, suffix string) bool { + return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix +} + +// CString converts a go string to *byte that can be passed to C code. +func CString(name string) *byte { + if hasSuffix(name, "\x00") { + return &(*(*[]byte)(unsafe.Pointer(&name)))[0] + } + b := make([]byte, len(name)+1) + copy(b, name) + return &b[0] +} diff --git a/internal/native/lib_unix.go b/internal/native/lib_unix.go new file mode 100644 index 000000000..c072731c6 --- /dev/null +++ b/internal/native/lib_unix.go @@ -0,0 +1,9 @@ +//go:build darwin || linux + +package native + +import "github.com/ebitengine/purego" + +func openLibrary(name string) (uintptr, error) { + return purego.Dlopen(name, purego.RTLD_NOW|purego.RTLD_GLOBAL) +} diff --git a/internal/native/lib_windows.go b/internal/native/lib_windows.go new file mode 100644 index 000000000..d07ffa93f --- /dev/null +++ b/internal/native/lib_windows.go @@ -0,0 +1,10 @@ +//go:build windows + +package native + +import "golang.org/x/sys/windows" + +func openLibrary(name string) (uintptr, error) { + handle, err := windows.LoadLibrary(name) + return uintptr(handle), err +} diff --git a/internal/native/message_server.go b/internal/native/message_server.go index 4fb0dbb9e..f6cada891 100644 --- a/internal/native/message_server.go +++ b/internal/native/message_server.go @@ -1,20 +1,16 @@ package native -/* -#include "pact.h" -*/ -import "C" - import ( "encoding/json" "errors" "fmt" "log" + "unsafe" ) type MessagePact struct { - handle C.PactHandle + handle uintptr } type messageType int @@ -25,7 +21,7 @@ const ( ) type Message struct { - handle C.InteractionHandle + handle uintptr messageType messageType pact *MessagePact index int @@ -40,24 +36,24 @@ type MessageServer struct { // NewMessage initialises a new message for the current contract func NewMessageServer(consumer string, provider string) *MessageServer { - cConsumer := C.CString(consumer) - cProvider := C.CString(provider) - defer free(cConsumer) - defer free(cProvider) + // cConsumer := C.CString(consumer) + // cProvider := C.CString(provider) + // defer free(cConsumer) + // defer free(cProvider) - return &MessageServer{messagePact: &MessagePact{handle: C.pactffi_new_message_pact(cConsumer, cProvider)}} + return &MessageServer{messagePact: &MessagePact{handle: pactffi_new_message_pact(consumer, provider)}} } // Sets the additional metadata on the Pact file. Common uses are to add the client library details such as the name and version func (m *MessageServer) WithMetadata(namespace, k, v string) *MessageServer { - cNamespace := C.CString(namespace) - defer free(cNamespace) - cName := C.CString(k) - defer free(cName) - cValue := C.CString(v) - defer free(cValue) + // cNamespace := C.CString(namespace) + // defer free(cNamespace) + // cName := C.CString(k) + // defer free(cName) + // cValue := C.CString(v) + // defer free(cValue) - C.pactffi_with_message_pact_metadata(m.messagePact.handle, cNamespace, cName, cValue) + pactffi_with_message_pact_metadata(m.messagePact.handle, namespace, k, v) return m } @@ -71,11 +67,9 @@ func (m *MessageServer) NewMessage() *Message { // NewSyncMessageInteraction initialises a new synchronous message interaction for the current contract func (m *MessageServer) NewSyncMessageInteraction(description string) *Message { - cDescription := C.CString(description) - defer free(cDescription) i := &Message{ - handle: C.pactffi_new_sync_message_interaction(m.messagePact.handle, cDescription), + handle: pactffi_new_sync_message_interaction(m.messagePact.handle, description), messageType: MESSAGE_TYPE_SYNC, pact: m.messagePact, index: len(m.messages), @@ -88,11 +82,9 @@ func (m *MessageServer) NewSyncMessageInteraction(description string) *Message { // NewAsyncMessageInteraction initialises a new asynchronous message interaction for the current contract func (m *MessageServer) NewAsyncMessageInteraction(description string) *Message { - cDescription := C.CString(description) - defer free(cDescription) i := &Message{ - handle: C.pactffi_new_message_interaction(m.messagePact.handle, cDescription), + handle: pactffi_new_message_interaction(m.messagePact.handle, description), messageType: MESSAGE_TYPE_ASYNC, pact: m.messagePact, index: len(m.messages), @@ -104,35 +96,22 @@ func (m *MessageServer) NewAsyncMessageInteraction(description string) *Message } func (m *MessageServer) WithSpecificationVersion(version specificationVersion) { - C.pactffi_with_specification(m.messagePact.handle, C.int(version)) + pactffi_with_specification(m.messagePact.handle, int32(version)) } func (m *Message) Given(state string) *Message { - cState := C.CString(state) - defer free(cState) - - C.pactffi_given(m.handle, cState) + pactffi_given(m.handle, state) return m } func (m *Message) GivenWithParameter(state string, params map[string]interface{}) *Message { - cState := C.CString(state) - defer free(cState) - if len(params) == 0 { - C.pactffi_given(m.handle, cState) + pactffi_given(m.handle, state) } else { for k, v := range params { - cKey := C.CString(k) - param := stringFromInterface(v) - cValue := C.CString(param) - - C.pactffi_given_with_param(m.handle, cState, cKey, cValue) - - free(cValue) - free(cKey) + pactffi_given_with_param(m.handle, state, k, param) } } @@ -140,76 +119,51 @@ func (m *Message) GivenWithParameter(state string, params map[string]interface{} } func (m *Message) ExpectsToReceive(description string) *Message { - cDescription := C.CString(description) - defer free(cDescription) - - C.pactffi_message_expects_to_receive(m.handle, cDescription) + pactffi_message_expects_to_receive(m.handle, description) return m } func (m *Message) WithMetadata(valueOrMatcher map[string]string) *Message { for k, v := range valueOrMatcher { - cName := C.CString(k) - // TODO: check if matching rules allowed here // value := stringFromInterface(v) // fmt.Printf("withheaders, sending: %+v \n\n", value) // cValue := C.CString(value) - cValue := C.CString(v) - - C.pactffi_message_with_metadata(m.handle, cName, cValue) - free(cValue) - free(cName) + pactffi_message_with_metadata(m.handle, k, v) } return m } func (m *Message) WithRequestMetadata(valueOrMatcher map[string]string) *Message { for k, v := range valueOrMatcher { - cName := C.CString(k) - cValue := C.CString(v) - - C.pactffi_with_metadata(m.handle, cName, cValue, 0) - - free(cValue) - free(cName) + pactffi_with_metadata(m.handle, k, v, 0) } return m } func (m *Message) WithResponseMetadata(valueOrMatcher map[string]string) *Message { for k, v := range valueOrMatcher { - cName := C.CString(k) - cValue := C.CString(v) - - C.pactffi_with_metadata(m.handle, cName, cValue, 1) - - free(cValue) - free(cName) + pactffi_with_metadata(m.handle, k, v, 1) } return m } func (m *Message) WithRequestBinaryContents(body []byte) *Message { - cHeader := C.CString("application/octet-stream") - defer free(cHeader) // TODO: handle response - res := C.pactffi_with_binary_file(m.handle, C.int(INTERACTION_PART_REQUEST), cHeader, (*C.uchar)(unsafe.Pointer(&body[0])), CUlong(len(body))) + res := pactffi_with_binary_file(m.handle, int32(INTERACTION_PART_REQUEST), "application/octet-stream", string(body), size_t(len(body))) - log.Println("[DEBUG] WithRequestBinaryContents - pactffi_with_binary_file returned", bool(res)) + log.Println("[DEBUG] WithRequestBinaryContents - pactffi_with_binary_file returned", res) return m } func (m *Message) WithRequestBinaryContentType(contentType string, body []byte) *Message { - cHeader := C.CString(contentType) - defer free(cHeader) // TODO: handle response - res := C.pactffi_with_binary_file(m.handle, C.int(INTERACTION_PART_REQUEST), cHeader, (*C.uchar)(unsafe.Pointer(&body[0])), CUlong(len(body))) + res := pactffi_with_binary_file(m.handle, int32(INTERACTION_PART_REQUEST), contentType, string(body), size_t(len(body))) log.Println("[DEBUG] WithRequestBinaryContents - pactffi_with_binary_file returned", res) @@ -225,11 +179,9 @@ func (m *Message) WithRequestJSONContents(body interface{}) *Message { } func (m *Message) WithResponseBinaryContents(body []byte) *Message { - cHeader := C.CString("application/octet-stream") - defer free(cHeader) // TODO: handle response - C.pactffi_with_binary_file(m.handle, C.int(INTERACTION_PART_RESPONSE), cHeader, (*C.uchar)(unsafe.Pointer(&body[0])), CUlong(len(body))) + pactffi_with_binary_file(m.handle, int32(INTERACTION_PART_RESPONSE), "application/octet-stream", string(body), size_t(len(body))) return m } @@ -244,14 +196,9 @@ func (m *Message) WithResponseJSONContents(body interface{}) *Message { // Note that string values here must be NUL terminated. func (m *Message) WithContents(part interactionPart, contentType string, body []byte) *Message { - cHeader := C.CString(contentType) - defer free(cHeader) - - cBody := C.CString(string(body)) - defer free(cBody) - res := C.pactffi_with_body(m.handle, C.int(part), cHeader, cBody) - log.Println("[DEBUG] response from pactffi_interaction_contents", (bool(res))) + res := pactffi_with_body(m.handle, int32(part), contentType, string(body)) + log.Println("[DEBUG] response from pactffi_interaction_contents", res) return m } @@ -260,13 +207,8 @@ func (m *Message) WithContents(part interactionPart, contentType string, body [] // NewInteraction initialises a new interaction for the current contract func (m *MessageServer) 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.messagePact.handle, cPluginName, cPluginVersion) + r := pactffi_using_plugin(m.messagePact.handle, pluginName, pluginVersion) // 1 - A general panic was caught. // 2 - Failed to load the plugin. // 3 - Pact Handle is not valid. @@ -289,12 +231,8 @@ func (m *MessageServer) UsingPlugin(pluginName string, pluginVersion string) err // NewInteraction initialises a new interaction for the current contract func (m *Message) WithPluginInteractionContents(part interactionPart, contentType string, contents string) error { - cContentType := C.CString(contentType) - defer free(cContentType) - cContents := C.CString(contents) - defer free(cContents) - r := C.pactffi_interaction_contents(m.handle, C.int(part), cContentType, cContents) + r := pactffi_interaction_contents(m.handle, int32(part), contentType, contents) // 1 - A general panic was caught. // 2 - The mock server has already been started. @@ -325,6 +263,18 @@ func (m *Message) WithPluginInteractionContents(part interactionPart, contentTyp return nil } +func GoByteArrayFromC(ptr uintptr, length int) []byte { + if unsafe.Pointer(ptr) == nil || length == 0 { + return []byte{} + } + // Create a Go byte slice from the C string + b := make([]byte, length) + for i := 0; i < length; i++ { + b[i] = *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(ptr)) + uintptr(i))) + } + return b +} + // GetMessageContents retreives the binary contents of the request for a given message // any matchers are stripped away if given // if the contents is from a plugin, the byte[] representation of the parsed @@ -332,9 +282,10 @@ func (m *Message) WithPluginInteractionContents(part interactionPart, contentTyp func (m *Message) GetMessageRequestContents() ([]byte, error) { log.Println("[DEBUG] GetMessageRequestContents") if m.messageType == MESSAGE_TYPE_ASYNC { - iter := C.pactffi_pact_handle_get_message_iter(m.pact.handle) + iter := pactffi_pact_handle_get_message_iter(m.pact.handle) log.Println("[DEBUG] pactffi_pact_handle_get_message_iter") - if iter == nil { + // TODO + if unsafe.Pointer(iter) == nil { return nil, errors.New("unable to get a message iterator") } log.Println("[DEBUG] pactffi_pact_handle_get_message_iter - OK") @@ -347,63 +298,59 @@ func (m *Message) GetMessageRequestContents() ([]byte, error) { for i := 0; i < len(m.server.messages); i++ { log.Println("[DEBUG] pactffi_pact_handle_get_message_iter - index", i) - message := C.pactffi_pact_message_iter_next(iter) + message := pactffi_pact_message_iter_next(iter) log.Println("[DEBUG] pactffi_pact_message_iter_next - message", message) if i == m.index { log.Println("[DEBUG] pactffi_pact_message_iter_next - index match", message) - if message == nil { + if unsafe.Pointer(message) == nil { return nil, errors.New("retrieved a null message pointer") } - - len := C.pactffi_message_get_contents_length(message) + len := pactffi_message_get_contents_length(message) log.Println("[DEBUG] pactffi_message_get_contents_length - len", len) if len == 0 { // You can have empty bodies log.Println("[DEBUG] message body is empty") - return nil, nil + return []byte{}, nil } - data := C.pactffi_message_get_contents_bin(message) + data := pactffi_message_get_contents_bin(message) log.Println("[DEBUG] pactffi_message_get_contents_bin - data", data) - if data == nil { + if unsafe.Pointer(data) == nil { // You can have empty bodies log.Println("[DEBUG] message binary contents are empty") return nil, nil } - ptr := unsafe.Pointer(data) - bytes := C.GoBytes(ptr, C.int(len)) - + bytes := GoByteArrayFromC(data, int(len)) return bytes, nil } } } else { - iter := C.pactffi_pact_handle_get_sync_message_iter(m.pact.handle) - if iter == nil { + iter := pactffi_pact_handle_get_sync_message_iter(m.pact.handle) + if unsafe.Pointer(iter) == nil { return nil, errors.New("unable to get a message iterator") } for i := 0; i < len(m.server.messages); i++ { - message := C.pactffi_pact_sync_message_iter_next(iter) + message := pactffi_pact_sync_message_iter_next(iter) if i == m.index { - if message == nil { + if unsafe.Pointer(message) == nil { return nil, errors.New("retrieved a null message pointer") } - len := C.pactffi_sync_message_get_request_contents_length(message) + len := pactffi_sync_message_get_request_contents_length(message) if len == 0 { log.Println("[DEBUG] message body is empty") - return nil, nil + return []byte{}, nil } - data := C.pactffi_sync_message_get_request_contents_bin(message) - if data == nil { + data := pactffi_sync_message_get_request_contents_bin(message) + if unsafe.Pointer(data) == nil { log.Println("[DEBUG] message binary contents are empty") return nil, nil } - ptr := unsafe.Pointer(data) - bytes := C.GoBytes(ptr, C.int(len)) + bytes := GoByteArrayFromC(data, int(len)) return bytes, nil } @@ -423,29 +370,35 @@ func (m *Message) GetMessageResponseContents() ([][]byte, error) { if m.messageType == MESSAGE_TYPE_ASYNC { return nil, errors.New("invalid request: asynchronous messages do not have response") } - iter := C.pactffi_pact_handle_get_sync_message_iter(m.pact.handle) - if iter == nil { + iter := pactffi_pact_handle_get_sync_message_iter(m.pact.handle) + if unsafe.Pointer(iter) == nil { return nil, errors.New("unable to get a message iterator") } for i := 0; i < len(m.server.messages); i++ { - message := C.pactffi_pact_sync_message_iter_next(iter) + message := pactffi_pact_sync_message_iter_next(iter) - if message == nil { + if unsafe.Pointer(message) == nil { return nil, errors.New("retrieved a null message pointer") } // Get Response body - len := C.pactffi_sync_message_get_response_contents_length(message, C.size_t(i)) - if len != 0 { - data := C.pactffi_sync_message_get_response_contents_bin(message, C.size_t(i)) - if data == nil { - return nil, errors.New("retrieved an empty pointer to the message contents") - } - ptr := unsafe.Pointer(data) - bytes := C.GoBytes(ptr, C.int(len)) - responses[i] = bytes + len := pactffi_sync_message_get_response_contents_length(message, size_t(i)) + // if len == 0 { + // return nil, errors.New("retrieved an empty message") + // } + if len == 0 { + // You can have empty bodies + log.Println("[DEBUG] message body is empty") + responses[i] = []byte{} + return responses, nil } + data := pactffi_sync_message_get_response_contents_bin(message, size_t(i)) + if unsafe.Pointer(data) == nil { + return nil, errors.New("retrieved an empty pointer to the message contents") + } + bytes := GoByteArrayFromC(data, int(len)) + responses[i] = bytes } return responses, nil @@ -459,17 +412,9 @@ func (m *MessageServer) StartTransport(transport string, address string, port in } log.Println("[DEBUG] mock server starting on address:", address, port) - cAddress := C.CString(address) - defer free(cAddress) - - cTransport := C.CString(transport) - defer free(cTransport) - configJson := stringFromInterface(config) - cConfig := C.CString(configJson) - defer free(cConfig) - p := C.pactffi_create_mock_server_for_transport(m.messagePact.handle, cAddress, C.ushort(port), cTransport, cConfig) + p := pactffi_create_mock_server_for_transport(m.messagePact.handle, address, uint16(port), transport, configJson) // | Error | Description // |-------|------------- @@ -501,7 +446,7 @@ func (m *MessageServer) StartTransport(transport string, address string, port in // NewInteraction initialises a new interaction for the current contract func (m *MessageServer) CleanupPlugins() { - C.pactffi_cleanup_plugins(m.messagePact.handle) + pactffi_cleanup_plugins(m.messagePact.handle) } // CleanupMockServer frees the memory from the previous mock server. @@ -510,9 +455,9 @@ func (m *MessageServer) CleanupMockServer(port int) bool { return true } log.Println("[DEBUG] mock server cleaning up port:", port) - res := C.pactffi_cleanup_mock_server(C.int(port)) + res := pactffi_cleanup_mock_server(int32(port)) - return bool(res) + return res } // MockServerMismatchedRequests returns a JSON object containing any mismatches from @@ -521,16 +466,17 @@ func (m *MessageServer) MockServerMismatchedRequests(port int) []MismatchedReque log.Println("[DEBUG] mock server determining mismatches:", port) var res []MismatchedRequest - mismatches := C.pactffi_mock_server_mismatches(C.int(port)) + mismatches := pactffi_mock_server_mismatches(int32(port)) // This method can return a nil pointer, in which case, it // should be considered a failure (or at least, an issue) // converting it to a string might also do nasty things here! - if mismatches == nil { + // TODO change return type to uintptr + if mismatches == "" { log.Println("[WARN] received a null pointer from the native interface, returning empty list of mismatches") return []MismatchedRequest{} } - err := json.Unmarshal([]byte(C.GoString(mismatches)), &res) + err := json.Unmarshal([]byte(mismatches), &res) if err != nil { log.Println("[ERROR] failed to unmarshal mismatches response, returning empty list of mismatches") return []MismatchedRequest{} @@ -544,27 +490,25 @@ func (m *MessageServer) MockServerMismatchedRequests(port int) []MismatchedReque func (m *MessageServer) MockServerMatched(port int) bool { log.Println("[DEBUG] mock server determining mismatches:", port) - res := C.pactffi_mock_server_matched(C.int(port)) + res := pactffi_mock_server_matched(int32(port)) // TODO: why this number is so big and not a bool? Type def wrong? Port value wrong? // log.Println("MATCHED RES?") // log.Println(int(res)) - return bool(res) + return res } // WritePactFile writes the Pact to file. func (m *MessageServer) WritePactFile(dir string, overwrite bool) error { log.Println("[DEBUG] writing pact file for message pact at dir:", dir) - cDir := C.CString(dir) - defer free(cDir) overwritePact := false if overwrite { overwritePact = true } - res := int(C.pactffi_write_message_pact_file(m.messagePact.handle, cDir, C.bool(overwritePact))) + res := pactffi_write_message_pact_file(m.messagePact.handle, dir, overwritePact) /// | Error | Description | /// |-------|-------------| @@ -585,15 +529,13 @@ func (m *MessageServer) WritePactFile(dir string, overwrite bool) error { // WritePactFile writes the Pact to file. func (m *MessageServer) WritePactFileForServer(port int, dir string, overwrite bool) error { log.Println("[DEBUG] writing pact file for message pact at dir:", dir) - cDir := C.CString(dir) - defer free(cDir) overwritePact := false if overwrite { overwritePact = true } - res := int(C.pactffi_write_pact_file(C.int(port), cDir, C.bool(overwritePact))) + res := pactffi_write_pact_file(int32(port), dir, overwritePact) /// | Error | Description | /// |-------|-------------| diff --git a/internal/native/mock_server.go b/internal/native/mock_server.go index 2429301c1..dcf179387 100644 --- a/internal/native/mock_server.go +++ b/internal/native/mock_server.go @@ -1,10 +1,5 @@ package native -/* -#include "pact.h" -*/ -import "C" - import ( "crypto/tls" "crypto/x509" @@ -12,8 +7,8 @@ import ( "fmt" "log" "os" + "strings" - "unsafe" ) type interactionPart int @@ -61,19 +56,19 @@ var logLevelStringToInt = map[string]logLevel{ // Pact is a Go representation of the PactHandle struct type Pact struct { - handle C.PactHandle + handle uintptr } // Interaction is a Go representation of the InteractionHandle struct type Interaction struct { - handle C.InteractionHandle + handle uintptr } // Version returns the current semver FFI interface version func Version() string { - v := C.pactffi_version() + v := pactffi_version() - return C.GoString(v) + return v } var loggingInitialised string @@ -111,18 +106,13 @@ func Init(logLevel string) { // MockServer is the public interface for managing the HTTP mock server type MockServer struct { pact *Pact - messagePact *MessagePact + // messagePact *MessagePact interactions []*Interaction } // NewHTTPPact creates a new HTTP mock server for a given consumer/provider func NewHTTPPact(consumer string, provider string) *MockServer { - cConsumer := C.CString(consumer) - cProvider := C.CString(provider) - defer free(cConsumer) - defer free(cProvider) - - return &MockServer{pact: &Pact{handle: C.pactffi_new_pact(cConsumer, cProvider)}} + return &MockServer{pact: &Pact{handle: pactffi_new_pact(consumer, provider)}} } // Version returns the current semver FFI interface version @@ -131,23 +121,19 @@ func (m *MockServer) Version() string { } func (m *MockServer) WithSpecificationVersion(version specificationVersion) { - C.pactffi_with_specification(m.pact.handle, C.int(version)) + pactffi_with_specification(m.pact.handle, int32(version)) } // CreateMockServer creates a new Mock Server from a given Pact file. // Returns the port number it started on or an error if failed func (m *MockServer) CreateMockServer(pact string, address string, tls bool) (int, error) { log.Println("[DEBUG] mock server starting on address:", address) - cPact := C.CString(pact) - cAddress := C.CString(address) - defer free(cPact) - defer free(cAddress) tlsEnabled := false if tls { tlsEnabled = true } - p := C.pactffi_create_mock_server(cPact, cAddress, C.bool(tlsEnabled)) + p := pactffi_create_mock_server(pact, address, tlsEnabled) // | Error | Description | // |-------|-------------| @@ -195,16 +181,16 @@ func (m *MockServer) MockServerMismatchedRequests(port int) []MismatchedRequest log.Println("[DEBUG] mock server determining mismatches:", port) var res []MismatchedRequest - mismatches := C.pactffi_mock_server_mismatches(C.int(port)) + mismatches := pactffi_mock_server_mismatches(int32(port)) // This method can return a nil pointer, in which case, it // should be considered a failure (or at least, an issue) // converting it to a string might also do nasty things here! - if mismatches == nil { + if mismatches == "" { log.Println("[WARN] received a null pointer from the native interface, returning empty list of mismatches") return []MismatchedRequest{} } - err := json.Unmarshal([]byte(C.GoString(mismatches)), &res) + err := json.Unmarshal([]byte(mismatches), &res) if err != nil { log.Println("[ERROR] failed to unmarshal mismatches response, returning empty list of mismatches") return []MismatchedRequest{} @@ -218,25 +204,23 @@ func (m *MockServer) CleanupMockServer(port int) bool { return true } log.Println("[DEBUG] mock server cleaning up port:", port) - res := C.pactffi_cleanup_mock_server(C.int(port)) + res := pactffi_cleanup_mock_server(int32(port)) - return bool(res) + return res } // WritePactFile writes the Pact to file. // TODO: expose overwrite func (m *MockServer) WritePactFile(port int, dir string) error { log.Println("[DEBUG] writing pact file for mock server on port:", port, ", dir:", dir) - cDir := C.CString(dir) - defer free(cDir) - // overwritePact := 0 + overwritePact := false // if overwrite { // overwritePact = 1 // } // res := int(C.pactffi_write_pact_file(C.int(port), cDir, C.int(overwritePact))) - res := int(C.pactffi_write_pact_file(C.int(port), cDir, C.bool(false))) + res := int(pactffi_write_pact_file(int32(port), dir, overwritePact)) // | Error | Description | // |-------|-------------| @@ -260,25 +244,28 @@ func (m *MockServer) WritePactFile(port int, dir string) error { // GetTLSConfig returns a tls.Config compatible with the TLS // mock server func GetTLSConfig() *tls.Config { - cert := C.pactffi_get_tls_ca_certificate() - defer libRustFree(cert) + cert := pactffi_get_tls_ca_certificate() + // defer libRustFree(cert) - goCert := C.GoString(cert) certPool := x509.NewCertPool() - certPool.AppendCertsFromPEM([]byte(goCert)) + certPool.AppendCertsFromPEM([]byte(cert)) return &tls.Config{ RootCAs: certPool, } } -func free(str *C.char) { - C.free(unsafe.Pointer(str)) -} +// func free(str *C.char) { +// C.free(unsafe.Pointer(str)) +// } -func libRustFree(str *C.char) { - C.pactffi_free_string(str) -} +// func libRustFree(str uintptr) { +// pactffi_free_string(str) +// } + +// func libRustFree(str string) { +// pactffi_string_delete(str) +// } // Start starts up the mock HTTP server on the given address:port and TLS config // https://docs.rs/pact_mock_server_ffi/0.0.7/pact_mock_server_ffi/fn.create_mock_server_for_pact.html @@ -288,14 +275,14 @@ func (m *MockServer) Start(address string, tls bool) (int, error) { } log.Println("[DEBUG] mock server starting on address:", address) - cAddress := C.CString(address) - defer free(cAddress) + // cAddress := C.CString(address) + // defer free(cAddress) tlsEnabled := false if tls { tlsEnabled = true } - p := C.pactffi_create_mock_server_for_pact(m.pact.handle, cAddress, C.bool(tlsEnabled)) + p := pactffi_create_mock_server_for_pact(m.pact.handle, address, tlsEnabled) // | Error | Description | // |-------|-------------| @@ -334,19 +321,10 @@ func (m *MockServer) StartTransport(transport string, address string, port int, if len(m.interactions) == 0 { return 0, ErrNoInteractions } - - log.Println("[DEBUG] mock server starting on address:", address, port) - cAddress := C.CString(address) - defer free(cAddress) - - cTransport := C.CString(transport) - defer free(cTransport) - configJson := stringFromInterface(config) - cConfig := C.CString(configJson) - defer free(cConfig) - p := C.pactffi_create_mock_server_for_transport(m.pact.handle, cAddress, C.ushort(port), cTransport, cConfig) + log.Println("[DEBUG] mock server starting on address:", address, port) + p := pactffi_create_mock_server_for_transport(m.pact.handle, address, uint16(port), transport, configJson) // | Error | Description // |-------|------------- @@ -378,27 +356,15 @@ func (m *MockServer) StartTransport(transport string, address string, port int, // Sets the additional metadata on the Pact file. Common uses are to add the client library details such as the name and version func (m *MockServer) WithMetadata(namespace, k, v string) *MockServer { - cNamespace := C.CString(namespace) - defer free(cNamespace) - cName := C.CString(k) - defer free(cName) - cValue := C.CString(v) - defer free(cValue) - - C.pactffi_with_pact_metadata(m.pact.handle, cNamespace, cName, cValue) + pactffi_with_pact_metadata(m.pact.handle, namespace, k, v) 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) + r := pactffi_using_plugin(m.pact.handle, pluginName, pluginVersion) // 1 - A general panic was caught. // 2 - Failed to load the plugin. // 3 - Pact Handle is not valid. @@ -421,16 +387,13 @@ func (m *MockServer) UsingPlugin(pluginName string, pluginVersion string) error // NewInteraction initialises a new interaction for the current contract func (m *MockServer) CleanupPlugins() { - C.pactffi_cleanup_plugins(m.pact.handle) + 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) - defer free(cDescription) - i := &Interaction{ - handle: C.pactffi_new_interaction(m.pact.handle, cDescription), + handle: pactffi_new_interaction(m.pact.handle, description), } m.interactions = append(m.interactions, i) @@ -439,12 +402,8 @@ func (m *MockServer) NewInteraction(description string) *Interaction { // NewInteraction initialises a new interaction for the current contract func (i *Interaction) WithPluginInteractionContents(part interactionPart, 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(part), cContentType, cContents) + r := pactffi_interaction_contents(i.handle, int32(part), contentType, contents) // 1 - A general panic was caught. // 2 - The mock server has already been started. @@ -476,50 +435,31 @@ func (i *Interaction) WithPluginInteractionContents(part interactionPart, conten } func (i *Interaction) UponReceiving(description string) *Interaction { - cDescription := C.CString(description) - defer free(cDescription) - - C.pactffi_upon_receiving(i.handle, cDescription) + pactffi_upon_receiving(i.handle, description) return i } func (i *Interaction) Given(state string) *Interaction { - cState := C.CString(state) - defer free(cState) - - C.pactffi_given(i.handle, cState) + pactffi_given(i.handle, state) return i } func (i *Interaction) GivenWithParameter(state string, params map[string]interface{}) *Interaction { - cState := C.CString(state) - defer free(cState) for k, v := range params { - cKey := C.CString(k) param := stringFromInterface(v) - cValue := C.CString(param) - - C.pactffi_given_with_param(i.handle, cState, cKey, cValue) - - free(cValue) - free(cKey) + pactffi_given_with_param(i.handle, state, k, param) } return i } func (i *Interaction) WithRequest(method string, pathOrMatcher interface{}) *Interaction { - cMethod := C.CString(method) - defer free(cMethod) - path := stringFromInterface(pathOrMatcher) - cPath := C.CString(path) - defer free(cPath) - C.pactffi_with_request(i.handle, cMethod, cPath) + pactffi_with_request(i.handle, method, path) return i } @@ -534,18 +474,12 @@ func (i *Interaction) WithResponseHeaders(valueOrMatcher map[string][]interface{ func (i *Interaction) withHeaders(part interactionPart, valueOrMatcher map[string][]interface{}) *Interaction { for k, v := range valueOrMatcher { - cName := C.CString(k) - for _, header := range v { value := stringFromInterface(header) - cValue := C.CString(value) - - C.pactffi_with_header_v2(i.handle, C.int(part), cName, CUlong(0), cValue) - free(cValue) + pactffi_with_header_v2(i.handle, int32(part), k, int(0), value) } - free(cName) } return i @@ -553,18 +487,12 @@ func (i *Interaction) withHeaders(part interactionPart, valueOrMatcher map[strin func (i *Interaction) WithQuery(valueOrMatcher map[string][]interface{}) *Interaction { for k, values := range valueOrMatcher { - cName := C.CString(k) for idx, v := range values { value := stringFromInterface(v) - cValue := C.CString(value) - C.pactffi_with_query_parameter_v2(i.handle, cName, CUlong(idx), cValue) - - free(cValue) + pactffi_with_query_parameter_v2(i.handle, k, int(idx), value) } - - free(cName) } return i @@ -579,14 +507,9 @@ func (i *Interaction) WithJSONResponseBody(body interface{}) *Interaction { } func (i *Interaction) withJSONBody(body interface{}, part interactionPart) *Interaction { - cHeader := C.CString("application/json") - defer free(cHeader) - jsonBody := stringFromInterface(body) - cBody := C.CString(jsonBody) - defer free(cBody) - C.pactffi_with_body(i.handle, C.int(part), cHeader, cBody) + pactffi_with_body(i.handle, int32(part), "application/json", jsonBody) return i } @@ -600,22 +523,15 @@ func (i *Interaction) WithResponseBody(contentType string, body []byte) *Interac } func (i *Interaction) withBody(contentType string, body []byte, part interactionPart) *Interaction { - cHeader := C.CString(contentType) - defer free(cHeader) - - cBody := C.CString(string(body)) - defer free(cBody) - C.pactffi_with_body(i.handle, C.int(part), cHeader, cBody) + pactffi_with_body(i.handle, int32(part), contentType, string(body)) return i } func (i *Interaction) withBinaryBody(contentType string, body []byte, part interactionPart) *Interaction { - cHeader := C.CString(contentType) - defer free(cHeader) - C.pactffi_with_binary_file(i.handle, C.int(part), cHeader, (*C.uchar)(unsafe.Pointer(&body[0])), CUlong(len(body))) + pactffi_with_binary_file(i.handle, int32(part), contentType, string(body), size_t(len(body))) return i } @@ -637,30 +553,21 @@ func (i *Interaction) WithResponseMultipartFile(contentType string, filename str } func (i *Interaction) withMultipartFile(contentType string, filename string, mimePartName string, part interactionPart) *Interaction { - cHeader := C.CString(contentType) - defer free(cHeader) - - cPartName := C.CString(mimePartName) - defer free(cPartName) - - cFilename := C.CString(filename) - defer free(cFilename) - - C.pactffi_with_multipart_file(i.handle, C.int(part), cHeader, cFilename, cPartName) + pactffi_with_multipart_file(i.handle, int32(part), contentType, filename, mimePartName) return i } // Set the expected HTTTP response status func (i *Interaction) WithStatus(status int) *Interaction { - C.pactffi_response_status(i.handle, C.ushort(status)) + pactffi_response_status(i.handle, uint16(status)) return i } -type stringLike interface { - String() string -} +// type stringLike interface { +// String() string +// } func stringFromInterface(obj interface{}) string { switch t := obj.(type) { @@ -708,17 +615,14 @@ func quotedString(s string) string { // } func logToStdout(level logLevel) error { - res := C.pactffi_log_to_stdout(C.int(level)) + res := pactffi_log_to_stdout(int32(level)) log.Println("[DEBUG] log_to_stdout res", res) return logResultToError(int(res)) } func logToFile(file string, level logLevel) error { - cFile := C.CString(file) - defer free(cFile) - - res := C.pactffi_log_to_file(cFile, C.int(level)) + res := pactffi_log_to_file(file, int32(level)) log.Println("[DEBUG] log_to_file res", res) return logResultToError(int(res)) diff --git a/internal/native/verifier.go b/internal/native/verifier.go index 3f03df269..ccc155777 100644 --- a/internal/native/verifier.go +++ b/internal/native/verifier.go @@ -1,27 +1,19 @@ package native -/* -#include "pact.h" -*/ -import "C" - import ( "fmt" "log" + "strings" - "unsafe" ) type Verifier struct { - handle *C.VerifierHandle + handle uintptr } func (v *Verifier) Verify(args []string) error { log.Println("[DEBUG] executing verifier FFI with args", args) - cargs := C.CString(strings.Join(args, "\n")) - defer free(cargs) - result := C.pactffi_verify(cargs) - + result := pactffi_verify(strings.Join(args, "\n")) /// | Error | Description | /// |-------|-------------| /// | 1 | The verification process failed, see output for errors | @@ -41,10 +33,10 @@ func (v *Verifier) Verify(args []string) error { } } -// Version returns the current semver FFI interface version -func (v *Verifier) Version() string { - return Version() -} +// // Version returns the current semver FFI interface version +// func (v *Verifier) Version() string { +// return Version() +// } var ( // ErrVerifierPanic indicates a panic ocurred when invoking the verifier. @@ -60,12 +52,7 @@ var ( ) func NewVerifier(name string, version string) *Verifier { - cName := C.CString(name) - cVersion := C.CString(version) - defer free(cName) - defer free(cVersion) - - h := C.pactffi_verifier_new_for_application(cName, cVersion) + h := pactffi_verifier_new_for_application(name, version) return &Verifier{ handle: h, @@ -73,130 +60,63 @@ func NewVerifier(name string, version string) *Verifier { } func (v *Verifier) Shutdown() { - C.pactffi_verifier_shutdown(v.handle) + pactffi_verifier_shutdown(v.handle) } func (v *Verifier) SetProviderInfo(name string, scheme string, host string, port uint16, path string) { - cName := C.CString(name) - defer free(cName) - cScheme := C.CString(scheme) - defer free(cScheme) - cHost := C.CString(host) - defer free(cHost) - cPort := C.ushort(port) - cPath := C.CString(path) - defer free(cPath) - - C.pactffi_verifier_set_provider_info(v.handle, cName, cScheme, cHost, cPort, cPath) + pactffi_verifier_set_provider_info(v.handle, name, scheme, host, port, path) } func (v *Verifier) AddTransport(protocol string, port uint16, path string, scheme string) { log.Println("[DEBUG] Adding transport with protocol:", protocol, "port:", port, "path:", path, "scheme:", scheme) - cProtocol := C.CString(protocol) - defer free(cProtocol) - cPort := C.ushort(port) - cPath := C.CString(path) - defer free(cPath) - cScheme := C.CString(scheme) - defer free(cScheme) - C.pactffi_verifier_add_provider_transport(v.handle, cProtocol, cPort, cPath, cScheme) + pactffi_verifier_add_provider_transport(v.handle, protocol, port, path, scheme) } func (v *Verifier) SetFilterInfo(description string, state string, noState bool) { - cFilterDescription := C.CString(description) - defer free(cFilterDescription) - cFilterState := C.CString(state) - defer free(cFilterState) - - C.pactffi_verifier_set_filter_info(v.handle, cFilterDescription, cFilterState, boolToCUchar(noState)) + pactffi_verifier_set_filter_info(v.handle, description, state, boolToCInt(noState)) } func (v *Verifier) SetProviderState(url string, teardown bool, body bool) { - cURL := C.CString(url) - defer free(cURL) - - C.pactffi_verifier_set_provider_state(v.handle, cURL, boolToCUchar(teardown), boolToCUchar(body)) + pactffi_verifier_set_provider_state(v.handle, url, boolToCInt(teardown), boolToCInt(body)) } func (v *Verifier) SetVerificationOptions(disableSSLVerification bool, requestTimeout int64) { // TODO: this returns an int and therefore can error. We should have all of these functions return values?? - C.pactffi_verifier_set_verification_options(v.handle, boolToCUchar(disableSSLVerification), C.ulong(requestTimeout)) + pactffi_verifier_set_verification_options(v.handle, boolToCInt(disableSSLVerification), uint64(requestTimeout)) } func (v *Verifier) SetConsumerFilters(consumers []string) { - // TODO: check if this actually works! - C.pactffi_verifier_set_consumer_filters(v.handle, stringArrayToCStringArray(consumers), C.ushort(len(consumers))) + pactffi_verifier_set_consumer_filters(v.handle, stringArrayToCByteArray(consumers), uint16(len(consumers))) } func (v *Verifier) AddCustomHeader(name string, value string) { - cHeaderName := C.CString(name) - defer free(cHeaderName) - cHeaderValue := C.CString(value) - defer free(cHeaderValue) - - C.pactffi_verifier_add_custom_header(v.handle, cHeaderName, cHeaderValue) + pactffi_verifier_add_custom_header(v.handle, name, value) } func (v *Verifier) AddFileSource(file string) { - cFile := C.CString(file) - defer free(cFile) - - C.pactffi_verifier_add_file_source(v.handle, cFile) + pactffi_verifier_add_file_source(v.handle, file) } func (v *Verifier) AddDirectorySource(directory string) { - cDirectory := C.CString(directory) - defer free(cDirectory) - - C.pactffi_verifier_add_directory_source(v.handle, cDirectory) + pactffi_verifier_add_directory_source(v.handle, directory) } func (v *Verifier) AddURLSource(url string, username string, password string, token string) { - cUrl := C.CString(url) - defer free(cUrl) - cUsername := C.CString(username) - defer free(cUsername) - cPassword := C.CString(password) - defer free(cPassword) - cToken := C.CString(token) - defer free(cToken) - - C.pactffi_verifier_url_source(v.handle, cUrl, cUsername, cPassword, cToken) + pactffi_verifier_url_source(v.handle, url, username, password, token) } func (v *Verifier) BrokerSourceWithSelectors(url string, username string, password string, token string, enablePending bool, includeWipPactsSince string, providerTags []string, providerBranch string, selectors []string, consumerVersionTags []string) { - cUrl := C.CString(url) - defer free(cUrl) - cUsername := C.CString(username) - defer free(cUsername) - cPassword := C.CString(password) - defer free(cPassword) - cToken := C.CString(token) - defer free(cToken) - cIncludeWipPactsSince := C.CString(includeWipPactsSince) - defer free(cIncludeWipPactsSince) - cProviderBranch := C.CString(providerBranch) - defer free(cProviderBranch) - - C.pactffi_verifier_broker_source_with_selectors(v.handle, cUrl, cUsername, cPassword, cToken, boolToCUchar(enablePending), cIncludeWipPactsSince, stringArrayToCStringArray(providerTags), C.ushort(len(providerTags)), cProviderBranch, stringArrayToCStringArray(selectors), C.ushort(len(selectors)), stringArrayToCStringArray(consumerVersionTags), C.ushort(len(consumerVersionTags))) + pactffi_verifier_broker_source_with_selectors(v.handle, url, username, password, token, boolToCInt(enablePending), includeWipPactsSince, stringArrayToCByteArray(providerTags), uint16(len(providerTags)), providerBranch, stringArrayToCByteArray(selectors), uint16(len(selectors)), stringArrayToCByteArray(consumerVersionTags), uint16(len(consumerVersionTags))) } func (v *Verifier) SetPublishOptions(providerVersion string, buildUrl string, providerTags []string, providerBranch string) { - cProviderVersion := C.CString(providerVersion) - defer free(cProviderVersion) - cBuildUrl := C.CString(buildUrl) - defer free(cBuildUrl) - cProviderBranch := C.CString(providerBranch) - defer free(cProviderBranch) - - C.pactffi_verifier_set_publish_options(v.handle, cProviderVersion, cBuildUrl, stringArrayToCStringArray(providerTags), C.ushort(len(providerTags)), cProviderBranch) + pactffi_verifier_set_publish_options(v.handle, providerVersion, buildUrl, stringArrayToCByteArray(providerTags), uint16(len(providerTags)), providerBranch) } func (v *Verifier) Execute() error { // TODO: Validate - result := C.pactffi_verifier_execute(v.handle) - + result := pactffi_verifier_execute(v.handle) /// | Error | Description | /// |-------|-------------| /// | 1 | The verification process failed, see output for errors | @@ -213,30 +133,30 @@ func (v *Verifier) Execute() error { } func (v *Verifier) SetNoPactsIsError(isError bool) { - C.pactffi_verifier_set_no_pacts_is_error(v.handle, boolToCUchar(isError)) + pactffi_verifier_set_no_pacts_is_error(v.handle, boolToCInt(isError)) } func (v *Verifier) SetColoredOutput(isColoredOutput bool) { - C.pactffi_verifier_set_coloured_output(v.handle, boolToCUchar(isColoredOutput)) + pactffi_verifier_set_coloured_output(v.handle, boolToCInt(isColoredOutput)) } -func stringArrayToCStringArray(inputs []string) **C.char { +func stringArrayToCByteArray(inputs []string) []*byte { if len(inputs) == 0 { return nil } - output := make([]*C.char, len(inputs)) + output := make([]*byte, len(inputs)) for i, consumer := range inputs { - output[i] = C.CString(consumer) + output[i] = CString(consumer) } - return (**C.char)(unsafe.Pointer(&output[0])) + return ([]*byte)(output) } -func boolToCUchar(val bool) C.uchar { +func boolToCInt(val bool) uint8 { if val { - return C.uchar(1) + return uint8(1) } - return C.uchar(0) + return uint8(0) }