Let users customize the path to the scouting database

I want to write a script that runs the scouting webserver. For that to
work elegantly, I need to be able to customize the database path.
Otherwise it gets created in the runfiles tree.

Signed-off-by: Philipp Schrader <philipp.schrader@gmail.com>
Change-Id: I6f06f9b82ca2d3476c76d795ad57b06f7b360ba8
diff --git a/scouting/db/db.go b/scouting/db/db.go
index 86d332e..1d0081b 100644
--- a/scouting/db/db.go
+++ b/scouting/db/db.go
@@ -26,9 +26,11 @@
 	climbing                                                     int
 }
 
-func NewDatabase() (*Database, error) {
+// Opens a database at the specified path. If the path refers to a non-existent
+// file, the database will be created and initialized with empty tables.
+func NewDatabase(path string) (*Database, error) {
 	database := new(Database)
-	database.DB, _ = sql.Open("sqlite3", "./scouting.db")
+	database.DB, _ = sql.Open("sqlite3", path)
 	statement, error_ := database.Prepare("CREATE TABLE IF NOT EXISTS matches " +
 		"(id INTEGER PRIMARY KEY, matchNumber INTEGER, round INTEGER, compLevel INTEGER, r1 INTEGER, r2 INTEGER, r3 INTEGER, b1 INTEGER, b2 INTEGER, b3 INTEGER, r1ID INTEGER, r2ID INTEGER, r3ID INTEGER, b1ID INTEGER, b2ID INTEGER, b3ID INTEGER)")
 	defer statement.Close()
diff --git a/scouting/db/db_test.go b/scouting/db/db_test.go
index 3c6d9c5..39f12e3 100644
--- a/scouting/db/db_test.go
+++ b/scouting/db/db_test.go
@@ -1,16 +1,28 @@
 package db
 
 import (
-	"fmt"
+	"os"
+	"path/filepath"
 	"reflect"
 	"testing"
 )
 
-func TestAddToMatchDB(t *testing.T) {
-	db, error_ := NewDatabase()
-	if error_ != nil {
-		t.Fatalf(error_.Error())
+// Creates a database in TEST_TMPDIR so that we don't accidentally write it
+// into the runfiles directory.
+func createDatabase(t *testing.T) *Database {
+	// Get the path to our temporary writable directory.
+	testTmpdir := os.Getenv("TEST_TMPDIR")
+	db, err := NewDatabase(filepath.Join(testTmpdir, "scouting.db"))
+	if err != nil {
+		t.Fatal("Failed to create a new database: ", err)
 	}
+	return db
+}
+
+func TestAddToMatchDB(t *testing.T) {
+	db := createDatabase(t)
+	defer db.Delete()
+
 	correct := []Match{Match{matchNumber: 7, round: 1, compLevel: "quals", r1: 9999, r2: 1000, r3: 777, b1: 0000, b2: 4321, b3: 1234, r1ID: 1, r2ID: 2, r3ID: 3, b1ID: 4, b2ID: 5, b3ID: 6}}
 	db.AddToMatch(correct[0])
 	got, error_ := db.ReturnMatches()
@@ -20,14 +32,12 @@
 	if !reflect.DeepEqual(correct, got) {
 		t.Fatalf("Got %#v,\nbut expected %#v.", got, correct)
 	}
-	db.Delete()
 }
 
 func TestAddToStatsDB(t *testing.T) {
-	db, error_ := NewDatabase()
-	if error_ != nil {
-		t.Fatalf(error_.Error())
-	}
+	db := createDatabase(t)
+	defer db.Delete()
+
 	correct := []Stats{
 		Stats{teamNumber: 1236, matchNumber: 7, shotsMissed: 9, upperGoalShots: 5, lowerGoalShots: 4, shotsMissedAuto: 3, upperGoalAuto: 2, lowerGoalAuto: 1, playedDefense: 2, climbing: 3},
 		Stats{teamNumber: 1001, matchNumber: 7, shotsMissed: 6, upperGoalShots: 9, lowerGoalShots: 9, shotsMissedAuto: 0, upperGoalAuto: 0, lowerGoalAuto: 0, playedDefense: 0, climbing: 0},
@@ -47,15 +57,11 @@
 	if !reflect.DeepEqual(correct, got) {
 		t.Errorf("Got %#v,\nbut expected %#v.", got, correct)
 	}
-	db.Delete()
 }
 
 func TestQueryMatchDB(t *testing.T) {
-	db, error_ := NewDatabase()
-	if error_ != nil {
-		t.Fatalf(error_.Error())
-		fmt.Println("Error creating new database")
-	}
+	db := createDatabase(t)
+	defer db.Delete()
 
 	testDatabase := []Match{
 		Match{matchNumber: 2, round: 1, compLevel: "quals", r1: 251, r2: 169, r3: 286, b1: 253, b2: 538, b3: 149},
@@ -74,17 +80,18 @@
 	}
 
 	got, error_ := db.QueryMatches(538)
+	if error_ != nil {
+		t.Fatal("Failed to query matches for 538: ", error_)
+	}
 	if !reflect.DeepEqual(correct, got) {
 		t.Fatalf("Got %#v,\nbut expected %#v.", got, correct)
 	}
-	db.Delete()
 }
 
 func TestQueryStatsDB(t *testing.T) {
-	db, error_ := NewDatabase()
-	if error_ != nil {
-		t.Fatalf(error_.Error())
-	}
+	db := createDatabase(t)
+	defer db.Delete()
+
 	testDatabase := []Stats{
 		Stats{teamNumber: 1235, matchNumber: 94, shotsMissed: 2, upperGoalShots: 2, lowerGoalShots: 2, shotsMissedAuto: 2, upperGoalAuto: 2, lowerGoalAuto: 2, playedDefense: 2, climbing: 2},
 		Stats{teamNumber: 1234, matchNumber: 94, shotsMissed: 4, upperGoalShots: 4, lowerGoalShots: 4, shotsMissedAuto: 4, upperGoalAuto: 4, lowerGoalAuto: 4, playedDefense: 7, climbing: 2},
@@ -107,14 +114,12 @@
 	if !reflect.DeepEqual(correct, got) {
 		t.Errorf("Got %#v,\nbut expected %#v.", got, correct)
 	}
-	db.Delete()
 }
 
 func TestReturnMatchDB(t *testing.T) {
-	db, error_ := NewDatabase()
-	if error_ != nil {
-		t.Fatalf(error_.Error())
-	}
+	db := createDatabase(t)
+	defer db.Delete()
+
 	correct := []Match{
 		Match{matchNumber: 2, round: 1, compLevel: "quals", r1: 251, r2: 169, r3: 286, b1: 253, b2: 538, b3: 149, r1ID: 1, r2ID: 2, r3ID: 3, b1ID: 4, b2ID: 5, b3ID: 6},
 		Match{matchNumber: 3, round: 1, compLevel: "quals", r1: 147, r2: 421, r3: 538, b1: 126, b2: 448, b3: 262, r1ID: 7, r2ID: 8, r3ID: 9, b1ID: 10, b2ID: 11, b3ID: 12},
@@ -132,14 +137,12 @@
 	if !reflect.DeepEqual(correct, got) {
 		t.Errorf("Got %#v,\nbut expected %#v.", got, correct)
 	}
-	db.Delete()
 }
 
 func TestReturnStatsDB(t *testing.T) {
-	db, error_ := NewDatabase()
-	if error_ != nil {
-		t.Fatalf(error_.Error())
-	}
+	db := createDatabase(t)
+	defer db.Delete()
+
 	correct := []Stats{
 		Stats{teamNumber: 1235, matchNumber: 94, shotsMissed: 2, upperGoalShots: 2, lowerGoalShots: 2, shotsMissedAuto: 2, upperGoalAuto: 2, lowerGoalAuto: 2, playedDefense: 2, climbing: 2},
 		Stats{teamNumber: 1236, matchNumber: 94, shotsMissed: 4, upperGoalShots: 4, lowerGoalShots: 4, shotsMissedAuto: 4, upperGoalAuto: 4, lowerGoalAuto: 4, playedDefense: 7, climbing: 2},
@@ -159,5 +162,4 @@
 	if !reflect.DeepEqual(correct, got) {
 		t.Errorf("Got %#v,\nbut expected %#v.", got, correct)
 	}
-	db.Delete()
 }