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  }