diff --git a/packages/ERTP/package.json b/packages/ERTP/package.json index 19ea04bd1b6..df87168d96a 100644 --- a/packages/ERTP/package.json +++ b/packages/ERTP/package.json @@ -48,11 +48,11 @@ "@endo/far": "^0.2.18", "@endo/marshal": "^0.8.5", "@endo/nat": "^4.1.27", - "@endo/promise-kit": "^0.2.56" + "@endo/promise-kit": "^0.2.56", + "@fast-check/ava": "^1.1.3" }, "devDependencies": { "@endo/bundle-source": "^2.5.1", - "@fast-check/ava": "^1.1.3", "ava": "^5.2.0", "tsd": "^0.28.1" }, @@ -67,7 +67,8 @@ "# fast-check unsupported", "test/unitTests/test-amountProperties.js", "test/unitTests/test-inputValidation.js", - "test/unitTests/test-issuerObj.js" + "test/unitTests/test-issuerObj.js", + "test/unitTests/test-amount-key-arith.js" ] }, "ava": { diff --git a/packages/ERTP/test/unitTests/mathHelpers/test-copyBagMathHelpers.js b/packages/ERTP/test/unitTests/mathHelpers/test-copyBagMathHelpers.js index 64e0ed9bd85..6ebaf161f7a 100644 --- a/packages/ERTP/test/unitTests/mathHelpers/test-copyBagMathHelpers.js +++ b/packages/ERTP/test/unitTests/mathHelpers/test-copyBagMathHelpers.js @@ -6,7 +6,7 @@ import { } from '@agoric/store'; import { AmountMath as m, AssetKind } from '../../../src/index.js'; -import { mockBrand } from './mockBrand.js'; +import { mockBrand } from '../../../tools/mockBrand.js'; // The "unit tests" for MathHelpers actually make the calls through // AmountMath so that we can test that any duplication is handled diff --git a/packages/ERTP/test/unitTests/mathHelpers/test-copySetMathHelpers.js b/packages/ERTP/test/unitTests/mathHelpers/test-copySetMathHelpers.js index 7a22eb2f6f7..f809ce98f3c 100644 --- a/packages/ERTP/test/unitTests/mathHelpers/test-copySetMathHelpers.js +++ b/packages/ERTP/test/unitTests/mathHelpers/test-copySetMathHelpers.js @@ -2,7 +2,7 @@ import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; import { getCopySetKeys, makeCopySet } from '@agoric/store'; import { AmountMath as m, AssetKind } from '../../../src/index.js'; -import { mockBrand } from './mockBrand.js'; +import { mockBrand } from '../../../tools/mockBrand.js'; // The "unit tests" for MathHelpers actually make the calls through // AmountMath so that we can test that any duplication is handled diff --git a/packages/ERTP/test/unitTests/mathHelpers/test-natMathHelpers.js b/packages/ERTP/test/unitTests/mathHelpers/test-natMathHelpers.js index 102af4db0de..778a3d555bb 100644 --- a/packages/ERTP/test/unitTests/mathHelpers/test-natMathHelpers.js +++ b/packages/ERTP/test/unitTests/mathHelpers/test-natMathHelpers.js @@ -4,7 +4,7 @@ import { M } from '@agoric/store'; import { Far } from '@endo/marshal'; import { AmountMath as m, AssetKind } from '../../../src/index.js'; -import { mockBrand } from './mockBrand.js'; +import { mockBrand } from '../../../tools/mockBrand.js'; // The "unit tests" for MathHelpers actually make the calls through // AmountMath so that we can test that any duplication is handled diff --git a/packages/ERTP/test/unitTests/mathHelpers/test-setMathHelpers.js b/packages/ERTP/test/unitTests/mathHelpers/test-setMathHelpers.js index 7d972568bc7..52dfe25c547 100644 --- a/packages/ERTP/test/unitTests/mathHelpers/test-setMathHelpers.js +++ b/packages/ERTP/test/unitTests/mathHelpers/test-setMathHelpers.js @@ -4,7 +4,7 @@ import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; import { Far } from '@endo/marshal'; import { AmountMath as m, AssetKind } from '../../../src/index.js'; -import { mockBrand } from './mockBrand.js'; +import { mockBrand } from '../../../tools/mockBrand.js'; // The "unit tests" for MathHelpers actually make the calls through // AmountMath so that we can test that any duplication is handled diff --git a/packages/ERTP/test/unitTests/mathHelpers/test-strSetMathHelpers.js b/packages/ERTP/test/unitTests/mathHelpers/test-strSetMathHelpers.js index b268a5d0644..3b3c91a5566 100644 --- a/packages/ERTP/test/unitTests/mathHelpers/test-strSetMathHelpers.js +++ b/packages/ERTP/test/unitTests/mathHelpers/test-strSetMathHelpers.js @@ -2,7 +2,7 @@ import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; import { AmountMath as m, AssetKind } from '../../../src/index.js'; -import { mockBrand } from './mockBrand.js'; +import { mockBrand } from '../../../tools/mockBrand.js'; // The "unit tests" for MathHelpers actually make the calls through // AmountMath so that we can test that any duplication is handled diff --git a/packages/ERTP/test/unitTests/test-amount-key-arith.js b/packages/ERTP/test/unitTests/test-amount-key-arith.js new file mode 100644 index 00000000000..f0e086d55fc --- /dev/null +++ b/packages/ERTP/test/unitTests/test-amount-key-arith.js @@ -0,0 +1,22 @@ +import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; +import { fc } from '@fast-check/ava'; +import { keyEQ, keyGTE } from '@agoric/store'; + +import { AmountMath as m } from '../../src/index.js'; +import { arbAmount } from '../../tools/arb-amount.js'; + +test('amount equality iff key equality', async t => { + await fc.assert( + fc.property(fc.record({ x: arbAmount, y: arbAmount }), ({ x, y }) => { + return t.true(m.isEqual(x, y) === keyEQ(x, y)); + }), + ); +}); + +test('amount >= iff key >=', async t => { + await fc.assert( + fc.property(fc.record({ x: arbAmount, y: arbAmount }), ({ x, y }) => { + return t.true(m.isGTE(x, y) === keyGTE(x, y)); + }), + ); +}); diff --git a/packages/ERTP/test/unitTests/test-amountProperties.js b/packages/ERTP/test/unitTests/test-amountProperties.js index 6bfa2d71878..ba167c7b046 100644 --- a/packages/ERTP/test/unitTests/test-amountProperties.js +++ b/packages/ERTP/test/unitTests/test-amountProperties.js @@ -1,29 +1,9 @@ import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; -import { makeCopyBag } from '@agoric/store'; import { fc } from '@fast-check/ava'; import { AmountMath as m, AssetKind } from '../../src/index.js'; -import { mockBrand } from './mathHelpers/mockBrand.js'; - -// Perhaps makeCopyBag should coalesce duplicate labels, but for now, it does -// not. -const distinctLabels = pairs => - new Set(pairs.map(([label, _qty]) => label)).size === pairs.length; -const positiveCounts = pairs => - pairs.filter(([_l, qty]) => qty > 0n).length === pairs.length; -const arbBagContents = fc - .nat(7) - .chain(size => - fc.array( - fc.tuple(fc.string(), fc.bigUint({ max: 1_000_000_000_000_000n })), - { minLength: size, maxLength: size }, - ), - ) - .filter(pairs => distinctLabels(pairs) && positiveCounts(pairs)); - -const arbAmount = arbBagContents.map(contents => - m.make(mockBrand, harden(makeCopyBag(contents))), -); +import { mockBrand } from '../../tools/mockBrand.js'; +import { arbAmount } from '../../tools/arb-amount.js'; // Note: we write P => Q as !P || Q since JS has no logical => operator const implies = (p, q) => !p || q; diff --git a/packages/ERTP/tools/arb-amount.js b/packages/ERTP/tools/arb-amount.js new file mode 100644 index 00000000000..154211aca46 --- /dev/null +++ b/packages/ERTP/tools/arb-amount.js @@ -0,0 +1,26 @@ +import { makeCopyBag } from '@agoric/store'; +import { fc } from '@fast-check/ava'; + +import { AmountMath as m } from '../src/index.js'; +import { mockBrand } from './mockBrand.js'; + +// Perhaps makeCopyBag should coalesce duplicate labels, but for now, it does +// not. +const distinctLabels = pairs => + new Set(pairs.map(([label, _qty]) => label)).size === pairs.length; +const positiveCounts = pairs => + pairs.filter(([_l, qty]) => qty > 0n).length === pairs.length; +const arbBagContents = fc + .nat(7) + .chain(size => + fc.array( + fc.tuple(fc.string(), fc.bigUint({ max: 1_000_000_000_000_000n })), + { minLength: size, maxLength: size }, + ), + ) + .filter(pairs => distinctLabels(pairs) && positiveCounts(pairs)); + +// TODO: should include many non-bag amounts too +export const arbAmount = arbBagContents.map(contents => + m.make(mockBrand, harden(makeCopyBag(contents))), +); diff --git a/packages/ERTP/test/unitTests/mathHelpers/mockBrand.js b/packages/ERTP/tools/mockBrand.js similarity index 74% rename from packages/ERTP/test/unitTests/mathHelpers/mockBrand.js rename to packages/ERTP/tools/mockBrand.js index 3b0dd05597f..e7424e29a80 100644 --- a/packages/ERTP/test/unitTests/mathHelpers/mockBrand.js +++ b/packages/ERTP/tools/mockBrand.js @@ -1,10 +1,10 @@ import { Far } from '@endo/marshal'; -import { AssetKind } from '../../../src/index.js'; +import { AssetKind } from '../src/index.js'; /** @type {Brand} */ export const mockBrand = Far('brand', { // eslint-disable-next-line no-unused-vars - isMyIssuer: async allegedIssuer => false, + isMyIssuer: async _allegedIssuer => false, getAllegedName: () => 'mock', getAmountShape: () => {}, getDisplayInfo: () => ({