Skip to content

Commit

Permalink
chore: add unit tests to variables pkg (#2519)
Browse files Browse the repository at this point in the history
## Description

This moves the unit tests from pkg (incorporating feedback from over
there)

## Related Issue

Fixes #N/A

## Checklist before merging

- [X] Test, docs, adr added or updated as needed
- [X] [Contributor Guide
Steps](https://github.com/defenseunicorns/zarf/blob/main/.github/CONTRIBUTING.md#developer-workflow)
followed

---------

Co-authored-by: Austin Abro <[email protected]>
Co-authored-by: Lucas Rodriguez <[email protected]>
  • Loading branch information
3 people authored May 23, 2024
1 parent a69c44f commit f0362d1
Show file tree
Hide file tree
Showing 5 changed files with 323 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -223,5 +223,5 @@ cve-report: ## Create a CVE report for the current project (must `brew install g
@test -d ./build || mkdir ./build
go run main.go tools sbom scan . -o json --exclude './site' --exclude './examples' | grype -o template -t hack/grype.tmpl > build/zarf-known-cves.csv

lint-go: ## Run golang-ci-lint to lint the go code (must `brew install golang-ci-lint` first)
lint-go: ## Run golang-ci-lint to lint the go code (must `brew install golangci-lint` first)
golangci-lint run
150 changes: 150 additions & 0 deletions src/pkg/variables/templates_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

package variables

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

"github.com/stretchr/testify/require"
)

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 bool
wantContents string
}

tests := []test{
{
vc: VariableConfig{setVariableMap: SetVariableMap{}, applicationTemplates: map[string]*TextTemplate{}},
path: "non-existent.test",
wantErr: true,
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"},
},
},
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"},
},
},
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},
},
},
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},
},
},
wantContents: file,
},
}

for _, tc := range tests {
if tc.path == "" {
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 tc.wantErr {
require.Error(t, gotErr)
} else {
require.NoError(t, gotErr)
gotContents, _ := os.ReadFile(tc.path)
require.Equal(t, tc.wantContents, string(gotContents))
}
}
}
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
15 changes: 12 additions & 3 deletions src/pkg/variables/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,18 @@ 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 {
r, err := regexp.Compile(pattern)
if err != nil {
return err
}

if r.MatchString(variable.Value) {
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)
}
159 changes: 159 additions & 0 deletions src/pkg/variables/variables_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

package variables

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestPopulateVariables(t *testing.T) {
type test struct {
vc VariableConfig
vars []InteractiveVariable
presets map[string]string
wantErr bool
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{},
wantVars: SetVariableMap{"NAME": {Variable: Variable{Name: "NAME"}}},
},
{
vc: VariableConfig{setVariableMap: SetVariableMap{}},
vars: []InteractiveVariable{
{Variable: Variable{Name: "NAME"}, Default: "Default"},
},
presets: map[string]string{},
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"},
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{},
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"},
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{},
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{},
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"},
wantVars: SetVariableMap{
"NAME": {Variable: Variable{Name: "NAME"}, Value: "Set"},
},
},
}

for _, tc := range tests {
gotErr := tc.vc.PopulateVariables(tc.vars, tc.presets)
if tc.wantErr {
require.Error(t, gotErr)
} else {
require.NoError(t, gotErr)
}

gotVars := tc.vc.setVariableMap

require.Equal(t, len(gotVars), len(tc.wantVars))

for key := range gotVars {
require.Equal(t, gotVars[key], tc.wantVars[key])
}
}
}

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

tests := []test{
{
vc: VariableConfig{setVariableMap: SetVariableMap{}}, name: "NAME", pattern: "n[a-z]me",
wantErrMsg: "variable \"NAME\" was not found in the current variable map",
},
{
vc: VariableConfig{
setVariableMap: SetVariableMap{"NAME": &SetVariable{Value: "name"}},
}, name: "NAME", pattern: "n[^a]me",
wantErrMsg: "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", wantErrMsg: "",
},
{
vc: VariableConfig{
setVariableMap: SetVariableMap{"NAME": &SetVariable{Value: "name"}},
}, name: "NAME", pattern: "n[a-z-bad-pattern", wantErrMsg: "error parsing regexp: missing closing ]: `[a-z-bad-pattern`",
},
}

for _, tc := range tests {
got := tc.vc.CheckVariablePattern(tc.name, tc.pattern)
if tc.wantErrMsg != "" {
require.EqualError(t, got, tc.wantErrMsg)
} else {
require.NoError(t, got)
}
}
}

0 comments on commit f0362d1

Please sign in to comment.