github.com/vanadium-archive/go.jiri@v0.0.0-20160715023856-abfb8b131290/cmd/jiri/snapshot_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 main 6 7 import ( 8 "bytes" 9 "fmt" 10 "os" 11 "path/filepath" 12 "testing" 13 14 "v.io/jiri" 15 "v.io/jiri/gitutil" 16 "v.io/jiri/jiritest" 17 "v.io/jiri/project" 18 "v.io/jiri/tool" 19 ) 20 21 func createLabelDir(t *testing.T, jirix *jiri.X, snapshotDir, name string, snapshots []string) { 22 if snapshotDir == "" { 23 snapshotDir = filepath.Join(jirix.Root, defaultSnapshotDir) 24 } 25 s := jirix.NewSeq() 26 labelDir, perm := filepath.Join(snapshotDir, "labels", name), os.FileMode(0700) 27 if err := s.MkdirAll(labelDir, perm).Done(); err != nil { 28 t.Fatalf("MkdirAll(%v, %v) failed: %v", labelDir, perm, err) 29 } 30 for i, snapshot := range snapshots { 31 path := filepath.Join(labelDir, snapshot) 32 _, err := os.Create(path) 33 if err != nil { 34 t.Fatalf("%v", err) 35 } 36 if i == 0 { 37 symlinkPath := filepath.Join(snapshotDir, name) 38 if err := s.Symlink(path, symlinkPath).Done(); err != nil { 39 t.Fatalf("Symlink(%v, %v) failed: %v", path, symlinkPath, err) 40 } 41 } 42 } 43 } 44 45 func generateOutput(labels []label) string { 46 output := "" 47 for _, label := range labels { 48 output += fmt.Sprintf("snapshots of label %q:\n", label.name) 49 for _, snapshot := range label.snapshots { 50 output += fmt.Sprintf(" %v\n", snapshot) 51 } 52 } 53 return output 54 } 55 56 type config struct { 57 remote bool 58 dir string 59 } 60 61 type label struct { 62 name string 63 snapshots []string 64 } 65 66 func TestList(t *testing.T) { 67 resetFlags() 68 fake, cleanup := jiritest.NewFakeJiriRoot(t) 69 defer cleanup() 70 71 snapshotDir1 := "" // Should use default dir. 72 snapshotDir2 := filepath.Join(fake.X.Root, "some/other/dir") 73 74 // Create a test suite. 75 tests := []config{ 76 config{ 77 dir: snapshotDir1, 78 }, 79 config{ 80 dir: snapshotDir2, 81 }, 82 } 83 labels := []label{ 84 label{ 85 name: "beta", 86 snapshots: []string{"beta-1", "beta-2", "beta-3"}, 87 }, 88 label{ 89 name: "stable", 90 snapshots: []string{"stable-1", "stable-2", "stable-3"}, 91 }, 92 } 93 94 for _, test := range tests { 95 snapshotDirFlag = test.dir 96 // Create the snapshots directory and populate it with the 97 // data specified by the test suite. 98 for _, label := range labels { 99 createLabelDir(t, fake.X, test.dir, label.name, label.snapshots) 100 } 101 102 // Check that running "jiri snapshot list" with no arguments 103 // returns the expected output. 104 var stdout bytes.Buffer 105 fake.X.Context = tool.NewContext(tool.ContextOpts{Stdout: &stdout}) 106 if err := runSnapshotList(fake.X, nil); err != nil { 107 t.Fatalf("%v", err) 108 } 109 got, want := stdout.String(), generateOutput(labels) 110 if got != want { 111 t.Fatalf("unexpected output:\ngot\n%v\nwant\n%v\n", got, want) 112 } 113 114 // Check that running "jiri snapshot list" with one argument 115 // returns the expected output. 116 stdout.Reset() 117 if err := runSnapshotList(fake.X, []string{"stable"}); err != nil { 118 t.Fatalf("%v", err) 119 } 120 got, want = stdout.String(), generateOutput(labels[1:]) 121 if got != want { 122 t.Fatalf("unexpected output:\ngot\n%v\nwant\n%v\n", got, want) 123 } 124 125 // Check that running "jiri snapshot list" with 126 // multiple arguments returns the expected output. 127 stdout.Reset() 128 if err := runSnapshotList(fake.X, []string{"beta", "stable"}); err != nil { 129 t.Fatalf("%v", err) 130 } 131 got, want = stdout.String(), generateOutput(labels) 132 if got != want { 133 t.Fatalf("unexpected output:\ngot\n%v\nwant\n%v\n", got, want) 134 } 135 } 136 } 137 138 func checkReadme(t *testing.T, jirix *jiri.X, project, message string) { 139 s := jirix.NewSeq() 140 if _, err := s.Stat(project); err != nil { 141 t.Fatalf("%v", err) 142 } 143 readmeFile := filepath.Join(project, "README") 144 data, err := s.ReadFile(readmeFile) 145 if err != nil { 146 t.Fatalf("%v", err) 147 } 148 if got, want := data, []byte(message); bytes.Compare(got, want) != 0 { 149 t.Fatalf("unexpected content %v:\ngot\n%s\nwant\n%s\n", project, got, want) 150 } 151 } 152 153 func localProjectName(i int) string { 154 return "test-local-project-" + fmt.Sprintf("%d", i+1) 155 } 156 157 func remoteProjectName(i int) string { 158 return "test-remote-project-" + fmt.Sprintf("%d", i+1) 159 } 160 161 func writeReadme(t *testing.T, jirix *jiri.X, projectDir, message string) { 162 s := jirix.NewSeq() 163 path, perm := filepath.Join(projectDir, "README"), os.FileMode(0644) 164 if err := s.WriteFile(path, []byte(message), perm).Done(); err != nil { 165 t.Fatalf("%v", err) 166 } 167 cwd, err := os.Getwd() 168 if err != nil { 169 t.Fatalf("%v", err) 170 } 171 defer jirix.NewSeq().Chdir(cwd) 172 if err := s.Chdir(projectDir).Done(); err != nil { 173 t.Fatalf("%v", err) 174 } 175 if err := gitutil.New(jirix.NewSeq()).CommitFile(path, "creating README"); err != nil { 176 t.Fatalf("%v", err) 177 } 178 } 179 180 func resetFlags() { 181 snapshotDirFlag = "" 182 pushRemoteFlag = false 183 } 184 185 func TestGetSnapshotDir(t *testing.T) { 186 resetFlags() 187 defer resetFlags() 188 fake, cleanup := jiritest.NewFakeJiriRoot(t) 189 defer cleanup() 190 191 // With all flags at default values, snapshot dir should be default. 192 resetFlags() 193 got, err := getSnapshotDir(fake.X) 194 if err != nil { 195 t.Fatalf("getSnapshotDir() failed: %v\n", err) 196 } 197 if want := filepath.Join(fake.X.Root, defaultSnapshotDir); got != want { 198 t.Errorf("unexpected snapshot dir: got %v want %v", got, want) 199 } 200 201 // With dir flag set to absolute path, snapshot dir should be value of dir 202 // flag. 203 resetFlags() 204 tempDir, err := fake.X.NewSeq().TempDir("", "") 205 if err != nil { 206 t.Fatalf("TempDir() failed: %v", err) 207 } 208 defer fake.X.NewSeq().RemoveAll(tempDir).Done() 209 snapshotDirFlag = tempDir 210 got, err = getSnapshotDir(fake.X) 211 if err != nil { 212 t.Fatalf("getSnapshotDir() failed: %v\n", err) 213 } 214 if want := snapshotDirFlag; got != want { 215 t.Errorf("unexpected snapshot dir: got %v want %v", got, want) 216 } 217 218 // With dir flag set to relative path, snapshot dir should absolute path 219 // rooted at current working dir. 220 resetFlags() 221 snapshotDirFlag = "some/relative/path" 222 cwd, err := os.Getwd() 223 if err != nil { 224 t.Fatalf("os.Getwd() failed: %v", err) 225 } 226 defer fake.X.NewSeq().RemoveAll(filepath.Join(cwd, "some")) 227 got, err = getSnapshotDir(fake.X) 228 if err != nil { 229 t.Fatalf("getSnapshotDir() failed: %v\n", err) 230 } 231 if want := filepath.Join(cwd, snapshotDirFlag); got != want { 232 t.Errorf("unexpected snapshot dir: got %v want %v", got, want) 233 } 234 } 235 236 // TestCreate tests creating and checking out a snapshot. 237 func TestCreate(t *testing.T) { 238 resetFlags() 239 defer resetFlags() 240 fake, cleanup := jiritest.NewFakeJiriRoot(t) 241 defer cleanup() 242 s := fake.X.NewSeq() 243 244 // Setup the initial remote and local projects. 245 numProjects, remoteProjects := 2, []string{} 246 for i := 0; i < numProjects; i++ { 247 if err := fake.CreateRemoteProject(remoteProjectName(i)); err != nil { 248 t.Fatalf("%v", err) 249 } 250 if err := fake.AddProject(project.Project{ 251 Name: remoteProjectName(i), 252 Path: localProjectName(i), 253 Remote: fake.Projects[remoteProjectName(i)], 254 }); err != nil { 255 t.Fatalf("%v", err) 256 } 257 } 258 259 // Create initial commits in the remote projects and use UpdateUniverse() 260 // to mirror them locally. 261 for i := 0; i < numProjects; i++ { 262 writeReadme(t, fake.X, fake.Projects[remoteProjectName(i)], "revision 1") 263 } 264 if err := project.UpdateUniverse(fake.X, true); err != nil { 265 t.Fatalf("%v", err) 266 } 267 268 // Create a snapshot. 269 var stdout bytes.Buffer 270 fake.X.Context = tool.NewContext(tool.ContextOpts{Stdout: &stdout}) 271 if err := runSnapshotCreate(fake.X, []string{"test-local"}); err != nil { 272 t.Fatalf("%v", err) 273 } 274 275 // Remove the local project repositories. 276 for i, _ := range remoteProjects { 277 localProject := filepath.Join(fake.X.Root, localProjectName(i)) 278 if err := s.RemoveAll(localProject).Done(); err != nil { 279 t.Fatalf("%v", err) 280 } 281 } 282 283 // Check that invoking the UpdateUniverse() with the snapshot restores the 284 // local repositories. 285 snapshotDir := filepath.Join(fake.X.Root, defaultSnapshotDir) 286 snapshotFile := filepath.Join(snapshotDir, "test-local") 287 localX := fake.X.Clone(tool.ContextOpts{ 288 Manifest: &snapshotFile, 289 }) 290 if err := project.UpdateUniverse(localX, true); err != nil { 291 t.Fatalf("%v", err) 292 } 293 for i, _ := range remoteProjects { 294 localProject := filepath.Join(fake.X.Root, localProjectName(i)) 295 checkReadme(t, fake.X, localProject, "revision 1") 296 } 297 } 298 299 // TestCreatePushRemote checks that creating a snapshot with the -push-remote 300 // flag causes the snapshot to be committed and pushed upstream. 301 func TestCreatePushRemote(t *testing.T) { 302 resetFlags() 303 defer resetFlags() 304 305 fake, cleanup := jiritest.NewFakeJiriRoot(t) 306 defer cleanup() 307 308 fake.EnableRemoteManifestPush() 309 defer fake.DisableRemoteManifestPush() 310 311 manifestDir := filepath.Join(fake.X.Root, "manifest") 312 snapshotDir := filepath.Join(manifestDir, "snapshot") 313 label := "test" 314 315 git := gitutil.New(fake.X.NewSeq(), gitutil.RootDirOpt(manifestDir)) 316 commitCount, err := git.CountCommits("master", "") 317 if err != nil { 318 t.Fatalf("git.CountCommits(\"master\", \"\") failed: %v", err) 319 } 320 321 // Create snapshot with -push-remote flag set to true. 322 snapshotDirFlag = snapshotDir 323 pushRemoteFlag = true 324 if err := runSnapshotCreate(fake.X, []string{label}); err != nil { 325 t.Fatalf("%v", err) 326 } 327 328 // Check that repo has one new commit. 329 newCommitCount, err := git.CountCommits("master", "") 330 if err != nil { 331 t.Fatalf("git.CountCommits(\"master\", \"\") failed: %v", err) 332 } 333 if got, want := newCommitCount, commitCount+1; got != want { 334 t.Errorf("unexpected commit count: got %v want %v", got, want) 335 } 336 337 // Check that new label is commited. 338 labelFile := filepath.Join(snapshotDir, "labels", label) 339 if !git.IsFileCommitted(labelFile) { 340 t.Errorf("expected file %v to be committed but it was not", labelFile) 341 } 342 }