Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

134 строки
3.3KB

  1. package app
  2. import (
  3. "context"
  4. "testing"
  5. "time"
  6. cfgpkg "github.com/jan/fm-rds-tx/internal/config"
  7. "github.com/jan/fm-rds-tx/internal/platform"
  8. )
  9. func TestEngineContinuousRun(t *testing.T) {
  10. cfg := cfgpkg.Default()
  11. driver := platform.NewSimulatedDriver(nil)
  12. eng := NewEngine(cfg, driver)
  13. eng.SetChunkDuration(10 * time.Millisecond)
  14. ctx := context.Background()
  15. if err := eng.Start(ctx); err != nil {
  16. t.Fatalf("start: %v", err)
  17. }
  18. // Let it run for 200ms
  19. time.Sleep(200 * time.Millisecond)
  20. stats := eng.Stats()
  21. if stats.State != "running" {
  22. t.Fatalf("expected running, got %s", stats.State)
  23. }
  24. if stats.ChunksProduced < 5 {
  25. t.Fatalf("expected at least 5 chunks, got %d", stats.ChunksProduced)
  26. }
  27. if stats.TotalSamples == 0 {
  28. t.Fatal("expected non-zero samples")
  29. }
  30. if err := eng.Stop(ctx); err != nil {
  31. t.Fatalf("stop: %v", err)
  32. }
  33. stats = eng.Stats()
  34. if stats.State != "idle" {
  35. t.Fatalf("expected idle after stop, got %s", stats.State)
  36. }
  37. }
  38. func TestEngineDoubleStartFails(t *testing.T) {
  39. cfg := cfgpkg.Default()
  40. driver := platform.NewSimulatedDriver(nil)
  41. eng := NewEngine(cfg, driver)
  42. ctx := context.Background()
  43. if err := eng.Start(ctx); err != nil {
  44. t.Fatalf("first start: %v", err)
  45. }
  46. defer eng.Stop(ctx)
  47. if err := eng.Start(ctx); err == nil {
  48. t.Fatal("expected error on double start")
  49. }
  50. }
  51. func TestEngineDriverStats(t *testing.T) {
  52. cfg := cfgpkg.Default()
  53. driver := platform.NewSimulatedDriver(nil)
  54. eng := NewEngine(cfg, driver)
  55. eng.SetChunkDuration(10 * time.Millisecond)
  56. ctx := context.Background()
  57. _ = eng.Start(ctx)
  58. time.Sleep(100 * time.Millisecond)
  59. _ = eng.Stop(ctx)
  60. driverStats := driver.Stats()
  61. if driverStats.SamplesWritten == 0 {
  62. t.Fatal("expected driver to have written samples")
  63. }
  64. if driverStats.FramesWritten == 0 {
  65. t.Fatal("expected driver to have written frames")
  66. }
  67. }
  68. func TestEngineSplitRate(t *testing.T) {
  69. // Simulate Pluto-like config: composite at 228kHz, device at 2.28MHz
  70. cfg := cfgpkg.Default()
  71. cfg.Backend.DeviceSampleRateHz = 2280000 // 10:1 ratio
  72. driver := platform.NewSimulatedDriver(nil)
  73. eng := NewEngine(cfg, driver)
  74. eng.SetChunkDuration(10 * time.Millisecond)
  75. // Verify split-rate path was chosen
  76. if eng.upsampler == nil {
  77. t.Fatal("expected split-rate mode (upsampler != nil)")
  78. }
  79. ctx := context.Background()
  80. if err := eng.Start(ctx); err != nil {
  81. t.Fatalf("start: %v", err)
  82. }
  83. time.Sleep(200 * time.Millisecond)
  84. stats := eng.Stats()
  85. if stats.ChunksProduced < 5 {
  86. t.Fatalf("expected at least 5 chunks, got %d", stats.ChunksProduced)
  87. }
  88. // With 10:1 upsampling and 10ms chunks at 228kHz source:
  89. // 2280 src samples → 22800 output samples per chunk
  90. // 5 chunks minimum → at least 114000 samples
  91. if stats.TotalSamples < 50000 {
  92. t.Fatalf("expected at least 50000 upsampled samples, got %d", stats.TotalSamples)
  93. }
  94. if err := eng.Stop(ctx); err != nil {
  95. t.Fatalf("stop: %v", err)
  96. }
  97. if stats.Underruns > 0 {
  98. t.Fatalf("unexpected underruns: %d", stats.Underruns)
  99. }
  100. }
  101. func TestEngineSameRate(t *testing.T) {
  102. // Default config: deviceSampleRateHz=0, compositeRateHz=228000
  103. // EffectiveDeviceRate = 228000 → same-rate mode, no upsampler
  104. cfg := cfgpkg.Default()
  105. driver := platform.NewSimulatedDriver(nil)
  106. eng := NewEngine(cfg, driver)
  107. if eng.upsampler != nil {
  108. t.Fatal("expected same-rate mode (upsampler == nil)")
  109. }
  110. }