Skip to content

Commit

Permalink
golang: get message tests working with purego/cgo
Browse files Browse the repository at this point in the history
  • Loading branch information
YOU54F committed Sep 4, 2024
1 parent 69f0ec6 commit c974fd7
Show file tree
Hide file tree
Showing 5 changed files with 247 additions and 4 deletions.
4 changes: 2 additions & 2 deletions go/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
SKIP_SIGNAL_HANDLERS?=false
TEST_COUNT?=50
TEST_COUNT?=1
RACE=-race
CGO_ENABLED=1
CGO_ENABLED?=1
ifeq ($(CGO_ENABLED),0)
SKIP_RACE=true
endif
Expand Down
125 changes: 125 additions & 0 deletions go/native/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import "C"
import (
"fmt"
"os"
"unsafe"
)

func plugin_provider() int {
Expand All @@ -36,3 +37,127 @@ func plugin_provider() int {
}
return int(result)
}

type MessagePact struct {
handle C.PactHandle
}

type messageType int

const (
MESSAGE_TYPE_ASYNC messageType = iota
MESSAGE_TYPE_SYNC
)

type Message struct {
handle C.InteractionHandle
messageType messageType
pact *MessagePact
index int
server *MessageServer
}

// MessageServer is the public interface for managing the message based interface
type MessageServer struct {
messagePact *MessagePact
messages []*Message
}

type interactionPart int

const (
INTERACTION_PART_REQUEST interactionPart = iota
INTERACTION_PART_RESPONSE
)


func free(str *C.char) {
C.free(unsafe.Pointer(str))
}

func message_consumer_test() {
C.pactffi_log_to_stdout(5)
var consumer = "foo"
var provider = "bar"
var description = "a desc"
var state = "test"
var expects = "expects"
cConsumer := C.CString(consumer)
cProvider := C.CString(provider)
defer free(cConsumer)
defer free(cProvider)

var m = &MessageServer{messagePact: &MessagePact{handle: C.pactffi_new_message_pact(cConsumer, cProvider)}}

cDescription := C.CString(description)
defer free(cDescription)

interaction := &Message{
handle: C.pactffi_new_message_interaction(m.messagePact.handle, cDescription),
messageType: MESSAGE_TYPE_ASYNC,
pact: m.messagePact,
index: len(m.messages),
server: m,
}
m.messages = append(m.messages, interaction)

cState := C.CString(state)
defer free(cState)

C.pactffi_given(interaction.handle, cState)

cExpects := C.CString(expects)
defer free(cExpects)

C.pactffi_message_expects_to_receive(interaction.handle, cExpects)

var contentType = "text/plain"
var part = INTERACTION_PART_REQUEST
var body = []byte("some string")
cHeader := C.CString(contentType)
defer free(cHeader)


res := C.pactffi_with_body(interaction.handle, uint32(part), cHeader, (*C.char)(unsafe.Pointer(&body[0])))
print(bool(res))
iter := C.pactffi_pact_handle_get_message_iter(m.messagePact.handle)
if iter == nil {
print("unable to get a message iterator")
}
print("[DEBUG] pactffi_pact_handle_get_message_iter - len", len(m.messages))
for i := 0; i < len(m.messages); i++ {
print("[DEBUG] pactffi_pact_handle_get_message_iter - index", i)
message := C.pactffi_pact_message_iter_next(iter)
print("[DEBUG] pactffi_pact_message_iter_next - message", message)

if i == interaction.index {
print("[DEBUG] pactffi_pact_message_iter_next - index match", message)

if message == nil {
print("retrieved a null message pointer")
return
}

len := C.pactffi_message_get_contents_length(message)
print("[DEBUG] pactffi_message_get_contents_length - len", len)
if len == 0 {
// You can have empty bodies
print("[DEBUG] message body is empty")
return
}
data := C.pactffi_message_get_contents_bin(message)
print("[DEBUG] pactffi_message_get_contents_bin - data", data)
if data == nil {
// You can have empty bodies
print("[DEBUG] message binary contents are empty")
return
}
ptr := unsafe.Pointer(data)
bytes := C.GoBytes(ptr, C.int(len))

print("got bytes")
print(string(bytes))
return
}
}
}
116 changes: 116 additions & 0 deletions go/native/lib_pure.go
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,19 @@ func CString(name string) *byte {
return &b[0]
}

