From 9b21a5b727b67647945024a27bfc2385f9224e10 Mon Sep 17 00:00:00 2001 From: Benjamin DeMann Date: Mon, 23 Oct 2023 14:07:20 -0600 Subject: [PATCH 1/3] add test support for NaNs and infinities --- examples/primitive_types/src/index.did | 60 +++++----- examples/primitive_types/test/tests.ts | 130 +++++++++++++++++----- property_tests/are_equal.ts | 7 ++ property_tests/tests/float32/test/test.ts | 13 ++- property_tests/tests/float64/test/test.ts | 13 ++- 5 files changed, 162 insertions(+), 61 deletions(-) create mode 100644 property_tests/are_equal.ts diff --git a/examples/primitive_types/src/index.did b/examples/primitive_types/src/index.did index 4ed7743ac6..a08b2ea1ef 100644 --- a/examples/primitive_types/src/index.did +++ b/examples/primitive_types/src/index.did @@ -1,42 +1,42 @@ service: () -> { + getBool: () -> (bool) query; + getEmpty: () -> (empty) query; + getFloat32: () -> (float32) query; + getFloat64: () -> (float64) query; + getInt: () -> (int) query; + getInt16: () -> (int16) query; + getInt32: () -> (int32) query; + getInt64: () -> (int64) query; + getInt8: () -> (int8) query; + getNat: () -> (nat) query; + getNat16: () -> (nat16) query; + getNat32: () -> (nat32) query; + getNat64: () -> (nat64) query; + getNat8: () -> (nat8) query; + getNull: () -> (null) query; + getNumber: () -> (float64) query; + getPrincipal: () -> (principal) query; + getReserved: () -> (reserved) query; getString: () -> (text) query; - printString: (text) -> (text) query; getText: () -> (text) query; - printText: (text) -> (text) query; - getNumber: () -> (float64) query; - printNumber: (float64) -> (float64) query; - getInt: () -> (int) query; + printBool: (bool) -> (bool) query; + printEmpty: (empty) -> (empty) query; + printFloat32: (float32) -> (float32) query; + printFloat64: (float64) -> (float64) query; printInt: (int) -> (int) query; - getInt64: () -> (int64) query; - printInt64: (int64) -> (int64) query; - getInt32: () -> (int32) query; - printInt32: (int32) -> (int32) query; - getInt16: () -> (int16) query; printInt16: (int16) -> (int16) query; - getInt8: () -> (int8) query; + printInt32: (int32) -> (int32) query; + printInt64: (int64) -> (int64) query; printInt8: (int8) -> (int8) query; - getNat: () -> (nat) query; printNat: (nat) -> (nat) query; - getNat64: () -> (nat64) query; - printNat64: (nat64) -> (nat64) query; - getNat32: () -> (nat32) query; - printNat32: (nat32) -> (nat32) query; - getNat16: () -> (nat16) query; printNat16: (nat16) -> (nat16) query; - getNat8: () -> (nat8) query; + printNat32: (nat32) -> (nat32) query; + printNat64: (nat64) -> (nat64) query; printNat8: (nat8) -> (nat8) query; - getFloat64: () -> (float64) query; - printFloat64: (float64) -> (float64) query; - getFloat32: () -> (float32) query; - printFloat32: (float32) -> (float32) query; - getBool: () -> (bool) query; - printBool: (bool) -> (bool) query; - getPrincipal: () -> (principal) query; - printPrincipal: (principal) -> (principal) query; - getNull: () -> (null) query; printNull: (null) -> (null) query; - getReserved: () -> (reserved) query; + printNumber: (float64) -> (float64) query; + printPrincipal: (principal) -> (principal) query; printReserved: (reserved) -> (reserved) query; - getEmpty: () -> (empty) query; - printEmpty: (empty) -> (empty) query; + printString: (text) -> (text) query; + printText: (text) -> (text) query; } diff --git a/examples/primitive_types/test/tests.ts b/examples/primitive_types/test/tests.ts index bdf756f240..c6c15fcc7f 100644 --- a/examples/primitive_types/test/tests.ts +++ b/examples/primitive_types/test/tests.ts @@ -20,9 +20,8 @@ export function getTests( { name: 'printString', test: async () => { - const result = await primitiveTypesCanister.printString( - 'string' - ); + const result = + await primitiveTypesCanister.printString('string'); return { Ok: result === 'string' @@ -62,9 +61,8 @@ export function getTests( { name: 'printNumber', test: async () => { - const result = await primitiveTypesCanister.printNumber( - 90071992547409.05 - ); + const result = + await primitiveTypesCanister.printNumber(90071992547409.05); return { Ok: result.toString() === '90071992547409.05' @@ -86,9 +84,10 @@ export function getTests( { name: 'printInt', test: async () => { - const result = await primitiveTypesCanister.printInt( - 170_141_183_460_469_231_731_687_303_715_884_105_727n - ); + const result = + await primitiveTypesCanister.printInt( + 170_141_183_460_469_231_731_687_303_715_884_105_727n + ); return { Ok: @@ -110,9 +109,10 @@ export function getTests( { name: 'printInt64', test: async () => { - const result = await primitiveTypesCanister.printInt( - 9_223_372_036_854_775_807n - ); + const result = + await primitiveTypesCanister.printInt( + 9_223_372_036_854_775_807n + ); return { Ok: result === 9_223_372_036_854_775_807n @@ -132,9 +132,8 @@ export function getTests( { name: 'printInt32', test: async () => { - const result = await primitiveTypesCanister.printInt32( - 2_147_483_647 - ); + const result = + await primitiveTypesCanister.printInt32(2_147_483_647); return { Ok: result === 2_147_483_647 @@ -196,9 +195,10 @@ export function getTests( { name: 'printNat', test: async () => { - const result = await primitiveTypesCanister.printNat( - 340_282_366_920_938_463_463_374_607_431_768_211_455n - ); + const result = + await primitiveTypesCanister.printNat( + 340_282_366_920_938_463_463_374_607_431_768_211_455n + ); return { Ok: @@ -220,9 +220,10 @@ export function getTests( { name: 'printNat64', test: async () => { - const result = await primitiveTypesCanister.printNat64( - 18_446_744_073_709_551_615n - ); + const result = + await primitiveTypesCanister.printNat64( + 18_446_744_073_709_551_615n + ); return { Ok: result === 18_446_744_073_709_551_615n @@ -242,9 +243,8 @@ export function getTests( { name: 'printNat32', test: async () => { - const result = await primitiveTypesCanister.printNat32( - 4_294_967_295 - ); + const result = + await primitiveTypesCanister.printNat32(4_294_967_295); return { Ok: result === 4_294_967_295 @@ -303,13 +303,50 @@ export function getTests( }, { name: 'printFloat64', + test: async () => { + const result = + await primitiveTypesCanister.printFloat64( + 2.718281828459045 + ); + + return { + Ok: result.toString() === '2.718281828459045' + }; + } + }, + { + name: 'print Float64.Nan', test: async () => { const result = await primitiveTypesCanister.printFloat64( - 2.718281828459045 + Number.NaN ); return { - Ok: result.toString() === '2.718281828459045' + Ok: Number.isNaN(result) + }; + } + }, + { + name: 'print positive Float64.Infinity', + test: async () => { + const result = await primitiveTypesCanister.printFloat64( + Number.POSITIVE_INFINITY + ); + + return { + Ok: !Number.isFinite(result) + }; + } + }, + { + name: 'print negative Float64.Infinity', + test: async () => { + const result = await primitiveTypesCanister.printFloat64( + Number.NEGATIVE_INFINITY + ); + + return { + Ok: !Number.isFinite(result) }; } }, @@ -327,9 +364,8 @@ export function getTests( { name: 'printFloat32', test: async () => { - const result = await primitiveTypesCanister.printFloat32( - 3.1415927 - ); + const result = + await primitiveTypesCanister.printFloat32(3.1415927); return { // Ok: result.toString() === '3.1415927' // TODO on the command line this is returned @@ -337,6 +373,42 @@ export function getTests( }; } }, + { + name: 'print Float32.Nan', + test: async () => { + const result = await primitiveTypesCanister.printFloat32( + Number.NaN + ); + + return { + Ok: Number.isNaN(result) + }; + } + }, + { + name: 'print positive Float32.Infinity', + test: async () => { + const result = await primitiveTypesCanister.printFloat32( + Number.POSITIVE_INFINITY + ); + + return { + Ok: !Number.isFinite(result) + }; + } + }, + { + name: 'print negative Float32.Infinity', + test: async () => { + const result = await primitiveTypesCanister.printFloat32( + Number.NEGATIVE_INFINITY + ); + + return { + Ok: !Number.isFinite(result) + }; + } + }, { name: 'getBool', test: async () => { diff --git a/property_tests/are_equal.ts b/property_tests/are_equal.ts new file mode 100644 index 0000000000..40f8791a3d --- /dev/null +++ b/property_tests/are_equal.ts @@ -0,0 +1,7 @@ +export function areFloatsEqual(paramName: string, paramValue: number) { + if (Number.isNaN(paramValue)) { + return `(Number.isNaN(${paramName}) && Number.isNaN(${paramValue}))`; + } else { + return `${paramName} === ${paramValue}`; + } +} diff --git a/property_tests/tests/float32/test/test.ts b/property_tests/tests/float32/test/test.ts index ef97e59f7f..eebcf767f7 100644 --- a/property_tests/tests/float32/test/test.ts +++ b/property_tests/tests/float32/test/test.ts @@ -4,6 +4,7 @@ import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_ import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; import { runPropTests } from '../../..'; import { Float32Arb } from '../../../arbitraries/candid/primitive/floats/float32_arb'; +import { areFloatsEqual } from '../../../are_equal'; const Float32TestArb = fc .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(Float32Arb)) @@ -25,7 +26,11 @@ const Float32TestArb = fc const paramsCorrectlyOrdered = paramNames .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}) throw new Error('${paramName} is incorrectly ordered')`; + let areFloat32sEqual = areFloatsEqual( + paramName, + paramSamples[index] + ); + return `if (!${areFloat32sEqual}) throw new Error('${paramName} is incorrectly ordered')`; }) .join('\n'); @@ -50,6 +55,12 @@ const Float32TestArb = fc const result = await actor[functionName](...float32s); + if (Number.isNaN(expectedResult)) { + return { + Ok: Number.isNaN(result) + }; + } + return { Ok: result === expectedResult }; diff --git a/property_tests/tests/float64/test/test.ts b/property_tests/tests/float64/test/test.ts index 347c50409b..8e253b59a3 100644 --- a/property_tests/tests/float64/test/test.ts +++ b/property_tests/tests/float64/test/test.ts @@ -4,6 +4,7 @@ import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_ import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; import { runPropTests } from '../../..'; import { Float64ArrayArb } from '../../../arbitraries/candid/primitive/floats/float64_arb'; +import { areFloatsEqual } from '../../../are_equal'; const Float64TestArb = fc .tuple(createUniquePrimitiveArb(JsFunctionNameArb), Float64ArrayArb) @@ -33,7 +34,11 @@ const Float64TestArb = fc const paramsCorrectlyOrdered = paramNames .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}) throw new Error('${paramName} is incorrectly ordered')`; + let areFloat64sEqual = areFloatsEqual( + paramName, + paramSamples[index] + ); + return `if (!${areFloat64sEqual}) throw new Error('${paramName} is incorrectly ordered')`; }) .join('\n'); @@ -58,6 +63,12 @@ const Float64TestArb = fc const result = await actor[functionName](...float64s); + if (Number.isNaN(expectedResult)) { + return { + Ok: Number.isNaN(result) + }; + } + return { Ok: result === expectedResult }; From 7f9b58709da8dbf8b034c556d85d82f5d98bed2d Mon Sep 17 00:00:00 2001 From: Benjamin DeMann Date: Mon, 23 Oct 2023 14:09:18 -0600 Subject: [PATCH 2/3] fixup From 08d689f898a2013433ed645eb1f0afb7438579b7 Mon Sep 17 00:00:00 2001 From: Benjamin DeMann Date: Mon, 23 Oct 2023 14:19:14 -0600 Subject: [PATCH 3/3] pr fixes --- property_tests/tests/float32/test/test.ts | 2 +- property_tests/tests/float64/test/test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/property_tests/tests/float32/test/test.ts b/property_tests/tests/float32/test/test.ts index eebcf767f7..f0f7ac1420 100644 --- a/property_tests/tests/float32/test/test.ts +++ b/property_tests/tests/float32/test/test.ts @@ -26,7 +26,7 @@ const Float32TestArb = fc const paramsCorrectlyOrdered = paramNames .map((paramName, index) => { - let areFloat32sEqual = areFloatsEqual( + const areFloat32sEqual = areFloatsEqual( paramName, paramSamples[index] ); diff --git a/property_tests/tests/float64/test/test.ts b/property_tests/tests/float64/test/test.ts index 8e253b59a3..0a7d4af7e4 100644 --- a/property_tests/tests/float64/test/test.ts +++ b/property_tests/tests/float64/test/test.ts @@ -34,7 +34,7 @@ const Float64TestArb = fc const paramsCorrectlyOrdered = paramNames .map((paramName, index) => { - let areFloat64sEqual = areFloatsEqual( + const areFloat64sEqual = areFloatsEqual( paramName, paramSamples[index] );