func (mc *MockRoundTripper) Expect(status int, body interface{}) *Response {
	mc.Lock()
	defer mc.Unlock()
	bodyPL, ok := body.(ResponsePayload)
	if !ok {
		bodyPL = JSON{body}
	}
	resp := &Response{Status: status, Body: bodyPL, Mock: mc}
	mc.Responses = append(mc.Responses, resp)
	return resp
}
Expect adds a new expected response, specifying status and body. The other components (headers, conditional filters)
can be further specified by chaining setter calls on the response object.
package amock
import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"reflect"
	"regexp"
	"runtime"
	"runtime/debug"
	"sync"
	"testing"
)
type MockRoundTripper struct {
	sync.Mutex
	Responses        []*Response
	potentialCallers map[string]struct{}
}
type ResponsePayload interface {
	Payload() ([]byte, error)
}
type Raw []byte
func (r Raw) Payload() ([]byte, error) {
	return []byte(r), nil
}
type JSON struct {
	Obj interface{}
}
func (j JSON) Payload() ([]byte, error) {
	return json.Marshal(j.Obj)
}
type Response struct {
	Status  int
	headers http.Header
	Body    ResponsePayload
	Cond    func(*Context) bool
	sticky  bool
	Mock    *MockRoundTripper
}
type Context struct {
	Request *http.Request
	callers map[string]struct{}
	mock    *MockRoundTripper
}
func (c *Context) Callers() map[string]struct{} {
	if c.callers == nil {
		c.callers = c.mock.callers()
	}
	return c.callers
}
func NewMock() *MockRoundTripper {
	return &MockRoundTripper{
		potentialCallers: map[string]struct{}{},
	}
}
func (r *Response) Sticky() *Response {
	r.Mock.Lock()
	defer r.Mock.Unlock()
	r.sticky = true
	return r
}
func (r *Response) Headers(h http.Header) *Response {
	r.Mock.Lock()
	defer r.Mock.Unlock()
	r.headers = h
	return r
}
func condAND(fs ...func(*Context) bool) func(*Context) bool {
	return func(c *Context) bool {
		for _, f := range fs {
			if !f(c) {
				return false
			}
		}
		return true
	}
}
func (r *Response) addCond(cond func(*Context) bool) {
	if r.Cond != nil {
		r.Cond = condAND(r.Cond, cond)
	} else {
		r.Cond = cond
	}
}
func (r *Response) OnFunc(callerFunc interface{}) *Response {
	r.Mock.Lock()
	defer r.Mock.Unlock()
	caller := getFunctionName(callerFunc)
	r.Mock.potentialCaller(caller)
	cond := func(c *Context) bool {
		callers := c.Callers()
		_, ok := callers[caller]
		return ok
	}
	r.addCond(cond)
	return r
}
func (r *Response) OnIdentifier(ident string) *Response {
	r.Mock.Lock()
	defer r.Mock.Unlock()
	ident = regexp.QuoteMeta(ident)
	matcher := regexp.MustCompile(`/[^/]+/` + ident + `(?:/.*|$)`)
	cond := func(c *Context) bool {
		return matcher.MatchString(c.Request.URL.Path)
	}
	r.addCond(cond)
	return r
}
func (r *Response) On(f func(*Context) bool) *Response {
	r.Mock.Lock()
	defer r.Mock.Unlock()
	r.addCond(f)
	return r
}
func (mc *MockRoundTripper) potentialCaller(caller string) {
	mc.potentialCallers[caller] = struct{}{}
}
func (mc *MockRoundTripper) callers() map[string]struct{} {
	ret := map[string]struct{}{}
	callers := make([]uintptr, 50)
	runtime.Callers(3, callers)
	frames := runtime.CallersFrames(callers)
	for {
		frame, more := frames.Next()
		_, ok := mc.potentialCallers[frame.Function]
		if ok {
			ret[frame.Function] = struct{}{}
		}
		if !more {
			break
		}
	}
	return ret
}