Skip to content

Commit b8129ab

Browse files
authored
Add property-base tests to Integer (#998)
1 parent 565310f commit b8129ab

File tree

2 files changed

+222
-79
lines changed

2 files changed

+222
-79
lines changed

packages/core/test/integer.test.ts

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import Integer, {
2525
inSafeRange
2626
} from '../src/integer'
2727
import { newError } from '../src/error'
28+
import fc from 'fast-check'
2829

2930
describe('Integer', () => {
3031
forEachToNumberOrInfinityScenarios(({ input, expectedOutput }) =>
@@ -355,6 +356,134 @@ describe('Integer', () => {
355356
Integer.MAX_SAFE_VALUE.toString()
356357
)
357358
})
359+
360+
test('int(BigInt) should be reversed by Integer.toBigInt', () => {
361+
fc.assert(
362+
fc.property(
363+
fc.bigInt({ max: Integer.MAX_SAFE_VALUE.toBigInt(), min: Integer.MIN_SAFE_VALUE.toBigInt() }),
364+
bigint => bigint === int(bigint).toBigInt()
365+
)
366+
)
367+
})
368+
369+
test('int.toString() should match Integer.toString()', () => {
370+
fc.assert(fc.property(fc.integer(), i => i.toString() === int(i).toString()))
371+
})
372+
373+
test('int(string) should match int(Integer)', () => {
374+
fc.assert(fc.property(fc.integer(), i => int(i).equals(int(i.toString()))))
375+
})
376+
377+
test('int(number) should be reversed by Integer.toNumber', () => {
378+
fc.assert(fc.property(fc.integer(), num => num === int(num).toNumber()))
379+
})
380+
381+
test('int(Integer) should be equal Integer', () => {
382+
fc.assert(fc.property(arbitraryInteger(), integer => integer === int(integer)))
383+
})
384+
385+
test('Integer.add should be Commutative', () => {
386+
fc.assert(fc.property(arbitraryInteger(), arbitraryInteger(),
387+
(a, b) => a.add(b).equals(b.add(a))))
388+
})
389+
390+
test('Integer.multiply should be Commutative', () => {
391+
fc.assert(fc.property(arbitraryInteger(), arbitraryInteger(),
392+
(a, b) => a.multiply(b).equals(b.multiply(a))))
393+
})
394+
395+
test('Integer.add should be Associative', () => {
396+
fc.assert(fc.property(arbitraryInteger(), arbitraryInteger(), arbitraryInteger(),
397+
(a, b, c) => a.add(b.add(c)).equals(a.add(b).add(c))))
398+
})
399+
400+
test('Integer.multiply should be Associative', () => {
401+
fc.assert(fc.property(arbitraryInteger(), arbitraryInteger(), arbitraryInteger(),
402+
(a, b, c) => a.multiply(b.multiply(c)).equals(a.multiply(b).multiply(c))))
403+
})
404+
405+
test('Integer.add should be Distributive', () => {
406+
fc.assert(fc.property(arbitraryInteger(), arbitraryInteger(), arbitraryInteger(),
407+
(a, b, c) => a.multiply(b.add(c)).equals(a.multiply(b).add(a.multiply(c)))))
408+
})
409+
410+
test('Integer.subtract should be Distributive', () => {
411+
fc.assert(fc.property(arbitraryInteger(), arbitraryInteger(), arbitraryInteger(),
412+
(a, b, c) => a.multiply(b.subtract(c)).equals(a.multiply(b).subtract(a.multiply(c)))))
413+
})
414+
415+
test('Integer.add should have 0 as identity', () => {
416+
fc.assert(fc.property(arbitraryInteger(), (a) => a.add(0).equals(a)))
417+
})
418+
419+
test('Integer.subtract should have 0 as identity', () => {
420+
fc.assert(fc.property(arbitraryInteger(), (a) => a.subtract(0).equals(a)))
421+
})
422+
423+
test('Integer.multiply should have 0 as identity', () => {
424+
fc.assert(fc.property(arbitraryInteger(), (a) => a.multiply(1).equals(a)))
425+
})
426+
427+
test('Integer.div should have 0 as identity', () => {
428+
fc.assert(fc.property(arbitraryInteger(), (a) => a.div(1).equals(a)))
429+
})
430+
431+
test('Integer.equals should return true if a - b is ZERO', () => {
432+
fc.assert(fc.property(arbitraryInteger(), arbitraryInteger(),
433+
(a, b) => a.subtract(b).isZero() ? a.equals(b) : !a.equals(b)))
434+
})
435+
436+
describe('with same sign', () => {
437+
test('Integer.greaterThan should return true if a - b is positive', () => {
438+
fc.assert(fc.property(
439+
arbitrarySameSignIntegers(),
440+
({ a, b }) => a.subtract(b).isPositive() ? a.greaterThan(b) : !a.greaterThan(b)))
441+
})
442+
443+
test('Integer.greaterThanOrEqual should return true if a - b is positive or ZERO', () => {
444+
fc.assert(fc.property(
445+
arbitrarySameSignIntegers(),
446+
({ a, b }) => a.subtract(b).isPositive() || a.subtract(b).isZero() ? a.greaterThanOrEqual(b) : !a.greaterThanOrEqual(b)))
447+
})
448+
449+
test('Integer.lessThanOrEqual should return true if a - b is ZERO or negative', () => {
450+
fc.assert(fc.property(
451+
arbitrarySameSignIntegers(),
452+
({ a, b }) => a.subtract(b).isNegative() || a.subtract(b).isZero() ? a.lessThanOrEqual(b) : !a.lessThanOrEqual(b)))
453+
})
454+
455+
test('Integer.lessThanOrEqual should return true if a - b is ZERO or negative', () => {
456+
fc.assert(fc.property(
457+
arbitrarySameSignIntegers(),
458+
({ a, b }) => a.subtract(b).isNegative() ? a.lessThan(b) : !a.lessThan(b)))
459+
})
460+
})
461+
462+
describe('with different sign', () => {
463+
test('Integer.greaterThan should return true if a is positive', () => {
464+
fc.assert(fc.property(
465+
arbitraryDiffSignIntegers(),
466+
({ a, b }) => a.isPositive() ? a.greaterThan(b) : !a.greaterThan(b)))
467+
})
468+
469+
test('Integer.greaterThanOrEqual should return true if a is positive or ZERO', () => {
470+
fc.assert(fc.property(
471+
arbitraryDiffSignIntegers(),
472+
({ a, b }) => a.isPositive() || a.isZero() ? a.greaterThanOrEqual(b) : !a.greaterThanOrEqual(b)))
473+
})
474+
475+
test('Integer.lessThanOrEqual should return true if a is ZERO or negative', () => {
476+
fc.assert(fc.property(
477+
arbitraryDiffSignIntegers(),
478+
({ a, b }) => a.isNegative() || a.isZero() ? a.lessThanOrEqual(b) : !a.lessThanOrEqual(b)))
479+
})
480+
481+
test('Integer.lessThanOrEqual should return true if a is ZERO or negative', () => {
482+
fc.assert(fc.property(
483+
arbitraryDiffSignIntegers(),
484+
({ a, b }) => a.isNegative() ? a.lessThan(b) : !a.lessThan(b)))
485+
})
486+
})
358487
})
359488

360489
function forEachToNumberOrInfinityScenarios (
@@ -1188,6 +1317,20 @@ function wellFormedNumbersAndRadix (): Array<[string, number]> {
11881317
]
11891318
}
11901319

1320+
function arbitraryInteger (): fc.Arbitrary<Integer> {
1321+
return fc.record({ low: fc.integer(), high: fc.integer() })
1322+
.map(({ low, high }) => new Integer(low, high))
1323+
}
1324+
1325+
function arbitrarySameSignIntegers (): fc.Arbitrary<{ a: Integer, b: Integer }> {
1326+
return fc.record({ a: arbitraryInteger(), b: arbitraryInteger() })
1327+
.map(({ a, b }) => a.isPositive() === b.isPositive() ? { a, b } : { a, b: b.negate() })
1328+
}
1329+
1330+
function arbitraryDiffSignIntegers (): fc.Arbitrary<{ a: Integer, b: Integer }> {
1331+
return fc.record({ a: arbitraryInteger(), b: arbitraryInteger() })
1332+
.map(({ a, b }) => a.isPositive() === b.isPositive() ? { a, b: b.negate() } : { a, b })
1333+
}
11911334
interface AssertionPair<I, O> {
11921335
input: I
11931336
expectedOutput: O

0 commit comments

Comments
 (0)