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.

80 lines
2.3KB

  1. package main
  2. import (
  3. "testing"
  4. "sdr-wideband-suite/internal/config"
  5. "sdr-wideband-suite/internal/detector"
  6. fftutil "sdr-wideband-suite/internal/fft"
  7. "sdr-wideband-suite/internal/pipeline"
  8. )
  9. func TestNewDSPRuntime(t *testing.T) {
  10. cfg := config.Default()
  11. det := detector.New(cfg.Detector, cfg.SampleRate, cfg.FFTSize)
  12. window := fftutil.Hann(cfg.FFTSize)
  13. rt := newDSPRuntime(cfg, det, window, &gpuStatus{})
  14. if rt == nil {
  15. t.Fatalf("runtime is nil")
  16. }
  17. if rt.plan == nil {
  18. t.Fatalf("fft plan is nil")
  19. }
  20. if rt.cfg.FFTSize != cfg.FFTSize {
  21. t.Fatalf("unexpected fft size: %d", rt.cfg.FFTSize)
  22. }
  23. }
  24. func TestScheduledCandidateSelectionUsesPolicy(t *testing.T) {
  25. cfg := config.Default()
  26. cfg.Resources.MaxRefinementJobs = 1
  27. cfg.Refinement.MinCandidateSNRDb = 6
  28. policy := pipeline.PolicyFromConfig(cfg)
  29. got := pipeline.ScheduleCandidates([]pipeline.Candidate{
  30. {ID: 1, SNRDb: 3, BandwidthHz: 1000},
  31. {ID: 2, SNRDb: 12, BandwidthHz: 5000},
  32. {ID: 3, SNRDb: 8, BandwidthHz: 7000},
  33. }, policy)
  34. if len(got) != 2 {
  35. t.Fatalf("expected 2 scheduled candidates after gating, got %d", len(got))
  36. }
  37. if got[0].Candidate.ID != 2 {
  38. t.Fatalf("expected highest priority candidate, got %d", got[0].Candidate.ID)
  39. }
  40. }
  41. func TestSurveillanceLevelsRespectStrategy(t *testing.T) {
  42. cfg := config.Default()
  43. det := detector.New(cfg.Detector, cfg.SampleRate, cfg.FFTSize)
  44. window := fftutil.Hann(cfg.FFTSize)
  45. rt := newDSPRuntime(cfg, det, window, &gpuStatus{})
  46. policy := pipeline.Policy{SurveillanceStrategy: "single-resolution"}
  47. plan := rt.buildSurveillancePlan(policy)
  48. if len(plan.Levels) != 1 {
  49. t.Fatalf("expected single level for single-resolution, got %d", len(plan.Levels))
  50. }
  51. policy.SurveillanceStrategy = "multi-res"
  52. plan = rt.buildSurveillancePlan(policy)
  53. if len(plan.Levels) != 2 {
  54. t.Fatalf("expected secondary level for multi-res, got %d", len(plan.Levels))
  55. }
  56. if plan.Levels[1].Decimation != 2 {
  57. t.Fatalf("expected decimation factor 2, got %d", plan.Levels[1].Decimation)
  58. }
  59. }
  60. func TestWindowSpanBounds(t *testing.T) {
  61. windows := []pipeline.RefinementWindow{
  62. {SpanHz: 8000},
  63. {SpanHz: 16000},
  64. {SpanHz: 12000},
  65. }
  66. minSpan, maxSpan, ok := windowSpanBounds(windows)
  67. if !ok {
  68. t.Fatalf("expected spans to be found")
  69. }
  70. if minSpan != 8000 || maxSpan != 16000 {
  71. t.Fatalf("unexpected span bounds: min %.0f max %.0f", minSpan, maxSpan)
  72. }
  73. }