package models import ( "encoding/xml" "testing" ) func TestNewBassRequest(t *testing.T) { tests := []struct { name string level int wantError bool wantLevel int }{ { name: "Valid bass level 0", level: 0, wantError: false, wantLevel: 0, }, { name: "Valid bass level +9", level: 9, wantError: false, wantLevel: 9, }, { name: "Valid bass level -9", level: -9, wantError: false, wantLevel: -9, }, { name: "Valid bass level +3", level: 3, wantError: false, wantLevel: 3, }, { name: "Valid bass level -3", level: -3, wantError: false, wantLevel: -3, }, { name: "Invalid bass level +10", level: 10, wantError: true, }, { name: "Invalid bass level -10", level: -10, wantError: true, }, { name: "Invalid bass level +100", level: 100, wantError: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { req, err := NewBassRequest(tt.level) if tt.wantError { if err == nil { t.Errorf("NewBassRequest() expected error, got nil") } } else { if err != nil { t.Errorf("NewBassRequest() unexpected error: %v", err) } if req.Level != tt.wantLevel { t.Errorf("NewBassRequest() level = %d, want %d", req.Level, tt.wantLevel) } } }) } } func TestValidateBassLevel(t *testing.T) { tests := []struct { name string level int want bool }{ { name: "Valid minimum level", level: -9, want: true, }, { name: "Valid maximum level", level: 9, want: true, }, { name: "Valid zero level", level: 0, want: true, }, { name: "Valid positive level", level: 5, want: true, }, { name: "Valid negative level", level: -5, want: true, }, { name: "Invalid too high", level: 10, want: false, }, { name: "Invalid too low", level: -10, want: false, }, { name: "Invalid way too high", level: 100, want: false, }, { name: "Invalid way too low", level: -100, want: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := ValidateBassLevel(tt.level); got != tt.want { t.Errorf("ValidateBassLevel() = %v, want %v", got, tt.want) } }) } } func TestClampBassLevel(t *testing.T) { tests := []struct { name string level int want int }{ { name: "Valid level unchanged", level: 0, want: 0, }, { name: "Valid positive level unchanged", level: 5, want: 5, }, { name: "Valid negative level unchanged", level: -5, want: -5, }, { name: "Maximum level unchanged", level: 9, want: 9, }, { name: "Minimum level unchanged", level: -9, want: -9, }, { name: "Too high clamped to max", level: 10, want: 9, }, { name: "Too low clamped to min", level: -10, want: -9, }, { name: "Way too high clamped to max", level: 100, want: 9, }, { name: "Way too low clamped to min", level: -100, want: -9, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := ClampBassLevel(tt.level); got != tt.want { t.Errorf("ClampBassLevel() = %v, want %v", got, tt.want) } }) } } func TestGetBassLevelName(t *testing.T) { tests := []struct { name string level int want string }{ { name: "Very low bass", level: -9, want: "Very Low", }, { name: "Low bass", level: -6, want: "Low", }, { name: "Slightly low bass", level: -2, want: "Slightly Low", }, { name: "Neutral bass", level: 0, want: "Neutral", }, { name: "Slightly high bass", level: 2, want: "Slightly High", }, { name: "High bass", level: 6, want: "High", }, { name: "Very high bass", level: 9, want: "Very High", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := GetBassLevelName(tt.level); got != tt.want { t.Errorf("GetBassLevelName() = %v, want %v", got, tt.want) } }) } } func TestGetBassLevelCategory(t *testing.T) { tests := []struct { name string level int want string }{ { name: "Bass cut negative", level: -5, want: "Bass Cut", }, { name: "Bass cut minimum", level: -9, want: "Bass Cut", }, { name: "Flat bass", level: 0, want: "Flat", }, { name: "Bass boost positive", level: 5, want: "Bass Boost", }, { name: "Bass boost maximum", level: 9, want: "Bass Boost", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := GetBassLevelCategory(tt.level); got != tt.want { t.Errorf("GetBassLevelCategory() = %v, want %v", got, tt.want) } }) } } func TestBass_GetMethods(t *testing.T) { bass := &Bass{ TargetBass: 5, ActualBass: 3, DeviceID: "1234567890AB", } if got := bass.GetLevel(); got != 5 { t.Errorf("GetLevel() = %v, want %v", got, 5) } if got := bass.GetActualLevel(); got != 3 { t.Errorf("GetActualLevel() = %v, want %v", got, 3) } if got := bass.IsAtTarget(); got != false { t.Errorf("IsAtTarget() = %v, want %v", got, false) } if got := bass.GetBassChangeNeeded(); got != 2 { t.Errorf("GetBassChangeNeeded() = %v, want %v", got, 2) } } func TestBass_BooleanMethods(t *testing.T) { tests := []struct { name string bass *Bass wantBoost bool wantCut bool wantFlat bool wantAtTarget bool }{ { name: "Bass boost", bass: &Bass{TargetBass: 5, ActualBass: 5}, wantBoost: true, wantCut: false, wantFlat: false, wantAtTarget: true, }, { name: "Bass cut", bass: &Bass{TargetBass: -3, ActualBass: -3}, wantBoost: false, wantCut: true, wantFlat: false, wantAtTarget: true, }, { name: "Flat bass", bass: &Bass{TargetBass: 0, ActualBass: 0}, wantBoost: false, wantCut: false, wantFlat: true, wantAtTarget: true, }, { name: "Not at target", bass: &Bass{TargetBass: 5, ActualBass: 2}, wantBoost: true, wantCut: false, wantFlat: false, wantAtTarget: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := tt.bass.IsBassBoost(); got != tt.wantBoost { t.Errorf("IsBassBoost() = %v, want %v", got, tt.wantBoost) } if got := tt.bass.IsBassCut(); got != tt.wantCut { t.Errorf("IsBassCut() = %v, want %v", got, tt.wantCut) } if got := tt.bass.IsFlat(); got != tt.wantFlat { t.Errorf("IsFlat() = %v, want %v", got, tt.wantFlat) } if got := tt.bass.IsAtTarget(); got != tt.wantAtTarget { t.Errorf("IsAtTarget() = %v, want %v", got, tt.wantAtTarget) } }) } } func TestBass_String(t *testing.T) { bass := &Bass{ TargetBass: 3, ActualBass: 3, } expected := "Bass: 3 (Slightly High)" if got := bass.String(); got != expected { t.Errorf("String() = %v, want %v", got, expected) } } func TestBass_UnmarshalXML(t *testing.T) { tests := []struct { name string xmlData string wantError bool want Bass }{ { name: "Valid bass XML", xmlData: ` 3 3 `, wantError: false, want: Bass{ DeviceID: "1234567890AB", TargetBass: 3, ActualBass: 3, }, }, { name: "Valid negative bass XML", xmlData: ` -5 -5 `, wantError: false, want: Bass{ DeviceID: "1234567890AB", TargetBass: -5, ActualBass: -5, }, }, { name: "Valid zero bass XML", xmlData: ` 0 0 `, wantError: false, want: Bass{ DeviceID: "1234567890AB", TargetBass: 0, ActualBass: 0, }, }, { name: "Invalid target bass too high", xmlData: ` 15 5 `, wantError: true, }, { name: "Invalid actual bass too low", xmlData: ` 5 -15 `, wantError: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var bass Bass err := xml.Unmarshal([]byte(tt.xmlData), &bass) if tt.wantError { if err == nil { t.Errorf("UnmarshalXML() expected error, got nil") } } else { if err != nil { t.Errorf("UnmarshalXML() unexpected error: %v", err) } if bass.DeviceID != tt.want.DeviceID { t.Errorf("DeviceID = %v, want %v", bass.DeviceID, tt.want.DeviceID) } if bass.TargetBass != tt.want.TargetBass { t.Errorf("TargetBass = %v, want %v", bass.TargetBass, tt.want.TargetBass) } if bass.ActualBass != tt.want.ActualBass { t.Errorf("ActualBass = %v, want %v", bass.ActualBass, tt.want.ActualBass) } } }) } } func TestBass_MarshalXML(t *testing.T) { tests := []struct { name string bass Bass wantError bool }{ { name: "Valid bass marshal", bass: Bass{ DeviceID: "1234567890AB", TargetBass: 3, ActualBass: 3, }, wantError: false, }, { name: "Valid negative bass marshal", bass: Bass{ DeviceID: "1234567890AB", TargetBass: -5, ActualBass: -5, }, wantError: false, }, { name: "Valid bass marshal with high values", bass: Bass{ DeviceID: "1234567890AB", TargetBass: 9, ActualBass: 8, }, wantError: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { _, err := xml.Marshal(tt.bass) if tt.wantError { if err == nil { t.Errorf("MarshalXML() expected error, got nil") } } else { if err != nil { t.Errorf("MarshalXML() unexpected error: %v", err) } } }) } } func TestBassRequest_MarshalXML(t *testing.T) { req := &BassRequest{ Level: 5, } data, err := xml.Marshal(req) if err != nil { t.Errorf("MarshalXML() unexpected error: %v", err) } expected := "5" if string(data) != expected { t.Errorf("MarshalXML() = %v, want %v", string(data), expected) } } func TestBassConstants(t *testing.T) { if BassLevelMin != -9 { t.Errorf("BassLevelMin = %v, want %v", BassLevelMin, -9) } if BassLevelMax != 9 { t.Errorf("BassLevelMax = %v, want %v", BassLevelMax, 9) } if BassLevelDefault != 0 { t.Errorf("BassLevelDefault = %v, want %v", BassLevelDefault, 0) } } func TestBassLevelEdgeCases(t *testing.T) { // Test boundary values t.Run("Minimum boundary", func(t *testing.T) { if !ValidateBassLevel(-9) { t.Error("ValidateBassLevel(-9) should be true") } if ValidateBassLevel(-10) { t.Error("ValidateBassLevel(-10) should be false") } }) t.Run("Maximum boundary", func(t *testing.T) { if !ValidateBassLevel(9) { t.Error("ValidateBassLevel(9) should be true") } if ValidateBassLevel(10) { t.Error("ValidateBassLevel(10) should be false") } }) t.Run("Zero boundary", func(t *testing.T) { if !ValidateBassLevel(0) { t.Error("ValidateBassLevel(0) should be true") } }) }