sanket3280/code-execution
0
1/**2 * JavaScript Test Harness Generator3 * Creates optimized test harness for JavaScript code execution4 */5 6const { getHelpers, extractFunctionName } = require('./baseHarness');7 8const createJavaScriptTestHarness = (sourceCode, testCases) => {9 let harness = '';10 11 const helpers = getHelpers(sourceCode, 'javascript');12 if (helpers) {13 harness += helpers + '\n\n';14 }15 16 harness += sourceCode + '\n\n';17 18 // Add deep copy helper function to prevent grid mutation19 harness += `20// Deep copy helper to prevent array mutation across test cases21function deepCopy(obj) {22 if (obj === null || typeof obj !== 'object') return obj;23 if (Array.isArray(obj)) return obj.map(item => deepCopy(item));24 const copy = {};25 for (const key in obj) {26 if (obj.hasOwnProperty(key)) {27 copy[key] = deepCopy(obj[key]);28 }29 }30 return copy;31}32\n\n`;33 34 harness += 'const testCases = [\n';35 36 testCases.forEach((testCase, index) => {37 const input = JSON.parse(testCase.input);38 const expected = testCase.expected;39 harness += ` { input: ${JSON.stringify(input)}, expected: ${JSON.stringify(expected)}, index: ${index} },\n`;40 });41 42 harness += '];\n\n';43 harness += createTestExecutionLogic(sourceCode);44 45 return harness;46};47 48/**49 * Create test execution logic50 */51const createTestExecutionLogic = (sourceCode) => {52 const functionName = extractFunctionName.javascript(sourceCode);53 54 return `55console.log('TEST_RESULTS_START');56 57for (let i = 0; i < testCases.length; i++) {58 const testCase = testCases[i];59 60 try {61 memo = {};62 cache = {};63 dp = [];64 65 // Check if this is a class-based problem (operations/values format)66 if (testCase.input.operations && testCase.input.values) {67 const operations = testCase.input.operations;68 const values = testCase.input.values;69 const results = [];70 let instance = null;71 72 for (let j = 0; j < operations.length; j++) {73 const op = operations[j];74 const args = values[j];75 76 if (j === 0) {77 // Constructor call78 instance = new (eval(op))(...args);79 results.push(null);80 } else {81 // Method call82 const result = instance[op](...args);83 results.push(result === undefined ? null : result);84 }85 }86 87 var result = results;88 } else {89 // Regular function call - with case-insensitive fallback90 const processedInput = {};91 for (const key in testCase.input) {92 const value = testCase.input[key];93 94 if (key === 'root' && Array.isArray(value)) {95 processedInput[key] = buildBinaryTree(value);96 } else if (key === 'lists' && Array.isArray(value) && value.length > 0 && Array.isArray(value[0])) {97 // Handle array of arrays (like mergeKLists) - convert each array to linked list98 processedInput[key] = value.map(arr => createLinkedList(arr));99 } else if (key.includes('list') && Array.isArray(value) && !Array.isArray(value[0])) {100 // Handle single linked list101 processedInput[key] = createLinkedList(value);102 } else if (Array.isArray(value)) {103 // Deep copy arrays (like grid) to prevent mutation across test cases104 processedInput[key] = deepCopy(value);105 } else {106 processedInput[key] = value;107 }108 }109 110 // Try exact function name first111 let targetFunction = typeof ${functionName} !== 'undefined' ? ${functionName} : null;112 113 // If not found, try case-insensitive search114 if (!targetFunction) {115 const expectedName = '${functionName}';116 const expectedLower = expectedName.toLowerCase();117 118 // Search for function with same name (case-insensitive)119 for (const key in globalThis) {120 if (typeof globalThis[key] === 'function' && key.toLowerCase() === expectedLower) {121 targetFunction = globalThis[key];122 if (i === 0) {123 console.error('WARNING: Function name case mismatch. Expected "' + expectedName + '" but found "' + key + '". Please use exact function name.');124 }125 break;126 }127 }128 }129 130 if (!targetFunction) {131 throw new Error('Function "${functionName}" not found. Please check function name spelling and capitalization.');132 }133 134 var result = targetFunction(...Object.values(processedInput));135 }136 137 let output;138 if (result && result.constructor && result.constructor.name === 'ListNode') {139 output = '[' + linkedListToArray(result).join(',') + ']';140 } else if (result === null && testCase.expected && testCase.expected.startsWith('[')) {141 output = '[]';142 } else if (Array.isArray(result)) {143 // Use JSON.stringify to properly handle null values144 output = JSON.stringify(result);145 } else if (typeof result === 'string') {146 output = JSON.stringify(result);147 } else if (result === null) {148 output = 'null';149 } else {150 output = String(result);151 }152 153 let expected;154 if (typeof testCase.expected === 'string' && 155 testCase.expected.startsWith('"') && 156 testCase.expected.endsWith('"')) {157 expected = testCase.expected;158 } else {159 expected = String(testCase.expected);160 }161 162 // Smart comparison: try numeric comparison first, then string163 let passed = output === expected;164 if (!passed) {165 const outputNum = parseFloat(output);166 const expectedNum = parseFloat(expected);167 if (!isNaN(outputNum) && !isNaN(expectedNum)) {168 // Use tolerance of 1e-5 (0.00001) for floating point comparison169 // This handles 5 decimal places precision170 const tolerance = 1e-5;171 passed = Math.abs(outputNum - expectedNum) < tolerance;172 }173 }174 175 console.log(\`TEST_\${i+1}:\${passed ? 'PASS' : 'FAIL'}:\${output}:\${expected}\`);176 177 } catch (error) {178 console.log(\`TEST_\${i+1}:ERROR:\${error.message}\`);179 }180}181 182console.log('TEST_RESULTS_END');183`;184};185 186module.exports = {187 createJavaScriptTestHarness188};189 