at master 355 lines 8.2 kB view raw
1package git 2 3import ( 4 "path/filepath" 5 "slices" 6 "testing" 7 8 gogit "github.com/go-git/go-git/v5" 9 "github.com/go-git/go-git/v5/plumbing" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 "github.com/stretchr/testify/suite" 13 14 "tangled.org/core/sets" 15) 16 17type BranchSuite struct { 18 suite.Suite 19 *RepoSuite 20} 21 22func TestBranchSuite(t *testing.T) { 23 t.Parallel() 24 suite.Run(t, new(BranchSuite)) 25} 26 27func (s *BranchSuite) SetupTest() { 28 s.RepoSuite = NewRepoSuite(s.T()) 29} 30 31func (s *BranchSuite) TearDownTest() { 32 s.RepoSuite.cleanup() 33} 34 35func (s *BranchSuite) setupRepoWithBranches() { 36 s.init() 37 38 // get the initial commit on master 39 head, err := s.repo.r.Head() 40 require.NoError(s.T(), err) 41 initialCommit := head.Hash() 42 43 // create multiple branches with commits 44 // branch-1 45 s.createBranch("branch-1", initialCommit) 46 s.checkoutBranch("branch-1") 47 _ = s.commitFile("file1.txt", "content 1", "Add file1 on branch-1") 48 49 // branch-2 50 s.createBranch("branch-2", initialCommit) 51 s.checkoutBranch("branch-2") 52 _ = s.commitFile("file2.txt", "content 2", "Add file2 on branch-2") 53 54 // branch-3 55 s.createBranch("branch-3", initialCommit) 56 s.checkoutBranch("branch-3") 57 _ = s.commitFile("file3.txt", "content 3", "Add file3 on branch-3") 58 59 // branch-4 60 s.createBranch("branch-4", initialCommit) 61 s.checkoutBranch("branch-4") 62 s.commitFile("file4.txt", "content 4", "Add file4 on branch-4") 63 64 // back to master and make a commit 65 s.checkoutBranch("master") 66 s.commitFile("master-file.txt", "master content", "Add file on master") 67 68 // verify we have multiple branches 69 refs, err := s.repo.r.References() 70 require.NoError(s.T(), err) 71 72 branchCount := 0 73 err = refs.ForEach(func(ref *plumbing.Reference) error { 74 if ref.Name().IsBranch() { 75 branchCount++ 76 } 77 return nil 78 }) 79 require.NoError(s.T(), err) 80 81 // we should have 5 branches: master, branch-1, branch-2, branch-3, branch-4 82 assert.Equal(s.T(), 5, branchCount, "expected 5 branches") 83} 84 85func (s *BranchSuite) TestBranches_All() { 86 s.setupRepoWithBranches() 87 88 branches, err := s.repo.Branches(&BranchesOptions{}) 89 require.NoError(s.T(), err) 90 91 assert.Len(s.T(), branches, 5, "expected 5 branches") 92 93 expectedBranches := sets.Collect(slices.Values([]string{ 94 "master", 95 "branch-1", 96 "branch-2", 97 "branch-3", 98 "branch-4", 99 })) 100 101 for _, branch := range branches { 102 assert.True(s.T(), expectedBranches.Contains(branch.Reference.Name), 103 "unexpected branch: %s", branch.Reference.Name) 104 assert.NotEmpty(s.T(), branch.Reference.Hash, "branch hash should not be empty") 105 assert.NotNil(s.T(), branch.Commit, "branch commit should not be nil") 106 } 107} 108 109func (s *BranchSuite) TestBranches_WithLimit() { 110 s.setupRepoWithBranches() 111 112 tests := []struct { 113 name string 114 limit int 115 expectedCount int 116 }{ 117 { 118 name: "limit 1", 119 limit: 1, 120 expectedCount: 1, 121 }, 122 { 123 name: "limit 2", 124 limit: 2, 125 expectedCount: 2, 126 }, 127 { 128 name: "limit 3", 129 limit: 3, 130 expectedCount: 3, 131 }, 132 { 133 name: "limit 10 (more than available)", 134 limit: 10, 135 expectedCount: 5, 136 }, 137 } 138 139 for _, tt := range tests { 140 s.Run(tt.name, func() { 141 branches, err := s.repo.Branches(&BranchesOptions{ 142 Limit: tt.limit, 143 }) 144 require.NoError(s.T(), err) 145 assert.Len(s.T(), branches, tt.expectedCount, "expected %d branches", tt.expectedCount) 146 }) 147 } 148} 149 150func (s *BranchSuite) TestBranches_WithOffset() { 151 s.setupRepoWithBranches() 152 153 tests := []struct { 154 name string 155 offset int 156 expectedCount int 157 }{ 158 { 159 name: "offset 0", 160 offset: 0, 161 expectedCount: 5, 162 }, 163 { 164 name: "offset 1", 165 offset: 1, 166 expectedCount: 4, 167 }, 168 { 169 name: "offset 2", 170 offset: 2, 171 expectedCount: 3, 172 }, 173 { 174 name: "offset 4", 175 offset: 4, 176 expectedCount: 1, 177 }, 178 { 179 name: "offset 5 (all skipped)", 180 offset: 5, 181 expectedCount: 0, 182 }, 183 { 184 name: "offset 10 (more than available)", 185 offset: 10, 186 expectedCount: 0, 187 }, 188 } 189 190 for _, tt := range tests { 191 s.Run(tt.name, func() { 192 branches, err := s.repo.Branches(&BranchesOptions{ 193 Offset: tt.offset, 194 }) 195 require.NoError(s.T(), err) 196 assert.Len(s.T(), branches, tt.expectedCount, "expected %d branches", tt.expectedCount) 197 }) 198 } 199} 200 201func (s *BranchSuite) TestBranches_WithLimitAndOffset() { 202 s.setupRepoWithBranches() 203 204 tests := []struct { 205 name string 206 limit int 207 offset int 208 expectedCount int 209 }{ 210 { 211 name: "limit 2, offset 0", 212 limit: 2, 213 offset: 0, 214 expectedCount: 2, 215 }, 216 { 217 name: "limit 2, offset 1", 218 limit: 2, 219 offset: 1, 220 expectedCount: 2, 221 }, 222 { 223 name: "limit 2, offset 3", 224 limit: 2, 225 offset: 3, 226 expectedCount: 2, 227 }, 228 { 229 name: "limit 2, offset 4", 230 limit: 2, 231 offset: 4, 232 expectedCount: 1, 233 }, 234 { 235 name: "limit 3, offset 2", 236 limit: 3, 237 offset: 2, 238 expectedCount: 3, 239 }, 240 { 241 name: "limit 10, offset 3", 242 limit: 10, 243 offset: 3, 244 expectedCount: 2, 245 }, 246 } 247 248 for _, tt := range tests { 249 s.Run(tt.name, func() { 250 branches, err := s.repo.Branches(&BranchesOptions{ 251 Limit: tt.limit, 252 Offset: tt.offset, 253 }) 254 require.NoError(s.T(), err) 255 assert.Len(s.T(), branches, tt.expectedCount, "expected %d branches", tt.expectedCount) 256 }) 257 } 258} 259 260func (s *BranchSuite) TestBranches_EmptyRepo() { 261 repoPath := filepath.Join(s.tempDir, "empty-repo") 262 263 _, err := gogit.PlainInit(repoPath, false) 264 require.NoError(s.T(), err) 265 266 gitRepo, err := PlainOpen(repoPath) 267 require.NoError(s.T(), err) 268 269 branches, err := gitRepo.Branches(&BranchesOptions{}) 270 require.NoError(s.T(), err) 271 272 if branches != nil { 273 assert.Empty(s.T(), branches, "expected no branches in empty repo") 274 } 275} 276 277func (s *BranchSuite) TestBranches_Pagination() { 278 s.setupRepoWithBranches() 279 280 allBranches, err := s.repo.Branches(&BranchesOptions{}) 281 require.NoError(s.T(), err) 282 assert.Len(s.T(), allBranches, 5, "expected 5 branches") 283 284 pageSize := 2 285 var paginatedBranches []string 286 287 for offset := 0; offset < len(allBranches); offset += pageSize { 288 branches, err := s.repo.Branches(&BranchesOptions{ 289 Limit: pageSize, 290 Offset: offset, 291 }) 292 require.NoError(s.T(), err) 293 for _, branch := range branches { 294 paginatedBranches = append(paginatedBranches, branch.Reference.Name) 295 } 296 } 297 298 assert.Len(s.T(), paginatedBranches, len(allBranches), "pagination should return all branches") 299 300 // create sets to verify all branches are present 301 allBranchNames := sets.New[string]() 302 for _, branch := range allBranches { 303 allBranchNames.Insert(branch.Reference.Name) 304 } 305 306 paginatedBranchNames := sets.New[string]() 307 for _, name := range paginatedBranches { 308 paginatedBranchNames.Insert(name) 309 } 310 311 assert.EqualValues(s.T(), allBranchNames, paginatedBranchNames, 312 "pagination should return the same set of branches") 313} 314 315func (s *BranchSuite) TestBranches_VerifyBranchFields() { 316 s.setupRepoWithBranches() 317 318 branches, err := s.repo.Branches(&BranchesOptions{}) 319 require.NoError(s.T(), err) 320 321 found := false 322 for i := range branches { 323 if branches[i].Reference.Name == "master" { 324 found = true 325 assert.Equal(s.T(), "master", branches[i].Reference.Name) 326 assert.NotEmpty(s.T(), branches[i].Reference.Hash) 327 assert.NotNil(s.T(), branches[i].Commit) 328 assert.NotEmpty(s.T(), branches[i].Commit.Author.Name) 329 assert.NotEmpty(s.T(), branches[i].Commit.Author.Email) 330 assert.False(s.T(), branches[i].Commit.Hash.IsZero()) 331 break 332 } 333 } 334 335 assert.True(s.T(), found, "master branch not found") 336} 337 338func (s *BranchSuite) TestBranches_NilOptions() { 339 s.setupRepoWithBranches() 340 341 branches, err := s.repo.Branches(nil) 342 require.NoError(s.T(), err) 343 assert.Len(s.T(), branches, 5, "nil options should return all branches") 344} 345 346func (s *BranchSuite) TestBranches_ZeroLimitAndOffset() { 347 s.setupRepoWithBranches() 348 349 branches, err := s.repo.Branches(&BranchesOptions{ 350 Limit: 0, 351 Offset: 0, 352 }) 353 require.NoError(s.T(), err) 354 assert.Len(s.T(), branches, 5, "zero limit should return all branches") 355}