func GoString(ptr uintptr, length int) string {
if unsafe.Pointer(ptr) == nil || length == 0 {
return ""
}
// 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 string(b)
}


func plugin_provider() int {
verifier := pactffi_verifier_new()
pactffi_verifier_set_provider_info(verifier, "p1", "http", "localhost", 8000, "/")
Expand All @@ -599,3 +612,106 @@ func plugin_provider() int {
}
return int(result)
}

type MessagePact struct {
handle uintptr
}

type messageType int

const (
MESSAGE_TYPE_ASYNC messageType = iota
MESSAGE_TYPE_SYNC
)

type Message struct {
handle uintptr
messageType messageType
pact *MessagePact
index int
server *MessageServer
}

// MessageServer is the public interface for managing the message based interface
type MessageServer struct {
messagePact *MessagePact
messages []*Message
}

type interactionPart int

const (
INTERACTION_PART_REQUEST interactionPart = iota
INTERACTION_PART_RESPONSE
)


func message_consumer_test() {
pactffi_log_to_stdout(5)
var consumer = "foo"
var provider = "bar"
var description = "a desc"
var state = "test"
var expects = "expects"
var m = &MessageServer{messagePact: &MessagePact{handle: pactffi_new_message_pact(consumer, provider)}}

interaction := &Message{
handle: pactffi_new_message_interaction(m.messagePact.handle, description),
messageType: MESSAGE_TYPE_ASYNC,
pact: m.messagePact,
index: len(m.messages),
server: m,
}
m.messages = append(m.messages, interaction)

pactffi_given(interaction.handle, state)

pactffi_message_expects_to_receive(interaction.handle, expects)

var contentType = "text/plain"
var part = INTERACTION_PART_REQUEST
// var body = []byte("some string")
// var body = CString("some string")


res := pactffi_with_body(interaction.handle, int32(part), contentType, "some string")
print(bool(res))
iter := pactffi_pact_handle_get_message_iter(m.messagePact.handle)
if unsafe.Pointer(iter) == nil {
print("unable to get a message iterator")
}
print("[DEBUG] pactffi_pact_handle_get_message_iter - len", len(m.messages))
for i := 0; i < len(m.messages); i++ {
print("[DEBUG] pactffi_pact_handle_get_message_iter - index", i)
message := pactffi_pact_message_iter_next(iter)
print("[DEBUG] pactffi_pact_message_iter_next - message", message)

if i == interaction.index {
print("[DEBUG] pactffi_pact_message_iter_next - index match", message)

if unsafe.Pointer(message) == nil {
print("retrieved a null message pointer")
return
}

len := pactffi_message_get_contents_length(message)
print("[DEBUG] pactffi_message_get_contents_length - len", len)
if len == 0 {
// You can have empty bodies
print("[DEBUG] message body is empty")
return
}
data := pactffi_message_get_contents_bin(message)
print("[DEBUG] pactffi_message_get_contents_bin - data", data)
if unsafe.Pointer(data) == nil {
// You can have empty bodies
print("[DEBUG] message binary contents are empty")
return
}
bytes := GoString(data, int(len))
print("got bytes")
print(bytes)
return
}
}
}
3 changes: 2 additions & 1 deletion go/native/main.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package main

func main() {
plugin_provider()
// plugin_provider()
message_consumer_test()
}
3 changes: 2 additions & 1 deletion go/native/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ import (
)

func TestPluginProvider1(t *testing.T) {
plugin_provider()
// plugin_provider()
message_consumer_test()
}

0 comments on commit c974fd7

Please sign in to comment.