github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/api_mock.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package libkb
     5  
     6  import (
     7  	"errors"
     8  	"io"
     9  	"net/http"
    10  
    11  	"golang.org/x/net/context"
    12  )
    13  
    14  type NullMockAPI struct{}
    15  
    16  var _ API = (*NullMockAPI)(nil)
    17  
    18  func (n *NullMockAPI) Get(MetaContext, APIArg) (*APIRes, error)                       { return nil, nil }
    19  func (n *NullMockAPI) GetDecode(MetaContext, APIArg, APIResponseWrapper) error        { return nil }
    20  func (n *NullMockAPI) GetDecodeCtx(context.Context, APIArg, APIResponseWrapper) error { return nil }
    21  func (n *NullMockAPI) GetResp(MetaContext, APIArg) (*http.Response, func(), error) {
    22  	return nil, noopFinisher, nil
    23  }
    24  func (n *NullMockAPI) Post(MetaContext, APIArg) (*APIRes, error)                       { return nil, nil }
    25  func (n *NullMockAPI) PostJSON(MetaContext, APIArg) (*APIRes, error)                   { return nil, nil }
    26  func (n *NullMockAPI) PostDecode(MetaContext, APIArg, APIResponseWrapper) error        { return nil }
    27  func (n *NullMockAPI) PostDecodeCtx(context.Context, APIArg, APIResponseWrapper) error { return nil }
    28  func (n *NullMockAPI) PostRaw(MetaContext, APIArg, string, io.Reader) (*APIRes, error) {
    29  	return nil, nil
    30  }
    31  func (n *NullMockAPI) Delete(MetaContext, APIArg) (*APIRes, error) { return nil, nil }
    32  
    33  type APIMethodType int
    34  
    35  const (
    36  	MethodGet APIMethodType = iota
    37  	MethodGetDecode
    38  	MethodGetDecodeCtx
    39  	MethodGetResp
    40  	MethodPost
    41  	MethodPostJSON
    42  	MethodPostDecode
    43  	MethodPostDecodeCtx
    44  	MethodPostRaw
    45  	MethodDelete
    46  )
    47  
    48  type APIRecord struct {
    49  	Arg    APIArg
    50  	Method APIMethodType
    51  	// various inputs and outputs of the API interface methods.
    52  	Res         *APIRes
    53  	RespWrapper APIResponseWrapper
    54  	HTTPResp    *http.Response
    55  	Func        func()
    56  	S           string
    57  	R           io.Reader
    58  	Err         error
    59  }
    60  
    61  // FilterAPIRecords returns only the records on which the filter function outputs true
    62  func FilterAPIRecords(recs []APIRecord, filter func(*APIRecord) bool) (filtered []APIRecord) {
    63  	for _, rec := range recs {
    64  		if filter(&rec) {
    65  			filtered = append(filtered, rec)
    66  		}
    67  	}
    68  	return filtered
    69  }
    70  
    71  // APIArgRecorder forwards all its calls to the underlying API, but records all
    72  // the inputs and outputs to be used in tests.
    73  type APIArgRecorder struct {
    74  	API
    75  	Records []APIRecord
    76  }
    77  
    78  var _ API = (*APIArgRecorder)(nil)
    79  
    80  func NewAPIArgRecorderWithNullAPI() *APIArgRecorder {
    81  	return NewAPIArgRecorder(&NullMockAPI{})
    82  }
    83  
    84  func NewAPIArgRecorder(inner API) *APIArgRecorder {
    85  	return &APIArgRecorder{API: inner}
    86  }
    87  
    88  func (a *APIArgRecorder) Reset() {
    89  	a.Records = nil
    90  }
    91  
    92  func (a *APIArgRecorder) NumCalls() int {
    93  	return len(a.Records)
    94  }
    95  
    96  func (a *APIArgRecorder) GetFilteredRecordsAndReset(filter func(*APIRecord) bool) (filtered []APIRecord) {
    97  	filtered = FilterAPIRecords(a.Records, filter)
    98  	a.Reset()
    99  	return filtered
   100  }
   101  
   102  func (a *APIArgRecorder) Get(mctx MetaContext, arg APIArg) (*APIRes, error) {
   103  	res, err := a.API.Get(mctx, arg)
   104  	a.Records = append(a.Records, APIRecord{Arg: arg, Method: MethodGet, Res: res, Err: err})
   105  	return res, err
   106  }
   107  func (a *APIArgRecorder) GetDecode(mctx MetaContext, arg APIArg, arw APIResponseWrapper) error {
   108  	err := a.API.GetDecode(mctx, arg, arw)
   109  	a.Records = append(a.Records, APIRecord{Arg: arg, Method: MethodGetDecode, RespWrapper: arw, Err: err})
   110  	return err
   111  }
   112  func (a *APIArgRecorder) GetDecodeCtx(ctx context.Context, arg APIArg, arw APIResponseWrapper) error {
   113  	err := a.API.GetDecodeCtx(ctx, arg, arw)
   114  	a.Records = append(a.Records, APIRecord{Arg: arg, Method: MethodGetDecodeCtx, RespWrapper: arw, Err: err})
   115  	return err
   116  }
   117  func (a *APIArgRecorder) GetResp(mctx MetaContext, arg APIArg) (*http.Response, func(), error) {
   118  	httpR, f, err := a.API.GetResp(mctx, arg)
   119  	a.Records = append(a.Records, APIRecord{Arg: arg, Method: MethodGetResp, HTTPResp: httpR, Func: f, Err: err})
   120  	return httpR, f, err
   121  }
   122  func (a *APIArgRecorder) Post(mctx MetaContext, arg APIArg) (*APIRes, error) {
   123  	res, err := a.API.Post(mctx, arg)
   124  	a.Records = append(a.Records, APIRecord{Arg: arg, Method: MethodPost, Res: res, Err: err})
   125  	return res, err
   126  }
   127  func (a *APIArgRecorder) PostJSON(mctx MetaContext, arg APIArg) (*APIRes, error) {
   128  	res, err := a.API.PostJSON(mctx, arg)
   129  	a.Records = append(a.Records, APIRecord{Arg: arg, Method: MethodPostJSON, Res: res, Err: err})
   130  	return res, err
   131  }
   132  func (a *APIArgRecorder) PostDecode(mctx MetaContext, arg APIArg, arw APIResponseWrapper) error {
   133  	err := a.API.PostDecode(mctx, arg, arw)
   134  	a.Records = append(a.Records, APIRecord{Arg: arg, Method: MethodPostDecode, RespWrapper: arw, Err: err})
   135  	return err
   136  }
   137  func (a *APIArgRecorder) PostDecodeCtx(ctx context.Context, arg APIArg, arw APIResponseWrapper) error {
   138  	err := a.API.PostDecodeCtx(ctx, arg, arw)
   139  	a.Records = append(a.Records, APIRecord{Arg: arg, Method: MethodPostDecodeCtx, RespWrapper: arw, Err: err})
   140  	return err
   141  }
   142  func (a *APIArgRecorder) PostRaw(mctx MetaContext, arg APIArg, s string, r io.Reader) (*APIRes, error) {
   143  	res, err := a.API.PostRaw(mctx, arg, s, r)
   144  	a.Records = append(a.Records, APIRecord{Arg: arg, Method: MethodPostRaw, S: s, R: r, Res: res, Err: err})
   145  	return res, err
   146  }
   147  func (a *APIArgRecorder) Delete(mctx MetaContext, arg APIArg) (*APIRes, error) {
   148  	res, err := a.API.Delete(mctx, arg)
   149  	a.Records = append(a.Records, APIRecord{Arg: arg, Method: MethodDelete, Res: res, Err: err})
   150  	return res, err
   151  }
   152  
   153  // APIRouter forwards each API call to one of the underlying API implementations
   154  // depending on an internal filter function passed to its constructor. Be
   155  // careful that the filter always returns a value in bound for the api array.
   156  // This is meant to be used in tests to mock some but not all api calls.
   157  type APIRouter struct {
   158  	APIs   []API
   159  	Filter func(arg APIArg, method APIMethodType) int
   160  }
   161  
   162  var _ API = (*APIRouter)(nil)
   163  
   164  func NewAPIRouter(apis []API, filter func(arg APIArg, method APIMethodType) int) *APIRouter {
   165  	return &APIRouter{APIs: apis, Filter: filter}
   166  }
   167  
   168  func (a *APIRouter) Get(mctx MetaContext, arg APIArg) (*APIRes, error) {
   169  	return a.APIs[a.Filter(arg, MethodGet)].Get(mctx, arg)
   170  }
   171  func (a *APIRouter) GetDecode(mctx MetaContext, arg APIArg, arw APIResponseWrapper) error {
   172  	return a.APIs[a.Filter(arg, MethodGetDecode)].GetDecode(mctx, arg, arw)
   173  }
   174  func (a *APIRouter) GetDecodeCtx(ctx context.Context, arg APIArg, arw APIResponseWrapper) error {
   175  	return a.APIs[a.Filter(arg, MethodGetDecodeCtx)].GetDecodeCtx(ctx, arg, arw)
   176  }
   177  func (a *APIRouter) GetResp(mctx MetaContext, arg APIArg) (*http.Response, func(), error) {
   178  	return a.APIs[a.Filter(arg, MethodGetResp)].GetResp(mctx, arg)
   179  }
   180  func (a *APIRouter) Post(mctx MetaContext, arg APIArg) (*APIRes, error) {
   181  	return a.APIs[a.Filter(arg, MethodPost)].Post(mctx, arg)
   182  }
   183  func (a *APIRouter) PostJSON(mctx MetaContext, arg APIArg) (*APIRes, error) {
   184  	return a.APIs[a.Filter(arg, MethodPostJSON)].PostJSON(mctx, arg)
   185  }
   186  func (a *APIRouter) PostDecode(mctx MetaContext, arg APIArg, arw APIResponseWrapper) error {
   187  	return a.APIs[a.Filter(arg, MethodPostDecode)].PostDecode(mctx, arg, arw)
   188  }
   189  func (a *APIRouter) PostDecodeCtx(ctx context.Context, arg APIArg, arw APIResponseWrapper) error {
   190  	return a.APIs[a.Filter(arg, MethodPostDecodeCtx)].PostDecodeCtx(ctx, arg, arw)
   191  }
   192  func (a *APIRouter) PostRaw(mctx MetaContext, arg APIArg, s string, r io.Reader) (*APIRes, error) {
   193  	return a.APIs[a.Filter(arg, MethodPostRaw)].PostRaw(mctx, arg, s, r)
   194  }
   195  func (a *APIRouter) Delete(mctx MetaContext, arg APIArg) (*APIRes, error) {
   196  	return a.APIs[a.Filter(arg, MethodDelete)].Delete(mctx, arg)
   197  }
   198  
   199  type ErrorMockAPI struct{}
   200  
   201  var _ API = (*ErrorMockAPI)(nil)
   202  
   203  var errMockAPI = errors.New("ErrorMockAPI error")
   204  
   205  func (n *ErrorMockAPI) Get(MetaContext, APIArg) (*APIRes, error)                { return nil, errMockAPI }
   206  func (n *ErrorMockAPI) GetDecode(MetaContext, APIArg, APIResponseWrapper) error { return errMockAPI }
   207  func (n *ErrorMockAPI) GetDecodeCtx(context.Context, APIArg, APIResponseWrapper) error {
   208  	return errMockAPI
   209  }
   210  func (n *ErrorMockAPI) GetResp(MetaContext, APIArg) (*http.Response, func(), error) {
   211  	return nil, noopFinisher, nil
   212  }
   213  func (n *ErrorMockAPI) Post(MetaContext, APIArg) (*APIRes, error)                { return nil, errMockAPI }
   214  func (n *ErrorMockAPI) PostJSON(MetaContext, APIArg) (*APIRes, error)            { return nil, errMockAPI }
   215  func (n *ErrorMockAPI) PostDecode(MetaContext, APIArg, APIResponseWrapper) error { return errMockAPI }
   216  func (n *ErrorMockAPI) PostDecodeCtx(context.Context, APIArg, APIResponseWrapper) error {
   217  	return errMockAPI
   218  }
   219  func (n *ErrorMockAPI) PostRaw(MetaContext, APIArg, string, io.Reader) (*APIRes, error) {
   220  	return nil, errMockAPI
   221  }
   222  func (n *ErrorMockAPI) Delete(MetaContext, APIArg) (*APIRes, error) { return nil, errMockAPI }