feat: Update testing documentation and introduce comprehensive report for IPSExtractor campaign. Add sections for executive summary, objectives, environment details, and methodology. Enhance README with compilation instructions and data sources for metrics analysis.

This commit is contained in:
erik
2026-07-13 21:10:43 -05:00
parent 6bf413c4ce
commit 311a4bd6d3
39 changed files with 1641 additions and 67 deletions
@@ -0,0 +1,61 @@
package pipeline
import "testing"
func TestClusterRowsTwoBands(t *testing.T) {
boxes := []indexedBox{
{Text: "a", X: 0, Y: 100},
{Text: "b", X: 10, Y: 102},
{Text: "c", X: 0, Y: 300},
{Text: "d", X: 10, Y: 301},
}
ClusterRows(boxes, 10, 1)
if boxes[0].Cluster < 0 || boxes[1].Cluster < 0 {
t.Fatal("first band should be clustered")
}
if boxes[0].Cluster != boxes[1].Cluster {
t.Fatalf("same band: got %d and %d", boxes[0].Cluster, boxes[1].Cluster)
}
if boxes[2].Cluster != boxes[3].Cluster {
t.Fatalf("second band: got %d and %d", boxes[2].Cluster, boxes[3].Cluster)
}
if boxes[0].Cluster == boxes[2].Cluster {
t.Fatal("distant Y bands should differ")
}
}
func TestClusterRowsSameBand(t *testing.T) {
boxes := []indexedBox{
{Text: "a", Y: 50},
{Text: "b", Y: 52},
{Text: "c", Y: 54},
}
ClusterRows(boxes, 10, 1)
id := boxes[0].Cluster
for i, b := range boxes {
if b.Cluster != id {
t.Fatalf("box %d cluster=%d, want %d", i, b.Cluster, id)
}
}
}
func TestClusterRowsEmpty(t *testing.T) {
ClusterRows(nil, 10, 1) // no panic
ClusterRows([]indexedBox{}, 10, 1)
}
func TestClusterRowsNoiseMinSamples(t *testing.T) {
boxes := []indexedBox{
{Text: "lonely", Y: 10},
{Text: "pair-a", Y: 200},
{Text: "pair-b", Y: 201},
}
// minSamples=2: lonely point stays noise (-1); pair forms a cluster
ClusterRows(boxes, 5, 2)
if boxes[0].Cluster != -1 {
t.Fatalf("lonely cluster=%d, want -1 (noise)", boxes[0].Cluster)
}
if boxes[1].Cluster < 0 || boxes[1].Cluster != boxes[2].Cluster {
t.Fatalf("pair clusters=%d,%d", boxes[1].Cluster, boxes[2].Cluster)
}
}