github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/config/interpolate_funcs_test.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"reflect"
     8  	"testing"
     9  
    10  	"github.com/hashicorp/terraform/config/lang"
    11  	"github.com/hashicorp/terraform/config/lang/ast"
    12  )
    13  
    14  func TestInterpolateFuncCompact(t *testing.T) {
    15  	testFunction(t, testFunctionConfig{
    16  		Cases: []testFunctionCase{
    17  			// empty string within array
    18  			{
    19  				`${compact(split(",", "a,,b"))}`,
    20  				NewStringList([]string{"a", "b"}).String(),
    21  				false,
    22  			},
    23  
    24  			// empty string at the end of array
    25  			{
    26  				`${compact(split(",", "a,b,"))}`,
    27  				NewStringList([]string{"a", "b"}).String(),
    28  				false,
    29  			},
    30  
    31  			// single empty string
    32  			{
    33  				`${compact(split(",", ""))}`,
    34  				NewStringList([]string{}).String(),
    35  				false,
    36  			},
    37  		},
    38  	})
    39  }
    40  
    41  func TestInterpolateFuncCidrHost(t *testing.T) {
    42  	testFunction(t, testFunctionConfig{
    43  		Cases: []testFunctionCase{
    44  			{
    45  				`${cidrhost("192.168.1.0/24", 5)}`,
    46  				"192.168.1.5",
    47  				false,
    48  			},
    49  			{
    50  				`${cidrhost("192.168.1.0/30", 255)}`,
    51  				nil,
    52  				true, // 255 doesn't fit in two bits
    53  			},
    54  			{
    55  				`${cidrhost("not-a-cidr", 6)}`,
    56  				nil,
    57  				true, // not a valid CIDR mask
    58  			},
    59  			{
    60  				`${cidrhost("10.256.0.0/8", 6)}`,
    61  				nil,
    62  				true, // can't have an octet >255
    63  			},
    64  		},
    65  	})
    66  }
    67  
    68  func TestInterpolateFuncCidrNetmask(t *testing.T) {
    69  	testFunction(t, testFunctionConfig{
    70  		Cases: []testFunctionCase{
    71  			{
    72  				`${cidrnetmask("192.168.1.0/24")}`,
    73  				"255.255.255.0",
    74  				false,
    75  			},
    76  			{
    77  				`${cidrnetmask("192.168.1.0/32")}`,
    78  				"255.255.255.255",
    79  				false,
    80  			},
    81  			{
    82  				`${cidrnetmask("0.0.0.0/0")}`,
    83  				"0.0.0.0",
    84  				false,
    85  			},
    86  			{
    87  				// This doesn't really make sense for IPv6 networks
    88  				// but it ought to do something sensible anyway.
    89  				`${cidrnetmask("1::/64")}`,
    90  				"ffff:ffff:ffff:ffff::",
    91  				false,
    92  			},
    93  			{
    94  				`${cidrnetmask("not-a-cidr")}`,
    95  				nil,
    96  				true, // not a valid CIDR mask
    97  			},
    98  			{
    99  				`${cidrnetmask("10.256.0.0/8")}`,
   100  				nil,
   101  				true, // can't have an octet >255
   102  			},
   103  		},
   104  	})
   105  }
   106  
   107  func TestInterpolateFuncCidrSubnet(t *testing.T) {
   108  	testFunction(t, testFunctionConfig{
   109  		Cases: []testFunctionCase{
   110  			{
   111  				`${cidrsubnet("192.168.2.0/20", 4, 6)}`,
   112  				"192.168.6.0/24",
   113  				false,
   114  			},
   115  			{
   116  				`${cidrsubnet("fe80::/48", 16, 6)}`,
   117  				"fe80:0:0:6::/64",
   118  				false,
   119  			},
   120  			{
   121  				// IPv4 address encoded in IPv6 syntax gets normalized
   122  				`${cidrsubnet("::ffff:192.168.0.0/112", 8, 6)}`,
   123  				"192.168.6.0/24",
   124  				false,
   125  			},
   126  			{
   127  				`${cidrsubnet("192.168.0.0/30", 4, 6)}`,
   128  				nil,
   129  				true, // not enough bits left
   130  			},
   131  			{
   132  				`${cidrsubnet("192.168.0.0/16", 2, 16)}`,
   133  				nil,
   134  				true, // can't encode 16 in 2 bits
   135  			},
   136  			{
   137  				`${cidrsubnet("not-a-cidr", 4, 6)}`,
   138  				nil,
   139  				true, // not a valid CIDR mask
   140  			},
   141  			{
   142  				`${cidrsubnet("10.256.0.0/8", 4, 6)}`,
   143  				nil,
   144  				true, // can't have an octet >255
   145  			},
   146  		},
   147  	})
   148  }
   149  
   150  func TestInterpolateFuncCoalesce(t *testing.T) {
   151  	testFunction(t, testFunctionConfig{
   152  		Cases: []testFunctionCase{
   153  			{
   154  				`${coalesce("first", "second", "third")}`,
   155  				"first",
   156  				false,
   157  			},
   158  			{
   159  				`${coalesce("", "second", "third")}`,
   160  				"second",
   161  				false,
   162  			},
   163  			{
   164  				`${coalesce("", "", "")}`,
   165  				"",
   166  				false,
   167  			},
   168  			{
   169  				`${coalesce("foo")}`,
   170  				nil,
   171  				true,
   172  			},
   173  		},
   174  	})
   175  }
   176  
   177  func TestInterpolateFuncDeprecatedConcat(t *testing.T) {
   178  	testFunction(t, testFunctionConfig{
   179  		Cases: []testFunctionCase{
   180  			{
   181  				`${concat("foo", "bar")}`,
   182  				"foobar",
   183  				false,
   184  			},
   185  
   186  			{
   187  				`${concat("foo")}`,
   188  				"foo",
   189  				false,
   190  			},
   191  
   192  			{
   193  				`${concat()}`,
   194  				nil,
   195  				true,
   196  			},
   197  		},
   198  	})
   199  }
   200  
   201  func TestInterpolateFuncConcat(t *testing.T) {
   202  	testFunction(t, testFunctionConfig{
   203  		Cases: []testFunctionCase{
   204  			// String + list
   205  			{
   206  				`${concat("a", split(",", "b,c"))}`,
   207  				NewStringList([]string{"a", "b", "c"}).String(),
   208  				false,
   209  			},
   210  
   211  			// List + string
   212  			{
   213  				`${concat(split(",", "a,b"), "c")}`,
   214  				NewStringList([]string{"a", "b", "c"}).String(),
   215  				false,
   216  			},
   217  
   218  			// Single list
   219  			{
   220  				`${concat(split(",", ",foo,"))}`,
   221  				NewStringList([]string{"", "foo", ""}).String(),
   222  				false,
   223  			},
   224  			{
   225  				`${concat(split(",", "a,b,c"))}`,
   226  				NewStringList([]string{"a", "b", "c"}).String(),
   227  				false,
   228  			},
   229  
   230  			// Two lists
   231  			{
   232  				`${concat(split(",", "a,b,c"), split(",", "d,e"))}`,
   233  				NewStringList([]string{"a", "b", "c", "d", "e"}).String(),
   234  				false,
   235  			},
   236  			// Two lists with different separators
   237  			{
   238  				`${concat(split(",", "a,b,c"), split(" ", "d e"))}`,
   239  				NewStringList([]string{"a", "b", "c", "d", "e"}).String(),
   240  				false,
   241  			},
   242  
   243  			// More lists
   244  			{
   245  				`${concat(split(",", "a,b"), split(",", "c,d"), split(",", "e,f"), split(",", "0,1"))}`,
   246  				NewStringList([]string{"a", "b", "c", "d", "e", "f", "0", "1"}).String(),
   247  				false,
   248  			},
   249  		},
   250  	})
   251  }
   252  
   253  func TestInterpolateFuncFile(t *testing.T) {
   254  	tf, err := ioutil.TempFile("", "tf")
   255  	if err != nil {
   256  		t.Fatalf("err: %s", err)
   257  	}
   258  	path := tf.Name()
   259  	tf.Write([]byte("foo"))
   260  	tf.Close()
   261  	defer os.Remove(path)
   262  
   263  	testFunction(t, testFunctionConfig{
   264  		Cases: []testFunctionCase{
   265  			{
   266  				fmt.Sprintf(`${file("%s")}`, path),
   267  				"foo",
   268  				false,
   269  			},
   270  
   271  			// Invalid path
   272  			{
   273  				`${file("/i/dont/exist")}`,
   274  				nil,
   275  				true,
   276  			},
   277  
   278  			// Too many args
   279  			{
   280  				`${file("foo", "bar")}`,
   281  				nil,
   282  				true,
   283  			},
   284  		},
   285  	})
   286  }
   287  
   288  func TestInterpolateFuncFormat(t *testing.T) {
   289  	testFunction(t, testFunctionConfig{
   290  		Cases: []testFunctionCase{
   291  			{
   292  				`${format("hello")}`,
   293  				"hello",
   294  				false,
   295  			},
   296  
   297  			{
   298  				`${format("hello %s", "world")}`,
   299  				"hello world",
   300  				false,
   301  			},
   302  
   303  			{
   304  				`${format("hello %d", 42)}`,
   305  				"hello 42",
   306  				false,
   307  			},
   308  
   309  			{
   310  				`${format("hello %05d", 42)}`,
   311  				"hello 00042",
   312  				false,
   313  			},
   314  
   315  			{
   316  				`${format("hello %05d", 12345)}`,
   317  				"hello 12345",
   318  				false,
   319  			},
   320  		},
   321  	})
   322  }
   323  
   324  func TestInterpolateFuncFormatList(t *testing.T) {
   325  	testFunction(t, testFunctionConfig{
   326  		Cases: []testFunctionCase{
   327  			// formatlist requires at least one list
   328  			{
   329  				`${formatlist("hello")}`,
   330  				nil,
   331  				true,
   332  			},
   333  			{
   334  				`${formatlist("hello %s", "world")}`,
   335  				nil,
   336  				true,
   337  			},
   338  			// formatlist applies to each list element in turn
   339  			{
   340  				`${formatlist("<%s>", split(",", "A,B"))}`,
   341  				NewStringList([]string{"<A>", "<B>"}).String(),
   342  				false,
   343  			},
   344  			// formatlist repeats scalar elements
   345  			{
   346  				`${join(", ", formatlist("%s=%s", "x", split(",", "A,B,C")))}`,
   347  				"x=A, x=B, x=C",
   348  				false,
   349  			},
   350  			// Multiple lists are walked in parallel
   351  			{
   352  				`${join(", ", formatlist("%s=%s", split(",", "A,B,C"), split(",", "1,2,3")))}`,
   353  				"A=1, B=2, C=3",
   354  				false,
   355  			},
   356  			// Mismatched list lengths generate an error
   357  			{
   358  				`${formatlist("%s=%2s", split(",", "A,B,C,D"), split(",", "1,2,3"))}`,
   359  				nil,
   360  				true,
   361  			},
   362  			// Works with lists of length 1 [GH-2240]
   363  			{
   364  				`${formatlist("%s.id", split(",", "demo-rest-elb"))}`,
   365  				NewStringList([]string{"demo-rest-elb.id"}).String(),
   366  				false,
   367  			},
   368  		},
   369  	})
   370  }
   371  
   372  func TestInterpolateFuncIndex(t *testing.T) {
   373  	testFunction(t, testFunctionConfig{
   374  		Cases: []testFunctionCase{
   375  			{
   376  				`${index("test", "")}`,
   377  				nil,
   378  				true,
   379  			},
   380  
   381  			{
   382  				fmt.Sprintf(`${index("%s", "foo")}`,
   383  					NewStringList([]string{"notfoo", "stillnotfoo", "bar"}).String()),
   384  				nil,
   385  				true,
   386  			},
   387  
   388  			{
   389  				fmt.Sprintf(`${index("%s", "foo")}`,
   390  					NewStringList([]string{"foo"}).String()),
   391  				"0",
   392  				false,
   393  			},
   394  
   395  			{
   396  				fmt.Sprintf(`${index("%s", "bar")}`,
   397  					NewStringList([]string{"foo", "spam", "bar", "eggs"}).String()),
   398  				"2",
   399  				false,
   400  			},
   401  		},
   402  	})
   403  }
   404  
   405  func TestInterpolateFuncJoin(t *testing.T) {
   406  	testFunction(t, testFunctionConfig{
   407  		Cases: []testFunctionCase{
   408  			{
   409  				`${join(",")}`,
   410  				nil,
   411  				true,
   412  			},
   413  
   414  			{
   415  				fmt.Sprintf(`${join(",", "%s")}`,
   416  					NewStringList([]string{"foo"}).String()),
   417  				"foo",
   418  				false,
   419  			},
   420  
   421  			/*
   422  				TODO
   423  				{
   424  					`${join(",", "foo", "bar")}`,
   425  					"foo,bar",
   426  					false,
   427  				},
   428  			*/
   429  
   430  			{
   431  				fmt.Sprintf(`${join(".", "%s")}`,
   432  					NewStringList([]string{"foo", "bar", "baz"}).String()),
   433  				"foo.bar.baz",
   434  				false,
   435  			},
   436  		},
   437  	})
   438  }
   439  
   440  func TestInterpolateFuncReplace(t *testing.T) {
   441  	testFunction(t, testFunctionConfig{
   442  		Cases: []testFunctionCase{
   443  			// Regular search and replace
   444  			{
   445  				`${replace("hello", "hel", "bel")}`,
   446  				"bello",
   447  				false,
   448  			},
   449  
   450  			// Search string doesn't match
   451  			{
   452  				`${replace("hello", "nope", "bel")}`,
   453  				"hello",
   454  				false,
   455  			},
   456  
   457  			// Regular expression
   458  			{
   459  				`${replace("hello", "/l/", "L")}`,
   460  				"heLLo",
   461  				false,
   462  			},
   463  
   464  			{
   465  				`${replace("helo", "/(l)/", "$1$1")}`,
   466  				"hello",
   467  				false,
   468  			},
   469  
   470  			// Bad regexp
   471  			{
   472  				`${replace("helo", "/(l/", "$1$1")}`,
   473  				nil,
   474  				true,
   475  			},
   476  		},
   477  	})
   478  }
   479  
   480  func TestInterpolateFuncLength(t *testing.T) {
   481  	testFunction(t, testFunctionConfig{
   482  		Cases: []testFunctionCase{
   483  			// Raw strings
   484  			{
   485  				`${length("")}`,
   486  				"0",
   487  				false,
   488  			},
   489  			{
   490  				`${length("a")}`,
   491  				"1",
   492  				false,
   493  			},
   494  			{
   495  				`${length(" ")}`,
   496  				"1",
   497  				false,
   498  			},
   499  			{
   500  				`${length(" a ,")}`,
   501  				"4",
   502  				false,
   503  			},
   504  			{
   505  				`${length("aaa")}`,
   506  				"3",
   507  				false,
   508  			},
   509  
   510  			// Lists
   511  			{
   512  				`${length(split(",", "a"))}`,
   513  				"1",
   514  				false,
   515  			},
   516  			{
   517  				`${length(split(",", "foo,"))}`,
   518  				"2",
   519  				false,
   520  			},
   521  			{
   522  				`${length(split(",", ",foo,"))}`,
   523  				"3",
   524  				false,
   525  			},
   526  			{
   527  				`${length(split(",", "foo,bar"))}`,
   528  				"2",
   529  				false,
   530  			},
   531  			{
   532  				`${length(split(".", "one.two.three.four.five"))}`,
   533  				"5",
   534  				false,
   535  			},
   536  			// Want length 0 if we split an empty string then compact
   537  			{
   538  				`${length(compact(split(",", "")))}`,
   539  				"0",
   540  				false,
   541  			},
   542  		},
   543  	})
   544  }
   545  
   546  func TestInterpolateFuncSplit(t *testing.T) {
   547  	testFunction(t, testFunctionConfig{
   548  		Cases: []testFunctionCase{
   549  			{
   550  				`${split(",")}`,
   551  				nil,
   552  				true,
   553  			},
   554  
   555  			{
   556  				`${split(",", "")}`,
   557  				NewStringList([]string{""}).String(),
   558  				false,
   559  			},
   560  
   561  			{
   562  				`${split(",", "foo")}`,
   563  				NewStringList([]string{"foo"}).String(),
   564  				false,
   565  			},
   566  
   567  			{
   568  				`${split(",", ",,,")}`,
   569  				NewStringList([]string{"", "", "", ""}).String(),
   570  				false,
   571  			},
   572  
   573  			{
   574  				`${split(",", "foo,")}`,
   575  				NewStringList([]string{"foo", ""}).String(),
   576  				false,
   577  			},
   578  
   579  			{
   580  				`${split(",", ",foo,")}`,
   581  				NewStringList([]string{"", "foo", ""}).String(),
   582  				false,
   583  			},
   584  
   585  			{
   586  				`${split(".", "foo.bar.baz")}`,
   587  				NewStringList([]string{"foo", "bar", "baz"}).String(),
   588  				false,
   589  			},
   590  		},
   591  	})
   592  }
   593  
   594  func TestInterpolateFuncLookup(t *testing.T) {
   595  	testFunction(t, testFunctionConfig{
   596  		Vars: map[string]ast.Variable{
   597  			"var.foo.bar": ast.Variable{
   598  				Value: "baz",
   599  				Type:  ast.TypeString,
   600  			},
   601  		},
   602  		Cases: []testFunctionCase{
   603  			{
   604  				`${lookup("foo", "bar")}`,
   605  				"baz",
   606  				false,
   607  			},
   608  
   609  			// Invalid key
   610  			{
   611  				`${lookup("foo", "baz")}`,
   612  				nil,
   613  				true,
   614  			},
   615  
   616  			// Too many args
   617  			{
   618  				`${lookup("foo", "bar", "baz")}`,
   619  				nil,
   620  				true,
   621  			},
   622  		},
   623  	})
   624  }
   625  
   626  func TestInterpolateFuncKeys(t *testing.T) {
   627  	testFunction(t, testFunctionConfig{
   628  		Vars: map[string]ast.Variable{
   629  			"var.foo.bar": ast.Variable{
   630  				Value: "baz",
   631  				Type:  ast.TypeString,
   632  			},
   633  			"var.foo.qux": ast.Variable{
   634  				Value: "quack",
   635  				Type:  ast.TypeString,
   636  			},
   637  			"var.str": ast.Variable{
   638  				Value: "astring",
   639  				Type:  ast.TypeString,
   640  			},
   641  		},
   642  		Cases: []testFunctionCase{
   643  			{
   644  				`${keys("foo")}`,
   645  				NewStringList([]string{"bar", "qux"}).String(),
   646  				false,
   647  			},
   648  
   649  			// Invalid key
   650  			{
   651  				`${keys("not")}`,
   652  				nil,
   653  				true,
   654  			},
   655  
   656  			// Too many args
   657  			{
   658  				`${keys("foo", "bar")}`,
   659  				nil,
   660  				true,
   661  			},
   662  
   663  			// Not a map
   664  			{
   665  				`${keys("str")}`,
   666  				nil,
   667  				true,
   668  			},
   669  		},
   670  	})
   671  }
   672  
   673  func TestInterpolateFuncValues(t *testing.T) {
   674  	testFunction(t, testFunctionConfig{
   675  		Vars: map[string]ast.Variable{
   676  			"var.foo.bar": ast.Variable{
   677  				Value: "quack",
   678  				Type:  ast.TypeString,
   679  			},
   680  			"var.foo.qux": ast.Variable{
   681  				Value: "baz",
   682  				Type:  ast.TypeString,
   683  			},
   684  			"var.str": ast.Variable{
   685  				Value: "astring",
   686  				Type:  ast.TypeString,
   687  			},
   688  		},
   689  		Cases: []testFunctionCase{
   690  			{
   691  				`${values("foo")}`,
   692  				NewStringList([]string{"quack", "baz"}).String(),
   693  				false,
   694  			},
   695  
   696  			// Invalid key
   697  			{
   698  				`${values("not")}`,
   699  				nil,
   700  				true,
   701  			},
   702  
   703  			// Too many args
   704  			{
   705  				`${values("foo", "bar")}`,
   706  				nil,
   707  				true,
   708  			},
   709  
   710  			// Not a map
   711  			{
   712  				`${values("str")}`,
   713  				nil,
   714  				true,
   715  			},
   716  		},
   717  	})
   718  }
   719  
   720  func TestInterpolateFuncElement(t *testing.T) {
   721  	testFunction(t, testFunctionConfig{
   722  		Cases: []testFunctionCase{
   723  			{
   724  				fmt.Sprintf(`${element("%s", "1")}`,
   725  					NewStringList([]string{"foo", "baz"}).String()),
   726  				"baz",
   727  				false,
   728  			},
   729  
   730  			{
   731  				fmt.Sprintf(`${element("%s", "0")}`,
   732  					NewStringList([]string{"foo"}).String()),
   733  				"foo",
   734  				false,
   735  			},
   736  
   737  			// Invalid index should wrap vs. out-of-bounds
   738  			{
   739  				fmt.Sprintf(`${element("%s", "2")}`,
   740  					NewStringList([]string{"foo", "baz"}).String()),
   741  				"foo",
   742  				false,
   743  			},
   744  
   745  			// Too many args
   746  			{
   747  				fmt.Sprintf(`${element("%s", "0", "2")}`,
   748  					NewStringList([]string{"foo", "baz"}).String()),
   749  				nil,
   750  				true,
   751  			},
   752  		},
   753  	})
   754  }
   755  
   756  func TestInterpolateFuncBase64Encode(t *testing.T) {
   757  	testFunction(t, testFunctionConfig{
   758  		Cases: []testFunctionCase{
   759  			// Regular base64 encoding
   760  			{
   761  				`${base64encode("abc123!?$*&()'-=@~")}`,
   762  				"YWJjMTIzIT8kKiYoKSctPUB+",
   763  				false,
   764  			},
   765  		},
   766  	})
   767  }
   768  
   769  func TestInterpolateFuncBase64Decode(t *testing.T) {
   770  	testFunction(t, testFunctionConfig{
   771  		Cases: []testFunctionCase{
   772  			// Regular base64 decoding
   773  			{
   774  				`${base64decode("YWJjMTIzIT8kKiYoKSctPUB+")}`,
   775  				"abc123!?$*&()'-=@~",
   776  				false,
   777  			},
   778  
   779  			// Invalid base64 data decoding
   780  			{
   781  				`${base64decode("this-is-an-invalid-base64-data")}`,
   782  				nil,
   783  				true,
   784  			},
   785  		},
   786  	})
   787  }
   788  
   789  func TestInterpolateFuncLower(t *testing.T) {
   790  	testFunction(t, testFunctionConfig{
   791  		Cases: []testFunctionCase{
   792  			{
   793  				`${lower("HELLO")}`,
   794  				"hello",
   795  				false,
   796  			},
   797  
   798  			{
   799  				`${lower("")}`,
   800  				"",
   801  				false,
   802  			},
   803  
   804  			{
   805  				`${lower()}`,
   806  				nil,
   807  				true,
   808  			},
   809  		},
   810  	})
   811  }
   812  
   813  func TestInterpolateFuncUpper(t *testing.T) {
   814  	testFunction(t, testFunctionConfig{
   815  		Cases: []testFunctionCase{
   816  			{
   817  				`${upper("hello")}`,
   818  				"HELLO",
   819  				false,
   820  			},
   821  
   822  			{
   823  				`${upper("")}`,
   824  				"",
   825  				false,
   826  			},
   827  
   828  			{
   829  				`${upper()}`,
   830  				nil,
   831  				true,
   832  			},
   833  		},
   834  	})
   835  }
   836  
   837  type testFunctionConfig struct {
   838  	Cases []testFunctionCase
   839  	Vars  map[string]ast.Variable
   840  }
   841  
   842  type testFunctionCase struct {
   843  	Input  string
   844  	Result interface{}
   845  	Error  bool
   846  }
   847  
   848  func testFunction(t *testing.T, config testFunctionConfig) {
   849  	for i, tc := range config.Cases {
   850  		ast, err := lang.Parse(tc.Input)
   851  		if err != nil {
   852  			t.Fatalf("Case #%d: input: %#v\nerr: %s", i, tc.Input, err)
   853  		}
   854  
   855  		out, _, err := lang.Eval(ast, langEvalConfig(config.Vars))
   856  		if err != nil != tc.Error {
   857  			t.Fatalf("Case #%d:\ninput: %#v\nerr: %s", i, tc.Input, err)
   858  		}
   859  
   860  		if !reflect.DeepEqual(out, tc.Result) {
   861  			t.Fatalf(
   862  				"%d: bad output for input: %s\n\nOutput: %#v\nExpected: %#v",
   863  				i, tc.Input, out, tc.Result)
   864  		}
   865  	}
   866  }