Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2
at master 386 lines 8.6 kB view raw
1package git 2 3import ( 4 "path/filepath" 5 "testing" 6 "time" 7 8 gogit "github.com/go-git/go-git/v5" 9 "github.com/go-git/go-git/v5/plumbing" 10 "github.com/go-git/go-git/v5/plumbing/object" 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 "github.com/stretchr/testify/suite" 14) 15 16type TagSuite struct { 17 suite.Suite 18 *RepoSuite 19} 20 21func TestTagSuite(t *testing.T) { 22 t.Parallel() 23 suite.Run(t, new(TagSuite)) 24} 25 26func (s *TagSuite) SetupTest() { 27 s.RepoSuite = NewRepoSuite(s.T()) 28} 29 30func (s *TagSuite) TearDownTest() { 31 s.RepoSuite.cleanup() 32} 33 34func (s *TagSuite) setupRepoWithTags() { 35 s.init() 36 37 // create commits for tagging 38 commit1 := s.commitFile("file1.txt", "content 1", "Add file1") 39 commit2 := s.commitFile("file2.txt", "content 2", "Add file2") 40 commit3 := s.commitFile("file3.txt", "content 3", "Add file3") 41 commit4 := s.commitFile("file4.txt", "content 4", "Add file4") 42 commit5 := s.commitFile("file5.txt", "content 5", "Add file5") 43 44 // create annotated tags 45 s.createAnnotatedTag( 46 "v1.0.0", 47 commit1, 48 "Tagger One", 49 "tagger1@example.com", 50 "Release version 1.0.0\n\nThis is the first stable release.", 51 s.baseTime.Add(1*time.Hour), 52 ) 53 54 s.createAnnotatedTag( 55 "v1.1.0", 56 commit2, 57 "Tagger Two", 58 "tagger2@example.com", 59 "Release version 1.1.0", 60 s.baseTime.Add(2*time.Hour), 61 ) 62 63 // create lightweight tags 64 s.createLightweightTag("v2.0.0", commit3) 65 s.createLightweightTag("v2.1.0", commit4) 66 67 // create another annotated tag 68 s.createAnnotatedTag( 69 "v3.0.0", 70 commit5, 71 "Tagger Three", 72 "tagger3@example.com", 73 "Major version 3.0.0\n\nBreaking changes included.", 74 s.baseTime.Add(3*time.Hour), 75 ) 76} 77 78func (s *TagSuite) TestTags_All() { 79 s.setupRepoWithTags() 80 81 tags, err := s.repo.Tags(nil) 82 require.NoError(s.T(), err) 83 84 // we created 5 tags total (3 annotated, 2 lightweight) 85 assert.Len(s.T(), tags, 5, "expected 5 tags") 86 87 // verify tags are sorted by creation date (newest first) 88 expectedAnnotated := map[string]bool{ 89 "v1.0.0": true, 90 "v1.1.0": true, 91 "v3.0.0": true, 92 } 93 94 expectedLightweight := map[string]bool{ 95 "v2.0.0": true, 96 "v2.1.0": true, 97 } 98 99 for _, tag := range tags { 100 if expectedAnnotated[tag.Name] { 101 // annotated tags should have tagger info 102 assert.NotEmpty(s.T(), tag.Tagger.Name, "annotated tag %s should have tagger name", tag.Name) 103 assert.NotEmpty(s.T(), tag.Message, "annotated tag %s should have message", tag.Name) 104 } else if expectedLightweight[tag.Name] { 105 // lightweight tags won't have tagger info or message (they'll have empty values) 106 } else { 107 s.T().Errorf("unexpected tag name: %s", tag.Name) 108 } 109 } 110} 111 112func (s *TagSuite) TestTags_WithLimit() { 113 s.setupRepoWithTags() 114 115 tests := []struct { 116 name string 117 limit int 118 expectedCount int 119 }{ 120 { 121 name: "limit 1", 122 limit: 1, 123 expectedCount: 1, 124 }, 125 { 126 name: "limit 2", 127 limit: 2, 128 expectedCount: 2, 129 }, 130 { 131 name: "limit 3", 132 limit: 3, 133 expectedCount: 3, 134 }, 135 { 136 name: "limit 10 (more than available)", 137 limit: 10, 138 expectedCount: 5, 139 }, 140 } 141 142 for _, tt := range tests { 143 s.Run(tt.name, func() { 144 tags, err := s.repo.Tags(&TagsOptions{ 145 Limit: tt.limit, 146 }) 147 require.NoError(s.T(), err) 148 assert.Len(s.T(), tags, tt.expectedCount, "expected %d tags", tt.expectedCount) 149 }) 150 } 151} 152 153func (s *TagSuite) TestTags_WithOffset() { 154 s.setupRepoWithTags() 155 156 tests := []struct { 157 name string 158 offset int 159 expectedCount int 160 }{ 161 { 162 name: "offset 0", 163 offset: 0, 164 expectedCount: 5, 165 }, 166 { 167 name: "offset 1", 168 offset: 1, 169 expectedCount: 4, 170 }, 171 { 172 name: "offset 2", 173 offset: 2, 174 expectedCount: 3, 175 }, 176 { 177 name: "offset 4", 178 offset: 4, 179 expectedCount: 1, 180 }, 181 { 182 name: "offset 5 (all skipped)", 183 offset: 5, 184 expectedCount: 0, 185 }, 186 { 187 name: "offset 10 (more than available)", 188 offset: 10, 189 expectedCount: 0, 190 }, 191 } 192 193 for _, tt := range tests { 194 s.Run(tt.name, func() { 195 tags, err := s.repo.Tags(&TagsOptions{ 196 Offset: tt.offset, 197 }) 198 require.NoError(s.T(), err) 199 assert.Len(s.T(), tags, tt.expectedCount, "expected %d tags", tt.expectedCount) 200 }) 201 } 202} 203 204func (s *TagSuite) TestTags_WithLimitAndOffset() { 205 s.setupRepoWithTags() 206 207 tests := []struct { 208 name string 209 limit int 210 offset int 211 expectedCount int 212 }{ 213 { 214 name: "limit 2, offset 0", 215 limit: 2, 216 offset: 0, 217 expectedCount: 2, 218 }, 219 { 220 name: "limit 2, offset 1", 221 limit: 2, 222 offset: 1, 223 expectedCount: 2, 224 }, 225 { 226 name: "limit 2, offset 3", 227 limit: 2, 228 offset: 3, 229 expectedCount: 2, 230 }, 231 { 232 name: "limit 2, offset 4", 233 limit: 2, 234 offset: 4, 235 expectedCount: 1, 236 }, 237 { 238 name: "limit 3, offset 2", 239 limit: 3, 240 offset: 2, 241 expectedCount: 3, 242 }, 243 { 244 name: "limit 10, offset 3", 245 limit: 10, 246 offset: 3, 247 expectedCount: 2, 248 }, 249 } 250 251 for _, tt := range tests { 252 s.Run(tt.name, func() { 253 tags, err := s.repo.Tags(&TagsOptions{ 254 Limit: tt.limit, 255 Offset: tt.offset, 256 }) 257 require.NoError(s.T(), err) 258 assert.Len(s.T(), tags, tt.expectedCount, "expected %d tags", tt.expectedCount) 259 }) 260 } 261} 262 263func (s *TagSuite) TestTags_EmptyRepo() { 264 repoPath := filepath.Join(s.tempDir, "empty-repo") 265 266 _, err := gogit.PlainInit(repoPath, false) 267 require.NoError(s.T(), err) 268 269 gitRepo, err := PlainOpen(repoPath) 270 require.NoError(s.T(), err) 271 272 tags, err := gitRepo.Tags(nil) 273 require.NoError(s.T(), err) 274 275 if tags != nil { 276 assert.Empty(s.T(), tags, "expected no tags in empty repo") 277 } 278} 279 280func (s *TagSuite) TestTags_Pagination() { 281 s.setupRepoWithTags() 282 283 allTags, err := s.repo.Tags(nil) 284 require.NoError(s.T(), err) 285 assert.Len(s.T(), allTags, 5, "expected 5 tags") 286 287 pageSize := 2 288 var paginatedTags []object.Tag 289 290 for offset := 0; offset < len(allTags); offset += pageSize { 291 tags, err := s.repo.Tags(&TagsOptions{ 292 Limit: pageSize, 293 Offset: offset, 294 }) 295 require.NoError(s.T(), err) 296 paginatedTags = append(paginatedTags, tags...) 297 } 298 299 assert.Len(s.T(), paginatedTags, len(allTags), "pagination should return all tags") 300 301 for i := range allTags { 302 assert.Equal(s.T(), allTags[i].Name, paginatedTags[i].Name, 303 "tag at index %d differs", i) 304 } 305} 306 307func (s *TagSuite) TestTags_VerifyAnnotatedTagFields() { 308 s.setupRepoWithTags() 309 310 tags, err := s.repo.Tags(nil) 311 require.NoError(s.T(), err) 312 313 var v1Tag *object.Tag 314 for i := range tags { 315 if tags[i].Name == "v1.0.0" { 316 v1Tag = &tags[i] 317 break 318 } 319 } 320 321 require.NotNil(s.T(), v1Tag, "v1.0.0 tag not found") 322 323 assert.Equal(s.T(), "Tagger One", v1Tag.Tagger.Name, "tagger name should match") 324 assert.Equal(s.T(), "tagger1@example.com", v1Tag.Tagger.Email, "tagger email should match") 325 326 assert.Equal(s.T(), "Release version 1.0.0\n\nThis is the first stable release.\n", 327 v1Tag.Message, "tag message should match") 328 329 assert.Equal(s.T(), plumbing.TagObject, v1Tag.TargetType, 330 "target type should be CommitObject") 331 332 assert.False(s.T(), v1Tag.Hash.IsZero(), "tag hash should be set") 333 334 assert.False(s.T(), v1Tag.Target.IsZero(), "target hash should be set") 335} 336 337func (s *TagSuite) TestTags_NilOptions() { 338 s.setupRepoWithTags() 339 340 tags, err := s.repo.Tags(nil) 341 require.NoError(s.T(), err) 342 assert.Len(s.T(), tags, 5, "nil options should return all tags") 343} 344 345func (s *TagSuite) TestTags_ZeroLimitAndOffset() { 346 s.setupRepoWithTags() 347 348 tags, err := s.repo.Tags(&TagsOptions{ 349 Limit: 0, 350 Offset: 0, 351 }) 352 require.NoError(s.T(), err) 353 assert.Len(s.T(), tags, 5, "zero limit should return all tags") 354} 355 356func (s *TagSuite) TestTags_OrderedNewestFirst() { 357 s.setupRepoWithTags() 358 359 tags, err := s.repo.Tags(nil) 360 require.NoError(s.T(), err) 361 require.Len(s.T(), tags, 5) 362 363 // v3.0.0 has the latest tagger date (baseTime+3h), should be first 364 assert.Equal(s.T(), "v3.0.0", tags[0].Name, "newest tag should be first") 365} 366 367func (s *TagSuite) TestTags_LatestWithLimit1() { 368 s.setupRepoWithTags() 369 370 tags, err := s.repo.Tags(&TagsOptions{Limit: 1}) 371 require.NoError(s.T(), err) 372 require.Len(s.T(), tags, 1) 373 374 assert.Equal(s.T(), "v3.0.0", tags[0].Name, "limit=1 should return the newest tag") 375} 376 377func (s *TagSuite) TestTags_Pattern() { 378 s.setupRepoWithTags() 379 380 v1tag, err := s.repo.Tags(&TagsOptions{ 381 Pattern: "refs/tags/v1.0.0", 382 }) 383 384 require.NoError(s.T(), err) 385 assert.Len(s.T(), v1tag, 1, "expected 1 tag") 386}