pkg.re/essentialkaos/ek.10@v12.41.0+incompatible/options/options_test.go (about)

     1  package options
     2  
     3  // ////////////////////////////////////////////////////////////////////////////////// //
     4  //                                                                                    //
     5  //                         Copyright (c) 2022 ESSENTIAL KAOS                          //
     6  //      Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0>     //
     7  //                                                                                    //
     8  // ////////////////////////////////////////////////////////////////////////////////// //
     9  
    10  import (
    11  	"strings"
    12  	"testing"
    13  
    14  	. "pkg.re/essentialkaos/check.v1"
    15  )
    16  
    17  // ////////////////////////////////////////////////////////////////////////////////// //
    18  
    19  func Test(t *testing.T) { TestingT(t) }
    20  
    21  type OptUtilSuite struct{}
    22  
    23  // ////////////////////////////////////////////////////////////////////////////////// //
    24  
    25  var _ = Suite(&OptUtilSuite{})
    26  
    27  // ////////////////////////////////////////////////////////////////////////////////// //
    28  
    29  func (s *OptUtilSuite) TestAdd(c *C) {
    30  	opts := &Options{}
    31  
    32  	c.Assert(opts.Add("", &V{}), NotNil)
    33  	c.Assert(opts.Add("t:", &V{}), NotNil)
    34  
    35  	c.Assert(opts.Add("test", &V{}), IsNil)
    36  	c.Assert(opts.Add(":test1", &V{}), IsNil)
    37  	c.Assert(opts.Add("t:test2", &V{}), IsNil)
    38  
    39  	c.Assert(opts.Add("t1:test", &V{}), NotNil)
    40  	c.Assert(opts.Add("t:test3", &V{}), NotNil)
    41  	c.Assert(opts.Add("t:test3", nil), NotNil)
    42  }
    43  
    44  func (s *OptUtilSuite) TestAddMap(c *C) {
    45  	opts := NewOptions()
    46  
    47  	m1 := Map{"": {}}
    48  	m2 := Map{"t:": {}}
    49  
    50  	c.Assert(opts.AddMap(m1), Not(HasLen), 0)
    51  	c.Assert(opts.AddMap(m2), Not(HasLen), 0)
    52  
    53  	m3 := Map{"test": {}}
    54  	m4 := Map{"t:test2": {}}
    55  
    56  	c.Assert(opts.AddMap(m3), HasLen, 0)
    57  	c.Assert(opts.AddMap(m4), HasLen, 0)
    58  
    59  	m5 := Map{
    60  		"t:test":  {},
    61  		"T:test1": {},
    62  		"t:test2": {},
    63  	}
    64  
    65  	c.Assert(opts.AddMap(m5), HasLen, 2)
    66  }
    67  
    68  func (s *OptUtilSuite) TestGlobal(c *C) {
    69  	long, short := ParseOptionName("t:test")
    70  
    71  	c.Assert(short, Equals, "t")
    72  	c.Assert(long, Equals, "test")
    73  
    74  	c.Assert(GetS("s:string"), Equals, "")
    75  	c.Assert(GetI("i:int"), Equals, 0)
    76  	c.Assert(GetF("f:float"), Equals, 0.0)
    77  	c.Assert(GetB("b:bool"), Equals, false)
    78  	c.Assert(Has("s:string"), Equals, false)
    79  
    80  	c.Assert(Add("t:test", &V{}), IsNil)
    81  
    82  	global = nil
    83  
    84  	c.Assert(AddMap(Map{}), IsNil)
    85  
    86  	global = nil
    87  
    88  	Parse(Map{})
    89  
    90  	global = NewOptions()
    91  
    92  	_, errs := global.Parse(
    93  		strings.Split("-s Test -i 123 -f 100.5 -b", " "),
    94  		Map{
    95  			"s:string": {},
    96  			"i:int":    {Type: INT},
    97  			"f:float":  {Type: FLOAT},
    98  			"b:bool":   {Type: BOOL},
    99  		},
   100  	)
   101  
   102  	c.Assert(errs, HasLen, 0)
   103  
   104  	c.Assert(Has("s:string"), Equals, true)
   105  	c.Assert(Has("string1"), Equals, false)
   106  	c.Assert(GetS("s:string"), Equals, "Test")
   107  	c.Assert(GetI("i:int"), Equals, 123)
   108  	c.Assert(GetF("f:float"), Equals, 100.5)
   109  	c.Assert(GetB("b:bool"), Equals, true)
   110  }
   111  
   112  func (s *OptUtilSuite) TestLimiters(c *C) {
   113  	argline := "--int1 1 --int2 5 --int3 10 --float1 1.0 --float2 5.0 --float3 10.0"
   114  
   115  	optMap := Map{
   116  		"int1":   {Type: INT, Min: 3, Max: 7},
   117  		"int2":   {Type: INT, Min: 3, Max: 7},
   118  		"int3":   {Type: INT, Min: 3, Max: 7},
   119  		"float1": {Type: FLOAT, Min: 3.0, Max: 7.0},
   120  		"float2": {Type: FLOAT, Min: 3.0, Max: 7.0},
   121  		"float3": {Type: FLOAT, Min: 3.0, Max: 7.0},
   122  	}
   123  
   124  	opts := NewOptions()
   125  	opts.Parse(strings.Split(argline, " "), optMap)
   126  
   127  	c.Assert(opts.GetI("int1"), Equals, 3)
   128  	c.Assert(opts.GetI("int2"), Equals, 5)
   129  	c.Assert(opts.GetI("int3"), Equals, 7)
   130  	c.Assert(opts.GetF("float1"), Equals, 3.0)
   131  	c.Assert(opts.GetF("float2"), Equals, 5.0)
   132  	c.Assert(opts.GetF("float3"), Equals, 7.0)
   133  }
   134  
   135  func (s *OptUtilSuite) TestConflicts(c *C) {
   136  	argline := "--test1 abc --test2 123"
   137  
   138  	optMap := Map{
   139  		"test1": {Conflicts: "test2"},
   140  		"test2": {},
   141  	}
   142  
   143  	opts := NewOptions()
   144  	_, errs := opts.Parse(strings.Split(argline, " "), optMap)
   145  
   146  	c.Assert(errs, Not(HasLen), 0)
   147  	c.Assert(errs[0].(OptionError).Type, Equals, ERROR_CONFLICT)
   148  	c.Assert(errs[0].Error(), Equals, "Option test1 conflicts with option test2")
   149  
   150  	argline = "--test0 xyz"
   151  
   152  	optMap = Map{
   153  		"test0": {},
   154  		"test1": {Conflicts: "test2"},
   155  		"test2": {},
   156  	}
   157  
   158  	opts = NewOptions()
   159  	_, errs = opts.Parse(strings.Split(argline, " "), optMap)
   160  
   161  	c.Assert(errs, HasLen, 0)
   162  }
   163  
   164  func (s *OptUtilSuite) TestBound(c *C) {
   165  	argline := "--test1 abc"
   166  
   167  	optMap := Map{
   168  		"test1": {Bound: "test2"},
   169  		"test2": {},
   170  	}
   171  
   172  	opts := NewOptions()
   173  	_, errs := opts.Parse(strings.Split(argline, " "), optMap)
   174  
   175  	c.Assert(errs, Not(HasLen), 0)
   176  	c.Assert(errs[0].(OptionError).Type, Equals, ERROR_BOUND_NOT_SET)
   177  	c.Assert(errs[0].Error(), Equals, "Option test2 must be defined with option test1")
   178  
   179  	argline = "--test0 xyz"
   180  
   181  	optMap = Map{
   182  		"test0": {},
   183  		"test1": {Bound: "test2"},
   184  		"test2": {},
   185  	}
   186  
   187  	opts = NewOptions()
   188  	_, errs = opts.Parse(strings.Split(argline, " "), optMap)
   189  
   190  	c.Assert(errs, HasLen, 0)
   191  }
   192  
   193  func (s *OptUtilSuite) TestGetters(c *C) {
   194  	argline := "file.mp3 -s STRING --required TEST -i 320 -b -f 1.098765 -S2 100 -f1 5 -f2 1 -ms ABC --merg-string DEF -mi 6 --merg-int 6 -f3 12 -mf 10.1 -mf 10.1 -i1 5"
   195  
   196  	optMap := Map{
   197  		"s:string":          {Type: STRING, Value: "STRING"},
   198  		"S:empty-string":    {Type: STRING},
   199  		"r:required":        {Required: true, Alias: "A:alias"},
   200  		"i:int":             {Type: INT},
   201  		"i1:int-between":    {Type: INT, Min: 1, Max: 3},
   202  		"I:not-set-int":     {Type: INT, Value: 0},
   203  		"b:bool":            {Type: BOOL},
   204  		"B:empty-bool":      {Type: BOOL},
   205  		"B1:not-set-bool":   {Type: BOOL, Value: false},
   206  		"f:float":           {Type: FLOAT},
   207  		"F:not-set-float":   {Type: FLOAT, Value: 0.0},
   208  		"f1:float-max":      {Type: FLOAT, Max: 3.0},
   209  		"f2:float-min":      {Type: FLOAT, Min: 3.0},
   210  		"f3:float-between":  {Type: FLOAT, Min: 3.0, Max: 10.0},
   211  		"ms:merg-string":    {Mergeble: true},
   212  		"mi:merg-int":       {Type: INT, Mergeble: true},
   213  		"mf:merg-float":     {Type: FLOAT, Mergeble: true},
   214  		"S1:not-set-string": {Type: STRING, Value: ""},
   215  		"S2:string-as-num":  {Type: STRING},
   216  		"M:mixed":           {Type: MIXED},
   217  	}
   218  
   219  	opts := NewOptions()
   220  	opts.Parse(strings.Split(argline, " "), optMap)
   221  
   222  	c.Assert(opts.GetS("_not_exist_"), Equals, "")
   223  	c.Assert(opts.GetI("_not_exist_"), Equals, 0)
   224  	c.Assert(opts.GetB("_not_exist_"), Equals, false)
   225  	c.Assert(opts.GetF("_not_exist_"), Equals, 0.0)
   226  
   227  	c.Assert(opts.GetS("s:string"), Equals, "STRING")
   228  	c.Assert(opts.GetS("string"), Equals, "STRING")
   229  	c.Assert(opts.GetS("S:empty-string"), Equals, "")
   230  	c.Assert(opts.GetS("empty-string"), Equals, "")
   231  	c.Assert(opts.GetB("string"), Equals, true)
   232  	c.Assert(opts.GetI("string"), Equals, 0)
   233  	c.Assert(opts.GetF("string"), Equals, 0.0)
   234  	c.Assert(opts.GetB("empty-string"), Equals, false)
   235  	c.Assert(opts.GetI("empty-string"), Equals, 0)
   236  	c.Assert(opts.GetF("empty-string"), Equals, 0.0)
   237  	c.Assert(opts.GetB("not-set-string"), Equals, false)
   238  	c.Assert(opts.GetI("not-set-string"), Equals, 0)
   239  	c.Assert(opts.GetF("not-set-string"), Equals, 0.0)
   240  	c.Assert(opts.GetS("S2:string-as-num"), Equals, "100")
   241  	c.Assert(opts.GetB("S2:string-as-num"), Equals, true)
   242  	c.Assert(opts.GetI("S2:string-as-num"), Equals, 100)
   243  	c.Assert(opts.GetF("S2:string-as-num"), Equals, 100.0)
   244  
   245  	c.Assert(opts.GetS("r:required"), Equals, "TEST")
   246  	c.Assert(opts.GetS("required"), Equals, "TEST")
   247  	c.Assert(opts.GetS("A:alias"), Equals, "TEST")
   248  	c.Assert(opts.GetS("alias"), Equals, "TEST")
   249  
   250  	c.Assert(opts.GetS("int"), Equals, "320")
   251  	c.Assert(opts.GetB("int"), Equals, true)
   252  	c.Assert(opts.GetI("int"), Equals, 320)
   253  	c.Assert(opts.GetF("int"), Equals, 320.0)
   254  	c.Assert(opts.GetI("int-between"), Equals, 3)
   255  	c.Assert(opts.GetS("not-set-int"), Equals, "0")
   256  	c.Assert(opts.GetB("not-set-int"), Equals, false)
   257  	c.Assert(opts.GetI("not-set-int"), Equals, 0)
   258  	c.Assert(opts.GetF("not-set-int"), Equals, 0.0)
   259  
   260  	c.Assert(opts.GetS("b:bool"), Equals, "true")
   261  	c.Assert(opts.GetI("b:bool"), Equals, 1)
   262  	c.Assert(opts.GetB("b:bool"), Equals, true)
   263  	c.Assert(opts.GetF("b:bool"), Equals, 1.0)
   264  	c.Assert(opts.GetS("empty-bool"), Equals, "")
   265  	c.Assert(opts.GetI("empty-bool"), Equals, 0)
   266  	c.Assert(opts.GetB("empty-bool"), Equals, false)
   267  	c.Assert(opts.GetF("empty-bool"), Equals, 0.0)
   268  	c.Assert(opts.GetS("not-set-bool"), Equals, "false")
   269  	c.Assert(opts.GetI("not-set-bool"), Equals, 0)
   270  	c.Assert(opts.GetB("not-set-bool"), Equals, false)
   271  	c.Assert(opts.GetF("not-set-bool"), Equals, 0.0)
   272  
   273  	c.Assert(opts.GetS("float"), Equals, "1.098765")
   274  	c.Assert(opts.GetB("float"), Equals, true)
   275  	c.Assert(opts.GetI("float"), Equals, 1)
   276  	c.Assert(opts.GetF("float"), Equals, 1.098765)
   277  	c.Assert(opts.GetS("not-set-float"), Equals, "0")
   278  	c.Assert(opts.GetB("not-set-float"), Equals, false)
   279  	c.Assert(opts.GetI("not-set-float"), Equals, 0)
   280  	c.Assert(opts.GetF("not-set-float"), Equals, 0.0)
   281  
   282  	c.Assert(opts.GetF("float-max"), Equals, 3.0)
   283  	c.Assert(opts.GetF("float-min"), Equals, 3.0)
   284  	c.Assert(opts.GetF("float-between"), Equals, 10.0)
   285  
   286  	c.Assert(opts.GetS("merg-string"), Equals, "ABC DEF")
   287  	c.Assert(opts.GetI("merg-int"), Equals, 12)
   288  	c.Assert(opts.GetF("merg-float"), Equals, 20.2)
   289  
   290  	c.Assert(opts.Has("_not_exist_"), Equals, false)
   291  	c.Assert(opts.Has("empty-string"), Equals, false)
   292  	c.Assert(opts.Has("s:string"), Equals, true)
   293  }
   294  
   295  func (s *OptUtilSuite) TestMixed(c *C) {
   296  	optMap := Map{
   297  		"M:mixed": {Type: MIXED},
   298  		"t:test":  {},
   299  	}
   300  
   301  	argline := "-M -t 123"
   302  	opts := NewOptions()
   303  	opts.Parse(strings.Split(argline, " "), optMap)
   304  
   305  	c.Assert(opts.Has("M:mixed"), Equals, true)
   306  	c.Assert(opts.GetS("M:mixed"), Equals, "true")
   307  	c.Assert(opts.GetS("t:test"), Equals, "123")
   308  
   309  	argline = "-M TEST123 --test 123"
   310  	opts = NewOptions()
   311  	opts.Parse(strings.Split(argline, " "), optMap)
   312  
   313  	c.Assert(opts.Has("M:mixed"), Equals, true)
   314  	c.Assert(opts.GetS("M:mixed"), Equals, "TEST123")
   315  	c.Assert(opts.GetS("t:test"), Equals, "123")
   316  
   317  	argline = "--test 123 -M"
   318  	opts = NewOptions()
   319  	opts.Parse(strings.Split(argline, " "), optMap)
   320  
   321  	c.Assert(opts.Has("M:mixed"), Equals, true)
   322  	c.Assert(opts.GetS("M:mixed"), Equals, "true")
   323  	c.Assert(opts.GetS("t:test"), Equals, "123")
   324  }
   325  
   326  func (s *OptUtilSuite) TestParsing(c *C) {
   327  	_, errs := NewOptions().Parse([]string{}, Map{})
   328  
   329  	c.Assert(errs, HasLen, 0)
   330  
   331  	// //////////////////////////////////////////////////////////////////////////////// //
   332  
   333  	_, errs = NewOptions().Parse([]string{"--test", "100"}, Map{"t:test": {Type: 10}})
   334  
   335  	c.Assert(errs, Not(HasLen), 0)
   336  	c.Assert(errs[0].Error(), Equals, "Option --test has unsupported type")
   337  
   338  	// //////////////////////////////////////////////////////////////////////////////// //
   339  
   340  	_, errs = NewOptions().Parse([]string{}, Map{"s:string": {}, "s:trace": {}})
   341  
   342  	c.Assert(errs, Not(HasLen), 0)
   343  	c.Assert(errs[0].Error(), Equals, "Option -s defined 2 or more times")
   344  
   345  	// //////////////////////////////////////////////////////////////////////////////// //
   346  
   347  	_, errs = NewOptions().Parse([]string{"-t"}, Map{"s:string": {}})
   348  
   349  	c.Assert(errs, Not(HasLen), 0)
   350  	c.Assert(errs[0].Error(), Equals, "Option -t is not supported")
   351  
   352  	// //////////////////////////////////////////////////////////////////////////////// //
   353  
   354  	_, errs = NewOptions().Parse([]string{"-t=100"}, Map{"s:string": {}})
   355  
   356  	c.Assert(errs, Not(HasLen), 0)
   357  	c.Assert(errs[0].Error(), Equals, "Option -t is not supported")
   358  
   359  	// //////////////////////////////////////////////////////////////////////////////// //
   360  
   361  	_, errs = NewOptions().Parse([]string{"--test"}, Map{"s:string": {}})
   362  
   363  	c.Assert(errs, Not(HasLen), 0)
   364  	c.Assert(errs[0].Error(), Equals, "Option --test is not supported")
   365  
   366  	// //////////////////////////////////////////////////////////////////////////////// //
   367  
   368  	fArgs, errs := NewOptions().Parse([]string{"-", "--"}, Map{"t:test": {}})
   369  
   370  	c.Assert(errs, HasLen, 0)
   371  	c.Assert(fArgs, DeepEquals, Arguments{"-", "--"})
   372  
   373  	// //////////////////////////////////////////////////////////////////////////////// //
   374  
   375  	_, errs = NewOptions().Parse([]string{"--asd="}, Map{"t:test": {}})
   376  
   377  	c.Assert(errs, Not(HasLen), 0)
   378  	c.Assert(errs[0].Error(), Equals, "Option --asd has wrong format")
   379  
   380  	// //////////////////////////////////////////////////////////////////////////////// //
   381  
   382  	_, errs = NewOptions().Parse([]string{"-j="}, Map{"t:test": {}})
   383  
   384  	c.Assert(errs, Not(HasLen), 0)
   385  	c.Assert(errs[0].Error(), Equals, "Option -j has wrong format")
   386  
   387  	// //////////////////////////////////////////////////////////////////////////////// //
   388  
   389  	_, errs = NewOptions().Parse([]string{}, Map{"t:test": {Required: true}})
   390  
   391  	c.Assert(errs, Not(HasLen), 0)
   392  	c.Assert(errs[0].Error(), Equals, "Required option test is not set")
   393  
   394  	// //////////////////////////////////////////////////////////////////////////////// //
   395  
   396  	_, errs = NewOptions().Parse([]string{"-t"}, Map{"t:test": {}})
   397  
   398  	c.Assert(errs, Not(HasLen), 0)
   399  	c.Assert(errs[0].Error(), Equals, "Non-boolean option --test is empty")
   400  
   401  	// //////////////////////////////////////////////////////////////////////////////// //
   402  
   403  	_, errs = NewOptions().Parse([]string{"--test=!"}, Map{"t:test": {Type: FLOAT}})
   404  
   405  	c.Assert(errs, Not(HasLen), 0)
   406  	c.Assert(errs[0].Error(), Equals, "Option --test has wrong format")
   407  
   408  	// //////////////////////////////////////////////////////////////////////////////// //
   409  
   410  	_, errs = NewOptions().Parse([]string{"-t=!"}, Map{"t:test": {Type: INT}})
   411  
   412  	c.Assert(errs, Not(HasLen), 0)
   413  	c.Assert(errs[0].Error(), Equals, "Option --test has wrong format")
   414  
   415  	// //////////////////////////////////////////////////////////////////////////////// //
   416  
   417  	_, errs = NewOptions().Parse([]string{"--test", "!"}, Map{"t:test": {Type: INT}})
   418  
   419  	c.Assert(errs, Not(HasLen), 0)
   420  	c.Assert(errs[0].Error(), Equals, "Option --test has wrong format")
   421  
   422  	// //////////////////////////////////////////////////////////////////////////////// //
   423  
   424  	_, errs = NewOptions().Parse([]string{}, Map{"t:test": nil})
   425  
   426  	c.Assert(errs, Not(HasLen), 0)
   427  	c.Assert(errs[0].Error(), Equals, "Struct for option --test is nil")
   428  
   429  	// //////////////////////////////////////////////////////////////////////////////// //
   430  
   431  	_, errs = NewOptions().Parse([]string{}, Map{"t:test": {Value: []string{}}})
   432  
   433  	c.Assert(errs, Not(HasLen), 0)
   434  	c.Assert(errs[0].Error(), Equals, "Option test contains unsupported default value")
   435  
   436  	// //////////////////////////////////////////////////////////////////////////////// //
   437  
   438  	_, errs = NewOptions().Parse([]string{}, Map{"": {}})
   439  
   440  	c.Assert(errs, Not(HasLen), 0)
   441  	c.Assert(errs[0].Error(), Equals, "Some option does not have a name")
   442  }
   443  
   444  func (s *OptUtilSuite) TestMerging(c *C) {
   445  	c.Assert(Q(), Equals, "")
   446  	c.Assert(Q("test"), Equals, "test")
   447  	c.Assert(Q("test1", "test2"), Equals, "test1 test2")
   448  }
   449  
   450  func (s *OptUtilSuite) TestGuessType(c *C) {
   451  	c.Assert(guessType(nil), Equals, STRING)
   452  	c.Assert(guessType("test"), Equals, STRING)
   453  	c.Assert(guessType(4), Equals, INT)
   454  	c.Assert(guessType(true), Equals, BOOL)
   455  	c.Assert(guessType(3.3), Equals, FLOAT)
   456  }
   457  
   458  func (s *OptUtilSuite) TestArguments(c *C) {
   459  	a := Arguments([]string{"test", "6", "2.67", "true"})
   460  
   461  	c.Assert(a.Has(1), Equals, true)
   462  	c.Assert(a.Has(9), Equals, false)
   463  
   464  	c.Assert(a.Get(0), Equals, "test")
   465  	c.Assert(a.Get(1), Equals, "6")
   466  	c.Assert(a.Get(2), Equals, "2.67")
   467  	c.Assert(a.Get(3), Equals, "true")
   468  	c.Assert(a.Get(4), Equals, "")
   469  
   470  	iv, err := a.GetI(0)
   471  	c.Assert(err, NotNil)
   472  	c.Assert(iv, Equals, 0)
   473  	iv, err = a.GetI(1)
   474  	c.Assert(err, IsNil)
   475  	c.Assert(iv, Equals, 6)
   476  
   477  	fv, err := a.GetF(0)
   478  	c.Assert(err, NotNil)
   479  	c.Assert(fv, Equals, 0.0)
   480  	fv, err = a.GetF(2)
   481  	c.Assert(err, IsNil)
   482  	c.Assert(fv, Equals, 2.67)
   483  
   484  	a = Arguments([]string{"true", "yes", "y", "1", "false", "no", "n", "0", "", "TEST"})
   485  
   486  	bv, err := a.GetB(0)
   487  	c.Assert(err, IsNil)
   488  	c.Assert(bv, Equals, true)
   489  	bv, err = a.GetB(1)
   490  	c.Assert(err, IsNil)
   491  	c.Assert(bv, Equals, true)
   492  	bv, err = a.GetB(2)
   493  	c.Assert(err, IsNil)
   494  	c.Assert(bv, Equals, true)
   495  	bv, err = a.GetB(3)
   496  	c.Assert(err, IsNil)
   497  	c.Assert(bv, Equals, true)
   498  	bv, err = a.GetB(4)
   499  	c.Assert(err, IsNil)
   500  	c.Assert(bv, Equals, false)
   501  	bv, err = a.GetB(5)
   502  	c.Assert(err, IsNil)
   503  	c.Assert(bv, Equals, false)
   504  	bv, err = a.GetB(6)
   505  	c.Assert(err, IsNil)
   506  	c.Assert(bv, Equals, false)
   507  	bv, err = a.GetB(7)
   508  	c.Assert(err, IsNil)
   509  	c.Assert(bv, Equals, false)
   510  	bv, err = a.GetB(8)
   511  	c.Assert(err, IsNil)
   512  	c.Assert(bv, Equals, false)
   513  	bv, err = a.GetB(9)
   514  	c.Assert(err, NotNil)
   515  	c.Assert(bv, Equals, false)
   516  }