package unit; import java.util.HashMap; import java.util.Map; /** * CWE-407 unit test: VLC module_find() / module_exists() * * Slow path: O(N) linear scan over full module list (mirrors module_find). * Fast path: O(1) HashMap lookup (proposed name-indexed hash). * * Scenario mirrors aout_New(): 6 sequential module_exists() calls. * Assert: slowOps > fastOps * 30x at N=500 modules. */ public class VlcModuleFindTest { static long slowOps = 0; static long fastOps = 0; // ---- SLOW: linear scan (mirrors module_find) ---- static String[] buildModuleList(int n) { String[] modules = new String[n]; for (int i = 0; i < n; i++) modules[i] = "module_" + i; // Put the target names at the end to force worst-case scan modules[n - 6] = "goom"; modules[n - 5] = "projectm"; modules[n - 4] = "vsxu"; modules[n - 3] = "glspectrum"; modules[n - 2] = "equalizer"; modules[n - 1] = "spatialaudio"; return modules; } static boolean slow_module_exists(String[] modules, String name) { for (String m : modules) { slowOps++; if (m.equals(name)) return true; } return false; } // ---- FAST: hash map lookup ---- static Map buildNameHash(String[] modules) { Map map = new HashMap<>(); for (String m : modules) { fastOps++; // build cost map.put(m, Boolean.TRUE); } return map; } static boolean fast_module_exists(Map map, String name) { fastOps++; return map.containsKey(name); } // Simulate aout_New(): 6 sequential module_exists() calls static final String[] AOUT_CHECKS = { "goom", "projectm", "vsxu", "glspectrum", "equalizer", "spatialaudio" }; public static void main(String[] args) { final int N = 500; final int Nx = 30; // assert slowOps > fastOps * Nx String[] modules = buildModuleList(N); slowOps = 0; fastOps = 0; // Slow: 6 linear scans per aout_New, called SESSIONS times (e.g. playlist) // Each call to module_exists triggers a fresh scan of all N modules. final int SESSIONS = 20; // 20 audio output creations in a session for (int s = 0; s < SESSIONS; s++) { for (String check : AOUT_CHECKS) { boolean found = slow_module_exists(modules, check); if (!found) { System.out.println("FAIL slow did not find: " + check); System.exit(1); } } } // Fast: one build + 6 hash lookups per session (index is persistent) Map map = buildNameHash(modules); for (int s = 0; s < SESSIONS; s++) { for (String check : AOUT_CHECKS) { boolean found = fast_module_exists(map, check); if (!found) { System.out.println("FAIL fast did not find: " + check); System.exit(1); } } } System.out.printf("vlc-0001: slowOps=%d fastOps=%d ratio=%.1f%n", slowOps, fastOps, (double) slowOps / fastOps); if (slowOps <= fastOps * Nx) { System.out.printf("FAIL: expected slowOps > fastOps * %d%n", Nx); System.exit(1); } System.out.printf("1/1 PASS (slowOps=%d > fastOps*%d=%d)%n", slowOps, Nx, fastOps * Nx); } }