This repository has been archived on 2025-11-20. You can view files and clone it, but cannot push or open issues or pull requests.
Files
drone-runner-podman/engine/compiler/compiler_test.go
2019-12-06 16:10:27 -08:00

214 lines
5.9 KiB
Go

// Copyright 2019 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by the Polyform License
// that can be found in the LICENSE file.
// +build !windows
package compiler
import (
"context"
"encoding/json"
"io/ioutil"
"os"
"testing"
"github.com/dchest/uniuri"
"github.com/drone-runners/drone-runner-docker/engine"
"github.com/drone-runners/drone-runner-docker/engine/resource"
"github.com/drone/drone-go/drone"
"github.com/drone/runner-go/environ/provider"
"github.com/drone/runner-go/manifest"
"github.com/drone/runner-go/pipeline/runtime"
"github.com/drone/runner-go/registry"
"github.com/drone/runner-go/secret"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)
var nocontext = context.Background()
// dummy function that returns a non-random string for testing.
// it is used in place of the random function.
func notRandom() string {
return "random"
}
// This test verifies the pipeline dependency graph. When no
// dependency graph is defined, a default dependency graph is
// automatically defined to run steps serially.
func TestCompile_Serial(t *testing.T) {
testCompile(t, "testdata/serial.yml", "testdata/serial.json")
}
// This test verifies the pipeline dependency graph. It also
// verifies that pipeline steps with no dependencies depend on
// the initial clone step.
func TestCompile_Graph(t *testing.T) {
testCompile(t, "testdata/graph.yml", "testdata/graph.json")
}
// This test verifies no clone step exists in the pipeline if
// cloning is disabled.
func TestCompile_CloneDisabled_Serial(t *testing.T) {
testCompile(t, "testdata/noclone_serial.yml", "testdata/noclone_serial.json")
}
// This test verifies no clone step exists in the pipeline if
// cloning is disabled. It also verifies no pipeline steps
// depend on a clone step.
func TestCompile_CloneDisabled_Graph(t *testing.T) {
testCompile(t, "testdata/noclone_graph.yml", "testdata/noclone_graph.json")
}
// This test verifies that steps are disabled if conditions
// defined in the when block are not satisfied.
func TestCompile_Match(t *testing.T) {
ir := testCompile(t, "testdata/match.yml", "testdata/match.json")
if ir.Steps[0].RunPolicy != runtime.RunOnSuccess {
t.Errorf("Expect run on success")
}
if ir.Steps[1].RunPolicy != runtime.RunNever {
t.Errorf("Expect run never")
}
}
// This test verifies that steps configured to run on both
// success or failure are configured to always run.
func TestCompile_RunAlways(t *testing.T) {
ir := testCompile(t, "testdata/run_always.yml", "testdata/run_always.json")
if ir.Steps[0].RunPolicy != runtime.RunAlways {
t.Errorf("Expect run always")
}
}
// This test verifies that steps configured to run on failure
// are configured to run on failure.
func TestCompile_RunFailure(t *testing.T) {
ir := testCompile(t, "testdata/run_failure.yml", "testdata/run_failure.json")
if ir.Steps[0].RunPolicy != runtime.RunOnFailure {
t.Errorf("Expect run on failure")
}
}
// This test verifies that secrets defined in the yaml are
// requested and stored in the intermediate representation
// at compile time.
func TestCompile_Secrets(t *testing.T) {
manifest, _ := manifest.ParseFile("testdata/secret.yml")
compiler := &Compiler{
Environ: provider.Static(nil),
Registry: registry.Static(nil),
Secret: secret.StaticVars(map[string]string{
"token": "3DA541559918A808C2402BBA5012F6C60B27661C",
"password": "password",
"my_username": "octocat",
}),
}
args := Args{
Repo: &drone.Repo{},
Build: &drone.Build{},
Stage: &drone.Stage{},
System: &drone.System{},
Netrc: &drone.Netrc{},
Manifest: manifest,
Pipeline: manifest.Resources[0].(*resource.Pipeline),
Secret: secret.Static(nil),
}
ir := compiler.Compile(nocontext, args)
got := ir.Steps[0].Secrets
want := []*engine.Secret{
{
Name: "my_password",
Env: "PASSWORD",
Data: nil, // secret not found, data nil
Mask: true,
},
{
Name: "my_username",
Env: "USERNAME",
Data: []byte("octocat"), // secret found
Mask: true,
},
}
if diff := cmp.Diff(got, want); len(diff) != 0 {
// TODO(bradrydzewski) ordering is not guaranteed. this
// unit tests needs to be adjusted accordingly.
t.Skipf(diff)
}
}
// helper function parses and compiles the source file and then
// compares to a golden json file.
func testCompile(t *testing.T, source, golden string) *engine.Spec {
// replace the default random function with one that
// is deterministic, for testing purposes.
random = notRandom
// restore the default random function and the previously
// specified temporary directory
defer func() {
random = uniuri.New
}()
manifest, err := manifest.ParseFile(source)
if err != nil {
t.Error(err)
return nil
}
compiler := &Compiler{
Environ: provider.Static(nil),
Registry: registry.Static(nil),
Secret: secret.StaticVars(map[string]string{
"token": "3DA541559918A808C2402BBA5012F6C60B27661C",
"password": "password",
"my_username": "octocat",
}),
}
args := Args{
Repo: &drone.Repo{},
Build: &drone.Build{Target: "master"},
Stage: &drone.Stage{},
System: &drone.System{},
Netrc: &drone.Netrc{Machine: "github.com", Login: "octocat", Password: "correct-horse-battery-staple"},
Manifest: manifest,
Pipeline: manifest.Resources[0].(*resource.Pipeline),
Secret: secret.Static(nil),
}
got := compiler.Compile(nocontext, args)
raw, err := ioutil.ReadFile(golden)
if err != nil {
t.Error(err)
}
want := new(engine.Spec)
err = json.Unmarshal(raw, want)
if err != nil {
t.Error(err)
}
opts := cmp.Options{
cmpopts.IgnoreUnexported(engine.Spec{}),
cmpopts.IgnoreFields(engine.Step{}, "Envs", "Secrets", "Labels"),
cmpopts.IgnoreFields(engine.Network{}, "Labels"),
cmpopts.IgnoreFields(engine.VolumeEmptyDir{}, "Labels"),
}
if diff := cmp.Diff(got, want, opts...); len(diff) != 0 {
t.Errorf(diff)
}
return got
}
func dump(v interface{}) {
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
enc.Encode(v)
}