Dan Anglin
3169d341d2
Change Status.Order to Status.Position, and the ByStatusOrder type to ByStatusPosition to make it clearer that status' are ordered by their position on the Kanban board.
347 lines
7.2 KiB
Go
347 lines
7.2 KiB
Go
package db_test
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/gob"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"codeflow.dananglin.me.uk/apollo/canal/internal/board"
|
|
"codeflow.dananglin.me.uk/apollo/canal/internal/db"
|
|
bolt "go.etcd.io/bbolt"
|
|
)
|
|
|
|
func TestOpenDataBaseXDGDataDir(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
projectDir, err := projectRoot()
|
|
if err != nil {
|
|
t.Fatalf(err.Error())
|
|
}
|
|
|
|
testXdgDataHome := filepath.Join(projectDir, "test", "databases", "xdg_data_dir")
|
|
defer os.RemoveAll(testXdgDataHome)
|
|
|
|
if err := os.Setenv("XDG_DATA_HOME", testXdgDataHome); err != nil {
|
|
t.Fatalf("An error occurred whilst setting the XDG_DATA_HOME environment variable, %s", err)
|
|
}
|
|
|
|
defer func() {
|
|
_ = os.Unsetenv("XDG_DATA_HOME")
|
|
}()
|
|
|
|
db, err := db.OpenDatabase("")
|
|
if err != nil {
|
|
t.Fatalf("An error occurred whilst opening the test database, %s.", err)
|
|
}
|
|
|
|
_ = db.Close()
|
|
|
|
wantDB := filepath.Join(testXdgDataHome, "canal", "canal.db")
|
|
|
|
// ensure that the database file exists
|
|
_, err = os.Stat(wantDB)
|
|
if err != nil {
|
|
t.Fatalf("Unable to get file information of the test database, %s", err)
|
|
}
|
|
}
|
|
|
|
func TestWriteAndReadStatusList(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var database *bolt.DB
|
|
|
|
var err error
|
|
|
|
projectDir, err := projectRoot()
|
|
if err != nil {
|
|
t.Fatalf(err.Error())
|
|
}
|
|
|
|
testDB := filepath.Join(projectDir, "test", "databases", "Database_TestWriteAndReadStatusList.db")
|
|
os.Remove(testDB)
|
|
|
|
if database, err = db.OpenDatabase(testDB); err != nil {
|
|
t.Fatalf("An error occurred whilst opening the test database %s, %s.", testDB, err)
|
|
}
|
|
|
|
defer func() {
|
|
_ = database.Close()
|
|
}()
|
|
|
|
testWriteStatusList(t, database)
|
|
testReadStatusList(t, database)
|
|
}
|
|
|
|
func testWriteStatusList(t *testing.T, database *bolt.DB) {
|
|
t.Helper()
|
|
|
|
newStatusList := []board.Status{
|
|
{
|
|
ID: -1,
|
|
Name: "Backlog",
|
|
CardIds: []int{1, 14, 9, 10},
|
|
Position: 1,
|
|
},
|
|
{
|
|
ID: -1,
|
|
Name: "Next",
|
|
CardIds: []int{2, 5, 12},
|
|
Position: 2,
|
|
},
|
|
{
|
|
ID: -1,
|
|
Name: "In progress",
|
|
CardIds: []int{3, 14},
|
|
Position: 3,
|
|
},
|
|
{
|
|
ID: -1,
|
|
Name: "Finished!",
|
|
CardIds: []int{4, 6, 7, 8, 11, 13},
|
|
Position: 4,
|
|
},
|
|
}
|
|
|
|
boltItems := make([]db.BoltItem, len(newStatusList))
|
|
|
|
for i := range newStatusList {
|
|
boltItems[i] = &newStatusList[i]
|
|
}
|
|
|
|
if _, err := db.WriteMany(database, db.StatusBucket, boltItems); err != nil {
|
|
t.Fatalf("An error occurred whilst writing the initial status list to the database, %s", err)
|
|
}
|
|
}
|
|
|
|
func testReadStatusList(t *testing.T, database *bolt.DB) {
|
|
t.Helper()
|
|
|
|
data, err := db.ReadAll(database, db.StatusBucket)
|
|
if err != nil {
|
|
t.Fatalf("An error occurred whilst reading the modified status list from the database, %s", err)
|
|
}
|
|
|
|
got := make([]board.Status, len(data))
|
|
|
|
for i, d := range data {
|
|
buf := bytes.NewBuffer(d)
|
|
|
|
decoder := gob.NewDecoder(buf)
|
|
|
|
var s board.Status
|
|
|
|
if err := decoder.Decode(&s); err != nil {
|
|
t.Fatalf("An error occurred whilst decoding data, %s", err)
|
|
}
|
|
|
|
got[i] = s
|
|
}
|
|
|
|
want := []board.Status{
|
|
{
|
|
ID: 1,
|
|
Name: "Backlog",
|
|
CardIds: []int{1, 14, 9, 10},
|
|
Position: 1,
|
|
},
|
|
{
|
|
ID: 2,
|
|
Name: "Next",
|
|
CardIds: []int{2, 5, 12},
|
|
Position: 2,
|
|
},
|
|
{
|
|
ID: 3,
|
|
Name: "In progress",
|
|
CardIds: []int{3, 14},
|
|
Position: 3,
|
|
},
|
|
{
|
|
ID: 4,
|
|
Name: "Finished!",
|
|
CardIds: []int{4, 6, 7, 8, 11, 13},
|
|
Position: 4,
|
|
},
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Errorf("Unexpected status list read from the database: got %+v, want %+v", got, want)
|
|
} else {
|
|
t.Logf("Expected status list read from the database: got %+v", got)
|
|
}
|
|
}
|
|
|
|
func TestReadAndWriteCards(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var database *bolt.DB
|
|
|
|
var err error
|
|
|
|
projectDir, err := projectRoot()
|
|
if err != nil {
|
|
t.Fatalf(err.Error())
|
|
}
|
|
|
|
testDB := filepath.Join(projectDir, "test", "databases", "Database_TestReadWriteCard.db")
|
|
os.Remove(testDB)
|
|
|
|
if database, err = db.OpenDatabase(testDB); err != nil {
|
|
t.Fatalf("An error occurred whilst opening the test database %s, %s.", testDB, err)
|
|
}
|
|
|
|
defer func() {
|
|
_ = database.Close()
|
|
}()
|
|
|
|
singleCard := board.Card{
|
|
ID: -1,
|
|
Title: "A test task.",
|
|
Content: "This task should be completed.",
|
|
}
|
|
|
|
singleCardID := testWriteOneCard(t, database, singleCard)
|
|
testReadOneCard(t, database, singleCardID)
|
|
|
|
manyCards := []board.Card{
|
|
{
|
|
ID: -1,
|
|
Title: "Test card A.",
|
|
Content: "This is test card A.",
|
|
},
|
|
{
|
|
ID: -1,
|
|
Title: "Test card B.",
|
|
Content: "This is test card B.",
|
|
},
|
|
{
|
|
ID: -1,
|
|
Title: "Test card C.",
|
|
Content: "This is test card C.",
|
|
},
|
|
}
|
|
|
|
manyCardIDs := testWriteManyCard(t, database, manyCards)
|
|
testReadManyCards(t, database, manyCardIDs)
|
|
}
|
|
|
|
func testWriteOneCard(t *testing.T, database *bolt.DB, card board.Card) int {
|
|
t.Helper()
|
|
|
|
cardID, err := db.Write(database, db.CardBucket, &card)
|
|
if err != nil {
|
|
t.Fatalf("An error occurred whilst writing the card to the database, %s", err)
|
|
}
|
|
|
|
return cardID
|
|
}
|
|
|
|
func testReadOneCard(t *testing.T, database *bolt.DB, cardID int) {
|
|
t.Helper()
|
|
|
|
data, err := db.Read(database, db.CardBucket, cardID)
|
|
if err != nil {
|
|
t.Fatalf("An error occurred whilst loading the modified from the database, %s", err)
|
|
}
|
|
|
|
var got board.Card
|
|
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
decoder := gob.NewDecoder(buf)
|
|
|
|
if err := decoder.Decode(&got); err != nil {
|
|
t.Fatalf("Unable to decode data, %s", err)
|
|
}
|
|
|
|
want := board.Card{
|
|
ID: 1,
|
|
Title: "A test task.",
|
|
Content: "This task should be completed.",
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Errorf("Unexpected card read from the database: got %+v, want %+v", got, want)
|
|
} else {
|
|
t.Logf("Expected card read from the database: got %+v", got)
|
|
}
|
|
}
|
|
|
|
func testWriteManyCard(t *testing.T, database *bolt.DB, cards []board.Card) []int {
|
|
t.Helper()
|
|
|
|
boltItems := make([]db.BoltItem, len(cards))
|
|
|
|
for i := range cards {
|
|
boltItems[i] = &cards[i]
|
|
}
|
|
|
|
ids, err := db.WriteMany(database, db.CardBucket, boltItems)
|
|
if err != nil {
|
|
t.Fatalf("An error occurred whilst writing many cards to the database, %s", err)
|
|
}
|
|
|
|
return ids
|
|
}
|
|
|
|
func testReadManyCards(t *testing.T, database *bolt.DB, cardIDs []int) {
|
|
t.Helper()
|
|
|
|
data, err := db.ReadMany(database, db.CardBucket, cardIDs)
|
|
if err != nil {
|
|
t.Fatalf("An error occurred whilst reading the data from the database, %s", err)
|
|
}
|
|
|
|
got := make([]board.Card, len(data))
|
|
|
|
for i, d := range data {
|
|
buf := bytes.NewBuffer(d)
|
|
|
|
decoder := gob.NewDecoder(buf)
|
|
|
|
var c board.Card
|
|
|
|
if err := decoder.Decode(&c); err != nil {
|
|
t.Fatalf("An error occurred whilst decoding data, %s", err)
|
|
}
|
|
|
|
got[i] = c
|
|
}
|
|
|
|
want := []board.Card{
|
|
{
|
|
ID: 2,
|
|
Title: "Test card A.",
|
|
Content: "This is test card A.",
|
|
},
|
|
{
|
|
ID: 3,
|
|
Title: "Test card B.",
|
|
Content: "This is test card B.",
|
|
},
|
|
{
|
|
ID: 4,
|
|
Title: "Test card C.",
|
|
Content: "This is test card C.",
|
|
},
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Errorf("Unexpected list of cards read from the database: got %+v, want %+v", got, want)
|
|
} else {
|
|
t.Logf("Expected list of cards read from the database: got %+v", got)
|
|
}
|
|
}
|
|
|
|
func projectRoot() (string, error) {
|
|
cwd, err := os.Getwd()
|
|
if err != nil {
|
|
return "", fmt.Errorf("unable to get the current working directory, %w", err)
|
|
}
|
|
|
|
return filepath.Join(cwd, "..", ".."), nil
|
|
}
|