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.