github.com/xsb/terraform@v0.6.13-0.20160314145438-fe415c2f09d7/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/hil"
    11  	"github.com/hashicorp/hil/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 TestInterpolateFuncSignum(t *testing.T) {
   547  	testFunction(t, testFunctionConfig{
   548  		Cases: []testFunctionCase{
   549  			{
   550  				`${signum()}`,
   551  				nil,
   552  				true,
   553  			},
   554  
   555  			{
   556  				`${signum("")}`,
   557  				nil,
   558  				true,
   559  			},
   560  
   561  			{
   562  				`${signum(0)}`,
   563  				"0",
   564  				false,
   565  			},
   566  
   567  			{
   568  				`${signum(15)}`,
   569  				"1",
   570  				false,
   571  			},
   572  
   573  			{
   574  				`${signum(-29)}`,
   575  				"-1",
   576  				false,
   577  			},
   578  		},
   579  	})
   580  }
   581  
   582  func TestInterpolateFuncSplit(t *testing.T) {
   583  	testFunction(t, testFunctionConfig{
   584  		Cases: []testFunctionCase{
   585  			{
   586  				`${split(",")}`,
   587  				nil,
   588  				true,
   589  			},
   590  
   591  			{
   592  				`${split(",", "")}`,
   593  				NewStringList([]string{""}).String(),
   594  				false,
   595  			},
   596  
   597  			{
   598  				`${split(",", "foo")}`,
   599  				NewStringList([]string{"foo"}).String(),
   600  				false,
   601  			},
   602  
   603  			{
   604  				`${split(",", ",,,")}`,
   605  				NewStringList([]string{"", "", "", ""}).String(),
   606  				false,
   607  			},
   608  
   609  			{
   610  				`${split(",", "foo,")}`,
   611  				NewStringList([]string{"foo", ""}).String(),
   612  				false,
   613  			},
   614  
   615  			{
   616  				`${split(",", ",foo,")}`,
   617  				NewStringList([]string{"", "foo", ""}).String(),
   618  				false,
   619  			},
   620  
   621  			{
   622  				`${split(".", "foo.bar.baz")}`,
   623  				NewStringList([]string{"foo", "bar", "baz"}).String(),
   624  				false,
   625  			},
   626  		},
   627  	})
   628  }
   629  
   630  func TestInterpolateFuncLookup(t *testing.T) {
   631  	testFunction(t, testFunctionConfig{
   632  		Vars: map[string]ast.Variable{
   633  			"var.foo.bar": ast.Variable{
   634  				Value: "baz",
   635  				Type:  ast.TypeString,
   636  			},
   637  		},
   638  		Cases: []testFunctionCase{
   639  			{
   640  				`${lookup("foo", "bar")}`,
   641  				"baz",
   642  				false,
   643  			},
   644  
   645  			// Invalid key
   646  			{
   647  				`${lookup("foo", "baz")}`,
   648  				nil,
   649  				true,
   650  			},
   651  
   652  			// Too many args
   653  			{
   654  				`${lookup("foo", "bar", "baz")}`,
   655  				nil,
   656  				true,
   657  			},
   658  		},
   659  	})
   660  }
   661  
   662  func TestInterpolateFuncKeys(t *testing.T) {
   663  	testFunction(t, testFunctionConfig{
   664  		Vars: map[string]ast.Variable{
   665  			"var.foo.bar": ast.Variable{
   666  				Value: "baz",
   667  				Type:  ast.TypeString,
   668  			},
   669  			"var.foo.qux": ast.Variable{
   670  				Value: "quack",
   671  				Type:  ast.TypeString,
   672  			},
   673  			"var.str": ast.Variable{
   674  				Value: "astring",
   675  				Type:  ast.TypeString,
   676  			},
   677  		},
   678  		Cases: []testFunctionCase{
   679  			{
   680  				`${keys("foo")}`,
   681  				NewStringList([]string{"bar", "qux"}).String(),
   682  				false,
   683  			},
   684  
   685  			// Invalid key
   686  			{
   687  				`${keys("not")}`,
   688  				nil,
   689  				true,
   690  			},
   691  
   692  			// Too many args
   693  			{
   694  				`${keys("foo", "bar")}`,
   695  				nil,
   696  				true,
   697  			},
   698  
   699  			// Not a map
   700  			{
   701  				`${keys("str")}`,
   702  				nil,
   703  				true,
   704  			},
   705  		},
   706  	})
   707  }
   708  
   709  func TestInterpolateFuncValues(t *testing.T) {
   710  	testFunction(t, testFunctionConfig{
   711  		Vars: map[string]ast.Variable{
   712  			"var.foo.bar": ast.Variable{
   713  				Value: "quack",
   714  				Type:  ast.TypeString,
   715  			},
   716  			"var.foo.qux": ast.Variable{
   717  				Value: "baz",
   718  				Type:  ast.TypeString,
   719  			},
   720  			"var.str": ast.Variable{
   721  				Value: "astring",
   722  				Type:  ast.TypeString,
   723  			},
   724  		},
   725  		Cases: []testFunctionCase{
   726  			{
   727  				`${values("foo")}`,
   728  				NewStringList([]string{"quack", "baz"}).String(),
   729  				false,
   730  			},
   731  
   732  			// Invalid key
   733  			{
   734  				`${values("not")}`,
   735  				nil,
   736  				true,
   737  			},
   738  
   739  			// Too many args
   740  			{
   741  				`${values("foo", "bar")}`,
   742  				nil,
   743  				true,
   744  			},
   745  
   746  			// Not a map
   747  			{
   748  				`${values("str")}`,
   749  				nil,
   750  				true,
   751  			},
   752  		},
   753  	})
   754  }
   755  
   756  func TestInterpolateFuncElement(t *testing.T) {
   757  	testFunction(t, testFunctionConfig{
   758  		Cases: []testFunctionCase{
   759  			{
   760  				fmt.Sprintf(`${element("%s", "1")}`,
   761  					NewStringList([]string{"foo", "baz"}).String()),
   762  				"baz",
   763  				false,
   764  			},
   765  
   766  			{
   767  				fmt.Sprintf(`${element("%s", "0")}`,
   768  					NewStringList([]string{"foo"}).String()),
   769  				"foo",
   770  				false,
   771  			},
   772  
   773  			// Invalid index should wrap vs. out-of-bounds
   774  			{
   775  				fmt.Sprintf(`${element("%s", "2")}`,
   776  					NewStringList([]string{"foo", "baz"}).String()),
   777  				"foo",
   778  				false,
   779  			},
   780  
   781  			// Too many args
   782  			{
   783  				fmt.Sprintf(`${element("%s", "0", "2")}`,
   784  					NewStringList([]string{"foo", "baz"}).String()),
   785  				nil,
   786  				true,
   787  			},
   788  		},
   789  	})
   790  }
   791  
   792  func TestInterpolateFuncBase64Encode(t *testing.T) {
   793  	testFunction(t, testFunctionConfig{
   794  		Cases: []testFunctionCase{
   795  			// Regular base64 encoding
   796  			{
   797  				`${base64encode("abc123!?$*&()'-=@~")}`,
   798  				"YWJjMTIzIT8kKiYoKSctPUB+",
   799  				false,
   800  			},
   801  		},
   802  	})
   803  }
   804  
   805  func TestInterpolateFuncBase64Decode(t *testing.T) {
   806  	testFunction(t, testFunctionConfig{
   807  		Cases: []testFunctionCase{
   808  			// Regular base64 decoding
   809  			{
   810  				`${base64decode("YWJjMTIzIT8kKiYoKSctPUB+")}`,
   811  				"abc123!?$*&()'-=@~",
   812  				false,
   813  			},
   814  
   815  			// Invalid base64 data decoding
   816  			{
   817  				`${base64decode("this-is-an-invalid-base64-data")}`,
   818  				nil,
   819  				true,
   820  			},
   821  		},
   822  	})
   823  }
   824  
   825  func TestInterpolateFuncLower(t *testing.T) {
   826  	testFunction(t, testFunctionConfig{
   827  		Cases: []testFunctionCase{
   828  			{
   829  				`${lower("HELLO")}`,
   830  				"hello",
   831  				false,
   832  			},
   833  
   834  			{
   835  				`${lower("")}`,
   836  				"",
   837  				false,
   838  			},
   839  
   840  			{
   841  				`${lower()}`,
   842  				nil,
   843  				true,
   844  			},
   845  		},
   846  	})
   847  }
   848  
   849  func TestInterpolateFuncUpper(t *testing.T) {
   850  	testFunction(t, testFunctionConfig{
   851  		Cases: []testFunctionCase{
   852  			{
   853  				`${upper("hello")}`,
   854  				"HELLO",
   855  				false,
   856  			},
   857  
   858  			{
   859  				`${upper("")}`,
   860  				"",
   861  				false,
   862  			},
   863  
   864  			{
   865  				`${upper()}`,
   866  				nil,
   867  				true,
   868  			},
   869  		},
   870  	})
   871  }
   872  
   873  func TestInterpolateFuncSha1(t *testing.T) {
   874  	testFunction(t, testFunctionConfig{
   875  		Cases: []testFunctionCase{
   876  			{
   877  				`${sha1("test")}`,
   878  				"a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
   879  				false,
   880  			},
   881  		},
   882  	})
   883  }
   884  
   885  func TestInterpolateFuncSha256(t *testing.T) {
   886  	testFunction(t, testFunctionConfig{
   887  		Cases: []testFunctionCase{
   888  			{ // hexadecimal representation of sha256 sum
   889  				`${sha256("test")}`,
   890  				"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
   891  				false,
   892  			},
   893  		},
   894  	})
   895  }
   896  
   897  func TestInterpolateFuncTrimSpace(t *testing.T) {
   898  	testFunction(t, testFunctionConfig{
   899  		Cases: []testFunctionCase{
   900  			{
   901  				`${trimspace(" test ")}`,
   902  				"test",
   903  				false,
   904  			},
   905  		},
   906  	})
   907  }
   908  
   909  func TestInterpolateFuncBase64Sha256(t *testing.T) {
   910  	testFunction(t, testFunctionConfig{
   911  		Cases: []testFunctionCase{
   912  			{
   913  				`${base64sha256("test")}`,
   914  				"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=",
   915  				false,
   916  			},
   917  			{ // This will differ because we're base64-encoding hex represantiation, not raw bytes
   918  				`${base64encode(sha256("test"))}`,
   919  				"OWY4NmQwODE4ODRjN2Q2NTlhMmZlYWEwYzU1YWQwMTVhM2JmNGYxYjJiMGI4MjJjZDE1ZDZjMTViMGYwMGEwOA==",
   920  				false,
   921  			},
   922  		},
   923  	})
   924  }
   925  
   926  func TestInterpolateFuncMd5(t *testing.T) {
   927  	testFunction(t, testFunctionConfig{
   928  		Cases: []testFunctionCase{
   929  			{
   930  				`${md5("tada")}`,
   931  				"ce47d07243bb6eaf5e1322c81baf9bbf",
   932  				false,
   933  			},
   934  			{ // Confirm that we're not trimming any whitespaces
   935  				`${md5(" tada ")}`,
   936  				"aadf191a583e53062de2d02c008141c4",
   937  				false,
   938  			},
   939  			{ // We accept empty string too
   940  				`${md5("")}`,
   941  				"d41d8cd98f00b204e9800998ecf8427e",
   942  				false,
   943  			},
   944  		},
   945  	})
   946  }
   947  
   948  func TestInterpolateFuncUUID(t *testing.T) {
   949  	results := make(map[string]bool)
   950  
   951  	for i := 0; i < 100; i++ {
   952  		ast, err := hil.Parse("${uuid()}")
   953  		if err != nil {
   954  			t.Fatalf("err: %s", err)
   955  		}
   956  
   957  		out, _, err := hil.Eval(ast, langEvalConfig(nil))
   958  		if err != nil {
   959  			t.Fatalf("err: %s", err)
   960  		}
   961  
   962  		if results[out.(string)] {
   963  			t.Fatalf("Got unexpected duplicate uuid: %s", out)
   964  		}
   965  
   966  		results[out.(string)] = true
   967  	}
   968  }
   969  
   970  type testFunctionConfig struct {
   971  	Cases []testFunctionCase
   972  	Vars  map[string]ast.Variable
   973  }
   974  
   975  type testFunctionCase struct {
   976  	Input  string
   977  	Result interface{}
   978  	Error  bool
   979  }
   980  
   981  func testFunction(t *testing.T, config testFunctionConfig) {
   982  	for i, tc := range config.Cases {
   983  		ast, err := hil.Parse(tc.Input)
   984  		if err != nil {
   985  			t.Fatalf("Case #%d: input: %#v\nerr: %s", i, tc.Input, err)
   986  		}
   987  
   988  		out, _, err := hil.Eval(ast, langEvalConfig(config.Vars))
   989  		if err != nil != tc.Error {
   990  			t.Fatalf("Case #%d:\ninput: %#v\nerr: %s", i, tc.Input, err)
   991  		}
   992  
   993  		if !reflect.DeepEqual(out, tc.Result) {
   994  			t.Fatalf(
   995  				"%d: bad output for input: %s\n\nOutput: %#v\nExpected: %#v",
   996  				i, tc.Input, out, tc.Result)
   997  		}
   998  	}
   999  }