go-proxy/job_test.go
Snider 31a151d23c feat(proxy): implement RFC test coverage and AX usage-example comments
Add missing Good/Bad/Ugly test triplets per RFC section 22:
- stats_test.go: OnAccept/OnReject/Tick/OnLogin/OnClose tests with
  concurrency race test and top-10 diff slot verification
- ratelimit_test.go: full Good/Bad/Ugly set including ban persistence
  and disabled-limiter edge case
- customdiff_test.go: renamed to Apply_Good/Bad/Ugly convention per RFC
- storage_test.go: full Add_Good/Bad/Ugly set including 256-slot fill,
  overflow rejection, and dead-slot reclamation via SetJob
- job_test.go: added Good/Bad/Ugly for BlobWithFixedByte, DifficultyFromTarget,
  and IsValid

Add Miner.Diff() public getter for the last difficulty sent to miner.

Add AX-compliant usage-example comments (principle 2) to all Miner
accessors, Proxy query methods, EffectiveShareDifficulty, targetFromDifficulty,
MinerSnapshot, and RateLimiter.IsActive.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-05 07:02:54 +01:00

116 lines
3.5 KiB
Go

package proxy
import (
"strings"
"testing"
)
// TestJob_BlobWithFixedByte_Good verifies nonce patching on a full 160-char blob.
//
// job := proxy.Job{Blob: strings.Repeat("0", 160)}
// result := job.BlobWithFixedByte(0x2A) // chars 78-79 become "2a"
func TestJob_BlobWithFixedByte_Good(t *testing.T) {
job := Job{Blob: strings.Repeat("0", 160)}
got := job.BlobWithFixedByte(0x2A)
if len(got) != 160 {
t.Fatalf("expected length 160, got %d", len(got))
}
if got[78:80] != "2a" {
t.Fatalf("expected fixed byte patch, got %q", got[78:80])
}
}
// TestJob_BlobWithFixedByte_Bad verifies a short blob is returned unchanged.
//
// job := proxy.Job{Blob: "0000"}
// result := job.BlobWithFixedByte(0x2A) // too short, returned as-is
func TestJob_BlobWithFixedByte_Bad(t *testing.T) {
shortBlob := "0000"
job := Job{Blob: shortBlob}
got := job.BlobWithFixedByte(0x2A)
if got != shortBlob {
t.Fatalf("expected short blob to be returned unchanged, got %q", got)
}
}
// TestJob_BlobWithFixedByte_Ugly verifies fixedByte 0xFF renders as lowercase "ff".
//
// job := proxy.Job{Blob: strings.Repeat("0", 160)}
// result := job.BlobWithFixedByte(0xFF) // chars 78-79 become "ff" (not "FF")
func TestJob_BlobWithFixedByte_Ugly(t *testing.T) {
job := Job{Blob: strings.Repeat("0", 160)}
got := job.BlobWithFixedByte(0xFF)
if got[78:80] != "ff" {
t.Fatalf("expected lowercase 'ff', got %q", got[78:80])
}
if len(got) != 160 {
t.Fatalf("expected blob length preserved, got %d", len(got))
}
}
// TestJob_DifficultyFromTarget_Good verifies a known target converts to the expected difficulty.
//
// job := proxy.Job{Target: "b88d0600"}
// diff := job.DifficultyFromTarget() // 10000
func TestJob_DifficultyFromTarget_Good(t *testing.T) {
job := Job{Target: "b88d0600"}
if got := job.DifficultyFromTarget(); got != 10000 {
t.Fatalf("expected difficulty 10000, got %d", got)
}
}
// TestJob_DifficultyFromTarget_Bad verifies a zero target produces difficulty 0 without panic.
//
// job := proxy.Job{Target: "00000000"}
// diff := job.DifficultyFromTarget() // 0 (no divide-by-zero)
func TestJob_DifficultyFromTarget_Bad(t *testing.T) {
job := Job{Target: "00000000"}
if got := job.DifficultyFromTarget(); got != 0 {
t.Fatalf("expected difficulty 0 for zero target, got %d", got)
}
}
// TestJob_DifficultyFromTarget_Ugly verifies the maximum target "ffffffff" yields difficulty 1.
//
// job := proxy.Job{Target: "ffffffff"}
// diff := job.DifficultyFromTarget() // 1
func TestJob_DifficultyFromTarget_Ugly(t *testing.T) {
job := Job{Target: "ffffffff"}
if got := job.DifficultyFromTarget(); got != 1 {
t.Fatalf("expected minimum difficulty 1, got %d", got)
}
}
// TestJob_IsValid_Good verifies a job with blob and job ID is valid.
//
// job := proxy.Job{Blob: "abc", JobID: "job-1"}
// job.IsValid() // true
func TestJob_IsValid_Good(t *testing.T) {
job := Job{Blob: "abc", JobID: "job-1"}
if !job.IsValid() {
t.Fatalf("expected job with blob and job id to be valid")
}
}
// TestJob_IsValid_Bad verifies a job with empty blob or job ID is invalid.
//
// job := proxy.Job{Blob: "", JobID: "job-1"}
// job.IsValid() // false
func TestJob_IsValid_Bad(t *testing.T) {
if (Job{Blob: "", JobID: "job-1"}).IsValid() {
t.Fatalf("expected empty blob to be invalid")
}
if (Job{Blob: "abc", JobID: ""}).IsValid() {
t.Fatalf("expected empty job id to be invalid")
}
}
// TestJob_IsValid_Ugly verifies a zero-value job is invalid.
//
// job := proxy.Job{}
// job.IsValid() // false
func TestJob_IsValid_Ugly(t *testing.T) {
if (Job{}).IsValid() {
t.Fatalf("expected zero-value job to be invalid")
}
}