Skip to content

Commit

Permalink
feat: add experimental log packages to ffi interface
Browse files Browse the repository at this point in the history
  • Loading branch information
mefellows committed May 30, 2021
1 parent c7b7c08 commit de379ad
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 21 deletions.
95 changes: 92 additions & 3 deletions v3/internal/native/mockserver/mock_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ void response_status(InteractionHandle interaction, int status);
int write_pact_file(int mock_server_port, const char *directory);
void with_pact_metadata(PactHandle pact, const char *namespace, const char *name, const char *value);
// Additional global logging functions
int log_to_buffer(int level);
int log_to_stdout(int level);
int log_to_file(const char *file_name, int level_filter);
char* fetch_memory_buffer();
*/
import "C"

Expand Down Expand Up @@ -187,6 +194,17 @@ const (
SPECIFICATION_VERSION_V4
)

type logLevel int

const (
LOG_LEVEL_OFF logLevel = iota
LOG_LEVEL_ERROR
LOG_LEVEL_WARN
LOG_LEVEL_INFO
LOG_LEVEL_DEBUG
LOG_LEVEL_TRACE
)

// Pact is a Go representation of the PactHandle struct
type Pact struct {
handle C.PactHandle
Expand All @@ -207,10 +225,15 @@ func Version() string {
// Init initialises the library
func Init() {
log.Println("[DEBUG] initialising rust mock server interface")
logLevel := C.CString("LOG_LEVEL")
defer free(logLevel)
l := C.CString("LOG_LEVEL")
defer free(l)

C.init(l)

C.init(logLevel)
// Alternative log destinations
// NOTE: only one can be applied
// logToBuffer(LOG_LEVEL_INFO)
// logToFile("/tmp/pact.log", LOG_LEVEL_TRACE)
}

// MockServer is the public interface for managing the HTTP mock server
Expand Down Expand Up @@ -649,6 +672,61 @@ func stringFromInterface(obj interface{}) string {
}
}

// Experimental logging options
func logToBuffer(level logLevel) error {
res := C.log_to_buffer(C.int(level))
log.Println("[DEBUG] log_to_buffer res", res)

return logResultToError(int(res))
}

func logToStdout(level logLevel) error {
res := C.log_to_stdout(C.int(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.log_to_file(cFile, C.int(level))
log.Println("[DEBUG] log_to_file res", res)

return logResultToError(int(res))
}

func getLogBuffer() string {
buf := C.fetch_memory_buffer()
defer free(buf)

return C.GoString(buf)
}

func logResultToError(res int) error {
switch res {
case 0:
return nil
case -1:
return ErrCantSetLogger
case -2:
return ErrNoLogger
case -3:
return ErrSpecifierNotUtf8
case -4:
return ErrUnknownSinkType
case -5:
return ErrMissingFilePath
case -6:
return ErrCantOpenSinkToFile
case -7:
return ErrCantConstructSink
default:
return fmt.Errorf("an unknown error ocurred when writing to pact file")
}
}

// Errors
var (
// ErrHandleNotFound indicates the underlying handle was not found, and a logic error in the framework
Expand Down Expand Up @@ -682,3 +760,14 @@ var (
// ErrNoInteractions indicates no Interactions have been registered to a mock server, and cannot be started/stopped until at least one is added
ErrNoInteractions = fmt.Errorf("no interactions have been registered for the mock server")
)

// Log Errors
var (
ErrCantSetLogger = fmt.Errorf("can't set logger (applying the logger failed, perhaps because one is applied already).")
ErrNoLogger = fmt.Errorf("no logger has been initialized (call `logger_init` before any other log function).")
ErrSpecifierNotUtf8 = fmt.Errorf("The sink specifier was not UTF-8 encoded.")
ErrUnknownSinkType = fmt.Errorf(`the sink type specified is not a known type (known types: "buffer", "stdout", "stderr", or "file /some/path").`)
ErrMissingFilePath = fmt.Errorf("no file path was specified in a file-type sink specification.")
ErrCantOpenSinkToFile = fmt.Errorf("opening a sink to the specified file path failed (check permissions).")
ErrCantConstructSink = fmt.Errorf("can't construct the log sink")
)
28 changes: 10 additions & 18 deletions v3/internal/native/mockserver/mock_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,11 @@ func TestMockServer_WritePactfile(t *testing.T) {
func TestMockServer_GetTLSConfig(t *testing.T) {
config := GetTLSConfig()

fmt.Println("tls config", config)
t.Log("tls config", config)
}

func TestVersion(t *testing.T) {
fmt.Println("version: ", Version())
t.Log("version: ", Version())
}

func TestHandleBasedHTTPTests(t *testing.T) {
Expand All @@ -128,25 +128,19 @@ func TestHandleBasedHTTPTests(t *testing.T) {

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

fmt.Println("pact struct:", m)

i := m.NewInteraction("some interaction")
fmt.Println("pact interaction:", i)

i.UponReceiving("some interaction").
Given("some state").
WithRequest("GET", "/products").
// withRequestHeader("x-special-header", 0, "header")
// withQuery("someParam", 0, "someValue")
WithJSONResponseBody(`{
"name": {
"pact:matcher:type": "type",
"value": "some name"
},
"age": 23,
"alive": true
}`).
// withResponseHeader(i, "x-special-header", 0, "header")
"name": {
"pact:matcher:type": "type",
"value": "some name"
},
"age": 23,
"alive": true
}`).
WithStatus(200)

// // Start the mock service
Expand All @@ -155,7 +149,7 @@ func TestHandleBasedHTTPTests(t *testing.T) {
assert.NoError(t, err)
defer m.CleanupMockServer(port)

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

mismatches := m.MockServerMismatchedRequests(port)
Expand All @@ -165,8 +159,6 @@ func TestHandleBasedHTTPTests(t *testing.T) {

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

fmt.Println(r)
}

var pactSimple = `{
Expand Down

0 comments on commit de379ad

Please sign in to comment.