import java.util.*; /** * CWE-407 simulation for Kdenlive defects. * kdenlive-0001: ThumbnailCache storedOnDisk vector linear find for dedup * kdenlive-0002: TimelineModel clipIds vector linear find in mix loop * kdenlive-0003: TimelineController sorted_clips vector linear find in moveGroup * kdenlive-0004: TimelineModel all_items list linear find in resize */ public class KdenliveTest { // --- kdenlive-0001: ThumbnailCache storedOnDisk dedup --- static long thumbnailCacheDefect(int numClips, int framesPerClip) { // Simulates m_storedOnDisk as Map> Map> storedOnDisk = new HashMap<>(); long ops = 0; for (int c = 0; c < numClips; c++) { String binId = "clip-" + c; storedOnDisk.put(binId, new ArrayList<>()); for (int f = 0; f < framesPerClip; f++) { List vec = storedOnDisk.get(binId); // std::find linear scan before push_back boolean found = false; for (int existing : vec) { ops++; if (existing == f) { found = true; break; } } if (!found) { vec.add(f); } } } return ops; } static long thumbnailCacheFixed(int numClips, int framesPerClip) { Map> storedOnDisk = new HashMap<>(); long ops = 0; for (int c = 0; c < numClips; c++) { String binId = "clip-" + c; storedOnDisk.put(binId, new HashSet<>()); for (int f = 0; f < framesPerClip; f++) { ops++; storedOnDisk.get(binId).add(f); } } return ops; } // --- kdenlive-0002: clipIds mix membership --- static long clipIdsMixDefect(int N) { List clipIds = new ArrayList<>(); for (int i = 0; i < N; i++) clipIds.add(i); long ops = 0; for (int s : clipIds) { // Simulate 3 std::find calls per clip (typical in mix logic) for (int check = 0; check < 3; check++) { int target = (s + 1) % N; for (int id : clipIds) { ops++; if (id == target) break; } } } return ops; } static long clipIdsMixFixed(int N) { List clipIds = new ArrayList<>(); Set clipIdSet = new HashSet<>(); for (int i = 0; i < N; i++) { clipIds.add(i); clipIdSet.add(i); } long ops = 0; for (int s : clipIds) { for (int check = 0; check < 3; check++) { ops++; int target = (s + 1) % N; clipIdSet.contains(target); } } return ops; } // --- kdenlive-0003: sorted_clips moveGroup membership --- static long sortedClipsMoveDefect(int N) { List sortedClips = new ArrayList<>(); for (int i = 0; i < N; i++) sortedClips.add(i); long ops = 0; for (int item : sortedClips) { // 2 std::find calls per clip (startMix + endMix check) for (int check = 0; check < 2; check++) { int target = (item + 1) % N; for (int id : sortedClips) { ops++; if (id == target) break; } } } return ops; } static long sortedClipsMoveFixed(int N) { List sortedClips = new ArrayList<>(); Set sortedSet = new HashSet<>(); for (int i = 0; i < N; i++) { sortedClips.add(i); sortedSet.add(i); } long ops = 0; for (int item : sortedClips) { for (int check = 0; check < 2; check++) { ops++; sortedSet.contains((item + 1) % N); } } return ops; } // --- kdenlive-0004: all_items resize dedup --- static long allItemsResizeDefect(int N) { // currentSelection has N items; all_items grows as we add non-duplicates LinkedList allItems = new LinkedList<>(); allItems.add(0); // itemId long ops = 0; for (int id = 1; id < N; id++) { // std::find on all_items boolean found = false; for (int existing : allItems) { ops++; if (existing == id) { found = true; break; } } if (!found) { allItems.add(id); } } return ops; } static long allItemsResizeFixed(int N) { LinkedList allItems = new LinkedList<>(); Set allItemsSet = new HashSet<>(); allItems.add(0); allItemsSet.add(0); long ops = 0; for (int id = 1; id < N; id++) { ops++; if (!allItemsSet.contains(id)) { allItems.add(id); allItemsSet.add(id); } } return ops; } public static void main(String[] args) { int pass = 0, fail = 0; // Test kdenlive-0001: ThumbnailCache (10 clips x 200 frames) { long defectOps = thumbnailCacheDefect(10, 200); long fixedOps = thumbnailCacheFixed(10, 200); double ratio = (double) defectOps / fixedOps; boolean ok = ratio > 5.0 && fixedOps < defectOps; System.out.printf("kdenlive-0001 ThumbnailCache storedOnDisk: defect=%d fixed=%d ratio=%.1fx %s%n", defectOps, fixedOps, ratio, ok ? "PASS" : "FAIL"); if (ok) pass++; else fail++; } // Test kdenlive-0002: clipIds mix (N=500) { long defectOps = clipIdsMixDefect(500); long fixedOps = clipIdsMixFixed(500); double ratio = (double) defectOps / fixedOps; boolean ok = ratio > 50.0; System.out.printf("kdenlive-0002 clipIds mix membership: defect=%d fixed=%d ratio=%.1fx %s%n", defectOps, fixedOps, ratio, ok ? "PASS" : "FAIL"); if (ok) pass++; else fail++; } // Test kdenlive-0003: sorted_clips move (N=500) { long defectOps = sortedClipsMoveDefect(500); long fixedOps = sortedClipsMoveFixed(500); double ratio = (double) defectOps / fixedOps; boolean ok = ratio > 50.0; System.out.printf("kdenlive-0003 sorted_clips moveGroup: defect=%d fixed=%d ratio=%.1fx %s%n", defectOps, fixedOps, ratio, ok ? "PASS" : "FAIL"); if (ok) pass++; else fail++; } // Test kdenlive-0004: all_items resize (N=500) { long defectOps = allItemsResizeDefect(500); long fixedOps = allItemsResizeFixed(500); double ratio = (double) defectOps / fixedOps; boolean ok = ratio > 50.0; System.out.printf("kdenlive-0004 all_items resize dedup: defect=%d fixed=%d ratio=%.1fx %s%n", defectOps, fixedOps, ratio, ok ? "PASS" : "FAIL"); if (ok) pass++; else fail++; } System.out.printf("%nSummary: %d/%d PASS%n", pass, pass + fail); if (fail > 0) System.exit(1); } }