github.com/comcast/canticle@v0.0.0-20161108184242-c53cface56e8/canticles/depwalker_test.go (about) 1 package canticles 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path" 7 "testing" 8 ) 9 10 type TestDepRead struct { 11 Deps []string 12 Err error 13 } 14 15 type TestDepReader struct { 16 PackageDeps map[string]TestDepRead 17 } 18 19 func (tdr *TestDepReader) ReadDependencies(p string) ([]string, error) { 20 r := tdr.PackageDeps[p] 21 return r.Deps, r.Err 22 } 23 24 type TestWalker struct { 25 calls []string 26 responses []error 27 } 28 29 func (tw *TestWalker) HandlePackage(pkg string) error { 30 tw.calls = append(tw.calls, pkg) 31 if len(tw.responses) > 0 { 32 resp := tw.responses[0] 33 tw.responses = tw.responses[1:] 34 return resp 35 } 36 return nil 37 } 38 39 var NormalReader = &TestDepReader{ 40 map[string]TestDepRead{ 41 "testpkg": TestDepRead{[]string{"dep1", "dep2"}, nil}, 42 "dep1": TestDepRead{[]string{"dep2"}, nil}, 43 "dep2": TestDepRead{}, 44 }, 45 } 46 47 var NormalReaderResult = []string{"testpkg", "dep1", "dep2"} 48 49 var HandlerErrorResult = []string{"testpkg"} 50 51 var HandlerSkipResult = []string{"testpkg"} 52 53 var CycledReader = &TestDepReader{ 54 map[string]TestDepRead{ 55 "testpkg": TestDepRead{[]string{"dep1", "dep2"}, nil}, 56 "dep1": TestDepRead{[]string{"dep2"}, nil}, 57 "dep2": TestDepRead{[]string{"dep1"}, nil}, 58 }, 59 } 60 61 var CycleReaderResult = []string{"testpkg", "dep1", "dep2"} 62 63 var ChildErrorReader = &TestDepReader{ 64 map[string]TestDepRead{ 65 "testpkg": TestDepRead{[]string{"dep1", "dep2"}, nil}, 66 "dep1": TestDepRead{[]string{"dep3"}, nil}, 67 "dep2": TestDepRead{}, 68 "dep3": TestDepRead{[]string{}, errTest}, 69 }, 70 } 71 72 var ChildErrorReaderResult = []string{"testpkg", "dep1", "dep2"} 73 74 func CheckResult(t *testing.T, logPrefix string, expected, got []string) { 75 for i, v := range expected { 76 if v != got[i] { 77 t.Errorf("%s expected dep: %+v != got %+v", logPrefix, v, got[i]) 78 } 79 } 80 } 81 82 func TestTraverseDependencies(t *testing.T) { 83 tw := &TestWalker{} 84 // Run a test with a reader with normal deps 85 dw := NewDependencyWalker(NormalReader.ReadDependencies, tw.HandlePackage) 86 err := dw.TraverseDependencies("testpkg") 87 if err != nil { 88 t.Errorf("Error loading valid pkg %s", err.Error()) 89 } 90 CheckResult(t, "NormalReader", NormalReaderResult, tw.calls) 91 92 // Run a test with an error from our handler 93 tw = &TestWalker{responses: []error{nil, errTest}} 94 dw = NewDependencyWalker(NormalReader.ReadDependencies, tw.HandlePackage) 95 err = dw.TraverseDependencies("testpkg") 96 if err == nil { 97 t.Errorf("Error not returned from hanlder") 98 } 99 CheckResult(t, "HandlerError", HandlerErrorResult, tw.calls) 100 101 // Run a test with a skip error from our handler 102 tw = &TestWalker{responses: []error{nil, ErrorSkip}} 103 dw = NewDependencyWalker(NormalReader.ReadDependencies, tw.HandlePackage) 104 err = dw.TraverseDependencies("testpkg") 105 if err != nil { 106 t.Errorf("Error returned when skip form hanlder %s", err.Error()) 107 } 108 CheckResult(t, "HandlerSkip", HandlerSkipResult, tw.calls) 109 110 // Run a test with a reader with cycled deps, make sure we don't infinite loop 111 tw = &TestWalker{} 112 dw = NewDependencyWalker(CycledReader.ReadDependencies, tw.HandlePackage) 113 err = dw.TraverseDependencies("testpkg") 114 if err != nil { 115 t.Errorf("Error loading valid pkg %s", err.Error()) 116 } 117 CheckResult(t, "CycledReader", CycleReaderResult, tw.calls) 118 119 // Run a test with a non loadable package 120 tw = &TestWalker{} 121 dw = NewDependencyWalker(ChildErrorReader.ReadDependencies, tw.HandlePackage) 122 err = dw.TraverseDependencies("testpkg") 123 if err == nil { 124 t.Errorf("Error loading invvalid pkg %s", err.Error()) 125 } 126 CheckResult(t, "ChildErrorReader", ChildErrorReaderResult, tw.calls) 127 } 128 129 type TestVCSResolve struct { 130 V VCS 131 Err error 132 } 133 134 type TestResolver struct { 135 ResolvePaths map[string]*TestVCSResolve 136 } 137 138 func (tr *TestResolver) ResolveRepo(importPath string, dep *CanticleDependency) (VCS, error) { 139 r := tr.ResolvePaths[importPath] 140 return r.V, r.Err 141 } 142 143 type TestDependencyRead struct { 144 Deps Dependencies 145 Err error 146 } 147 148 type TestDependencyReader struct { 149 PackageDeps map[string]TestDependencyRead 150 } 151 152 func (tdr *TestDependencyReader) ReadDependencies(p string) (Dependencies, error) { 153 r := tdr.PackageDeps[p] 154 return r.Deps, r.Err 155 } 156 157 func TestDependencyLoader(t *testing.T) { 158 // Create our 159 testHome, err := ioutil.TempDir("", "cant-test") 160 if err != nil { 161 t.Fatalf("Error creating tempdir: %s", err.Error()) 162 } 163 defer os.RemoveAll(testHome) 164 if err := os.MkdirAll(path.Join(testHome, "src", "pkg1", "child"), 0755); err != nil { 165 t.Fatal(err) 166 } 167 pkg1dep := map[string]*Dependency{ 168 "pkg1/child": NewDependency("pkg1/child"), 169 } 170 pkg1childdep := map[string]*Dependency{ 171 "pkg2/child": NewDependency("pkg2/child"), 172 } 173 deps := &TestDependencyReader{ 174 map[string]TestDependencyRead{ 175 testHome + "/src/" + "pkg1": TestDependencyRead{pkg1dep, nil}, 176 testHome + "/src/" + "pkg1/child": TestDependencyRead{pkg1childdep, nil}, 177 testHome + "/src/" + "pkg2": TestDependencyRead{NewDependencies(), nil}, 178 testHome + "/src/" + "pkg2/child": TestDependencyRead{NewDependencies(), nil}, 179 }, 180 } 181 182 cdeps := []*CanticleDependency{ 183 &CanticleDependency{Root: "pkg1"}, 184 &CanticleDependency{Root: "pkg2"}, 185 } 186 pkg1vcs := &TestVCS{} 187 pkg2vcs := &TestVCS{} 188 tr := &TestResolver{map[string]*TestVCSResolve{ 189 "pkg1": &TestVCSResolve{pkg1vcs, nil}, 190 "pkg1/child": &TestVCSResolve{pkg1vcs, nil}, 191 "pkg2": &TestVCSResolve{pkg2vcs, nil}, 192 "pkg2/child": &TestVCSResolve{pkg2vcs, nil}, 193 }} 194 dl := NewDependencyLoader(tr, deps.ReadDependencies, cdeps, testHome) 195 if err := dl.FetchUpdatePackage("pkg1"); err != nil { 196 t.Errorf("Error fetching pkg1: %s", err.Error()) 197 } 198 pkgImports, err := dl.PackageImports("pkg1") 199 if err != nil { 200 t.Errorf("Error getting imports for pkg1: %s", err.Error()) 201 } 202 if pkgImports[0] != "pkg1/child" { 203 t.Errorf("Expected pkg1 to have imports pkg1/child got: %s", pkgImports[0]) 204 } 205 if pkg1vcs.Created != 0 { 206 t.Errorf("Expected pkg1vcs to have no creates: %d", pkg1vcs.Created) 207 } 208 if err := dl.FetchUpdatePackage("pkg1/child"); err != nil { 209 t.Errorf("Error fetching pkg1: %s", err.Error()) 210 } 211 pkgImports, err = dl.PackageImports("pkg1/child") 212 if err != nil { 213 t.Errorf("Error getting imports for pkg1: %s", err.Error()) 214 } 215 if pkgImports[0] != "pkg2/child" { 216 t.Errorf("Expected pkg1 to have imports pkg2/child got: %s", pkgImports[0]) 217 } 218 if pkg1vcs.Created != 0 { 219 t.Errorf("Expected pkg1vcs to have no creates: %d", pkg1vcs.Created) 220 } 221 222 if err := dl.FetchUpdatePackage("pkg2/child"); err != nil { 223 t.Errorf("Error fetching pkg2: %s", err.Error()) 224 } 225 pkgImports, err = dl.PackageImports("pkg2/child") 226 if err != nil { 227 t.Errorf("Error getting imports for pkg2: %s", err.Error()) 228 } 229 if len(pkgImports) != 0 { 230 t.Errorf("Expected pkg2 to have no imports pkg2/child got: %d", len(pkgImports)) 231 } 232 if pkg2vcs.Created != 1 { 233 t.Errorf("Expected pkg2vcs to have 1 create: %d", pkg2vcs.Created) 234 } 235 236 }