mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Previously we were just returning a string representation of the file mode, which spends more characters on the irrelevant permission bits that it does on the directory entry type, and is presented in a Unix-centric format that likely won't be familiar to the user of a Windows system. Instead, we'll recognize a few specific directory entry types that seem worth mentioning by name, and then use a generic message for the rest. The original motivation here was actually to deal with the fact that our tests for this function were previously not portable due to the error message leaking system-specific permission detail that are not relevant to the test. Rather than just directly addressing that portability problem, I took the opportunity to improve the error messages at the same time. However, because of that initial focus there are only actually tests here for the directory case. A test that tries to test any of these other file modes would not be portable and in some cases would require superuser access, so we'll just leave those cases untested for the moment since they weren't tested before anyway, and so we've not _lost_ any test coverage here.
696 lines
17 KiB
Go
696 lines
17 KiB
Go
package funcs
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/terraform/internal/lang/marks"
|
|
homedir "github.com/mitchellh/go-homedir"
|
|
"github.com/zclconf/go-cty/cty"
|
|
"github.com/zclconf/go-cty/cty/function"
|
|
"github.com/zclconf/go-cty/cty/function/stdlib"
|
|
)
|
|
|
|
func TestFile(t *testing.T) {
|
|
tests := []struct {
|
|
Path cty.Value
|
|
Want cty.Value
|
|
Err string
|
|
}{
|
|
{
|
|
cty.StringVal("testdata/hello.txt"),
|
|
cty.StringVal("Hello World"),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/icon.png"),
|
|
cty.NilVal,
|
|
`contents of "testdata/icon.png" are not valid UTF-8; use the filebase64 function to obtain the Base64 encoded contents or the other file functions (e.g. filemd5, filesha256) to obtain file hashing results instead`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/icon.png").Mark(marks.Sensitive),
|
|
cty.NilVal,
|
|
`contents of (sensitive value) are not valid UTF-8; use the filebase64 function to obtain the Base64 encoded contents or the other file functions (e.g. filemd5, filesha256) to obtain file hashing results instead`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/missing"),
|
|
cty.NilVal,
|
|
`no file exists at "testdata/missing"; this function works only with files that are distributed as part of the configuration source code, so if this file will be created by a resource in this configuration you must instead obtain this result from an attribute of that resource`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/missing").Mark(marks.Sensitive),
|
|
cty.NilVal,
|
|
`no file exists at (sensitive value); this function works only with files that are distributed as part of the configuration source code, so if this file will be created by a resource in this configuration you must instead obtain this result from an attribute of that resource`,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("File(\".\", %#v)", test.Path), func(t *testing.T) {
|
|
got, err := File(".", test.Path)
|
|
|
|
if test.Err != "" {
|
|
if err == nil {
|
|
t.Fatal("succeeded; want error")
|
|
}
|
|
if got, want := err.Error(), test.Err; got != want {
|
|
t.Errorf("wrong error\ngot: %s\nwant: %s", got, want)
|
|
}
|
|
return
|
|
} else if err != nil {
|
|
t.Fatalf("unexpected error: %s", err)
|
|
}
|
|
|
|
if !got.RawEquals(test.Want) {
|
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTemplateFile(t *testing.T) {
|
|
tests := []struct {
|
|
Path cty.Value
|
|
Vars cty.Value
|
|
Want cty.Value
|
|
Err string
|
|
}{
|
|
{
|
|
cty.StringVal("testdata/hello.txt"),
|
|
cty.EmptyObjectVal,
|
|
cty.StringVal("Hello World"),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/icon.png"),
|
|
cty.EmptyObjectVal,
|
|
cty.NilVal,
|
|
`contents of "testdata/icon.png" are not valid UTF-8; use the filebase64 function to obtain the Base64 encoded contents or the other file functions (e.g. filemd5, filesha256) to obtain file hashing results instead`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/missing"),
|
|
cty.EmptyObjectVal,
|
|
cty.NilVal,
|
|
`no file exists at "testdata/missing"; this function works only with files that are distributed as part of the configuration source code, so if this file will be created by a resource in this configuration you must instead obtain this result from an attribute of that resource`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/secrets.txt").Mark(marks.Sensitive),
|
|
cty.EmptyObjectVal,
|
|
cty.NilVal,
|
|
`no file exists at (sensitive value); this function works only with files that are distributed as part of the configuration source code, so if this file will be created by a resource in this configuration you must instead obtain this result from an attribute of that resource`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/hello.tmpl"),
|
|
cty.MapVal(map[string]cty.Value{
|
|
"name": cty.StringVal("Jodie"),
|
|
}),
|
|
cty.StringVal("Hello, Jodie!"),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/hello.tmpl"),
|
|
cty.MapVal(map[string]cty.Value{
|
|
"name!": cty.StringVal("Jodie"),
|
|
}),
|
|
cty.NilVal,
|
|
`invalid template variable name "name!": must start with a letter, followed by zero or more letters, digits, and underscores`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/hello.tmpl"),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"name": cty.StringVal("Jimbo"),
|
|
}),
|
|
cty.StringVal("Hello, Jimbo!"),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/hello.tmpl"),
|
|
cty.EmptyObjectVal,
|
|
cty.NilVal,
|
|
`vars map does not contain key "name", referenced at testdata/hello.tmpl:1,10-14`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/func.tmpl"),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"list": cty.ListVal([]cty.Value{
|
|
cty.StringVal("a"),
|
|
cty.StringVal("b"),
|
|
cty.StringVal("c"),
|
|
}),
|
|
}),
|
|
cty.StringVal("The items are a, b, c"),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/recursive.tmpl"),
|
|
cty.MapValEmpty(cty.String),
|
|
cty.NilVal,
|
|
`testdata/recursive.tmpl:1,3-16: Error in function call; Call to function "templatefile" failed: cannot recursively call templatefile from inside templatefile call.`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/list.tmpl"),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"list": cty.ListVal([]cty.Value{
|
|
cty.StringVal("a"),
|
|
cty.StringVal("b"),
|
|
cty.StringVal("c"),
|
|
}),
|
|
}),
|
|
cty.StringVal("- a\n- b\n- c\n"),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/list.tmpl"),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"list": cty.True,
|
|
}),
|
|
cty.NilVal,
|
|
`testdata/list.tmpl:1,13-17: Iteration over non-iterable value; A value of type bool cannot be used as the collection in a 'for' expression.`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/bare.tmpl"),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"val": cty.True,
|
|
}),
|
|
cty.True, // since this template contains only an interpolation, its true value shines through
|
|
``,
|
|
},
|
|
}
|
|
|
|
templateFileFn := MakeTemplateFileFunc(".", func() map[string]function.Function {
|
|
return map[string]function.Function{
|
|
"join": stdlib.JoinFunc,
|
|
"templatefile": MakeFileFunc(".", false), // just a placeholder, since templatefile itself overrides this
|
|
}
|
|
})
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("TemplateFile(%#v, %#v)", test.Path, test.Vars), func(t *testing.T) {
|
|
got, err := templateFileFn.Call([]cty.Value{test.Path, test.Vars})
|
|
|
|
if argErr, ok := err.(function.ArgError); ok {
|
|
if argErr.Index < 0 || argErr.Index > 1 {
|
|
t.Errorf("ArgError index %d is out of range for templatefile (must be 0 or 1)", argErr.Index)
|
|
}
|
|
}
|
|
|
|
if test.Err != "" {
|
|
if err == nil {
|
|
t.Fatal("succeeded; want error")
|
|
}
|
|
if got, want := err.Error(), test.Err; got != want {
|
|
t.Errorf("wrong error\ngot: %s\nwant: %s", got, want)
|
|
}
|
|
return
|
|
} else if err != nil {
|
|
t.Fatalf("unexpected error: %s", err)
|
|
}
|
|
|
|
if !got.RawEquals(test.Want) {
|
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFileExists(t *testing.T) {
|
|
tests := []struct {
|
|
Path cty.Value
|
|
Want cty.Value
|
|
Err string
|
|
}{
|
|
{
|
|
cty.StringVal("testdata/hello.txt"),
|
|
cty.BoolVal(true),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal(""),
|
|
cty.BoolVal(false),
|
|
`"." is a directory, not a file`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata").Mark(marks.Sensitive),
|
|
cty.BoolVal(false),
|
|
`(sensitive value) is a directory, not a file`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/missing"),
|
|
cty.BoolVal(false),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/unreadable/foobar"),
|
|
cty.BoolVal(false),
|
|
`failed to stat "testdata/unreadable/foobar"`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/unreadable/foobar").Mark(marks.Sensitive),
|
|
cty.BoolVal(false),
|
|
`failed to stat (sensitive value)`,
|
|
},
|
|
}
|
|
|
|
// Ensure "unreadable" directory cannot be listed during the test run
|
|
fi, err := os.Lstat("testdata/unreadable")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
os.Chmod("testdata/unreadable", 0000)
|
|
defer func(mode os.FileMode) {
|
|
os.Chmod("testdata/unreadable", mode)
|
|
}(fi.Mode())
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("FileExists(\".\", %#v)", test.Path), func(t *testing.T) {
|
|
got, err := FileExists(".", test.Path)
|
|
|
|
if test.Err != "" {
|
|
if err == nil {
|
|
t.Fatal("succeeded; want error")
|
|
}
|
|
if got, want := err.Error(), test.Err; got != want {
|
|
t.Errorf("wrong error\ngot: %s\nwant: %s", got, want)
|
|
}
|
|
return
|
|
} else if err != nil {
|
|
t.Fatalf("unexpected error: %s", err)
|
|
}
|
|
|
|
if !got.RawEquals(test.Want) {
|
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFileSet(t *testing.T) {
|
|
tests := []struct {
|
|
Path cty.Value
|
|
Pattern cty.Value
|
|
Want cty.Value
|
|
Err string
|
|
}{
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("testdata*"),
|
|
cty.SetValEmpty(cty.String),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("testdata"),
|
|
cty.SetValEmpty(cty.String),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("{testdata,missing}"),
|
|
cty.SetValEmpty(cty.String),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("testdata/missing"),
|
|
cty.SetValEmpty(cty.String),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("testdata/missing*"),
|
|
cty.SetValEmpty(cty.String),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("*/missing"),
|
|
cty.SetValEmpty(cty.String),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("**/missing"),
|
|
cty.SetValEmpty(cty.String),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("testdata/*.txt"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("testdata/hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("testdata/hello.txt"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("testdata/hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("testdata/hello.???"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("testdata/hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("testdata/hello*"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("testdata/hello.tmpl"),
|
|
cty.StringVal("testdata/hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("testdata/hello.{tmpl,txt}"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("testdata/hello.tmpl"),
|
|
cty.StringVal("testdata/hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("*/hello.txt"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("testdata/hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("*/*.txt"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("testdata/hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("*/hello*"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("testdata/hello.tmpl"),
|
|
cty.StringVal("testdata/hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("**/hello*"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("testdata/hello.tmpl"),
|
|
cty.StringVal("testdata/hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("**/hello.{tmpl,txt}"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("testdata/hello.tmpl"),
|
|
cty.StringVal("testdata/hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("["),
|
|
cty.SetValEmpty(cty.String),
|
|
`failed to glob pattern "[": syntax error in pattern`,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("[").Mark(marks.Sensitive),
|
|
cty.SetValEmpty(cty.String),
|
|
`failed to glob pattern (sensitive value): syntax error in pattern`,
|
|
},
|
|
{
|
|
cty.StringVal("."),
|
|
cty.StringVal("\\"),
|
|
cty.SetValEmpty(cty.String),
|
|
`failed to glob pattern "\\": syntax error in pattern`,
|
|
},
|
|
{
|
|
cty.StringVal("testdata"),
|
|
cty.StringVal("missing"),
|
|
cty.SetValEmpty(cty.String),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("testdata"),
|
|
cty.StringVal("missing*"),
|
|
cty.SetValEmpty(cty.String),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("testdata"),
|
|
cty.StringVal("*.txt"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("testdata"),
|
|
cty.StringVal("hello.txt"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("testdata"),
|
|
cty.StringVal("hello.???"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
{
|
|
cty.StringVal("testdata"),
|
|
cty.StringVal("hello*"),
|
|
cty.SetVal([]cty.Value{
|
|
cty.StringVal("hello.tmpl"),
|
|
cty.StringVal("hello.txt"),
|
|
}),
|
|
``,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("FileSet(\".\", %#v, %#v)", test.Path, test.Pattern), func(t *testing.T) {
|
|
got, err := FileSet(".", test.Path, test.Pattern)
|
|
|
|
if test.Err != "" {
|
|
if err == nil {
|
|
t.Fatal("succeeded; want error")
|
|
}
|
|
if got, want := err.Error(), test.Err; got != want {
|
|
t.Errorf("wrong error\ngot: %s\nwant: %s", got, want)
|
|
}
|
|
return
|
|
} else if err != nil {
|
|
t.Fatalf("unexpected error: %s", err)
|
|
}
|
|
|
|
if !got.RawEquals(test.Want) {
|
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFileBase64(t *testing.T) {
|
|
tests := []struct {
|
|
Path cty.Value
|
|
Want cty.Value
|
|
Err bool
|
|
}{
|
|
{
|
|
cty.StringVal("testdata/hello.txt"),
|
|
cty.StringVal("SGVsbG8gV29ybGQ="),
|
|
false,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/icon.png"),
|
|
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="),
|
|
false,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/missing"),
|
|
cty.NilVal,
|
|
true, // no file exists
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("FileBase64(\".\", %#v)", test.Path), func(t *testing.T) {
|
|
got, err := FileBase64(".", test.Path)
|
|
|
|
if test.Err {
|
|
if err == nil {
|
|
t.Fatal("succeeded; want error")
|
|
}
|
|
return
|
|
} else if err != nil {
|
|
t.Fatalf("unexpected error: %s", err)
|
|
}
|
|
|
|
if !got.RawEquals(test.Want) {
|
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBasename(t *testing.T) {
|
|
tests := []struct {
|
|
Path cty.Value
|
|
Want cty.Value
|
|
Err bool
|
|
}{
|
|
{
|
|
cty.StringVal("testdata/hello.txt"),
|
|
cty.StringVal("hello.txt"),
|
|
false,
|
|
},
|
|
{
|
|
cty.StringVal("hello.txt"),
|
|
cty.StringVal("hello.txt"),
|
|
false,
|
|
},
|
|
{
|
|
cty.StringVal(""),
|
|
cty.StringVal("."),
|
|
false,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("Basename(%#v)", test.Path), func(t *testing.T) {
|
|
got, err := Basename(test.Path)
|
|
|
|
if test.Err {
|
|
if err == nil {
|
|
t.Fatal("succeeded; want error")
|
|
}
|
|
return
|
|
} else if err != nil {
|
|
t.Fatalf("unexpected error: %s", err)
|
|
}
|
|
|
|
if !got.RawEquals(test.Want) {
|
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDirname(t *testing.T) {
|
|
tests := []struct {
|
|
Path cty.Value
|
|
Want cty.Value
|
|
Err bool
|
|
}{
|
|
{
|
|
cty.StringVal("testdata/hello.txt"),
|
|
cty.StringVal("testdata"),
|
|
false,
|
|
},
|
|
{
|
|
cty.StringVal("testdata/foo/hello.txt"),
|
|
cty.StringVal("testdata/foo"),
|
|
false,
|
|
},
|
|
{
|
|
cty.StringVal("hello.txt"),
|
|
cty.StringVal("."),
|
|
false,
|
|
},
|
|
{
|
|
cty.StringVal(""),
|
|
cty.StringVal("."),
|
|
false,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("Dirname(%#v)", test.Path), func(t *testing.T) {
|
|
got, err := Dirname(test.Path)
|
|
|
|
if test.Err {
|
|
if err == nil {
|
|
t.Fatal("succeeded; want error")
|
|
}
|
|
return
|
|
} else if err != nil {
|
|
t.Fatalf("unexpected error: %s", err)
|
|
}
|
|
|
|
if !got.RawEquals(test.Want) {
|
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPathExpand(t *testing.T) {
|
|
homePath, err := homedir.Dir()
|
|
if err != nil {
|
|
t.Fatalf("Error getting home directory: %v", err)
|
|
}
|
|
|
|
tests := []struct {
|
|
Path cty.Value
|
|
Want cty.Value
|
|
Err bool
|
|
}{
|
|
{
|
|
cty.StringVal("~/test-file"),
|
|
cty.StringVal(filepath.Join(homePath, "test-file")),
|
|
false,
|
|
},
|
|
{
|
|
cty.StringVal("~/another/test/file"),
|
|
cty.StringVal(filepath.Join(homePath, "another/test/file")),
|
|
false,
|
|
},
|
|
{
|
|
cty.StringVal("/root/file"),
|
|
cty.StringVal("/root/file"),
|
|
false,
|
|
},
|
|
{
|
|
cty.StringVal("/"),
|
|
cty.StringVal("/"),
|
|
false,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("Dirname(%#v)", test.Path), func(t *testing.T) {
|
|
got, err := Pathexpand(test.Path)
|
|
|
|
if test.Err {
|
|
if err == nil {
|
|
t.Fatal("succeeded; want error")
|
|
}
|
|
return
|
|
} else if err != nil {
|
|
t.Fatalf("unexpected error: %s", err)
|
|
}
|
|
|
|
if !got.RawEquals(test.Want) {
|
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
|
}
|
|
})
|
|
}
|
|
}
|