import java.util.*; /** * CWE-407 unit tests for Quarkus. * * quarkus-0001: BeanInfo.getBoundInterceptors() * independent-projects/arc/processor/.../BeanInfo.java * Builds deduplicated interceptor list using ArrayList.contains() inside * nested loops over lifecycle+method interceptions. * Complexity: O(M * I^2) where M = intercepted methods, I = interceptors. * Fix: LinkedHashSet for O(1) dedup → O(M * I). * * quarkus-0002: BeanInfo.getBoundDecorators() * Same file. ArrayList.contains(dm.decorator) inside loop over decorated methods. * Complexity: O(M * D^2) where M = decorated methods, D = decorators. * Fix: LinkedHashSet for O(1) dedup → O(M * D). * * quarkus-0003: RuntimeUpdatesProcessor.checkForClassFilesChangesInModule() * core/deployment/.../dev/RuntimeUpdatesProcessor.java * moduleChangedSourceFiles is ArrayList; contains(sourceFilePath) called * for every class file in the module during dev mode hot reload. * Complexity: O(C * S) where C = class files, S = changed source files. * Fix: change declaration to Set (LinkedHashSet) → O(C). * * quarkus-0004: CORSFilter.handle() * extensions/vertx-http/.../cors/CORSFilter.java * corsConfig.origins().get().contains(origin) on List executed per * HTTP request. O(O) per request where O = configured origins count. * Fix: pre-build HashSet of exact origins at construction → O(1) per request. */ public class QuarkusTest { // ----------------------------------------------------------------------- // quarkus-0001 / quarkus-0002: getBoundInterceptors / getBoundDecorators // ----------------------------------------------------------------------- /** Defect: deduplicate using ArrayList.contains — O(N^2). */ static List deduplicateList(List inputs) { List bound = new ArrayList<>(); for (int item : inputs) { if (!bound.contains(item)) { // O(N) per call — defect bound.add(item); } } return bound; } /** Fix: deduplicate using LinkedHashSet — O(N) total, preserves order. */ static List deduplicateSet(List inputs) { Set seen = new LinkedHashSet<>(); for (int item : inputs) { seen.add(item); // O(1) per call — fix } return new ArrayList<>(seen); } static void testQuarkus0001_getBoundInterceptors() throws Exception { // Simulate M=200 intercepted methods, each with I=100 interceptors (some repeated) int M = 200; int I = 100; int totalInterceptors = 50; // universe of unique interceptors List allInterceptors = new ArrayList<>(); Random rng = new Random(42); for (int m = 0; m < M; m++) { for (int i = 0; i < I; i++) { allInterceptors.add(rng.nextInt(totalInterceptors)); } } long t0 = System.nanoTime(); for (int trial = 0; trial < 1000; trial++) { deduplicateList(allInterceptors); } long defectNs = System.nanoTime() - t0; long t1 = System.nanoTime(); for (int trial = 0; trial < 1000; trial++) { deduplicateSet(allInterceptors); } long fixNs = System.nanoTime() - t1; double ratio = (double) defectNs / fixNs; System.out.printf("quarkus-0001 getBoundInterceptors: defect=%.1fms fix=%.1fms ratio=%.1fx%n", defectNs / 1e6, fixNs / 1e6, ratio); if (ratio < 2.0) { throw new AssertionError("Expected ratio >= 2.0, got " + ratio); } System.out.println("quarkus-0001 PASS"); } static void testQuarkus0002_getBoundDecorators() throws Exception { // Simulate M=150 decorated methods, each with D=80 decorators (some repeated) int M = 150; int D = 80; int totalDecorators = 30; List allDecorators = new ArrayList<>(); Random rng = new Random(123); for (int m = 0; m < M; m++) { for (int d = 0; d < D; d++) { allDecorators.add(rng.nextInt(totalDecorators)); } } long t0 = System.nanoTime(); for (int trial = 0; trial < 1000; trial++) { deduplicateList(allDecorators); } long defectNs = System.nanoTime() - t0; long t1 = System.nanoTime(); for (int trial = 0; trial < 1000; trial++) { deduplicateSet(allDecorators); } long fixNs = System.nanoTime() - t1; double ratio = (double) defectNs / fixNs; System.out.printf("quarkus-0002 getBoundDecorators: defect=%.1fms fix=%.1fms ratio=%.1fx%n", defectNs / 1e6, fixNs / 1e6, ratio); if (ratio < 2.0) { throw new AssertionError("Expected ratio >= 2.0, got " + ratio); } System.out.println("quarkus-0002 PASS"); } // ----------------------------------------------------------------------- // quarkus-0003: checkForClassFilesChangesInModule — dev mode hot reload // ----------------------------------------------------------------------- /** Defect: List.contains per class file — O(C * S). */ static int scanModuleDefect(List classFiles, List changedSourceFiles) { int deletions = 0; for (String classFile : classFiles) { String sourceFile = classFile.replace(".class", ".java"); if (changedSourceFiles.contains(sourceFile)) { // O(S) per call — defect deletions++; } } return deletions; } /** Fix: Set.contains per class file — O(C). */ static int scanModuleFix(List classFiles, Set changedSourceFiles) { int deletions = 0; for (String classFile : classFiles) { String sourceFile = classFile.replace(".class", ".java"); if (changedSourceFiles.contains(sourceFile)) { // O(1) per call — fix deletions++; } } return deletions; } static void testQuarkus0003_devModeChangedSourceFiles() throws Exception { // Simulate: C=2000 class files, S=200 changed source files int C = 2000; int S = 200; List classFiles = new ArrayList<>(C); List changedSourceList = new ArrayList<>(S); Set changedSourceSet = new LinkedHashSet<>(S * 2); for (int i = 0; i < C; i++) { classFiles.add("com/example/Foo" + i + ".class"); } for (int i = 0; i < S; i++) { String src = "com/example/Foo" + (i * 5) + ".java"; changedSourceList.add(src); changedSourceSet.add(src); } long t0 = System.nanoTime(); for (int trial = 0; trial < 200; trial++) { scanModuleDefect(classFiles, changedSourceList); } long defectNs = System.nanoTime() - t0; long t1 = System.nanoTime(); for (int trial = 0; trial < 200; trial++) { scanModuleFix(classFiles, changedSourceSet); } long fixNs = System.nanoTime() - t1; double ratio = (double) defectNs / fixNs; System.out.printf("quarkus-0003 devModeChangedSourceFiles: defect=%.1fms fix=%.1fms ratio=%.1fx%n", defectNs / 1e6, fixNs / 1e6, ratio); if (ratio < 5.0) { throw new AssertionError("Expected ratio >= 5.0, got " + ratio); } System.out.println("quarkus-0003 PASS"); } // ----------------------------------------------------------------------- // quarkus-0004: CORSFilter.handle — origins list lookup per request // ----------------------------------------------------------------------- /** Defect: List.contains per HTTP request — O(O). */ static int handleRequestsDefect(List origins, String[] incomingOrigins) { int allowed = 0; for (String origin : incomingOrigins) { if (origins.contains(origin)) { // O(O) per request — defect allowed++; } } return allowed; } /** Fix: pre-built HashSet.contains per request — O(1). */ static int handleRequestsFix(Set originsSet, String[] incomingOrigins) { int allowed = 0; for (String origin : incomingOrigins) { if (originsSet.contains(origin)) { // O(1) per request — fix allowed++; } } return allowed; } static void testQuarkus0004_corsOriginsLookup() throws Exception { // Simulate: O=100 configured origins, R=100000 requests int O = 100; int R = 100000; List originsList = new ArrayList<>(O); Set originsSet = new HashSet<>(O * 2); for (int i = 0; i < O; i++) { originsList.add("https://example" + i + ".com"); originsSet.add("https://example" + i + ".com"); } // Requests target last origin (worst case for list scan) String[] requests = new String[R]; for (int i = 0; i < R; i++) { requests[i] = "https://example" + ((i % O)) + ".com"; } long t0 = System.nanoTime(); handleRequestsDefect(originsList, requests); long defectNs = System.nanoTime() - t0; long t1 = System.nanoTime(); handleRequestsFix(originsSet, requests); long fixNs = System.nanoTime() - t1; double ratio = (double) defectNs / fixNs; System.out.printf("quarkus-0004 corsOriginsLookup: defect=%.1fms fix=%.1fms ratio=%.1fx%n", defectNs / 1e6, fixNs / 1e6, ratio); if (ratio < 2.0) { throw new AssertionError("Expected ratio >= 2.0, got " + ratio); } System.out.println("quarkus-0004 PASS"); } // ----------------------------------------------------------------------- // Main // ----------------------------------------------------------------------- public static void main(String[] args) throws Exception { testQuarkus0001_getBoundInterceptors(); testQuarkus0002_getBoundDecorators(); testQuarkus0003_devModeChangedSourceFiles(); testQuarkus0004_corsOriginsLookup(); System.out.println("ALL PASS"); } }