java-topology/defects/ansible/unit/AnsibleTest.java
russell@unturf.com e0aba0e21e terraform-0001/ansible-0002/ansible-0003: CWE-407 deeper scan — 3 defects, 6/6 PASS
terraform-0001: Tarjan SCC inStack linear scan O(E*V) — HIGH, 994x at V=2000
ansible-0002: Host.add_group() list membership O(A*G) — MEDIUM, 499x at G=1000
ansible-0003: Handler.notify_host() list membership O(H^2) — MEDIUM, 499x at H=1000
2026-03-30 13:29:25 -04:00

132 lines
4.5 KiB
Java

import java.util.*;
/**
* CWE-407 unit tests for ansible-0002 and ansible-0003.
*
* ansible-0002: Host.add_group() uses `group not in self.groups` list scan O(G)
* inside ancestor loop — O(A*G) per call, O(H*G*A) total.
*
* ansible-0003: Handler.is_host_notified() uses `host in self.notified_hosts`
* list scan — O(H) per notify, O(H^2) total.
*
* Fix: set alongside list for O(1) membership.
*/
public class AnsibleTest {
static long ops;
// ===== ansible-0002: Host.add_group linear scan =====
/** Simulates adding G groups to a host, each with some ancestors */
static long hostAddGroupDefective(int G) {
ops = 0;
List<String> hostGroups = new ArrayList<>(); // self.groups as list
for (int g = 0; g < G; g++) {
// Simulate: group not in self.groups (linear scan)
boolean found = false;
for (String existing : hostGroups) {
ops++;
if (existing.equals("group-" + g)) { found = true; break; }
}
if (!found) {
hostGroups.add("group-" + g);
}
}
return ops;
}
static long hostAddGroupFixed(int G) {
ops = 0;
List<String> hostGroups = new ArrayList<>();
Set<String> hostGroupsSet = new HashSet<>();
for (int g = 0; g < G; g++) {
ops++; // HashSet.contains = O(1), count as 1 op
if (!hostGroupsSet.contains("group-" + g)) {
hostGroups.add("group-" + g);
hostGroupsSet.add("group-" + g);
}
}
return ops;
}
// ===== ansible-0003: Handler.notify_host linear scan =====
/** Simulates notifying H hosts on a handler */
static long handlerNotifyDefective(int H) {
ops = 0;
List<String> notifiedHosts = new ArrayList<>(); // self.notified_hosts as list
for (int h = 0; h < H; h++) {
String host = "host-" + h;
// is_host_notified: host in self.notified_hosts (linear scan)
boolean found = false;
for (String existing : notifiedHosts) {
ops++;
if (existing.equals(host)) { found = true; break; }
}
if (!found) {
notifiedHosts.add(host);
}
}
return ops;
}
static long handlerNotifyFixed(int H) {
ops = 0;
List<String> notifiedHosts = new ArrayList<>();
Set<String> notifiedSet = new HashSet<>();
for (int h = 0; h < H; h++) {
String host = "host-" + h;
ops++; // HashSet.contains = O(1)
if (!notifiedSet.contains(host)) {
notifiedHosts.add(host);
notifiedSet.add(host);
}
}
return ops;
}
public static void main(String[] args) {
int[] sizes = {200, 500, 1000};
boolean allPass = true;
// --- ansible-0002 ---
System.out.println("ansible-0002: Host.add_group() list membership scan");
System.out.println("===================================================");
System.out.printf("%-8s %14s %14s %10s %s%n",
"G", "Defect(ops)", "Fixed(ops)", "Ratio", "Status");
for (int G : sizes) {
long dOps = hostAddGroupDefective(G);
long fOps = hostAddGroupFixed(G);
double ratio = (double) dOps / Math.max(fOps, 1);
String status = (ratio >= 5.0) ? "PASS" : "FAIL";
if (!status.equals("PASS")) allPass = false;
System.out.printf("%-8d %14d %14d %10.1fx %s%n", G, dOps, fOps, ratio, status);
}
System.out.println();
// --- ansible-0003 ---
System.out.println("ansible-0003: Handler.notify_host() list membership scan");
System.out.println("=======================================================");
System.out.printf("%-8s %14s %14s %10s %s%n",
"H", "Defect(ops)", "Fixed(ops)", "Ratio", "Status");
for (int H : sizes) {
long dOps = handlerNotifyDefective(H);
long fOps = handlerNotifyFixed(H);
double ratio = (double) dOps / Math.max(fOps, 1);
String status = (ratio >= 5.0) ? "PASS" : "FAIL";
if (!status.equals("PASS")) allPass = false;
System.out.printf("%-8d %14d %14d %10.1fx %s%n", H, dOps, fOps, ratio, status);
}
System.out.println();
System.out.println(allPass ? "ALL PASS" : "SOME FAIL");
System.exit(allPass ? 0 : 1);
}
}