@patchworkdev/common
Version:
Patchwork Development Kit
182 lines (181 loc) • 8.65 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const child_process_1 = require("child_process");
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const types_1 = require("../../types");
const contractSchema_1 = require("../contractSchema");
const mainContractGen_1 = require("../mainContractGen");
const userContractGen_1 = require("../userContractGen");
function removeDirectoryRecursive(dirPath) {
if (fs_1.default.existsSync(dirPath)) {
fs_1.default.readdirSync(dirPath).forEach((file) => {
const curPath = path_1.default.join(dirPath, file);
if (fs_1.default.lstatSync(curPath).isDirectory()) {
// Recursive call for directories
removeDirectoryRecursive(curPath);
}
else {
// Delete file
fs_1.default.unlinkSync(curPath);
}
});
fs_1.default.rmdirSync(dirPath);
}
}
function generateFieldPermutations() {
const fieldTypes = Object.values(types_1.FieldTypeEnum)
.filter(value => typeof value === 'string' && value !== 'empty' && value !== 'CHAR64');
let permutations = [];
fieldTypes.forEach((fieldType, index) => {
let actualFieldType = (fieldType.toLowerCase());
actualFieldType = actualFieldType.toLowerCase();
// Single field
permutations.push([{
id: 1,
key: `field_${actualFieldType}`,
type: actualFieldType,
description: `A single ${actualFieldType} field`,
}]);
// Array field (exclude for 'string' type)
if (actualFieldType !== 'string') {
permutations.push([{
id: 1,
key: `array_${actualFieldType}`,
type: actualFieldType,
arrayLength: 4,
description: `An array of ${actualFieldType} fields`,
}]);
}
});
return permutations;
}
function generateContractSchemaPermutations() {
const baseConfig = {
scopeName: "TestScope",
name: "TestContract",
symbol: "TST",
baseURI: "https://example.com/",
schemaURI: "https://example.com/schema",
imageURI: "https://example.com/image",
fields: [],
features: [types_1.Feature.MINTABLE, types_1.Feature.LITEREF],
fragments: []
};
const fieldPermutations = generateFieldPermutations();
return fieldPermutations.map((fields) => ({
...baseConfig,
fields,
}));
}
describe("Generate and Build Contract Schema Field Permutations", () => {
const outputDir = path_1.default.join(__dirname, "generated_contracts");
const schemaNoVerifyDir = path_1.default.join(__dirname, "schema_noverify");
const schemaNoBuildDir = path_1.default.join(__dirname, "schema_nobuild");
beforeAll(() => {
// Create directories if they don't exist
[outputDir, schemaNoVerifyDir, schemaNoBuildDir].forEach(dir => {
if (!fs_1.default.existsSync(dir)) {
fs_1.default.mkdirSync(dir, { recursive: true });
}
});
// Clear contents of schema_noverify and schema_nobuild
[schemaNoVerifyDir, schemaNoBuildDir].forEach(dir => {
removeDirectoryRecursive(dir);
fs_1.default.mkdirSync(dir);
});
// Clear contents of generated_contracts, preserving remappings.txt and foundry.toml
fs_1.default.readdirSync(outputDir).forEach(file => {
const filePath = path_1.default.join(outputDir, file);
if (file !== 'remappings.txt' && file !== 'foundry.toml') {
if (fs_1.default.lstatSync(filePath).isDirectory()) {
removeDirectoryRecursive(filePath);
}
else {
fs_1.default.unlinkSync(filePath);
}
}
});
});
it("should generate, save, and build all contract schema field permutations", async () => {
console.log("Generating contract schema field permutations...");
const permutations = generateContractSchemaPermutations();
const mainContractGen = new mainContractGen_1.MainContractGen();
const userContractGen = new userContractGen_1.UserContractGen();
let errors = [];
for (let index = 0; index < permutations.length; index++) {
const config = permutations[index];
console.log(`Processing field permutation ${index}:`, config);
const schema = new contractSchema_1.ContractSchemaImpl(config);
try {
schema.validate();
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error(`Schema validation failed for contract ${index}:`, errorMessage);
fs_1.default.writeFileSync(path_1.default.join(schemaNoVerifyDir, `schema_${index}.json`), JSON.stringify(config, null, 2));
errors.push(`Schema validation failed for contract ${index}: ${errorMessage}`);
continue; // Skip to the next permutation
}
try {
const mainCode = mainContractGen.gen(schema);
const userCode = userContractGen.gen(schema);
const mainFileName = path_1.default.join(outputDir, `TestContractGenerated.sol`);
const userFileName = path_1.default.join(outputDir, `TestContract.sol`);
fs_1.default.writeFileSync(mainFileName, mainCode);
fs_1.default.writeFileSync(userFileName, userCode);
console.log(`Generated contract ${index}`);
// Call forge build
await new Promise((resolve, reject) => {
(0, child_process_1.exec)('forge build', { cwd: outputDir }, (error, stdout, stderr) => {
if (error) {
console.error(`forge build failed for contract ${index}:`);
console.error(stderr);
fs_1.default.writeFileSync(path_1.default.join(schemaNoBuildDir, `schema_${index}.json`), JSON.stringify(config, null, 2));
errors.push(`forge build failed for contract ${index}: ${stderr}`);
resolve(); // Resolve even on error to continue processing
}
else {
console.log(`Successfully built contract ${index}`);
resolve();
}
});
});
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error(`Error in contract ${index}:`, errorMessage);
errors.push(`Error in contract ${index}: ${errorMessage}`);
}
finally {
// Clean up .sol files after each attempt
const mainFileName = path_1.default.join(outputDir, `TestContractGenerated.sol`);
const userFileName = path_1.default.join(outputDir, `TestContract.sol`);
if (fs_1.default.existsSync(mainFileName))
fs_1.default.unlinkSync(mainFileName);
if (fs_1.default.existsSync(userFileName))
fs_1.default.unlinkSync(userFileName);
}
// Add a small delay between iterations to allow for any pending I/O operations
await new Promise(resolve => setTimeout(resolve, 100));
}
console.log(`Total field permutations processed: ${permutations.length}`);
console.log(`Total errors encountered: ${errors.length}`);
if (errors.length > 0) {
console.error("Errors encountered during processing:");
errors.forEach((error, index) => {
console.error(`${index + 1}: ${error}`);
});
throw new Error(`${errors.length} errors encountered during processing`);
}
expect(permutations.length).toBeGreaterThan(0);
});
afterAll(() => {
// Clean up after all tests
removeDirectoryRecursive(path_1.default.join(outputDir, 'out'));
removeDirectoryRecursive(path_1.default.join(outputDir, 'cache'));
});
});