@@ -19,8 +19,12 @@ package dbtype
19
19
20
20
import (
21
21
"fmt"
22
+ "math"
23
+ "math/rand/v2"
22
24
"testing"
23
25
"time"
26
+
27
+ "github.com/neo4j/neo4j-go-driver/v5/neo4j/internal/testutil"
24
28
)
25
29
26
30
type stringTestCase [T interface { String () string }] struct {
@@ -152,22 +156,119 @@ func TestLocalDateTimeString(outer *testing.T) {
152
156
}
153
157
154
158
func TestDurationSting (outer * testing.T ) {
159
+ intIs64BitsWide := math .MaxInt64 == int64 (math .MaxInt )
160
+
161
+ var maxNanosCase , minNanosCase , maxCase , minCase stringTestCase [Duration ]
162
+
163
+ {
164
+ var output string
165
+ duration := Duration {Months : 0 , Days : 0 , Seconds : 0 , Nanos : math .MaxInt }
166
+ if intIs64BitsWide {
167
+ output = "PT2562047H47M16.854775807S"
168
+ } else {
169
+ output = "PT2.147483647S"
170
+ }
171
+ maxNanosCase = stringTestCase [Duration ]{input : duration , output : output }
172
+ }
173
+
174
+ {
175
+ var output string
176
+ duration := Duration {Months : 0 , Days : 0 , Seconds : 0 , Nanos : math .MinInt }
177
+ if intIs64BitsWide {
178
+ output = "PT-2562047H-47M-16.854775808S"
179
+ } else {
180
+ output = "PT-2.147483648S"
181
+ }
182
+ minNanosCase = stringTestCase [Duration ]{input : duration , output : output }
183
+ }
184
+
185
+ {
186
+ var output string
187
+ duration := Duration {Months : math .MaxInt64 , Days : math .MaxInt64 , Seconds : math .MaxInt64 , Nanos : math .MaxInt }
188
+ if intIs64BitsWide {
189
+ output = "P768614336404564650Y7M9223372036854775807DT2562047790577263H17M23.854775807S"
190
+ } else {
191
+ output = "P768614336404564650Y7M9223372036854775807DT2562047788015215H30M9.147483647S"
192
+ }
193
+ maxCase = stringTestCase [Duration ]{input : duration , output : output }
194
+ }
195
+
196
+ {
197
+ var output string
198
+ duration := Duration {Months : math .MinInt64 , Days : math .MinInt64 , Seconds : math .MinInt64 , Nanos : math .MinInt }
199
+ if intIs64BitsWide {
200
+ output = "P-768614336404564650Y-8M-9223372036854775808DT-2562047790577263H-17M-24.854775808S"
201
+ } else {
202
+ output = "P-768614336404564650Y-8M-9223372036854775808DT-2562047788015215H-30M-10.147483648S"
203
+ }
204
+ minCase = stringTestCase [Duration ]{input : duration , output : output }
205
+ }
206
+
155
207
outer .Parallel ()
156
208
testCases := []stringTestCase [Duration ]{
157
- {input : Duration {Months : 15 , Days : 32 , Seconds : 785 , Nanos : 789215800 }, output : "P15M32DT785.789215800S" },
158
- {input : Duration {Months : 0 , Days : 32 , Seconds : 785 , Nanos : 789215800 }, output : "P0M32DT785.789215800S" },
159
- {input : Duration {Months : 0 , Days : 0 , Seconds : 785 , Nanos : 789215800 }, output : "P0M0DT785.789215800S" },
160
- {input : Duration {Months : 0 , Days : 0 , Seconds : 0 , Nanos : 789215800 }, output : "P0M0DT0.789215800S" },
161
- {input : Duration {Months : 0 , Days : 0 , Seconds : - 1 , Nanos : 0 }, output : "P0M0DT-1S" },
162
- {input : Duration {Months : 0 , Days : 0 , Seconds : 0 , Nanos : 999999999 }, output : "P0M0DT0.999999999S" },
163
- {input : Duration {Months : 0 , Days : 0 , Seconds : - 1 , Nanos : 5 }, output : "P0M0DT-0.999999995S" },
164
- {input : Duration {Months : 0 , Days : 0 , Seconds : - 1 , Nanos : 999999999 }, output : "P0M0DT-0.000000001S" },
165
- {input : Duration {Months : 500 , Days : 0 , Seconds : 0 , Nanos : 0 }, output : "P500M0DT0S" },
166
- {input : Duration {Months : 0 , Days : 0 , Seconds : 0 , Nanos : 5 }, output : "P0M0DT0.000000005S" },
167
- {input : Duration {Months : 0 , Days : 0 , Seconds : - 500 , Nanos : 1 }, output : "P0M0DT-499.999999999S" },
168
- {input : Duration {Months : 0 , Days : 0 , Seconds : - 500 , Nanos : 0 }, output : "P0M0DT-500S" },
169
- {input : Duration {Months : - 10 , Days : 5 , Seconds : - 2 , Nanos : 500 }, output : "P-10M5DT-1.999999500S" },
170
- {input : Duration {Months : - 10 , Days : - 5 , Seconds : - 2 , Nanos : 500 }, output : "P-10M-5DT-1.999999500S" },
209
+ // all 0
210
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 0 , Nanos : 0 }, output : "PT0S" },
211
+ // single positive component
212
+ {input : Duration {Months : 1 , Days : 0 , Seconds : 0 , Nanos : 0 }, output : "P1M" },
213
+ {input : Duration {Months : 0 , Days : 1 , Seconds : 0 , Nanos : 0 }, output : "P1D" },
214
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 1 , Nanos : 0 }, output : "PT1S" },
215
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 0 , Nanos : 1 }, output : "PT0.000000001S" },
216
+ {input : Duration {Months : math .MaxInt64 , Days : 0 , Seconds : 0 , Nanos : 0 }, output : "P768614336404564650Y7M" },
217
+ {input : Duration {Months : 0 , Days : math .MaxInt64 , Seconds : 0 , Nanos : 0 }, output : "P9223372036854775807D" },
218
+ {input : Duration {Months : 0 , Days : 0 , Seconds : math .MaxInt64 , Nanos : 0 }, output : "PT2562047788015215H30M7S" },
219
+ maxNanosCase ,
220
+ // single negative component
221
+ {input : Duration {Months : - 1 , Days : 0 , Seconds : 0 , Nanos : 0 }, output : "P-1M" },
222
+ {input : Duration {Months : 0 , Days : - 1 , Seconds : 0 , Nanos : 0 }, output : "P-1D" },
223
+ {input : Duration {Months : 0 , Days : 0 , Seconds : - 1 , Nanos : 0 }, output : "PT-1S" },
224
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 0 , Nanos : - 1 }, output : "PT-0.000000001S" },
225
+ {input : Duration {Months : math .MinInt64 , Days : 0 , Seconds : 0 , Nanos : 0 }, output : "P-768614336404564650Y-8M" },
226
+ {input : Duration {Months : 0 , Days : math .MinInt64 , Seconds : 0 , Nanos : 0 }, output : "P-9223372036854775808D" },
227
+ {input : Duration {Months : 0 , Days : 0 , Seconds : math .MinInt64 , Nanos : 0 }, output : "PT-2562047788015215H-30M-8S" },
228
+ minNanosCase ,
229
+ // only time components
230
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 1 , Nanos : 1 }, output : "PT1.000000001S" },
231
+ {input : Duration {Months : 0 , Days : 0 , Seconds : - 1 , Nanos : - 1 }, output : "PT-1.000000001S" },
232
+ // only date components
233
+ {input : Duration {Months : 1 , Days : 1 , Seconds : 0 , Nanos : 0 }, output : "P1M1D" },
234
+ {input : Duration {Months : - 1 , Days : - 1 , Seconds : 0 , Nanos : 0 }, output : "P-1M-1D" },
235
+ {input : Duration {Months : - 1 , Days : 1 , Seconds : 0 , Nanos : 0 }, output : "P-1M1D" },
236
+ {input : Duration {Months : 1 , Days : - 1 , Seconds : 0 , Nanos : 0 }, output : "P1M-1D" },
237
+ // all components
238
+ {input : Duration {Months : 1 , Days : 1 , Seconds : 1 , Nanos : 1 }, output : "P1M1DT1.000000001S" },
239
+ {input : Duration {Months : - 1 , Days : - 1 , Seconds : - 1 , Nanos : - 1 }, output : "P-1M-1DT-1.000000001S" },
240
+ // nanos don't need trailing 0 decimals
241
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 0 , Nanos : 1_000 }, output : "PT0.000001S" },
242
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 0 , Nanos : - 1_000 }, output : "PT-0.000001S" },
243
+ // nanos wrap into seconds
244
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 0 , Nanos : 2_100_000_000 }, output : "PT2.1S" },
245
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 0 , Nanos : - 2_100_000_000 }, output : "PT-2.1S" },
246
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 3 , Nanos : 2_100_000_000 }, output : "PT5.1S" },
247
+ {input : Duration {Months : 0 , Days : 0 , Seconds : - 3 , Nanos : - 2_100_000_000 }, output : "PT-5.1S" },
248
+ {input : Duration {Months : 0 , Days : 0 , Seconds : - 3 , Nanos : 2_100_000_000 }, output : "PT-0.9S" },
249
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 3 , Nanos : - 2_100_000_000 }, output : "PT0.9S" },
250
+ {input : Duration {Months : 0 , Days : 0 , Seconds : - 3 , Nanos : 2_100_000_000 }, output : "PT-0.9S" },
251
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 3 , Nanos : - 2_100_000_000 }, output : "PT0.9S" },
252
+ // seconds wrap into minutes and hours
253
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 60 , Nanos : 0 }, output : "PT1M" },
254
+ {input : Duration {Months : 0 , Days : 0 , Seconds : - 60 , Nanos : 0 }, output : "PT-1M" },
255
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 3600 , Nanos : 0 }, output : "PT1H" },
256
+ {input : Duration {Months : 0 , Days : 0 , Seconds : - 3600 , Nanos : 0 }, output : "PT-1H" },
257
+ // all max/min components
258
+ maxCase ,
259
+ minCase ,
260
+ }
261
+
262
+ if intIs64BitsWide {
263
+ testCases = append (testCases , []stringTestCase [Duration ]{
264
+ // nanos wrap into seconds and hours
265
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 7_203 , Nanos : 3_601_100_000_000 }, output : "PT3H4.1S" },
266
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 7_263 , Nanos : 3_721_100_000_000 }, output : "PT3H3M4.1S" },
267
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 7_203 , Nanos : - 3_601_100_000_000 }, output : "PT1H1.9S" },
268
+ {input : Duration {Months : 0 , Days : 0 , Seconds : 7_383 , Nanos : - 3_721_100_000_000 }, output : "PT1H1M1.9S" },
269
+ {input : Duration {Months : 0 , Days : 0 , Seconds : - 7_203 , Nanos : 3_601_100_000_000 }, output : "PT-1H-1.9S" },
270
+ {input : Duration {Months : 0 , Days : 0 , Seconds : - 7_323 , Nanos : 3_661_100_000_000 }, output : "PT-1H-1M-1.9S" },
271
+ }... )
171
272
}
172
273
173
274
for _ , testCase := range testCases {
@@ -178,3 +279,49 @@ func TestDurationSting(outer *testing.T) {
178
279
})
179
280
}
180
281
}
282
+
283
+ func TestSign (outer * testing.T ) {
284
+ outer .Parallel ()
285
+
286
+ type testCaseType struct {
287
+ name string
288
+ input int64
289
+ output int64
290
+ }
291
+
292
+ testCases := []testCaseType {
293
+ {name : "0" , input : 0 , output : 1 },
294
+ {name : "1" , input : 1 , output : 1 },
295
+ {name : "2" , input : 2 , output : 1 },
296
+ {name : "math.MaxInt64 / 2" , input : math .MaxInt64 / 2 , output : 1 },
297
+ {name : "math.MaxInt64 - 1" , input : math .MaxInt64 - 1 , output : 1 },
298
+ {name : "math.MaxInt64" , input : math .MaxInt64 , output : 1 },
299
+ {name : "-1" , input : - 1 , output : - 1 },
300
+ {name : "-2" , input : - 2 , output : - 1 },
301
+ {name : "math.MinInt64 / 2" , input : math .MinInt64 / 2 , output : - 1 },
302
+ {name : "math.MinInt64 + 1" , input : math .MinInt64 + 1 , output : - 1 },
303
+ {name : "math.MinInt64" , input : math .MinInt64 , output : - 1 },
304
+ }
305
+
306
+ for _ , testCase := range testCases {
307
+ testCase := testCase
308
+ outer .Run (testCase .name , func (inner * testing.T ) {
309
+ inner .Parallel ()
310
+ res := sign (testCase .input )
311
+ testutil .AssertDeepEquals (inner , res , testCase .output )
312
+ })
313
+
314
+ }
315
+ }
316
+
317
+ func BenchmarkSign (b * testing.B ) {
318
+ numbers := make ([]int64 , 0 , 1_000_000 )
319
+ for i := 0 ; i < 1_000_000 ; i ++ {
320
+ numbers = append (numbers , rand .Int64 ())
321
+ }
322
+ b .ResetTimer ()
323
+
324
+ for i := 0 ; i < b .N ; i ++ {
325
+ sign (numbers [i % 1_000_000 ])
326
+ }
327
+ }
0 commit comments