2023-05-06 12:49:40 +01:00
|
|
|
package db_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/gob"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"codeflow.dananglin.me.uk/apollo/pelican/internal/board"
|
|
|
|
"codeflow.dananglin.me.uk/apollo/pelican/internal/db"
|
|
|
|
bolt "go.etcd.io/bbolt"
|
|
|
|
)
|
|
|
|
|
|
|
|
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 ind, d := range data {
|
|
|
|
buf := bytes.NewBuffer(d)
|
|
|
|
|
|
|
|
decoder := gob.NewDecoder(buf)
|
|
|
|
|
|
|
|
var status board.Status
|
|
|
|
|
|
|
|
if err := decoder.Decode(&status); err != nil {
|
|
|
|
t.Fatalf("An error occurred whilst decoding data, %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
got[ind] = status
|
|
|
|
}
|
|
|
|
|
|
|
|
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.",
|
2024-01-10 12:12:54 +00:00
|
|
|
Description: "This task should be completed.",
|
2023-05-06 12:49:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
singleCardID := testWriteOneCard(t, database, singleCard)
|
|
|
|
testReadOneCard(t, database, singleCardID)
|
|
|
|
|
|
|
|
manyCards := []board.Card{
|
|
|
|
{
|
|
|
|
ID: -1,
|
|
|
|
Title: "Test card A.",
|
2024-01-10 12:12:54 +00:00
|
|
|
Description: "This is test card A.",
|
2023-05-06 12:49:40 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: -1,
|
|
|
|
Title: "Test card B.",
|
2024-01-10 12:12:54 +00:00
|
|
|
Description: "This is test card B.",
|
2023-05-06 12:49:40 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: -1,
|
|
|
|
Title: "Test card C.",
|
2024-01-10 12:12:54 +00:00
|
|
|
Description: "This is test card C.",
|
2023-05-06 12:49:40 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
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.",
|
2024-01-10 12:12:54 +00:00
|
|
|
Description: "This task should be completed.",
|
2023-05-06 12:49:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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.",
|
2024-01-10 12:12:54 +00:00
|
|
|
Description: "This is test card A.",
|
2023-05-06 12:49:40 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: 3,
|
|
|
|
Title: "Test card B.",
|
2024-01-10 12:12:54 +00:00
|
|
|
Description: "This is test card B.",
|
2023-05-06 12:49:40 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: 4,
|
|
|
|
Title: "Test card C.",
|
2024-01-10 12:12:54 +00:00
|
|
|
Description: "This is test card C.",
|
2023-05-06 12:49:40 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
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 TestDeleteOneCard(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_TestDeleteOneCard.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()
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Create one card, get card ID.
|
|
|
|
card := board.Card{
|
|
|
|
ID: -1,
|
|
|
|
Title: "Test card",
|
2024-01-10 12:12:54 +00:00
|
|
|
Description: "",
|
2023-05-06 12:49:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
cardID, err := db.Write(database, db.CardBucket, &card)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("ERROR: Unable to create the card in the database, %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cards, err := db.ReadAll(database, db.CardBucket)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("ERROR: Unable to read the cards from the database, %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
numCards := len(cards)
|
|
|
|
if numCards != 1 {
|
|
|
|
t.Fatalf("ERROR: Unexpected number of cards returned from the card bucket; want 1; got %d", numCards)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := db.Delete(database, db.CardBucket, cardID); err != nil {
|
|
|
|
t.Fatalf("ERROR: Unable to delete the card from the database, %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get all cards, expect length = 0; error if not 0
|
|
|
|
cards, err = db.ReadAll(database, db.CardBucket)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("ERROR: Unable to read the cards from the database, %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
numCards = len(cards)
|
|
|
|
if numCards != 0 {
|
|
|
|
t.Errorf("%s\tUnexpected number of cards returned from the card bucket; want 0; got %d", failure, numCards)
|
|
|
|
} else {
|
|
|
|
t.Logf("%s\tThe card was successfully deleted from the database.", success)
|
|
|
|
}
|
|
|
|
}
|