Skip to content

Commit

Permalink
Restructuring btconnect private methods for better testing
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronromeo committed Jan 6, 2024
1 parent 2a04082 commit c773df7
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 219 deletions.
113 changes: 7 additions & 106 deletions system/bin/btconnect/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,19 @@ package btconnect

import (
"bufio"
"bytes"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
)

const DefaultASLAConfig = "/home/pi/.asoundrc"
const DefaultProjectRoot = "/home/pi/workspace/pyrfid-jukebox"
const DefaultRelativeASLAConfig = "/system/home/.asoundrc"

type CommandExecutor interface {
Command(name string, arg ...string) Cmd
}

type Cmd interface {
Run() error
}

type OSCommandExecutor struct{}

func (e *OSCommandExecutor) Command(name string, arg ...string) Cmd {
return exec.Command(name, arg...)
}
helper "aaronromeo.com/rfid-jukebox/system/bin/helper"
)

type Service struct {
cmdExecutor CommandExecutor
cmdExecutor helper.CommandExecutor
}

func NewBtConnectService(cmdExecutor CommandExecutor) *Service {
func NewBtConnectService(cmdExecutor helper.CommandExecutor) *Service {
return &Service{
cmdExecutor: cmdExecutor,
}
Expand All @@ -45,7 +26,7 @@ func (bt *Service) Run() error {
return fmt.Errorf("env var PJ_BLUETOOTH_DEVICE not set")
}

err := bt.updateALSAConfig()
err := helper.UpdateALSAConfig(bt.cmdExecutor)
if err != nil {
log.Printf("Error updating ALSA config: %v", err)
return err
Expand All @@ -62,15 +43,13 @@ func (bt *Service) Run() error {
}

func (bt *Service) getBluetoothConnectionCount(device string) (int, error) {
cmd := exec.Command("bluetoothctl", "info", device)
var out bytes.Buffer
cmd.Stdout = &out
cmd := bt.cmdExecutor.Command("bluetoothctl", "info", device)
err := cmd.Run()
if err != nil {
return 0, err
}

return bt.countConnectedLines(out.String()), nil
return bt.countConnectedLines(bt.cmdExecutor.GetOutput()), nil
}

func (*Service) countConnectedLines(output string) int {
Expand All @@ -83,81 +62,3 @@ func (*Service) countConnectedLines(output string) int {
}
return count
}

func (bt *Service) updateALSAConfig() error {
if hasChanged, errHC := bt.HasALSAConfigChanged(); errHC != nil {
return errHC
} else if hasChanged {
log.Println("ALSA config has changed. Copying over system config...")

aslaConfig := bt.getALSASystemConfig()
projectAslaConfig := bt.getALSARepoConfig()

if err := bt.copyFile(aslaConfig, projectAslaConfig); err != nil {
log.Printf("Error copying file: %v", err)
return err
}

if err := bt.cmdExecutor.Command("sudo", "alsactl", "restore").Run(); err != nil {
log.Printf("Error executing alsactl restore: %v", err)
return err
}
}
return nil
}

func (bt *Service) HasALSAConfigChanged() (bool, error) {
aslaConfig := bt.getALSASystemConfig()
projectAslaConfig := bt.getALSARepoConfig()

var diff bool
var err error
if diff, err = bt.FilesAreDifferent(aslaConfig, projectAslaConfig); err != nil {
return false, err
}
return diff, nil
}

func (*Service) copyFile(src, dst string) error {
input, err := os.ReadFile(src)
if err != nil {
return err
}

err = os.WriteFile(dst, input, 0600)
if err != nil {
return err
}

return nil
}

func (*Service) getALSASystemConfig() string {
aslaConfig := os.Getenv("PJ_ALSA_CONFIG")
if aslaConfig == "" {
aslaConfig = DefaultASLAConfig
}
return aslaConfig
}

func (*Service) getALSARepoConfig() string {
projectRoot := os.Getenv("PJ_PROJECT_ROOT")
if projectRoot == "" {
projectRoot = DefaultProjectRoot
}
return filepath.Join(projectRoot, DefaultRelativeASLAConfig)
}

func (*Service) FilesAreDifferent(file1, file2 string) (bool, error) {
bytes1, err := os.ReadFile(file1)
if err != nil {
return false, err
}

bytes2, err := os.ReadFile(file2)
if err != nil {
return false, err
}

return !bytes.Equal(bytes1, bytes2), nil
}
112 changes: 0 additions & 112 deletions system/bin/btconnect/service_test.go
Original file line number Diff line number Diff line change
@@ -1,113 +1 @@
package btconnect_test

import (
"os"
"path/filepath"
"testing"

btconnect "aaronromeo.com/rfid-jukebox/system/bin/btconnect"
)

func TestFilesAreDifferent(t *testing.T) {
service := &btconnect.Service{}

// Test 1: Two identical files
err := os.WriteFile("test1.txt", []byte("test"), 0644)
if err != nil {
t.Fatal(err)
}
err = os.WriteFile("test2.txt", []byte("test"), 0644)
if err != nil {
t.Fatal(err)
}
diff, err := service.FilesAreDifferent("test1.txt", "test2.txt")
if err != nil {
t.Fatal(err)
}
if diff {
t.Errorf("Expected files to be identical, but they were different")
}

// Test 2: Two different files
err = os.WriteFile("test2.txt", []byte("test2"), 0644)
if err != nil {
t.Fatal(err)
}
diff, err = service.FilesAreDifferent("test1.txt", "test2.txt")
if err != nil {
t.Fatal(err)
}
if !diff {
t.Errorf("Expected files to be different, but they were identical")
}

// Test 3: File does not exist
_, err = service.FilesAreDifferent("test1.txt", "nonexistent.txt")
if err == nil {
t.Errorf("Expected error, but got none")
}

// Cleanup
os.Remove("test1.txt")
os.Remove("test2.txt")
}

func TestHasALSAConfigChanged(t *testing.T) {
service := &btconnect.Service{}

// Setup test files
testDir, err := os.MkdirTemp(".", "test_data")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(testDir)
err = os.MkdirAll(filepath.Join(testDir, "system", "home"), 0755)
if err != nil {
t.Fatal(err)
}

testSystemConfig := filepath.Join(testDir, "system.asoundrc")
testRepoConfig := filepath.Join(filepath.Join(testDir, "system", "home"), ".asoundrc")

t.Setenv("PJ_ALSA_CONFIG", testSystemConfig)
t.Setenv("PJ_PROJECT_ROOT", testDir)

// Test 1: Identical Files
err = os.WriteFile(testSystemConfig, []byte("test config"), 0644)
if err != nil {
t.Fatal(err)
}
err = os.WriteFile(testRepoConfig, []byte("test config"), 0644)
if err != nil {
t.Fatal(err)
}
diff, err := service.HasALSAConfigChanged()
if err != nil {
t.Fatal(err)
}
if diff {
t.Errorf("Expected ALSA configs to be identical, but they were reported as different")
}

// Test 2: Different Files
err = os.WriteFile(testRepoConfig, []byte("different config"), 0644)
if err != nil {
t.Fatal(err)
}
diff, err = service.HasALSAConfigChanged()
if err != nil {
t.Fatal(err)
}
if !diff {
t.Errorf("Expected ALSA configs to be different, but they were reported as identical")
}

// Test 3: File Does Not Exist
os.Remove(testRepoConfig)
_, err = service.HasALSAConfigChanged()
if err == nil {
t.Errorf("Expected error for missing file, but got none")
}

// Optionally, add more tests for scenarios with environment variables set
}
3 changes: 2 additions & 1 deletion system/bin/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"

"aaronromeo.com/rfid-jukebox/system/bin/btconnect"
"aaronromeo.com/rfid-jukebox/system/bin/helper"
"github.com/urfave/cli/v2"
)

Expand All @@ -16,7 +17,7 @@ func main() {
Aliases: []string{"b"},
Usage: "Maintain a connection to bluetooth device",
Action: func(c *cli.Context) error {
connectService := btconnect.NewBtConnectService(&btconnect.OSCommandExecutor{})
connectService := btconnect.NewBtConnectService(&helper.OSCommandExecutor{})
err := connectService.Run()
if err != nil {
log.Fatalf("Command execution failed: %v", err)
Expand Down
90 changes: 90 additions & 0 deletions system/bin/helper/alsa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package helper

import (
"bytes"
"log"
"os"
"path/filepath"
)

const DefaultASLAConfig = "/home/pi/.asoundrc"
const DefaultProjectRoot = "/home/pi/workspace/pyrfid-jukebox"
const DefaultRelativeASLAConfig = "/system/home/.asoundrc"

func UpdateALSAConfig(cmdExecutor CommandExecutor) error {
if hasChanged, errHC := HasALSAConfigChanged(); errHC != nil {
return errHC
} else if hasChanged {
log.Println("ALSA config has changed. Copying over system config...")

aslaConfig := GetALSASystemConfig()
projectAslaConfig := GetALSARepoConfig()

if err := CopyFile(aslaConfig, projectAslaConfig); err != nil {
log.Printf("Error copying file: %v", err)
return err
}

if err := cmdExecutor.Command("sudo", "alsactl", "restore").Run(); err != nil {
log.Printf("Error executing alsactl restore: %v", err)
return err
}
}
return nil
}

func HasALSAConfigChanged() (bool, error) {
aslaConfig := GetALSASystemConfig()
projectAslaConfig := GetALSARepoConfig()

var diff bool
var err error
if diff, err = FilesAreDifferent(aslaConfig, projectAslaConfig); err != nil {
return false, err
}
return diff, nil
}

func CopyFile(src, dst string) error {
input, err := os.ReadFile(src)
if err != nil {
return err
}

err = os.WriteFile(dst, input, 0600)
if err != nil {
return err
}

return nil
}

func GetALSASystemConfig() string {
aslaConfig := os.Getenv("PJ_ALSA_CONFIG")
if aslaConfig == "" {
aslaConfig = DefaultASLAConfig
}
return aslaConfig
}

func GetALSARepoConfig() string {
projectRoot := os.Getenv("PJ_PROJECT_ROOT")
if projectRoot == "" {
projectRoot = DefaultProjectRoot
}
return filepath.Join(projectRoot, DefaultRelativeASLAConfig)
}

func FilesAreDifferent(file1, file2 string) (bool, error) {
bytes1, err := os.ReadFile(file1)
if err != nil {
return false, err
}

bytes2, err := os.ReadFile(file2)
if err != nil {
return false, err
}

return !bytes.Equal(bytes1, bytes2), nil
}
Loading

0 comments on commit c773df7

Please sign in to comment.