import java.util.*; /** * CWE-407 unit tests for VS Code defects. * * vscode-0001: extensionGalleryService getExtensions uuid dedup O(N×M) * vscode-0002: abstractExtensionManagementService getAllDepsAndPacks O(D²) * vscode-0003: userDataSync merge compare() O(N×M) array includes (8 sites) * vscode-0004: configurationModels override identifiers O(N×M) */ public class VscodeTest { // --------------------------------------------------------------- // vscode-0001: gallery uuid includes O(N×M) // --------------------------------------------------------------- /** BEFORE: uuids array with Array.includes() — O(N×M) */ static int galleryUuidBefore(List extensionUuids, List resultUuids) { int ops = 0; // const uuids = result.map(r => r.identifier.uuid); // array for (String uuid : extensionUuids) { // uuids.includes(e.uuid) for (String r : resultUuids) { ops++; if (r.equals(uuid)) break; } } return ops; } /** AFTER: uuids Set with Set.has() — O(N+M) */ static int galleryUuidAfter(List extensionUuids, List resultUuids) { int ops = 0; Set uuidSet = new HashSet<>(resultUuids); ops += resultUuids.size(); // set construction for (String uuid : extensionUuids) { ops++; // set lookup O(1) uuidSet.contains(uuid); } return ops; } // --------------------------------------------------------------- // vscode-0002: getAllDepsAndPacks includes O(D²) // --------------------------------------------------------------- /** BEFORE: allDepsOrPacks.includes() in recursive traversal — O(D²) */ static int depsScanBefore(List depChain) { int ops = 0; List allDeps = new ArrayList<>(); for (String id : depChain) { // allDepsOrPacks.includes(id.toLowerCase()) boolean found = false; for (String existing : allDeps) { ops++; if (existing.equals(id)) { found = true; break; } } if (!found) allDeps.add(id); } return ops; } /** AFTER: Set for seen-check — O(D) */ static int depsScanAfter(List depChain) { int ops = 0; Set seen = new HashSet<>(); List allDeps = new ArrayList<>(); for (String id : depChain) { ops++; // set lookup if (!seen.contains(id)) { seen.add(id); allDeps.add(id); } } return ops; } // --------------------------------------------------------------- // vscode-0003: sync merge compare() — filter+includes O(N×M) // --------------------------------------------------------------- /** BEFORE: fromKeys.filter(key => !toKeys.includes(key)) — O(N×M) */ static int mergeCompareBefore(List fromKeys, List toKeys) { int ops = 0; // added = toKeys.filter(key => !fromKeys.includes(key)) for (String key : toKeys) { for (String fk : fromKeys) { ops++; if (fk.equals(key)) break; } } // removed = fromKeys.filter(key => !toKeys.includes(key)) for (String key : fromKeys) { for (String tk : toKeys) { ops++; if (tk.equals(key)) break; } } return ops; } /** AFTER: Set lookup — O(N+M) */ static int mergeCompareAfter(List fromKeys, List toKeys) { int ops = 0; Set fromSet = new HashSet<>(fromKeys); ops += fromKeys.size(); Set toSet = new HashSet<>(toKeys); ops += toKeys.size(); for (String key : toKeys) { ops++; fromSet.contains(key); } for (String key : fromKeys) { ops++; toSet.contains(key); } return ops; } // --------------------------------------------------------------- // vscode-0004: config override identifiers — filter+includes O(N×M) // --------------------------------------------------------------- /** BEFORE: overrideIdentifiers.filter + includes — O(N²) */ static int configOverrideBefore(List fromIds, List toIds) { int ops = 0; // addedOverrideIdentifiers = toIds.filter(key => !fromIds.includes(key)) for (String key : toIds) { for (String fk : fromIds) { ops++; if (fk.equals(key)) break; } } // removedOverrideIdentifiers = fromIds.filter(key => !toIds.includes(key)) for (String key : fromIds) { for (String tk : toIds) { ops++; if (tk.equals(key)) break; } } // inner loop: toOverrideIdentifiers.includes(identifier) for (String id : fromIds) { for (String tk : toIds) { ops++; if (tk.equals(id)) break; } } return ops; } /** AFTER: Set lookups — O(N+M) */ static int configOverrideAfter(List fromIds, List toIds) { int ops = 0; Set fromSet = new HashSet<>(fromIds); ops += fromIds.size(); Set toSet = new HashSet<>(toIds); ops += toIds.size(); for (String key : toIds) { ops++; fromSet.contains(key); } for (String key : fromIds) { ops++; toSet.contains(key); } for (String id : fromIds) { ops++; toSet.contains(id); } return ops; } // --------------------------------------------------------------- // Main: run all tests // --------------------------------------------------------------- public static void main(String[] args) { int pass = 0, fail = 0; // --- vscode-0001: gallery uuid --- { int N = 200; List extUuids = new ArrayList<>(); List resultUuids = new ArrayList<>(); for (int i = 0; i < N; i++) { extUuids.add("ext-" + i); resultUuids.add("res-" + i); // disjoint = worst case } int before = galleryUuidBefore(extUuids, resultUuids); int after = galleryUuidAfter(extUuids, resultUuids); double ratio = (double) before / after; boolean ok = ratio > 10; System.out.printf("vscode-0001 gallery-uuid N=%d before=%d after=%d ratio=%.1fx %s%n", N, before, after, ratio, ok ? "PASS" : "FAIL"); if (ok) pass++; else fail++; } // --- vscode-0002: deps scan --- { int D = 100; List deps = new ArrayList<>(); for (int i = 0; i < D; i++) deps.add("dep-" + i); int before = depsScanBefore(deps); int after = depsScanAfter(deps); double ratio = (double) before / after; boolean ok = ratio > 10; System.out.printf("vscode-0002 deps-scan D=%d before=%d after=%d ratio=%.1fx %s%n", D, before, after, ratio, ok ? "PASS" : "FAIL"); if (ok) pass++; else fail++; } // --- vscode-0003: sync merge compare --- { int N = 500; List fromKeys = new ArrayList<>(); List toKeys = new ArrayList<>(); for (int i = 0; i < N; i++) { fromKeys.add("setting-" + i); toKeys.add("setting-" + (i + N)); // disjoint = worst case } int before = mergeCompareBefore(fromKeys, toKeys); int after = mergeCompareAfter(fromKeys, toKeys); double ratio = (double) before / after; boolean ok = ratio > 50; System.out.printf("vscode-0003 sync-merge-compare N=%d before=%d after=%d ratio=%.1fx %s%n", N, before, after, ratio, ok ? "PASS" : "FAIL"); if (ok) pass++; else fail++; } // --- vscode-0004: config override identifiers --- { int N = 30; List fromIds = new ArrayList<>(); List toIds = new ArrayList<>(); for (int i = 0; i < N; i++) { fromIds.add("[lang-" + i + "]"); toIds.add("[lang-" + (i + N) + "]"); // disjoint } int before = configOverrideBefore(fromIds, toIds); int after = configOverrideAfter(fromIds, toIds); double ratio = (double) before / after; boolean ok = ratio > 5; System.out.printf("vscode-0004 config-overrides N=%d before=%d after=%d ratio=%.1fx %s%n", N, before, after, ratio, ok ? "PASS" : "FAIL"); if (ok) pass++; else fail++; } System.out.printf("%n%d/%d PASS%n", pass, pass + fail); if (fail > 0) System.exit(1); } }