/** * CWE-407 simulation tests for Audacity defects. * * Each test simulates the defective O(N^2) pattern and the fixed O(N) pattern, * measuring operation counts to confirm the quadratic vs linear behavior. */ import java.util.*; public class AudacityTest { static int ops; // ======================================================================== // audacity-0001: TrackeditActionsController selectedTracks O(T*S) // ======================================================================== /** Defective: for each track, linear scan of selectedTracks */ static List filterTracksDefective(List allTracks, List selectedTracks) { ops = 0; List result = new ArrayList<>(); for (int trackId : allTracks) { boolean found = false; for (int sel : selectedTracks) { ops++; if (sel == trackId) { found = true; break; } } if (found) { result.add(trackId); } } return result; } /** Fixed: HashSet for O(1) membership */ static List filterTracksFixed(List allTracks, List selectedTracks) { ops = 0; Set selectedSet = new HashSet<>(selectedTracks); List result = new ArrayList<>(); for (int trackId : allTracks) { ops++; if (selectedSet.contains(trackId)) { result.add(trackId); } } return result; } static void testSelectedTracksFilter() { int T = 500, S = 100; List allTracks = new ArrayList<>(); List selectedTracks = new ArrayList<>(); for (int i = 0; i < T; i++) allTracks.add(i); // Selected tracks are the last S tracks — worst case for linear scan for (int i = T - S; i < T; i++) selectedTracks.add(i); List r1 = filterTracksDefective(allTracks, selectedTracks); int defectOps = ops; List r2 = filterTracksFixed(allTracks, selectedTracks); int fixedOps = ops; assert r1.size() == r2.size() : "Results must match"; double ratio = (double) defectOps / fixedOps; System.out.printf("audacity-0001 selectedTracks filter T=%d S=%d defect=%d fixed=%d ratio=%.1fx%n", T, S, defectOps, fixedOps, ratio); assert ratio > 10 : "Expected >10x ratio, got " + ratio; } // ======================================================================== // audacity-0002: WaveTrack::CanOffsetClips() O(I*M) moving clip scan // ======================================================================== /** Defective: for each interval, linear scan of movingClips */ static boolean canOffsetClipsDefective(int[] intervals, int[] movingClips, double amount) { ops = 0; for (int interval : intervals) { // Check if this interval is in movingClips boolean isMoving = false; for (int mc : movingClips) { ops++; if (mc == interval) { isMoving = true; break; } } if (isMoving) continue; // Would check overlap with moving clips here } return true; } /** Fixed: HashSet for O(1) membership */ static boolean canOffsetClipsFixed(int[] intervals, int[] movingClips, double amount) { ops = 0; Set movingSet = new HashSet<>(); for (int mc : movingClips) movingSet.add(mc); for (int interval : intervals) { ops++; if (movingSet.contains(interval)) continue; } return true; } static void testCanOffsetClips() { int I = 500, M = 100; // All unique intervals, none are moving — worst case int[] intervals = new int[I]; int[] movingClips = new int[M]; for (int i = 0; i < I; i++) intervals[i] = i; for (int i = 0; i < M; i++) movingClips[i] = I + i; // none match canOffsetClipsDefective(intervals, movingClips, 1.0); int defectOps = ops; canOffsetClipsFixed(intervals, movingClips, 1.0); int fixedOps = ops; double ratio = (double) defectOps / fixedOps; System.out.printf("audacity-0002 CanOffsetClips I=%d M=%d defect=%d fixed=%d ratio=%.1fx%n", I, M, defectOps, fixedOps, ratio); assert ratio > 10 : "Expected >10x ratio, got " + ratio; } // ======================================================================== // Main // ======================================================================== public static void main(String[] args) { testSelectedTracksFilter(); testCanOffsetClips(); System.out.println("ALL 2 TESTS PASSED"); } }