import java.util.*; /** * CWE-407 unit tests for element-web (Matrix client) defects. * * element-web-0001: TextForEvent.tsx textForPowerEvent() * users array + indexOf for dedup -> O(U^2) * Fix: Set-based dedup -> O(U) * * element-web-0002: TextForEvent.tsx textForPinnedEvent() * previouslyPinned.indexOf inside filter -> O(P*Q) * Fix: Set.has() inside filter -> O(P+Q) * * element-web-0003: TextForEvent.tsx textForCanonicalAliasEvent() * oldAltAliases.filter(a => !newAltAliases.includes(a)) -> O(A*B) * Fix: Set.has() inside filter -> O(A+B) * * element-web-0004: utils/arrays.ts arrayDiff() and arrayIntersection() * b.filter(i => !a.includes(i)) -> O(A*B) * Fix: new Set(a) then setA.has() -> O(A+B) */ public class ElementWebTest { // --- element-web-0001: user dedup --- static List deduplicateUsersArray(String[] current, String[] previous) { List users = new ArrayList<>(); for (String u : current) { if (!users.contains(u)) users.add(u); // O(U) per user } for (String u : previous) { if (!users.contains(u)) users.add(u); } return users; } static List deduplicateUsersSet(String[] current, String[] previous) { Set seen = new LinkedHashSet<>(); // preserves insertion order for (String u : current) seen.add(u); for (String u : previous) seen.add(u); return new ArrayList<>(seen); } static void testElementWeb0001() throws Exception { int U = 1000; String[] current = new String[U]; String[] previous = new String[U]; for (int i = 0; i < U; i++) { current[i] = "@user" + i + ":matrix.org"; previous[i] = "@user" + (i + U / 2) + ":matrix.org"; // partial overlap } // correctness List rArr = deduplicateUsersArray(current, previous); List rSet = deduplicateUsersSet(current, previous); Collections.sort(rArr); Collections.sort(rSet); assert rArr.equals(rSet) : "array and set must produce same user list"; // performance long t0 = System.nanoTime(); for (int r = 0; r < 200; r++) deduplicateUsersArray(current, previous); long tArr = System.nanoTime() - t0; t0 = System.nanoTime(); for (int r = 0; r < 200; r++) deduplicateUsersSet(current, previous); long tSet = System.nanoTime() - t0; double ratio = (double) tArr / tSet; System.out.printf("element-web-0001: array=%.3fs set=%.3fs ratio=%.1f×%n", tArr / 1e9, tSet / 1e9, ratio); assert ratio > 10 : "Expected >10x speedup, got " + ratio; System.out.println("PASS element-web-0001"); } // --- element-web-0002: pinned messages filter --- static List newlyPinnedIndexOf(List pinned, List previouslyPinned) { List result = new ArrayList<>(); for (String item : pinned) { if (!previouslyPinned.contains(item)) result.add(item); // O(P) per item } return result; } static List newlyPinnedSet(List pinned, List previouslyPinned) { Set prevSet = new HashSet<>(previouslyPinned); // O(1) lookup List result = new ArrayList<>(); for (String item : pinned) { if (!prevSet.contains(item)) result.add(item); } return result; } static void testElementWeb0002() throws Exception { int P = 1000; List pinned = new ArrayList<>(); List previouslyPinned = new ArrayList<>(); for (int i = 0; i < P; i++) { pinned.add("$event" + i); previouslyPinned.add("$event" + (i + P / 2)); } // correctness List r1 = newlyPinnedIndexOf(pinned, previouslyPinned); List r2 = newlyPinnedSet(pinned, previouslyPinned); Collections.sort(r1); Collections.sort(r2); assert r1.equals(r2) : "indexOf and set paths must agree"; // performance long t0 = System.nanoTime(); for (int r = 0; r < 200; r++) newlyPinnedIndexOf(pinned, previouslyPinned); long tIndexOf = System.nanoTime() - t0; t0 = System.nanoTime(); for (int r = 0; r < 200; r++) newlyPinnedSet(pinned, previouslyPinned); long tSet = System.nanoTime() - t0; double ratio = (double) tIndexOf / tSet; System.out.printf("element-web-0002: indexOf=%.3fs set=%.3fs ratio=%.1f×%n", tIndexOf / 1e9, tSet / 1e9, ratio); assert ratio > 5 : "Expected >5x speedup, got " + ratio; System.out.println("PASS element-web-0002"); } // --- element-web-0003: canonical alias alt_aliases diff --- static List removedAliasesIncludes(List oldAlt, List newAlt) { List removed = new ArrayList<>(); for (String alias : oldAlt) { if (!newAlt.contains(alias)) removed.add(alias); // O(N) per alias } return removed; } static List addedAliasesIncludes(List oldAlt, List newAlt) { List added = new ArrayList<>(); for (String alias : newAlt) { if (!oldAlt.contains(alias)) added.add(alias); } return added; } static List removedAliasesSet(List oldAlt, List newAlt) { Set newSet = new HashSet<>(newAlt); List removed = new ArrayList<>(); for (String alias : oldAlt) { if (!newSet.contains(alias)) removed.add(alias); // O(1) per alias } return removed; } static List addedAliasesSet(List oldAlt, List newAlt) { Set oldSet = new HashSet<>(oldAlt); List added = new ArrayList<>(); for (String alias : newAlt) { if (!oldSet.contains(alias)) added.add(alias); } return added; } static void testElementWeb0003() throws Exception { int A = 1000; List oldAlt = new ArrayList<>(); List newAlt = new ArrayList<>(); for (int i = 0; i < A; i++) { oldAlt.add("#alias" + i + ":matrix.org"); newAlt.add("#alias" + (i + A / 2) + ":matrix.org"); } // correctness List removedArr = removedAliasesIncludes(oldAlt, newAlt); List removedSet = removedAliasesSet(oldAlt, newAlt); Collections.sort(removedArr); Collections.sort(removedSet); assert removedArr.equals(removedSet) : "removed aliases must agree"; List addedArr = addedAliasesIncludes(oldAlt, newAlt); List addedSetR = addedAliasesSet(oldAlt, newAlt); Collections.sort(addedArr); Collections.sort(addedSetR); assert addedArr.equals(addedSetR) : "added aliases must agree"; // performance long t0 = System.nanoTime(); for (int r = 0; r < 200; r++) { removedAliasesIncludes(oldAlt, newAlt); addedAliasesIncludes(oldAlt, newAlt); } long tArr = System.nanoTime() - t0; t0 = System.nanoTime(); for (int r = 0; r < 200; r++) { removedAliasesSet(oldAlt, newAlt); addedAliasesSet(oldAlt, newAlt); } long tSet = System.nanoTime() - t0; double ratio = (double) tArr / tSet; System.out.printf("element-web-0003: includes=%.3fs set=%.3fs ratio=%.1f×%n", tArr / 1e9, tSet / 1e9, ratio); assert ratio > 5 : "Expected >5x speedup, got " + ratio; System.out.println("PASS element-web-0003"); } // --- element-web-0004: arrayDiff + arrayIntersection --- static Map> arrayDiffIncludes(List a, List b) { List added = new ArrayList<>(); for (String i : b) { if (!a.contains(i)) added.add(i); // O(A) per element } List removed = new ArrayList<>(); for (String i : a) { if (!b.contains(i)) removed.add(i); // O(B) per element } Map> result = new HashMap<>(); result.put("added", added); result.put("removed", removed); return result; } static Map> arrayDiffSet(List a, List b) { Set setA = new HashSet<>(a); Set setB = new HashSet<>(b); List added = new ArrayList<>(); for (String i : b) { if (!setA.contains(i)) added.add(i); // O(1) per element } List removed = new ArrayList<>(); for (String i : a) { if (!setB.contains(i)) removed.add(i); } Map> result = new HashMap<>(); result.put("added", added); result.put("removed", removed); return result; } static List arrayIntersectionIncludes(List a, List b) { List result = new ArrayList<>(); for (String i : a) { if (b.contains(i)) result.add(i); // O(B) per element } return result; } static List arrayIntersectionSet(List a, List b) { Set setB = new HashSet<>(b); List result = new ArrayList<>(); for (String i : a) { if (setB.contains(i)) result.add(i); // O(1) per element } return result; } static void testElementWeb0004() throws Exception { int N = 1000; List a = new ArrayList<>(); List b = new ArrayList<>(); for (int i = 0; i < N; i++) { a.add("room_" + i); b.add("room_" + (i + N / 2)); } // correctness: arrayDiff Map> d1 = arrayDiffIncludes(a, b); Map> d2 = arrayDiffSet(a, b); List added1 = new ArrayList<>(d1.get("added")); Collections.sort(added1); List added2 = new ArrayList<>(d2.get("added")); Collections.sort(added2); assert added1.equals(added2) : "arrayDiff added must agree"; List rem1 = new ArrayList<>(d1.get("removed")); Collections.sort(rem1); List rem2 = new ArrayList<>(d2.get("removed")); Collections.sort(rem2); assert rem1.equals(rem2) : "arrayDiff removed must agree"; // correctness: arrayIntersection List i1 = arrayIntersectionIncludes(a, b); List i2 = arrayIntersectionSet(a, b); Collections.sort(i1); Collections.sort(i2); assert i1.equals(i2) : "arrayIntersection must agree"; // performance: arrayDiff long t0 = System.nanoTime(); for (int r = 0; r < 200; r++) arrayDiffIncludes(a, b); long tInc = System.nanoTime() - t0; t0 = System.nanoTime(); for (int r = 0; r < 200; r++) arrayDiffSet(a, b); long tSet = System.nanoTime() - t0; double ratio = (double) tInc / tSet; System.out.printf("element-web-0004-diff: includes=%.3fs set=%.3fs ratio=%.1f×%n", tInc / 1e9, tSet / 1e9, ratio); assert ratio > 5 : "Expected >5x speedup for arrayDiff, got " + ratio; // performance: arrayIntersection t0 = System.nanoTime(); for (int r = 0; r < 200; r++) arrayIntersectionIncludes(a, b); tInc = System.nanoTime() - t0; t0 = System.nanoTime(); for (int r = 0; r < 200; r++) arrayIntersectionSet(a, b); tSet = System.nanoTime() - t0; double ratio2 = (double) tInc / tSet; System.out.printf("element-web-0004-intersect: includes=%.3fs set=%.3fs ratio=%.1f×%n", tInc / 1e9, tSet / 1e9, ratio2); assert ratio2 > 5 : "Expected >5x speedup for arrayIntersection, got " + ratio2; System.out.println("PASS element-web-0004"); } public static void main(String[] args) throws Exception { testElementWeb0001(); testElementWeb0002(); testElementWeb0003(); testElementWeb0004(); System.out.println("ALL PASS"); } }