• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2020 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package workspace
16
17import (
18	"io/ioutil"
19	"os"
20	"os/exec"
21	"path"
22	"testing"
23
24	"android.googlesource.com/platform/tools/treble.git/hacksaw/bind"
25	"android.googlesource.com/platform/tools/treble.git/hacksaw/codebase"
26	"android.googlesource.com/platform/tools/treble.git/hacksaw/config"
27)
28
29func TestBasicCreate(t *testing.T) {
30	defer config.GetConfig().Reset()
31	codebaseDir, err := ioutil.TempDir("", "codebase")
32	if err != nil {
33		t.Error(err)
34	}
35	defer os.RemoveAll(codebaseDir)
36	gitDir := path.Join(codebaseDir, "project", ".git")
37	if err = os.MkdirAll(gitDir, os.ModePerm); err != nil {
38		t.Error(err)
39	}
40	repoDir := path.Join(codebaseDir, ".repo")
41	if err = os.Mkdir(repoDir, os.ModePerm); err != nil {
42		t.Error(err)
43	}
44	listContents := []byte("project")
45	listPath := path.Join(repoDir, "project.list")
46	if err = ioutil.WriteFile(listPath, listContents, os.ModePerm); err != nil {
47		t.Error(err)
48	}
49	_, err = codebase.Add("test-codebase", codebaseDir)
50	if err != nil {
51		t.Error(err)
52	}
53	// The top dir must be named "hacksaw"
54	// otherwise the mounters will reject any
55	// mount requests
56	wsTempDir, err := ioutil.TempDir("", "workspace")
57	if err != nil {
58		t.Error(err)
59	}
60	defer os.RemoveAll(wsTempDir)
61	wsTopDir := path.Join(wsTempDir, "hacksaw")
62	if err = os.Mkdir(wsTopDir, os.ModePerm); err != nil {
63		t.Error(err)
64	}
65	ws := New(bind.NewFakePathBinder(), wsTopDir)
66	if _, err = ws.Create("test-workspace", "test-codebase"); err != nil {
67		t.Error(err)
68	}
69	workspaceDir, err := ws.GetDir("test-workspace")
70	if err != nil {
71		t.Error(err)
72	}
73	_, err = os.Stat(workspaceDir)
74	if err != nil {
75		t.Error(err)
76	}
77}
78
79func TestWorkspaceDuplicate(t *testing.T) {
80	defer config.GetConfig().Reset()
81	codebaseDir, err := ioutil.TempDir("", "codebase")
82	if err != nil {
83		t.Error(err)
84	}
85	defer os.RemoveAll(codebaseDir)
86	gitDir := path.Join(codebaseDir, "project", ".git")
87	if err = os.MkdirAll(gitDir, os.ModePerm); err != nil {
88		t.Error(err)
89	}
90	repoDir := path.Join(codebaseDir, ".repo")
91	if err = os.Mkdir(repoDir, os.ModePerm); err != nil {
92		t.Error(err)
93	}
94	listContents := []byte("project")
95	listPath := path.Join(repoDir, "project.list")
96	if err = ioutil.WriteFile(listPath, listContents, os.ModePerm); err != nil {
97		t.Error(err)
98	}
99	_, err = codebase.Add("test-codebase", codebaseDir)
100	if err != nil {
101		t.Error(err)
102	}
103	// The top dir must be named "hacksaw"
104	// otherwise the mounters will reject any
105	// mount requests
106	wsTempDir, err := ioutil.TempDir("", "workspace")
107	if err != nil {
108		t.Error(err)
109	}
110	defer os.RemoveAll(wsTempDir)
111	wsTopDir := path.Join(wsTempDir, "hacksaw")
112	if err = os.Mkdir(wsTopDir, os.ModePerm); err != nil {
113		t.Error(err)
114	}
115	ws := New(bind.NewFakePathBinder(), wsTopDir)
116	_, err = ws.Create("test-workspace", "test-codebase")
117	if err != nil {
118		t.Error(err)
119	}
120	_, err = ws.Create("test-workspace", "test-codebase")
121	if err == nil {
122		t.Error("Allowed workspace duplicate")
123	}
124}
125
126func TestCreateWorkspaceFromBadCodebase(t *testing.T) {
127	defer config.GetConfig().Reset()
128	codebaseDir, err := ioutil.TempDir("", "test")
129	if err != nil {
130		t.Error(err)
131	}
132	defer os.RemoveAll(codebaseDir)
133	_, err = codebase.Add("test-codebase", codebaseDir)
134	if err != nil {
135		t.Error(err)
136	}
137	wsTempDir, err := ioutil.TempDir("", "workspace")
138	if err != nil {
139		t.Error(err)
140	}
141	defer os.RemoveAll(wsTempDir)
142	wsTopDir := path.Join(wsTempDir, "hacksaw")
143	if err = os.Mkdir(wsTopDir, os.ModePerm); err != nil {
144		t.Error(err)
145	}
146	ws := New(bind.NewFakePathBinder(), wsTopDir)
147	if _, err = ws.Create("test-workspace", "does-not-exist"); err == nil {
148		t.Error("Allowed bad codebase")
149	}
150}
151
152func TestList(t *testing.T) {
153	defer config.GetConfig().Reset()
154	codebaseDir, err := ioutil.TempDir("", "test")
155	if err != nil {
156		t.Error(err)
157	}
158	defer os.RemoveAll(codebaseDir)
159	gitDir := path.Join(codebaseDir, "project", ".git")
160	if err = os.MkdirAll(gitDir, os.ModePerm); err != nil {
161		t.Error(err)
162	}
163	repoDir := path.Join(codebaseDir, ".repo")
164	if err = os.Mkdir(repoDir, os.ModePerm); err != nil {
165		t.Error(err)
166	}
167	listContents := []byte("project")
168	listPath := path.Join(repoDir, "project.list")
169	if err = ioutil.WriteFile(listPath, listContents, os.ModePerm); err != nil {
170		t.Error(err)
171	}
172	_, err = codebase.Add("test-codebase", codebaseDir)
173	if err != nil {
174		t.Error(err)
175	}
176	wsTempDir, err := ioutil.TempDir("", "workspace")
177	if err != nil {
178		t.Error(err)
179	}
180	defer os.RemoveAll(wsTempDir)
181	wsTopDir := path.Join(wsTempDir, "hacksaw")
182	if err = os.Mkdir(wsTopDir, os.ModePerm); err != nil {
183		t.Error(err)
184	}
185	ws := New(bind.NewFakePathBinder(), wsTopDir)
186	if _, err = ws.Create("test-workspace", "test-codebase"); err != nil {
187		t.Error(err)
188	}
189	list := ws.List()
190	cb, ok := list["test-workspace"]
191	if !ok || cb != "test-codebase" {
192		t.Error("Added workspace not listed")
193	}
194}
195
196func TestRemove(t *testing.T) {
197	defer config.GetConfig().Reset()
198	codebaseDir, err := ioutil.TempDir("", "test")
199	if err != nil {
200		t.Error(err)
201	}
202	defer os.RemoveAll(codebaseDir)
203	gitDir := path.Join(codebaseDir, "project", ".git")
204	if err = os.MkdirAll(gitDir, os.ModePerm); err != nil {
205		t.Error(err)
206	}
207	repoDir := path.Join(codebaseDir, ".repo")
208	if err = os.Mkdir(repoDir, os.ModePerm); err != nil {
209		t.Error(err)
210	}
211	listContents := []byte("project")
212	listPath := path.Join(repoDir, "project.list")
213	if err = ioutil.WriteFile(listPath, listContents, os.ModePerm); err != nil {
214		t.Error(err)
215	}
216	_, err = codebase.Add("test-codebase", codebaseDir)
217	if err != nil {
218		t.Error(err)
219	}
220	wsTempDir, err := ioutil.TempDir("", "workspace")
221	if err != nil {
222		t.Error(err)
223	}
224	defer os.RemoveAll(wsTempDir)
225	wsTopDir := path.Join(wsTempDir, "hacksaw")
226	if err = os.Mkdir(wsTopDir, os.ModePerm); err != nil {
227		t.Error(err)
228	}
229	ws := New(bind.NewFakePathBinder(), wsTopDir)
230	if _, err = ws.Create("test-workspace", "test-codebase"); err != nil {
231		t.Error(err)
232	}
233	workspaceDir, err := ws.GetDir("test-workspace")
234	if err != nil {
235		t.Error(err)
236	}
237	_, err = os.Stat(workspaceDir)
238	if err != nil {
239		t.Error(err)
240	}
241	cfg, err := ws.Remove("test-workspace")
242	if err != nil {
243		t.Error(err)
244	}
245	_, ok := cfg.Workspaces["test-codebase"]
246	if ok {
247		t.Error("Removed workspace test-codebase is still in the configuration")
248	}
249	_, err = os.Stat(workspaceDir)
250	if err == nil {
251		t.Error("Workspace test-workspace was removed but its directory remains")
252	} else if os.IsNotExist(err) {
253		// This is the expected error
254	} else {
255		t.Error(err)
256	}
257}
258
259func TestEdit(t *testing.T) {
260	defer config.GetConfig().Reset()
261	codebaseDir, err := ioutil.TempDir("", "codebase")
262	if err != nil {
263		t.Error(err)
264	}
265	defer os.RemoveAll(codebaseDir)
266	projectDir := path.Join(codebaseDir, "project")
267	if err = os.MkdirAll(projectDir, os.ModePerm); err != nil {
268		t.Error(err)
269	}
270	cmd := exec.Command("git", "-C", projectDir, "init")
271	output, err := cmd.CombinedOutput()
272	if err != nil {
273		t.Errorf("Command\n%s\nfailed with the following:\n%s\n%s",
274			cmd.String(), err.Error(), output)
275	}
276	cmd = exec.Command("git", "-C", projectDir, "commit", `--message="Initial commit"`, "--allow-empty")
277	output, err = cmd.CombinedOutput()
278	if err != nil {
279		t.Errorf("Command\n%s\nfailed with the following:\n%s\n%s",
280			cmd.String(), err.Error(), output)
281	}
282	repoDir := path.Join(codebaseDir, ".repo")
283	if err = os.Mkdir(repoDir, os.ModePerm); err != nil {
284		t.Error(err)
285	}
286	listContents := []byte("project")
287	listPath := path.Join(repoDir, "project.list")
288	if err = ioutil.WriteFile(listPath, listContents, os.ModePerm); err != nil {
289		t.Error(err)
290	}
291	_, err = codebase.Add("test-codebase", codebaseDir)
292	if err != nil {
293		t.Error(err)
294	}
295	wsTempDir, err := ioutil.TempDir("", "workspace")
296	if err != nil {
297		t.Error(err)
298	}
299	defer os.RemoveAll(wsTempDir)
300	wsTopDir := path.Join(wsTempDir, "hacksaw")
301	if err = os.Mkdir(wsTopDir, os.ModePerm); err != nil {
302		t.Error(err)
303	}
304	ws := New(bind.NewFakePathBinder(), wsTopDir)
305	if _, err = ws.Create("test-workspace", "test-codebase"); err != nil {
306		t.Error(err)
307	}
308	workspaceDir, err := ws.GetDir("test-workspace")
309	if err != nil {
310		t.Error(err)
311	}
312	_, err = os.Stat(workspaceDir)
313	if err != nil {
314		t.Error(err)
315	}
316	editPath := path.Join(workspaceDir, "project")
317	branchName, wsProjectDir, err := ws.Edit(editPath)
318	if err != nil {
319		t.Error(err)
320	}
321	if branchName == "" {
322		t.Error("Editing returned an empty branch")
323	}
324	if wsProjectDir == "" {
325		t.Error("Editing returned an empty project path")
326	}
327	cmd = exec.Command("git", "-C", wsProjectDir, "show", branchName)
328	output, err = cmd.CombinedOutput()
329	if err != nil {
330		t.Errorf("Command\n%s\nfailed with the following:\n%s\n%s",
331			cmd.String(), err.Error(), output)
332	}
333	//Recreate workspace and try editing again
334	_, err = ws.Remove("test-workspace")
335	if err != nil {
336		t.Error(err)
337	}
338	_, err = ws.Create("test-workspace", "test-codebase")
339	if err != nil {
340		t.Error(err)
341	}
342	_, _, err = ws.Edit(editPath)
343	if err != nil {
344		t.Error(err)
345	}
346}
347
348const projectList = `read-only-project
349editable-project`
350
351func TestRecreate(t *testing.T) {
352	defer config.GetConfig().Reset()
353	codebaseDir, err := ioutil.TempDir("", "codebase")
354	if err != nil {
355		t.Error(err)
356	}
357	defer os.RemoveAll(codebaseDir)
358	roProjectDir := path.Join(codebaseDir, "read-only-project")
359	if err = os.MkdirAll(roProjectDir, os.ModePerm); err != nil {
360		t.Error(err)
361	}
362	cmd := exec.Command("git", "-C", roProjectDir, "init")
363	output, err := cmd.CombinedOutput()
364	if err != nil {
365		t.Errorf("Command\n%s\nfailed with the following:\n%s\n%s",
366			cmd.String(), err.Error(), output)
367	}
368	cmd = exec.Command("git", "-C", roProjectDir, "commit", `--message="Initial commit"`, "--allow-empty")
369	output, err = cmd.CombinedOutput()
370	if err != nil {
371		t.Errorf("Command\n%s\nfailed with the following:\n%s\n%s",
372			cmd.String(), err.Error(), output)
373	}
374	linkPath := path.Join(codebaseDir, "symlink")
375	if err = os.Symlink(roProjectDir, linkPath); err != nil {
376		t.Error(err)
377	}
378	rwProjectDir := path.Join(codebaseDir, "editable-project")
379	if err = os.MkdirAll(rwProjectDir, os.ModePerm); err != nil {
380		t.Error(err)
381	}
382	cmd = exec.Command("git", "-C", rwProjectDir, "init")
383	output, err = cmd.CombinedOutput()
384	if err != nil {
385		t.Errorf("Command\n%s\nfailed with the following:\n%s\n%s",
386			cmd.String(), err.Error(), output)
387	}
388	cmd = exec.Command("git", "-C", rwProjectDir, "commit", `--message="Initial commit"`, "--allow-empty")
389	output, err = cmd.CombinedOutput()
390	if err != nil {
391		t.Errorf("Command\n%s\nfailed with the following:\n%s\n%s",
392			cmd.String(), err.Error(), output)
393	}
394	repoDir := path.Join(codebaseDir, ".repo")
395	if err = os.Mkdir(repoDir, os.ModePerm); err != nil {
396		t.Error(err)
397	}
398	listContents := []byte(projectList)
399	listPath := path.Join(repoDir, "project.list")
400	if err = ioutil.WriteFile(listPath, listContents, os.ModePerm); err != nil {
401		t.Error(err)
402	}
403	_, err = codebase.Add("test-codebase", codebaseDir)
404	if err != nil {
405		t.Error(err)
406	}
407	wsTempDir, err := ioutil.TempDir("", "workspace")
408	if err != nil {
409		t.Error(err)
410	}
411	defer os.RemoveAll(wsTempDir)
412	wsTopDir := path.Join(wsTempDir, "hacksaw")
413	if err = os.Mkdir(wsTopDir, os.ModePerm); err != nil {
414		t.Error(err)
415	}
416	pathBinder := bind.NewFakePathBinder()
417	ws := New(pathBinder, wsTopDir)
418	if _, err = ws.Create("test-workspace", "test-codebase"); err != nil {
419		t.Error(err)
420	}
421	workspaceDir, err := ws.GetDir("test-workspace")
422	if err != nil {
423		t.Error(err)
424	}
425	editPath := path.Join(workspaceDir, "editable-project")
426	_, _, err = ws.Edit(editPath)
427	if err != nil {
428		t.Error(err)
429	}
430	emptyFilePath := path.Join(editPath, "empty-edit")
431	emptyFile, err := os.Create(emptyFilePath)
432	if err != nil {
433		t.Error(err)
434	}
435	emptyFile.Close()
436	if _, err = ws.Recreate("test-workspace"); err != nil {
437		t.Error(err)
438	}
439	_, err = os.Stat(emptyFilePath)
440	if err != nil {
441		t.Error(err)
442	}
443	wsRoProjectDir := path.Join(workspaceDir, "read-only-project")
444	isRoPathBound := false
445	pathList, err := pathBinder.List()
446	if err != nil {
447		t.Error(err)
448	}
449	for _, path := range pathList {
450		if path == wsRoProjectDir {
451			isRoPathBound = true
452		}
453	}
454	if !isRoPathBound {
455		t.Error("Read only project was not mounted to the workspace")
456	}
457}
458