瀏覽代碼

feat: ginkgo for testing and sqlx

Fela Maslen 5 年之前
父節點
當前提交
8f5bc53f26

+ 1 - 1
music-player/Makefile

@@ -5,7 +5,7 @@ clean:
 	mkdir -p bin && rm -rf ./bin/*
 
 test:
-	GO_ENV=test go test -v ./...
+	GO_ENV=test ginkgo ./...
 
 migrate:
 	go run ./cmd/migrate

+ 3 - 3
music-player/cmd/scan/main.go

@@ -1,8 +1,7 @@
 package main
 
 import (
-	"os"
-
+	"github.com/felamaslen/go-music-player/pkg/database"
 	"github.com/felamaslen/go-music-player/pkg/read"
 	"github.com/felamaslen/go-music-player/pkg/services"
 )
@@ -11,5 +10,6 @@ const musicDirectory = read.TestDirectory
 
 func main() {
   services.ScanAndInsert(musicDirectory)
-  os.Exit(0)
+
+  database.EndPool()
 }

+ 7 - 2
music-player/go.mod

@@ -6,7 +6,12 @@ require (
 	github.com/anyhon/engine v0.1.0
 	github.com/dhowden/tag v0.0.0-20200828214007-46e57f75dbfc
 	github.com/golang-migrate/migrate/v4 v4.13.0
-	github.com/jackc/pgx/v4 v4.9.2
+	github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect
+	github.com/jackc/pgx v3.6.2+incompatible
+	github.com/jackc/pgx/v4 v4.9.2 // indirect
+	github.com/jmoiron/sqlx v1.2.0
 	github.com/joho/godotenv v1.3.0
-	github.com/stretchr/testify v1.5.1
+	github.com/onsi/ginkgo v1.14.2
+	github.com/onsi/gomega v1.10.1
+	github.com/stretchr/testify v1.5.1 // indirect
 )

+ 30 - 1
music-player/go.sum

@@ -90,11 +90,14 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
 github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
@@ -173,6 +176,7 @@ github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g
 github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
@@ -180,9 +184,12 @@ github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9
 github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
 github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
 github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
+github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc=
+github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
 github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
 github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
 github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
+github.com/jackc/pgconn v1.3.2 h1:9UIGICxEAW70RQDGilGwsCG63NCcm5amjuBQCFzrmsw=
 github.com/jackc/pgconn v1.3.2/go.mod h1:LvCquS3HbBKwgl7KbX9KyqEIumJAbm1UMcTvGaIf3bM=
 github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk=
 github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
@@ -201,6 +208,7 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod
 github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
 github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
 github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
+github.com/jackc/pgproto3/v2 v2.0.1 h1:Rdjp4NFjwHnEslx2b66FfCI2S0LhO4itac3hXz6WX9M=
 github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
 github.com/jackc/pgproto3/v2 v2.0.6 h1:b1105ZGEMFe7aCvrT1Cca3VoVb4ZFMaFJLJcg/3zD+8=
 github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
@@ -209,14 +217,18 @@ github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHF
 github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
 github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
 github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
+github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59 h1:xOamcCJ9MFJTxR5bvw3ZXmiP8evQMohdt2VJ57C0W8Q=
 github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
 github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0=
 github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po=
 github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ=
 github.com/jackc/pgtype v1.6.1 h1:CAtFD7TS95KrxRAh3bidgLwva48WYxk8YkbHZsSWfbI=
 github.com/jackc/pgtype v1.6.1/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig=
+github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o=
+github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
 github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
 github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
+github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186 h1:ZQM8qLT/E/CGD6XX0E6q9FAwxJYmWpJufzmLMaFuzgQ=
 github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
 github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA=
 github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o=
@@ -227,9 +239,9 @@ github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0f
 github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
-github.com/jackc/puddle v1.1.2 h1:mpQEXihFnWGDy6X98EOTh81JYuxn7txby8ilJ3iIPGM=
 github.com/jackc/puddle v1.1.2/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
 github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
 github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
 github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
@@ -262,16 +274,25 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
 github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
+github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
 github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
 github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
 github.com/mutecomm/go-sqlcipher/v4 v4.4.0/go.mod h1:PyN04SaWalavxRGH9E8ZftG6Ju7rsPrGmQRjrEaVpiY=
 github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA=
 github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcLuHrG+/sUeP8gI=
+github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
+github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
 github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
+github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
+github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
+github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
+github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
 github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
 github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
@@ -403,6 +424,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
 golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
@@ -438,7 +460,9 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -454,6 +478,7 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200817155316-9781c653f443 h1:X18bCaipMcoJGm27Nv7zr4XYPKGUy92GtqboKC2Hxaw=
@@ -610,15 +635,19 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
 gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E=
 gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
 honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

+ 1 - 1
music-player/pkg/config/main.go

@@ -63,7 +63,7 @@ func getDatabaseUrl() string {
     log.Fatal("Must set POSTGRES_DATABASE")
   }
 
-  databaseUrl := fmt.Sprintf("postgres://%s:%s@%s:%d/%s", user, password, host, portNumeric, database)
+  databaseUrl := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=disable", user, password, host, portNumeric, database)
 
   return databaseUrl
 }

+ 52 - 0
music-player/pkg/database/main.go

@@ -0,0 +1,52 @@
+package database
+
+import (
+	"fmt"
+	"log"
+	"os"
+	"path/filepath"
+
+	migrate "github.com/golang-migrate/migrate/v4"
+	_ "github.com/golang-migrate/migrate/v4/database/postgres"
+	_ "github.com/golang-migrate/migrate/v4/source/file"
+
+	config "github.com/felamaslen/go-music-player/pkg/config"
+
+	_ "github.com/jackc/pgx/stdlib"
+	"github.com/jmoiron/sqlx"
+)
+
+var db *sqlx.DB
+
+func GetConnection() *sqlx.DB {
+  if (db != nil) {
+    return db
+  }
+
+  db := sqlx.MustConnect("pgx", config.GetConfig().DatabaseUrl)
+
+  return db
+}
+
+func EndPool() {
+  if (db == nil) {
+    return
+  }
+
+  db.Close()
+}
+
+func MigrateDatabase() {
+  cwd, err := os.Getwd()
+  if err != nil {
+    log.Fatal("Error getting directory:", err)
+    return
+  }
+  directoryUrl := fmt.Sprintf("file://%s", filepath.Join(cwd, "migrations"))
+
+  m, err := migrate.New(directoryUrl, config.GetConfig().DatabaseUrl)
+  if err != nil {
+    log.Fatal("Error setting up: ", err)
+  }
+  m.Up()
+}

+ 0 - 62
music-player/pkg/db/main.go

@@ -1,62 +0,0 @@
-package db
-
-import (
-	"context"
-	"fmt"
-	"log"
-	"os"
-	"path/filepath"
-
-	"github.com/jackc/pgx/v4/pgxpool"
-
-	migrate "github.com/golang-migrate/migrate/v4"
-	_ "github.com/golang-migrate/migrate/v4/database/postgres"
-	_ "github.com/golang-migrate/migrate/v4/source/file"
-
-	config "github.com/felamaslen/go-music-player/pkg/config"
-)
-
-var pool *pgxpool.Pool
-
-func GetConnection() *pgxpool.Conn {
-  if pool == nil {
-    var err error
-    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)
-      os.Exit(1)
-    }
-  }
-
-  conn, err := pool.Acquire(context.Background())
-  if err != nil {
-    fmt.Fprintf(os.Stderr, "Unable to acquire connection from pool: %v\n", err)
-    os.Exit(1)
-  }
-
-  return conn
-}
-
-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 {
-    log.Fatal("Error setting up: ", err)
-  }
-  m.Up()
-}

+ 28 - 20
music-player/pkg/read/audio_test.go

@@ -1,29 +1,37 @@
-package read
+package read_test
 
 import (
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+
 	"os"
 	"path"
-	"testing"
 
+	"github.com/felamaslen/go-music-player/pkg/read"
 	_ "github.com/felamaslen/go-music-player/pkg/testing"
-	"github.com/stretchr/testify/assert"
 )
 
-func TestReadFile(t *testing.T) {
+var _ = Describe("reading audio files", func() {
+
   rootDir, _ := os.Getwd()
-  basePath := path.Join(rootDir, TestDirectory)
-
-  result, err := ReadFile(basePath, TestSong.RelativePath)
-
-  assert.Nil(t, err)
-
-  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)
-}
+  basePath := path.Join(rootDir, read.TestDirectory)
+
+  Context("when the file is ogg vorbis", func() {
+
+    It("should get the expected info from the file", func() {
+      result, err := read.ReadFile(basePath, read.TestSong.RelativePath)
+
+      Expect(err).To(BeNil())
+
+      Expect(*result).To(Equal(read.Song{
+	Title: "Impact Moderato",
+	Artist: "Kevin MacLeod",
+	Album: "YouTube Audio Library",
+	Duration: 74,
+	DurationOk: true,
+	BasePath: basePath,
+	RelativePath: "file_example_OOG_1MG.ogg",
+      }))
+    })
+  })
+})

+ 56 - 37
music-player/pkg/read/files_test.go

@@ -1,57 +1,76 @@
-package read
+package read_test
 
 import (
-	"testing"
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
 
+	"github.com/felamaslen/go-music-player/pkg/read"
 	_ "github.com/felamaslen/go-music-player/pkg/testing"
-	"github.com/stretchr/testify/assert"
 )
 
-func TestReadMultipleFiles(t *testing.T) {
-  files := make(chan string, 1)
+var _ = Describe("reading files", func() {
 
-  go func() {
-    files <- TestSong.RelativePath
-    close(files)
-  }()
+  Describe("reading file info", func() {
+    var results []*read.Song
 
-  outputChan := ReadMultipleFiles(TestDirectory, files)
+    BeforeEach(func() {
+      results = nil
+      files := make(chan string, 1)
 
-  var results []*Song
+      go func() {
+	defer close(files)
+	files <- read.TestSong.RelativePath
+      }()
 
-  outputDone := false
+      outputChan := read.ReadMultipleFiles(read.TestDirectory, files)
 
-  for !outputDone {
-    select {
-    case result, more := <- outputChan:
-      if more {
-        results = append(results, result)
+      outputDone := false
+
+      for !outputDone {
+	select {
+	case result, more := <- outputChan:
+	  if more {
+	    results = append(results, result)
+	  }
+	  outputDone = !more
+	}
       }
-      outputDone = !more
-    }
-  }
+    })
 
-  assert.Len(t, results, 1)
+    It("should return the correct number of results", func() {
+      Expect(results).To(HaveLen(1))
+    })
 
-  assert.Equal(t, TestSong, *results[0])
-}
+    It("should get the correct info from the file", func() {
+      Expect(*results[0]).To(Equal(read.TestSong))
+    })
+  })
 
-func TestScanDirectory(t *testing.T) {
-  files := ScanDirectory(TestDirectory)
+  Describe("scanning a directory recursively", func() {
+    var results []string
 
-  var results []string
+    BeforeEach(func() {
+      results = nil
+      files := read.ScanDirectory(read.TestDirectory)
 
-  done := false
+      done := false
 
-  for !done {
-    select {
-    case result, more := <- files:
-      if more {
-        results = append(results, result)
+      for !done {
+	select {
+	case result, more := <- files:
+	  if more {
+	    results = append(results, result)
+	  }
+	  done = !more
+	}
       }
-      done = !more
-    }
-  }
+    })
 
-  assert.Equal(t, results, []string{TestSong.RelativePath, TestSongNested.RelativePath})
-}
+    It("should return a channel with all the files in the directory", func() {
+      Expect(results).To(Equal([]string{
+	read.TestSong.RelativePath,
+	read.TestSongNested.RelativePath,
+      }))
+    })
+  })
+})

+ 14 - 0
music-player/pkg/read/read_suite_test.go

@@ -0,0 +1,14 @@
+package read_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+func TestRepository(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Read Suite")
+}
+

+ 6 - 3
music-player/pkg/read/types.go

@@ -1,8 +1,11 @@
 package read
 
 type Song struct {
-  Title, Artist, Album string
-  Duration int
+  Title string 		`db:"title"`
+  Artist string 	`db:"artist"`
+  Album string 		`db:"album"`
+  Duration int 		`db:"duration"`
   DurationOk bool
-  BasePath, RelativePath string
+  BasePath string 	`db:"base_path"`
+  RelativePath string 	`db:"relative_path"`
 }

+ 13 - 0
music-player/pkg/repository/repository_suite_test.go

@@ -0,0 +1,13 @@
+package repository_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+func TestRepository(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Repository Suite")
+}

+ 8 - 8
music-player/pkg/repository/scan.go

@@ -1,11 +1,10 @@
 package repository
 
 import (
-	"context"
 	"fmt"
 
 	"github.com/felamaslen/go-music-player/pkg/config"
-	"github.com/felamaslen/go-music-player/pkg/db"
+	"github.com/felamaslen/go-music-player/pkg/database"
 	"github.com/felamaslen/go-music-player/pkg/logger"
 	"github.com/felamaslen/go-music-player/pkg/read"
 )
@@ -13,6 +12,8 @@ import (
 func InsertMusicIntoDatabase(songs chan *read.Song) {
   var l = logger.CreateLogger(config.GetConfig().LogLevel)
 
+  db := database.GetConnection()
+
   for {
     select {
     case song, more := <- songs:
@@ -28,10 +29,7 @@ func InsertMusicIntoDatabase(songs chan *read.Song) {
         duration = fmt.Sprintf("%d", song.Duration)
       }
 
-      conn := db.GetConnection()
-
-      _, err := conn.Query(
-        context.Background(),
+      query, err := db.Query(
         "insert into songs (title, artist, album, duration, base_path, relative_path) values ($1, $2, $3, $4, $5, $6)",
         song.Title,
         song.Artist,
@@ -41,9 +39,11 @@ func InsertMusicIntoDatabase(songs chan *read.Song) {
         song.RelativePath,
       )
 
-      conn.Conn().Close(context.Background())
+      query.Close()
 
-      if err != nil {
+      if err == nil {
+        l.Info("Added %s\n", song.RelativePath)
+      } else {
         l.Error("Error inserting record: %s\n", err)
       }
     }

+ 87 - 76
music-player/pkg/repository/scan_test.go

@@ -1,83 +1,94 @@
-package repository
+package repository_test
 
 import (
-	"context"
-	"testing"
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
 
-	"github.com/stretchr/testify/assert"
-
-	"github.com/felamaslen/go-music-player/pkg/db"
+	"github.com/felamaslen/go-music-player/pkg/database"
 	"github.com/felamaslen/go-music-player/pkg/read"
+	"github.com/felamaslen/go-music-player/pkg/repository"
 	setup "github.com/felamaslen/go-music-player/pkg/testing"
 )
 
-func TestInsertMusicIntoDatabase(t *testing.T) {
-  setup.PrepareDatabaseForTesting()
-
-  songs := make(chan *read.Song)
-
-  go func() {
-    defer close(songs)
-
-    songs <- &read.Song{
-      Title: "Hey Jude",
-      Artist: "The Beatles",
-      Album: "",
-      Duration: 431,
-      DurationOk: true,
-      BasePath: "/path/to",
-      RelativePath: "file.ogg",
-    }
-
-    songs <- &read.Song{
-      Title: "Starman",
-      Artist: "David Bowie",
-      Album: "The Rise and Fall of Ziggy Stardust and the Spiders from Mars",
-      Duration: 256,
-      DurationOk: true,
-      BasePath: "/different/path",
-      RelativePath: "otherFile.ogg",
-    }
-  }()
-
-  InsertMusicIntoDatabase(songs)
-
-  conn := db.GetConnection()
-
-  rows, err := conn.Query(
-    context.Background(),
-    `
-    select title, artist, album, duration, base_path, relative_path
-    from songs
-    order by title
-    `,
-  )
-
-  assert.Nil(t, err)
-
-  var row read.Song
-
-  rows.Next()
-  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.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)
-}
+var _ = Describe("scanning repository", func() {
+  db := database.GetConnection()
+
+  BeforeEach(func() {
+    setup.PrepareDatabaseForTesting()
+  })
+
+  Describe("when the channel sends two files", func() {
+    var songs chan *read.Song
+
+    BeforeEach(func() {
+      songs = make(chan *read.Song)
+
+      go func() {
+	defer close(songs)
+	songs <- &read.Song{
+	  Title: "Hey Jude",
+	  Artist: "The Beatles",
+	  Album: "",
+	  Duration: 431,
+	  DurationOk: true,
+	  BasePath: "/path/to",
+	  RelativePath: "file.ogg",
+	}
+
+	songs <- &read.Song{
+	  Title: "Starman",
+	  Artist: "David Bowie",
+	  Album: "The Rise and Fall of Ziggy Stardust and the Spiders from Mars",
+	  Duration: 256,
+	  DurationOk: true,
+	  BasePath: "/different/path",
+	  RelativePath: "otherFile.ogg",
+	}
+      }()
+
+      repository.InsertMusicIntoDatabase(songs)
+    })
+
+    It("should insert the correct number of songs", func() {
+      var count int
+      db.Get(&count, "select count(*) from songs")
+      Expect(count).To(Equal(2))
+    })
+
+    It("should insert both songs", func() {
+      var song read.Song
+
+      rows, _ := db.Queryx(`
+      select title, artist, album, duration, base_path, relative_path
+      from songs
+      order by title
+      `)
+
+      rows.Next()
+      rows.StructScan(&song)
+
+      Expect(song).To(Equal(read.Song{
+        Title: "Hey Jude",
+        Artist: "The Beatles",
+        Album: "",
+        Duration: 431,
+        BasePath: "/path/to",
+        RelativePath: "file.ogg",
+      }))
+
+      rows.Next()
+      rows.StructScan(&song)
+
+      Expect(song).To(Equal(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",
+      }))
+
+      rows.Close()
+    })
+  })
+})

+ 40 - 44
music-player/pkg/services/scanner_test.go

@@ -1,51 +1,47 @@
-package services
+package services_test
 
 import (
-	"context"
-	"testing"
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
 
-	"github.com/felamaslen/go-music-player/pkg/db"
+	"github.com/felamaslen/go-music-player/pkg/database"
 	"github.com/felamaslen/go-music-player/pkg/read"
+	"github.com/felamaslen/go-music-player/pkg/services"
 	setup "github.com/felamaslen/go-music-player/pkg/testing"
-	"github.com/stretchr/testify/assert"
 )
 
-func TestIntegrationScanAndInsert(t *testing.T) {
-  setup.PrepareDatabaseForTesting()
-
-  ScanAndInsert(read.TestDirectory)
-
-  conn := db.GetConnection()
-
-  rows, err := conn.Query(
-    context.Background(),
-    `
-    select
-      title as "Title"
-      ,artist as "Artist"
-      ,album as "Album"
-      ,coalesce(duration, 0) as "Duration"
-      ,duration is not null as "DurationOk"
-      ,base_path as "BasePath"
-      ,relative_path as "RelativePath"
-    from songs
-    `,
-  )
-
-  assert.Nil(t, err)
-
-  var song read.Song
-
-  rows.Next()
-  rows.Scan(&song.Title, &song.Artist, &song.Album, &song.Duration, &song.DurationOk, &song.BasePath, &song.RelativePath)
-
-  assert.Equal(t, read.Song{
-    Title: read.TestSong.Title,
-    Artist: read.TestSong.Artist,
-    Album: read.TestSong.Album,
-    Duration: read.TestSong.Duration,
-    DurationOk: true,
-    BasePath: read.TestSong.BasePath,
-    RelativePath: read.TestSong.RelativePath,
-  }, song)
-}
+var _ = Describe("music scanner (integration test)", func() {
+
+  BeforeEach(func() {
+    setup.PrepareDatabaseForTesting()
+  })
+
+  It("should recursively scan files from a directory and add them to the database", func() {
+    services.ScanAndInsert(read.TestDirectory)
+
+    db := database.GetConnection()
+
+    rows, err := db.Queryx(`
+      select title, artist, album, duration, base_path, relative_path
+      from songs
+    `)
+
+    Expect(err).To(BeNil())
+
+    var song read.Song
+
+    rows.Next()
+    rows.StructScan(&song)
+
+    Expect(song).To(Equal(read.Song{
+      Title: read.TestSong.Title,
+      Artist: read.TestSong.Artist,
+      Album: read.TestSong.Album,
+      Duration: read.TestSong.Duration,
+      BasePath: read.TestSong.BasePath,
+      RelativePath: read.TestSong.RelativePath,
+    }))
+
+    rows.Close()
+  })
+})

+ 13 - 0
music-player/pkg/services/services_suite_test.go

@@ -0,0 +1,13 @@
+package services_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+func TestRepository(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Services Suite")
+}

+ 5 - 13
music-player/pkg/testing/testing.go

@@ -1,14 +1,12 @@
 package testing
 
 import (
-	"context"
 	"fmt"
 	"os"
 	"path"
 	"runtime"
 
-	"github.com/felamaslen/go-music-player/pkg/db"
-	"github.com/jackc/pgx/v4/pgxpool"
+	"github.com/felamaslen/go-music-player/pkg/database"
 )
 
 func ChangeToRootDir() {
@@ -25,16 +23,10 @@ func init() {
   ChangeToRootDir()
 }
 
-func PrepareDatabaseForTesting() *pgxpool.Conn {
-  fmt.Println("Preparing database for testing")
+func PrepareDatabaseForTesting() {
+  database.MigrateDatabase()
 
-  db.MigrateDatabase()
-  conn := db.GetConnection()
+  db := database.GetConnection()
 
-  conn.Query(
-    context.Background(),
-    "truncate table songs",
-  )
-
-  return conn
+  db.MustExec("truncate table songs")
 }

+ 1 - 1
music-player/test.env

@@ -3,4 +3,4 @@ POSTGRES_DATABASE=music_player_test
 POSTGRES_USER=docker
 POSTGRES_PASSWORD=docker
 POSTGRES_PORT=5417
-LOG_LEVEL=5
+LOG_LEVEL=0