kubeform.dev/terraform-backend-sdk@v0.0.0-20220310143633-45f07fe731c5/configs/parser_test.go (about)

     1  package configs
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path"
     7  	"path/filepath"
     8  	"reflect"
     9  	"testing"
    10  
    11  	"github.com/davecgh/go-spew/spew"
    12  
    13  	version "github.com/hashicorp/go-version"
    14  	"github.com/hashicorp/hcl/v2"
    15  	"github.com/spf13/afero"
    16  )
    17  
    18  // testParser returns a parser that reads files from the given map, which
    19  // is from paths to file contents.
    20  //
    21  // Since this function uses only in-memory objects, it should never fail.
    22  // If any errors are encountered in practice, this function will panic.
    23  func testParser(files map[string]string) *Parser {
    24  	fs := afero.Afero{Fs: afero.NewMemMapFs()}
    25  
    26  	for filePath, contents := range files {
    27  		dirPath := path.Dir(filePath)
    28  		err := fs.MkdirAll(dirPath, os.ModePerm)
    29  		if err != nil {
    30  			panic(err)
    31  		}
    32  		err = fs.WriteFile(filePath, []byte(contents), os.ModePerm)
    33  		if err != nil {
    34  			panic(err)
    35  		}
    36  	}
    37  
    38  	return NewParser(fs)
    39  }
    40  
    41  // testModuleConfigFrom File reads a single file from the given path as a
    42  // module and returns its configuration. This is a helper for use in unit tests.
    43  func testModuleConfigFromFile(filename string) (*Config, hcl.Diagnostics) {
    44  	parser := NewParser(nil)
    45  	f, diags := parser.LoadConfigFile(filename)
    46  	mod, modDiags := NewModule([]*File{f}, nil)
    47  	diags = append(diags, modDiags...)
    48  	cfg, moreDiags := BuildConfig(mod, nil)
    49  	return cfg, append(diags, moreDiags...)
    50  }
    51  
    52  // testModuleFromDir reads configuration from the given directory path as
    53  // a module and returns it. This is a helper for use in unit tests.
    54  func testModuleFromDir(path string) (*Module, hcl.Diagnostics) {
    55  	parser := NewParser(nil)
    56  	return parser.LoadConfigDir(path)
    57  }
    58  
    59  // testModuleFromDir reads configuration from the given directory path as a
    60  // module and returns its configuration. This is a helper for use in unit tests.
    61  func testModuleConfigFromDir(path string) (*Config, hcl.Diagnostics) {
    62  	parser := NewParser(nil)
    63  	mod, diags := parser.LoadConfigDir(path)
    64  	cfg, moreDiags := BuildConfig(mod, nil)
    65  	return cfg, append(diags, moreDiags...)
    66  }
    67  
    68  // testNestedModuleConfigFromDir reads configuration from the given directory path as
    69  // a module with (optional) submodules and returns its configuration. This is a
    70  // helper for use in unit tests.
    71  func testNestedModuleConfigFromDir(t *testing.T, path string) (*Config, hcl.Diagnostics) {
    72  	t.Helper()
    73  
    74  	parser := NewParser(nil)
    75  	mod, diags := parser.LoadConfigDir(path)
    76  	if mod == nil {
    77  		t.Fatal("got nil root module; want non-nil")
    78  	}
    79  
    80  	versionI := 0
    81  	cfg, nestedDiags := BuildConfig(mod, ModuleWalkerFunc(
    82  		func(req *ModuleRequest) (*Module, *version.Version, hcl.Diagnostics) {
    83  			// For the sake of this test we're going to just treat our
    84  			// SourceAddr as a path relative to the calling module.
    85  			// A "real" implementation of ModuleWalker should accept the
    86  			// various different source address syntaxes Terraform supports.
    87  
    88  			// Build a full path by walking up the module tree, prepending each
    89  			// source address path until we hit the root
    90  			paths := []string{req.SourceAddr.String()}
    91  			for config := req.Parent; config != nil && config.Parent != nil; config = config.Parent {
    92  				paths = append([]string{config.SourceAddr.String()}, paths...)
    93  			}
    94  			paths = append([]string{path}, paths...)
    95  			sourcePath := filepath.Join(paths...)
    96  
    97  			mod, diags := parser.LoadConfigDir(sourcePath)
    98  			version, _ := version.NewVersion(fmt.Sprintf("1.0.%d", versionI))
    99  			versionI++
   100  			return mod, version, diags
   101  		},
   102  	))
   103  
   104  	diags = append(diags, nestedDiags...)
   105  	return cfg, diags
   106  }
   107  
   108  func assertNoDiagnostics(t *testing.T, diags hcl.Diagnostics) bool {
   109  	t.Helper()
   110  	return assertDiagnosticCount(t, diags, 0)
   111  }
   112  
   113  func assertDiagnosticCount(t *testing.T, diags hcl.Diagnostics, want int) bool {
   114  	t.Helper()
   115  	if len(diags) != want {
   116  		t.Errorf("wrong number of diagnostics %d; want %d", len(diags), want)
   117  		for _, diag := range diags {
   118  			t.Logf("- %s", diag)
   119  		}
   120  		return true
   121  	}
   122  	return false
   123  }
   124  
   125  func assertDiagnosticSummary(t *testing.T, diags hcl.Diagnostics, want string) bool {
   126  	t.Helper()
   127  
   128  	for _, diag := range diags {
   129  		if diag.Summary == want {
   130  			return false
   131  		}
   132  	}
   133  
   134  	t.Errorf("missing diagnostic summary %q", want)
   135  	for _, diag := range diags {
   136  		t.Logf("- %s", diag)
   137  	}
   138  	return true
   139  }
   140  
   141  func assertExactDiagnostics(t *testing.T, diags hcl.Diagnostics, want []string) bool {
   142  	t.Helper()
   143  
   144  	gotDiags := map[string]bool{}
   145  	wantDiags := map[string]bool{}
   146  
   147  	for _, diag := range diags {
   148  		gotDiags[diag.Error()] = true
   149  	}
   150  	for _, msg := range want {
   151  		wantDiags[msg] = true
   152  	}
   153  
   154  	bad := false
   155  	for got := range gotDiags {
   156  		if _, exists := wantDiags[got]; !exists {
   157  			t.Errorf("unexpected diagnostic: %s", got)
   158  			bad = true
   159  		}
   160  	}
   161  	for want := range wantDiags {
   162  		if _, exists := gotDiags[want]; !exists {
   163  			t.Errorf("missing expected diagnostic: %s", want)
   164  			bad = true
   165  		}
   166  	}
   167  
   168  	return bad
   169  }
   170  
   171  func assertResultDeepEqual(t *testing.T, got, want interface{}) bool {
   172  	t.Helper()
   173  	if !reflect.DeepEqual(got, want) {
   174  		t.Errorf("wrong result\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(want))
   175  		return true
   176  	}
   177  	return false
   178  }
   179  
   180  func stringPtr(s string) *string {
   181  	return &s
   182  }