Skip to content

Commit 59bb2bf

Browse files
authored
Merge pull request #17 from Skarlso/test_coverage_in_build
[Test] Test coverage in build
2 parents 2416f93 + 94c0486 commit 59bb2bf

File tree

3 files changed

+245
-4
lines changed

3 files changed

+245
-4
lines changed

pipeline/build_golang.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ const (
1818
srcFolder = "src"
1919
)
2020

21+
var execCommandContext = exec.CommandContext
22+
2123
// BuildPipelineGolang is the real implementation of BuildPipeline for golang
2224
type BuildPipelineGolang struct {
2325
Type gaia.PipelineType
@@ -57,8 +59,8 @@ func (b *BuildPipelineGolang) ExecuteBuild(p *gaia.CreatePipeline) error {
5759
"-d",
5860
"./...",
5961
}
60-
env := os.Environ()
61-
env = append(env, "GOPATH="+goPath)
62+
63+
env := append(os.Environ(), "GOPATH="+goPath)
6264

6365
// Execute and wait until finish or timeout
6466
output, err := executeCmd(path, args, env, p.Pipeline.Repo.LocalDest)
@@ -93,7 +95,7 @@ func executeCmd(path string, args []string, env []string, dir string) ([]byte, e
9395
defer cancel()
9496

9597
// Create command
96-
cmd := exec.CommandContext(ctx, path, args...)
98+
cmd := execCommandContext(ctx, path, args...)
9799
cmd.Env = env
98100
cmd.Dir = dir
99101

pipeline/build_golang_test.go

+239
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
package pipeline
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io/ioutil"
7+
"os"
8+
"os/exec"
9+
"path/filepath"
10+
"regexp"
11+
"strconv"
12+
"strings"
13+
"testing"
14+
15+
"github.com/gaia-pipeline/gaia"
16+
hclog "github.com/hashicorp/go-hclog"
17+
)
18+
19+
var killContext = false
20+
var killOnBuild = false
21+
22+
func fakeExecCommandContext(ctx context.Context, name string, args ...string) *exec.Cmd {
23+
if killContext {
24+
c, cancel := context.WithTimeout(context.Background(), 0)
25+
defer cancel()
26+
ctx = c
27+
}
28+
cs := []string{"-test.run=TestExecCommandContextHelper", "--", name}
29+
cs = append(cs, args...)
30+
cmd := exec.CommandContext(ctx, os.Args[0], cs...)
31+
arg := strings.Join(cs, ",")
32+
envArgs := os.Getenv("CMD_ARGS")
33+
if len(envArgs) != 0 {
34+
envArgs += ":" + arg
35+
} else {
36+
envArgs = arg
37+
}
38+
os.Setenv("CMD_ARGS", envArgs)
39+
return cmd
40+
}
41+
42+
func TestExecCommandContextHelper(t *testing.T) {
43+
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
44+
return
45+
}
46+
fmt.Fprintf(os.Stdout, os.Getenv("STDOUT"))
47+
i, _ := strconv.Atoi(os.Getenv("EXIT_STATUS"))
48+
os.Exit(i)
49+
}
50+
51+
func TestPrepareEnvironment(t *testing.T) {
52+
tmp := os.TempDir()
53+
gaia.Cfg = new(gaia.Config)
54+
gaia.Cfg.HomePath = tmp
55+
b := new(BuildPipelineGolang)
56+
p := new(gaia.CreatePipeline)
57+
err := b.PrepareEnvironment(p)
58+
if err != nil {
59+
t.Fatal("error was not expected when preparing environment: ", err)
60+
}
61+
var expectedDest = regexp.MustCompile(`^/.*/tmp/golang/src/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`)
62+
if !expectedDest.MatchString(p.Pipeline.Repo.LocalDest) {
63+
t.Fatalf("expected destination is '%s', but was '%s'", expectedDest, p.Pipeline.Repo.LocalDest)
64+
}
65+
}
66+
67+
func TestPrepareEnvironmentInvalidPathForMkdir(t *testing.T) {
68+
gaia.Cfg = new(gaia.Config)
69+
gaia.Cfg.HomePath = "/notexists"
70+
b := new(BuildPipelineGolang)
71+
p := new(gaia.CreatePipeline)
72+
err := b.PrepareEnvironment(p)
73+
if err == nil {
74+
t.Fatal("error was expected but none occurred")
75+
}
76+
}
77+
78+
func TestExecuteBuild(t *testing.T) {
79+
execCommandContext = fakeExecCommandContext
80+
defer func() {
81+
execCommandContext = exec.CommandContext
82+
}()
83+
tmp := os.TempDir()
84+
gaia.Cfg = new(gaia.Config)
85+
gaia.Cfg.HomePath = tmp
86+
b := new(BuildPipelineGolang)
87+
p := new(gaia.CreatePipeline)
88+
err := b.ExecuteBuild(p)
89+
if err != nil {
90+
t.Fatal("error while running executebuild. none was expected")
91+
}
92+
expectedDepArgs := "get,-d,./..."
93+
expectedBuildArgs := "build,-o,_"
94+
actualArgs := os.Getenv("CMD_ARGS")
95+
if !strings.Contains(actualArgs, expectedBuildArgs) && !strings.Contains(actualArgs, expectedDepArgs) {
96+
t.Fatalf("expected args '%s, %s' actual args '%s'", expectedDepArgs, expectedBuildArgs, actualArgs)
97+
}
98+
}
99+
100+
func TestExecuteBuildFailPipelineBuild(t *testing.T) {
101+
os.Mkdir("tmp", 0744)
102+
ioutil.WriteFile(filepath.Join("tmp", "main.go"), []byte(`package main
103+
import "os"
104+
func main() {
105+
os.Exit(1
106+
}`), 0766)
107+
wd, _ := os.Getwd()
108+
tmp := filepath.Join(wd, "tmp")
109+
defer func() {
110+
os.RemoveAll(tmp)
111+
}()
112+
gaia.Cfg = new(gaia.Config)
113+
gaia.Cfg.HomePath = tmp
114+
gaia.Cfg.Logger = hclog.New(&hclog.LoggerOptions{
115+
Level: hclog.Trace,
116+
Output: hclog.DefaultOutput,
117+
Name: "Gaia",
118+
})
119+
b := new(BuildPipelineGolang)
120+
p := new(gaia.CreatePipeline)
121+
p.Pipeline.Repo.LocalDest = tmp
122+
err := b.ExecuteBuild(p)
123+
if err == nil {
124+
t.Fatal("error while running executebuild. none was expected")
125+
}
126+
expected := "syntax error: unexpected newline, expecting comma or )"
127+
if !strings.Contains(p.Output, expected) {
128+
t.Fatal("got a different output than expected: ", p.Output)
129+
}
130+
}
131+
132+
func TestExecuteBuildContextTimeout(t *testing.T) {
133+
execCommandContext = fakeExecCommandContext
134+
killContext = true
135+
defer func() {
136+
execCommandContext = exec.CommandContext
137+
}()
138+
defer func() { killContext = false }()
139+
tmp := os.TempDir()
140+
gaia.Cfg = new(gaia.Config)
141+
gaia.Cfg.HomePath = tmp
142+
// Initialize shared logger
143+
gaia.Cfg.Logger = hclog.New(&hclog.LoggerOptions{
144+
Level: hclog.Trace,
145+
Output: hclog.DefaultOutput,
146+
Name: "Gaia",
147+
})
148+
b := new(BuildPipelineGolang)
149+
p := new(gaia.CreatePipeline)
150+
err := b.ExecuteBuild(p)
151+
if err == nil {
152+
t.Fatal("no error found while expecting error.")
153+
}
154+
if err.Error() != "context deadline exceeded" {
155+
t.Fatal("context deadline should have been exceeded. was instead: ", err)
156+
}
157+
}
158+
159+
func TestExecuteBuildBinaryNotFoundError(t *testing.T) {
160+
tmp := os.TempDir()
161+
gaia.Cfg = new(gaia.Config)
162+
gaia.Cfg.HomePath = tmp
163+
// Initialize shared logger
164+
gaia.Cfg.Logger = hclog.New(&hclog.LoggerOptions{
165+
Level: hclog.Trace,
166+
Output: hclog.DefaultOutput,
167+
Name: "Gaia",
168+
})
169+
currentPath := os.Getenv("PATH")
170+
defer func() { os.Setenv("PATH", currentPath) }()
171+
os.Setenv("PATH", "")
172+
b := new(BuildPipelineGolang)
173+
p := new(gaia.CreatePipeline)
174+
err := b.ExecuteBuild(p)
175+
if err == nil {
176+
t.Fatal("no error found while expecting error.")
177+
}
178+
if err.Error() != "exec: \"go\": executable file not found in $PATH" {
179+
t.Fatal("the error wasn't what we expected. instead it was: ", err)
180+
}
181+
}
182+
183+
func TestCopyBinary(t *testing.T) {
184+
tmp := os.TempDir()
185+
gaia.Cfg = new(gaia.Config)
186+
gaia.Cfg.HomePath = tmp
187+
// Initialize shared logger
188+
gaia.Cfg.Logger = hclog.New(&hclog.LoggerOptions{
189+
Level: hclog.Trace,
190+
Output: hclog.DefaultOutput,
191+
Name: "Gaia",
192+
})
193+
b := new(BuildPipelineGolang)
194+
p := new(gaia.CreatePipeline)
195+
p.Pipeline.Name = "main"
196+
p.Pipeline.Type = "go"
197+
p.Pipeline.Repo.LocalDest = tmp
198+
src := filepath.Join(tmp, appendTypeToName(p.Pipeline.Name, p.Pipeline.Type))
199+
dst := appendTypeToName(p.Pipeline.Name, p.Pipeline.Type)
200+
f, _ := os.Create(src)
201+
defer f.Close()
202+
defer os.Remove(dst)
203+
ioutil.WriteFile(src, []byte("testcontent"), 0666)
204+
err := b.CopyBinary(p)
205+
if err != nil {
206+
t.Fatal("error was not expected when copying binary: ", err)
207+
}
208+
content, err := ioutil.ReadFile(dst)
209+
if err != nil {
210+
t.Fatal("error encountered while reading destination file: ", err)
211+
}
212+
if string(content) != "testcontent" {
213+
t.Fatal("file content did not equal src content. was: ", string(content))
214+
}
215+
}
216+
217+
func TestCopyBinarySrcDoesNotExist(t *testing.T) {
218+
tmp := os.TempDir()
219+
gaia.Cfg = new(gaia.Config)
220+
gaia.Cfg.HomePath = tmp
221+
// Initialize shared logger
222+
gaia.Cfg.Logger = hclog.New(&hclog.LoggerOptions{
223+
Level: hclog.Trace,
224+
Output: hclog.DefaultOutput,
225+
Name: "Gaia",
226+
})
227+
b := new(BuildPipelineGolang)
228+
p := new(gaia.CreatePipeline)
229+
p.Pipeline.Name = "main"
230+
p.Pipeline.Type = "go"
231+
p.Pipeline.Repo.LocalDest = "/noneexistent"
232+
err := b.CopyBinary(p)
233+
if err == nil {
234+
t.Fatal("error was expected when copying binary but none occurred ")
235+
}
236+
if err.Error() != "open /noneexistent/main_go: no such file or directory" {
237+
t.Fatal("a different error occurred then expected: ", err)
238+
}
239+
}

pipeline/git_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
func TestGitCloneRepo(t *testing.T) {
1111
repo := &gaia.GitRepo{
12-
URL: "https://github.com/gaia-pipeline/gaia",
12+
URL: "https://github.com/gaia-pipeline/go-test-example",
1313
LocalDest: "tmp",
1414
}
1515
// always ensure that tmp folder is cleaned up

0 commit comments

Comments
 (0)