Wideband autonomous SDR analysis engine forked from sdr-visual-suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
3.0KB

  1. package pipeline
  2. import "testing"
  3. func TestScheduleCandidates(t *testing.T) {
  4. policy := Policy{MaxRefinementJobs: 2, MinCandidateSNRDb: 5}
  5. cands := []Candidate{
  6. {ID: 1, CenterHz: 100, SNRDb: 4, BandwidthHz: 10000, PeakDb: 1},
  7. {ID: 2, CenterHz: 200, SNRDb: 12, BandwidthHz: 50000, PeakDb: 3},
  8. {ID: 3, CenterHz: 300, SNRDb: 10, BandwidthHz: 25000, PeakDb: 2},
  9. {ID: 4, CenterHz: 400, SNRDb: 20, BandwidthHz: 100000, PeakDb: 5},
  10. }
  11. got := ScheduleCandidates(cands, policy)
  12. if len(got) != 2 {
  13. t.Fatalf("expected 2 scheduled candidates, got %d", len(got))
  14. }
  15. if got[0].Candidate.ID != 4 {
  16. t.Fatalf("expected strongest candidate first, got id=%d", got[0].Candidate.ID)
  17. }
  18. if got[1].Candidate.ID != 2 {
  19. t.Fatalf("expected next strongest candidate second, got id=%d", got[1].Candidate.ID)
  20. }
  21. }
  22. func TestBuildRefinementPlanTracksDrops(t *testing.T) {
  23. policy := Policy{MaxRefinementJobs: 1, MinCandidateSNRDb: 10}
  24. cands := []Candidate{
  25. {ID: 1, CenterHz: 100, SNRDb: 4, BandwidthHz: 10000, PeakDb: 1},
  26. {ID: 2, CenterHz: 200, SNRDb: 12, BandwidthHz: 50000, PeakDb: 3},
  27. {ID: 3, CenterHz: 300, SNRDb: 11, BandwidthHz: 25000, PeakDb: 2},
  28. }
  29. plan := BuildRefinementPlan(cands, policy)
  30. if plan.TotalCandidates != 3 {
  31. t.Fatalf("expected total candidates 3, got %d", plan.TotalCandidates)
  32. }
  33. if plan.DroppedBySNR != 1 {
  34. t.Fatalf("expected 1 dropped by SNR, got %d", plan.DroppedBySNR)
  35. }
  36. if plan.DroppedByBudget != 1 {
  37. t.Fatalf("expected 1 dropped by budget, got %d", plan.DroppedByBudget)
  38. }
  39. if len(plan.Selected) != 1 || plan.Selected[0].Candidate.ID != 2 {
  40. t.Fatalf("unexpected plan selection: %+v", plan.Selected)
  41. }
  42. }
  43. func TestBuildRefinementPlanRespectsMaxConcurrent(t *testing.T) {
  44. policy := Policy{MaxRefinementJobs: 5, RefinementMaxConcurrent: 2, MinCandidateSNRDb: 0}
  45. cands := []Candidate{
  46. {ID: 1, CenterHz: 100, SNRDb: 9},
  47. {ID: 2, CenterHz: 200, SNRDb: 8},
  48. {ID: 3, CenterHz: 300, SNRDb: 7},
  49. }
  50. plan := BuildRefinementPlan(cands, policy)
  51. if plan.Budget != 2 {
  52. t.Fatalf("expected budget 2, got %d", plan.Budget)
  53. }
  54. if len(plan.Selected) != 2 {
  55. t.Fatalf("expected 2 selected, got %d", len(plan.Selected))
  56. }
  57. }
  58. func TestAutoSpanForHint(t *testing.T) {
  59. span, source := AutoSpanForHint("WFM_STEREO")
  60. if span < 150000 || source == "" {
  61. t.Fatalf("expected WFM span, got %.0f (%s)", span, source)
  62. }
  63. span, source = AutoSpanForHint("CW")
  64. if span != 500 || source == "" {
  65. t.Fatalf("expected CW span, got %.0f (%s)", span, source)
  66. }
  67. span, source = AutoSpanForHint("")
  68. if span != 0 || source != "" {
  69. t.Fatalf("expected empty span for unknown hint, got %.0f (%s)", span, source)
  70. }
  71. }
  72. func TestScheduleCandidatesPriorityBoost(t *testing.T) {
  73. policy := Policy{MaxRefinementJobs: 1, MinCandidateSNRDb: 0, SignalPriorities: []string{"digital"}}
  74. got := ScheduleCandidates([]Candidate{
  75. {ID: 1, SNRDb: 15, Hint: "voice"},
  76. {ID: 2, SNRDb: 14, Hint: "digital-burst"},
  77. }, policy)
  78. if len(got) != 1 || got[0].Candidate.ID != 2 {
  79. t.Fatalf("expected priority boost to favor digital candidate, got %+v", got)
  80. }
  81. }