diff options
author | Andrej Shadura <andrew.shadura@collabora.co.uk> | 2019-03-25 10:34:02 +0100 |
---|---|---|
committer | Andrej Shadura <andrew.shadura@collabora.co.uk> | 2019-03-25 10:34:02 +0100 |
commit | 100044871faa0e1de2f62728c3d5b83e1ce41176 (patch) | |
tree | e6cf1968d23cba398dae25174567616f45fb53d2 /actions/recipe_test.go | |
parent | 4a31eda27ed921e8d8b8c705facd554c8fff490c (diff) |
New upstream version 1.0.0+git20190319.cf3fc48
Diffstat (limited to 'actions/recipe_test.go')
-rw-r--r-- | actions/recipe_test.go | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/actions/recipe_test.go b/actions/recipe_test.go new file mode 100644 index 0000000..972bf61 --- /dev/null +++ b/actions/recipe_test.go @@ -0,0 +1,370 @@ +package actions_test + +import ( + "github.com/go-debos/debos" + "github.com/go-debos/debos/actions" + "github.com/stretchr/testify/assert" + "io/ioutil" + "os" + "testing" + "strings" +) + +type testRecipe struct { + recipe string + err string +} + +// Test if incorrect file has been passed +func TestParse_incorrect_file(t *testing.T) { + var err error + + var tests = []struct { + filename string + err string + }{ + { + "non-existing.yaml", + "open non-existing.yaml: no such file or directory", + }, + { + "/proc", + "read /proc: is a directory", + }, + } + + for _, test := range tests { + r := actions.Recipe{} + err = r.Parse(test.filename, false, false) + assert.EqualError(t, err, test.err) + } +} + +// Check common recipe syntax +func TestParse_syntax(t *testing.T) { + + var tests = []testRecipe{ + // Test if all actions are supported + {` +architecture: arm64 + +actions: + - action: apt + - action: debootstrap + - action: download + - action: filesystem-deploy + - action: image-partition + - action: ostree-commit + - action: ostree-deploy + - action: overlay + - action: pack + - action: raw + - action: run + - action: unpack + - action: recipe +`, + "", // Do not expect failure + }, + // Test of unknown action in list + {` +architecture: arm64 + +actions: + - action: test_unknown_action +`, + "Unknown action: test_unknown_action", + }, + // Test if 'architecture' property absence + {` +actions: + - action: raw +`, + "Recipe file must have 'architecture' property", + }, + // Test if no actions listed + {` +architecture: arm64 +`, + "Recipe file must have at least one action", + }, + // Test of wrong syntax in Yaml + {`wrong`, + "yaml: unmarshal errors:\n line 1: cannot unmarshal !!str `wrong` into actions.Recipe", + }, + // Test if no actions listed + {` +architecture: arm64 +`, + "Recipe file must have at least one action", + }, + } + + for _, test := range tests { + runTest(t, test) + } +} + +// Check template engine +func TestParse_template(t *testing.T) { + + var test = testRecipe{ + // Test template variables + ` +{{ $action:= or .action "download" }} +architecture: arm64 +actions: + - action: {{ $action }} +`, + "", // Do not expect failure + } + + { // Test of embedded template + r := runTest(t, test) + assert.Equalf(t, r.Actions[0].String(), "download", + "Fail to use embedded variable definition from recipe:%s\n", + test.recipe) + } + + { // Test of user-defined template variable + var templateVars = map[string]string{ + "action": "pack", + } + + r := runTest(t, test, templateVars) + assert.Equalf(t, r.Actions[0].String(), "pack", + "Fail to redefine variable with user-defined map:%s\n", + test.recipe) + } +} + +// Test of 'sector' function embedded to recipe package +func TestParse_sector(t *testing.T) { + var testSector = testRecipe{ + // Fail with unknown action + ` +architecture: arm64 + +actions: + - action: {{ sector 42 }} +`, + "Unknown action: 21504", + } + runTest(t, testSector) +} + +func runTest(t *testing.T, test testRecipe, templateVars ...map[string]string) actions.Recipe { + file, err := ioutil.TempFile(os.TempDir(), "recipe") + assert.Empty(t, err) + defer os.Remove(file.Name()) + + file.WriteString(test.recipe) + file.Close() + + r := actions.Recipe{} + if len(templateVars) == 0 { + err = r.Parse(file.Name(), false, false) + } else { + err = r.Parse(file.Name(), false, false, templateVars[0]) + } + + failed := false + + if len(test.err) > 0 { + // Expected error? + failed = !assert.EqualError(t, err, test.err) + } else { + // Unexpected error + failed = !assert.Empty(t, err) + } + + if failed { + t.Logf("Failed recipe:%s\n", test.recipe) + } + + return r +} + +type subRecipe struct { + name string + recipe string +} + +type testSubRecipe struct { + recipe string + subrecipe subRecipe + err string +} + +func TestSubRecipe(t *testing.T) { + // Embedded recipes + var recipeAmd64 = subRecipe { + "amd64.yaml", + ` +architecture: amd64 + +actions: + - action: run + command: ok.sh +`, + } + var recipeInheritedArch = subRecipe { + "inherited.yaml", + ` +{{- $architecture := or .architecture "armhf" }} +architecture: {{ $architecture }} + +actions: + - action: run + command: ok.sh +`, + } + var recipeArmhf = subRecipe { + "armhf.yaml", + ` +architecture: armhf + +actions: + - action: run + command: ok.sh +`, + } + var recipeIncluded = subRecipe { + "included.yaml", + ` +{{- $included_recipe := or .included_recipe "false"}} +architecture: amd64 + +actions: + - action: run + command: ok.sh + {{- if ne $included_recipe "true" }} + - action: recipe + recipe: armhf.yaml + {{- end }} +`, + } + + // test recipes + var tests = []testSubRecipe { + { + // Test recipe same architecture OK + ` +architecture: amd64 + +actions: + - action: recipe + recipe: amd64.yaml +`, + recipeAmd64, + "", // Do not expect failure + }, + { + // Test recipe with inherited architecture OK + ` +architecture: amd64 + +actions: + - action: recipe + recipe: inherited.yaml +`, + recipeInheritedArch, + "", // Do not expect failure + }, + { + // Fail with unknown recipe + ` +architecture: amd64 + +actions: + - action: recipe + recipe: unknown_recipe.yaml +`, + recipeAmd64, + "stat /tmp/unknown_recipe.yaml: no such file or directory", + }, + { + // Fail with different architecture recipe + ` +architecture: amd64 + +actions: + - action: recipe + recipe: armhf.yaml +`, + recipeArmhf, + "Expect architecture 'amd64' but got 'armhf'", + }, + { + // Test included_recipe prevents parsing OK + ` +architecture: amd64 + +actions: + - action: recipe + recipe: included.yaml +`, + recipeIncluded, + "", // Do not expect failure + }, + } + + for _, test := range tests { + runTestWithSubRecipes(t, test) + } +} + +func runTestWithSubRecipes(t *testing.T, test testSubRecipe, templateVars ...map[string]string) actions.Recipe { + var context debos.DebosContext + dir, err := ioutil.TempDir("", "go-debos") + assert.Empty(t, err) + defer os.RemoveAll(dir) + + file, err := ioutil.TempFile(dir, "recipe") + assert.Empty(t, err) + defer os.Remove(file.Name()) + + file.WriteString(test.recipe) + file.Close() + + file_subrecipe, err := os.Create(dir + "/" + test.subrecipe.name) + assert.Empty(t, err) + defer os.Remove(file_subrecipe.Name()) + + file_subrecipe.WriteString(test.subrecipe.recipe) + file_subrecipe.Close() + + r := actions.Recipe{} + if len(templateVars) == 0 { + err = r.Parse(file.Name(), false, false) + } else { + err = r.Parse(file.Name(), false, false, templateVars[0]) + } + + // Should not expect error during parse + failed := !assert.Empty(t, err) + + if !failed { + context.Architecture = r.Architecture + context.RecipeDir = dir + + for _, a := range r.Actions { + if err = a.Verify(&context); err != nil { + break + } + } + + if len(test.err) > 0 { + // Expected error? + failed = !assert.EqualError(t, err, strings.Replace(test.err, "/tmp", dir, 1)) + } else { + // Unexpected error + failed = !assert.Empty(t, err) + } + } + + if failed { + t.Logf("Failed recipe:%s\n", test.recipe) + } + + return r +} |