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 }