94 lines
3.3 KiB
Java
94 lines
3.3 KiB
Java
import java.util.*;
|
|
|
|
/**
|
|
* CWE-407 unit test for digikam-0001: Haar similarity search targetAlbums
|
|
* QList<int>::contains() called for every image in DB during similarity search.
|
|
* O(N * A) where N = images, A = target albums → O(N) with QSet.
|
|
*
|
|
* Simulates fulfillsRestrictions called N times with targetAlbums.contains().
|
|
*/
|
|
public class DigikamHaarTargetAlbumsTest {
|
|
|
|
// --- DEFECTIVE: List contains in inner loop ---
|
|
static int searchDefective(int numImages, List<Integer> targetAlbums, int[] imageAlbums) {
|
|
int matches = 0;
|
|
for (int i = 0; i < numImages; i++) {
|
|
int albumId = imageAlbums[i];
|
|
if (targetAlbums.isEmpty() || targetAlbums.contains(albumId)) { // O(A)
|
|
matches++;
|
|
}
|
|
}
|
|
return matches;
|
|
}
|
|
|
|
// --- PATCHED: Set contains in inner loop ---
|
|
static int searchPatched(int numImages, Set<Integer> targetAlbumsSet, int[] imageAlbums) {
|
|
int matches = 0;
|
|
for (int i = 0; i < numImages; i++) {
|
|
int albumId = imageAlbums[i];
|
|
if (targetAlbumsSet.isEmpty() || targetAlbumsSet.contains(albumId)) { // O(1)
|
|
matches++;
|
|
}
|
|
}
|
|
return matches;
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
int N = 50000; // images in database
|
|
int A = 200; // target albums
|
|
int totalAlbums = 500;
|
|
|
|
// Build target albums list/set
|
|
List<Integer> targetAlbumsList = new ArrayList<>();
|
|
Set<Integer> targetAlbumsSet = new HashSet<>();
|
|
for (int i = 0; i < A; i++) {
|
|
targetAlbumsList.add(i);
|
|
targetAlbumsSet.add(i);
|
|
}
|
|
|
|
// Build image album assignments
|
|
Random rng = new Random(42);
|
|
int[] imageAlbums = new int[N];
|
|
for (int i = 0; i < N; i++) {
|
|
imageAlbums[i] = rng.nextInt(totalAlbums);
|
|
}
|
|
|
|
// Warm up
|
|
for (int w = 0; w < 3; w++) {
|
|
searchDefective(N, targetAlbumsList, imageAlbums);
|
|
searchPatched(N, targetAlbumsSet, imageAlbums);
|
|
}
|
|
|
|
// Benchmark defective
|
|
int iterations = 20;
|
|
long startDef = System.nanoTime();
|
|
int resultDef = 0;
|
|
for (int i = 0; i < iterations; i++) {
|
|
resultDef = searchDefective(N, targetAlbumsList, imageAlbums);
|
|
}
|
|
long defectiveNs = System.nanoTime() - startDef;
|
|
|
|
// Benchmark patched
|
|
long startPat = System.nanoTime();
|
|
int resultPat = 0;
|
|
for (int i = 0; i < iterations; i++) {
|
|
resultPat = searchPatched(N, targetAlbumsSet, imageAlbums);
|
|
}
|
|
long patchedNs = System.nanoTime() - startPat;
|
|
|
|
double ratio = (double) defectiveNs / patchedNs;
|
|
|
|
System.out.println("digikam-0001: Haar searchDatabase targetAlbums.contains()");
|
|
System.out.println("N=" + N + " images, A=" + A + " target albums");
|
|
System.out.println("Defective matches: " + resultDef + " Patched matches: " + resultPat);
|
|
System.out.printf("Defective: %.3f ms%n", defectiveNs / 1e6);
|
|
System.out.printf("Patched: %.3f ms%n", patchedNs / 1e6);
|
|
System.out.printf("Ratio: %.1fx%n", ratio);
|
|
|
|
assert resultDef == resultPat : "Results must match!";
|
|
|
|
boolean pass = ratio > 2.0;
|
|
System.out.println(pass ? "PASS" : "FAIL");
|
|
if (!pass) System.exit(1);
|
|
}
|
|
}
|