github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/btcjson/register_test.go (about)

     1  // Copyright (c) 2014 The btcsuite developers
     2  // Copyright (c) 2016 The Dash developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package btcjson_test
     7  
     8  import (
     9  	"reflect"
    10  	"sort"
    11  	"testing"
    12  
    13  	"github.com/dashpay/godash/btcjson"
    14  )
    15  
    16  // TestUsageFlagStringer tests the stringized output for the UsageFlag type.
    17  func TestUsageFlagStringer(t *testing.T) {
    18  	t.Parallel()
    19  
    20  	tests := []struct {
    21  		in   btcjson.UsageFlag
    22  		want string
    23  	}{
    24  		{0, "0x0"},
    25  		{btcjson.UFWalletOnly, "UFWalletOnly"},
    26  		{btcjson.UFWebsocketOnly, "UFWebsocketOnly"},
    27  		{btcjson.UFNotification, "UFNotification"},
    28  		{btcjson.UFWalletOnly | btcjson.UFWebsocketOnly,
    29  			"UFWalletOnly|UFWebsocketOnly"},
    30  		{btcjson.UFWalletOnly | btcjson.UFWebsocketOnly | (1 << 31),
    31  			"UFWalletOnly|UFWebsocketOnly|0x80000000"},
    32  	}
    33  
    34  	// Detect additional usage flags that don't have the stringer added.
    35  	numUsageFlags := 0
    36  	highestUsageFlagBit := btcjson.TstHighestUsageFlagBit
    37  	for highestUsageFlagBit > 1 {
    38  		numUsageFlags++
    39  		highestUsageFlagBit >>= 1
    40  	}
    41  	if len(tests)-3 != numUsageFlags {
    42  		t.Errorf("It appears a usage flag was added without adding " +
    43  			"an associated stringer test")
    44  	}
    45  
    46  	t.Logf("Running %d tests", len(tests))
    47  	for i, test := range tests {
    48  		result := test.in.String()
    49  		if result != test.want {
    50  			t.Errorf("String #%d\n got: %s want: %s", i, result,
    51  				test.want)
    52  			continue
    53  		}
    54  	}
    55  }
    56  
    57  // TestRegisterCmdErrors ensures the RegisterCmd function returns the expected
    58  // error when provided with invalid types.
    59  func TestRegisterCmdErrors(t *testing.T) {
    60  	t.Parallel()
    61  
    62  	tests := []struct {
    63  		name    string
    64  		method  string
    65  		cmdFunc func() interface{}
    66  		flags   btcjson.UsageFlag
    67  		err     btcjson.Error
    68  	}{
    69  		{
    70  			name:   "duplicate method",
    71  			method: "getblock",
    72  			cmdFunc: func() interface{} {
    73  				return struct{}{}
    74  			},
    75  			err: btcjson.Error{ErrorCode: btcjson.ErrDuplicateMethod},
    76  		},
    77  		{
    78  			name:   "invalid usage flags",
    79  			method: "registertestcmd",
    80  			cmdFunc: func() interface{} {
    81  				return 0
    82  			},
    83  			flags: btcjson.TstHighestUsageFlagBit,
    84  			err:   btcjson.Error{ErrorCode: btcjson.ErrInvalidUsageFlags},
    85  		},
    86  		{
    87  			name:   "invalid type",
    88  			method: "registertestcmd",
    89  			cmdFunc: func() interface{} {
    90  				return 0
    91  			},
    92  			err: btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
    93  		},
    94  		{
    95  			name:   "invalid type 2",
    96  			method: "registertestcmd",
    97  			cmdFunc: func() interface{} {
    98  				return &[]string{}
    99  			},
   100  			err: btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
   101  		},
   102  		{
   103  			name:   "embedded field",
   104  			method: "registertestcmd",
   105  			cmdFunc: func() interface{} {
   106  				type test struct{ int }
   107  				return (*test)(nil)
   108  			},
   109  			err: btcjson.Error{ErrorCode: btcjson.ErrEmbeddedType},
   110  		},
   111  		{
   112  			name:   "unexported field",
   113  			method: "registertestcmd",
   114  			cmdFunc: func() interface{} {
   115  				type test struct{ a int }
   116  				return (*test)(nil)
   117  			},
   118  			err: btcjson.Error{ErrorCode: btcjson.ErrUnexportedField},
   119  		},
   120  		{
   121  			name:   "unsupported field type 1",
   122  			method: "registertestcmd",
   123  			cmdFunc: func() interface{} {
   124  				type test struct{ A **int }
   125  				return (*test)(nil)
   126  			},
   127  			err: btcjson.Error{ErrorCode: btcjson.ErrUnsupportedFieldType},
   128  		},
   129  		{
   130  			name:   "unsupported field type 2",
   131  			method: "registertestcmd",
   132  			cmdFunc: func() interface{} {
   133  				type test struct{ A chan int }
   134  				return (*test)(nil)
   135  			},
   136  			err: btcjson.Error{ErrorCode: btcjson.ErrUnsupportedFieldType},
   137  		},
   138  		{
   139  			name:   "unsupported field type 3",
   140  			method: "registertestcmd",
   141  			cmdFunc: func() interface{} {
   142  				type test struct{ A complex64 }
   143  				return (*test)(nil)
   144  			},
   145  			err: btcjson.Error{ErrorCode: btcjson.ErrUnsupportedFieldType},
   146  		},
   147  		{
   148  			name:   "unsupported field type 4",
   149  			method: "registertestcmd",
   150  			cmdFunc: func() interface{} {
   151  				type test struct{ A complex128 }
   152  				return (*test)(nil)
   153  			},
   154  			err: btcjson.Error{ErrorCode: btcjson.ErrUnsupportedFieldType},
   155  		},
   156  		{
   157  			name:   "unsupported field type 5",
   158  			method: "registertestcmd",
   159  			cmdFunc: func() interface{} {
   160  				type test struct{ A func() }
   161  				return (*test)(nil)
   162  			},
   163  			err: btcjson.Error{ErrorCode: btcjson.ErrUnsupportedFieldType},
   164  		},
   165  		{
   166  			name:   "unsupported field type 6",
   167  			method: "registertestcmd",
   168  			cmdFunc: func() interface{} {
   169  				type test struct{ A interface{} }
   170  				return (*test)(nil)
   171  			},
   172  			err: btcjson.Error{ErrorCode: btcjson.ErrUnsupportedFieldType},
   173  		},
   174  		{
   175  			name:   "required after optional",
   176  			method: "registertestcmd",
   177  			cmdFunc: func() interface{} {
   178  				type test struct {
   179  					A *int
   180  					B int
   181  				}
   182  				return (*test)(nil)
   183  			},
   184  			err: btcjson.Error{ErrorCode: btcjson.ErrNonOptionalField},
   185  		},
   186  		{
   187  			name:   "non-optional with default",
   188  			method: "registertestcmd",
   189  			cmdFunc: func() interface{} {
   190  				type test struct {
   191  					A int `jsonrpcdefault:"1"`
   192  				}
   193  				return (*test)(nil)
   194  			},
   195  			err: btcjson.Error{ErrorCode: btcjson.ErrNonOptionalDefault},
   196  		},
   197  		{
   198  			name:   "mismatched default",
   199  			method: "registertestcmd",
   200  			cmdFunc: func() interface{} {
   201  				type test struct {
   202  					A *int `jsonrpcdefault:"1.7"`
   203  				}
   204  				return (*test)(nil)
   205  			},
   206  			err: btcjson.Error{ErrorCode: btcjson.ErrMismatchedDefault},
   207  		},
   208  	}
   209  
   210  	t.Logf("Running %d tests", len(tests))
   211  	for i, test := range tests {
   212  		err := btcjson.RegisterCmd(test.method, test.cmdFunc(),
   213  			test.flags)
   214  		if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
   215  			t.Errorf("Test #%d (%s) wrong error - got %T, "+
   216  				"want %T", i, test.name, err, test.err)
   217  			continue
   218  		}
   219  		gotErrorCode := err.(btcjson.Error).ErrorCode
   220  		if gotErrorCode != test.err.ErrorCode {
   221  			t.Errorf("Test #%d (%s) mismatched error code - got "+
   222  				"%v, want %v", i, test.name, gotErrorCode,
   223  				test.err.ErrorCode)
   224  			continue
   225  		}
   226  	}
   227  }
   228  
   229  // TestMustRegisterCmdPanic ensures the MustRegisterCmd function panics when
   230  // used to register an invalid type.
   231  func TestMustRegisterCmdPanic(t *testing.T) {
   232  	t.Parallel()
   233  
   234  	// Setup a defer to catch the expected panic to ensure it actually
   235  	// paniced.
   236  	defer func() {
   237  		if err := recover(); err == nil {
   238  			t.Error("MustRegisterCmd did not panic as expected")
   239  		}
   240  	}()
   241  
   242  	// Intentionally try to register an invalid type to force a panic.
   243  	btcjson.MustRegisterCmd("panicme", 0, 0)
   244  }
   245  
   246  // TestRegisteredCmdMethods tests the RegisteredCmdMethods function ensure it
   247  // works as expected.
   248  func TestRegisteredCmdMethods(t *testing.T) {
   249  	t.Parallel()
   250  
   251  	// Ensure the registerd methods are returned.
   252  	methods := btcjson.RegisteredCmdMethods()
   253  	if len(methods) == 0 {
   254  		t.Fatal("RegisteredCmdMethods: no methods")
   255  	}
   256  
   257  	// Ensure the returned methods are sorted.
   258  	sortedMethods := make([]string, len(methods))
   259  	copy(sortedMethods, methods)
   260  	sort.Sort(sort.StringSlice(sortedMethods))
   261  	if !reflect.DeepEqual(sortedMethods, methods) {
   262  		t.Fatal("RegisteredCmdMethods: methods are not sorted")
   263  	}
   264  }