github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/lang/funcs/filesystem_test.go (about)

     1  package funcs
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  	"testing"
     7  
     8  	homedir "github.com/mitchellh/go-homedir"
     9  	"github.com/zclconf/go-cty/cty"
    10  	"github.com/zclconf/go-cty/cty/function"
    11  )
    12  
    13  func TestFile(t *testing.T) {
    14  	tests := []struct {
    15  		Path cty.Value
    16  		Want cty.Value
    17  		Err  bool
    18  	}{
    19  		{
    20  			cty.StringVal("testdata/hello.txt"),
    21  			cty.StringVal("Hello World"),
    22  			false,
    23  		},
    24  		{
    25  			cty.StringVal("testdata/icon.png"),
    26  			cty.NilVal,
    27  			true, // Not valid UTF-8
    28  		},
    29  		{
    30  			cty.StringVal("testdata/missing"),
    31  			cty.NilVal,
    32  			true, // no file exists
    33  		},
    34  	}
    35  
    36  	for _, test := range tests {
    37  		t.Run(fmt.Sprintf("File(\".\", %#v)", test.Path), func(t *testing.T) {
    38  			got, err := File(".", test.Path)
    39  
    40  			if test.Err {
    41  				if err == nil {
    42  					t.Fatal("succeeded; want error")
    43  				}
    44  				return
    45  			} else if err != nil {
    46  				t.Fatalf("unexpected error: %s", err)
    47  			}
    48  
    49  			if !got.RawEquals(test.Want) {
    50  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
    51  			}
    52  		})
    53  	}
    54  }
    55  
    56  func TestTemplateFile(t *testing.T) {
    57  	tests := []struct {
    58  		Path cty.Value
    59  		Vars cty.Value
    60  		Want cty.Value
    61  		Err  bool
    62  	}{
    63  		{
    64  			cty.StringVal("testdata/hello.txt"),
    65  			cty.EmptyObjectVal,
    66  			cty.StringVal("Hello World"),
    67  			false,
    68  		},
    69  		{
    70  			cty.StringVal("testdata/icon.png"),
    71  			cty.EmptyObjectVal,
    72  			cty.NilVal,
    73  			true, // Not valid UTF-8
    74  		},
    75  		{
    76  			cty.StringVal("testdata/missing"),
    77  			cty.EmptyObjectVal,
    78  			cty.NilVal,
    79  			true, // no file exists
    80  		},
    81  		{
    82  			cty.StringVal("testdata/hello.tmpl"),
    83  			cty.MapVal(map[string]cty.Value{
    84  				"name": cty.StringVal("Jodie"),
    85  			}),
    86  			cty.StringVal("Hello, Jodie!"),
    87  			false,
    88  		},
    89  		{
    90  			cty.StringVal("testdata/hello.tmpl"),
    91  			cty.ObjectVal(map[string]cty.Value{
    92  				"name": cty.StringVal("Jimbo"),
    93  			}),
    94  			cty.StringVal("Hello, Jimbo!"),
    95  			false,
    96  		},
    97  		{
    98  			cty.StringVal("testdata/hello.tmpl"),
    99  			cty.EmptyObjectVal,
   100  			cty.NilVal,
   101  			true, // "name" is missing from the vars map
   102  		},
   103  		{
   104  			cty.StringVal("testdata/func.tmpl"),
   105  			cty.ObjectVal(map[string]cty.Value{
   106  				"list": cty.ListVal([]cty.Value{
   107  					cty.StringVal("a"),
   108  					cty.StringVal("b"),
   109  					cty.StringVal("c"),
   110  				}),
   111  			}),
   112  			cty.StringVal("The items are a, b, c"),
   113  			false,
   114  		},
   115  		{
   116  			cty.StringVal("testdata/recursive.tmpl"),
   117  			cty.MapValEmpty(cty.String),
   118  			cty.NilVal,
   119  			true, // recursive templatefile call not allowed
   120  		},
   121  		{
   122  			cty.StringVal("testdata/list.tmpl"),
   123  			cty.ObjectVal(map[string]cty.Value{
   124  				"list": cty.ListVal([]cty.Value{
   125  					cty.StringVal("a"),
   126  					cty.StringVal("b"),
   127  					cty.StringVal("c"),
   128  				}),
   129  			}),
   130  			cty.StringVal("- a\n- b\n- c\n"),
   131  			false,
   132  		},
   133  		{
   134  			cty.StringVal("testdata/list.tmpl"),
   135  			cty.ObjectVal(map[string]cty.Value{
   136  				"list": cty.True,
   137  			}),
   138  			cty.NilVal,
   139  			true, // iteration over non-iterable value
   140  		},
   141  		{
   142  			cty.StringVal("testdata/bare.tmpl"),
   143  			cty.ObjectVal(map[string]cty.Value{
   144  				"val": cty.True,
   145  			}),
   146  			cty.True, // since this template contains only an interpolation, its true value shines through
   147  			false,
   148  		},
   149  	}
   150  
   151  	templateFileFn := MakeTemplateFileFunc(".", func() map[string]function.Function {
   152  		return map[string]function.Function{
   153  			"join":         JoinFunc,
   154  			"templatefile": MakeFileFunc(".", false), // just a placeholder, since templatefile itself overrides this
   155  		}
   156  	})
   157  
   158  	for _, test := range tests {
   159  		t.Run(fmt.Sprintf("TemplateFile(%#v, %#v)", test.Path, test.Vars), func(t *testing.T) {
   160  			got, err := templateFileFn.Call([]cty.Value{test.Path, test.Vars})
   161  
   162  			if argErr, ok := err.(function.ArgError); ok {
   163  				if argErr.Index < 0 || argErr.Index > 1 {
   164  					t.Errorf("ArgError index %d is out of range for templatefile (must be 0 or 1)", argErr.Index)
   165  				}
   166  			}
   167  
   168  			if test.Err {
   169  				if err == nil {
   170  					t.Fatal("succeeded; want error")
   171  				}
   172  				return
   173  			} else if err != nil {
   174  				t.Fatalf("unexpected error: %s", err)
   175  			}
   176  
   177  			if !got.RawEquals(test.Want) {
   178  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   179  			}
   180  		})
   181  	}
   182  }
   183  
   184  func TestFileExists(t *testing.T) {
   185  	tests := []struct {
   186  		Path cty.Value
   187  		Want cty.Value
   188  		Err  bool
   189  	}{
   190  		{
   191  			cty.StringVal("testdata/hello.txt"),
   192  			cty.BoolVal(true),
   193  			false,
   194  		},
   195  		{
   196  			cty.StringVal(""), // empty path
   197  			cty.BoolVal(false),
   198  			true,
   199  		},
   200  		{
   201  			cty.StringVal("testdata/missing"),
   202  			cty.BoolVal(false),
   203  			false, // no file exists
   204  		},
   205  	}
   206  
   207  	for _, test := range tests {
   208  		t.Run(fmt.Sprintf("FileExists(\".\", %#v)", test.Path), func(t *testing.T) {
   209  			got, err := FileExists(".", test.Path)
   210  
   211  			if test.Err {
   212  				if err == nil {
   213  					t.Fatal("succeeded; want error")
   214  				}
   215  				return
   216  			} else if err != nil {
   217  				t.Fatalf("unexpected error: %s", err)
   218  			}
   219  
   220  			if !got.RawEquals(test.Want) {
   221  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   222  			}
   223  		})
   224  	}
   225  }
   226  
   227  func TestFileSet(t *testing.T) {
   228  	tests := []struct {
   229  		Path    cty.Value
   230  		Pattern cty.Value
   231  		Want    cty.Value
   232  		Err     bool
   233  	}{
   234  		{
   235  			cty.StringVal("."),
   236  			cty.StringVal("testdata*"),
   237  			cty.SetValEmpty(cty.String),
   238  			false,
   239  		},
   240  		{
   241  			cty.StringVal("."),
   242  			cty.StringVal("testdata"),
   243  			cty.SetValEmpty(cty.String),
   244  			false,
   245  		},
   246  		{
   247  			cty.StringVal("."),
   248  			cty.StringVal("{testdata,missing}"),
   249  			cty.SetValEmpty(cty.String),
   250  			false,
   251  		},
   252  		{
   253  			cty.StringVal("."),
   254  			cty.StringVal("testdata/missing"),
   255  			cty.SetValEmpty(cty.String),
   256  			false,
   257  		},
   258  		{
   259  			cty.StringVal("."),
   260  			cty.StringVal("testdata/missing*"),
   261  			cty.SetValEmpty(cty.String),
   262  			false,
   263  		},
   264  		{
   265  			cty.StringVal("."),
   266  			cty.StringVal("*/missing"),
   267  			cty.SetValEmpty(cty.String),
   268  			false,
   269  		},
   270  		{
   271  			cty.StringVal("."),
   272  			cty.StringVal("**/missing"),
   273  			cty.SetValEmpty(cty.String),
   274  			false,
   275  		},
   276  		{
   277  			cty.StringVal("."),
   278  			cty.StringVal("testdata/*.txt"),
   279  			cty.SetVal([]cty.Value{
   280  				cty.StringVal("testdata/hello.txt"),
   281  			}),
   282  			false,
   283  		},
   284  		{
   285  			cty.StringVal("."),
   286  			cty.StringVal("testdata/hello.txt"),
   287  			cty.SetVal([]cty.Value{
   288  				cty.StringVal("testdata/hello.txt"),
   289  			}),
   290  			false,
   291  		},
   292  		{
   293  			cty.StringVal("."),
   294  			cty.StringVal("testdata/hello.???"),
   295  			cty.SetVal([]cty.Value{
   296  				cty.StringVal("testdata/hello.txt"),
   297  			}),
   298  			false,
   299  		},
   300  		{
   301  			cty.StringVal("."),
   302  			cty.StringVal("testdata/hello*"),
   303  			cty.SetVal([]cty.Value{
   304  				cty.StringVal("testdata/hello.tmpl"),
   305  				cty.StringVal("testdata/hello.txt"),
   306  			}),
   307  			false,
   308  		},
   309  		{
   310  			cty.StringVal("."),
   311  			cty.StringVal("testdata/hello.{tmpl,txt}"),
   312  			cty.SetVal([]cty.Value{
   313  				cty.StringVal("testdata/hello.tmpl"),
   314  				cty.StringVal("testdata/hello.txt"),
   315  			}),
   316  			false,
   317  		},
   318  		{
   319  			cty.StringVal("."),
   320  			cty.StringVal("*/hello.txt"),
   321  			cty.SetVal([]cty.Value{
   322  				cty.StringVal("testdata/hello.txt"),
   323  			}),
   324  			false,
   325  		},
   326  		{
   327  			cty.StringVal("."),
   328  			cty.StringVal("*/*.txt"),
   329  			cty.SetVal([]cty.Value{
   330  				cty.StringVal("testdata/hello.txt"),
   331  			}),
   332  			false,
   333  		},
   334  		{
   335  			cty.StringVal("."),
   336  			cty.StringVal("*/hello*"),
   337  			cty.SetVal([]cty.Value{
   338  				cty.StringVal("testdata/hello.tmpl"),
   339  				cty.StringVal("testdata/hello.txt"),
   340  			}),
   341  			false,
   342  		},
   343  		{
   344  			cty.StringVal("."),
   345  			cty.StringVal("**/hello*"),
   346  			cty.SetVal([]cty.Value{
   347  				cty.StringVal("testdata/hello.tmpl"),
   348  				cty.StringVal("testdata/hello.txt"),
   349  			}),
   350  			false,
   351  		},
   352  		{
   353  			cty.StringVal("."),
   354  			cty.StringVal("**/hello.{tmpl,txt}"),
   355  			cty.SetVal([]cty.Value{
   356  				cty.StringVal("testdata/hello.tmpl"),
   357  				cty.StringVal("testdata/hello.txt"),
   358  			}),
   359  			false,
   360  		},
   361  		{
   362  			cty.StringVal("."),
   363  			cty.StringVal("["),
   364  			cty.SetValEmpty(cty.String),
   365  			true,
   366  		},
   367  		{
   368  			cty.StringVal("."),
   369  			cty.StringVal("\\"),
   370  			cty.SetValEmpty(cty.String),
   371  			true,
   372  		},
   373  		{
   374  			cty.StringVal("testdata"),
   375  			cty.StringVal("missing"),
   376  			cty.SetValEmpty(cty.String),
   377  			false,
   378  		},
   379  		{
   380  			cty.StringVal("testdata"),
   381  			cty.StringVal("missing*"),
   382  			cty.SetValEmpty(cty.String),
   383  			false,
   384  		},
   385  		{
   386  			cty.StringVal("testdata"),
   387  			cty.StringVal("*.txt"),
   388  			cty.SetVal([]cty.Value{
   389  				cty.StringVal("hello.txt"),
   390  			}),
   391  			false,
   392  		},
   393  		{
   394  			cty.StringVal("testdata"),
   395  			cty.StringVal("hello.txt"),
   396  			cty.SetVal([]cty.Value{
   397  				cty.StringVal("hello.txt"),
   398  			}),
   399  			false,
   400  		},
   401  		{
   402  			cty.StringVal("testdata"),
   403  			cty.StringVal("hello.???"),
   404  			cty.SetVal([]cty.Value{
   405  				cty.StringVal("hello.txt"),
   406  			}),
   407  			false,
   408  		},
   409  		{
   410  			cty.StringVal("testdata"),
   411  			cty.StringVal("hello*"),
   412  			cty.SetVal([]cty.Value{
   413  				cty.StringVal("hello.tmpl"),
   414  				cty.StringVal("hello.txt"),
   415  			}),
   416  			false,
   417  		},
   418  	}
   419  
   420  	for _, test := range tests {
   421  		t.Run(fmt.Sprintf("FileSet(\".\", %#v, %#v)", test.Path, test.Pattern), func(t *testing.T) {
   422  			got, err := FileSet(".", test.Path, test.Pattern)
   423  
   424  			if test.Err {
   425  				if err == nil {
   426  					t.Fatal("succeeded; want error")
   427  				}
   428  				return
   429  			} else if err != nil {
   430  				t.Fatalf("unexpected error: %s", err)
   431  			}
   432  
   433  			if !got.RawEquals(test.Want) {
   434  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   435  			}
   436  		})
   437  	}
   438  }
   439  
   440  func TestFileBase64(t *testing.T) {
   441  	tests := []struct {
   442  		Path cty.Value
   443  		Want cty.Value
   444  		Err  bool
   445  	}{
   446  		{
   447  			cty.StringVal("testdata/hello.txt"),
   448  			cty.StringVal("SGVsbG8gV29ybGQ="),
   449  			false,
   450  		},
   451  		{
   452  			cty.StringVal("testdata/icon.png"),
   453  			cty.StringVal("iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAq1BMVEX///9cTuVeUeRcTuZcTuZcT+VbSe1cTuVdT+MAAP9JSbZcT+VcTuZAQLFAQLJcTuVcTuZcUuBBQbA/P7JAQLJaTuRcT+RcTuVGQ7xAQLJVVf9cTuVcTuVGRMFeUeRbTeJcTuU/P7JeTeZbTOVcTeZAQLJBQbNAQLNaUORcTeZbT+VcTuRAQLNAQLRdTuRHR8xgUOdgUN9cTuVdTeRdT+VZTulcTuVAQLL///8+GmETAAAANnRSTlMApibw+osO6DcBB3fIX87+oRk3yehB0/Nj/gNs7nsTRv3dHmu//JYUMLVr3bssjxkgEK5CaxeK03nIAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAADoQAAA6EBvJf9gwAAAAd0SU1FB+EEBRIQDxZNTKsAAACCSURBVBjTfc7JFsFQEATQQpCYxyBEzJ55rvf/f0ZHcyQLvelTd1GngEwWycs5+UISyKLraSi9geWKK9Gr1j7AeqOJVtt2XtD1Bchef2BjQDAcCTC0CsA4mihMtXw2XwgsV2sFw812F+4P3y2GdI6nn3FGSs//4HJNAXDzU4Dg/oj/E+bsEbhf5cMsAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTA0LTA1VDE4OjE2OjE1KzAyOjAws5bLVQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wNC0wNVQxODoxNjoxNSswMjowMMLLc+kAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAC3RFWHRUaXRsZQBHcm91cJYfIowAAABXelRYdFJhdyBwcm9maWxlIHR5cGUgaXB0YwAAeJzj8gwIcVYoKMpPy8xJ5VIAAyMLLmMLEyMTS5MUAxMgRIA0w2QDI7NUIMvY1MjEzMQcxAfLgEigSi4A6hcRdPJCNZUAAAAASUVORK5CYII="),
   454  			false,
   455  		},
   456  		{
   457  			cty.StringVal("testdata/missing"),
   458  			cty.NilVal,
   459  			true, // no file exists
   460  		},
   461  	}
   462  
   463  	for _, test := range tests {
   464  		t.Run(fmt.Sprintf("FileBase64(\".\", %#v)", test.Path), func(t *testing.T) {
   465  			got, err := FileBase64(".", test.Path)
   466  
   467  			if test.Err {
   468  				if err == nil {
   469  					t.Fatal("succeeded; want error")
   470  				}
   471  				return
   472  			} else if err != nil {
   473  				t.Fatalf("unexpected error: %s", err)
   474  			}
   475  
   476  			if !got.RawEquals(test.Want) {
   477  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   478  			}
   479  		})
   480  	}
   481  }
   482  
   483  func TestBasename(t *testing.T) {
   484  	tests := []struct {
   485  		Path cty.Value
   486  		Want cty.Value
   487  		Err  bool
   488  	}{
   489  		{
   490  			cty.StringVal("testdata/hello.txt"),
   491  			cty.StringVal("hello.txt"),
   492  			false,
   493  		},
   494  		{
   495  			cty.StringVal("hello.txt"),
   496  			cty.StringVal("hello.txt"),
   497  			false,
   498  		},
   499  		{
   500  			cty.StringVal(""),
   501  			cty.StringVal("."),
   502  			false,
   503  		},
   504  	}
   505  
   506  	for _, test := range tests {
   507  		t.Run(fmt.Sprintf("Basename(%#v)", test.Path), func(t *testing.T) {
   508  			got, err := Basename(test.Path)
   509  
   510  			if test.Err {
   511  				if err == nil {
   512  					t.Fatal("succeeded; want error")
   513  				}
   514  				return
   515  			} else if err != nil {
   516  				t.Fatalf("unexpected error: %s", err)
   517  			}
   518  
   519  			if !got.RawEquals(test.Want) {
   520  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   521  			}
   522  		})
   523  	}
   524  }
   525  
   526  func TestDirname(t *testing.T) {
   527  	tests := []struct {
   528  		Path cty.Value
   529  		Want cty.Value
   530  		Err  bool
   531  	}{
   532  		{
   533  			cty.StringVal("testdata/hello.txt"),
   534  			cty.StringVal("testdata"),
   535  			false,
   536  		},
   537  		{
   538  			cty.StringVal("testdata/foo/hello.txt"),
   539  			cty.StringVal("testdata/foo"),
   540  			false,
   541  		},
   542  		{
   543  			cty.StringVal("hello.txt"),
   544  			cty.StringVal("."),
   545  			false,
   546  		},
   547  		{
   548  			cty.StringVal(""),
   549  			cty.StringVal("."),
   550  			false,
   551  		},
   552  	}
   553  
   554  	for _, test := range tests {
   555  		t.Run(fmt.Sprintf("Dirname(%#v)", test.Path), func(t *testing.T) {
   556  			got, err := Dirname(test.Path)
   557  
   558  			if test.Err {
   559  				if err == nil {
   560  					t.Fatal("succeeded; want error")
   561  				}
   562  				return
   563  			} else if err != nil {
   564  				t.Fatalf("unexpected error: %s", err)
   565  			}
   566  
   567  			if !got.RawEquals(test.Want) {
   568  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   569  			}
   570  		})
   571  	}
   572  }
   573  
   574  func TestPathExpand(t *testing.T) {
   575  	homePath, err := homedir.Dir()
   576  	if err != nil {
   577  		t.Fatalf("Error getting home directory: %v", err)
   578  	}
   579  
   580  	tests := []struct {
   581  		Path cty.Value
   582  		Want cty.Value
   583  		Err  bool
   584  	}{
   585  		{
   586  			cty.StringVal("~/test-file"),
   587  			cty.StringVal(filepath.Join(homePath, "test-file")),
   588  			false,
   589  		},
   590  		{
   591  			cty.StringVal("~/another/test/file"),
   592  			cty.StringVal(filepath.Join(homePath, "another/test/file")),
   593  			false,
   594  		},
   595  		{
   596  			cty.StringVal("/root/file"),
   597  			cty.StringVal("/root/file"),
   598  			false,
   599  		},
   600  		{
   601  			cty.StringVal("/"),
   602  			cty.StringVal("/"),
   603  			false,
   604  		},
   605  	}
   606  
   607  	for _, test := range tests {
   608  		t.Run(fmt.Sprintf("Dirname(%#v)", test.Path), func(t *testing.T) {
   609  			got, err := Pathexpand(test.Path)
   610  
   611  			if test.Err {
   612  				if err == nil {
   613  					t.Fatal("succeeded; want error")
   614  				}
   615  				return
   616  			} else if err != nil {
   617  				t.Fatalf("unexpected error: %s", err)
   618  			}
   619  
   620  			if !got.RawEquals(test.Want) {
   621  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   622  			}
   623  		})
   624  	}
   625  }