-
Notifications
You must be signed in to change notification settings - Fork 123
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Map property tests + map int limit tests (#1343)
- Loading branch information
1 parent
7fbe9a2
commit 5aaa18d
Showing
11 changed files
with
1,174 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import { run } from "../../../node"; | ||
import { keyTypes, valTypes } from "./map-properties-key-value-types"; | ||
import { mkdir, writeFile } from "fs/promises"; | ||
import path from "path"; | ||
import { exit } from "node:process"; | ||
import { | ||
descriptionToString, | ||
intKeyFormats, | ||
intValFormats, | ||
maxInt, | ||
minInt, | ||
} from "./map-int-limits-key-value-types"; | ||
import { readFile } from "node:fs/promises"; | ||
|
||
type TestKind = "map-properties" | "map-int-limits"; | ||
|
||
// template with substitutions that make it an instance after application | ||
type TemplateWithSubst = { | ||
template: string; | ||
subst: Map<string, string>; | ||
}; | ||
|
||
const pwd = (fileName: string): string => path.join(__dirname, fileName); | ||
|
||
const testDirectory = (kind: TestKind, testName: string): string => | ||
pwd(`./build/${kind}_${testName}`.replaceAll(" ", "-")); | ||
|
||
const testContractFileName = "test.tact"; | ||
|
||
const applySubstitutions = ({ template, subst }: TemplateWithSubst): string => { | ||
return Array.from(subst).reduce( | ||
(partialTemplate, [placeholder, concreteValue]) => { | ||
return partialTemplate.replaceAll(placeholder, concreteValue); | ||
}, | ||
template, | ||
); | ||
}; | ||
|
||
const instantiateContractAndSpecTemplates = async ( | ||
testKind: TestKind, | ||
testName: string, | ||
templateTact: TemplateWithSubst, | ||
templateSpec: TemplateWithSubst, | ||
): Promise<string> => { | ||
const testDir = testDirectory(testKind, testName); | ||
const tactSourceCode = applySubstitutions(templateTact); | ||
const specSourceCode = applySubstitutions(templateSpec); | ||
await mkdir(testDir, { recursive: true }); | ||
const tactFilePath = path.join(testDir, testContractFileName); | ||
await writeFile(tactFilePath, tactSourceCode); | ||
const specFilePath = path.join(testDir, `${testKind}.spec.ts`); | ||
await writeFile(specFilePath, specSourceCode); | ||
return tactFilePath; | ||
}; | ||
|
||
const compileAndExitOnError = async (tactFilePath: string) => { | ||
const compilationResult = await run({ | ||
fileName: tactFilePath, | ||
suppressLog: true, | ||
}); | ||
if (!compilationResult.ok) { | ||
console.error(compilationResult.error); | ||
exit(1); | ||
} | ||
}; | ||
|
||
const generatePropertyTests = async () => { | ||
const templateTactSourceCodeProperties: string = ( | ||
await readFile(pwd("map-properties.tact.template")) | ||
).toString(); | ||
const templateSpecSourceCodeProperties: string = ( | ||
await readFile(pwd("map-properties.spec.ts.template")) | ||
).toString(); | ||
for (const key of keyTypes) { | ||
for (const val of valTypes) { | ||
const testName = `${key.type}_${val.type}`; | ||
const tactFilePath = await instantiateContractAndSpecTemplates( | ||
"map-properties", | ||
testName, | ||
{ | ||
template: templateTactSourceCodeProperties, | ||
subst: new Map([ | ||
["KEY_TYPE_PLACEHOLDER", key.type], | ||
["VAL_TYPE_PLACEHOLDER", val.type], | ||
]), | ||
}, | ||
{ | ||
template: templateSpecSourceCodeProperties, | ||
subst: new Map([ | ||
["KEY_1_PLACEHOLDER", key._1], | ||
["KEY_2_PLACEHOLDER", key._2], | ||
["VAL_1_PLACEHOLDER", val._1], | ||
["VAL_2_PLACEHOLDER", val._2], | ||
]), | ||
}, | ||
); | ||
await compileAndExitOnError(tactFilePath); | ||
} | ||
} | ||
}; | ||
|
||
const generateIntLimitsTests = async () => { | ||
const templateTactSourceCodeLimits: string = ( | ||
await readFile(pwd("map-int-limits.tact.template")) | ||
).toString(); | ||
const templateSpecSourceCodeLimits: string = ( | ||
await readFile(pwd("map-int-limits.spec.ts.template")) | ||
).toString(); | ||
for (const key of intKeyFormats) { | ||
for (const val of intValFormats) { | ||
const testName = `${descriptionToString(key)}_${descriptionToString(val)}`; | ||
const tactFilePath = await instantiateContractAndSpecTemplates( | ||
"map-int-limits", | ||
testName, | ||
{ | ||
template: templateTactSourceCodeLimits, | ||
subst: new Map([ | ||
["KEY_FORMAT_PLACEHOLDER", descriptionToString(key)], | ||
["VAL_FORMAT_PLACEHOLDER", descriptionToString(val)], | ||
["KEY_MIN_PLACEHOLDER", minInt(key).toString()], | ||
["KEY_MAX_PLACEHOLDER", maxInt(key).toString()], | ||
["VAL_MIN_PLACEHOLDER", minInt(val).toString()], | ||
["VAL_MAX_PLACEHOLDER", maxInt(val).toString()], | ||
]), | ||
}, | ||
{ | ||
template: templateSpecSourceCodeLimits, | ||
subst: new Map(), | ||
}, | ||
); | ||
await compileAndExitOnError(tactFilePath); | ||
} | ||
} | ||
}; | ||
|
||
const main = async () => { | ||
try { | ||
await generatePropertyTests(); | ||
await generateIntLimitsTests(); | ||
} catch (e) { | ||
console.error(e); | ||
process.exit(1); | ||
} | ||
}; | ||
|
||
void main(); |
113 changes: 113 additions & 0 deletions
113
src/test/e2e-emulated/map-tests/map-int-limits-key-value-types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
type FixedWidthFormat = "int" | "uint"; | ||
type VarWidthFormat = "varint" | "varuint"; | ||
|
||
type MapIntKeyDescription = | ||
| { | ||
format: FixedWidthFormat; | ||
size: number; | ||
} | ||
| { format: null }; | ||
|
||
type MapIntValDescription = | ||
| MapIntKeyDescription | ||
| { | ||
format: VarWidthFormat; | ||
size: 16 | 32; | ||
} | ||
| { format: "coins" }; | ||
|
||
const minSignedInt = (nBits: number): bigint => -(2n ** (BigInt(nBits) - 1n)); | ||
|
||
const maxSignedInt = (nBits: number): bigint => 2n ** (BigInt(nBits) - 1n) - 1n; | ||
|
||
const minUnsignedInt = (_nBits: number): bigint => 0n; | ||
|
||
const maxUnsignedInt = (nBits: number): bigint => 2n ** BigInt(nBits) - 1n; | ||
|
||
const minVarInt = (size: number): bigint => minSignedInt(8 * (size - 1)); | ||
|
||
const maxVarInt = (size: number): bigint => maxSignedInt(8 * (size - 1)); | ||
|
||
const minVarUInt = (_size: number): bigint => 0n; | ||
|
||
const maxVarUInt = (size: number): bigint => maxUnsignedInt(8 * (size - 1)); | ||
|
||
export const minInt = (descr: MapIntValDescription): bigint => { | ||
switch (descr.format) { | ||
case null: | ||
return minSignedInt(257); | ||
case "int": | ||
return minSignedInt(descr.size); | ||
case "uint": | ||
return minUnsignedInt(descr.size); | ||
case "varint": | ||
return minVarInt(descr.size); | ||
case "varuint": | ||
return minVarUInt(descr.size); | ||
case "coins": | ||
return minVarUInt(16); | ||
} | ||
}; | ||
|
||
export const maxInt = (descr: MapIntValDescription): bigint => { | ||
switch (descr.format) { | ||
case null: | ||
return maxSignedInt(257); | ||
case "int": | ||
return maxSignedInt(descr.size); | ||
case "uint": | ||
return maxUnsignedInt(descr.size); | ||
case "varint": | ||
return maxVarInt(descr.size); | ||
case "varuint": | ||
return maxVarUInt(descr.size); | ||
case "coins": | ||
return maxVarUInt(16); | ||
} | ||
}; | ||
|
||
export const descriptionToString = (descr: MapIntValDescription): string => { | ||
switch (descr.format) { | ||
case null: | ||
return "Int"; | ||
case "int": | ||
case "uint": | ||
case "varint": | ||
case "varuint": | ||
return `Int as ${descr.format}${descr.size}`; | ||
case "coins": | ||
return "Int as coins"; | ||
} | ||
}; | ||
|
||
const signedIntFormats: MapIntKeyDescription[] = [ | ||
{ format: "int", size: 2 }, | ||
{ format: "int", size: 10 }, | ||
{ format: "int", size: 37 }, | ||
{ format: "int", size: 256 }, | ||
{ format: "int", size: 257 }, | ||
{ format: null }, | ||
]; | ||
|
||
const unsignedIntFormats: MapIntKeyDescription[] = [ | ||
{ format: "uint", size: 2 }, | ||
{ format: "uint", size: 8 }, | ||
{ format: "uint", size: 32 }, | ||
{ format: "uint", size: 256 }, | ||
]; | ||
|
||
const varIntFormats: MapIntValDescription[] = [ | ||
{ format: "varint", size: 16 }, | ||
{ format: "varint", size: 32 }, | ||
{ format: "varuint", size: 16 }, | ||
{ format: "varuint", size: 32 }, | ||
{ format: "coins" }, | ||
]; | ||
|
||
const fixedWidthInts: MapIntKeyDescription[] = | ||
signedIntFormats.concat(unsignedIntFormats); | ||
|
||
export const intKeyFormats: MapIntKeyDescription[] = fixedWidthInts; | ||
|
||
export const intValFormats: MapIntValDescription[] = | ||
varIntFormats.concat(fixedWidthInts); |
Oops, something went wrong.