pelican/internal/database/database_test.go

347 lines
7.1 KiB
Go

package database_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/database"
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 := database.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 db *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 db, err = database.OpenDatabase(testDB); err != nil {
t.Fatalf("An error occurred whilst opening the test database %s, %s.", testDB, err)
}
defer func() {
_ = db.Close()
}()
testWriteStatusList(t, db)
testReadStatusList(t, db)
}
func testWriteStatusList(t *testing.T, db *bolt.DB) {
t.Helper()
newStatusList := []board.Status{
{
ID: -1,
Name: "Backlog",
CardIds: []int{1, 14, 9, 10},
Order: 1,
},
{
ID: -1,
Name: "Next",
CardIds: []int{2, 5, 12},
Order: 2,
},
{
ID: -1,
Name: "In progress",
CardIds: []int{3, 14},
Order: 3,
},
{
ID: -1,
Name: "Finished!",
CardIds: []int{4, 6, 7, 8, 11, 13},
Order: 4,
},
}
boltItems := make([]database.BoltItem, len(newStatusList))
for i := range newStatusList {
boltItems[i] = &newStatusList[i]
}
if _, err := database.WriteMany(db, database.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, db *bolt.DB) {
t.Helper()
data, err := database.ReadAll(db, database.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},
Order: 1,
},
{
ID: 2,
Name: "Next",
CardIds: []int{2, 5, 12},
Order: 2,
},
{
ID: 3,
Name: "In progress",
CardIds: []int{3, 14},
Order: 3,
},
{
ID: 4,
Name: "Finished!",
CardIds: []int{4, 6, 7, 8, 11, 13},
Order: 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 db *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 db, err = database.OpenDatabase(testDB); err != nil {
t.Fatalf("An error occurred whilst opening the test database %s, %s.", testDB, err)
}
defer func() {
_ = db.Close()
}()
singleCard := board.Card{
ID: -1,
Title: "A test task.",
Content: "This task should be completed.",
}
singleCardID := testWriteOneCard(t, db, singleCard)
testReadOneCard(t, db, 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, db, manyCards)
testReadManyCards(t, db, manyCardIDs)
}
func testWriteOneCard(t *testing.T, db *bolt.DB, card board.Card) int {
t.Helper()
cardID, err := database.Write(db, database.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, db *bolt.DB, cardID int) {
t.Helper()
data, err := database.Read(db, database.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, db *bolt.DB, cards []board.Card) []int {
t.Helper()
boltItems := make([]database.BoltItem, len(cards))
for i := range cards {
boltItems[i] = &cards[i]
}
ids, err := database.WriteMany(db, database.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, db *bolt.DB, cardIDs []int) {
t.Helper()
data, err := database.ReadMany(db, database.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
}