github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/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 TestFileBase64(t *testing.T) {
   228  	tests := []struct {
   229  		Path cty.Value
   230  		Want cty.Value
   231  		Err  bool
   232  	}{
   233  		{
   234  			cty.StringVal("testdata/hello.txt"),
   235  			cty.StringVal("SGVsbG8gV29ybGQ="),
   236  			false,
   237  		},
   238  		{
   239  			cty.StringVal("testdata/icon.png"),
   240  			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="),
   241  			false,
   242  		},
   243  		{
   244  			cty.StringVal("testdata/missing"),
   245  			cty.NilVal,
   246  			true, // no file exists
   247  		},
   248  	}
   249  
   250  	for _, test := range tests {
   251  		t.Run(fmt.Sprintf("FileBase64(\".\", %#v)", test.Path), func(t *testing.T) {
   252  			got, err := FileBase64(".", test.Path)
   253  
   254  			if test.Err {
   255  				if err == nil {
   256  					t.Fatal("succeeded; want error")
   257  				}
   258  				return
   259  			} else if err != nil {
   260  				t.Fatalf("unexpected error: %s", err)
   261  			}
   262  
   263  			if !got.RawEquals(test.Want) {
   264  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   265  			}
   266  		})
   267  	}
   268  }
   269  
   270  func TestBasename(t *testing.T) {
   271  	tests := []struct {
   272  		Path cty.Value
   273  		Want cty.Value
   274  		Err  bool
   275  	}{
   276  		{
   277  			cty.StringVal("testdata/hello.txt"),
   278  			cty.StringVal("hello.txt"),
   279  			false,
   280  		},
   281  		{
   282  			cty.StringVal("hello.txt"),
   283  			cty.StringVal("hello.txt"),
   284  			false,
   285  		},
   286  		{
   287  			cty.StringVal(""),
   288  			cty.StringVal("."),
   289  			false,
   290  		},
   291  	}
   292  
   293  	for _, test := range tests {
   294  		t.Run(fmt.Sprintf("Basename(%#v)", test.Path), func(t *testing.T) {
   295  			got, err := Basename(test.Path)
   296  
   297  			if test.Err {
   298  				if err == nil {
   299  					t.Fatal("succeeded; want error")
   300  				}
   301  				return
   302  			} else if err != nil {
   303  				t.Fatalf("unexpected error: %s", err)
   304  			}
   305  
   306  			if !got.RawEquals(test.Want) {
   307  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   308  			}
   309  		})
   310  	}
   311  }
   312  
   313  func TestDirname(t *testing.T) {
   314  	tests := []struct {
   315  		Path cty.Value
   316  		Want cty.Value
   317  		Err  bool
   318  	}{
   319  		{
   320  			cty.StringVal("testdata/hello.txt"),
   321  			cty.StringVal("testdata"),
   322  			false,
   323  		},
   324  		{
   325  			cty.StringVal("testdata/foo/hello.txt"),
   326  			cty.StringVal("testdata/foo"),
   327  			false,
   328  		},
   329  		{
   330  			cty.StringVal("hello.txt"),
   331  			cty.StringVal("."),
   332  			false,
   333  		},
   334  		{
   335  			cty.StringVal(""),
   336  			cty.StringVal("."),
   337  			false,
   338  		},
   339  	}
   340  
   341  	for _, test := range tests {
   342  		t.Run(fmt.Sprintf("Dirname(%#v)", test.Path), func(t *testing.T) {
   343  			got, err := Dirname(test.Path)
   344  
   345  			if test.Err {
   346  				if err == nil {
   347  					t.Fatal("succeeded; want error")
   348  				}
   349  				return
   350  			} else if err != nil {
   351  				t.Fatalf("unexpected error: %s", err)
   352  			}
   353  
   354  			if !got.RawEquals(test.Want) {
   355  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   356  			}
   357  		})
   358  	}
   359  }
   360  
   361  func TestPathExpand(t *testing.T) {
   362  	homePath, err := homedir.Dir()
   363  	if err != nil {
   364  		t.Fatalf("Error getting home directory: %v", err)
   365  	}
   366  
   367  	tests := []struct {
   368  		Path cty.Value
   369  		Want cty.Value
   370  		Err  bool
   371  	}{
   372  		{
   373  			cty.StringVal("~/test-file"),
   374  			cty.StringVal(filepath.Join(homePath, "test-file")),
   375  			false,
   376  		},
   377  		{
   378  			cty.StringVal("~/another/test/file"),
   379  			cty.StringVal(filepath.Join(homePath, "another/test/file")),
   380  			false,
   381  		},
   382  		{
   383  			cty.StringVal("/root/file"),
   384  			cty.StringVal("/root/file"),
   385  			false,
   386  		},
   387  		{
   388  			cty.StringVal("/"),
   389  			cty.StringVal("/"),
   390  			false,
   391  		},
   392  	}
   393  
   394  	for _, test := range tests {
   395  		t.Run(fmt.Sprintf("Dirname(%#v)", test.Path), func(t *testing.T) {
   396  			got, err := Pathexpand(test.Path)
   397  
   398  			if test.Err {
   399  				if err == nil {
   400  					t.Fatal("succeeded; want error")
   401  				}
   402  				return
   403  			} else if err != nil {
   404  				t.Fatalf("unexpected error: %s", err)
   405  			}
   406  
   407  			if !got.RawEquals(test.Want) {
   408  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   409  			}
   410  		})
   411  	}
   412  }