github.com/zaquestion/lab@v0.25.1/internal/git/git_test.go (about)

     1  package git
     2  
     3  import (
     4  	"math/rand"
     5  	"os"
     6  	"os/exec"
     7  	"path/filepath"
     8  	"regexp"
     9  	"strconv"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/otiai10/copy"
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  func TestMain(m *testing.M) {
    20  	rand.Seed(time.Now().UnixNano())
    21  	repo := copyTestRepo()
    22  	if err := os.Chdir(repo); err != nil {
    23  		log.Fatal(err)
    24  	}
    25  
    26  	code := m.Run()
    27  
    28  	if err := os.Chdir("../"); err != nil {
    29  		log.Fatalf("Error chdir to ../: %s", err)
    30  	}
    31  	if err := os.RemoveAll(repo); err != nil {
    32  		log.Fatalf("Error removing %s: %s", repo, err)
    33  	}
    34  	os.Exit(code)
    35  }
    36  
    37  func TestGitDir(t *testing.T) {
    38  	wd, err := os.Getwd()
    39  	if err != nil {
    40  		t.Fatal(err)
    41  	}
    42  	dir, err := Dir()
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  	require.Equal(t, filepath.Clean(wd+"/.git"), filepath.Clean(dir))
    47  }
    48  
    49  func TestWorkingDir(t *testing.T) {
    50  	wd, err := os.Getwd()
    51  	if err != nil {
    52  		t.Fatal(err)
    53  	}
    54  	dir, err := WorkingDir()
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  	require.Equal(t, filepath.Clean(wd), filepath.Clean(dir))
    59  }
    60  
    61  func TestCommentChar(t *testing.T) {
    62  	require.Equal(t, "#", CommentChar())
    63  }
    64  
    65  func TestLastCommitMessage(t *testing.T) {
    66  	lcm, err := LastCommitMessage("HEAD")
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  	expectedLCM := "(ci) jobs with interleaved sleeps and prints"
    71  	require.Equal(t, expectedLCM, lcm)
    72  }
    73  
    74  func TestLog(t *testing.T) {
    75  	log, err := Log("HEAD~1", "HEAD")
    76  	if err != nil {
    77  		t.Fatal(err)
    78  	}
    79  	count := NumberCommits("HEAD~1", "HEAD")
    80  	expectedSHA := "09b519c"
    81  	expectedAuthor := "Zaq? Wiedmann"
    82  	expectedMessage := "(ci) jobs with interleaved sleeps and prints"
    83  	assert.Contains(t, log, expectedSHA)
    84  	assert.Contains(t, log, expectedAuthor)
    85  	assert.Contains(t, log, expectedMessage)
    86  	assert.Equal(t, 1, count)
    87  }
    88  
    89  func TestCurrentBranch(t *testing.T) {
    90  	branch, err := CurrentBranch()
    91  	if err != nil {
    92  		t.Fatal(err)
    93  	}
    94  	expectedBranch := "master"
    95  	require.Equal(t, expectedBranch, branch)
    96  }
    97  
    98  func TestPathWithNamespace(t *testing.T) {
    99  	tests := []struct {
   100  		desc        string
   101  		remote      string
   102  		expected    string
   103  		expectedErr string
   104  	}{
   105  		{
   106  			desc:        "ssh",
   107  			remote:      "origin",
   108  			expected:    "zaquestion/test",
   109  			expectedErr: "",
   110  		},
   111  		{
   112  			desc:        "http",
   113  			remote:      "origin-http",
   114  			expected:    "zaquestion/test",
   115  			expectedErr: "",
   116  		},
   117  		{
   118  			desc:        "https",
   119  			remote:      "origin-https",
   120  			expected:    "zaquestion/test",
   121  			expectedErr: "",
   122  		},
   123  		{
   124  			desc:        "pushurl",
   125  			remote:      "origin-pushurl",
   126  			expected:    "zaquestion/test",
   127  			expectedErr: "",
   128  		},
   129  		{
   130  			desc:        "empty-pushurl",
   131  			remote:      "origin-empty-pushurl",
   132  			expected:    "zaquestion/test",
   133  			expectedErr: "",
   134  		},
   135  		{
   136  			desc:        "https://token@gitlab.com/org/repo",
   137  			remote:      "origin-https-token",
   138  			expected:    "zaquestion/test",
   139  			expectedErr: "",
   140  		},
   141  		{
   142  			desc:        "git://",
   143  			remote:      "origin-git",
   144  			expected:    "zaquestion/test",
   145  			expectedErr: "",
   146  		},
   147  		{
   148  			desc:        "ssh://",
   149  			remote:      "origin-ssh-alt",
   150  			expected:    "zaquestion/test",
   151  			expectedErr: "",
   152  		},
   153  		{
   154  			desc:        "no .git suffix",
   155  			remote:      "origin-no_dot_git",
   156  			expected:    "zaquestion/test",
   157  			expectedErr: "",
   158  		},
   159  		{
   160  			desc:        "subdfolders-ssh",
   161  			remote:      "origin-subfolder-ssh",
   162  			expected:    "zaquestion/sub/folder/test",
   163  			expectedErr: "",
   164  		},
   165  		{
   166  			desc:        "subdfolders-git",
   167  			remote:      "origin-subfolder-git",
   168  			expected:    "zaquestion/sub/folder/test",
   169  			expectedErr: "",
   170  		},
   171  		{
   172  			desc:        "ssh-custom-port",
   173  			remote:      "origin-custom-port",
   174  			expected:    "zaquestion/test",
   175  			expectedErr: "",
   176  		},
   177  		{
   178  			desc:        "ssh-subfolder-custom-port",
   179  			remote:      "origin-subfolder-custom-port",
   180  			expected:    "zaquestion/sub/folder/test",
   181  			expectedErr: "",
   182  		},
   183  		{
   184  			desc:        "remote doesn't exist",
   185  			remote:      "phoney",
   186  			expected:    "",
   187  			expectedErr: "the key `remote.phoney.url` is not found",
   188  		},
   189  		{
   190  			desc:        "invalid remote URL",
   191  			remote:      "garbage",
   192  			expected:    "",
   193  			expectedErr: "invalid remote URL format for garbage",
   194  		},
   195  	}
   196  
   197  	for _, test := range tests {
   198  		test := test
   199  		t.Run(test.desc, func(t *testing.T) {
   200  			t.Parallel()
   201  			path, err := PathWithNamespace(test.remote)
   202  			if test.expectedErr != "" {
   203  				assert.EqualError(t, err, test.expectedErr)
   204  			} else {
   205  				assert.Nil(t, err)
   206  			}
   207  			assert.Equal(t, test.expected, path)
   208  		})
   209  	}
   210  }
   211  
   212  func TestRepoName(t *testing.T) {
   213  	repo, err := RepoName()
   214  	if err != nil {
   215  		t.Fatal(err)
   216  	}
   217  	expectedRepo := "test"
   218  	require.Equal(t, expectedRepo, repo)
   219  }
   220  
   221  func TestIsRemote(t *testing.T) {
   222  	res, err := IsRemote("origin")
   223  	if err != nil {
   224  		t.Fatal(err)
   225  	}
   226  	require.True(t, res)
   227  }
   228  
   229  func TestInsideGitRepo(t *testing.T) {
   230  	require.True(t, InsideGitRepo())
   231  }
   232  
   233  func TestRemotes(t *testing.T) {
   234  	res, err := Remotes()
   235  	if err != nil {
   236  		t.Fatal(err)
   237  	}
   238  	require.Contains(t, res, "origin", "remotes should contain 'origin' [%v]", res)
   239  }
   240  
   241  func TestRemoteBranches(t *testing.T) {
   242  	res, err := RemoteBranches("origin")
   243  	if err != nil {
   244  		t.Fatal(err)
   245  	}
   246  	require.Contains(t, res, "master", "remote branches should contain 'master' [%v]", res)
   247  }
   248  
   249  // Make sure the git command follow the expected behavior.
   250  func TestGetLocalRemotesFromFile(t *testing.T) {
   251  	repo := copyTestRepo()
   252  	gitconfig := repo + "/.git/config"
   253  
   254  	// First get the remotes directly from file
   255  	cmd := exec.Command("grep", "^\\[remote.*", gitconfig)
   256  	cmd.Dir = repo
   257  	grep, err := cmd.Output()
   258  	if err != nil {
   259  		t.Log(string(grep))
   260  		t.Error(err)
   261  	}
   262  	// And get the remote names
   263  	re := regexp.MustCompile(`\[remote\s+"(.*)".*`)
   264  	reMatches := re.FindAllStringSubmatch(string(grep), -1)
   265  
   266  	// Second, get result from local function
   267  	res, err := GetLocalRemotesFromFile()
   268  	if err != nil {
   269  		t.Log(string(res))
   270  		t.Error(err)
   271  	}
   272  	remotesList := strings.Split(string(res), "\n")
   273  
   274  	// Create an array (the ordering matters) to place all unique
   275  	// remote names
   276  	var remoteNames []string
   277  	for _, remote := range remotesList {
   278  		if len(remote) == 0 {
   279  			continue
   280  		}
   281  
   282  		name := strings.Split(remote, ".")[1]
   283  		// Check if name is unique
   284  		var found bool
   285  		for _, placedName := range remoteNames {
   286  			if name == placedName {
   287  				found = true
   288  				break
   289  			}
   290  		}
   291  		if found {
   292  			continue
   293  		}
   294  		remoteNames = append(remoteNames, name)
   295  	}
   296  
   297  	// Check if remote exists and is in order
   298  	for i, match := range reMatches {
   299  		require.Equal(t, match[1], remoteNames[i])
   300  	}
   301  }
   302  
   303  // copyTestRepo creates a copy of the testdata directory (contains a Git repo) in
   304  // the project root with a random dir name. It returns the absolute path of the
   305  // new testdata dir.
   306  // Note: testdata-* must be in the .gitignore or the copies will create write
   307  // errors as Git attempts to add the Git repo to the the project repo's index.
   308  func copyTestRepo() string {
   309  	dst, err := filepath.Abs(os.ExpandEnv("$GOPATH/src/github.com/zaquestion/lab/testdata-" + strconv.Itoa(int(rand.Uint64()))))
   310  	if err != nil {
   311  		log.Fatal(err)
   312  	}
   313  	src, err := filepath.Abs(os.ExpandEnv("$GOPATH/src/github.com/zaquestion/lab/testdata"))
   314  	if err != nil {
   315  		log.Fatal(err)
   316  	}
   317  	if err := copy.Copy(src, dst); err != nil {
   318  		log.Fatal(err)
   319  	}
   320  	// Move the test.git dir into the expected path at .git
   321  	if err := copy.Copy(dst+"/test.git", dst+"/.git"); err != nil {
   322  		log.Fatal(err)
   323  	}
   324  	return dst
   325  }