github.com/btcsuite/btcd@v0.24.0/btcjson/help_test.go (about)

     1  // Copyright (c) 2014 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package btcjson_test
     6  
     7  import (
     8  	"reflect"
     9  	"testing"
    10  
    11  	"github.com/btcsuite/btcd/btcjson"
    12  )
    13  
    14  // TestHelpReflectInternals ensures the various help functions which deal with
    15  // reflect types work as expected for various Go types.
    16  func TestHelpReflectInternals(t *testing.T) {
    17  	t.Parallel()
    18  
    19  	tests := []struct {
    20  		name        string
    21  		reflectType reflect.Type
    22  		indentLevel int
    23  		key         string
    24  		examples    []string
    25  		isComplex   bool
    26  		help        string
    27  		isInvalid   bool
    28  	}{
    29  		{
    30  			name:        "int",
    31  			reflectType: reflect.TypeOf(int(0)),
    32  			key:         "json-type-numeric",
    33  			examples:    []string{"n"},
    34  			help:        "n (json-type-numeric) fdk",
    35  		},
    36  		{
    37  			name:        "*int",
    38  			reflectType: reflect.TypeOf((*int)(nil)),
    39  			key:         "json-type-value",
    40  			examples:    []string{"n"},
    41  			help:        "n (json-type-value) fdk",
    42  			isInvalid:   true,
    43  		},
    44  		{
    45  			name:        "int8",
    46  			reflectType: reflect.TypeOf(int8(0)),
    47  			key:         "json-type-numeric",
    48  			examples:    []string{"n"},
    49  			help:        "n (json-type-numeric) fdk",
    50  		},
    51  		{
    52  			name:        "int16",
    53  			reflectType: reflect.TypeOf(int16(0)),
    54  			key:         "json-type-numeric",
    55  			examples:    []string{"n"},
    56  			help:        "n (json-type-numeric) fdk",
    57  		},
    58  		{
    59  			name:        "int32",
    60  			reflectType: reflect.TypeOf(int32(0)),
    61  			key:         "json-type-numeric",
    62  			examples:    []string{"n"},
    63  			help:        "n (json-type-numeric) fdk",
    64  		},
    65  		{
    66  			name:        "int64",
    67  			reflectType: reflect.TypeOf(int64(0)),
    68  			key:         "json-type-numeric",
    69  			examples:    []string{"n"},
    70  			help:        "n (json-type-numeric) fdk",
    71  		},
    72  		{
    73  			name:        "uint",
    74  			reflectType: reflect.TypeOf(uint(0)),
    75  			key:         "json-type-numeric",
    76  			examples:    []string{"n"},
    77  			help:        "n (json-type-numeric) fdk",
    78  		},
    79  		{
    80  			name:        "uint8",
    81  			reflectType: reflect.TypeOf(uint8(0)),
    82  			key:         "json-type-numeric",
    83  			examples:    []string{"n"},
    84  			help:        "n (json-type-numeric) fdk",
    85  		},
    86  		{
    87  			name:        "uint16",
    88  			reflectType: reflect.TypeOf(uint16(0)),
    89  			key:         "json-type-numeric",
    90  			examples:    []string{"n"},
    91  			help:        "n (json-type-numeric) fdk",
    92  		},
    93  		{
    94  			name:        "uint32",
    95  			reflectType: reflect.TypeOf(uint32(0)),
    96  			key:         "json-type-numeric",
    97  			examples:    []string{"n"},
    98  			help:        "n (json-type-numeric) fdk",
    99  		},
   100  		{
   101  			name:        "uint64",
   102  			reflectType: reflect.TypeOf(uint64(0)),
   103  			key:         "json-type-numeric",
   104  			examples:    []string{"n"},
   105  			help:        "n (json-type-numeric) fdk",
   106  		},
   107  		{
   108  			name:        "float32",
   109  			reflectType: reflect.TypeOf(float32(0)),
   110  			key:         "json-type-numeric",
   111  			examples:    []string{"n.nnn"},
   112  			help:        "n.nnn (json-type-numeric) fdk",
   113  		},
   114  		{
   115  			name:        "float64",
   116  			reflectType: reflect.TypeOf(float64(0)),
   117  			key:         "json-type-numeric",
   118  			examples:    []string{"n.nnn"},
   119  			help:        "n.nnn (json-type-numeric) fdk",
   120  		},
   121  		{
   122  			name:        "string",
   123  			reflectType: reflect.TypeOf(""),
   124  			key:         "json-type-string",
   125  			examples:    []string{`"json-example-string"`},
   126  			help:        "\"json-example-string\" (json-type-string) fdk",
   127  		},
   128  		{
   129  			name:        "bool",
   130  			reflectType: reflect.TypeOf(true),
   131  			key:         "json-type-bool",
   132  			examples:    []string{"json-example-bool"},
   133  			help:        "json-example-bool (json-type-bool) fdk",
   134  		},
   135  		{
   136  			name:        "array of int",
   137  			reflectType: reflect.TypeOf([1]int{0}),
   138  			key:         "json-type-arrayjson-type-numeric",
   139  			examples:    []string{"[n,...]"},
   140  			help:        "[n,...] (json-type-arrayjson-type-numeric) fdk",
   141  		},
   142  		{
   143  			name:        "slice of int",
   144  			reflectType: reflect.TypeOf([]int{0}),
   145  			key:         "json-type-arrayjson-type-numeric",
   146  			examples:    []string{"[n,...]"},
   147  			help:        "[n,...] (json-type-arrayjson-type-numeric) fdk",
   148  		},
   149  		{
   150  			name:        "struct",
   151  			reflectType: reflect.TypeOf(struct{}{}),
   152  			key:         "json-type-object",
   153  			examples:    []string{"{", "}\t\t"},
   154  			isComplex:   true,
   155  			help:        "{\n} ",
   156  		},
   157  		{
   158  			name:        "struct indent level 1",
   159  			reflectType: reflect.TypeOf(struct{ field int }{}),
   160  			indentLevel: 1,
   161  			key:         "json-type-object",
   162  			examples: []string{
   163  				"  \"field\": n,\t(json-type-numeric)\t-field",
   164  				" },\t\t",
   165  			},
   166  			help: "{\n" +
   167  				" \"field\": n, (json-type-numeric) -field\n" +
   168  				"}            ",
   169  			isComplex: true,
   170  		},
   171  		{
   172  			name: "array of struct indent level 0",
   173  			reflectType: func() reflect.Type {
   174  				type s struct {
   175  					field int
   176  				}
   177  				return reflect.TypeOf([]s{})
   178  			}(),
   179  			key: "json-type-arrayjson-type-object",
   180  			examples: []string{
   181  				"[{",
   182  				" \"field\": n,\t(json-type-numeric)\ts-field",
   183  				"},...]",
   184  			},
   185  			help: "[{\n" +
   186  				" \"field\": n, (json-type-numeric) s-field\n" +
   187  				"},...]",
   188  			isComplex: true,
   189  		},
   190  		{
   191  			name: "array of struct indent level 1",
   192  			reflectType: func() reflect.Type {
   193  				type s struct {
   194  					field int
   195  				}
   196  				return reflect.TypeOf([]s{})
   197  			}(),
   198  			indentLevel: 1,
   199  			key:         "json-type-arrayjson-type-object",
   200  			examples: []string{
   201  				"  \"field\": n,\t(json-type-numeric)\ts-field",
   202  				" },...],\t\t",
   203  			},
   204  			help: "[{\n" +
   205  				" \"field\": n, (json-type-numeric) s-field\n" +
   206  				"},...]",
   207  			isComplex: true,
   208  		},
   209  		{
   210  			name:        "map",
   211  			reflectType: reflect.TypeOf(map[string]string{}),
   212  			key:         "json-type-object",
   213  			examples: []string{"{",
   214  				" \"fdk--key\": fdk--value, (json-type-object) fdk--desc",
   215  				" ...", "}",
   216  			},
   217  			help: "{\n" +
   218  				" \"fdk--key\": fdk--value, (json-type-object) fdk--desc\n" +
   219  				" ...\n" +
   220  				"}",
   221  			isComplex: true,
   222  		},
   223  		{
   224  			name:        "complex",
   225  			reflectType: reflect.TypeOf(complex64(0)),
   226  			key:         "json-type-value",
   227  			examples:    []string{"json-example-unknown"},
   228  			help:        "json-example-unknown (json-type-value) fdk",
   229  			isInvalid:   true,
   230  		},
   231  	}
   232  
   233  	xT := func(key string) string {
   234  		return key
   235  	}
   236  
   237  	t.Logf("Running %d tests", len(tests))
   238  	for i, test := range tests {
   239  		// Ensure the description key is the expected value.
   240  		key := btcjson.TstReflectTypeToJSONType(xT, test.reflectType)
   241  		if key != test.key {
   242  			t.Errorf("Test #%d (%s) unexpected key - got: %v, "+
   243  				"want: %v", i, test.name, key, test.key)
   244  			continue
   245  		}
   246  
   247  		// Ensure the generated example is as expected.
   248  		examples, isComplex := btcjson.TstReflectTypeToJSONExample(xT,
   249  			test.reflectType, test.indentLevel, "fdk")
   250  		if isComplex != test.isComplex {
   251  			t.Errorf("Test #%d (%s) unexpected isComplex - got: %v, "+
   252  				"want: %v", i, test.name, isComplex,
   253  				test.isComplex)
   254  			continue
   255  		}
   256  		if len(examples) != len(test.examples) {
   257  			t.Errorf("Test #%d (%s) unexpected result length - "+
   258  				"got: %v, want: %v", i, test.name, len(examples),
   259  				len(test.examples))
   260  			continue
   261  		}
   262  		for j, example := range examples {
   263  			if example != test.examples[j] {
   264  				t.Errorf("Test #%d (%s) example #%d unexpected "+
   265  					"example - got: %v, want: %v", i,
   266  					test.name, j, example, test.examples[j])
   267  				continue
   268  			}
   269  		}
   270  
   271  		// Ensure the generated result type help is as expected.
   272  		helpText := btcjson.TstResultTypeHelp(xT, test.reflectType, "fdk")
   273  		if helpText != test.help {
   274  			t.Errorf("Test #%d (%s) unexpected result help - "+
   275  				"got: %v, want: %v", i, test.name, helpText,
   276  				test.help)
   277  			continue
   278  		}
   279  
   280  		isValid := btcjson.TstIsValidResultType(test.reflectType.Kind())
   281  		if isValid != !test.isInvalid {
   282  			t.Errorf("Test #%d (%s) unexpected result type validity "+
   283  				"- got: %v", i, test.name, isValid)
   284  			continue
   285  		}
   286  	}
   287  }
   288  
   289  // TestResultStructHelp ensures the expected help text format is returned for
   290  // various Go struct types.
   291  func TestResultStructHelp(t *testing.T) {
   292  	t.Parallel()
   293  
   294  	tests := []struct {
   295  		name        string
   296  		reflectType reflect.Type
   297  		expected    []string
   298  	}{
   299  		{
   300  			name: "empty struct",
   301  			reflectType: func() reflect.Type {
   302  				type s struct{}
   303  				return reflect.TypeOf(s{})
   304  			}(),
   305  			expected: nil,
   306  		},
   307  		{
   308  			name: "struct with primitive field",
   309  			reflectType: func() reflect.Type {
   310  				type s struct {
   311  					field int
   312  				}
   313  				return reflect.TypeOf(s{})
   314  			}(),
   315  			expected: []string{
   316  				"\"field\": n,\t(json-type-numeric)\ts-field",
   317  			},
   318  		},
   319  		{
   320  			name: "struct with primitive field and json tag",
   321  			reflectType: func() reflect.Type {
   322  				type s struct {
   323  					Field int `json:"f"`
   324  				}
   325  				return reflect.TypeOf(s{})
   326  			}(),
   327  			expected: []string{
   328  				"\"f\": n,\t(json-type-numeric)\ts-f",
   329  			},
   330  		},
   331  		{
   332  			name: "struct with array of primitive field",
   333  			reflectType: func() reflect.Type {
   334  				type s struct {
   335  					field []int
   336  				}
   337  				return reflect.TypeOf(s{})
   338  			}(),
   339  			expected: []string{
   340  				"\"field\": [n,...],\t(json-type-arrayjson-type-numeric)\ts-field",
   341  			},
   342  		},
   343  		{
   344  			name: "struct with sub-struct field",
   345  			reflectType: func() reflect.Type {
   346  				type s2 struct {
   347  					subField int
   348  				}
   349  				type s struct {
   350  					field s2
   351  				}
   352  				return reflect.TypeOf(s{})
   353  			}(),
   354  			expected: []string{
   355  				"\"field\": {\t(json-type-object)\ts-field",
   356  				"{",
   357  				" \"subfield\": n,\t(json-type-numeric)\ts2-subfield",
   358  				"}\t\t",
   359  			},
   360  		},
   361  		{
   362  			name: "struct with sub-struct field pointer",
   363  			reflectType: func() reflect.Type {
   364  				type s2 struct {
   365  					subField int
   366  				}
   367  				type s struct {
   368  					field *s2
   369  				}
   370  				return reflect.TypeOf(s{})
   371  			}(),
   372  			expected: []string{
   373  				"\"field\": {\t(json-type-object)\ts-field",
   374  				"{",
   375  				" \"subfield\": n,\t(json-type-numeric)\ts2-subfield",
   376  				"}\t\t",
   377  			},
   378  		},
   379  		{
   380  			name: "struct with array of structs field",
   381  			reflectType: func() reflect.Type {
   382  				type s2 struct {
   383  					subField int
   384  				}
   385  				type s struct {
   386  					field []s2
   387  				}
   388  				return reflect.TypeOf(s{})
   389  			}(),
   390  			expected: []string{
   391  				"\"field\": [{\t(json-type-arrayjson-type-object)\ts-field",
   392  				"[{",
   393  				" \"subfield\": n,\t(json-type-numeric)\ts2-subfield",
   394  				"},...]",
   395  			},
   396  		},
   397  	}
   398  
   399  	xT := func(key string) string {
   400  		return key
   401  	}
   402  
   403  	t.Logf("Running %d tests", len(tests))
   404  	for i, test := range tests {
   405  		results := btcjson.TstResultStructHelp(xT, test.reflectType, 0)
   406  		if len(results) != len(test.expected) {
   407  			t.Errorf("Test #%d (%s) unexpected result length - "+
   408  				"got: %v, want: %v", i, test.name, len(results),
   409  				len(test.expected))
   410  			continue
   411  		}
   412  		for j, result := range results {
   413  			if result != test.expected[j] {
   414  				t.Errorf("Test #%d (%s) result #%d unexpected "+
   415  					"result - got: %v, want: %v", i,
   416  					test.name, j, result, test.expected[j])
   417  				continue
   418  			}
   419  		}
   420  	}
   421  }
   422  
   423  // TestHelpArgInternals ensures the various help functions which deal with
   424  // arguments work as expected for various argument types.
   425  func TestHelpArgInternals(t *testing.T) {
   426  	t.Parallel()
   427  
   428  	tests := []struct {
   429  		name        string
   430  		method      string
   431  		reflectType reflect.Type
   432  		defaults    map[int]reflect.Value
   433  		help        string
   434  	}{
   435  		{
   436  			name:   "command with no args",
   437  			method: "test",
   438  			reflectType: func() reflect.Type {
   439  				type s struct{}
   440  				return reflect.TypeOf((*s)(nil))
   441  			}(),
   442  			defaults: nil,
   443  			help:     "",
   444  		},
   445  		{
   446  			name:   "command with one required arg",
   447  			method: "test",
   448  			reflectType: func() reflect.Type {
   449  				type s struct {
   450  					Field int
   451  				}
   452  				return reflect.TypeOf((*s)(nil))
   453  			}(),
   454  			defaults: nil,
   455  			help:     "1. field (json-type-numeric, help-required) test-field\n",
   456  		},
   457  		{
   458  			name:   "command with one optional arg, no default",
   459  			method: "test",
   460  			reflectType: func() reflect.Type {
   461  				type s struct {
   462  					Optional *int
   463  				}
   464  				return reflect.TypeOf((*s)(nil))
   465  			}(),
   466  			defaults: nil,
   467  			help:     "1. optional (json-type-numeric, help-optional) test-optional\n",
   468  		},
   469  		{
   470  			name:   "command with one optional arg with default",
   471  			method: "test",
   472  			reflectType: func() reflect.Type {
   473  				type s struct {
   474  					Optional *string
   475  				}
   476  				return reflect.TypeOf((*s)(nil))
   477  			}(),
   478  			defaults: func() map[int]reflect.Value {
   479  				defVal := "test"
   480  				return map[int]reflect.Value{
   481  					0: reflect.ValueOf(&defVal),
   482  				}
   483  			}(),
   484  			help: "1. optional (json-type-string, help-optional, help-default=\"test\") test-optional\n",
   485  		},
   486  		{
   487  			name:   "command with struct field",
   488  			method: "test",
   489  			reflectType: func() reflect.Type {
   490  				type s2 struct {
   491  					F int8
   492  				}
   493  				type s struct {
   494  					Field s2
   495  				}
   496  				return reflect.TypeOf((*s)(nil))
   497  			}(),
   498  			defaults: nil,
   499  			help: "1. field (json-type-object, help-required) test-field\n" +
   500  				"{\n" +
   501  				" \"f\": n, (json-type-numeric) s2-f\n" +
   502  				"}        \n",
   503  		},
   504  		{
   505  			name:   "command with map field",
   506  			method: "test",
   507  			reflectType: func() reflect.Type {
   508  				type s struct {
   509  					Field map[string]float64
   510  				}
   511  				return reflect.TypeOf((*s)(nil))
   512  			}(),
   513  			defaults: nil,
   514  			help: "1. field (json-type-object, help-required) test-field\n" +
   515  				"{\n" +
   516  				" \"test-field--key\": test-field--value, (json-type-object) test-field--desc\n" +
   517  				" ...\n" +
   518  				"}\n",
   519  		},
   520  		{
   521  			name:   "command with slice of primitives field",
   522  			method: "test",
   523  			reflectType: func() reflect.Type {
   524  				type s struct {
   525  					Field []int64
   526  				}
   527  				return reflect.TypeOf((*s)(nil))
   528  			}(),
   529  			defaults: nil,
   530  			help:     "1. field (json-type-arrayjson-type-numeric, help-required) test-field\n",
   531  		},
   532  		{
   533  			name:   "command with slice of structs field",
   534  			method: "test",
   535  			reflectType: func() reflect.Type {
   536  				type s2 struct {
   537  					F int64
   538  				}
   539  				type s struct {
   540  					Field []s2
   541  				}
   542  				return reflect.TypeOf((*s)(nil))
   543  			}(),
   544  			defaults: nil,
   545  			help: "1. field (json-type-arrayjson-type-object, help-required) test-field\n" +
   546  				"[{\n" +
   547  				" \"f\": n, (json-type-numeric) s2-f\n" +
   548  				"},...]\n",
   549  		},
   550  	}
   551  
   552  	xT := func(key string) string {
   553  		return key
   554  	}
   555  
   556  	t.Logf("Running %d tests", len(tests))
   557  	for i, test := range tests {
   558  		help := btcjson.TstArgHelp(xT, test.reflectType, test.defaults,
   559  			test.method)
   560  		if help != test.help {
   561  			t.Errorf("Test #%d (%s) unexpected help - got:\n%v\n"+
   562  				"want:\n%v", i, test.name, help, test.help)
   563  			continue
   564  		}
   565  	}
   566  }
   567  
   568  // TestMethodHelp ensures the method help function works as expected for various
   569  // command structs.
   570  func TestMethodHelp(t *testing.T) {
   571  	t.Parallel()
   572  
   573  	tests := []struct {
   574  		name        string
   575  		method      string
   576  		reflectType reflect.Type
   577  		defaults    map[int]reflect.Value
   578  		resultTypes []interface{}
   579  		help        string
   580  	}{
   581  		{
   582  			name:   "command with no args or results",
   583  			method: "test",
   584  			reflectType: func() reflect.Type {
   585  				type s struct{}
   586  				return reflect.TypeOf((*s)(nil))
   587  			}(),
   588  			help: "test\n\ntest--synopsis\n\n" +
   589  				"help-arguments:\nhelp-arguments-none\n\n" +
   590  				"help-result:\nhelp-result-nothing\n",
   591  		},
   592  		{
   593  			name:   "command with no args and one primitive result",
   594  			method: "test",
   595  			reflectType: func() reflect.Type {
   596  				type s struct{}
   597  				return reflect.TypeOf((*s)(nil))
   598  			}(),
   599  			resultTypes: []interface{}{(*int64)(nil)},
   600  			help: "test\n\ntest--synopsis\n\n" +
   601  				"help-arguments:\nhelp-arguments-none\n\n" +
   602  				"help-result:\nn (json-type-numeric) test--result0\n",
   603  		},
   604  		{
   605  			name:   "command with no args and two results",
   606  			method: "test",
   607  			reflectType: func() reflect.Type {
   608  				type s struct{}
   609  				return reflect.TypeOf((*s)(nil))
   610  			}(),
   611  			resultTypes: []interface{}{(*int64)(nil), nil},
   612  			help: "test\n\ntest--synopsis\n\n" +
   613  				"help-arguments:\nhelp-arguments-none\n\n" +
   614  				"help-result (test--condition0):\nn (json-type-numeric) test--result0\n\n" +
   615  				"help-result (test--condition1):\nhelp-result-nothing\n",
   616  		},
   617  		{
   618  			name:   "command with primitive arg and no results",
   619  			method: "test",
   620  			reflectType: func() reflect.Type {
   621  				type s struct {
   622  					Field bool
   623  				}
   624  				return reflect.TypeOf((*s)(nil))
   625  			}(),
   626  			help: "test field\n\ntest--synopsis\n\n" +
   627  				"help-arguments:\n1. field (json-type-bool, help-required) test-field\n\n" +
   628  				"help-result:\nhelp-result-nothing\n",
   629  		},
   630  		{
   631  			name:   "command with primitive optional and no results",
   632  			method: "test",
   633  			reflectType: func() reflect.Type {
   634  				type s struct {
   635  					Field *bool
   636  				}
   637  				return reflect.TypeOf((*s)(nil))
   638  			}(),
   639  			help: "test (field)\n\ntest--synopsis\n\n" +
   640  				"help-arguments:\n1. field (json-type-bool, help-optional) test-field\n\n" +
   641  				"help-result:\nhelp-result-nothing\n",
   642  		},
   643  	}
   644  
   645  	xT := func(key string) string {
   646  		return key
   647  	}
   648  
   649  	t.Logf("Running %d tests", len(tests))
   650  	for i, test := range tests {
   651  		help := btcjson.TestMethodHelp(xT, test.reflectType,
   652  			test.defaults, test.method, test.resultTypes)
   653  		if help != test.help {
   654  			t.Errorf("Test #%d (%s) unexpected help - got:\n%v\n"+
   655  				"want:\n%v", i, test.name, help, test.help)
   656  			continue
   657  		}
   658  	}
   659  }
   660  
   661  // TestGenerateHelpErrors ensures the GenerateHelp function returns the expected
   662  // errors.
   663  func TestGenerateHelpErrors(t *testing.T) {
   664  	t.Parallel()
   665  
   666  	tests := []struct {
   667  		name        string
   668  		method      string
   669  		resultTypes []interface{}
   670  		err         btcjson.Error
   671  	}{
   672  		{
   673  			name:   "unregistered command",
   674  			method: "boguscommand",
   675  			err:    btcjson.Error{ErrorCode: btcjson.ErrUnregisteredMethod},
   676  		},
   677  		{
   678  			name:        "non-pointer result type",
   679  			method:      "help",
   680  			resultTypes: []interface{}{0},
   681  			err:         btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
   682  		},
   683  		{
   684  			name:        "invalid result type",
   685  			method:      "help",
   686  			resultTypes: []interface{}{(*complex64)(nil)},
   687  			err:         btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
   688  		},
   689  		{
   690  			name:        "missing description",
   691  			method:      "help",
   692  			resultTypes: []interface{}{(*string)(nil), nil},
   693  			err:         btcjson.Error{ErrorCode: btcjson.ErrMissingDescription},
   694  		},
   695  	}
   696  
   697  	t.Logf("Running %d tests", len(tests))
   698  	for i, test := range tests {
   699  		_, err := btcjson.GenerateHelp(test.method, nil,
   700  			test.resultTypes...)
   701  		if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
   702  			t.Errorf("Test #%d (%s) wrong error - got %T (%v), "+
   703  				"want %T", i, test.name, err, err, test.err)
   704  			continue
   705  		}
   706  		gotErrorCode := err.(btcjson.Error).ErrorCode
   707  		if gotErrorCode != test.err.ErrorCode {
   708  			t.Errorf("Test #%d (%s) mismatched error code - got "+
   709  				"%v (%v), want %v", i, test.name, gotErrorCode,
   710  				err, test.err.ErrorCode)
   711  			continue
   712  		}
   713  	}
   714  }
   715  
   716  // TestGenerateHelp performs a very basic test to ensure GenerateHelp is working
   717  // as expected.  The internal are testd much more thoroughly in other tests, so
   718  // there is no need to add more tests here.
   719  func TestGenerateHelp(t *testing.T) {
   720  	t.Parallel()
   721  
   722  	descs := map[string]string{
   723  		"help--synopsis": "test",
   724  		"help-command":   "test",
   725  	}
   726  	help, err := btcjson.GenerateHelp("help", descs)
   727  	if err != nil {
   728  		t.Fatalf("GenerateHelp: unexpected error: %v", err)
   729  	}
   730  	wantHelp := "help (\"command\")\n\n" +
   731  		"test\n\nArguments:\n1. command (string, optional) test\n\n" +
   732  		"Result:\nNothing\n"
   733  	if help != wantHelp {
   734  		t.Fatalf("GenerateHelp: unexpected help - got\n%v\nwant\n%v",
   735  			help, wantHelp)
   736  	}
   737  }