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 }