java-topology/defects/wolfssl/unit/WolfSslAlpnFindTest.java

143 lines
5.9 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.

package unit;
import java.util.HashMap;
/**
* wolfssl-0001 unit test
*
* Models the O(C×S) ALPN selection in ALPN_find_match() / TLSX_ALPN_Find()
* and the O(C+S) fixed version using a hash set of server names.
*
* Compile: javac -d . WolfSslAlpnFindTest.java
* Run: java unit.WolfSslAlpnFindTest
*/
public class WolfSslAlpnFindTest {
// ------------------------------------------------------------------ //
// Model TLSX_ALPN_Find: O(S) linear scan of server linked list //
// ------------------------------------------------------------------ //
static String tlsxAlpnFind(String[] serverList, String name) {
for (String s : serverList) {
if (s.length() == name.length() && s.equals(name))
return s;
}
return null;
}
// ------------------------------------------------------------------ //
// DEFECTIVE: O(C × S) — ALPN_find_match calls TLSX_ALPN_Find(O(S)) //
// for each of C client-offered names //
// ------------------------------------------------------------------ //
static String defectiveMatch(String[] serverList, String[] clientNames) {
// Outer: iterate client list (wolfSSL uses client-preference order)
for (String clientName : clientNames) {
// Inner: TLSX_ALPN_Find — O(S) scan
String found = tlsxAlpnFind(serverList, clientName);
if (found != null) return found;
}
return null;
}
// ------------------------------------------------------------------ //
// FIXED: O(C + S) — hash set of server names, O(1) lookup //
// ------------------------------------------------------------------ //
static String fixedMatch(String[] serverList, String[] clientNames) {
// Build hash set of server names — O(S)
HashMap<String, String> serverSet = new HashMap<>();
for (String s : serverList) serverSet.put(s, s);
// Iterate client list — O(C), each lookup O(1) expected
for (String clientName : clientNames) {
String found = serverSet.get(clientName);
if (found != null) return found;
}
return null;
}
// ------------------------------------------------------------------ //
// Counting versions //
// ------------------------------------------------------------------ //
static long[] ops = new long[2];
static String defectiveCounting(String[] serverList, String[] clientNames) {
for (String cn : clientNames) {
for (String sn : serverList) {
ops[0]++;
if (sn.equals(cn)) return sn;
}
}
return null;
}
static String fixedCounting(String[] serverList, String[] clientNames) {
HashMap<String, String> ss = new HashMap<>();
for (String s : serverList) { ops[1]++; ss.put(s, s); }
for (String cn : clientNames) {
ops[1]++;
String found = ss.get(cn);
if (found != null) return found;
}
return null;
}
static int pass = 0, fail = 0;
static void check(String label, boolean cond) {
if (cond) { System.out.println(" PASS " + label); pass++; }
else { System.out.println(" FAIL " + label); fail++; }
}
public static void main(String[] args) {
System.out.println("=== wolfssl-0001: ALPN_find_match O(C×S) defect ===\n");
// wolfSSL uses client-preference order (matches first client name found in server)
String[] server = {"h2", "http/1.1", "grpc"};
// Test 1: first client name matches server
String[] client1 = {"h2", "ftp"};
check("defective: match h2", "h2".equals(defectiveMatch(server, client1)));
check("fixed: match h2", "h2".equals(fixedMatch(server, client1)));
// Test 2: second client name matches
String[] client2 = {"ftp", "grpc"};
check("defective: match grpc", "grpc".equals(defectiveMatch(server, client2)));
check("fixed: match grpc", "grpc".equals(fixedMatch(server, client2)));
// Test 3: client-preference wins (wolfSSL: first matching client entry)
String[] client3 = {"grpc", "h2"};
check("defective: client-pref → grpc", "grpc".equals(defectiveMatch(server, client3)));
check("fixed: client-pref → grpc", "grpc".equals(fixedMatch(server, client3)));
// Test 4: no match
String[] client4 = {"smtp", "pop3"};
check("defective: no match → null", defectiveMatch(server, client4) == null);
check("fixed: no match → null", fixedMatch(server, client4) == null);
// Test 5: complexity — adversarial client list
int S = 5;
int C = 400;
String[] bigServer = new String[S];
for (int i = 0; i < S; i++) bigServer[i] = "proto-server-" + i;
String[] bigClient = new String[C];
for (int i = 0; i < C - 1; i++) bigClient[i] = "proto-client-" + i;
bigClient[C - 1] = bigServer[S - 1]; // match at end — worst case
ops[0] = 0; ops[1] = 0;
String rd = defectiveCounting(bigServer, bigClient);
String rf = fixedCounting(bigServer, bigClient);
System.out.println("\n Complexity comparison (S=" + S + ", C=" + C + "):");
System.out.println(" Defective ops: " + ops[0] + " (expected ~" + ((long)(C-1)*S + 1) + ")");
System.out.println(" Fixed ops: " + ops[1] + " (expected ~" + (S + C) + ")");
System.out.printf(" Speedup: %.1fx%n", (double) ops[0] / ops[1]);
check("defective and fixed agree on result",
java.util.Objects.equals(rd, rf));
check("defective ops > 4x fixed ops (quadratic vs linear)",
ops[0] > 4 * ops[1]);
System.out.println("\n--- " + (pass + fail) + " tests: " + pass + " passed, " + fail + " failed ---");
if (fail > 0) System.exit(1);
}
}