audacity: add Java unit test for CWE-407 defects (audacity-0001/0002)
This commit is contained in:
parent
9b71d0d527
commit
bf6a727f08
1 changed files with 136 additions and 0 deletions
136
defects/audacity/unit/AudacityTest.java
Normal file
136
defects/audacity/unit/AudacityTest.java
Normal file
|
|
@ -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<Integer> filterTracksDefective(List<Integer> allTracks, List<Integer> selectedTracks) {
|
||||
ops = 0;
|
||||
List<Integer> 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<Integer> filterTracksFixed(List<Integer> allTracks, List<Integer> selectedTracks) {
|
||||
ops = 0;
|
||||
Set<Integer> selectedSet = new HashSet<>(selectedTracks);
|
||||
List<Integer> 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<Integer> allTracks = new ArrayList<>();
|
||||
List<Integer> 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<Integer> r1 = filterTracksDefective(allTracks, selectedTracks);
|
||||
int defectOps = ops;
|
||||
|
||||
List<Integer> 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<Integer> 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");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue