Browse Source

feat: more robust recursive scanning tests

Fela Maslen 5 years ago
parent
commit
f00d326f64

+ 1 - 9
music-player/cmd/migrate/main.go

@@ -1,17 +1,9 @@
 package main
 
 import (
-	"log"
-	"os"
-
 	"github.com/felamaslen/go-music-player/pkg/db"
 )
 
 func main() {
-  cwd, err := os.Getwd()
-  if err != nil {
-    log.Fatal("Error getting directory:", err)
-    return
-  }
-  db.MigrateDatabase(cwd)
+  db.MigrateDatabase()
 }

+ 7 - 5
music-player/cmd/scan/main.go

@@ -1,12 +1,14 @@
 package main
 
 import (
-  "fmt"
-  "github.com/felamaslen/go-music-player/pkg/db"
+	"github.com/felamaslen/go-music-player/pkg/db"
+	"github.com/felamaslen/go-music-player/pkg/read"
+	"github.com/felamaslen/go-music-player/pkg/services"
 )
 
-func main() {
-  fmt.Println("Hello world! TODO: start scanning music into database")
+const musicDirectory = read.TestDirectory
 
-  db.InsertMusicIntoDatabase()
+func main() {
+  services.ScanAndInsert(musicDirectory)
+  db.EndPool()
 }

+ 17 - 5
music-player/pkg/db/main.go

@@ -13,7 +13,7 @@ import (
 	_ "github.com/golang-migrate/migrate/v4/database/postgres"
 	_ "github.com/golang-migrate/migrate/v4/source/file"
 
-	"github.com/felamaslen/go-music-player/pkg/config"
+	config "github.com/felamaslen/go-music-player/pkg/config"
 )
 
 var pool *pgxpool.Pool
@@ -21,7 +21,7 @@ var pool *pgxpool.Pool
 func GetConnection() *pgxpool.Conn {
   if pool == nil {
     var err error
-    pool, err = pgxpool.Connect(context.Background(), config.Config.DatabaseUrl)
+    pool, err = pgxpool.Connect(context.Background(), config.GetConfig().DatabaseUrl)
 
     if err != nil {
       fmt.Fprintf(os.Stderr, "Unable to acquire database connection pool: %v\n", err)
@@ -38,9 +38,21 @@ func GetConnection() *pgxpool.Conn {
   return conn
 }
 
-func MigrateDatabase(migrationDirectory string) {
-  databaseUrl := fmt.Sprintf("%s?sslmode=disable", config.Config.DatabaseUrl)
-  directoryUrl := fmt.Sprintf("file://%s", filepath.Join(migrationDirectory, "migrations"))
+func EndPool() {
+  if pool == nil {
+    return
+  }
+  pool.Close()
+}
+
+func MigrateDatabase() {
+  cwd, err := os.Getwd()
+  if err != nil {
+    log.Fatal("Error getting directory:", err)
+    return
+  }
+  databaseUrl := fmt.Sprintf("%s?sslmode=disable", config.GetConfig().DatabaseUrl)
+  directoryUrl := fmt.Sprintf("file://%s", filepath.Join(cwd, "migrations"))
 
   m, err := migrate.New(directoryUrl, databaseUrl)
   if err != nil {

+ 0 - 13
music-player/pkg/db/main_test.go

@@ -1,13 +0,0 @@
-package db
-
-import (
-  "context"
-  "testing"
-)
-
-func TestDbIntegration(t *testing.T) {
-  conn := PrepareDatabaseForTesting()
-  defer conn.Conn().Close(context.Background())
-
-  t.Run("Scanning and inserting songs", IntegrationTestInsertMusicIntoDatabase)
-}

+ 0 - 1
music-player/pkg/db/test.env

@@ -1 +0,0 @@
-../../test.env

+ 0 - 30
music-player/pkg/db/test_utils.go

@@ -1,30 +0,0 @@
-package db
-
-import (
-	"context"
-	"fmt"
-	"log"
-	"os"
-
-	"github.com/jackc/pgx/v4/pgxpool"
-)
-
-func PrepareDatabaseForTesting() *pgxpool.Conn {
-  fmt.Println("Preparing database for testing")
-
-  cwd, err := os.Getwd()
-  if err != nil {
-    log.Fatal("Error getting working dir: ", err)
-    os.Exit(1)
-  }
-
-  MigrateDatabase(cwd + "/../..")
-  conn := GetConnection()
-
-  conn.Query(
-    context.Background(),
-    "truncate table songs",
-  )
-
-  return conn
-}

+ 18 - 13
music-player/pkg/read/audio_test.go

@@ -1,24 +1,29 @@
 package read
 
 import (
-  "os"
-  "testing"
-  "github.com/stretchr/testify/assert"
+	"os"
+	"path"
+	"testing"
+
+	_ "github.com/felamaslen/go-music-player/pkg/testing"
+	"github.com/stretchr/testify/assert"
 )
 
 func TestReadFile(t *testing.T) {
-  basePath, _ := os.Getwd()
+  rootDir, _ := os.Getwd()
+  basePath := path.Join(rootDir, TestDirectory)
 
-  result, err := ReadFile(basePath, testFile)
+  result, err := ReadFile(basePath, TestSong.RelativePath)
 
   assert.Nil(t, err)
 
-  assert.Equal(t, result.Title, testTitle, "title must be correct")
-  assert.Equal(t, result.Artist, testArtist, "artist must be correct")
-  assert.Equal(t, result.Album, testAlbum, "album must be correct")
-  assert.Equal(t, result.Duration, testLengthSeconds, "duration must be correct")
-  assert.True(t, result.DurationOk, "duration must be fetched successfully")
-
-  assert.Equal(t, result.BasePath, basePath)
-  assert.Equal(t, result.RelativePath, testFile)
+  assert.Equal(t, Song{
+    Title: "Impact Moderato",
+    Artist: "Kevin MacLeod",
+    Album: "YouTube Audio Library",
+    Duration: 74,
+    DurationOk: true,
+    BasePath: basePath,
+    RelativePath: "file_example_OOG_1MG.ogg",
+  }, *result)
 }

+ 36 - 14
music-player/pkg/read/files.go

@@ -1,26 +1,35 @@
 package read
 
 import (
-  "fmt"
-  "io/ioutil"
-  "path/filepath"
+	"io/ioutil"
+	"path/filepath"
+
+	config "github.com/felamaslen/go-music-player/pkg/config"
+	"github.com/felamaslen/go-music-player/pkg/logger"
 )
 
 func ReadMultipleFiles(basePath string, files chan string) chan *Song {
+  var l = logger.CreateLogger(config.GetConfig().LogLevel)
+
   songs := make(chan *Song)
 
   go func() {
-    defer close(songs)
+    defer func() {
+      l.Verbose("Finished reading files")
+      close(songs)
+    }()
 
     for {
       select {
       case file, more := <- files:
         if more {
+          l.Verbose("Reading file: %s\n", file)
           song, err := ReadFile(basePath, file)
+
           if err == nil {
             songs <- song
           } else {
-            fmt.Printf("Error reading file (%s): %s\n", file, err)
+            l.Error("Error reading file (%s): %s\n", file, err)
           }
         } else {
           return
@@ -37,10 +46,23 @@ func isValidFile(file string) bool {
   return filepath.Ext(file) == ".ogg"
 }
 
-func recursiveDirScan(directory string, output chan string, root bool, basePath string) {
+func recursiveDirScan(l *logger.Logger, directory string, output *chan string, root bool, basePath string) {
+  if (root) {
+    l.Verbose("Scanning root directory: %s\n", directory)
+
+    defer func() {
+      l.Verbose("Finished recursive directory scan")
+      close(*output)
+    }()
+  } else {
+    l.Debug("Scanning subdirectory: %s\n", directory)
+  }
+
+
   files, err := ioutil.ReadDir(directory)
+
   if err != nil {
-    fmt.Printf("Error scanning directory (%s): %s", directory, err)
+    l.Fatal("Error scanning directory: (%s): %s", directory, err)
     return
   }
 
@@ -49,22 +71,22 @@ func recursiveDirScan(directory string, output chan string, root bool, basePath
     relativePath := filepath.Join(basePath, file.Name())
 
     if file.IsDir() {
-      recursiveDirScan(absolutePath, output, false, relativePath)
+      recursiveDirScan(l, absolutePath, output, false, relativePath)
     } else if isValidFile(file.Name()) {
-      output <- relativePath
-    }
-  }
+      l.Verbose("Found file: %s\n", relativePath)
 
-  if (root) {
-    close(output)
+      *output <- relativePath
+    }
   }
 }
 
 func ScanDirectory(directory string) chan string {
+  l := logger.CreateLogger(config.GetConfig().LogLevel)
+
   files := make(chan string)
   
   go func() {
-    recursiveDirScan(directory, files, true, "")
+    recursiveDirScan(l, directory, &files, true, "")
   }()
 
   return files

+ 9 - 17
music-player/pkg/read/files_test.go

@@ -1,21 +1,21 @@
 package read
 
 import (
-  "os"
-  "testing"
-  "github.com/stretchr/testify/assert"
+	"testing"
+
+	_ "github.com/felamaslen/go-music-player/pkg/testing"
+	"github.com/stretchr/testify/assert"
 )
 
 func TestReadMultipleFiles(t *testing.T) {
-  directory, _ := os.Getwd()
   files := make(chan string, 1)
 
   go func() {
-    files <- testFile
+    files <- TestSong.RelativePath
     close(files)
   }()
 
-  outputChan := ReadMultipleFiles(directory, files)
+  outputChan := ReadMultipleFiles(TestDirectory, files)
 
   var results []*Song
 
@@ -33,19 +33,11 @@ func TestReadMultipleFiles(t *testing.T) {
 
   assert.Len(t, results, 1)
 
-  assert.Equal(t, *results[0], Song{
-    Title: testTitle,
-    Artist: testArtist,
-    Album: testAlbum,
-    Duration: testLengthSeconds,
-    DurationOk: true,
-    BasePath: directory,
-    RelativePath: testFile,
-  })
+  assert.Equal(t, TestSong, *results[0])
 }
 
 func TestScanDirectory(t *testing.T) {
-  files := ScanDirectory(".")
+  files := ScanDirectory(TestDirectory)
 
   var results []string
 
@@ -61,5 +53,5 @@ func TestScanDirectory(t *testing.T) {
     }
   }
 
-  assert.Equal(t, results, []string{testFile})
+  assert.Equal(t, results, []string{TestSong.RelativePath, TestSongNested.RelativePath})
 }

+ 20 - 5
music-player/pkg/read/test_file_info.go

@@ -1,8 +1,23 @@
 package read
 
-const testFile = "testdata/file_example_OOG_1MG.ogg"
+const TestDirectory = "pkg/read/testdata"
 
-const testTitle = "Impact Moderato"
-const testArtist = "Kevin MacLeod"
-const testAlbum = "YouTube Audio Library"
-const testLengthSeconds = 74
+var TestSong = Song{
+  Title: "Impact Moderato",
+  Artist: "Kevin MacLeod",
+  Album: "YouTube Audio Library",
+  Duration: 74,
+  DurationOk: true,
+  BasePath: TestDirectory,
+  RelativePath: "file_example_OOG_1MG.ogg",
+}
+
+var TestSongNested = Song{
+  Title: "Clementi: Piano Sonata in D major, Op 25 No 6 - Movement 2: Un poco andante",
+  Artist: "Howard Shelley",
+  Album: "Clementi: The Complete Piano Sonatas, Vol. 4",
+  Duration: 166,
+  DurationOk: true,
+  BasePath: TestDirectory,
+  RelativePath: "nested/14 Clementi Piano Sonata in D major, Op 25 No 6 - Movement 2 Un poco andante.ogg",
+}

BIN
music-player/pkg/read/testdata/nested/14 Clementi Piano Sonata in D major, Op 25 No 6 - Movement 2 Un poco andante.ogg


+ 18 - 9
music-player/pkg/db/scan.go → music-player/pkg/repository/scan.go

@@ -1,26 +1,35 @@
-package db
+package repository
 
 import (
-  "fmt"
-  "context"
+	"context"
+	"fmt"
 
-  "github.com/felamaslen/go-music-player/pkg/read"
+	"github.com/felamaslen/go-music-player/pkg/config"
+	"github.com/felamaslen/go-music-player/pkg/db"
+	"github.com/felamaslen/go-music-player/pkg/logger"
+	"github.com/felamaslen/go-music-player/pkg/read"
 )
 
 func InsertMusicIntoDatabase(songs chan *read.Song) {
+  var l = logger.CreateLogger(config.GetConfig().LogLevel)
+
   for {
     select {
     case song, more := <- songs:
       if !more {
+        l.Verbose("Finished inserting songs\n")
         return
       }
 
+      l.Debug("Adding song: %v\n", song)
+
       duration := "NULL"
       if song.DurationOk {
         duration = fmt.Sprintf("%d", song.Duration)
       }
 
-      conn := GetConnection()
+      conn := db.GetConnection()
+
       _, err := conn.Query(
         context.Background(),
         "insert into songs (title, artist, album, duration, base_path, relative_path) values ($1, $2, $3, $4, $5, $6)",
@@ -32,10 +41,10 @@ func InsertMusicIntoDatabase(songs chan *read.Song) {
         song.RelativePath,
       )
 
-      if err == nil {
-        fmt.Printf("Inserted record successfully: %s, %s, %s, %s\n", song.RelativePath, song.Artist, song.Album, song.Title)
-      } else {
-        fmt.Printf("Error inserting record: %s\n", err)
+      conn.Conn().Close(context.Background())
+
+      if err != nil {
+        l.Error("Error inserting record: %s\n", err)
       }
     }
   }

+ 26 - 31
music-player/pkg/db/scan_test.go → music-player/pkg/repository/scan_test.go

@@ -1,4 +1,4 @@
-package db
+package repository
 
 import (
 	"context"
@@ -6,10 +6,14 @@ import (
 
 	"github.com/stretchr/testify/assert"
 
+	"github.com/felamaslen/go-music-player/pkg/db"
 	"github.com/felamaslen/go-music-player/pkg/read"
+	setup "github.com/felamaslen/go-music-player/pkg/testing"
 )
 
-func IntegrationTestInsertMusicIntoDatabase(t *testing.T) {
+func TestInsertMusicIntoDatabase(t *testing.T) {
+  setup.PrepareDatabaseForTesting()
+
   songs := make(chan *read.Song)
 
   go func() {
@@ -38,16 +42,7 @@ func IntegrationTestInsertMusicIntoDatabase(t *testing.T) {
 
   InsertMusicIntoDatabase(songs)
 
-  conn := GetConnection()
-
-  type Row struct {
-    title string
-    artist string
-    album string
-    duration int
-    base_path string
-    relative_path string
-  }
+  conn := db.GetConnection()
 
   rows, err := conn.Query(
     context.Background(),
@@ -60,29 +55,29 @@ func IntegrationTestInsertMusicIntoDatabase(t *testing.T) {
 
   assert.Nil(t, err)
 
-  var row Row
+  var row read.Song
 
   rows.Next()
-  rows.Scan(&row.title, &row.artist, &row.album, &row.duration, &row.base_path, &row.relative_path)
-
-  assert.Equal(t, Row{
-    title: "Hey Jude",
-    artist: "The Beatles",
-    album: "",
-    duration: 431,
-    base_path: "/path/to",
-    relative_path: "file.ogg",
+  rows.Scan(&row.Title, &row.Artist, &row.Album, &row.Duration, &row.BasePath, &row.RelativePath)
+
+  assert.Equal(t, read.Song{
+    Title: "Hey Jude",
+    Artist: "The Beatles",
+    Album: "",
+    Duration: 431,
+    BasePath: "/path/to",
+    RelativePath: "file.ogg",
   }, row)
 
   rows.Next()
-  rows.Scan(&row.title, &row.artist, &row.album, &row.duration, &row.base_path, &row.relative_path)
-
-  assert.Equal(t, Row{
-    title: "Starman",
-    artist: "David Bowie",
-    album: "The Rise and Fall of Ziggy Stardust and the Spiders from Mars",
-    duration: 256,
-    base_path: "/different/path",
-    relative_path: "otherFile.ogg",
+  rows.Scan(&row.Title, &row.Artist, &row.Album, &row.Duration, &row.BasePath, &row.RelativePath)
+
+  assert.Equal(t, read.Song{
+    Title: "Starman",
+    Artist: "David Bowie",
+    Album: "The Rise and Fall of Ziggy Stardust and the Spiders from Mars",
+    Duration: 256,
+    BasePath: "/different/path",
+    RelativePath: "otherFile.ogg",
   }, row)
 }

+ 40 - 0
music-player/pkg/testing/testing.go

@@ -0,0 +1,40 @@
+package testing
+
+import (
+	"context"
+	"fmt"
+	"os"
+	"path"
+	"runtime"
+
+	"github.com/felamaslen/go-music-player/pkg/db"
+	"github.com/jackc/pgx/v4/pgxpool"
+)
+
+func ChangeToRootDir() {
+  _, filename, _, _ := runtime.Caller(0)
+  dir := path.Join(path.Dir(filename), "../..")
+  fmt.Printf("Changing dir to %v\n", dir)
+  err := os.Chdir(dir)
+  if err != nil {
+    panic(err)
+  }
+}
+
+func init() {
+  ChangeToRootDir()
+}
+
+func PrepareDatabaseForTesting() *pgxpool.Conn {
+  fmt.Println("Preparing database for testing")
+
+  db.MigrateDatabase()
+  conn := db.GetConnection()
+
+  conn.Query(
+    context.Background(),
+    "truncate table songs",
+  )
+
+  return conn
+}