go.fuchsia.dev/jiri@v0.0.0-20240502161911-b66513b29486/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  	"go.fuchsia.dev/jiri"
    15  	"go.fuchsia.dev/jiri/gitutil"
    16  	"go.fuchsia.dev/jiri/jiritest"
    17  	"go.fuchsia.dev/jiri/project"
    18  	"go.fuchsia.dev/jiri/tool"
    19  )
    20  
    21  func checkReadme(t *testing.T, jirix *jiri.X, project, message string) {
    22  	if _, err := os.Stat(project); err != nil {
    23  		t.Fatalf("%v", err)
    24  	}
    25  	readmeFile := filepath.Join(project, "README")
    26  	data, err := os.ReadFile(readmeFile)
    27  	if err != nil {
    28  		t.Fatalf("%v", err)
    29  	}
    30  	if got, want := data, []byte(message); bytes.Compare(got, want) != 0 {
    31  		t.Fatalf("unexpected content %v:\ngot\n%s\nwant\n%s\n", project, got, want)
    32  	}
    33  }
    34  
    35  func localProjectName(i int) string {
    36  	return "test-local-project-" + fmt.Sprintf("%d", i+1)
    37  }
    38  
    39  func remoteProjectName(i int) string {
    40  	return "test-remote-project-" + fmt.Sprintf("%d", i+1)
    41  }
    42  
    43  func writeReadme(t *testing.T, jirix *jiri.X, projectDir, message string) {
    44  	path, perm := filepath.Join(projectDir, "README"), os.FileMode(0644)
    45  	if err := os.WriteFile(path, []byte(message), perm); err != nil {
    46  		t.Fatalf("%s", err)
    47  	}
    48  	cwd, err := os.Getwd()
    49  	if err != nil {
    50  		t.Fatalf("%s", err)
    51  	}
    52  	defer os.Chdir(cwd)
    53  	if err := os.Chdir(projectDir); err != nil {
    54  		t.Fatalf("%s", err)
    55  	}
    56  	if err := gitutil.New(jirix, gitutil.UserNameOpt("John Doe"), gitutil.UserEmailOpt("john.doe@example.com")).CommitFile(path, "creating README"); err != nil {
    57  		t.Fatalf("%s", err)
    58  	}
    59  }
    60  
    61  // TestSnapshot tests creating and checking out a snapshot.
    62  func TestSnapshot(t *testing.T) {
    63  	fake, cleanup := jiritest.NewFakeJiriRoot(t)
    64  	defer cleanup()
    65  
    66  	// Setup the initial remote and local projects.
    67  	numProjects, remoteProjects := 2, []string{}
    68  	for i := 0; i < numProjects; i++ {
    69  		if err := fake.CreateRemoteProject(remoteProjectName(i)); err != nil {
    70  			t.Fatalf("%v", err)
    71  		}
    72  		if err := fake.AddProject(project.Project{
    73  			Name:   remoteProjectName(i),
    74  			Path:   localProjectName(i),
    75  			Remote: fake.Projects[remoteProjectName(i)],
    76  		}); err != nil {
    77  			t.Fatalf("%v", err)
    78  		}
    79  	}
    80  
    81  	// Create initial commits in the remote projects and use UpdateUniverse()
    82  	// to mirror them locally.
    83  	for i := 0; i < numProjects; i++ {
    84  		writeReadme(t, fake.X, fake.Projects[remoteProjectName(i)], "revision 1")
    85  	}
    86  	if err := project.UpdateUniverse(fake.X, true, false, false, false, false, true /*run-hooks*/, true /*run-packages*/, false /*rebase-subdmodules*/, project.DefaultHookTimeout, project.DefaultPackageTimeout, nil); err != nil {
    87  		t.Fatalf("%v", err)
    88  	}
    89  
    90  	// Create a snapshot.
    91  	var stdout bytes.Buffer
    92  	fake.X.Context = tool.NewContext(tool.ContextOpts{Stdout: &stdout, Env: fake.X.Context.Env()})
    93  
    94  	tmpfile, err := os.CreateTemp("", "jiri-snapshot-")
    95  	if err != nil {
    96  		t.Fatal(err)
    97  	}
    98  	defer os.Remove(tmpfile.Name())
    99  
   100  	if err := runSnapshot(fake.X, []string{tmpfile.Name()}); err != nil {
   101  		t.Fatalf("%v", err)
   102  	}
   103  
   104  	// Remove the local project repositories.
   105  	for i := range remoteProjects {
   106  		localProject := filepath.Join(fake.X.Root, localProjectName(i))
   107  		if err := os.RemoveAll(localProject); err != nil {
   108  			t.Fatalf("%v", err)
   109  		}
   110  	}
   111  
   112  	snapshotFile := tmpfile.Name()
   113  	if err := project.CheckoutSnapshot(fake.X, snapshotFile, false, true /*run-hooks*/, true /*run-packages*/, project.DefaultHookTimeout, project.DefaultPackageTimeout, nil); err != nil {
   114  		t.Fatalf("%s", err)
   115  	}
   116  	for i := range remoteProjects {
   117  		localProject := filepath.Join(fake.X.Root, localProjectName(i))
   118  		checkReadme(t, fake.X, localProject, "revision 1")
   119  	}
   120  }
   121  
   122  // TestCipdSnapshot tests creating cipd snapshot files.
   123  func TestCipdSnapshot(t *testing.T) {
   124  	fake, cleanup := jiritest.NewFakeJiriRoot(t)
   125  	defer cleanup()
   126  
   127  	// Setup fake packages
   128  	fake.AddPackage(project.Package{
   129  		Name:       "test_package",
   130  		Path:       "path-to-test-package",
   131  		Version:    "git_revision:05715c8fbbdb952ab38e50533a1b653445e74b40",
   132  		Attributes: "",
   133  	})
   134  	fake.AddPackage(project.Package{
   135  		Name:       "test_package_internal",
   136  		Path:       "path-to-test-package-internal",
   137  		Version:    "git_revision:05715c8fbbdb952ab38e50533a1b653445e74b41",
   138  		Attributes: "",
   139  		Internal:   true,
   140  	})
   141  
   142  	// Create a snapshot.
   143  	var stdout bytes.Buffer
   144  	fake.X.Context = tool.NewContext(tool.ContextOpts{Stdout: &stdout, Env: fake.X.Context.Env()})
   145  
   146  	tmpfile, err := os.CreateTemp("", "jiri-snapshot-")
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  	defer os.Remove(tmpfile.Name())
   151  
   152  	if err := project.CreateSnapshot(fake.X, tmpfile.Name(), nil, nil, true, true /*cipdEnsureFlag*/); err != nil {
   153  		t.Fatalf("%v", err)
   154  	}
   155  	pathExists := func(pkgPath string) bool {
   156  		if _, err := os.Stat(pkgPath); err != nil {
   157  			if os.IsNotExist(err) {
   158  				return false
   159  			}
   160  			t.Errorf("failed to access path due to error: %v", err)
   161  		}
   162  		return true
   163  	}
   164  	assertExist := func(localPath string) {
   165  		if !pathExists(localPath) {
   166  			t.Errorf("expecting path %q exists, but it does not", localPath)
   167  		}
   168  	}
   169  
   170  	// Verify cipd snapshot files were generated.
   171  	ensureFilePath := tmpfile.Name() + ".ensure"
   172  	ensureFileIntPath := tmpfile.Name() + "_internal.ensure"
   173  	versionFilePath := tmpfile.Name() + ".version"
   174  	versionFileIntPath := tmpfile.Name() + "_internal.version"
   175  	assertExist(ensureFilePath)
   176  	assertExist(ensureFileIntPath)
   177  	assertExist(versionFilePath)
   178  	assertExist(versionFileIntPath)
   179  	os.Remove(ensureFilePath)
   180  	os.Remove(ensureFileIntPath)
   181  	os.Remove(versionFilePath)
   182  	os.Remove(versionFileIntPath)
   183  }