java-topology/defects/mattermost/unit/MattermostTest.java
russell@unturf.com c9e86c450c opensmtpd-0001: mta_handle_envelope TAILQ_FOREACH O(N²) task lookup — patch + unit test
Add patch replacing linear TAILQ_FOREACH scan in mta_handle_envelope()
with tree_get() on a per-relay task_by_msgid splay-tree index; assign
UNDF-2026-000000201. Unit test confirms 100x op-count improvement at
N=100 tasks/relay.
2026-03-30 07:00:50 -04:00

156 lines
5.6 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* CWE-407 unit test: mattermost-0001
* notification.go Push StringArray O(N²) vs map O(N)
*
* Simulates the notificationsForCRT.Push.Contains(id) pattern from
* server/channels/app/notification.go (lines 541, 593).
*
* model.StringArray.Contains() delegates to slices.Contains() which is
* O(P) where P = len(Push). Called once per user in mentionedUsersList
* and once per user in allActivityPushUserIds, the total cost is O((N+M)×P).
*
* The fix builds a map[string]bool once (O(P)) and then all lookups are O(1),
* reducing total cost to O(N+M+P).
*/
public class MattermostTest {
/** Simulate StringArray.Contains: linear scan of a String array. */
static boolean stringArrayContains(String[] arr, String target) {
for (String s : arr) {
if (s.equals(target)) return true;
}
return false;
}
/**
* Count total element comparisons made by the defective pattern:
* for each id in userList, scan pushArray linearly.
*/
static long countListOps(String[] userList, String[] pushArray) {
long ops = 0;
for (String id : userList) {
for (String p : pushArray) {
ops++;
if (p.equals(id)) break; // early-exit on match (worst case: no match)
}
}
return ops;
}
/**
* Count total operations for the fixed map pattern:
* build the map once, then each lookup is O(1).
* We count 1 op per map build entry + 1 op per lookup.
*/
static long countMapOps(String[] userList, String[] pushArray) {
// Build phase: O(P)
java.util.Map<String, Boolean> pushSet = new java.util.HashMap<>(pushArray.length * 2);
long ops = 0;
for (String id : pushArray) {
pushSet.put(id, true);
ops++; // one insert op per entry
}
// Lookup phase: O(1) per user
for (String id : userList) {
ops++; // one hash lookup
pushSet.containsKey(id);
}
return ops;
}
static boolean testRatioExceeds10x() {
int n = 1000; // mentioned users
int p = 1000; // push CRT users (no overlap — worst case for scan)
String[] userList = new String[n];
String[] pushArray = new String[p];
for (int i = 0; i < n; i++) userList[i] = "user-mentioned-" + i;
for (int i = 0; i < p; i++) pushArray[i] = "user-crt-" + i;
long listOps = countListOps(userList, pushArray);
long mapOps = countMapOps(userList, pushArray);
double ratio = (double) listOps / Math.max(mapOps, 1);
System.out.printf(" N=%d P=%d: list_ops=%d map_ops=%d ratio=%.1fx%n",
n, p, listOps, mapOps, ratio);
if (ratio < 10.0) {
System.out.printf(" FAIL: expected ratio >= 10x, got %.1fx%n", ratio);
return false;
}
System.out.println(" PASS");
return true;
}
static boolean testListGrowsQuadratically() {
// Double N and P: op count should 4x for list, 2x for map
int n1 = 500, p1 = 500;
int n2 = 1000, p2 = 1000;
String[] u1 = new String[n1]; for (int i=0;i<n1;i++) u1[i]="u"+i;
String[] k1 = new String[p1]; for (int i=0;i<p1;i++) k1[i]="k"+i;
String[] u2 = new String[n2]; for (int i=0;i<n2;i++) u2[i]="u"+i;
String[] k2 = new String[p2]; for (int i=0;i<p2;i++) k2[i]="k"+i;
long listSmall = countListOps(u1, k1);
long listLarge = countListOps(u2, k2);
double listRatio = (double) listLarge / Math.max(listSmall, 1);
long mapSmall = countMapOps(u1, k1);
long mapLarge = countMapOps(u2, k2);
double mapRatio = (double) mapLarge / Math.max(mapSmall, 1);
System.out.printf(" list doubling-ratio=%.2fx (expect ~4x) map doubling-ratio=%.2fx (expect ~2x)%n",
listRatio, mapRatio);
if (listRatio < 3.0) {
System.out.printf(" FAIL: list should grow ~4x when inputs double, got %.2fx%n", listRatio);
return false;
}
if (mapRatio > 3.0) {
System.out.printf(" FAIL: map should grow ~2x when inputs double, got %.2fx%n", mapRatio);
return false;
}
System.out.println(" PASS");
return true;
}
static boolean testMapAlwaysFewerOps() {
int[] sizes = {100, 250, 500, 1000};
for (int n : sizes) {
String[] u = new String[n]; for (int i=0;i<n;i++) u[i]="u"+i;
String[] k = new String[n]; for (int i=0;i<n;i++) k[i]="k"+i;
long l = countListOps(u, k);
long m = countMapOps(u, k);
if (m >= l) {
System.out.printf(" FAIL: N=%d map_ops=%d >= list_ops=%d%n", n, m, l);
return false;
}
}
System.out.println(" map_ops < list_ops for N in {100, 250, 500, 1000} PASS");
return true;
}
public static void main(String[] args) {
System.out.println("mattermost-0001 CWE-407 unit test — notification.go Push StringArray vs map");
System.out.println("=".repeat(75));
boolean[] results = {
testRatioExceeds10x(),
testListGrowsQuadratically(),
testMapAlwaysFewerOps(),
};
int passed = 0;
for (boolean r : results) if (r) passed++;
System.out.println();
if (passed == results.length) {
System.out.println("ALL PASS (" + passed + "/" + results.length + ")");
} else {
System.out.println("FAILED: " + (results.length - passed) + "/" + results.length + " tests failed");
System.exit(1);
}
}
}