Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add unit tests to variables pkg #2519

Merged
merged 13 commits into from
May 23, 2024
157 changes: 157 additions & 0 deletions src/pkg/variables/templates_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

package variables

import (
"errors"
"os"
"path/filepath"
"testing"
)

var start = `
This is a test file for templating.

###PREFIX_VAR_REPLACE_ME###
###PREFIX_CONST_REPLACE_ME###
###PREFIX_APP_REPLACE_ME###
###PREFIX_NON_EXIST###
`
var simple = `
This is a test file for templating.

VAR_REPLACED
CONST_REPLACED
APP_REPLACED
###PREFIX_NON_EXIST###
`
var multiline = `
This is a test file for templating.

VAR_REPLACED
VAR_SECOND
CONST_REPLACED
CONST_SECOND
APP_REPLACED
APP_SECOND
###PREFIX_NON_EXIST###
`
var autoIndent = `
This is a test file for templating.

VAR_REPLACED
VAR_SECOND
CONST_REPLACED
CONST_SECOND
APP_REPLACED
APP_SECOND
###PREFIX_NON_EXIST###
`
var file = `
This is a test file for templating.

The contents of this file become the template value
CONSTs Don't Support File
The contents of this file become the template value
###PREFIX_NON_EXIST###
`

func TestReplaceTextTemplate(t *testing.T) {
type test struct {
vc VariableConfig
path string
wantErr error
wantContents string
}

tests := []test{
{
vc: VariableConfig{setVariableMap: SetVariableMap{}, applicationTemplates: map[string]*TextTemplate{}},
path: "non-existent.test",
wantErr: errors.New("open non-existent.test: no such file or directory"),
wantContents: start,
},
{
vc: VariableConfig{
templatePrefix: "PREFIX",
setVariableMap: SetVariableMap{
"REPLACE_ME": {Value: "VAR_REPLACED"},
},
constants: []Constant{{Name: "REPLACE_ME", Value: "CONST_REPLACED"}},
applicationTemplates: map[string]*TextTemplate{
"###PREFIX_APP_REPLACE_ME###": {Value: "APP_REPLACED"},
},
},
wantErr: nil,
wantContents: simple,
},
{
vc: VariableConfig{
templatePrefix: "PREFIX",
setVariableMap: SetVariableMap{
"REPLACE_ME": {Value: "VAR_REPLACED\nVAR_SECOND"},
},
constants: []Constant{{Name: "REPLACE_ME", Value: "CONST_REPLACED\nCONST_SECOND"}},
applicationTemplates: map[string]*TextTemplate{
"###PREFIX_APP_REPLACE_ME###": {Value: "APP_REPLACED\nAPP_SECOND"},
},
},
wantErr: nil,
wantContents: multiline,
},
{
vc: VariableConfig{
templatePrefix: "PREFIX",
setVariableMap: SetVariableMap{
"REPLACE_ME": {Value: "VAR_REPLACED\nVAR_SECOND", Variable: Variable{AutoIndent: true}},
},
constants: []Constant{{Name: "REPLACE_ME", Value: "CONST_REPLACED\nCONST_SECOND", AutoIndent: true}},
applicationTemplates: map[string]*TextTemplate{
"###PREFIX_APP_REPLACE_ME###": {Value: "APP_REPLACED\nAPP_SECOND", AutoIndent: true},
},
},
wantErr: nil,
wantContents: autoIndent,
},
{
vc: VariableConfig{
templatePrefix: "PREFIX",
setVariableMap: SetVariableMap{
"REPLACE_ME": {Value: "testdata/file.txt", Variable: Variable{Type: FileVariableType}},
},
constants: []Constant{{Name: "REPLACE_ME", Value: "CONSTs Don't Support File"}},
applicationTemplates: map[string]*TextTemplate{
"###PREFIX_APP_REPLACE_ME###": {Value: "testdata/file.txt", Type: FileVariableType},
},
},
wantErr: nil,
wantContents: file,
},
}

for _, tc := range tests {
tmpDir := t.TempDir()
tc.path = filepath.Join(tmpDir, "templates.test")

f, _ := os.Create(tc.path)
defer f.Close()

f.WriteString(start)

gotErr := tc.vc.ReplaceTextTemplate(tc.path)
if gotErr != nil && tc.wantErr != nil {
if gotErr.Error() != tc.wantErr.Error() {
t.Fatalf("wanted err: %s, got err: %s", tc.wantErr, gotErr)
}
} else if gotErr != nil {
t.Fatalf("got unexpected err: %s", gotErr)
} else {
gotContents, _ := os.ReadFile(tc.path)
if string(gotContents) != tc.wantContents {
t.Fatalf("wanted contents: %s, got contents: %s", tc.wantContents, string(gotContents))
}
}
Racer159 marked this conversation as resolved.
Show resolved Hide resolved

}
}
1 change: 1 addition & 0 deletions src/pkg/variables/testdata/file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The contents of this file become the template value
10 changes: 7 additions & 3 deletions src/pkg/variables/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,13 @@ func (vc *VariableConfig) SetVariable(name, value string, sensitive bool, autoIn

// CheckVariablePattern checks to see if a current variable is set to a value that matches its pattern
func (vc *VariableConfig) CheckVariablePattern(name, pattern string) error {
if regexp.MustCompile(pattern).MatchString(vc.setVariableMap[name].Value) {
return nil
if variable, ok := vc.setVariableMap[name]; ok {
if regexp.MustCompile(pattern).MatchString(variable.Value) {
Racer159 marked this conversation as resolved.
Show resolved Hide resolved
return nil
}

return fmt.Errorf("provided value for variable %q does not match pattern %q", name, pattern)
}

return fmt.Errorf("provided value for variable %q does not match pattern %q", name, pattern)
return fmt.Errorf("variable %q was not found in the current variable map", name)
}
170 changes: 170 additions & 0 deletions src/pkg/variables/variables_test.go
Racer159 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

package variables

import (
"errors"
"reflect"
"testing"
)

func TestPopulateVariables(t *testing.T) {
type test struct {
vc VariableConfig
vars []InteractiveVariable
presets map[string]string
wantErr error
wantVars SetVariableMap
}

prompt := func(_ InteractiveVariable) (value string, err error) { return "Prompt", nil }

tests := []test{
{
vc: VariableConfig{setVariableMap: SetVariableMap{}},
vars: []InteractiveVariable{{Variable: Variable{Name: "NAME"}}},
presets: map[string]string{},
wantErr: nil,
wantVars: SetVariableMap{"NAME": {Variable: Variable{Name: "NAME"}}},
},
{
vc: VariableConfig{setVariableMap: SetVariableMap{}},
vars: []InteractiveVariable{
{Variable: Variable{Name: "NAME"}, Default: "Default"},
},
presets: map[string]string{},
wantErr: nil,
wantVars: SetVariableMap{
"NAME": {Variable: Variable{Name: "NAME"}, Value: "Default"},
},
},
{
vc: VariableConfig{setVariableMap: SetVariableMap{}},
vars: []InteractiveVariable{
{Variable: Variable{Name: "NAME"}, Default: "Default"},
},
presets: map[string]string{"NAME": "Set"},
wantErr: nil,
wantVars: SetVariableMap{
"NAME": {Variable: Variable{Name: "NAME"}, Value: "Set"},
},
},
{
vc: VariableConfig{setVariableMap: SetVariableMap{}},
vars: []InteractiveVariable{
{Variable: Variable{Name: "NAME", Sensitive: true, AutoIndent: true, Type: FileVariableType}},
},
presets: map[string]string{},
wantErr: nil,
wantVars: SetVariableMap{
"NAME": {Variable: Variable{Name: "NAME", Sensitive: true, AutoIndent: true, Type: FileVariableType}},
},
},
{
vc: VariableConfig{setVariableMap: SetVariableMap{}},
vars: []InteractiveVariable{
{Variable: Variable{Name: "NAME", Sensitive: true, AutoIndent: true, Type: FileVariableType}},
},
presets: map[string]string{"NAME": "Set"},
wantErr: nil,
wantVars: SetVariableMap{
"NAME": {Variable: Variable{Name: "NAME", Sensitive: true, AutoIndent: true, Type: FileVariableType}, Value: "Set"},
},
},
{
vc: VariableConfig{setVariableMap: SetVariableMap{}, prompt: prompt},
vars: []InteractiveVariable{
{Variable: Variable{Name: "NAME"}, Prompt: true},
},
presets: map[string]string{},
wantErr: nil,
wantVars: SetVariableMap{
"NAME": {Variable: Variable{Name: "NAME"}, Value: "Prompt"},
},
},
{
vc: VariableConfig{setVariableMap: SetVariableMap{}, prompt: prompt},
vars: []InteractiveVariable{
{Variable: Variable{Name: "NAME"}, Default: "Default", Prompt: true},
},
presets: map[string]string{},
wantErr: nil,
wantVars: SetVariableMap{
"NAME": {Variable: Variable{Name: "NAME"}, Value: "Prompt"},
},
},
{
vc: VariableConfig{setVariableMap: SetVariableMap{}, prompt: prompt},
vars: []InteractiveVariable{
{Variable: Variable{Name: "NAME"}, Prompt: true},
},
presets: map[string]string{"NAME": "Set"},
wantErr: nil,
wantVars: SetVariableMap{
"NAME": {Variable: Variable{Name: "NAME"}, Value: "Set"},
},
},
}

for _, tc := range tests {
gotErr := tc.vc.PopulateVariables(tc.vars, tc.presets)
if gotErr != nil && tc.wantErr != nil {
if gotErr.Error() != tc.wantErr.Error() {
t.Fatalf("wanted err: %s, got err: %s", tc.wantErr, gotErr)
}
} else if gotErr != nil {
t.Fatalf("got unexpected err: %s", gotErr)
}

gotVars := tc.vc.setVariableMap

if len(gotVars) != len(tc.wantVars) {
t.Fatalf("wanted vars len: %d, got vars len: %d", len(tc.wantVars), len(gotVars))
}

for key := range gotVars {
if !reflect.DeepEqual(gotVars[key], tc.wantVars[key]) {
t.Fatalf("for key %s: wanted var: %v, got var: %v", key, tc.wantVars[key], gotVars[key])
}
}
}
}

func TestCheckVariablePattern(t *testing.T) {
type test struct {
vc VariableConfig
name string
pattern string
want error
}

tests := []test{
{
vc: VariableConfig{setVariableMap: SetVariableMap{}}, name: "NAME", pattern: "n[a-z]me",
want: errors.New("variable \"NAME\" was not found in the current variable map"),
},
{
vc: VariableConfig{
setVariableMap: SetVariableMap{"NAME": &SetVariable{Value: "name"}},
}, name: "NAME", pattern: "n[^a]me",
want: errors.New("provided value for variable \"NAME\" does not match pattern \"n[^a]me\""),
},
{
vc: VariableConfig{
setVariableMap: SetVariableMap{"NAME": &SetVariable{Value: "name"}},
}, name: "NAME", pattern: "n[a-z]me", want: nil,
},
}

for _, tc := range tests {
got := tc.vc.CheckVariablePattern(tc.name, tc.pattern)
if got != nil && tc.want != nil {
if got.Error() != tc.want.Error() {
t.Fatalf("wanted err: %s, got err: %s", tc.want, got)
}
} else if got != nil {
t.Fatalf("got unexpected err: %s", got)
}
}
}
Loading