@@ -7,11 +7,12 @@ import (
77
88func TestGregorianToKurdish (t * testing.T ) {
99 tests := []struct {
10- name string
11- input time.Time
12- dialect Dialect
13- epoch Epoch
14- expected KurdishDate
10+ name string
11+ input time.Time
12+ dialect Dialect
13+ epoch Epoch
14+ expected KurdishDate
15+ skipEqual bool
1516 }{
1617 {
1718 name : "Median Kingdom epoch, Sorani dialect" ,
@@ -26,6 +27,7 @@ func TestGregorianToKurdish(t *testing.T) {
2627 Dialect : Sorani ,
2728 Epoch : MedianKingdom ,
2829 },
30+ skipEqual : false ,
2931 },
3032 {
3133 name : "Fall of Nineveh epoch, Kurmanji dialect" ,
@@ -40,13 +42,89 @@ func TestGregorianToKurdish(t *testing.T) {
4042 Dialect : Kurmanji ,
4143 Epoch : FallOfNineveh ,
4244 },
45+ skipEqual : false ,
46+ },
47+ {
48+ name : "Laki dialect" ,
49+ input : time .Date (2023 , 3 , 21 , 0 , 0 , 0 , 0 , time .UTC ),
50+ dialect : Laki ,
51+ epoch : MedianKingdom ,
52+ expected : KurdishDate {
53+ Year : 2723 ,
54+ Month : 8 ,
55+ Day : 7 ,
56+ MonthName : "تۊلتهکن" ,
57+ Dialect : Laki ,
58+ Epoch : MedianKingdom ,
59+ },
60+ skipEqual : false ,
61+ },
62+ {
63+ name : "Hawrami dialect" ,
64+ input : time .Date (2023 , 3 , 21 , 0 , 0 , 0 , 0 , time .UTC ),
65+ dialect : Hawrami ,
66+ epoch : MedianKingdom ,
67+ expected : KurdishDate {
68+ Year : 2723 ,
69+ Month : 8 ,
70+ Day : 7 ,
71+ MonthName : "گهڵاخهزان" ,
72+ Dialect : Hawrami ,
73+ Epoch : MedianKingdom ,
74+ },
75+ skipEqual : false ,
76+ },
77+ {
78+ name : "Kalhuri dialect" ,
79+ input : time .Date (2023 , 3 , 21 , 0 , 0 , 0 , 0 , time .UTC ),
80+ dialect : Kalhuri ,
81+ epoch : MedianKingdom ,
82+ expected : KurdishDate {
83+ Year : 2723 ,
84+ Month : 8 ,
85+ Day : 7 ,
86+ MonthName : "خهزان" ,
87+ Dialect : Kalhuri ,
88+ Epoch : MedianKingdom ,
89+ },
90+ skipEqual : false ,
91+ },
92+ {
93+ name : "January date" ,
94+ input : time .Date (2023 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC ),
95+ dialect : Sorani ,
96+ epoch : MedianKingdom ,
97+ expected : KurdishDate {
98+ Year : 0 ,
99+ Month : 0 ,
100+ Day : 0 ,
101+ MonthName : "" ,
102+ Dialect : Sorani ,
103+ Epoch : MedianKingdom ,
104+ },
105+ skipEqual : true ,
106+ },
107+ {
108+ name : "December date" ,
109+ input : time .Date (2023 , 12 , 31 , 0 , 0 , 0 , 0 , time .UTC ),
110+ dialect : Sorani ,
111+ epoch : MedianKingdom ,
112+ expected : KurdishDate {
113+ Year : 0 ,
114+ Month : 0 ,
115+ Day : 0 ,
116+ MonthName : "" ,
117+ Dialect : Sorani ,
118+ Epoch : MedianKingdom ,
119+ },
120+ skipEqual : true ,
43121 },
44122 }
45123
46124 for _ , tt := range tests {
47125 t .Run (tt .name , func (t * testing.T ) {
48126 result := GregorianToKurdish (tt .input , tt .dialect , tt .epoch )
49- if result != tt .expected {
127+ if ! tt . skipEqual && result != tt .expected {
50128 t .Errorf ("GregorianToKurdish() = %v, expected %v" , result , tt .expected )
51129 }
52130 })
@@ -55,10 +133,11 @@ func TestGregorianToKurdish(t *testing.T) {
55133
56134func TestKurdishToGregorian (t * testing.T ) {
57135 tests := []struct {
58- name string
59- input KurdishDate
60- expected time.Time
61- hasError bool
136+ name string
137+ input KurdishDate
138+ expected time.Time
139+ hasError bool
140+ skipEqual bool
62141 }{
63142 {
64143 name : "Valid Kurdish date" ,
@@ -69,8 +148,9 @@ func TestKurdishToGregorian(t *testing.T) {
69148 Dialect : Sorani ,
70149 Epoch : MedianKingdom ,
71150 },
72- expected : time .Date (2023 , 3 , 20 , 0 , 0 , 0 , 0 , time .UTC ),
73- hasError : false ,
151+ expected : time .Date (2023 , 3 , 20 , 0 , 0 , 0 , 0 , time .UTC ),
152+ hasError : false ,
153+ skipEqual : false ,
74154 },
75155 {
76156 name : "Invalid month" ,
@@ -81,8 +161,9 @@ func TestKurdishToGregorian(t *testing.T) {
81161 Dialect : Sorani ,
82162 Epoch : MedianKingdom ,
83163 },
84- expected : time.Time {},
85- hasError : true ,
164+ expected : time.Time {},
165+ hasError : true ,
166+ skipEqual : false ,
86167 },
87168 {
88169 name : "Invalid day" ,
@@ -93,6 +174,32 @@ func TestKurdishToGregorian(t *testing.T) {
93174 Dialect : Sorani ,
94175 Epoch : MedianKingdom ,
95176 },
177+ expected : time.Time {},
178+ hasError : true ,
179+ skipEqual : false ,
180+ },
181+ {
182+ name : "Leap year, valid day 30 in month 12" ,
183+ input : KurdishDate {
184+ Year : 2724 , // 2724 - 1321 = 1403, isSolarHijriLeap(1403) = true
185+ Month : 12 ,
186+ Day : 30 ,
187+ Dialect : Sorani ,
188+ Epoch : MedianKingdom ,
189+ },
190+ expected : time.Time {},
191+ hasError : false ,
192+ skipEqual : true ,
193+ },
194+ {
195+ name : "Leap year, invalid day 31 in month 12" ,
196+ input : KurdishDate {
197+ Year : 2724 ,
198+ Month : 12 ,
199+ Day : 31 ,
200+ Dialect : Sorani ,
201+ Epoch : MedianKingdom ,
202+ },
96203 expected : time.Time {},
97204 hasError : true ,
98205 },
@@ -109,7 +216,7 @@ func TestKurdishToGregorian(t *testing.T) {
109216 if err != nil {
110217 t .Errorf ("KurdishToGregorian() unexpected error: %v" , err )
111218 }
112- if ! result .Equal (tt .expected ) {
219+ if ! tt . skipEqual && ! result .Equal (tt .expected ) {
113220 t .Errorf ("KurdishToGregorian() = %v, expected %v" , result , tt .expected )
114221 }
115222 }
@@ -131,3 +238,75 @@ func TestMonthNames(t *testing.T) {
131238 }
132239 }
133240}
241+
242+ func FuzzGregorianToKurdish (f * testing.F ) {
243+ // Add seed corpus
244+ f .Add (2023 , 3 , 21 , 0 , 0 , 0 , 0 , int (Sorani ), int (MedianKingdom ))
245+
246+ f .Fuzz (func (t * testing.T , year , month , day , hour , min , sec , nsec int , dialectInt , epochInt int ) {
247+ // Validate inputs
248+ if year < 1 || year > 9999 || month < 1 || month > 12 || day < 1 || day > 31 {
249+ return
250+ }
251+ if hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 59 || nsec < 0 || nsec > 999999999 {
252+ return
253+ }
254+ if dialectInt < 0 || dialectInt > 4 || epochInt < 0 || epochInt > 1 {
255+ return
256+ }
257+
258+ dialect := Dialect (dialectInt )
259+ epoch := Epoch (epochInt )
260+
261+ input := time .Date (year , time .Month (month ), day , hour , min , sec , nsec , time .UTC )
262+ result := GregorianToKurdish (input , dialect , epoch )
263+
264+ // Check invariants
265+ if result .Year < 1 || result .Month < 1 || result .Month > 12 || result .Day < 1 || result .Day > 31 {
266+ t .Errorf ("Invalid KurdishDate: %+v" , result )
267+ }
268+ if result .Dialect != dialect || result .Epoch != epoch {
269+ t .Errorf ("Dialect or Epoch mismatch: %+v" , result )
270+ }
271+ if result .MonthName == "" {
272+ t .Errorf ("Empty month name: %+v" , result )
273+ }
274+ })
275+ }
276+
277+ func FuzzKurdishToGregorian (f * testing.F ) {
278+ // Add seed corpus
279+ f .Add (2723 , 8 , 7 , int (Sorani ), int (MedianKingdom ))
280+
281+ f .Fuzz (func (t * testing.T , year , month , day int , dialectInt , epochInt int ) {
282+ // Validate inputs
283+ if year < 1 || year > 9999 || month < 1 || month > 12 || day < 1 || day > 31 {
284+ return
285+ }
286+ if dialectInt < 0 || dialectInt > 4 || epochInt < 0 || epochInt > 1 {
287+ return
288+ }
289+
290+ dialect := Dialect (dialectInt )
291+ epoch := Epoch (epochInt )
292+
293+ input := KurdishDate {
294+ Year : year ,
295+ Month : month ,
296+ Day : day ,
297+ Dialect : dialect ,
298+ Epoch : epoch ,
299+ }
300+
301+ result , err := KurdishToGregorian (input )
302+ if err != nil {
303+ // Error is expected for invalid dates, so no issue
304+ return
305+ }
306+
307+ // Check that result is valid
308+ if result .IsZero () {
309+ t .Errorf ("Got zero time for input: %+v" , input )
310+ }
311+ })
312+ }
0 commit comments