From bf6a727f083f3098099aa243e83e42d7f21b36b5 Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Mon, 30 Mar 2026 11:15:03 -0400 Subject: [PATCH] audacity: add Java unit test for CWE-407 defects (audacity-0001/0002) --- defects/audacity/unit/AudacityTest.java | 136 ++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 defects/audacity/unit/AudacityTest.java diff --git a/defects/audacity/unit/AudacityTest.java b/defects/audacity/unit/AudacityTest.java new file mode 100644 index 000000000..7121eac34 --- /dev/null +++ b/defects/audacity/unit/AudacityTest.java @@ -0,0 +1,136 @@ +/** + * 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"); + } +}