go.fuchsia.dev/jiri@v0.0.0-20240502161911-b66513b29486/cmd/jiri/override_test.go (about)

     1  // Copyright 2018 The Fuchsia 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  	"fmt"
     9  	"os"
    10  	"strings"
    11  	"testing"
    12  
    13  	"go.fuchsia.dev/jiri/jiritest/xtest"
    14  	"go.fuchsia.dev/jiri/project"
    15  )
    16  
    17  type overrideTestCase struct {
    18  	Args           []string
    19  	Filename       string
    20  	OutputFileName string
    21  	Exist, Want    string
    22  	Stdout, Stderr string
    23  	SetFlags       func()
    24  	runOnce        bool
    25  }
    26  
    27  func setDefaultOverrideFlags() {
    28  	overrideFlags.importManifest = ""
    29  	overrideFlags.path = ""
    30  	overrideFlags.revision = ""
    31  	overrideFlags.gerritHost = ""
    32  	overrideFlags.delete = false
    33  	overrideFlags.list = false
    34  	overrideFlags.JSONOutput = ""
    35  }
    36  
    37  func TestOverride(t *testing.T) {
    38  	tests := []overrideTestCase{
    39  		{
    40  			Stderr: `wrong number of arguments`,
    41  		},
    42  		{
    43  			Args:   []string{"a"},
    44  			Stderr: `wrong number of arguments`,
    45  		},
    46  		{
    47  			Args:   []string{"a", "b", "c"},
    48  			Stderr: `wrong number of arguments`,
    49  		},
    50  		// Remote imports, default append behavior
    51  		{
    52  			Args: []string{"foo", "https://github.com/new.git"},
    53  			Want: `<manifest>
    54    <imports>
    55      <import manifest="manifest" name="foo" remote="https://github.com/new.git"/>
    56    </imports>
    57    <overrides>
    58      <project name="foo" remote="https://github.com/new.git"/>
    59    </overrides>
    60  </manifest>
    61  `,
    62  		},
    63  		{
    64  			SetFlags: func() {
    65  				overrideFlags.path = "bar"
    66  			},
    67  			Args: []string{"foo", "https://github.com/new.git"},
    68  			Want: `<manifest>
    69    <imports>
    70      <import manifest="manifest" name="foo" remote="https://github.com/new.git"/>
    71    </imports>
    72    <overrides>
    73      <project name="foo" path="bar" remote="https://github.com/new.git"/>
    74    </overrides>
    75  </manifest>
    76  `,
    77  		},
    78  		{
    79  			SetFlags: func() {
    80  				overrideFlags.revision = "bar"
    81  			},
    82  			Args: []string{"foo", "https://github.com/new.git"},
    83  			Want: `<manifest>
    84    <imports>
    85      <import manifest="manifest" name="foo" remote="https://github.com/new.git"/>
    86    </imports>
    87    <overrides>
    88      <project name="foo" remote="https://github.com/new.git" revision="bar"/>
    89    </overrides>
    90  </manifest>
    91  `,
    92  		},
    93  		{
    94  			SetFlags: func() {
    95  				overrideFlags.list = true
    96  				overrideFlags.JSONOutput = "file"
    97  			},
    98  			Exist: `<manifest>
    99    <imports>
   100      <import manifest="manifest" name="orig" remote="https://github.com/orig.git"/>
   101    </imports>
   102    <overrides>
   103      <project name="foo" remote="https://github.com/new.git"/>
   104    </overrides>
   105  </manifest>
   106  `,
   107  			OutputFileName: `file`,
   108  			Want: `[
   109    {
   110      "name": "foo",
   111      "remote": "https://github.com/new.git",
   112      "revision": "HEAD"
   113    }
   114  ]
   115  `,
   116  		},
   117  		{
   118  			SetFlags: func() {
   119  				overrideFlags.list = true
   120  			},
   121  			Exist: `<manifest>
   122    <imports>
   123      <import manifest="manifest" name="orig" remote="https://github.com/orig.git"/>
   124    </imports>
   125    <overrides>
   126      <project name="foo" remote="https://github.com/new.git"/>
   127    </overrides>
   128  </manifest>
   129  `,
   130  			Stdout: `* override foo
   131    Name:        foo
   132    Remote:      https://github.com/new.git
   133  `,
   134  		},
   135  		{
   136  			Args: []string{"bar", "https://github.com/bar.git"},
   137  			Exist: `<manifest>
   138    <imports>
   139      <import manifest="manifest" name="orig" remote="https://github.com/orig.git"/>
   140    </imports>
   141    <overrides>
   142      <project name="foo" remote="https://github.com/foo.git"/>
   143    </overrides>
   144  </manifest>
   145  `,
   146  			Want: `<manifest>
   147    <imports>
   148      <import manifest="manifest" name="orig" remote="https://github.com/orig.git"/>
   149    </imports>
   150    <overrides>
   151      <project name="foo" remote="https://github.com/foo.git"/>
   152      <project name="bar" remote="https://github.com/bar.git"/>
   153    </overrides>
   154  </manifest>
   155  `,
   156  		},
   157  		// test delete flag
   158  		{
   159  			SetFlags: func() {
   160  				overrideFlags.delete = true
   161  			},
   162  			Stderr:  `wrong number of arguments`,
   163  			runOnce: true,
   164  		},
   165  		{
   166  			SetFlags: func() {
   167  				overrideFlags.delete = true
   168  			},
   169  			Args:    []string{"a", "b", "c"},
   170  			Stderr:  `wrong number of arguments`,
   171  			runOnce: true,
   172  		},
   173  		{
   174  			SetFlags: func() {
   175  				overrideFlags.delete = true
   176  				overrideFlags.list = true
   177  			},
   178  			Args:    []string{"a", "b"},
   179  			Stderr:  `cannot use -delete and -list together`,
   180  			runOnce: true,
   181  		},
   182  		{
   183  			SetFlags: func() {
   184  				overrideFlags.delete = true
   185  			},
   186  			Args:    []string{"foo"},
   187  			runOnce: true,
   188  			Exist: `<manifest>
   189    <imports>
   190      <import manifest="manifest" name="orig" remote="https://github.com/orig.git"/>
   191    </imports>
   192    <overrides>
   193      <project name="foo" remote="https://github.com/foo.git"/>
   194      <project name="bar" remote="https://github.com/bar.git"/>
   195    </overrides>
   196  </manifest>
   197  `,
   198  			Want: `<manifest>
   199    <imports>
   200      <import manifest="manifest" name="orig" remote="https://github.com/orig.git"/>
   201    </imports>
   202    <overrides>
   203      <project name="bar" remote="https://github.com/bar.git"/>
   204    </overrides>
   205  </manifest>
   206  `,
   207  		},
   208  		{
   209  			SetFlags: func() {
   210  				overrideFlags.delete = true
   211  			},
   212  			Args:    []string{"foo"},
   213  			runOnce: true,
   214  			Exist: `<manifest>
   215    <imports>
   216      <import manifest="manifest" name="orig" remote="https://github.com/orig.git"/>
   217    </imports>
   218    <overrides>
   219      <project name="foo" remote="https://github.com/foo.git"/>
   220      <project name="foo" remote="https://github.com/bar.git"/>
   221    </overrides>
   222  </manifest>
   223  `,
   224  			Stderr: `more than one override matches`,
   225  		},
   226  		{
   227  			SetFlags: func() {
   228  				overrideFlags.delete = true
   229  			},
   230  			Args:    []string{"foo", "https://github.com/bar.git"},
   231  			runOnce: true,
   232  			Exist: `<manifest>
   233    <imports>
   234      <import manifest="manifest" name="orig" remote="https://github.com/orig.git"/>
   235    </imports>
   236    <overrides>
   237      <project name="foo" remote="https://github.com/foo.git"/>
   238      <project name="foo" remote="https://github.com/bar.git"/>
   239    </overrides>
   240  </manifest>
   241  `,
   242  			Want: `<manifest>
   243    <imports>
   244      <import manifest="manifest" name="orig" remote="https://github.com/orig.git"/>
   245    </imports>
   246    <overrides>
   247      <project name="foo" remote="https://github.com/foo.git"/>
   248    </overrides>
   249  </manifest>
   250  `,
   251  		},
   252  		{
   253  			SetFlags: func() {
   254  				overrideFlags.importManifest = "manifest"
   255  				overrideFlags.revision = "eabeadae97b1e7f97ba93206066411adfe93a509"
   256  			},
   257  			Args:    []string{"orig", "https://github.com/orig.git"},
   258  			runOnce: true,
   259  			Exist: `<manifest>
   260    <imports>
   261      <import manifest="manifest" name="orig" remote="https://github.com/orig.git"/>
   262    </imports>
   263  </manifest>
   264  `,
   265  			Want: `<manifest>
   266    <imports>
   267      <import manifest="manifest" name="orig" remote="https://github.com/orig.git"/>
   268    </imports>
   269    <overrides>
   270      <import manifest="manifest" name="orig" remote="https://github.com/orig.git" revision="eabeadae97b1e7f97ba93206066411adfe93a509"/>
   271    </overrides>
   272  </manifest>
   273  `,
   274  		},
   275  	}
   276  
   277  	// Temporary directory in which our jiri binary will live.
   278  	binDir, err := os.MkdirTemp("", "")
   279  	if err != nil {
   280  		t.Fatal(err)
   281  	}
   282  	defer os.RemoveAll(binDir)
   283  
   284  	for _, test := range tests {
   285  		if err := testOverride(t, test); err != nil {
   286  			t.Errorf("%v: %v", test.Args, err)
   287  		}
   288  	}
   289  }
   290  
   291  func testOverride(t *testing.T, test overrideTestCase) error {
   292  	jirix, cleanup := xtest.NewX(t)
   293  	defer cleanup()
   294  	// Temporary directory in which to run `jiri import`.
   295  	tmpDir, err := os.MkdirTemp("", "")
   296  	if err != nil {
   297  		return err
   298  	}
   299  	defer os.RemoveAll(tmpDir)
   300  
   301  	// Create a .jiri_manifest file which imports the manifest created above.
   302  	manifest := project.Manifest{
   303  		Imports: []project.Import{
   304  			{
   305  				Manifest: "manifest",
   306  				Name:     "foo",
   307  				Remote:   "https://github.com/new.git",
   308  			},
   309  		},
   310  	}
   311  	if err := manifest.ToFile(jirix, jirix.JiriManifestFile()); err != nil {
   312  		t.Fatal(err)
   313  	}
   314  
   315  	// Return to the current working directory when done.
   316  	cwd, err := os.Getwd()
   317  	if err != nil {
   318  		return err
   319  	}
   320  	defer os.Chdir(cwd)
   321  
   322  	// cd into a root directory in which to do the actual import.
   323  	jiriRoot := jirix.Root
   324  	if err := os.Chdir(jiriRoot); err != nil {
   325  		return err
   326  	}
   327  
   328  	// Allow optional non-default filenames.
   329  	filename := test.Filename
   330  	if filename == "" {
   331  		filename = ".jiri_manifest"
   332  	}
   333  
   334  	// Set up an existing file if it was specified.
   335  	if test.Exist != "" {
   336  		if err := os.WriteFile(filename, []byte(test.Exist), 0644); err != nil {
   337  			return err
   338  		}
   339  	}
   340  
   341  	run := func() error {
   342  		// Run override and check the results.
   343  		overrideCmd := func() {
   344  			setDefaultOverrideFlags()
   345  			if test.SetFlags != nil {
   346  				test.SetFlags()
   347  			}
   348  			err = runOverride(jirix, test.Args)
   349  		}
   350  		stdout, _, runErr := runfunc(overrideCmd)
   351  		if runErr != nil {
   352  			return err
   353  		}
   354  		stderr := ""
   355  		if err != nil {
   356  			stderr = err.Error()
   357  		}
   358  		if got, want := stdout, test.Stdout; !strings.Contains(got, want) || (got != "" && want == "") {
   359  			return fmt.Errorf("stdout got %q, want substr %q", got, want)
   360  		}
   361  		if got, want := stderr, test.Stderr; !strings.Contains(got, want) || (got != "" && want == "") {
   362  			return fmt.Errorf("stderr got %q, want substr %q", got, want)
   363  		}
   364  		return nil
   365  	}
   366  	if err := run(); err != nil {
   367  		return err
   368  	}
   369  
   370  	// check that it is idempotent
   371  	if !test.runOnce {
   372  		if err := run(); err != nil {
   373  			return err
   374  		}
   375  	}
   376  	f := test.OutputFileName
   377  	if f == "" {
   378  		f = filename
   379  	}
   380  
   381  	// Make sure the right file is generated.
   382  	if test.Want != "" {
   383  		data, err := os.ReadFile(f)
   384  		if err != nil {
   385  			return err
   386  		}
   387  		if got, want := string(data), test.Want; got != want {
   388  			return fmt.Errorf("GOT\n%s\nWANT\n%s", got, want)
   389  		}
   390  	}
   391  	return nil
   392  }