1+ ////////////////////////////////////////////////////////////////////////////////////////
2+ //
3+ // RelaxVersioner - Git tag/branch based, full-automatic version generator.
4+ // Copyright (c) Kouji Matsui (@kozy_kekyo, @[email protected] ) 5+ //
6+ // Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0
7+ //
8+ ////////////////////////////////////////////////////////////////////////////////////////
9+
10+ using GitReader ;
11+ using GitReader . Primitive ;
12+ using NUnit . Framework ;
13+ using System ;
14+ using System . IO ;
15+ using System . Threading . Tasks ;
16+
17+ namespace RelaxVersioner ;
18+
19+ [ Parallelizable ( ParallelScope . All ) ]
20+ public sealed class AnalyzerEdgeCasesTests
21+ {
22+ [ Test ]
23+ public async Task LookupVersionLabel_EmptyRepository_ReturnsDefaultVersion ( )
24+ {
25+ var tempPath = Path . Combine ( Path . GetTempPath ( ) , $ "RelaxVersionerTest_{ Guid . NewGuid ( ) : N} ") ;
26+
27+ try
28+ {
29+ Directory . CreateDirectory ( tempPath ) ;
30+
31+ // Initialize empty git repository
32+ await TestUtilities . InitializeGitRepositoryWithMainBranch ( tempPath ) ;
33+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.email \" [email protected] \" " ) ; 34+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.name \" Test User\" " ) ;
35+
36+ using var repository = await Repository . Factory . OpenPrimitiveAsync ( tempPath ) ;
37+ var version = await Analyzer . LookupVersionLabelAsync ( repository , false , default ) ;
38+
39+ Assert . That ( version . ToString ( ) , Is . EqualTo ( "0.0.1" ) ) ;
40+ }
41+ finally
42+ {
43+ if ( Directory . Exists ( tempPath ) )
44+ {
45+ try { Directory . Delete ( tempPath , true ) ; } catch { }
46+ }
47+ }
48+ }
49+
50+ [ Test ]
51+ public async Task LookupVersionLabel_DetachedHead_ReturnsCorrectVersion ( )
52+ {
53+ var tempPath = Path . Combine ( Path . GetTempPath ( ) , $ "RelaxVersionerTest_{ Guid . NewGuid ( ) : N} ") ;
54+
55+ try
56+ {
57+ Directory . CreateDirectory ( tempPath ) ;
58+
59+ // Initialize repository with commits and tag
60+ await TestUtilities . InitializeGitRepositoryWithMainBranch ( tempPath ) ;
61+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.email \" [email protected] \" " ) ; 62+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.name \" Test User\" " ) ;
63+
64+ var testFile = Path . Combine ( tempPath , "test.txt" ) ;
65+ File . WriteAllText ( testFile , "content" ) ;
66+ await TestUtilities . RunGitCommandAsync ( tempPath , "add test.txt" ) ;
67+ await TestUtilities . RunGitCommandAsync ( tempPath , "commit -m \" Initial commit\" " ) ;
68+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v2.1.0" ) ;
69+
70+ // Create another commit
71+ File . WriteAllText ( testFile , "modified content" ) ;
72+ await TestUtilities . RunGitCommandAsync ( tempPath , "add test.txt" ) ;
73+ await TestUtilities . RunGitCommandAsync ( tempPath , "commit -m \" Second commit\" " ) ;
74+
75+ // Checkout to detached HEAD state (HEAD~1 points to the tagged commit)
76+ await TestUtilities . RunGitCommandAsync ( tempPath , "checkout HEAD~1" ) ;
77+
78+ using var repository = await Repository . Factory . OpenPrimitiveAsync ( tempPath ) ;
79+ var version = await Analyzer . LookupVersionLabelAsync ( repository , false , default ) ;
80+
81+ Assert . That ( version . ToString ( ) , Is . EqualTo ( "2.1.0" ) ) ;
82+ }
83+ finally
84+ {
85+ if ( Directory . Exists ( tempPath ) )
86+ {
87+ try { Directory . Delete ( tempPath , true ) ; } catch { }
88+ }
89+ }
90+ }
91+
92+ [ Test ]
93+ public async Task LookupVersionLabel_WithInvalidTags_IgnoresInvalidOnes ( )
94+ {
95+ var tempPath = Path . Combine ( Path . GetTempPath ( ) , $ "RelaxVersionerTest_{ Guid . NewGuid ( ) : N} ") ;
96+
97+ try
98+ {
99+ Directory . CreateDirectory ( tempPath ) ;
100+
101+ await TestUtilities . InitializeGitRepositoryWithMainBranch ( tempPath ) ;
102+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.email \" [email protected] \" " ) ; 103+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.name \" Test User\" " ) ;
104+
105+ var testFile = Path . Combine ( tempPath , "test.txt" ) ;
106+ File . WriteAllText ( testFile , "content" ) ;
107+ await TestUtilities . RunGitCommandAsync ( tempPath , "add test.txt" ) ;
108+ await TestUtilities . RunGitCommandAsync ( tempPath , "commit -m \" Initial commit\" " ) ;
109+
110+ // Add various invalid and valid tags
111+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag invalid-tag" ) ;
112+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v1" ) ; // Single component - should be ignored
113+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag not-a-version" ) ;
114+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v3.2.1" ) ; // Valid
115+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag release-notes" ) ;
116+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v2.5.0" ) ; // Valid but smaller
117+
118+ using var repository = await Repository . Factory . OpenPrimitiveAsync ( tempPath ) ;
119+ var version = await Analyzer . LookupVersionLabelAsync ( repository , false , default ) ;
120+
121+ // Should pick the largest valid version (v3.2.1)
122+ Assert . That ( version . ToString ( ) , Is . EqualTo ( "3.2.1" ) ) ;
123+ }
124+ finally
125+ {
126+ if ( Directory . Exists ( tempPath ) )
127+ {
128+ try { Directory . Delete ( tempPath , true ) ; } catch { }
129+ }
130+ }
131+ }
132+
133+ [ Test ]
134+ public async Task LookupVersionLabel_WithOrphanBranch_ReturnsDefaultVersion ( )
135+ {
136+ var tempPath = Path . Combine ( Path . GetTempPath ( ) , $ "RelaxVersionerTest_{ Guid . NewGuid ( ) : N} ") ;
137+
138+ try
139+ {
140+ Directory . CreateDirectory ( tempPath ) ;
141+
142+ await TestUtilities . InitializeGitRepositoryWithMainBranch ( tempPath ) ;
143+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.email \" [email protected] \" " ) ; 144+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.name \" Test User\" " ) ;
145+
146+ // Create main branch with tagged commit
147+ var testFile = Path . Combine ( tempPath , "test.txt" ) ;
148+ File . WriteAllText ( testFile , "content" ) ;
149+ await TestUtilities . RunGitCommandAsync ( tempPath , "add test.txt" ) ;
150+ await TestUtilities . RunGitCommandAsync ( tempPath , "commit -m \" Initial commit\" " ) ;
151+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v1.0.0" ) ;
152+
153+ // Create orphan branch
154+ await TestUtilities . RunGitCommandAsync ( tempPath , "checkout --orphan orphan-branch" ) ;
155+ await TestUtilities . RunGitCommandAsync ( tempPath , "rm -f test.txt" ) ;
156+
157+ var orphanFile = Path . Combine ( tempPath , "orphan.txt" ) ;
158+ File . WriteAllText ( orphanFile , "orphan content" ) ;
159+ await TestUtilities . RunGitCommandAsync ( tempPath , "add orphan.txt" ) ;
160+ await TestUtilities . RunGitCommandAsync ( tempPath , "commit -m \" Orphan commit\" " ) ;
161+
162+ using var repository = await Repository . Factory . OpenPrimitiveAsync ( tempPath ) ;
163+ var version = await Analyzer . LookupVersionLabelAsync ( repository , false , default ) ;
164+
165+ // Orphan branch should return default version
166+ Assert . That ( version . ToString ( ) , Is . EqualTo ( "0.0.1" ) ) ;
167+ }
168+ finally
169+ {
170+ if ( Directory . Exists ( tempPath ) )
171+ {
172+ try { Directory . Delete ( tempPath , true ) ; } catch { }
173+ }
174+ }
175+ }
176+
177+ [ Test ]
178+ public async Task LookupVersionLabel_DeepHistory_PerformsCorrectly ( )
179+ {
180+ var tempPath = Path . Combine ( Path . GetTempPath ( ) , $ "RelaxVersionerTest_{ Guid . NewGuid ( ) : N} ") ;
181+
182+ try
183+ {
184+ Directory . CreateDirectory ( tempPath ) ;
185+
186+ await TestUtilities . InitializeGitRepositoryWithMainBranch ( tempPath ) ;
187+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.email \" [email protected] \" " ) ; 188+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.name \" Test User\" " ) ;
189+
190+ var testFile = Path . Combine ( tempPath , "test.txt" ) ;
191+ File . WriteAllText ( testFile , "initial" ) ;
192+ await TestUtilities . RunGitCommandAsync ( tempPath , "add test.txt" ) ;
193+ await TestUtilities . RunGitCommandAsync ( tempPath , "commit -m \" Initial commit\" " ) ;
194+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v1.0.0" ) ;
195+
196+ // Create deep history (50 commits)
197+ for ( int i = 1 ; i <= 50 ; i ++ )
198+ {
199+ File . WriteAllText ( testFile , $ "content { i } ") ;
200+ await TestUtilities . RunGitCommandAsync ( tempPath , "add test.txt" ) ;
201+ await TestUtilities . RunGitCommandAsync ( tempPath , $ "commit -m \" Commit { i } \" ") ;
202+ }
203+
204+ using var repository = await Repository . Factory . OpenPrimitiveAsync ( tempPath ) ;
205+ var version = await Analyzer . LookupVersionLabelAsync ( repository , false , default ) ;
206+
207+ // Should be v1.0.0 + 50 increments = v1.0.50
208+ Assert . That ( version . ToString ( ) , Is . EqualTo ( "1.0.50" ) ) ;
209+ }
210+ finally
211+ {
212+ if ( Directory . Exists ( tempPath ) )
213+ {
214+ try { Directory . Delete ( tempPath , true ) ; } catch { }
215+ }
216+ }
217+ }
218+
219+ [ Test ]
220+ public async Task LookupVersionLabel_MultipleTagsOnSameCommit_ChoosesLargest ( )
221+ {
222+ var tempPath = Path . Combine ( Path . GetTempPath ( ) , $ "RelaxVersionerTest_{ Guid . NewGuid ( ) : N} ") ;
223+
224+ try
225+ {
226+ Directory . CreateDirectory ( tempPath ) ;
227+
228+ await TestUtilities . InitializeGitRepositoryWithMainBranch ( tempPath ) ;
229+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.email \" [email protected] \" " ) ; 230+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.name \" Test User\" " ) ;
231+
232+ var testFile = Path . Combine ( tempPath , "test.txt" ) ;
233+ File . WriteAllText ( testFile , "content" ) ;
234+ await TestUtilities . RunGitCommandAsync ( tempPath , "add test.txt" ) ;
235+ await TestUtilities . RunGitCommandAsync ( tempPath , "commit -m \" Tagged commit\" " ) ;
236+
237+ // Add multiple tags to the same commit
238+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v1.5.0" ) ;
239+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v2.0.0" ) ;
240+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v1.9.9" ) ;
241+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v2.0.1" ) ; // This should be the largest
242+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v1.10.0" ) ;
243+
244+ using var repository = await Repository . Factory . OpenPrimitiveAsync ( tempPath ) ;
245+ var version = await Analyzer . LookupVersionLabelAsync ( repository , false , default ) ;
246+
247+ Assert . That ( version . ToString ( ) , Is . EqualTo ( "2.0.1" ) ) ;
248+ }
249+ finally
250+ {
251+ if ( Directory . Exists ( tempPath ) )
252+ {
253+ try { Directory . Delete ( tempPath , true ) ; } catch { }
254+ }
255+ }
256+ }
257+
258+ [ Test ]
259+ public async Task LookupVersionLabel_WithWorkingDirectoryChanges_IncrementsCorrectly ( )
260+ {
261+ var tempPath = Path . Combine ( Path . GetTempPath ( ) , $ "RelaxVersionerTest_{ Guid . NewGuid ( ) : N} ") ;
262+
263+ try
264+ {
265+ Directory . CreateDirectory ( tempPath ) ;
266+
267+ await TestUtilities . InitializeGitRepositoryWithMainBranch ( tempPath ) ;
268+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.email \" [email protected] \" " ) ; 269+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.name \" Test User\" " ) ;
270+
271+ var testFile = Path . Combine ( tempPath , "test.txt" ) ;
272+ File . WriteAllText ( testFile , "content" ) ;
273+ await TestUtilities . RunGitCommandAsync ( tempPath , "add test.txt" ) ;
274+ await TestUtilities . RunGitCommandAsync ( tempPath , "commit -m \" Initial commit\" " ) ;
275+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v1.2.3.4" ) ; // 4-component version
276+
277+ // Test clean state
278+ using ( var repository = await Repository . Factory . OpenPrimitiveAsync ( tempPath ) )
279+ {
280+ var version = await Analyzer . LookupVersionLabelAsync ( repository , true , default ) ;
281+ Assert . That ( version . ToString ( ) , Is . EqualTo ( "1.2.3.4" ) ) ;
282+ }
283+
284+ // Test with unstaged changes
285+ File . WriteAllText ( testFile , "modified" ) ;
286+ using ( var repository = await Repository . Factory . OpenPrimitiveAsync ( tempPath ) )
287+ {
288+ var version = await Analyzer . LookupVersionLabelAsync ( repository , true , default ) ;
289+ Assert . That ( version . ToString ( ) , Is . EqualTo ( "1.2.3.5" ) ) ; // Revision incremented
290+ }
291+ }
292+ finally
293+ {
294+ if ( Directory . Exists ( tempPath ) )
295+ {
296+ try { Directory . Delete ( tempPath , true ) ; } catch { }
297+ }
298+ }
299+ }
300+
301+ [ Test ]
302+ public async Task LookupVersionLabel_DifferentVersionFormats_ParsesCorrectly ( )
303+ {
304+ var tempPath = Path . Combine ( Path . GetTempPath ( ) , $ "RelaxVersionerTest_{ Guid . NewGuid ( ) : N} ") ;
305+
306+ try
307+ {
308+ Directory . CreateDirectory ( tempPath ) ;
309+
310+ await TestUtilities . InitializeGitRepositoryWithMainBranch ( tempPath ) ;
311+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.email \" [email protected] \" " ) ; 312+ await TestUtilities . RunGitCommandAsync ( tempPath , "config user.name \" Test User\" " ) ;
313+
314+ var testFile = Path . Combine ( tempPath , "test.txt" ) ;
315+
316+ // Test 2-component version
317+ File . WriteAllText ( testFile , "content1" ) ;
318+ await TestUtilities . RunGitCommandAsync ( tempPath , "add test.txt" ) ;
319+ await TestUtilities . RunGitCommandAsync ( tempPath , "commit -m \" Commit 1\" " ) ;
320+ await TestUtilities . RunGitCommandAsync ( tempPath , "tag v5.10" ) ;
321+
322+ File . WriteAllText ( testFile , "content2" ) ;
323+ await TestUtilities . RunGitCommandAsync ( tempPath , "add test.txt" ) ;
324+ await TestUtilities . RunGitCommandAsync ( tempPath , "commit -m \" Commit 2\" " ) ;
325+
326+ using var repository = await Repository . Factory . OpenPrimitiveAsync ( tempPath ) ;
327+ var version = await Analyzer . LookupVersionLabelAsync ( repository , false , default ) ;
328+
329+ // Should be v5.10 + 1 = v5.11
330+ Assert . That ( version . ToString ( ) , Is . EqualTo ( "5.11" ) ) ;
331+ }
332+ finally
333+ {
334+ if ( Directory . Exists ( tempPath ) )
335+ {
336+ try { Directory . Delete ( tempPath , true ) ; } catch { }
337+ }
338+ }
339+ }
340+ }
0 commit comments