#!/usr/bin/env node /** * Correctness test to verify Go and JS implementations produce identical SVG output * This must pass before performance benchmarks are meaningful */ const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); // Check if jdenticon-js is available let jdenticon; try { jdenticon = require('../jdenticon-js/dist/jdenticon-node.js'); } catch (err) { console.error('Error: jdenticon-js not found. Please ensure it\'s available in jdenticon-js/dist/'); console.error('You may need to build the JS version first.'); process.exit(1); } // Test inputs for correctness verification const testInputs = [ 'user@example.com', 'test-hash-123', 'benchmark-input-abc', 'empty-string', 'special-chars-!@#$%' ]; const ICON_SIZE = 64; console.log('Running correctness test...'); console.log('Verifying Go and JS implementations produce identical SVG output\n'); // Create temporary directory for outputs const tempDir = './temp-correctness'; if (!fs.existsSync(tempDir)) { fs.mkdirSync(tempDir); } let allPassed = true; for (let i = 0; i < testInputs.length; i++) { const input = testInputs[i]; console.log(`Testing input ${i + 1}/${testInputs.length}: "${input}"`); try { // Generate SVG using JavaScript implementation const jsSvg = jdenticon.toSvg(input, ICON_SIZE); const jsPath = path.join(tempDir, `js-${i}.svg`); fs.writeFileSync(jsPath, jsSvg); // Generate SVG using Go implementation via CLI const goPath = path.join(tempDir, `go-${i}.svg`); const absoluteGoPath = path.resolve(goPath); const goCommand = `cd .. && go run cmd/jdenticon/main.go -value="${input}" -size=${ICON_SIZE} -format=svg -output="${absoluteGoPath}"`; try { execSync(goCommand, { stdio: 'pipe' }); } catch (goErr) { console.error(` ❌ Failed to generate Go SVG: ${goErr.message}`); allPassed = false; continue; } // Read Go-generated SVG if (!fs.existsSync(goPath)) { console.error(` ❌ Go SVG file not created: ${goPath}`); allPassed = false; continue; } const goSvg = fs.readFileSync(goPath, 'utf8'); // Compare SVGs if (jsSvg === goSvg) { console.log(` ✅ PASS - SVGs are identical`); } else { console.log(` ❌ FAIL - SVGs differ`); console.log(` JS length: ${jsSvg.length} chars`); console.log(` Go length: ${goSvg.length} chars`); // Save diff for analysis const diffPath = path.join(tempDir, `diff-${i}.txt`); fs.writeFileSync(diffPath, `JS SVG:\n${jsSvg}\n\nGo SVG:\n${goSvg}\n`); console.log(` Diff saved to: ${diffPath}`); allPassed = false; } } catch (err) { console.error(` ❌ Error testing input "${input}": ${err.message}`); allPassed = false; } console.log(''); } // Clean up temporary files if all tests passed if (allPassed) { try { fs.rmSync(tempDir, { recursive: true }); console.log('✅ All correctness tests PASSED - SVG outputs are identical!'); console.log(' Performance benchmarks will be meaningful.'); } catch (cleanupErr) { console.log('✅ All correctness tests PASSED (cleanup failed)'); } } else { console.log('❌ Some correctness tests FAILED'); console.log(` Review differences in ${tempDir}/`); console.log(' Fix Go implementation before running performance benchmarks.'); process.exit(1); }