wave14a/c/d: 524/239 — rails-0018/grape-0001..3/django-0005..6/sqlalchemy-0003/go-stdlib-0001/vault-0001/tf-aws-0001
This commit is contained in:
parent
8f0bc73afa
commit
ac0e1e091e
20 changed files with 1948 additions and 21 deletions
175
defects/terraform/unit/TfAwsCloudFormationAlgorithm.java
Normal file
175
defects/terraform/unit/TfAwsCloudFormationAlgorithm.java
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* TfAwsCloudFormationAlgorithm — CWE-407 benchmark
|
||||
*
|
||||
* Models terraform-provider-aws cloudformation/stack_set_instance.go
|
||||
* findStackInstanceSummariesByFourPartKey():
|
||||
* SLOW: slices.Contains(orgIDs, v.OrganizationalUnitId) — O(O) per summary
|
||||
* called S times inside pagination → O(S × O) total
|
||||
* FAST: pre-build map[string]bool from orgIDs → O(1) per summary
|
||||
*
|
||||
* tf-aws-0001
|
||||
*/
|
||||
public class TfAwsCloudFormationAlgorithm {
|
||||
|
||||
// ------------------------------------------------------------------ nodes
|
||||
|
||||
static class Node {
|
||||
String ouId;
|
||||
String stackInstanceId;
|
||||
Node(String ouId, String stackInstanceId) {
|
||||
this.ouId = ouId;
|
||||
this.stackInstanceId = stackInstanceId;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ result
|
||||
|
||||
static class Result {
|
||||
List<Node> matched;
|
||||
Result(List<Node> matched) { this.matched = matched; }
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ slow (defect)
|
||||
|
||||
static class DefectiveFinder {
|
||||
/**
|
||||
* For each summary across all pagination pages, scan orgIDs linearly.
|
||||
* O(S × O) where S = total summaries, O = number of org IDs.
|
||||
*/
|
||||
static Result findSummaries(List<List<Node>> pages, List<String> orgIDs) {
|
||||
List<Node> output = new ArrayList<>();
|
||||
for (List<Node> page : pages) {
|
||||
for (Node v : page) {
|
||||
// CWE-407: linear scan of orgIDs on every summary
|
||||
if (orgIDs.contains(v.ouId)) { // O(O)
|
||||
output.add(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Result(output);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ fast (fix)
|
||||
|
||||
static class FixedFinder {
|
||||
/**
|
||||
* Pre-build a HashSet from orgIDs before the pagination loop.
|
||||
* O(S + O) total.
|
||||
*/
|
||||
static Result findSummaries(List<List<Node>> pages, List<String> orgIDs) {
|
||||
// CWE-407 fix: O(1) lookup set built once before pagination
|
||||
Set<String> orgIDSet = new HashSet<>(orgIDs);
|
||||
List<Node> output = new ArrayList<>();
|
||||
for (List<Node> page : pages) {
|
||||
for (Node v : page) {
|
||||
if (orgIDSet.contains(v.ouId)) { // O(1)
|
||||
output.add(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Result(output);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ helpers
|
||||
|
||||
static List<List<Node>> buildPages(int totalSummaries, int pageSize, int numOUs) {
|
||||
List<List<Node>> pages = new ArrayList<>();
|
||||
List<Node> page = new ArrayList<>();
|
||||
for (int i = 0; i < totalSummaries; i++) {
|
||||
String ouId = "ou-" + (i % numOUs); // distribute across OUs
|
||||
page.add(new Node(ouId, "stack-instance-" + i));
|
||||
if (page.size() == pageSize) {
|
||||
pages.add(page);
|
||||
page = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
if (!page.isEmpty()) pages.add(page);
|
||||
return pages;
|
||||
}
|
||||
|
||||
static List<String> buildOrgIDs(int n) {
|
||||
List<String> ids = new ArrayList<>(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
ids.add("ou-" + i);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
static long benchSlow(int S, int O, int iters) {
|
||||
List<List<Node>> pages = buildPages(S, 100, O * 2);
|
||||
List<String> orgIDs = buildOrgIDs(O);
|
||||
long start = System.nanoTime();
|
||||
for (int i = 0; i < iters; i++) {
|
||||
DefectiveFinder.findSummaries(pages, orgIDs);
|
||||
}
|
||||
return System.nanoTime() - start;
|
||||
}
|
||||
|
||||
static long benchFast(int S, int O, int iters) {
|
||||
List<List<Node>> pages = buildPages(S, 100, O * 2);
|
||||
List<String> orgIDs = buildOrgIDs(O);
|
||||
long start = System.nanoTime();
|
||||
for (int i = 0; i < iters; i++) {
|
||||
FixedFinder.findSummaries(pages, orgIDs);
|
||||
}
|
||||
return System.nanoTime() - start;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ main
|
||||
|
||||
public static void main(String[] args) {
|
||||
int passed = 0, total = 0;
|
||||
|
||||
// ---- correctness
|
||||
List<Node> page1 = Arrays.asList(
|
||||
new Node("ou-1", "s1"), new Node("ou-2", "s2"), new Node("ou-3", "s3")
|
||||
);
|
||||
List<Node> page2 = Arrays.asList(
|
||||
new Node("ou-4", "s4"), new Node("ou-1", "s5")
|
||||
);
|
||||
List<List<Node>> pages = Arrays.asList(page1, page2);
|
||||
List<String> orgIDs = Arrays.asList("ou-1", "ou-3");
|
||||
|
||||
Result slowR = DefectiveFinder.findSummaries(pages, orgIDs);
|
||||
Result fastR = FixedFinder.findSummaries(pages, orgIDs);
|
||||
|
||||
assert slowR.matched.size() == 3 : "slow: expected 3 matches, got " + slowR.matched.size();
|
||||
assert fastR.matched.size() == 3 : "fast: expected 3 matches, got " + fastR.matched.size();
|
||||
assert slowR.matched.size() == fastR.matched.size() : "slow/fast count mismatch";
|
||||
System.out.println("Correctness: PASS (slow.matched.size == fast.matched.size == 3)");
|
||||
|
||||
// ---- performance
|
||||
int ITERS = 50;
|
||||
int[][] scenarios = {{2000, 200}, {4000, 350}, {7000, 500}};
|
||||
System.out.printf("%-6s %-6s %-12s %-12s %s%n", "S", "O", "slow(ns)", "fast(ns)", "ratio");
|
||||
|
||||
for (int[] sc : scenarios) {
|
||||
int S = sc[0], O = sc[1];
|
||||
// warm-up (extra iterations to stabilize JIT at larger sizes)
|
||||
benchSlow(S, O, 10); benchFast(S, O, 10);
|
||||
|
||||
long slowNs = benchSlow(S, O, ITERS);
|
||||
long fastNs = benchFast(S, O, ITERS);
|
||||
double ratio = (double) slowNs / fastNs;
|
||||
|
||||
System.out.printf("%-6d %-6d %-12d %-12d %.2fx%n", S, O, slowNs, fastNs, ratio);
|
||||
|
||||
total++;
|
||||
if (ratio >= 5.0) {
|
||||
System.out.printf(" PASS (ratio=%.2f >= 5.0)%n", ratio);
|
||||
passed++;
|
||||
} else {
|
||||
System.out.printf(" FAIL (ratio=%.2f < 5.0)%n", ratio);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.printf("%nTests: %d/%d PASS%n", passed, total);
|
||||
if (passed < total) System.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue