package benchmark import ( "bytes" "strings" "testing" "time" ) // TestValidateRejectsCompressibleThroughput ist der wichtigste Test des Pakets. // // In Phase 4 zeigte ein Messlauf eine 1021-fache Kompression — die Testdaten // waren periodisch, und die Zahl damit wertlos. Ein Durchsatz aus // komprimierbaren Daten hat dasselbe Problem: Er misst, wie schnell zstd // Wiederholungen erkennt, nicht wie schnell die Anlage arbeitet. // // Die Prüfung sitzt im Modell, nicht in der Anleitung: Wer eine Messreihe // ergänzt, stolpert darüber, statt sie zu übersehen. func TestValidateRejectsCompressibleThroughput(testInstance *testing.T) { compressibleResult := &Result{ ScenarioName: "komprimierbar", Data: DataShape{Compressible: true, TotalBytes: 1 << 30}, BytesProcessed: 1 << 30, Usage: ResourceUsage{WallClockSeconds: 5}, } if validationError := compressibleResult.Validate(); validationError == nil { testInstance.Error("ein Durchsatz aus komprimierbaren Daten wurde angenommen") } } // TestValidateRejectsTooShortRuns prueft die Mindestlaufzeit. // // Unter einer halben Sekunde schlagen der Start der Arbeiter, das Öffnen des // Repositorys und die erste Speicherbereinigung stärker durch als die // eigentliche Arbeit. func TestValidateRejectsTooShortRuns(testInstance *testing.T) { shortResult := &Result{ ScenarioName: "zu kurz", Data: DataShape{Compressible: false, TotalBytes: 1024}, BytesProcessed: 1024, Usage: ResourceUsage{WallClockSeconds: 0.05}, } if validationError := shortResult.Validate(); validationError == nil { testInstance.Error("ein Lauf von 50 ms wurde als aussagekräftig angenommen") } longEnoughResult := &Result{ ScenarioName: "lang genug", Data: DataShape{Compressible: false, TotalBytes: 1 << 30}, BytesProcessed: 1 << 30, Usage: ResourceUsage{WallClockSeconds: 3}, } if validationError := longEnoughResult.Validate(); validationError != nil { testInstance.Errorf("ein Lauf von drei Sekunden wurde abgelehnt: %v", validationError) } } // TestRecorderMeasuresRealWork prueft, dass ueberhaupt gemessen wird. // // Ein Messwerk, das immer null liefert, ist von einer unendlich schnellen // Anlage nicht zu unterscheiden. func TestRecorderMeasuresRealWork(testInstance *testing.T) { recorder := StartRecording() // Etwas Arbeit, die Rechenzeit **und** Speicher kostet. accumulatedSum := 0 for iteration := 0; iteration < 40; iteration++ { workBuffer := make([]byte, 4*1024*1024) for bufferIndex := range workBuffer { workBuffer[bufferIndex] = byte(bufferIndex) } accumulatedSum += len(workBuffer) } measuredUsage := recorder.Stop() if accumulatedSum == 0 { testInstance.Fatal("die Arbeit wurde wegoptimiert") } if measuredUsage.WallClockSeconds <= 0 { testInstance.Error("es wurde keine Laufzeit gemessen") } if measuredUsage.UserCPUSeconds <= 0 { testInstance.Error("es wurde keine Rechenzeit gemessen") } if measuredUsage.AllocatedBytes <= 0 { testInstance.Error("es wurde keine Speicheranforderung gemessen") } } // TestReportNamesWhatItDidNotMeasure prueft die Vollstaendigkeit des Berichts. // // Ein Messbericht, der verschweigt, was er nicht gemessen hat, liest sich // vollständig und ist es nicht — dieselbe Regel wie bei den ungeprüften // Bereichen im Security Center (Phase 15). func TestReportNamesWhatItDidNotMeasure(testInstance *testing.T) { measurementReport := &Report{ Title: "Messreihe", Machine: CurrentMachine(), GeneratedAt: time.Now().UTC(), } measurementReport.AddSkipped("Eine große VM", "Ohne Proxmox-Verbund nicht messbar; der Provider ist nicht abgeschlossen.") var outputBuffer bytes.Buffer measurementReport.WriteText(&outputBuffer) reportText := outputBuffer.String() if !strings.Contains(reportText, "Nicht gemessen") { testInstance.Error("der Bericht nennt den übersprungenen Abschnitt nicht") } if !strings.Contains(reportText, "Proxmox") { testInstance.Error("der Bericht nennt den Grund nicht") } } // TestCompressibleThroughputIsNotPrinted prueft die Ausgabe. // // Auch wenn ein Lauf komprimierbare Daten misst — etwa um die Kompression zu // zeigen —, darf im Bericht keine Durchsatzzahl stehen, die jemand // herausschneiden und zitieren kann. func TestCompressibleThroughputIsNotPrinted(testInstance *testing.T) { measurementReport := &Report{ Title: "Messreihe", Machine: CurrentMachine(), GeneratedAt: time.Now().UTC(), Results: []*Result{{ ScenarioName: "Kompression", Description: "Gut komprimierbare Textdaten.", Data: DataShape{Description: "Text", TotalBytes: 1 << 30, Compressible: true}, BytesProcessed: 1 << 30, Usage: ResourceUsage{WallClockSeconds: 2}, }}, } var outputBuffer bytes.Buffer measurementReport.WriteText(&outputBuffer) if !strings.Contains(outputBuffer.String(), "nicht ausgewiesen") { testInstance.Error("bei komprimierbaren Daten wurde ein Durchsatz ausgewiesen") } } // TestCPUEfficiencyReflectsParallelism prueft die Auslastungskennzahl. func TestCPUEfficiencyReflectsParallelism(testInstance *testing.T) { singleCoreUsage := ResourceUsage{WallClockSeconds: 10, UserCPUSeconds: 9, SystemCPUSeconds: 1} if efficiency := singleCoreUsage.CPUEfficiency(); efficiency < 0.99 || efficiency > 1.01 { testInstance.Errorf("ein ausgelasteter Kern ergab %.2f statt 1,0", efficiency) } idleUsage := ResourceUsage{WallClockSeconds: 10, UserCPUSeconds: 0.5} if efficiency := idleUsage.CPUEfficiency(); efficiency > 0.1 { testInstance.Errorf("ein wartender Lauf ergab %.2f", efficiency) } }