remove tests
This commit is contained in:
@@ -1,476 +0,0 @@
|
||||
package recording
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDefaultConfig(t *testing.T) {
|
||||
config := DefaultConfig()
|
||||
|
||||
t.Run("default values", func(t *testing.T) {
|
||||
if config.SampleRate != 16000 {
|
||||
t.Errorf("default sample rate should be 16000, got %d", config.SampleRate)
|
||||
}
|
||||
if config.Channels != 1 {
|
||||
t.Errorf("default channels should be 1, got %d", config.Channels)
|
||||
}
|
||||
if config.Format != "s16" {
|
||||
t.Errorf("default format should be s16, got %s", config.Format)
|
||||
}
|
||||
if config.BufferSize != 8192 {
|
||||
t.Errorf("default buffer size should be 8192, got %d", config.BufferSize)
|
||||
}
|
||||
if config.Device != "" {
|
||||
t.Errorf("default device should be empty, got %s", config.Device)
|
||||
}
|
||||
if config.ChannelBufferSize != 30 {
|
||||
t.Errorf("default channel buffer size should be 30, got %d", config.ChannelBufferSize)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewRecorder(t *testing.T) {
|
||||
config := DefaultConfig()
|
||||
recorder := NewRecorder(config)
|
||||
|
||||
t.Run("initial state", func(t *testing.T) {
|
||||
if recorder == nil {
|
||||
t.Fatal("recorder should not be nil")
|
||||
}
|
||||
if recorder.IsRecording() {
|
||||
t.Error("recorder should not be recording initially")
|
||||
}
|
||||
if recorder.config.SampleRate != config.SampleRate {
|
||||
t.Error("recorder should store the provided config")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewDefaultRecorder(t *testing.T) {
|
||||
recorder := NewDefaultRecorder()
|
||||
|
||||
t.Run("default recorder", func(t *testing.T) {
|
||||
if recorder == nil {
|
||||
t.Fatal("default recorder should not be nil")
|
||||
}
|
||||
if recorder.IsRecording() {
|
||||
t.Error("default recorder should not be recording initially")
|
||||
}
|
||||
if recorder.config.SampleRate != 16000 {
|
||||
t.Error("default recorder should use default config")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRecorderValidateConfig(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
config Config
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "valid default config",
|
||||
config: DefaultConfig(),
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "invalid sample rate",
|
||||
config: Config{
|
||||
SampleRate: 0,
|
||||
Channels: 1,
|
||||
Format: "s16",
|
||||
BufferSize: 8192,
|
||||
ChannelBufferSize: 30,
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "negative sample rate",
|
||||
config: Config{
|
||||
SampleRate: -1,
|
||||
Channels: 1,
|
||||
Format: "s16",
|
||||
BufferSize: 8192,
|
||||
ChannelBufferSize: 30,
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid channels",
|
||||
config: Config{
|
||||
SampleRate: 16000,
|
||||
Channels: 0,
|
||||
Format: "s16",
|
||||
BufferSize: 8192,
|
||||
ChannelBufferSize: 30,
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid buffer size",
|
||||
config: Config{
|
||||
SampleRate: 16000,
|
||||
Channels: 1,
|
||||
Format: "s16",
|
||||
BufferSize: 0,
|
||||
ChannelBufferSize: 30,
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid channel buffer size",
|
||||
config: Config{
|
||||
SampleRate: 16000,
|
||||
Channels: 1,
|
||||
Format: "s16",
|
||||
BufferSize: 8192,
|
||||
ChannelBufferSize: 0,
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "empty format",
|
||||
config: Config{
|
||||
SampleRate: 16000,
|
||||
Channels: 1,
|
||||
Format: "",
|
||||
BufferSize: 8192,
|
||||
ChannelBufferSize: 30,
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "unaligned buffer size",
|
||||
config: Config{
|
||||
SampleRate: 16000,
|
||||
Channels: 1,
|
||||
Format: "s16",
|
||||
BufferSize: 8193, // Not aligned to frame size (2 bytes per sample)
|
||||
ChannelBufferSize: 30,
|
||||
},
|
||||
expectError: false, // Should log warning but not error
|
||||
},
|
||||
{
|
||||
name: "stereo valid config",
|
||||
config: Config{
|
||||
SampleRate: 48000,
|
||||
Channels: 2,
|
||||
Format: "s16",
|
||||
BufferSize: 8192, // 4 bytes per frame with 2 channels
|
||||
ChannelBufferSize: 30,
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
recorder := NewRecorder(tt.config)
|
||||
err := recorder.validateConfig()
|
||||
|
||||
if tt.expectError && err == nil {
|
||||
t.Errorf("expected error for config %+v", tt.config)
|
||||
}
|
||||
if !tt.expectError && err != nil {
|
||||
t.Errorf("unexpected error for config %+v: %v", tt.config, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecorderBuildPwRecordArgs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
config Config
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "default config",
|
||||
config: DefaultConfig(),
|
||||
expected: []string{
|
||||
"--format", "s16",
|
||||
"--rate", "16000",
|
||||
"--channels", "1",
|
||||
"-",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with device",
|
||||
config: Config{
|
||||
SampleRate: 48000,
|
||||
Channels: 2,
|
||||
Format: "f32",
|
||||
Device: "alsa_output.pci-0000_00_1f.3.analog-stereo",
|
||||
BufferSize: 4096,
|
||||
ChannelBufferSize: 30,
|
||||
},
|
||||
expected: []string{
|
||||
"--format", "f32",
|
||||
"--rate", "48000",
|
||||
"--channels", "2",
|
||||
"-",
|
||||
"--target", "alsa_output.pci-0000_00_1f.3.analog-stereo",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "different sample rate",
|
||||
config: Config{
|
||||
SampleRate: 44100,
|
||||
Channels: 1,
|
||||
Format: "s24",
|
||||
BufferSize: 8192,
|
||||
ChannelBufferSize: 30,
|
||||
},
|
||||
expected: []string{
|
||||
"--format", "s24",
|
||||
"--rate", "44100",
|
||||
"--channels", "1",
|
||||
"-",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
recorder := NewRecorder(tt.config)
|
||||
args := recorder.buildPwRecordArgs()
|
||||
|
||||
if len(args) != len(tt.expected) {
|
||||
t.Errorf("args length mismatch: got %d, expected %d", len(args), len(tt.expected))
|
||||
t.Errorf("got: %v", args)
|
||||
t.Errorf("expected: %v", tt.expected)
|
||||
return
|
||||
}
|
||||
|
||||
for i, arg := range args {
|
||||
if arg != tt.expected[i] {
|
||||
t.Errorf("arg[%d] mismatch: got %q, expected %q", i, arg, tt.expected[i])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecorderLifecycle(t *testing.T) {
|
||||
recorder := NewDefaultRecorder()
|
||||
|
||||
t.Run("initial state", func(t *testing.T) {
|
||||
if recorder.IsRecording() {
|
||||
t.Error("recorder should not be recording initially")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("stop before start", func(t *testing.T) {
|
||||
err := recorder.Stop()
|
||||
if err != nil {
|
||||
t.Errorf("stop should not error when not recording: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
// Note: We can't easily test actual recording without PipeWire
|
||||
// But we can test the state management
|
||||
}
|
||||
|
||||
func TestAudioFrame(t *testing.T) {
|
||||
t.Run("audio frame creation", func(t *testing.T) {
|
||||
data := []byte("test audio data")
|
||||
timestamp := time.Now()
|
||||
|
||||
frame := AudioFrame{
|
||||
Data: data,
|
||||
Timestamp: timestamp,
|
||||
}
|
||||
|
||||
if len(frame.Data) != len(data) {
|
||||
t.Errorf("frame data length mismatch: got %d, expected %d", len(frame.Data), len(data))
|
||||
}
|
||||
|
||||
for i, b := range frame.Data {
|
||||
if b != data[i] {
|
||||
t.Errorf("frame data[%d] mismatch: got %d, expected %d", i, b, data[i])
|
||||
}
|
||||
}
|
||||
|
||||
if !frame.Timestamp.Equal(timestamp) {
|
||||
t.Errorf("frame timestamp mismatch: got %v, expected %v", frame.Timestamp, timestamp)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("empty audio frame", func(t *testing.T) {
|
||||
frame := AudioFrame{}
|
||||
|
||||
if frame.Data != nil {
|
||||
t.Error("empty frame data should be nil")
|
||||
}
|
||||
|
||||
if !frame.Timestamp.IsZero() {
|
||||
t.Error("empty frame timestamp should be zero")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("large audio frame", func(t *testing.T) {
|
||||
data := make([]byte, 65536) // 64KB
|
||||
for i := range data {
|
||||
data[i] = byte(i % 256)
|
||||
}
|
||||
|
||||
frame := AudioFrame{
|
||||
Data: data,
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
|
||||
if len(frame.Data) != len(data) {
|
||||
t.Errorf("large frame data length mismatch: got %d, expected %d", len(frame.Data), len(data))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestCheckPipeWireAvailable(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("check pipewire availability", func(t *testing.T) {
|
||||
// This test depends on the system having PipeWire installed
|
||||
// We'll just verify it doesn't panic and returns some result
|
||||
err := CheckPipeWireAvailable(ctx)
|
||||
|
||||
// We can't assert on the specific result since it depends on the system
|
||||
// But we can ensure it doesn't panic and returns within reasonable time
|
||||
_ = err
|
||||
})
|
||||
|
||||
t.Run("context cancellation", func(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel() // Cancel immediately
|
||||
|
||||
err := CheckPipeWireAvailable(ctx)
|
||||
// Should return an error due to context cancellation
|
||||
if err == nil {
|
||||
t.Log("CheckPipeWireAvailable with cancelled context returned nil (may be OK if commands complete quickly)")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("timeout context", func(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Nanosecond)
|
||||
defer cancel()
|
||||
|
||||
err := CheckPipeWireAvailable(ctx)
|
||||
// Should return an error due to timeout
|
||||
if err == nil {
|
||||
t.Log("CheckPipeWireAvailable with timeout context returned nil (may be OK if commands complete quickly)")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRecorderConcurrency(t *testing.T) {
|
||||
recorder := NewDefaultRecorder()
|
||||
|
||||
t.Run("concurrent IsRecording calls", func(t *testing.T) {
|
||||
done := make(chan bool, 10)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
go func() {
|
||||
for j := 0; j < 100; j++ {
|
||||
recorder.IsRecording()
|
||||
}
|
||||
done <- true
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(1 * time.Second):
|
||||
t.Fatal("timeout waiting for concurrent IsRecording calls")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("concurrent Stop calls", func(t *testing.T) {
|
||||
done := make(chan bool, 10)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
go func() {
|
||||
recorder.Stop()
|
||||
done <- true
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(1 * time.Second):
|
||||
t.Fatal("timeout waiting for concurrent Stop calls")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigEquality(t *testing.T) {
|
||||
config1 := DefaultConfig()
|
||||
config2 := DefaultConfig()
|
||||
|
||||
t.Run("default configs should be equal", func(t *testing.T) {
|
||||
if config1.SampleRate != config2.SampleRate {
|
||||
t.Error("sample rates should be equal")
|
||||
}
|
||||
if config1.Channels != config2.Channels {
|
||||
t.Error("channels should be equal")
|
||||
}
|
||||
if config1.Format != config2.Format {
|
||||
t.Error("formats should be equal")
|
||||
}
|
||||
if config1.BufferSize != config2.BufferSize {
|
||||
t.Error("buffer sizes should be equal")
|
||||
}
|
||||
if config1.Device != config2.Device {
|
||||
t.Error("devices should be equal")
|
||||
}
|
||||
if config1.ChannelBufferSize != config2.ChannelBufferSize {
|
||||
t.Error("channel buffer sizes should be equal")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("modified config should not be equal", func(t *testing.T) {
|
||||
config2.SampleRate = 48000
|
||||
|
||||
if config1.SampleRate == config2.SampleRate {
|
||||
t.Error("sample rates should not be equal after modification")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRecorderErrorConditions(t *testing.T) {
|
||||
t.Run("double start without stop", func(t *testing.T) {
|
||||
recorder := NewDefaultRecorder()
|
||||
|
||||
// Mark as recording manually to simulate the condition
|
||||
recorder.recording.Store(true)
|
||||
defer recorder.recording.Store(false)
|
||||
|
||||
ctx := context.Background()
|
||||
_, _, err := recorder.Start(ctx)
|
||||
if err == nil {
|
||||
t.Error("Start should return error when already recording")
|
||||
}
|
||||
|
||||
expectedMsg := "already recording"
|
||||
if err.Error() != expectedMsg {
|
||||
t.Errorf("error message should be %q, got %q", expectedMsg, err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("invalid config start", func(t *testing.T) {
|
||||
invalidConfig := Config{
|
||||
SampleRate: -1, // Invalid
|
||||
}
|
||||
recorder := NewRecorder(invalidConfig)
|
||||
|
||||
ctx := context.Background()
|
||||
_, _, err := recorder.Start(ctx)
|
||||
if err == nil {
|
||||
t.Error("Start should return error with invalid config")
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user