199 lines
3.5 KiB
Go
199 lines
3.5 KiB
Go
|
package caller
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"os"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
//
|
||
|
// Testing targets
|
||
|
//
|
||
|
|
||
|
type testMessage struct {
|
||
|
Body string `json:"body"`
|
||
|
}
|
||
|
|
||
|
const testPayload = `{"body":"Success!"}`
|
||
|
|
||
|
func testFun(m testMessage) {
|
||
|
fmt.Print(m.Body)
|
||
|
}
|
||
|
|
||
|
func testFunSilent(_ testMessage) {}
|
||
|
|
||
|
//
|
||
|
// Tests
|
||
|
//
|
||
|
|
||
|
func TestNewCallerSuccess(t *testing.T) {
|
||
|
c, err := New(testFun)
|
||
|
if err != nil {
|
||
|
t.Errorf("Expected no error, got: %v", err)
|
||
|
}
|
||
|
if c == nil {
|
||
|
t.Error("Expected an instance of Caller, got nil")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestNewCallerWithNonFunc(t *testing.T) {
|
||
|
c, err := New(1)
|
||
|
if err != ErrInvalidFunctionType {
|
||
|
t.Errorf("Expected ErrInvalidFunctionType, got: %v", err)
|
||
|
}
|
||
|
if c != nil {
|
||
|
t.Error("Expected nil, got an instance of Caller")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestNewCallerWithFuncMultipleArgs(t *testing.T) {
|
||
|
fun := func(a, b int) {}
|
||
|
c, err := New(fun)
|
||
|
if err != ErrInvalidFunctionInArguments {
|
||
|
t.Errorf("Expected ErrInvalidFunctionInArguments, got: %v", err)
|
||
|
}
|
||
|
if c != nil {
|
||
|
t.Error("Expected nil, got an instance of Caller")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestNewCallerWithFuncReturnValue(t *testing.T) {
|
||
|
fun := func(a int) int { return 0 }
|
||
|
c, err := New(fun)
|
||
|
if err != ErrInvalidFunctionOutArguments {
|
||
|
t.Errorf("Expected ErrInvalidFunctionOutArguments, got: %v", err)
|
||
|
}
|
||
|
if c != nil {
|
||
|
t.Error("Expected nil, got an instance of Caller")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestCallSuccess(t *testing.T) {
|
||
|
c, err := New(testFun)
|
||
|
if err != nil {
|
||
|
t.Fatal(err.Error())
|
||
|
}
|
||
|
|
||
|
out := captureStdoutAround(func() {
|
||
|
if err := c.Call([]byte(testPayload)); err != nil {
|
||
|
t.Fatal(err.Error())
|
||
|
}
|
||
|
})
|
||
|
|
||
|
if string(out) != "Success!" {
|
||
|
t.Errorf("Expected output to be %q, got %q", "Success!", out)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestCallFalure(t *testing.T) {
|
||
|
c, _ := New(testFunSilent)
|
||
|
|
||
|
err := c.Call([]byte("{"))
|
||
|
if err == nil {
|
||
|
t.Error("Expected unmarshalling error, got nil")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestUnmarshalSuccess(t *testing.T) {
|
||
|
c, _ := New(testFunSilent)
|
||
|
|
||
|
_, err := c.unmarshal([]byte(testPayload))
|
||
|
if err != nil {
|
||
|
t.Errorf("Expected no error, got: %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestUnmarshalFailure(t *testing.T) {
|
||
|
c, _ := New(testFunSilent)
|
||
|
|
||
|
_, err := c.unmarshal([]byte("{"))
|
||
|
if err == nil {
|
||
|
t.Error("Expected unmarshalling error, got nil")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func captureStdoutAround(f func()) []byte {
|
||
|
origStdout := os.Stdout
|
||
|
r, w, _ := os.Pipe()
|
||
|
os.Stdout = w
|
||
|
|
||
|
f()
|
||
|
|
||
|
w.Close()
|
||
|
out, _ := ioutil.ReadAll(r)
|
||
|
r.Close()
|
||
|
os.Stdout = origStdout
|
||
|
|
||
|
return out
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Benchmarks
|
||
|
//
|
||
|
|
||
|
func BenchmarkCaller(b *testing.B) {
|
||
|
c, _ := New(testFunSilent)
|
||
|
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
c.Call([]byte(testPayload))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkNoCaller(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
var msg testMessage
|
||
|
json.Unmarshal([]byte(testPayload), &msg)
|
||
|
testFunSilent(msg)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkDynamicNew(b *testing.B) {
|
||
|
c, _ := New(testFunSilent)
|
||
|
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
_ = c.newValue()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkStaticNew(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
_ = testMessage{}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkDynamicCall(b *testing.B) {
|
||
|
c, _ := New(testFunSilent)
|
||
|
val, _ := c.unmarshal([]byte(testPayload))
|
||
|
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
c.makeDynamicCall(val)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkStaticCall(b *testing.B) {
|
||
|
var msg testMessage
|
||
|
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
testFunSilent(msg)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkUnmarshalIntoInterface(b *testing.B) {
|
||
|
c, _ := New(testFunSilent)
|
||
|
val := c.newValue()
|
||
|
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
json.Unmarshal([]byte(testPayload), val.Interface())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkUnmarshalIntoTypedValue(b *testing.B) {
|
||
|
var msg testMessage
|
||
|
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
json.Unmarshal([]byte(testPayload), &msg)
|
||
|
}
|
||
|
}
|