github.com/vanadium-archive/go.jiri@v0.0.0-20160715023856-abfb8b131290/profiles/profilescmdline/manager_test.go (about) 1 // Copyright 2015 The Vanadium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package profilescmdline_test 6 7 import ( 8 "bufio" 9 "bytes" 10 "flag" 11 "fmt" 12 "io/ioutil" 13 "os" 14 "path/filepath" 15 "reflect" 16 "regexp" 17 "runtime" 18 "strings" 19 "sync" 20 "testing" 21 22 "v.io/jiri" 23 "v.io/jiri/jiritest" 24 "v.io/jiri/profiles" 25 "v.io/jiri/profiles/profilescmdline" 26 "v.io/jiri/profiles/profilesreader" 27 "v.io/x/lib/envvar" 28 "v.io/x/lib/gosh" 29 ) 30 31 func TestManagerArgs(t *testing.T) { 32 profilescmdline.Reset() 33 p := parent 34 profilescmdline.RegisterManagementCommands(&p, false, "", "", jiri.ProfilesRootDir) 35 if got, want := len(p.Children), 6; got != want { 36 t.Errorf("got %v, want %v", got, want) 37 } 38 type cl struct { 39 args string 40 n int 41 } 42 cls := map[string]cl{ 43 "install": cl{"--profiles-db=db --profiles-dir=root --target=arch-os --env=a=b,c=d --force=false", 5}, 44 "uninstall": cl{"--profiles-db=db --profiles-dir=root --target=arch-os --all-targets --v", 5}, 45 "cleanup": cl{"--profiles-db=db --profiles-dir=root --gc --rm-all --v", 5}, 46 "update": cl{"--profiles-db=db --profiles-dir=root -v", 3}, 47 "available": cl{"-v", 1}, 48 } 49 for _, c := range p.Children { 50 args := cls[c.Name].args 51 if err := c.Flags.Parse(strings.Split(args, " ")); err != nil { 52 t.Errorf("failed to parse for %s: %s: %v", c.Name, args, err) 53 continue 54 } 55 if got, want := c.Flags.NFlag(), cls[c.Name].n; got != want { 56 t.Errorf("%s: got %v, want %v", c.Name, got, want) 57 } 58 } 59 } 60 61 var ( 62 buildInstallersOnce, buildJiriOnce sync.Once 63 buildInstallersBinDir, buildJiriBinDir = "", "" 64 ) 65 66 // TestMain must cleanup these directories created by this function. 67 func buildInstallers(t *testing.T) string { 68 buildInstallersOnce.Do(func() { 69 binDir, err := ioutil.TempDir("", "") 70 if err != nil { 71 t.Fatal(err) 72 } 73 sh := gosh.NewShell(t) 74 defer sh.Cleanup() 75 prefix := "v.io/jiri/profiles/profilescmdline/internal/" 76 gosh.BuildGoPkg(sh, binDir, "v.io/jiri/cmd/jiri", "-o", "jiri") 77 gosh.BuildGoPkg(sh, binDir, prefix+"i1", "-o", "jiri-profile-i1") 78 gosh.BuildGoPkg(sh, binDir, prefix+"i2", "-o", "jiri-profile-i2") 79 buildInstallersBinDir = binDir 80 }) 81 return buildInstallersBinDir 82 } 83 84 func TestMain(m *testing.M) { 85 flag.Parse() 86 r := m.Run() 87 if buildInstallersBinDir != "" { 88 os.RemoveAll(buildInstallersBinDir) 89 } 90 os.Exit(r) 91 } 92 93 func createProfilesDB(t *testing.T, jirix *jiri.X) { 94 if err := os.MkdirAll(jirix.ProfilesDBDir(), os.FileMode(0755)); err != nil { 95 t.Fatalf("%s:%s", loc(), err) 96 } 97 } 98 99 func buildJiri(t *testing.T) string { 100 buildJiriOnce.Do(func() { 101 binDir, err := ioutil.TempDir("", "") 102 if err != nil { 103 t.Fatal(err) 104 } 105 sh := gosh.NewShell(t) 106 defer sh.Cleanup() 107 gosh.BuildGoPkg(sh, binDir, "v.io/jiri/cmd/jiri", "-o", "jiri") 108 buildJiriBinDir = binDir 109 }) 110 return buildJiriBinDir 111 } 112 113 func run(sh *gosh.Shell, dir, bin string, args ...string) string { 114 cmd := sh.Cmd(filepath.Join(dir, bin), args...) 115 if testing.Verbose() { 116 cmd.PropagateOutput = true 117 } 118 return cmd.CombinedOutput() 119 } 120 121 func TestManagerAvailable(t *testing.T) { 122 fake, cleanup := jiritest.NewFakeJiriRoot(t) 123 defer cleanup() 124 dir, sh := buildInstallers(t), gosh.NewShell(t) 125 createProfilesDB(t, fake.X) 126 sh.Vars["JIRI_ROOT"] = fake.X.Root 127 sh.Vars["PATH"] = envvar.PrependUniqueToken(sh.Vars["PATH"], ":", dir) 128 stdout := run(sh, dir, "jiri", "profile", "available", "-v") 129 for _, installer := range []string{"i1", "i2"} { 130 re := regexp.MustCompile("Available Subcommands:.*profile-" + installer + ".*\n") 131 if got := stdout; !re.MatchString(got) { 132 t.Errorf("%v does not match %v\n", got, re.String()) 133 } 134 if got, want := stdout, installer+":eg"; !strings.Contains(got, want) { 135 t.Errorf("%v does not contain %v\n", got, want) 136 } 137 } 138 } 139 140 func loc() string { 141 _, file, line, _ := runtime.Caller(2) 142 return fmt.Sprintf("%s:%d", filepath.Base(file), line) 143 } 144 func exists(filename string) bool { 145 _, err := os.Stat(filename) 146 return err == nil 147 } 148 149 func contains(t *testing.T, filename, want string) { 150 o, err := ioutil.ReadFile(filename) 151 if err != nil { 152 t.Fatal(err) 153 } 154 if got := string(o); got != want { 155 t.Errorf("%s: %s: got %v, want %v", loc(), filename, got, want) 156 } 157 } 158 159 func cat(msg, filename string) { 160 o, err := ioutil.ReadFile(filename) 161 if err != nil { 162 panic(err) 163 } 164 fmt.Fprintln(os.Stderr, msg) 165 fmt.Fprintln(os.Stderr, string(o)) 166 fmt.Fprintln(os.Stderr, msg) 167 } 168 169 func removeDate(s string) string { 170 var result bytes.Buffer 171 scanner := bufio.NewScanner(bytes.NewBufferString(s)) 172 re := regexp.MustCompile("(.*) date=\".*\"") 173 for scanner.Scan() { 174 result.WriteString(re.ReplaceAllString(scanner.Text(), "$1")) 175 result.WriteString("\n") 176 } 177 return strings.TrimSpace(result.String()) 178 } 179 180 func cmpFiles(t *testing.T, gotFilename, wantFilename string) { 181 g, err := ioutil.ReadFile(gotFilename) 182 if err != nil { 183 t.Fatalf("%s: %s", loc(), err) 184 } 185 w, err := ioutil.ReadFile(wantFilename) 186 if err != nil { 187 t.Fatalf("%s: %s", loc(), err) 188 } 189 if got, want := removeDate(strings.TrimSpace(string(g))), removeDate(strings.TrimSpace(string(w))); got != want { 190 t.Errorf("%s: got %v, want %v from %q and %q", loc(), got, want, gotFilename, wantFilename) 191 } 192 } 193 194 func TestManagerInstallUninstall(t *testing.T) { 195 fake, cleanup := jiritest.NewFakeJiriRoot(t) 196 defer cleanup() 197 dir, sh := buildInstallers(t), gosh.NewShell(t) 198 createProfilesDB(t, fake.X) 199 sh.Vars["JIRI_ROOT"] = fake.X.Root 200 sh.Vars["PATH"] = envvar.PrependUniqueToken(sh.Vars["PATH"], ":", dir) 201 202 run(sh, dir, "jiri", "profile", "list", "-v") 203 204 i1 := filepath.Join(fake.X.Root, ".jiri_root/profile_db/i1") 205 i2 := filepath.Join(fake.X.Root, ".jiri_root/profile_db/i2") 206 207 run(sh, dir, "jiri", "profile", "install", "--target=arch-os", "i1:eg", "i2:eg") 208 for _, installer := range []string{"i1", "i2"} { 209 tdir := filepath.Join(fake.X.Root, jiri.ProfilesRootDir, installer, "eg", "arch_os") 210 contains(t, filepath.Join(tdir, "version"), "3") 211 contains(t, filepath.Join(tdir, "3"), "3") 212 } 213 cmpFiles(t, i1, filepath.Join("testdata", "i1a.xml")) 214 cmpFiles(t, i2, filepath.Join("testdata", "i2a.xml")) 215 216 run(sh, dir, "jiri", "profile", "install", "--target=arch-os@2", "i1:eg", "i2:eg") 217 // Installs are idempotent. 218 run(sh, dir, "jiri", "profile", "install", "--target=arch-os@2", "i1:eg", "i2:eg") 219 for _, installer := range []string{"i1", "i2"} { 220 tdir := filepath.Join(fake.X.Root, jiri.ProfilesRootDir, installer, "eg", "arch_os") 221 contains(t, filepath.Join(tdir, "version"), "2") 222 contains(t, filepath.Join(tdir, "3"), "3") 223 contains(t, filepath.Join(tdir, "2"), "2") 224 } 225 226 cmpFiles(t, i1, filepath.Join("testdata", "i1b.xml")) 227 cmpFiles(t, i2, filepath.Join("testdata", "i2b.xml")) 228 229 run(sh, dir, "jiri", "profile", "uninstall", "--target=arch-os@2", "i1:eg", "i2:eg") 230 for _, installer := range []string{"i1", "i2"} { 231 tdir := filepath.Join(fake.X.Root, jiri.ProfilesRootDir, installer, "eg", "arch_os") 232 contains(t, filepath.Join(tdir, "version"), "2") 233 contains(t, filepath.Join(tdir, "3"), "3") 234 if got, want := exists(filepath.Join(tdir, "2")), false; got != want { 235 t.Errorf("%s: got %v, want %v", filepath.Join(tdir, "2"), got, want) 236 } 237 } 238 cmpFiles(t, i1, filepath.Join("testdata", "i1c.xml")) 239 cmpFiles(t, i2, filepath.Join("testdata", "i2c.xml")) 240 241 // Put v2 back. 242 run(sh, dir, "jiri", "profile", "list", "-v") 243 run(sh, dir, "jiri", "profile", "install", "--target=arch-os@2", "i1:eg", "i2:eg") 244 cmpFiles(t, i1, filepath.Join("testdata", "i1b.xml")) 245 cmpFiles(t, i2, filepath.Join("testdata", "i2b.xml")) 246 } 247 248 func TestManagerUpdate(t *testing.T) { 249 fake, cleanup := jiritest.NewFakeJiriRoot(t) 250 defer cleanup() 251 dir, sh := buildInstallers(t), gosh.NewShell(t) 252 createProfilesDB(t, fake.X) 253 sh.Vars["JIRI_ROOT"] = fake.X.Root 254 sh.Vars["PATH"] = envvar.PrependUniqueToken(sh.Vars["PATH"], ":", dir) 255 256 i1 := filepath.Join(fake.X.ProfilesDBDir(), "i1") 257 i2 := filepath.Join(fake.X.ProfilesDBDir(), "i2") 258 259 run(sh, dir, "jiri", "profile", "install", "--target=arch-os@2", "i1:eg", "i2:eg") 260 cmpFiles(t, i1, filepath.Join("testdata", "i1d.xml")) 261 cmpFiles(t, i2, filepath.Join("testdata", "i2d.xml")) 262 263 run(sh, dir, "jiri", "profile", "update") 264 cmpFiles(t, i1, filepath.Join("testdata", "i1e.xml")) 265 cmpFiles(t, i2, filepath.Join("testdata", "i2e.xml")) 266 267 run(sh, dir, "jiri", "profile", "cleanup", "-gc") 268 cmpFiles(t, i1, filepath.Join("testdata", "i1f.xml")) 269 cmpFiles(t, i2, filepath.Join("testdata", "i2f.xml")) 270 271 run(sh, dir, "jiri", "profile", "cleanup", "-rm-all") 272 profiledir := filepath.Join(fake.X.Root, jiri.ProfilesRootDir) 273 for _, dir := range []string{ 274 fake.X.ProfilesDBDir(), 275 filepath.Join(profiledir, "i1"), 276 filepath.Join(profiledir, "i2"), 277 } { 278 _, err := os.Stat(dir) 279 if !os.IsNotExist(err) { 280 t.Errorf("%v still exists: %v", dir, err) 281 } 282 } 283 // Start over, make sure update is idempotent. 284 createProfilesDB(t, fake.X) 285 run(sh, dir, "jiri", "profile", "install", "--target=arch-os@2", "i1:eg") 286 run(sh, dir, "jiri", "profile", "update") 287 run(sh, dir, "jiri", "profile", "update") 288 cmpFiles(t, i1, filepath.Join("testdata", "i1g.xml")) 289 run(sh, dir, "jiri", "profile", "install", "--target=arch-os@4", "i1:eg") 290 run(sh, dir, "jiri", "profile", "update") 291 cmpFiles(t, i1, filepath.Join("testdata", "i1h.xml")) 292 } 293 294 func TestList(t *testing.T) { 295 fake, cleanup := jiritest.NewFakeJiriRoot(t) 296 defer cleanup() 297 dir, sh := buildInstallers(t), gosh.NewShell(t) 298 sh.Vars["JIRI_ROOT"] = fake.X.Root 299 sh.Vars["PATH"] = envvar.PrependUniqueToken(os.Getenv("PATH"), ":", dir) 300 run(sh, dir, "jiri", "profile", "install", "--target=arch-os@2", "i1:eg", "i2:eg") 301 if got, want := run(sh, dir, "jiri", "profile", "list", "--target=arch-os"), 302 "i1:eg, i2:eg\n"; got != want { 303 t.Errorf("got %v, want %v", got, want) 304 } 305 if got, want := run(sh, dir, "jiri", "profile", "list"), "i1:eg, i2:eg\n"; got != want { 306 t.Errorf("got %v, want %v", got, want) 307 } 308 for _, arg := range []string{"", "--info=SchemaVersion"} { 309 sh.ContinueOnError = true 310 sh.Err = nil 311 got := run(sh, dir, "jiri", "profile", "list", "--target=no-suchtarget", arg) 312 if sh.Err == nil { 313 t.Errorf("expected an error for: jiri profile list --target=no-suchtarget %s", arg) 314 } 315 if want := "ERROR: no matching targets for no-suchtarget@\n"; got != want { 316 t.Errorf("got %v, want %v", got, want) 317 } 318 } 319 } 320 321 // Test using a fake jiri root. 322 func TestJiriFakeRoot(t *testing.T) { 323 fake, cleanup := jiritest.NewFakeJiriRoot(t) 324 defer cleanup() 325 profilesDBDir := filepath.Join(fake.X.Root, jiri.ProfilesDBDir) 326 pdb := profiles.NewDB() 327 t1, err := profiles.NewTarget("cpu1-os1@1", "A=B,C=D") 328 if err != nil { 329 t.Fatal(err) 330 } 331 pdb.InstallProfile("test", "b", "") 332 if err := pdb.AddProfileTarget("test", "b", t1); err != nil { 333 t.Fatal(err) 334 } 335 if err := pdb.Write(fake.X, "test", profilesDBDir); err != nil { 336 t.Fatal(err) 337 } 338 339 rd, err := profilesreader.NewReader(fake.X, profilesreader.UseProfiles, profilesDBDir) 340 if err != nil { 341 t.Fatal(err) 342 } 343 344 if got, want := rd.ProfileNames(), []string{"test:b"}; !reflect.DeepEqual(got, want) { 345 t.Errorf("got %v, want %v", got, want) 346 } 347 348 dir, sh := buildJiri(t), gosh.NewShell(t) 349 sh.Vars["JIRI_ROOT"] = fake.X.Root 350 sh.Vars["PATH"] = envvar.PrependUniqueToken(sh.Vars["PATH"], ":", dir) 351 run(sh, dir, "jiri", "profile", "list", "-v") 352 }