748 lines
30 KiB
Java
748 lines
30 KiB
Java
import javax.swing.*;
|
|
import javax.swing.border.EmptyBorder;
|
|
import javax.swing.table.DefaultTableModel;
|
|
import javax.swing.text.DefaultCaret;
|
|
import java.awt.*;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.ActionListener;
|
|
import java.io.*;
|
|
import java.nio.file.*;
|
|
import java.nio.file.attribute.BasicFileAttributes;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.*;
|
|
import java.util.List;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
import java.util.stream.Collectors;
|
|
|
|
public class BakeTestRunner extends JFrame {
|
|
private JPanel mainPanel;
|
|
private JTable testTable;
|
|
private DefaultTableModel tableModel;
|
|
private JTextArea logArea;
|
|
private JButton runSelectedButton;
|
|
private JButton runAllButton;
|
|
private JComboBox<String> languageComboBox;
|
|
private JProgressBar progressBar;
|
|
private JButton openLogsButton;
|
|
private JButton compareSelectedButton;
|
|
|
|
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
private final String baseDir = System.getProperty("user.dir");
|
|
private final String logsDir = baseDir + File.separator + "logs";
|
|
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
|
private final Color PASSED_COLOR = new Color(220, 255, 220);
|
|
private final Color FAILED_COLOR = new Color(255, 220, 220);
|
|
private final Color RUNNING_COLOR = new Color(220, 220, 255);
|
|
|
|
enum TestStatus {
|
|
NOT_RUN, RUNNING, PASSED, FAILED
|
|
}
|
|
|
|
public BakeTestRunner() {
|
|
setTitle("Bake Test Runner");
|
|
setSize(1000, 700);
|
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
setLocationRelativeTo(null);
|
|
|
|
setupUI();
|
|
loadTests();
|
|
createLogsDirectory();
|
|
}
|
|
|
|
private void setupUI() {
|
|
mainPanel = new JPanel(new BorderLayout(10, 10));
|
|
mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
|
|
|
// Top panel with controls
|
|
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
|
|
runSelectedButton = new JButton("Run Selected Tests");
|
|
runAllButton = new JButton("Run All Tests");
|
|
compareSelectedButton = new JButton("Compare Selected Test");
|
|
languageComboBox = new JComboBox<>(new String[]{"All", "C", "Java"});
|
|
openLogsButton = new JButton("Open Logs Directory");
|
|
|
|
controlPanel.add(runSelectedButton);
|
|
controlPanel.add(runAllButton);
|
|
controlPanel.add(compareSelectedButton);
|
|
controlPanel.add(new JLabel("Language:"));
|
|
controlPanel.add(languageComboBox);
|
|
controlPanel.add(openLogsButton);
|
|
|
|
// Table for test list
|
|
String[] columnNames = {"#", "Language", "Test Name", "Status", "Last Run"};
|
|
tableModel = new DefaultTableModel(columnNames, 0) {
|
|
@Override
|
|
public boolean isCellEditable(int row, int column) {
|
|
return false;
|
|
}
|
|
};
|
|
testTable = new JTable(tableModel);
|
|
testTable.getColumnModel().getColumn(0).setPreferredWidth(30);
|
|
testTable.getColumnModel().getColumn(1).setPreferredWidth(70);
|
|
testTable.getColumnModel().getColumn(2).setPreferredWidth(300);
|
|
testTable.getColumnModel().getColumn(3).setPreferredWidth(80);
|
|
testTable.getColumnModel().getColumn(4).setPreferredWidth(150);
|
|
testTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
|
testTable.setRowHeight(25);
|
|
|
|
// Log area
|
|
logArea = new JTextArea();
|
|
logArea.setEditable(false);
|
|
logArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
|
|
DefaultCaret caret = (DefaultCaret) logArea.getCaret();
|
|
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
|
|
|
|
// Progress bar
|
|
progressBar = new JProgressBar(0, 100);
|
|
progressBar.setStringPainted(true);
|
|
progressBar.setString("Ready");
|
|
|
|
// Layout
|
|
JSplitPane splitPane = new JSplitPane(
|
|
JSplitPane.VERTICAL_SPLIT,
|
|
new JScrollPane(testTable),
|
|
new JScrollPane(logArea)
|
|
);
|
|
splitPane.setDividerLocation(300);
|
|
|
|
mainPanel.add(controlPanel, BorderLayout.NORTH);
|
|
mainPanel.add(splitPane, BorderLayout.CENTER);
|
|
mainPanel.add(progressBar, BorderLayout.SOUTH);
|
|
|
|
setContentPane(mainPanel);
|
|
|
|
// Add action listeners
|
|
runSelectedButton.addActionListener(e -> runSelectedTests());
|
|
runAllButton.addActionListener(e -> runAllTests());
|
|
compareSelectedButton.addActionListener(e -> compareSelectedTest());
|
|
openLogsButton.addActionListener(e -> openLogsDirectory());
|
|
languageComboBox.addActionListener(e -> filterTestsByLanguage());
|
|
}
|
|
|
|
private void createLogsDirectory() {
|
|
try {
|
|
Files.createDirectories(Paths.get(logsDir));
|
|
} catch (IOException e) {
|
|
logMessage("Error creating logs directory: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
private void openLogsDirectory() {
|
|
try {
|
|
Desktop.getDesktop().open(new File(logsDir));
|
|
} catch (IOException e) {
|
|
logMessage("Error opening logs directory: " + e.getMessage());
|
|
JOptionPane.showMessageDialog(this,
|
|
"Could not open logs directory: " + e.getMessage(),
|
|
"Error", JOptionPane.ERROR_MESSAGE);
|
|
}
|
|
}
|
|
|
|
private void compareSelectedTest() {
|
|
int selectedRow = testTable.getSelectedRow();
|
|
if (selectedRow == -1) {
|
|
JOptionPane.showMessageDialog(this,
|
|
"Please select a test to compare",
|
|
"No Test Selected", JOptionPane.WARNING_MESSAGE);
|
|
return;
|
|
}
|
|
|
|
String language = (String) tableModel.getValueAt(selectedRow, 1);
|
|
String testName = (String) tableModel.getValueAt(selectedRow, 2);
|
|
|
|
String logFilePath = logsDir + File.separator + language + "_" + testName + ".log";
|
|
File logFile = new File(logFilePath);
|
|
|
|
if (!logFile.exists()) {
|
|
JOptionPane.showMessageDialog(this,
|
|
"No log file found for this test. Please run the test first.",
|
|
"Log Not Found", JOptionPane.WARNING_MESSAGE);
|
|
return;
|
|
}
|
|
|
|
showComparisonDialog(logFile, language, testName);
|
|
}
|
|
|
|
private void showComparisonDialog(File logFile, String language, String testName) {
|
|
JDialog dialog = new JDialog(this, "Comparison: " + language + " - " + testName, true);
|
|
dialog.setLayout(new BorderLayout(10, 10));
|
|
dialog.setSize(1000, 600);
|
|
dialog.setLocationRelativeTo(this);
|
|
|
|
try {
|
|
List<String> lines = Files.readAllLines(logFile.toPath());
|
|
String content = String.join("\n", lines);
|
|
|
|
// Split content to make and bake sections if possible
|
|
String makeOutput = "";
|
|
String bakeOutput = "";
|
|
|
|
// Basic parsing - can be enhanced for better splitting
|
|
int makeIndex = content.indexOf("=== Make Output ===");
|
|
int bakeIndex = content.indexOf("=== Bake Output ===");
|
|
int comparisonIndex = content.indexOf("=== Comparison Results ===");
|
|
|
|
if (makeIndex != -1 && bakeIndex != -1) {
|
|
makeOutput = content.substring(makeIndex, bakeIndex).trim();
|
|
if (comparisonIndex != -1) {
|
|
bakeOutput = content.substring(bakeIndex, comparisonIndex).trim();
|
|
} else {
|
|
bakeOutput = content.substring(bakeIndex).trim();
|
|
}
|
|
}
|
|
|
|
JTextArea makeArea = new JTextArea(makeOutput);
|
|
JTextArea bakeArea = new JTextArea(bakeOutput);
|
|
JTextArea comparisonArea = new JTextArea();
|
|
|
|
if (comparisonIndex != -1) {
|
|
comparisonArea.setText(content.substring(comparisonIndex).trim());
|
|
} else {
|
|
comparisonArea.setText("No comparison results available.");
|
|
}
|
|
|
|
makeArea.setEditable(false);
|
|
bakeArea.setEditable(false);
|
|
comparisonArea.setEditable(false);
|
|
|
|
makeArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
|
|
bakeArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
|
|
comparisonArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
|
|
|
|
JTabbedPane tabbedPane = new JTabbedPane();
|
|
tabbedPane.addTab("Make Output", new JScrollPane(makeArea));
|
|
tabbedPane.addTab("Bake Output", new JScrollPane(bakeArea));
|
|
tabbedPane.addTab("Comparison", new JScrollPane(comparisonArea));
|
|
|
|
dialog.add(tabbedPane, BorderLayout.CENTER);
|
|
|
|
JButton closeButton = new JButton("Close");
|
|
closeButton.addActionListener(e -> dialog.dispose());
|
|
|
|
JPanel buttonPanel = new JPanel();
|
|
buttonPanel.add(closeButton);
|
|
dialog.add(buttonPanel, BorderLayout.SOUTH);
|
|
|
|
dialog.setVisible(true);
|
|
|
|
} catch (IOException e) {
|
|
JOptionPane.showMessageDialog(dialog,
|
|
"Error reading log file: " + e.getMessage(),
|
|
"Error", JOptionPane.ERROR_MESSAGE);
|
|
}
|
|
}
|
|
|
|
private void loadTests() {
|
|
tableModel.setRowCount(0);
|
|
|
|
// Load C tests
|
|
loadTestsForLanguage("C");
|
|
|
|
// Load Java tests
|
|
loadTestsForLanguage("Java");
|
|
}
|
|
|
|
private void loadTestsForLanguage(String language) {
|
|
File languageDir = new File(baseDir + File.separator + "tests" + File.separator + language);
|
|
if (!languageDir.exists() || !languageDir.isDirectory()) {
|
|
logMessage("Warning: Directory not found: " + languageDir.getPath());
|
|
return;
|
|
}
|
|
|
|
File[] testDirs = languageDir.listFiles(File::isDirectory);
|
|
if (testDirs == null) {
|
|
logMessage("Warning: No test directories found in " + languageDir.getPath());
|
|
return;
|
|
}
|
|
|
|
Arrays.sort(testDirs, (a, b) -> {
|
|
// Extract test number for sorting
|
|
Pattern pattern = Pattern.compile("test-(\\d+)");
|
|
Matcher matcherA = pattern.matcher(a.getName());
|
|
Matcher matcherB = pattern.matcher(b.getName());
|
|
|
|
if (matcherA.find() && matcherB.find()) {
|
|
try {
|
|
int numA = Integer.parseInt(matcherA.group(1));
|
|
int numB = Integer.parseInt(matcherB.group(1));
|
|
return Integer.compare(numA, numB);
|
|
} catch (NumberFormatException e) {
|
|
return a.getName().compareTo(b.getName());
|
|
}
|
|
}
|
|
return a.getName().compareTo(b.getName());
|
|
});
|
|
|
|
for (File testDir : testDirs) {
|
|
String testName = testDir.getName();
|
|
if (testName.startsWith("test-")) {
|
|
Object[] row = {tableModel.getRowCount() + 1, language, testName, "Not Run", ""};
|
|
tableModel.addRow(row);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void filterTestsByLanguage() {
|
|
String selectedLanguage = (String) languageComboBox.getSelectedItem();
|
|
if (selectedLanguage == null || selectedLanguage.equals("All")) {
|
|
loadTests();
|
|
return;
|
|
}
|
|
|
|
tableModel.setRowCount(0);
|
|
loadTestsForLanguage(selectedLanguage);
|
|
}
|
|
|
|
private void runSelectedTests() {
|
|
int[] selectedRows = testTable.getSelectedRows();
|
|
if (selectedRows.length == 0) {
|
|
JOptionPane.showMessageDialog(this,
|
|
"Please select at least one test to run",
|
|
"No Test Selected", JOptionPane.WARNING_MESSAGE);
|
|
return;
|
|
}
|
|
|
|
List<TestInfo> testsToRun = new ArrayList<>();
|
|
for (int row : selectedRows) {
|
|
String language = (String) tableModel.getValueAt(row, 1);
|
|
String testName = (String) tableModel.getValueAt(row, 2);
|
|
testsToRun.add(new TestInfo(row, language, testName));
|
|
}
|
|
|
|
disableButtons();
|
|
runTests(testsToRun);
|
|
}
|
|
|
|
private void runAllTests() {
|
|
List<TestInfo> testsToRun = new ArrayList<>();
|
|
for (int row = 0; row < tableModel.getRowCount(); row++) {
|
|
String language = (String) tableModel.getValueAt(row, 1);
|
|
String testName = (String) tableModel.getValueAt(row, 2);
|
|
testsToRun.add(new TestInfo(row, language, testName));
|
|
}
|
|
|
|
disableButtons();
|
|
runTests(testsToRun);
|
|
}
|
|
|
|
private void disableButtons() {
|
|
runSelectedButton.setEnabled(false);
|
|
runAllButton.setEnabled(false);
|
|
compareSelectedButton.setEnabled(false);
|
|
languageComboBox.setEnabled(false);
|
|
}
|
|
|
|
private void enableButtons() {
|
|
runSelectedButton.setEnabled(true);
|
|
runAllButton.setEnabled(true);
|
|
compareSelectedButton.setEnabled(true);
|
|
languageComboBox.setEnabled(true);
|
|
}
|
|
|
|
private void runTests(List<TestInfo> testsToRun) {
|
|
progressBar.setValue(0);
|
|
progressBar.setString("Running tests (0/" + testsToRun.size() + ")");
|
|
logArea.setText("");
|
|
|
|
executor.submit(() -> {
|
|
try {
|
|
int total = testsToRun.size();
|
|
int current = 0;
|
|
|
|
for (int i = 0; i < testsToRun.size(); i++) {
|
|
TestInfo test = testsToRun.get(i);
|
|
final int currentTest = i + 1;
|
|
|
|
// Update UI to show we're running this test
|
|
SwingUtilities.invokeLater(() -> {
|
|
tableModel.setValueAt(TestStatus.RUNNING.name(), test.row, 3);
|
|
testTable.setValueAt(TestStatus.RUNNING.name(), test.row, 3);
|
|
testTable.setValueAt(dateFormat.format(new Date()), test.row, 4);
|
|
|
|
// Highlight the row
|
|
testTable.setRowSelectionInterval(test.row, test.row);
|
|
|
|
// Update the progress bar
|
|
progressBar.setValue((int)((double)currentTest / total * 100));
|
|
progressBar.setString("Running tests (" + currentTest + "/" + total + ")");
|
|
});
|
|
|
|
// Run the test
|
|
logMessage("\n========================================================");
|
|
logMessage("Running Test: " + test.language + " - " + test.testName);
|
|
logMessage("========================================================");
|
|
|
|
boolean success = runTest(test);
|
|
|
|
// Update UI with the result
|
|
SwingUtilities.invokeLater(() -> {
|
|
testTable.setValueAt(success ? TestStatus.PASSED.name() : TestStatus.FAILED.name(),
|
|
test.row, 3);
|
|
});
|
|
}
|
|
|
|
// Test run complete
|
|
SwingUtilities.invokeLater(() -> {
|
|
progressBar.setValue(100);
|
|
progressBar.setString("All tests completed");
|
|
enableButtons();
|
|
logMessage("\n========================================================");
|
|
logMessage("Test run completed at " + dateFormat.format(new Date()));
|
|
logMessage("========================================================");
|
|
});
|
|
} catch (Exception e) {
|
|
SwingUtilities.invokeLater(() -> {
|
|
logMessage("Error running tests: " + e.getMessage());
|
|
for (StackTraceElement element : e.getStackTrace()) {
|
|
logMessage(" " + element.toString());
|
|
}
|
|
progressBar.setString("Error running tests");
|
|
enableButtons();
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
private boolean runTest(TestInfo test) {
|
|
String testDir = baseDir + File.separator + "tests" + File.separator +
|
|
test.language + File.separator + test.testName;
|
|
|
|
File makeDir = new File(testDir + File.separator + "make");
|
|
File bakeDir = new File(testDir + File.separator + "bake");
|
|
|
|
if (!makeDir.exists() || !bakeDir.exists()) {
|
|
logMessage("Error: Make or Bake directory not found for test " + test.testName);
|
|
return false;
|
|
}
|
|
|
|
String logFilePath = logsDir + File.separator + test.language + "_" + test.testName + ".log";
|
|
|
|
try (PrintWriter writer = new PrintWriter(new FileWriter(logFilePath))) {
|
|
// Header information
|
|
writer.println("Test: " + test.language + " - " + test.testName);
|
|
writer.println("Date: " + dateFormat.format(new Date()));
|
|
writer.println("========================================================");
|
|
|
|
// Compare initial file state
|
|
writer.println("\n=== Initial File Comparison ===");
|
|
logMessage("Comparing initial files...");
|
|
|
|
Map<String, FileInfo> makeFiles = scanDirectory(makeDir);
|
|
Map<String, FileInfo> bakeFiles = scanDirectory(bakeDir);
|
|
|
|
compareAndLogFiles(makeFiles, bakeFiles, writer);
|
|
|
|
// Run make
|
|
writer.println("\n=== Make Output ===");
|
|
logMessage("Running make...");
|
|
|
|
ProcessResult makeResult = runProcess("make", makeDir);
|
|
writer.println(makeResult.output);
|
|
logMessage(makeResult.output);
|
|
|
|
// Run bake
|
|
writer.println("\n=== Bake Output ===");
|
|
logMessage("Running bake...");
|
|
|
|
ProcessResult bakeResult = runProcess("java -cp bakefile.jar fr.monlouyan.bakefile.Main", bakeDir);
|
|
writer.println(bakeResult.output);
|
|
logMessage(bakeResult.output);
|
|
|
|
// Compare results
|
|
logMessage("Comparing results...");
|
|
writer.println("\n=== Comparison Results ===");
|
|
|
|
// Compare exit codes
|
|
boolean exitCodesMatch = makeResult.exitCode == bakeResult.exitCode;
|
|
writer.println("Exit codes match: " + exitCodesMatch);
|
|
writer.println("Make exit code: " + makeResult.exitCode);
|
|
writer.println("Bake exit code: " + bakeResult.exitCode);
|
|
|
|
// Compare output patterns (ignoring the tool name differences)
|
|
boolean outputPatternsMatch = compareOutputPatterns(makeResult.output, bakeResult.output);
|
|
writer.println("Output patterns match: " + outputPatternsMatch);
|
|
|
|
// Compare final file state
|
|
writer.println("\n=== Final File State Comparison ===");
|
|
|
|
Map<String, FileInfo> makeFinalFiles = scanDirectory(makeDir);
|
|
Map<String, FileInfo> bakeFinalFiles = scanDirectory(bakeDir);
|
|
|
|
compareAndLogFiles(makeFinalFiles, bakeFinalFiles, writer);
|
|
|
|
// Check if files were created or modified as expected
|
|
boolean fileChangesMatch = compareFileChanges(makeFiles, makeFinalFiles, bakeFiles, bakeFinalFiles);
|
|
writer.println("File changes match: " + fileChangesMatch);
|
|
|
|
// Test summary
|
|
boolean testPassed = exitCodesMatch && outputPatternsMatch && fileChangesMatch;
|
|
writer.println("\n=== Test Result ===");
|
|
writer.println(testPassed ? "PASSED" : "FAILED");
|
|
|
|
logMessage(testPassed ? "Test PASSED" : "Test FAILED");
|
|
|
|
return testPassed;
|
|
|
|
} catch (IOException e) {
|
|
logMessage("Error running test: " + e.getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private boolean compareFileChanges(
|
|
Map<String, FileInfo> makeInitial,
|
|
Map<String, FileInfo> makeFinal,
|
|
Map<String, FileInfo> bakeInitial,
|
|
Map<String, FileInfo> bakeFinal) {
|
|
|
|
// Check if the same files were created in both directories
|
|
Set<String> makeCreated = new HashSet<>(makeFinal.keySet());
|
|
makeCreated.removeAll(makeInitial.keySet());
|
|
|
|
Set<String> bakeCreated = new HashSet<>(bakeFinal.keySet());
|
|
bakeCreated.removeAll(bakeInitial.keySet());
|
|
|
|
if (!makeCreated.equals(bakeCreated)) {
|
|
logMessage("Different files created:\nMake: " + makeCreated + "\nBake: " + bakeCreated);
|
|
return false;
|
|
}
|
|
|
|
// Check if the same files were modified
|
|
boolean filesMatch = true;
|
|
for (String file : makeInitial.keySet()) {
|
|
if (makeFinal.containsKey(file) && bakeInitial.containsKey(file) && bakeFinal.containsKey(file)) {
|
|
boolean makeModified = !makeInitial.get(file).equals(makeFinal.get(file));
|
|
boolean bakeModified = !bakeInitial.get(file).equals(bakeFinal.get(file));
|
|
|
|
if (makeModified != bakeModified) {
|
|
logMessage("File modification mismatch for " + file +
|
|
"\nMake modified: " + makeModified +
|
|
"\nBake modified: " + bakeModified);
|
|
filesMatch = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return filesMatch;
|
|
}
|
|
|
|
private ProcessResult runProcess(String command, File directory) throws IOException {
|
|
ProcessBuilder processBuilder = new ProcessBuilder("/bin/sh", "-c", command);
|
|
processBuilder.directory(directory);
|
|
Process process = processBuilder.start();
|
|
|
|
// Capture stdout and stderr
|
|
StringBuilder output = new StringBuilder();
|
|
try (BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
|
|
|
|
String line;
|
|
while ((line = stdInput.readLine()) != null) {
|
|
output.append(line).append("\n");
|
|
}
|
|
|
|
while ((line = stdError.readLine()) != null) {
|
|
output.append("ERROR: ").append(line).append("\n");
|
|
}
|
|
}
|
|
|
|
try {
|
|
process.waitFor();
|
|
} catch (InterruptedException e) {
|
|
Thread.currentThread().interrupt();
|
|
}
|
|
|
|
return new ProcessResult(process.exitValue(), output.toString());
|
|
}
|
|
|
|
private Map<String, FileInfo> scanDirectory(File directory) throws IOException {
|
|
Map<String, FileInfo> files = new HashMap<>();
|
|
|
|
if (!directory.exists() || !directory.isDirectory()) {
|
|
return files;
|
|
}
|
|
|
|
Files.walkFileTree(directory.toPath(), new SimpleFileVisitor<Path>() {
|
|
@Override
|
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
|
String relativePath = directory.toPath().relativize(file).toString();
|
|
|
|
// Skip bakefile.jar to avoid differences
|
|
if (relativePath.equals("bakefile.jar")) {
|
|
return FileVisitResult.CONTINUE;
|
|
}
|
|
|
|
FileInfo info = new FileInfo(
|
|
Files.isRegularFile(file),
|
|
attrs.size(),
|
|
attrs.lastModifiedTime().toMillis()
|
|
);
|
|
|
|
files.put(relativePath, info);
|
|
return FileVisitResult.CONTINUE;
|
|
}
|
|
});
|
|
|
|
return files;
|
|
}
|
|
|
|
private void compareAndLogFiles(Map<String, FileInfo> makeFiles,
|
|
Map<String, FileInfo> bakeFiles,
|
|
PrintWriter writer) {
|
|
Set<String> allFiles = new HashSet<>();
|
|
allFiles.addAll(makeFiles.keySet());
|
|
allFiles.addAll(bakeFiles.keySet());
|
|
|
|
List<String> sortedFiles = new ArrayList<>(allFiles);
|
|
Collections.sort(sortedFiles);
|
|
|
|
writer.println("File comparison:");
|
|
for (String file : sortedFiles) {
|
|
FileInfo makeInfo = makeFiles.get(file);
|
|
FileInfo bakeInfo = bakeFiles.get(file);
|
|
|
|
writer.print(file + ": ");
|
|
if (makeInfo == null) {
|
|
writer.println("Only in Bake");
|
|
} else if (bakeInfo == null) {
|
|
writer.println("Only in Make");
|
|
} else if (makeInfo.equals(bakeInfo)) {
|
|
writer.println("Identical");
|
|
} else {
|
|
writer.println("Different");
|
|
writer.println(" Make: " + makeInfo);
|
|
writer.println(" Bake: " + bakeInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean compareOutputPatterns(String makeOutput, String bakeOutput) {
|
|
// Normalize output by replacing tool-specific words
|
|
String normalizedMake = makeOutput.replaceAll("\\bmake\\b", "TOOL")
|
|
.replaceAll("\\bMake\\b", "TOOL")
|
|
.replaceAll("ERROR: ", "");
|
|
String normalizedBake = bakeOutput.replaceAll("\\bbake\\b", "TOOL")
|
|
.replaceAll("\\bBake\\b", "TOOL")
|
|
.replaceAll("ERROR: ", "");;
|
|
|
|
// Compare line by line, ignoring exact timestamps or specific paths
|
|
String[] makeLines = normalizedMake.split("\n");
|
|
String[] bakeLines = normalizedBake.split("\n");
|
|
|
|
// If line counts are very different, they're probably not matching
|
|
if (Math.abs(makeLines.length - bakeLines.length) > 2) {
|
|
logMessage("Output line count mismatch: Make=" + makeLines.length +
|
|
", Bake=" + bakeLines.length);
|
|
return false;
|
|
}
|
|
|
|
// Compare key patterns like error messages, file operations, etc.
|
|
Pattern errorPattern = Pattern.compile(".*Error.*|.*\\*\\*\\*.*|.*failed.*",
|
|
Pattern.CASE_INSENSITIVE);
|
|
Pattern commandPattern = Pattern.compile("^[a-z0-9_\\-]+ .*|^\\$.*");
|
|
|
|
List<String> makeErrors = extractMatches(makeLines, errorPattern);
|
|
List<String> bakeErrors = extractMatches(bakeLines, errorPattern);
|
|
|
|
List<String> makeCommands = extractMatches(makeLines, commandPattern);
|
|
List<String> bakeCommands = extractMatches(bakeLines, commandPattern);
|
|
|
|
// If error counts are different, that's a significant difference
|
|
if (makeErrors.size() != bakeErrors.size()) {
|
|
logMessage("Error count mismatch: Make=" + makeErrors.size() +
|
|
", Bake=" + bakeErrors.size());
|
|
return false;
|
|
}
|
|
|
|
// If command counts are different, that's a significant difference
|
|
if (makeCommands.size() != bakeCommands.size()) {
|
|
logMessage("Command count mismatch: Make=" + makeCommands.size() +
|
|
", Bake=" + bakeCommands.size());
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private List<String> extractMatches(String[] lines, Pattern pattern) {
|
|
return Arrays.stream(lines)
|
|
.filter(line -> pattern.matcher(line).matches())
|
|
.collect(Collectors.toList());
|
|
}
|
|
|
|
private void logMessage(String message) {
|
|
SwingUtilities.invokeLater(() -> {
|
|
logArea.append(message + "\n");
|
|
// Scroll to bottom
|
|
logArea.setCaretPosition(logArea.getDocument().getLength());
|
|
});
|
|
}
|
|
|
|
private static class TestInfo {
|
|
int row;
|
|
String language;
|
|
String testName;
|
|
|
|
TestInfo(int row, String language, String testName) {
|
|
this.row = row;
|
|
this.language = language;
|
|
this.testName = testName;
|
|
}
|
|
}
|
|
|
|
private static class FileInfo {
|
|
boolean isFile;
|
|
long size;
|
|
long lastModified;
|
|
|
|
FileInfo(boolean isFile, long size, long lastModified) {
|
|
this.isFile = isFile;
|
|
this.size = size;
|
|
this.lastModified = lastModified;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (!(obj instanceof FileInfo)) {
|
|
return false;
|
|
}
|
|
FileInfo other = (FileInfo) obj;
|
|
return isFile == other.isFile && size == other.size;
|
|
// We don't compare lastModified times directly
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "isFile=" + isFile + ", size=" + size + ", lastModified=" +
|
|
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(lastModified));
|
|
}
|
|
}
|
|
|
|
private static class ProcessResult {
|
|
int exitCode;
|
|
String output;
|
|
|
|
ProcessResult(int exitCode, String output) {
|
|
this.exitCode = exitCode;
|
|
this.output = output;
|
|
}
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
SwingUtilities.invokeLater(() -> {
|
|
try {
|
|
// Set native look and feel
|
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
BakeTestRunner runner = new BakeTestRunner();
|
|
runner.setVisible(true);
|
|
});
|
|
}
|
|
} |