github.com/comcast/canticle@v0.0.0-20161108184242-c53cface56e8/canticles/vcs_test.go (about)

     1  package canticles
     2  
     3  import (
     4  	"errors"
     5  	"io/ioutil"
     6  	"os"
     7  	"path"
     8  	"regexp"
     9  	"testing"
    10  
    11  	"golang.org/x/tools/go/vcs"
    12  )
    13  
    14  var errTest = errors.New("Test err")
    15  
    16  func TestDefaultRepoResolver(t *testing.T) {
    17  	dr := &DefaultRepoResolver{os.ExpandEnv("$GOPATH")}
    18  	// Try a VCS resolution against someone supports go get syntax
    19  	importPath := "golang.org/x/tools/go/vcs"
    20  	vcs, err := dr.ResolveRepo(importPath, nil)
    21  	if err != nil {
    22  		t.Errorf("DefaultRepoResolver returned error for golang.org repo: %s", err.Error())
    23  	}
    24  	if vcs == nil {
    25  		t.Fatalf("DefaultRepoResolver returned nil vcs for repo: %s", importPath)
    26  	}
    27  
    28  	v := vcs.(*PackageVCS)
    29  	if v.Repo.Root != "golang.org/x/tools" {
    30  		t.Errorf("DefaultRepoResolver did not set correct root for repo got %s expected %s", v.Repo.Root, "golang.org/x/tools")
    31  	}
    32  	if v.Repo.Repo == "" {
    33  		t.Errorf("DefaultRepoResolver did not set any repo for repo %s", importPath)
    34  	}
    35  }
    36  
    37  func TestRemoteRepoResolver(t *testing.T) {
    38  	rr := &RemoteRepoResolver{os.ExpandEnv("$GOPATH")}
    39  
    40  	dep := &CanticleDependency{
    41  		SourcePath: "git@github.com:Comcast/Canticle.git",
    42  		Root:       "github.com/Comcast/Canticle",
    43  	}
    44  
    45  	vcs, err := rr.ResolveRepo(dep.Root, dep)
    46  	if err != nil {
    47  		t.Errorf("RemoteRepoResolver returned error for our own repo: %s", err.Error())
    48  	}
    49  	if vcs == nil {
    50  		t.Fatalf("RemoteRepoResolverResolveRepo returned nil vcs for repo: %+v", dep)
    51  	}
    52  	v := vcs.(*PackageVCS)
    53  	expectedRoot := "github.com/Comcast/Canticle"
    54  	if v.Repo.Root != expectedRoot {
    55  		t.Errorf("RemoteRepoResolver did not set correct root for repo got %s expected %s", v.Repo.Root, expectedRoot)
    56  	}
    57  	expectedURL := "git@github.com:Comcast/Canticle.git"
    58  	if v.Repo.Repo != expectedURL {
    59  		t.Errorf("ResolveRepo did not set correct repo for repo got %s expected %s", v.Repo.Repo, expectedURL)
    60  	}
    61  
    62  	// Try a VCS resolution that just flat fails
    63  	dep = &CanticleDependency{
    64  		Root:       "nothere.comcast.com/viper-cog/cant",
    65  		SourcePath: "git@nothere.comcast.com:viper-cog/cant.git",
    66  	}
    67  	vcs, err = rr.ResolveRepo(dep.Root, dep)
    68  	if err == nil {
    69  		t.Errorf("RemoteRepoResolver returned no error for a package that does not exist")
    70  	}
    71  	if vcs != nil {
    72  		t.Errorf("RemoteRepoResolver returned non nil vcs for repo: %+v", dep)
    73  	}
    74  }
    75  
    76  func TestLocalRepoResolver(t *testing.T) {
    77  	gopath, err := EnvGoPath()
    78  	if err != nil {
    79  		t.Fatalf("Could not get gopath: %s", err.Error())
    80  	}
    81  	lr := &LocalRepoResolver{
    82  		LocalPath: gopath,
    83  	}
    84  
    85  	pkg := "github.com/Comcast/Canticle"
    86  	vcs, err := lr.ResolveRepo(pkg, nil)
    87  	if err != nil {
    88  		t.Errorf("LocalRepoResolver returned error resolving our own package %s", err.Error())
    89  	}
    90  
    91  	if vcs == nil {
    92  		t.Fatalf("LocalRepoResolver returned a nil VCS resolving our own package")
    93  	}
    94  	v := vcs.(*LocalVCS)
    95  	if v.Cmd.Cmd != "git" {
    96  		t.Errorf("LocalRepoResolver did not set correct vcs command %s expected %s", v.Cmd.Cmd, "git")
    97  	}
    98  
    99  	// Test dealing with a package whose vcs root != the importpath
   100  	pkg = "golang.org/x/tools/go/vcs"
   101  	vcs, err = lr.ResolveRepo(pkg, nil)
   102  	if err != nil {
   103  		t.Errorf("LocalRepoResolver returned error resolving our own package %s", err.Error())
   104  	}
   105  
   106  	if vcs == nil {
   107  		t.Fatalf("LocalRepoResolver returned a nil VCS resolving our own package")
   108  	}
   109  	v = vcs.(*LocalVCS)
   110  	if v.Cmd.Cmd != "git" {
   111  		t.Errorf("LocalRepoResolver did not set correct vcs command %s expected %s", v.Cmd.Cmd, "git")
   112  	}
   113  }
   114  
   115  func TestResolveRootWithNoSlash(t *testing.T) {
   116  	gopath, err := EnvGoPath()
   117  	if err != nil {
   118  		t.Fatalf("Could not get gopath: %s", err.Error())
   119  	}
   120  
   121  	dep := &CanticleDependency{
   122  		Root:       "camlistore.org",
   123  		SourcePath: "https://camlistore.googlesource.com/camlistore",
   124  	}
   125  
   126  	dr := &DefaultRepoResolver{gopath}
   127  	_, err = dr.ResolveRepo(dep.Root, dep)
   128  	if err != nil {
   129  		t.Errorf("DefaultRepoResolver could not resolve Root that does not contain a slash: %v", err)
   130  	}
   131  
   132  	rr := &RemoteRepoResolver{gopath}
   133  	_, err = rr.ResolveRepo(dep.Root, dep)
   134  	if err != nil {
   135  		t.Errorf("RemoteRepoResolver could not resolve Root that does not contain a slash: %v", err)
   136  	}
   137  
   138  	// Create a temp test dir for testing no slash local
   139  	testHome, err := ioutil.TempDir("", "cant-test-src")
   140  	if err != nil {
   141  		t.Fatalf("Error creating tempdir: %s", err.Error())
   142  	}
   143  	defer os.RemoveAll(testHome)
   144  	if err := os.MkdirAll(path.Join(testHome, "src", "camlistore.org", ".git"), 0755); err != nil {
   145  		t.Fatalf("Error creating tempdir: %s", err.Error())
   146  	}
   147  
   148  	lr := &LocalRepoResolver{testHome}
   149  	_, err = lr.ResolveRepo(dep.Root, dep)
   150  	if err != nil {
   151  		t.Errorf("LocalRepoResolver could not resolve Root that does not contain a slash: %v", err)
   152  	}
   153  
   154  }
   155  
   156  type TestVCS struct {
   157  	Updated int
   158  	Created int
   159  	Err     error
   160  	Rev     string
   161  	Source  string
   162  	Root    string
   163  }
   164  
   165  func (v *TestVCS) UpdateBranch(branch string) (bool, string, error) {
   166  	return false, "", nil
   167  }
   168  
   169  func (v *TestVCS) Create(rev string) error {
   170  	v.Rev = rev
   171  	v.Created++
   172  	return v.Err
   173  }
   174  
   175  func (v *TestVCS) SetRev(rev string) error {
   176  	v.Rev = rev
   177  	v.Updated++
   178  	return v.Err
   179  }
   180  
   181  func (v *TestVCS) GetRev() (string, error) {
   182  	return v.Rev, v.Err
   183  }
   184  
   185  func (v *TestVCS) GetSource() (string, error) {
   186  	return v.Source, v.Err
   187  }
   188  
   189  func (v *TestVCS) GetRoot() string {
   190  	return v.Root
   191  }
   192  
   193  func (v *TestVCS) GetBranch() (string, error) {
   194  	return v.Rev, v.Err
   195  }
   196  
   197  type testResolve struct {
   198  	path string
   199  	dep  *CanticleDependency
   200  }
   201  
   202  type testResolver struct {
   203  	resolutions []testResolve
   204  	response    []resolve
   205  }
   206  
   207  func (tr *testResolver) ResolveRepo(i string, d *CanticleDependency) (VCS, error) {
   208  	tr.resolutions = append(tr.resolutions, testResolve{i, d})
   209  	resp := tr.response[0]
   210  	tr.response = tr.response[1:]
   211  	return resp.v, resp.err
   212  }
   213  
   214  func TestCompositeRepoResolver(t *testing.T) {
   215  	res := &TestVCS{}
   216  	tr1 := &testResolver{response: []resolve{{nil, errTest}}}
   217  	tr2 := &testResolver{response: []resolve{{res, nil}}}
   218  
   219  	cr := &CompositeRepoResolver{[]RepoResolver{tr1, tr2}}
   220  
   221  	dep := &CanticleDependency{
   222  		Root: "testi",
   223  	}
   224  	v, err := cr.ResolveRepo(dep.Root, dep)
   225  	if err != nil {
   226  		t.Errorf("CompositeRepoResolver returned error with valid resolve %s", err.Error())
   227  	}
   228  	if v != res {
   229  		t.Errorf("CompositeRepoResolver returned incorrect vcs")
   230  	}
   231  	if tr1.resolutions[0].path != dep.Root {
   232  		t.Errorf("CompositeRepoResolver tr1 bad import path")
   233  	}
   234  	if tr1.resolutions[0].dep != dep {
   235  		t.Errorf("CompositeRepoResolver tr1 bad dep")
   236  	}
   237  	if tr2.resolutions[0].dep != dep {
   238  		t.Errorf("CompositeRepoResolver tr2 bad dep")
   239  	}
   240  
   241  	tr1 = &testResolver{response: []resolve{{nil, errTest}}}
   242  	tr2 = &testResolver{response: []resolve{{nil, errTest}}}
   243  	cr = &CompositeRepoResolver{[]RepoResolver{tr1, tr2}}
   244  	v, err = cr.ResolveRepo(dep.Root, dep)
   245  	if re := ResolutionFailureErr(err); re == nil {
   246  		t.Errorf("CompositeRepoResolver did not return resolution failure")
   247  	}
   248  }
   249  
   250  func TestMemoizedRepoResolver(t *testing.T) {
   251  	res := &TestVCS{}
   252  	tr1 := &testResolver{response: []resolve{{res, nil}}}
   253  	mr := NewMemoizedRepoResolver(tr1)
   254  	dep := &CanticleDependency{
   255  		Root: "testi",
   256  	}
   257  	v, err := mr.ResolveRepo(dep.Root, dep)
   258  	if err != nil {
   259  		t.Errorf("MemoizedRepoResolver returned error %s", err.Error())
   260  	}
   261  	if v != res {
   262  		t.Errorf("MemoizedRepoResolver returned wrong vcs")
   263  	}
   264  	if len(tr1.resolutions) != 1 {
   265  		t.Errorf("MemoizedRepoResolver did not call tr1 only once")
   266  	}
   267  
   268  	v, err = mr.ResolveRepo(dep.Root, dep)
   269  	if err != nil {
   270  		t.Errorf("MemoizedRepoResolver returned error %s", err.Error())
   271  	}
   272  	if v != res {
   273  		t.Errorf("MemoizedRepoResolver returned wrong vcs")
   274  	}
   275  	if len(tr1.resolutions) != 1 {
   276  		t.Errorf("MemoizedRepoResolver did not call tr1 only once")
   277  	}
   278  }
   279  
   280  var (
   281  	expectedRev = "testrev"
   282  	TestRevCmd  = &VCSCmd{
   283  		Name:       "Test",
   284  		Cmd:        "echo",
   285  		Args:       []string{expectedRev},
   286  		ParseRegex: regexp.MustCompile(`^(\S+)$`),
   287  	}
   288  )
   289  
   290  // TODO: Add coverage for LocalVCS and PackageVCS
   291  func TestVCSCmds(t *testing.T) {
   292  
   293  	testHome, err := ioutil.TempDir("", "cant-test")
   294  	if err != nil {
   295  		t.Fatalf("Error creating tempdir: %s", err.Error())
   296  	}
   297  	defer os.RemoveAll(testHome)
   298  
   299  	rev, err := TestRevCmd.Exec(testHome)
   300  	if err != nil {
   301  		t.Fatalf("Error running valid test exec command: %s", err.Error())
   302  	}
   303  	if rev != expectedRev {
   304  		t.Errorf("Exec not %s not match expected %s", rev, expectedRev)
   305  	}
   306  
   307  	rev, err = TestRevCmd.Exec("someinvaliddir")
   308  	if err == nil {
   309  		t.Fatalf("No Error running invalid test exec command")
   310  	}
   311  	if rev != "" {
   312  		t.Errorf("Rev returned non empty string for errored command")
   313  	}
   314  
   315  	TestRevCmd.Args = []string{"this should be invalid"}
   316  	rev, err = TestRevCmd.Exec(testHome)
   317  	if err == nil {
   318  		t.Fatalf("No Error running invalid test exec command")
   319  	}
   320  	if rev != "" {
   321  		t.Errorf("Exec returned non empty string for regex that did not match")
   322  	}
   323  	TestRevCmd.Args = []string{expectedRev}
   324  }
   325  
   326  var (
   327  	TestVCSCmd = &vcs.Cmd{
   328  		Name:        "Test",
   329  		Cmd:         "echo",
   330  		CreateCmd:   "create",
   331  		DownloadCmd: "download",
   332  		TagCmd: []vcs.TagCmd{
   333  			{"show-ref", `(?:tags|origin)/(\S+)$`},
   334  		},
   335  		TagLookupCmd: []vcs.TagCmd{
   336  			{"-n {tag}", `(\S+)$`},
   337  		},
   338  		TagSyncCmd:     "checkout {tag}",
   339  		TagSyncDefault: "checkout master",
   340  
   341  		Scheme:  []string{"test", "https"},
   342  		PingCmd: "ping {scheme}://{repo}",
   343  	}
   344  )
   345  
   346  func TestLocalVCS(t *testing.T) {
   347  	vcs.Verbose = true
   348  	testHome, err := ioutil.TempDir("", "cant-test-src")
   349  	if err != nil {
   350  		t.Fatalf("Error creating tempdir: %s", err.Error())
   351  	}
   352  	defer os.RemoveAll(testHome)
   353  
   354  	pkgname := "test.com/test"
   355  	childpkg := "test.com/test/child"
   356  	if err := os.MkdirAll(PackageSource(testHome, childpkg), 0755); err != nil {
   357  		t.Fatalf("Error creating tempdir: %s", err.Error())
   358  	}
   359  
   360  	v := NewLocalVCS(childpkg, pkgname, testHome, TestVCSCmd)
   361  	rev, err := v.GetRev()
   362  	if err != nil {
   363  		t.Fatalf("Local vcs should not return error with no rev command")
   364  	}
   365  	if rev != "" {
   366  		t.Errorf("Rev returned non empty string for no rev command: %s %+v", rev, v)
   367  	}
   368  
   369  	RevCmds[TestRevCmd.Name] = TestRevCmd
   370  	v = NewLocalVCS(childpkg, pkgname, testHome, TestVCSCmd)
   371  	v.Branches = func(path string) ([]string, error) {
   372  		return []string{"testrev"}, nil
   373  	}
   374  	rev, err = v.GetRev()
   375  	if err != nil {
   376  		t.Errorf("Error getting valid rev: %s", err.Error())
   377  	}
   378  	if rev != expectedRev {
   379  		t.Errorf("Rev not %s not match expected %s", rev, expectedRev)
   380  	}
   381  
   382  	if err := v.Create(""); err != nil {
   383  		t.Errorf("Error running create command with no revision: %s", err.Error())
   384  	}
   385  	if err = v.SetRev("testrev"); err != nil {
   386  		t.Errorf("Error setting rev to testrev: %s", err.Error())
   387  	}
   388  }