Skip to content

Commit

Permalink
chore(testing): add e2e migration testing for previously published so…
Browse files Browse the repository at this point in the history
…urce codes
  • Loading branch information
atticusofsparta committed Oct 2, 2024
1 parent 1863a06 commit fc56729
Show file tree
Hide file tree
Showing 11 changed files with 379 additions and 11 deletions.
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@
"aos:publish": "node tools/bundle-aos.js && node tools/publish-aos.js",
"aos:load": "node tools/bundle-aos.js && node tools/load-aos.js",
"aos:spawn": "node tools/spawn-aos.js",
"test:e2e": "yarn aos:build && node --experimental-wasm-memory64 test/e2e-test-runner.js",
"test": "yarn aos:build && node --test --test-concurrency 1 --experimental-wasm-memory64 **/*.test.js"
},
"devDependencies": {
"prettier": "^3.3.2",
"@permaweb/ao-loader": "^0.0.35",
"@permaweb/aoconnect": "^0.0.55",
"arweave": "^1.15.1"
}
"arweave": "^1.15.1",
"chalk": "4.1.2",
"fast-glob": "^3.3.2",
"plimit-lit": "^3.0.1",
"prettier": "^3.3.2"
},
"dependencies": {}
}
2 changes: 1 addition & 1 deletion test/balances.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const {

describe('aos Balances', async () => {
const { handle: originalHandle, memory: startMemory } =
await createAntAosLoader();
await createAntAosLoader(process.env.luaSourceId);

async function handle(options = {}, mem = startMemory) {
return originalHandle(
Expand Down
2 changes: 1 addition & 1 deletion test/controllers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const {

describe('aos Controllers', async () => {
const { handle: originalHandle, memory: startMemory } =
await createAntAosLoader();
await createAntAosLoader(process.env.luaSourceId);

async function handle(options = {}, mem = startMemory) {
return originalHandle(
Expand Down
120 changes: 120 additions & 0 deletions test/e2e-test-runner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// test-runner.js
const { spawn } = require('node:child_process');
const path = require('node:path');
const glob = require('fast-glob');
const { pLimit } = require('plimit-lit');
const chalk = require('chalk'); // Import chalk for colorizing output
const { getPublishedSourceCodeIds } = require('./utils'); // Import the function for getting source IDs

// Define the concurrency limit for test runs using `plimit-lit`
const limit = pLimit(5);

// Define the pattern to match all .test.js files in the current directory and subdirectories
const testPattern = path.resolve(__dirname, '**/*.test.js');

// Use `fast-glob` to find all matching test files
const testFiles = glob.sync(testPattern);

// Check if any test files were found
if (testFiles.length === 0) {
console.error('No test files found. Aborting test run.');
process.exit(1);
}

// Retrieve the source code IDs using the previously defined function
const luaSourceIds = getPublishedSourceCodeIds();

// Check if any source code IDs were found
if (luaSourceIds.length === 0) {
console.error('No Lua Source IDs found. Aborting test run.');
process.exit(1);
}

// Store results for final reporting
const testResults = {
successes: [],
failures: [],
};

// Function to spawn a test process for a given `luaSourceId`
const runTestForSourceId = (luaSourceId) => {
return new Promise((resolve, reject) => {
console.log(`Running tests for Lua Source ID: ${luaSourceId}`);

// Spawn a new Node.js process using `node --test` with the collected test files and `luaSourceId`
const testProcess = spawn(
'node',
[
'--test',
'--test-concurrency',
'1',
'--experimental-wasm-memory64',
...testFiles,
],
{
stdio: 'inherit', // Inherit stdio to show real-time test output
env: { ...process.env, luaSourceId }, // Pass `luaSourceId` to the environment variables
},
);

// Handle process completion
testProcess.on('close', (code) => {
if (code !== 0) {
const errorMessage = `Tests failed for Lua Source ID: ${luaSourceId} with exit code: ${code}`;
console.error(errorMessage);
testResults.failures.push({
luaSourceId,
message: errorMessage,
});
reject(new Error(errorMessage));
} else {
const successMessage = `Tests completed successfully for Lua Source ID: ${luaSourceId}`;
console.log(successMessage);
testResults.successes.push({
luaSourceId,
message: successMessage,
});
resolve();
}
});
});
};

// Create and execute test tasks with the concurrency limit
const testTasks = luaSourceIds.map((sourceId) =>
limit(() => runTestForSourceId(sourceId)),
);

Promise.allSettled(testTasks)
.then((results) => {
// Generate the summary report
console.log('\nTest Summary:');
console.log('---------------');

// Display successful tests in green
if (testResults.successes.length > 0) {
console.log(chalk.green('\nSuccessful Tests:'));
testResults.successes.forEach((result, index) => {
console.log(chalk.green(`${index + 1}. ${result.message}`));
});
}

// Display failed tests in red
if (testResults.failures.length > 0) {
console.error(chalk.red('\nFailed Tests:'));
testResults.failures.forEach((result, index) => {
console.error(chalk.red(`${index + 1}. ${result.message}`));
});
console.error(
chalk.red(`\n${testResults.failures.length} test(s) failed.`),
);
process.exit(1); // Exit with a non-zero code for failed tests
} else {
console.log(chalk.green('\nAll tests completed successfully.'));
process.exit(0);
}
})
.catch((error) => {
console.error('Unexpected error occurred:', error);
process.exit(1);
});
3 changes: 2 additions & 1 deletion test/evolve.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const {

describe('aos Evolve', async () => {
const { handle: originalHandle, memory: startMemory } =
await createAntAosLoader();
await createAntAosLoader(process.env.luaSourceId);

async function handle(options = {}, mem = startMemory) {
return originalHandle(
Expand Down Expand Up @@ -72,6 +72,7 @@ describe('aos Evolve', async () => {
);

const state = JSON.parse(result.Messages[0].Data);
console.log(state);
assert(state);
assert(state['Source-Code-TX-ID'] === '__INSERT_SOURCE_CODE_ID__');
});
Expand Down
2 changes: 1 addition & 1 deletion test/info.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const {

describe('aos Info', async () => {
const { handle: originalHandle, memory: startMemory } =
await createAntAosLoader();
await createAntAosLoader(process.env.luaSourceId);

async function handle(options = {}, mem = startMemory) {
return originalHandle(
Expand Down
2 changes: 1 addition & 1 deletion test/initialize.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const {

describe('aos Initialization', async () => {
const { handle: originalHandle, memory: startMemory } =
await createAntAosLoader();
await createAntAosLoader(process.env.luaSourceId);

async function handle(options = {}, mem = startMemory) {
return originalHandle(
Expand Down
2 changes: 1 addition & 1 deletion test/records.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const {

describe('aos Records', async () => {
const { handle: originalHandle, memory: startMemory } =
await createAntAosLoader();
await createAntAosLoader(process.env.luaSourceId);

async function handle(options = {}, mem = startMemory) {
return originalHandle(
Expand Down
2 changes: 1 addition & 1 deletion test/registry.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const {

describe('Registry Updates', async () => {
const { handle: originalHandle, memory: startMemory } =
await createAntAosLoader();
await createAntAosLoader(process.env.luaSourceId);

const controllerAddress = 'controller-address'.padEnd(43, '0');

Expand Down
74 changes: 73 additions & 1 deletion test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ const {
DEFAULT_HANDLE_OPTIONS,
ANT_EVAL_OPTIONS,
} = require('../tools/constants');
const Arweave = require('arweave');
const fs = require('node:fs');
const path = require('node:path');
const assert = require('node:assert');

/**
* Loads the aos wasm binary and returns the handle function with program memory
Expand All @@ -25,11 +29,79 @@ async function createAosLoader(params) {
};
}

async function createAntAosLoader() {
async function createAntAosLoader(id) {
if (id) {
const luaCode = await getLuaCodeFromTxId(id);
const { handle: originalHandle, memory: originalMemory } =
await createAosLoader({
...ANT_EVAL_OPTIONS,
Data: luaCode,
});

// reset the source id to template string
const freshStateRes = await originalHandle(
originalMemory,
{
...DEFAULT_HANDLE_OPTIONS,
...ANT_EVAL_OPTIONS,
Data: 'SourceCodeTxId = "__INSERT_SOURCE_CODE_ID__"',
},
AO_LOADER_HANDLER_ENV,
);

const currentLuaCodeEvalRes = await originalHandle(
freshStateRes.Memory,
{
...DEFAULT_HANDLE_OPTIONS,
...ANT_EVAL_OPTIONS,
},
AO_LOADER_HANDLER_ENV,
);

return { handle: originalHandle, memory: currentLuaCodeEvalRes.Memory };
}
return createAosLoader(ANT_EVAL_OPTIONS);
}

function getPublishedSourceCodeIds() {
// Read all filenames from the changelogs directory
const changeLogFileNames = fs.readdirSync(
path.join(__dirname, '../changelogs'),
);

// Process each file name to extract the source code ID
const txIds = changeLogFileNames
.map((fileName) => {
// Remove the date portion at the start, which is in the format YYYY-MM-DD-
const parts = fileName.split('-').slice(3); // Skip the first 3 parts (YYYY, MM, DD)
const idWithExtension = parts.join('-'); // Join the remaining parts in case the ID itself has dashes
const txId = idWithExtension.split('.').shift(); // Remove the file extension (e.g., .md)

return txId;
})
.filter((txId) => txId.length === 43); // Filter for valid IDs with length 43

return txIds;
}
async function getLuaCodeFromTxId(
txId,
arweave = Arweave.init({
host: 'arweave.net',
port: 443,
protocol: 'https',
}),
) {
const luaCode = await arweave.transactions.getData(txId, {
decode: true,
string: true,
});
assert(luaCode);
return luaCode;
}

module.exports = {
createAntAosLoader,
createAosLoader,
getPublishedSourceCodeIds,
getLuaCodeFromTxId,
};
Loading

0 comments on commit fc56729

Please sign in to comment.