bird-0003/0004 + frrouting-0003/0004: BGP community set ops O(N×M)/O(N²); OpenBGPD CLEAN; count 595→599
This commit is contained in:
parent
3f8c5e6d3e
commit
ff7bd27654
11 changed files with 671 additions and 4 deletions
153
defects/bird/unit/BirdCommunitySetAlgorithmTest.java
Normal file
153
defects/bird/unit/BirdCommunitySetAlgorithmTest.java
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Models BIRD routing daemon community set operations.
|
||||
*
|
||||
* bird-0003: int_set_union O(N×M) — contains check in union loop
|
||||
* bird-0004: clist_filter O(L×S) — contains check in filter loop
|
||||
*
|
||||
* SLOW: O(N×M) union / O(L×S) filter — linear scan per element
|
||||
* FAST: O(N+M) union / O(L+S) filter — HashSet pre-built from second operand
|
||||
*
|
||||
* CWE-407: nest/a-set.c:394 (union), filter/data.c:421 (filter)
|
||||
*/
|
||||
public class BirdCommunitySetAlgorithmTest {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Slow (defective) — mirrors int_set_contains in loop
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static class SlowCommunityOps {
|
||||
long scanOps = 0;
|
||||
|
||||
boolean contains(int[] arr, int val) {
|
||||
for (int v : arr) {
|
||||
scanOps++;
|
||||
if (v == val) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** bird-0003: O(N×M) union */
|
||||
int[] union(int[] l1, int[] l2) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (int v : l1) result.add(v);
|
||||
for (int v : l2) {
|
||||
if (!contains(l1, v)) result.add(v);
|
||||
}
|
||||
return result.stream().mapToInt(Integer::intValue).toArray();
|
||||
}
|
||||
|
||||
/** bird-0004: O(L×S) filter — keep entries in l1 that are in filterSet */
|
||||
int[] filter(int[] l1, int[] filterSet) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (int v : l1) {
|
||||
if (contains(filterSet, v)) result.add(v);
|
||||
}
|
||||
return result.stream().mapToInt(Integer::intValue).toArray();
|
||||
}
|
||||
|
||||
long unionOps(int[] l1, int[] l2) { scanOps = 0; union(l1, l2); return scanOps; }
|
||||
long filterOps(int[] l1, int[] filterSet) { scanOps = 0; filter(l1, filterSet); return scanOps; }
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Fast (fixed) — HashSet from one operand
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static class FastCommunityOps {
|
||||
long scanOps = 0;
|
||||
|
||||
int[] union(int[] l1, int[] l2) {
|
||||
Set<Integer> seen = new HashSet<>();
|
||||
for (int v : l1) { seen.add(v); scanOps++; }
|
||||
List<Integer> result = new ArrayList<>(Arrays.stream(l1).boxed().toList());
|
||||
for (int v : l2) {
|
||||
scanOps++;
|
||||
if (seen.add(v)) result.add(v);
|
||||
}
|
||||
return result.stream().mapToInt(Integer::intValue).toArray();
|
||||
}
|
||||
|
||||
int[] filter(int[] l1, int[] filterSet) {
|
||||
Set<Integer> fs = new HashSet<>();
|
||||
for (int v : filterSet) { fs.add(v); scanOps++; }
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (int v : l1) {
|
||||
scanOps++;
|
||||
if (fs.contains(v)) result.add(v);
|
||||
}
|
||||
return result.stream().mapToInt(Integer::intValue).toArray();
|
||||
}
|
||||
|
||||
long unionOps(int[] l1, int[] l2) { scanOps = 0; union(l1, l2); return scanOps; }
|
||||
long filterOps(int[] l1, int[] filterSet) { scanOps = 0; filter(l1, filterSet); return scanOps; }
|
||||
}
|
||||
|
||||
static int[] range(int from, int n) {
|
||||
int[] a = new int[n];
|
||||
for (int i = 0; i < n; i++) a[i] = from + i;
|
||||
return a;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SlowCommunityOps slow = new SlowCommunityOps();
|
||||
FastCommunityOps fast = new FastCommunityOps();
|
||||
|
||||
int passed = 0, total = 0;
|
||||
|
||||
System.out.println("=== bird-0003: int_set_union O(N×M) ===");
|
||||
int[] sizes = {50, 100, 200, 500};
|
||||
for (int n : sizes) {
|
||||
int[] l1 = range(0, n);
|
||||
int[] l2 = range(n / 2, n); // partial overlap
|
||||
long s = slow.unionOps(l1, l2);
|
||||
long f = fast.unionOps(l1, l2);
|
||||
double ratio = (double) s / f;
|
||||
total++;
|
||||
boolean ok = s > f && ratio >= 5.0;
|
||||
System.out.printf("N=%3d slow=%8d fast=%5d ratio=%6.1fx %s%n",
|
||||
n, s, f, ratio, ok ? "PASS" : "FAIL");
|
||||
if (ok) passed++;
|
||||
}
|
||||
|
||||
System.out.println("=== bird-0004: clist_filter O(L×S) ===");
|
||||
for (int n : sizes) {
|
||||
int[] l1 = range(0, n); // route's community list
|
||||
int[] filterSet = range(n/4, n/2); // keep middle half
|
||||
long s = slow.filterOps(l1, filterSet);
|
||||
long f = fast.filterOps(l1, filterSet);
|
||||
double ratio = (double) s / f;
|
||||
total++;
|
||||
boolean ok = s > f && ratio >= 3.0;
|
||||
System.out.printf("L=%3d S=%3d slow=%8d fast=%5d ratio=%6.1fx %s%n",
|
||||
n, n/2, s, f, ratio, ok ? "PASS" : "FAIL");
|
||||
if (ok) passed++;
|
||||
}
|
||||
|
||||
// Correctness: union contains all unique elements
|
||||
int[] a = range(0, 100), b = range(50, 100);
|
||||
int[] slowUnion = slow.union(a, b);
|
||||
int[] fastUnion = fast.union(a, b);
|
||||
Arrays.sort(slowUnion); Arrays.sort(fastUnion);
|
||||
total++;
|
||||
boolean correct1 = Arrays.equals(slowUnion, fastUnion);
|
||||
System.out.printf("union correctness: %s%n", correct1 ? "PASS" : "FAIL");
|
||||
if (correct1) passed++;
|
||||
|
||||
// Correctness: filter returns same kept elements
|
||||
int[] l = range(0, 100), fs = range(20, 60);
|
||||
int[] slowFilter = slow.filter(l, fs);
|
||||
int[] fastFilter = fast.filter(l, fs);
|
||||
Arrays.sort(slowFilter); Arrays.sort(fastFilter);
|
||||
total++;
|
||||
boolean correct2 = Arrays.equals(slowFilter, fastFilter);
|
||||
System.out.printf("filter correctness: %s%n", correct2 ? "PASS" : "FAIL");
|
||||
if (correct2) passed++;
|
||||
|
||||
System.out.printf("%n%d/%d PASS%n", passed, total);
|
||||
if (passed < total) System.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue