github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/runtime/source/git/git_test.go (about) 1 // Licensed under the Apache License, Version 2.0 (the "License"); 2 // you may not use this file except in compliance with the License. 3 // You may obtain a copy of the License at 4 // 5 // https://www.apache.org/licenses/LICENSE-2.0 6 // 7 // Unless required by applicable law or agreed to in writing, software 8 // distributed under the License is distributed on an "AS IS" BASIS, 9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 // See the License for the specific language governing permissions and 11 // limitations under the License. 12 // 13 // Original source: github.com/micro/go-micro/v3/runtime/local/source/git/git_test.go 14 15 package git 16 17 import ( 18 "archive/tar" 19 "archive/zip" 20 "bytes" 21 "compress/gzip" 22 "io/ioutil" 23 "net/http" 24 "strings" 25 "testing" 26 27 "github.com/tickoalcantara12/micro/v3/test/fakes" 28 29 "github.com/onsi/gomega/types" 30 31 . "github.com/onsi/gomega" 32 ) 33 34 type parseCase struct { 35 source string 36 expected *Source 37 } 38 39 func TestParseSource(t *testing.T) { 40 cases := []parseCase{ 41 { 42 source: "github.com/micro/services/helloworld", 43 expected: &Source{ 44 Repo: "github.com/micro/services", 45 Folder: "helloworld", 46 Ref: "latest", 47 }, 48 }, 49 { 50 source: "github.com/micro/services/helloworld", 51 expected: &Source{ 52 Repo: "github.com/micro/services", 53 Folder: "helloworld", 54 Ref: "latest", 55 }, 56 }, 57 { 58 source: "github.com/micro/services/helloworld@v1.12.1", 59 expected: &Source{ 60 Repo: "github.com/micro/services", 61 Folder: "helloworld", 62 Ref: "v1.12.1", 63 }, 64 }, 65 { 66 source: "github.com/micro/services/helloworld@branchname", 67 expected: &Source{ 68 Repo: "github.com/micro/services", 69 Folder: "helloworld", 70 Ref: "branchname", 71 }, 72 }, 73 { 74 source: "github.com/crufter/reponame/helloworld@branchname", 75 expected: &Source{ 76 Repo: "github.com/crufter/reponame", 77 Folder: "helloworld", 78 Ref: "branchname", 79 }, 80 }, 81 } 82 for i, c := range cases { 83 result, err := ParseSource(c.source) 84 if err != nil { 85 t.Fatalf("Failed case %v: %v", i, err) 86 } 87 if result.Folder != c.expected.Folder { 88 t.Fatalf("Folder does not match for '%v', expected '%v', got '%v'", i, c.expected.Folder, result.Folder) 89 } 90 if result.Repo != c.expected.Repo { 91 t.Fatalf("Repo address does not match for '%v', expected '%v', got '%v'", i, c.expected.Repo, result.Repo) 92 } 93 if result.Ref != c.expected.Ref { 94 t.Fatalf("Ref does not match for '%v', expected '%v', got '%v'", i, c.expected.Ref, result.Ref) 95 } 96 } 97 } 98 99 type localParseCase struct { 100 source string 101 expected *Source 102 workDir string 103 pathExists bool 104 } 105 106 func TestLocalParseSource(t *testing.T) { 107 cases := []localParseCase{ 108 { 109 source: ".", 110 expected: &Source{ 111 Folder: "folder2", 112 Ref: "latest", 113 }, 114 workDir: "/folder1/folder2", 115 pathExists: true, 116 }, 117 } 118 for i, c := range cases { 119 result, err := ParseSourceLocal(c.workDir, c.source, func(s string) (bool, error) { 120 return c.pathExists, nil 121 }) 122 if err != nil { 123 t.Fatalf("Failed case %v: %v", i, err) 124 } 125 if result.Folder != c.expected.Folder { 126 t.Fatalf("Folder does not match for '%v', expected '%v', got '%v'", i, c.expected.Folder, result.Folder) 127 } 128 if result.Repo != c.expected.Repo { 129 t.Fatalf("Repo address does not match for '%v', expected '%v', got '%v'", i, c.expected.Repo, result.Repo) 130 } 131 if result.Ref != c.expected.Ref { 132 t.Fatalf("Ref does not match for '%v', expected '%v', got '%v'", i, c.expected.Ref, result.Ref) 133 } 134 } 135 } 136 137 type nameCase struct { 138 fileContent string 139 expected string 140 } 141 142 func TestServiceNameExtract(t *testing.T) { 143 cases := []nameCase{ 144 { 145 fileContent: `func main() { 146 // New Service 147 service := micro.NewService( 148 micro.Name("go.micro.service.helloworld"), 149 micro.Version("latest"), 150 )`, 151 expected: "go.micro.service.helloworld", 152 }, 153 } 154 for i, c := range cases { 155 result := extractServiceName([]byte(c.fileContent)) 156 if result != c.expected { 157 t.Fatalf("Case %v, expected: %v, got: %v", i, c.expected, result) 158 } 159 } 160 } 161 162 type roundTripFunc func(req *http.Request) *http.Response 163 164 func (f roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) { 165 return f(req), nil 166 } 167 168 func TestCheckout(t *testing.T) { 169 tcs := []struct { 170 name string 171 repo string 172 branchOrCommit string // the branch we're looking for 173 remoteBranch string // the branch that actually exists remotely 174 errMatcher types.GomegaMatcher 175 callCount int 176 }{ 177 {name: "github-latest", repo: "https://github.com/micro/services", branchOrCommit: "latest", remoteBranch: "latest", callCount: 1}, 178 {name: "github-master", repo: "https://github.com/micro/services", branchOrCommit: "latest", remoteBranch: "master", callCount: 2}, 179 {name: "github-main", repo: "https://github.com/micro/services", branchOrCommit: "latest", remoteBranch: "main", callCount: 3}, 180 {name: "github-error", repo: "https://github.com/micro/services", branchOrCommit: "latest", remoteBranch: "someotherdefault", errMatcher: HaveOccurred(), callCount: 4}, 181 {name: "github-specific", repo: "https://github.com/micro/services", branchOrCommit: "mybranch", remoteBranch: "mybranch", callCount: 1}, 182 {name: "github-specific-error", repo: "https://github.com/micro/services", branchOrCommit: "mybranch", remoteBranch: "main", errMatcher: HaveOccurred(), callCount: 1}, 183 {name: "gitlab-latest", repo: "https://gitlab.com/micro-test/basic-micro-service", branchOrCommit: "latest", remoteBranch: "latest", callCount: 1}, 184 {name: "gitlab-master", repo: "https://gitlab.com/micro-test/basic-micro-service", branchOrCommit: "latest", remoteBranch: "master", callCount: 2}, 185 {name: "gitlab-main", repo: "https://gitlab.com/micro-test/basic-micro-service", branchOrCommit: "latest", remoteBranch: "main", callCount: 3}, 186 {name: "gitlab-error", repo: "https://gitlab.com/micro-test/basic-micro-service", branchOrCommit: "latest", remoteBranch: "someotherdefault", errMatcher: HaveOccurred(), callCount: 4}, 187 {name: "gitlab-error", repo: "https://gitlab.com/micro-test/basic-micro-service", branchOrCommit: "mybranch", remoteBranch: "mybranch", callCount: 1}, 188 {name: "gitlab-error", repo: "https://gitlab.com/micro-test/basic-micro-service", branchOrCommit: "mybranch", remoteBranch: "main", errMatcher: HaveOccurred(), callCount: 1}, 189 } 190 for _, tc := range tcs { 191 t.Run(tc.name, func(t *testing.T) { 192 gInt := NewGitter(nil) 193 gitter := gInt.(*binaryGitter) 194 fakeTripper := fakes.FakeRoundTripper{ 195 RoundTripStub: func(req *http.Request) (*http.Response, error) { 196 if !strings.Contains(req.URL.String(), tc.remoteBranch) { 197 // not asking for a branch that exists , return 404 198 return &http.Response{ 199 StatusCode: 404, 200 Body: ioutil.NopCloser(new(bytes.Buffer)), 201 Header: make(http.Header), 202 }, nil 203 } 204 if strings.HasSuffix(req.URL.String(), ".zip") { 205 // simulate a zip file 206 buf := new(bytes.Buffer) 207 zipw := zip.NewWriter(buf) 208 w, _ := zipw.Create("foo/bar") 209 w.Write([]byte("foobar")) 210 zipw.Close() 211 212 return &http.Response{ 213 StatusCode: 200, 214 // Send response to be tested 215 Body: ioutil.NopCloser(buf), 216 // Must be set to non-nil value or it panics 217 Header: make(http.Header), 218 }, nil 219 } 220 221 if strings.HasSuffix(req.URL.String(), "tar.gz") { 222 // simulate a tar.gz file which has a directory at root 223 buf := new(bytes.Buffer) 224 gz := gzip.NewWriter(buf) 225 tw := tar.NewWriter(gz) 226 hdr := &tar.Header{ 227 Name: "foo", 228 Mode: 0600, 229 Typeflag: tar.TypeDir, 230 } 231 tw.WriteHeader(hdr) 232 hdr = &tar.Header{ 233 Name: "foo/bar", 234 Mode: 0600, 235 Size: int64(len([]byte("foobar"))), 236 Typeflag: tar.TypeReg, 237 } 238 tw.WriteHeader(hdr) 239 tw.Write([]byte("foobar")) 240 tw.Close() 241 gz.Close() 242 return &http.Response{ 243 StatusCode: 200, 244 // Send response to be tested 245 Body: ioutil.NopCloser(buf), 246 // Must be set to non-nil value or it panics 247 Header: make(http.Header), 248 }, nil 249 } 250 return &http.Response{ 251 StatusCode: 404, 252 Body: ioutil.NopCloser(new(bytes.Buffer)), 253 Header: make(http.Header), 254 }, nil 255 }, 256 } 257 gitter.client = &http.Client{ 258 Transport: &fakeTripper, 259 } 260 261 g := NewWithT(t) 262 err := gitter.Checkout(tc.repo, tc.branchOrCommit) 263 if tc.errMatcher != nil { 264 g.Expect(err).To(tc.errMatcher) 265 } else { 266 g.Expect(err).To(BeNil()) 267 } 268 g.Expect(fakeTripper.RoundTripCallCount()).To(Equal(tc.callCount)) 269 270 }) 271 } 272 273 }