-
Notifications
You must be signed in to change notification settings - Fork 1
/
component_tester.go
334 lines (301 loc) · 8.52 KB
/
component_tester.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
package component
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"testing"
"time"
"github.com/ekara-platform/engine/util"
"github.com/ekara-platform/model"
"github.com/stretchr/testify/assert"
"gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/object"
)
type (
//ComponentTester is an helper user to run unit tests based on local GIT repositories
ComponentTester struct {
workdir string
paths []string
context util.LaunchContext
t *testing.T
cM *manager
}
testRepo struct {
path string
rep *git.Repository
lastHash plumbing.Hash
}
)
//CreateComponentTester creates a new ComponentTester
func CreateComponentTester(t *testing.T, lC util.LaunchContext) *ComponentTester {
tester := &ComponentTester{
workdir: "testdata/gitwork",
context: lC,
t: t,
paths: make([]string, 0, 0),
}
tester.Clean()
tester.cM = CreateComponentManager(lC, tester.workdir).(*manager)
return tester
}
//Clean deletes all the content created locally during a test
func (t *ComponentTester) Clean() {
os.RemoveAll("./testdata/gittest/")
os.RemoveAll(t.workdir)
for _, v := range t.paths {
os.RemoveAll(v)
}
}
//Init initializes the ComponentTester and build the environment
// bases on the launch context used during the tester's creation.
func (t *ComponentTester) Init() error {
wdURL, err := model.GetCurrentDirectoryURL(t.context.Log())
if err != nil {
return err
}
repo, ref := util.RepositoryFlavor(t.context.Location())
mainRep, err := model.CreateRepository(model.Base{Url: wdURL}, repo, ref, t.context.DescriptorName())
if err != nil {
return err
}
mainComponent := model.CreateComponent(model.MainComponentId, mainRep)
err = t.cM.Init(mainComponent)
if err != nil {
return err
}
return t.cM.Ensure()
// TODO Link here the generated interface with the context
// ONce this is done into the engine then remove this link.
//t.context.templateContext.Model = t.Env()
}
//CreateRepDefaultDescriptor creates a new component folder corresponding
// to the given path and write into it an empty descriptor
func (t *ComponentTester) CreateRepDefaultDescriptor(path string) *testRepo {
t.paths = append(t.paths, path)
rep, err := git.PlainInit(path, false)
assert.NotNil(t.t, rep)
assert.Nil(t.t, err)
res := &testRepo{
path: path,
rep: rep,
}
res.WriteCommit("ekara.yaml", ``)
return res
}
//CreateRep creates a new component folder corresponding
// to the given path
func (t *ComponentTester) CreateRep(path string) *testRepo {
t.paths = append(t.paths, path)
rep, err := git.PlainInit(path, false)
assert.NotNil(t.t, rep)
assert.Nil(t.t, err)
return &testRepo{
path: path,
rep: rep,
}
}
//WriteCommit commit into the repo the given content into
// a file named as the provided name
func (r *testRepo) WriteCommit(name, content string) {
co := &git.CommitOptions{
Author: &object.Signature{
Name: "Test Create Branchh",
Email: "dummy@stupid.com",
When: time.Now(),
},
}
err := ioutil.WriteFile(filepath.Join(r.path, name), []byte(content), 0644)
if err != nil {
panic(err)
}
wt, err := r.rep.Worktree()
if err != nil {
panic(err)
}
_, err = wt.Add(".")
if err != nil {
panic(err)
}
r.lastHash, err = wt.Commit("Written", co)
if err != nil {
panic(err)
}
}
//WriteCommit create the desired folder and then commit into it the given content into
// a file named as the provided name
func (r *testRepo) WriteFolderCommit(folder, name, content string) {
co := &git.CommitOptions{
Author: &object.Signature{
Name: "Test Create Branch",
Email: "dummy@stupid.com",
When: time.Now(),
},
}
path := filepath.Join(r.path, folder)
if _, err := os.Stat(path); os.IsNotExist(err) {
os.MkdirAll(path, 0777)
}
namePath := filepath.Join(path, name)
err := ioutil.WriteFile(namePath, []byte(content), 0644)
if err != nil {
panic(err)
}
wt, err := r.rep.Worktree()
if err != nil {
panic(err)
}
_, err = wt.Add(".")
if err != nil {
panic(err)
}
r.lastHash, err = wt.Commit("Written", co)
if err != nil {
panic(err)
}
}
//CreateBranch creates a branch into the repo
func (r *testRepo) CreateBranch(branch string) {
branch = fmt.Sprintf("refs/heads/%s", branch)
bo := &git.CheckoutOptions{
Create: true,
Force: true,
Branch: plumbing.ReferenceName(branch),
}
wt, err := r.rep.Worktree()
if err != nil {
panic(err)
}
err = wt.Checkout(bo)
if err != nil {
panic(err)
}
}
//Checkout Switch to the desired branch
func (r *testRepo) Checkout(branch string) {
branch = fmt.Sprintf("refs/heads/%s", branch)
bo := &git.CheckoutOptions{
Create: false,
Force: false,
Branch: plumbing.ReferenceName(branch),
}
wt, err := r.rep.Worktree()
if err != nil {
panic(err)
}
err = wt.Checkout(bo)
if err != nil {
panic(err)
}
}
//Tag creates a tag into the repo
func (r *testRepo) Tag(tag string) {
to := &git.CreateTagOptions{
Tagger: &object.Signature{
Name: "Test Create Tag",
Email: "dummy@stupid.com",
When: time.Now(),
},
Message: "Tag created",
}
_, err := r.rep.CreateTag(tag, r.lastHash, to)
if err != nil {
panic(err)
}
}
//Env returns the environment built during the test
func (t *ComponentTester) Env() model.Environment {
return *t.cM.Environment()
}
//AssertComponentsContainsExactly asserts that the fetched component folder
// contains exactly the components identified by the provided ids
func (t *ComponentTester) AssertComponentsContainsExactly(ids ...string) bool {
files, _ := ioutil.ReadDir(t.workdir + "/components/")
assert.Equal(t.t, len(ids), len(files))
return t.AssertComponentsContains(ids...)
}
//AssertComponentsContains asserts that the fetched component folder
// contains at least the components identified by the provided ids
func (t *ComponentTester) AssertComponentsContains(paths ...string) bool {
for _, v := range paths {
_, err := os.Stat(filepath.Join(t.workdir, "components", v))
if err == nil {
continue
}
log.Println(err.Error())
if os.IsNotExist(err) {
return assert.Fail(t.t, fmt.Sprintf("workdir doesn't contains %s", v))
}
}
return true
}
//ComponentCount returns the number of components fetched into the
// component folder
func (t *ComponentTester) ComponentCount() int {
files, _ := ioutil.ReadDir(filepath.Join(t.workdir, "components"))
res := 0
for _, f := range files {
if f.IsDir() {
res++
}
}
return res
}
//RootContainsComponent returns true the components tester contains
// the given path
func (t *ComponentTester) RootContainsComponent(path string) bool {
if info, err := os.Stat(path); os.IsNotExist(err) || !info.IsDir() {
return false
}
return true
}
//CheckFile asserts than a usable component contains a file with the desirec content
func (t *ComponentTester) CheckFile(u UsableComponent, file, desiredContent string) {
b, err := ioutil.ReadFile(filepath.Join(u.RootPath(), file))
assert.Nil(t.t, err)
assert.Equal(t.t, desiredContent, string(b))
}
//CheckParameter asserts that the template context contains the given parameter
func (t *ComponentTester) CheckParameter(key, value string) {
v, ok := t.cM.TemplateContext().Vars[key]
if assert.True(t.t, ok) {
assert.Equal(t.t, value, v)
}
}
//CheckSpecificParameter asserts that a parameter contains the value
func (t *ComponentTester) CheckSpecificParameter(p model.Parameters, key, value string) {
v, ok := p[key]
if assert.True(t.t, ok) {
assert.Equal(t.t, value, v)
}
}
//CheckSpecificEnvVar asserts that an environment variable contains the value
func (t *ComponentTester) CheckSpecificEnvVar(env model.EnvVars, key, value string) {
v, ok := env[key]
if assert.True(t.t, ok) {
assert.Equal(t.t, value, v)
}
}
// CheckStack asserts than the environment contains the stack, then check that the stack's component
// is usable and finally check that the stack containts the provide compose content .
func (t *ComponentTester) CheckStack(holder, stackName, composeContent string) {
stack, ok := t.cM.Environment().Stacks[stackName]
if assert.True(t.t, ok) {
//Check that the self contained stack has been well built
assert.Equal(t.t, stackName, stack.Name)
stackC, err := stack.Component()
assert.Nil(t.t, err)
assert.NotNil(t.t, stackC)
assert.Equal(t.t, holder, stackC.Id)
// Check that the stack is usable and returns the correct component
usableStack, err := t.cM.Use(stack)
defer usableStack.Release()
assert.Nil(t.t, err)
assert.NotNil(t.t, usableStack)
assert.False(t.t, usableStack.Templated())
// Check that the stacks contains the compose/playbook file
t.CheckFile(usableStack, "docker_compose.yml", composeContent)
}
}