import java.util.*; /** * Unit test for cmake-0006: FinishWritingSource writtenSettings O(S^2) -> O(S). * * Models the dedup logic: for each (config, setting) pair, skip if already written. * Defect: std::find over vector grows O(S) per check -> O(C * S^2) total. * Fix: unordered_set -> O(1) per check -> O(C * S) total. */ public class WrittenSettingsAlgorithm { static final int CONFIGS = 4; static final int SETTINGS_PER_CONFIG = 30; // Simulate settings: each config has same setting names (all should dedup after first config) static Map> buildToolSettings() { Map> toolSettings = new LinkedHashMap<>(); for (int c = 0; c < CONFIGS; c++) { String config = "Config" + c; Map settings = new LinkedHashMap<>(); for (int s = 0; s < SETTINGS_PER_CONFIG; s++) { settings.put("Setting" + s, "Value" + c + "_" + s); } toolSettings.put(config, settings); } return toolSettings; } // --- Defective: std::find over vector --- static long finishWritingSourceDefective(Map> toolSettings) { List writtenSettings = new ArrayList<>(); long ops = 0; for (Map.Entry> configEntry : toolSettings.entrySet()) { for (Map.Entry setting : configEntry.getValue().entrySet()) { // O(S) linear scan -- the defect for (String ws : writtenSettings) { ops++; if (ws.equals(setting.getKey())) break; } if (!writtenSettings.contains(setting.getKey())) { writtenSettings.add(setting.getKey()); } } } return ops; } // --- Fixed: unordered_set --- static long finishWritingSourceFixed(Map> toolSettings) { Set writtenSettings = new HashSet<>(); long ops = 0; for (Map.Entry> configEntry : toolSettings.entrySet()) { for (Map.Entry setting : configEntry.getValue().entrySet()) { ops++; // O(1) hash check if (!writtenSettings.contains(setting.getKey())) { writtenSettings.add(setting.getKey()); } } } return ops; } // --- Correctness: both produce same written set --- static void testCorrectness() { Map> toolSettings = buildToolSettings(); Set defectWritten = new HashSet<>(); List defectList = new ArrayList<>(); for (Map.Entry> ce : toolSettings.entrySet()) { for (Map.Entry s : ce.getValue().entrySet()) { if (!defectList.contains(s.getKey())) defectList.add(s.getKey()); } } defectWritten.addAll(defectList); Set fixedWritten = new HashSet<>(); for (Map.Entry> ce : toolSettings.entrySet()) { for (Map.Entry s : ce.getValue().entrySet()) { fixedWritten.add(s.getKey()); } } if (!defectWritten.equals(fixedWritten)) { throw new AssertionError("Written sets differ: defect=" + defectWritten.size() + " fixed=" + fixedWritten.size()); } if (fixedWritten.size() != SETTINGS_PER_CONFIG) { throw new AssertionError("Expected " + SETTINGS_PER_CONFIG + " unique settings, got " + fixedWritten.size()); } System.out.println("PASS testCorrectness (written set matches, size=" + fixedWritten.size() + ")"); } static void testBenchmark() { Map> toolSettings = buildToolSettings(); long defectOps = finishWritingSourceDefective(toolSettings); long fixedOps = finishWritingSourceFixed(toolSettings); double ratio = (double) defectOps / fixedOps; System.out.printf("BENCH finishWritingSource C=%d S=%d: defective=%d ops, fixed=%d ops, ratio=%.1fx%n", CONFIGS, SETTINGS_PER_CONFIG, defectOps, fixedOps, ratio); if (ratio < 3.0) { throw new AssertionError("Expected ratio >= 3x, got " + ratio); } System.out.println("PASS testBenchmark (ratio >= 3x confirmed)"); } public static void main(String[] args) { testCorrectness(); testBenchmark(); System.out.println("ALL PASS cmake-0006 WrittenSettings"); } }