processor/locomo_test.go GO 273 lines View on github.com → Search inside
1// SPDX-License-Identifier: MIT23package processor45import (6	"math"7	"testing"8)910func TestLocomoComplexityDensityZeroCode(t *testing.T) {11	got := LocomoComplexityDensity(10, 0)12	if got != 0 {13		t.Errorf("Expected 0 for zero code lines, got %f", got)14	}15}1617func TestLocomoComplexityDensity(t *testing.T) {18	got := LocomoComplexityDensity(30, 100)19	if math.Abs(got-0.3) > 0.001 {20		t.Errorf("Expected 0.3, got %f", got)21	}22}2324func TestLocomoComplexityFactor(t *testing.T) {25	// density 0.3, weight 5 → 1 + sqrt(0.3)*5 ≈ 1 + 0.5477*5 ≈ 3.73826	got := LocomoComplexityFactor(0.3, 5)27	if got < 3.7 || got > 3.8 {28		t.Errorf("Expected ~3.74, got %f", got)29	}30}3132func TestLocomoComplexityFactorLowDensity(t *testing.T) {33	// density 0.05, weight 5 → 1 + sqrt(0.05)*5 ≈ 1 + 0.2236*5 ≈ 2.11834	got := LocomoComplexityFactor(0.05, 5)35	if got < 2.0 || got > 2.2 {36		t.Errorf("Expected ~2.12, got %f", got)37	}38}3940func TestLocomoIterationFactor(t *testing.T) {41	// density 0.3, base 1.5, weight 2 → 1.5 + sqrt(0.3)*2 ≈ 1.5 + 1.095 ≈ 2.59542	got := LocomoIterationFactor(0.3, 1.5, 2)43	if got < 2.5 || got > 2.7 {44		t.Errorf("Expected ~2.60, got %f", got)45	}46}4748func TestLocomoIterationFactorLowDensity(t *testing.T) {49	// density 0.05, base 1.5, weight 2 → 1.5 + sqrt(0.05)*2 ≈ 1.5 + 0.447 ≈ 1.94750	got := LocomoIterationFactor(0.05, 1.5, 2)51	if got < 1.9 || got > 2.0 {52		t.Errorf("Expected ~1.95, got %f", got)53	}54}5556func TestLocomoEstimateBasic(t *testing.T) {57	// Reset to defaults58	LocomoPresetName = "medium"59	LocomoTokensPerLine = 1060	LocomoBaseInputPerLine = 2061	LocomoComplexityWeight = 562	LocomoIterations = 1.563	LocomoIterationWeight = 264	LocomoReviewMinutesPerLine = 0.0165	LocomoConfig = ""66	LocomoInputPriceSet = false67	LocomoOutputPriceSet = false68	LocomoTPSSet = false69	LocomoCyclesSet = false7071	result := LocomoEstimate(1000, 100)7273	// density = 0.1, complexityFactor ≈ 2.58, iterationFactor ≈ 2.1374	// outputTokens = 1000 * 10 * 2.13 = 2132275	// inputTokens = 1000 * 20 * 2.58 * 2.13 = 10992976	// cost = (109929/1M * 3) + (21322/1M * 15) ≈ 0.33 + 0.32 ≈ 0.657778	if result.OutputTokens <= 0 {79		t.Error("Expected positive output tokens")80	}81	if result.InputTokens <= 0 {82		t.Error("Expected positive input tokens")83	}84	if result.Cost <= 0 {85		t.Error("Expected positive cost")86	}87	if result.GenerationSeconds <= 0 {88		t.Error("Expected positive generation time")89	}90	if result.ReviewHours <= 0 {91		t.Error("Expected positive review hours")92	}93	if result.AverageComplexityMult <= 1 {94		t.Error("Expected complexity multiplier > 1")95	}96	if result.Preset != "medium" {97		t.Errorf("Expected preset medium, got %s", result.Preset)98	}99}100101func TestLocomoEstimateZeroCode(t *testing.T) {102	LocomoPresetName = "medium"103	LocomoConfig = ""104	LocomoInputPriceSet = false105	LocomoOutputPriceSet = false106	LocomoTPSSet = false107	LocomoTokensPerLine = 10108	LocomoBaseInputPerLine = 20109	LocomoComplexityWeight = 5110	LocomoIterations = 1.5111	LocomoIterationWeight = 2112	LocomoReviewMinutesPerLine = 0.01113114	result := LocomoEstimate(0, 0)115116	if result.OutputTokens != 0 {117		t.Errorf("Expected 0 output tokens for zero code, got %f", result.OutputTokens)118	}119	if result.Cost != 0 {120		t.Errorf("Expected 0 cost for zero code, got %f", result.Cost)121	}122}123124func TestLocomoEstimateHighComplexity(t *testing.T) {125	LocomoPresetName = "medium"126	LocomoConfig = ""127	LocomoInputPriceSet = false128	LocomoOutputPriceSet = false129	LocomoTPSSet = false130	LocomoTokensPerLine = 10131	LocomoBaseInputPerLine = 20132	LocomoComplexityWeight = 5133	LocomoIterations = 1.5134	LocomoIterationWeight = 2135	LocomoReviewMinutesPerLine = 0.01136137	low := LocomoEstimate(1000, 50)   // density 0.05138	high := LocomoEstimate(1000, 300) // density 0.3139140	if high.Cost <= low.Cost {141		t.Error("Higher complexity should produce higher cost")142	}143144	// The ratio should be in a reasonable range (not 12x like v1 linear would produce)145	ratio := high.Cost / low.Cost146	if ratio > 5 {147		t.Errorf("Cost ratio between high and low complexity seems too high: %f", ratio)148	}149}150151func TestLocomoEstimateLocalLlama(t *testing.T) {152	LocomoPresetName = "local"153	LocomoConfig = ""154	LocomoInputPriceSet = false155	LocomoOutputPriceSet = false156	LocomoTPSSet = false157	LocomoTokensPerLine = 10158	LocomoBaseInputPerLine = 20159	LocomoComplexityWeight = 5160	LocomoIterations = 1.5161	LocomoIterationWeight = 2162	LocomoReviewMinutesPerLine = 0.01163164	result := LocomoEstimate(1000, 100)165166	if result.Cost != 0 {167		t.Errorf("Expected 0 cost for local, got %f", result.Cost)168	}169	if result.GenerationSeconds <= 0 {170		t.Error("Expected positive generation time even for local model")171	}172}173174func TestGetLocomoPresetUnknown(t *testing.T) {175	p := GetLocomoPreset("nonexistent")176	if p.Name != "medium" {177		t.Errorf("Expected fallback to medium, got %s", p.Name)178	}179}180181func TestParseLocomoConfig(t *testing.T) {182	var a, b, c, d, e float64183	parseLocomoConfig("8,15,3,2.0,1.5", &a, &b, &c, &d, &e)184185	if a != 8 || b != 15 || c != 3 || d != 2.0 || e != 1.5 {186		t.Errorf("Config parsing failed: got %f,%f,%f,%f,%f", a, b, c, d, e)187	}188}189190func TestParseLocomoConfigInvalid(t *testing.T) {191	a, b, c, d, e := 10.0, 20.0, 5.0, 1.5, 2.0192	parseLocomoConfig("bad,config", &a, &b, &c, &d, &e)193194	// Should remain unchanged195	if a != 10 || b != 20 || c != 5 || d != 1.5 || e != 2 {196		t.Error("Invalid config should not change defaults")197	}198}199200func TestLocomoEstimateIterationFactorPopulated(t *testing.T) {201	LocomoPresetName = "medium"202	LocomoConfig = ""203	LocomoInputPriceSet = false204	LocomoOutputPriceSet = false205	LocomoTPSSet = false206	LocomoCyclesSet = false207	LocomoTokensPerLine = 10208	LocomoBaseInputPerLine = 20209	LocomoComplexityWeight = 5210	LocomoIterations = 1.5211	LocomoIterationWeight = 2212	LocomoReviewMinutesPerLine = 0.01213214	result := LocomoEstimate(1000, 100)215216	if result.IterationFactor <= 0 {217		t.Error("Expected positive IterationFactor")218	}219	// density = 0.1, iFactor = 1.5 + sqrt(0.1)*2 ≈ 2.13220	if result.IterationFactor < 2.0 || result.IterationFactor > 2.3 {221		t.Errorf("Expected IterationFactor ~2.13, got %f", result.IterationFactor)222	}223}224225func TestLocomoCyclesOverride(t *testing.T) {226	LocomoPresetName = "medium"227	LocomoConfig = ""228	LocomoInputPriceSet = false229	LocomoOutputPriceSet = false230	LocomoTPSSet = false231	LocomoTokensPerLine = 10232	LocomoBaseInputPerLine = 20233	LocomoComplexityWeight = 5234	LocomoIterations = 1.5235	LocomoIterationWeight = 2236	LocomoReviewMinutesPerLine = 0.01237238	// First get the default result239	LocomoCyclesSet = false240	defaultResult := LocomoEstimate(1000, 100)241242	// Now override with 100 cycles243	LocomoCyclesSet = true244	LocomoCyclesOverride = 100245	overrideResult := LocomoEstimate(1000, 100)246247	// Reset248	LocomoCyclesSet = false249	LocomoCyclesOverride = 0250251	if overrideResult.IterationFactor != 100 {252		t.Errorf("Expected IterationFactor 100, got %f", overrideResult.IterationFactor)253	}254	if overrideResult.Cost <= defaultResult.Cost {255		t.Error("Expected override cost to be higher than default")256	}257	// Cost should scale roughly proportionally with cycles258	ratio := overrideResult.Cost / defaultResult.Cost259	if ratio < 30 || ratio > 70 {260		t.Errorf("Cost ratio seems off: %f (expected ~47x for 100 vs ~2.13 cycles)", ratio)261	}262}263264func TestParseLocomoConfigPartialInvalid(t *testing.T) {265	a, b, c, d, e := 10.0, 20.0, 5.0, 1.5, 2.0266	parseLocomoConfig("8,15,bad,2.0,1.5", &a, &b, &c, &d, &e)267268	// Should remain unchanged since one part failed269	if a != 10 || b != 20 || c != 5 || d != 1.5 || e != 2 {270		t.Error("Partially invalid config should not change defaults")271	}272}

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.