Skip to content

Commit

Permalink
Add property-based tests for discard utility functions
Browse files Browse the repository at this point in the history
This commit adds tests for `isParamsMatch` and `isReturnTypeBoolean`.
  • Loading branch information
BowTiedRadone committed Nov 7, 2024
1 parent 96130cf commit 7eabfaf
Show file tree
Hide file tree
Showing 2 changed files with 209 additions and 3 deletions.
205 changes: 205 additions & 0 deletions property.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@ import {
deriveTestContractName,
filterTestContractsInterfaces,
getTestsContractSource,
isParamsMatch,
isReturnTypeBoolean,
} from "./property";
import { getSimnetDeployerContractsInterfaces } from "./shared";
import { resolve } from "path";
import fs from "fs";
import fc from "fast-check";
import {
ContractInterfaceFunction,
ContractInterfaceFunctionAccess,
ContractInterfaceFunctionArg,
ContractInterfaceFunctionOutput,
} from "@hirosystems/clarinet-sdk/dist/esm/contractInterface";

describe("File stream operations", () => {
it("retrieves the test contract source", async () => {
Expand Down Expand Up @@ -165,3 +173,200 @@ describe("Simnet contracts operations", () => {
expect(actualTestContractsList).toEqual(expectedTestContractsList);
});
});

describe("Test discarding related operations", () => {
it("boolean output checker returns true when the function's output is boolean", () => {
fc.assert(
fc.property(
fc.record({
fnName: fc.string(),
access: fc.constant("read_only"),
args: fc.array(
fc.record({
name: fc.string(),
type: fc.constantFrom("int128", "uint128", "bool", "principal"),
})
),
outputs: fc.record({ type: fc.constant("bool") }),
}),
(r: {
fnName: string;
access: string;
args: { name: string; type: string }[];
outputs: { type: string };
}) => {
const discardFunctionInterface: ContractInterfaceFunction = {
name: r.fnName,
access: r.access as ContractInterfaceFunctionAccess,
args: r.args as ContractInterfaceFunctionArg[],
outputs: r.outputs as ContractInterfaceFunctionOutput,
};
const actual = isReturnTypeBoolean(discardFunctionInterface);
expect(actual).toBe(true);
}
)
);
});

it("boolean output checker returns false when the function's output is non-boolean", () => {
fc.assert(
fc.property(
fc.record({
fnName: fc.string(),
access: fc.constant("read_only"),
args: fc.array(
fc.record({
name: fc.string(),
type: fc.constantFrom("int128", "uint128", "bool", "principal"),
})
),
outputs: fc.record({
type: fc.constantFrom("int128", "uint128", "principal"),
}),
}),
(r: {
fnName: string;
access: string;
args: { name: string; type: string }[];
outputs: { type: string };
}) => {
const discardFunctionInterface: ContractInterfaceFunction = {
name: r.fnName,
access: r.access as ContractInterfaceFunctionAccess,
args: r.args as ContractInterfaceFunctionArg[],
outputs: r.outputs as ContractInterfaceFunctionOutput,
};
const actual = isReturnTypeBoolean(discardFunctionInterface);
expect(actual).toBe(false);
}
)
);
});

it("param matcher returns true when two functions have the same parameters", () => {
fc.assert(
fc.property(
fc.record({
fnName: fc.string(),
access: fc.constant("read_only"),
args: fc.array(
fc.record({
name: fc.string(),
type: fc.constantFrom("int128", "uint128", "bool", "principal"),
})
),
outputs: fc.record({ type: fc.constant("bool") }),
}),
(r: {
fnName: string;
access: string;
args: { name: string; type: string }[];
outputs: { type: string };
}) => {
const testFunctionInterface: ContractInterfaceFunction = {
name: r.fnName,
access: r.access as ContractInterfaceFunctionAccess,
args: r.args as ContractInterfaceFunctionArg[],
outputs: r.outputs as ContractInterfaceFunctionOutput,
};
const discardFunctionInterface: ContractInterfaceFunction = {
name: r.fnName,
access: r.access as ContractInterfaceFunctionAccess,
args: r.args as ContractInterfaceFunctionArg[],
outputs: r.outputs as ContractInterfaceFunctionOutput,
};
const actual = isParamsMatch(
testFunctionInterface,
discardFunctionInterface
);
expect(actual).toBe(true);
}
)
);
});

it("param matcher returns false when two functions have different parameters", () => {
fc.assert(
fc.property(
fc
.record({
testFn: fc.record({
fnName: fc.string(),
access: fc.constant("read_only"),
args: fc.array(
fc.record({
name: fc.string(),
type: fc.constantFrom(
"int128",
"uint128",
"bool",
"principal"
),
})
),
outputs: fc.record({ type: fc.constant("bool") }),
}),
discardFn: fc.record({
fnName: fc.string(),
access: fc.constant("read_only"),
args: fc.array(
fc.record({
name: fc.string(),
type: fc.constantFrom(
"int128",
"uint128",
"bool",
"principal"
),
})
),
outputs: fc.record({ type: fc.constant("bool") }),
}),
})
.filter(
(r) =>
JSON.stringify(
[...r.testFn.args].sort((a, b) => a.name.localeCompare(b.name))
) !==
JSON.stringify(
[...r.discardFn.args].sort((a, b) =>
a.name.localeCompare(b.name)
)
)
),
(r: {
testFn: {
fnName: string;
access: string;
args: { name: string; type: string }[];
outputs: { type: string };
};
discardFn: {
fnName: string;
access: string;
args: { name: string; type: string }[];
outputs: { type: string };
};
}) => {
const testFunctionInterface: ContractInterfaceFunction = {
name: r.testFn.fnName,
access: r.testFn.access as ContractInterfaceFunctionAccess,
args: r.testFn.args as ContractInterfaceFunctionArg[],
outputs: r.testFn.outputs as ContractInterfaceFunctionOutput,
};
const discardFunctionInterface: ContractInterfaceFunction = {
name: r.discardFn.fnName,
access: r.discardFn.access as ContractInterfaceFunctionAccess,
args: r.discardFn.args as ContractInterfaceFunctionArg[],
outputs: r.discardFn.outputs as ContractInterfaceFunctionOutput,
};
const actual = isParamsMatch(
testFunctionInterface,
discardFunctionInterface
);
expect(actual).toBe(false);
}
)
);
});
});
7 changes: 4 additions & 3 deletions property.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ const validateDiscardFunction = (
* @param discardFunction The discard function's interface.
* @returns A boolean indicating if the parameters match.
*/
const isParamsMatch = (
export const isParamsMatch = (
testFunction: ContractInterfaceFunction,
discardFunction: ContractInterfaceFunction
) => {
Expand All @@ -483,5 +483,6 @@ const isParamsMatch = (
* @param discardFunction The discard function's interface.
* @returns A boolean indicating if the return type is boolean.
*/
const isReturnTypeBoolean = (discardFunction: ContractInterfaceFunction) =>
discardFunction.outputs.type === "bool";
export const isReturnTypeBoolean = (
discardFunction: ContractInterfaceFunction
) => discardFunction.outputs.type === "bool";

0 comments on commit 7eabfaf

Please sign in to comment.