dnote/pkg/cli/database/queries_test.go
2022-05-10 20:19:04 +10:00

384 lines
12 KiB
Go

/* Copyright (C) 2019, 2020, 2021, 2022 Monomax Software Pty Ltd
*
* This file is part of Dnote.
*
* Dnote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dnote is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dnote. If not, see <https://www.gnu.org/licenses/>.
*/
package database
import (
"database/sql"
"fmt"
"testing"
"time"
"github.com/dnote/dnote/pkg/assert"
"github.com/dnote/dnote/pkg/clock"
"github.com/pkg/errors"
)
func TestInsertSystem(t *testing.T) {
testCases := []struct {
key string
val string
}{
{
key: "foo",
val: "1558089284",
},
{
key: "baz",
val: "quz",
},
}
for _, tc := range testCases {
t.Run(fmt.Sprintf("insert %s %s", tc.key, tc.val), func(t *testing.T) {
// Setup
db := InitTestDB(t, "../tmp/dnote-test.db", nil)
defer TeardownTestDB(t, db)
// execute
tx, err := db.Begin()
if err != nil {
t.Fatalf(errors.Wrap(err, "beginning a transaction").Error())
}
if err := InsertSystem(tx, tc.key, tc.val); err != nil {
tx.Rollback()
t.Fatalf(errors.Wrap(err, "executing for test case").Error())
}
tx.Commit()
// test
var key, val string
MustScan(t, "getting the saved record",
db.QueryRow("SELECT key, value FROM system WHERE key = ?", tc.key), &key, &val)
assert.Equal(t, key, tc.key, "key mismatch for test case")
assert.Equal(t, val, tc.val, "val mismatch for test case")
})
}
}
func TestUpsertSystem(t *testing.T) {
testCases := []struct {
key string
val string
countDelta int
}{
{
key: "foo",
val: "1558089284",
countDelta: 1,
},
{
key: "baz",
val: "quz2",
countDelta: 0,
},
}
for _, tc := range testCases {
t.Run(fmt.Sprintf("insert %s %s", tc.key, tc.val), func(t *testing.T) {
// Setup
db := InitTestDB(t, "../tmp/dnote-test.db", nil)
defer TeardownTestDB(t, db)
MustExec(t, "inserting a system configuration", db, "INSERT INTO system (key, value) VALUES (?, ?)", "baz", "quz")
var initialSystemCount int
MustScan(t, "counting records", db.QueryRow("SELECT count(*) FROM system"), &initialSystemCount)
// execute
tx, err := db.Begin()
if err != nil {
t.Fatalf(errors.Wrap(err, "beginning a transaction").Error())
}
if err := UpsertSystem(tx, tc.key, tc.val); err != nil {
tx.Rollback()
t.Fatalf(errors.Wrap(err, "executing for test case").Error())
}
tx.Commit()
// test
var key, val string
MustScan(t, "getting the saved record",
db.QueryRow("SELECT key, value FROM system WHERE key = ?", tc.key), &key, &val)
var systemCount int
MustScan(t, "counting records",
db.QueryRow("SELECT count(*) FROM system"), &systemCount)
assert.Equal(t, key, tc.key, "key mismatch")
assert.Equal(t, val, tc.val, "val mismatch")
assert.Equal(t, systemCount, initialSystemCount+tc.countDelta, "count mismatch")
})
}
}
func TestGetSystem(t *testing.T) {
t.Run(fmt.Sprintf("get string value"), func(t *testing.T) {
// Setup
db := InitTestDB(t, "../tmp/dnote-test.db", nil)
defer TeardownTestDB(t, db)
// execute
MustExec(t, "inserting a system configuration", db, "INSERT INTO system (key, value) VALUES (?, ?)", "foo", "bar")
tx, err := db.Begin()
if err != nil {
t.Fatalf(errors.Wrap(err, "beginning a transaction").Error())
}
var dest string
if err := GetSystem(tx, "foo", &dest); err != nil {
tx.Rollback()
t.Fatalf(errors.Wrap(err, "executing for test case").Error())
}
tx.Commit()
// test
assert.Equal(t, dest, "bar", "dest mismatch")
})
t.Run(fmt.Sprintf("get int64 value"), func(t *testing.T) {
// Setup
db := InitTestDB(t, "../tmp/dnote-test.db", nil)
defer TeardownTestDB(t, db)
// execute
MustExec(t, "inserting a system configuration", db, "INSERT INTO system (key, value) VALUES (?, ?)", "foo", 1234)
tx, err := db.Begin()
if err != nil {
t.Fatalf(errors.Wrap(err, "beginning a transaction").Error())
}
var dest int64
if err := GetSystem(tx, "foo", &dest); err != nil {
tx.Rollback()
t.Fatalf(errors.Wrap(err, "executing for test case").Error())
}
tx.Commit()
// test
assert.Equal(t, dest, int64(1234), "dest mismatch")
})
}
func TestUpdateSystem(t *testing.T) {
testCases := []struct {
key string
val string
countDelta int
}{
{
key: "foo",
val: "1558089284",
},
{
key: "foo",
val: "bar",
},
}
for _, tc := range testCases {
t.Run(fmt.Sprintf("update %s %s", tc.key, tc.val), func(t *testing.T) {
// Setup
db := InitTestDB(t, "../tmp/dnote-test.db", nil)
defer TeardownTestDB(t, db)
MustExec(t, "inserting a system configuration", db, "INSERT INTO system (key, value) VALUES (?, ?)", "foo", "fuz")
MustExec(t, "inserting a system configuration", db, "INSERT INTO system (key, value) VALUES (?, ?)", "baz", "quz")
var initialSystemCount int
MustScan(t, "counting records", db.QueryRow("SELECT count(*) FROM system"), &initialSystemCount)
// execute
tx, err := db.Begin()
if err != nil {
t.Fatalf(errors.Wrap(err, "beginning a transaction").Error())
}
if err := UpdateSystem(tx, tc.key, tc.val); err != nil {
tx.Rollback()
t.Fatalf(errors.Wrap(err, "executing for test case").Error())
}
tx.Commit()
// test
var key, val string
MustScan(t, "getting the saved record",
db.QueryRow("SELECT key, value FROM system WHERE key = ?", tc.key), &key, &val)
var systemCount int
MustScan(t, "counting records",
db.QueryRow("SELECT count(*) FROM system"), &systemCount)
assert.Equal(t, key, tc.key, "key mismatch")
assert.Equal(t, val, tc.val, "val mismatch")
assert.Equal(t, systemCount, initialSystemCount, "count mismatch")
})
}
}
func TestGetActiveNote(t *testing.T) {
t.Run("not deleted", func(t *testing.T) {
// set up
db := InitTestDB(t, "../tmp/dnote-test.db", nil)
defer TeardownTestDB(t, db)
n1UUID := "n1-uuid"
MustExec(t, "inserting n1", db, "INSERT INTO notes (uuid, book_uuid, body, added_on, edited_on, usn, public, deleted, dirty) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", n1UUID, "b1-uuid", "n1 content", 1542058875, 1542058876, 1, true, false, true)
var n1RowID int
MustScan(t, "getting rowid", db.QueryRow("SELECT rowid FROM notes WHERE uuid = ?", n1UUID), &n1RowID)
// execute
got, err := GetActiveNote(db, n1RowID)
if err != nil {
t.Fatal(errors.Wrap(err, "executing"))
}
// test
assert.Equal(t, got.RowID, n1RowID, "RowID mismatch")
assert.Equal(t, got.UUID, n1UUID, "UUID mismatch")
assert.Equal(t, got.BookUUID, "b1-uuid", "BookUUID mismatch")
assert.Equal(t, got.Body, "n1 content", "Body mismatch")
assert.Equal(t, got.AddedOn, int64(1542058875), "AddedOn mismatch")
assert.Equal(t, got.EditedOn, int64(1542058876), "EditedOn mismatch")
assert.Equal(t, got.USN, 1, "USN mismatch")
assert.Equal(t, got.Public, true, "Public mismatch")
assert.Equal(t, got.Deleted, false, "Deleted mismatch")
assert.Equal(t, got.Dirty, true, "Dirty mismatch")
})
t.Run("deleted", func(t *testing.T) {
// set up
db := InitTestDB(t, "../tmp/dnote-test.db", nil)
defer TeardownTestDB(t, db)
n1UUID := "n1-uuid"
MustExec(t, "inserting n1", db, "INSERT INTO notes (uuid, book_uuid, body, added_on, edited_on, usn, public, deleted, dirty) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", n1UUID, "b1-uuid", "n1 content", 1542058875, 1542058876, 1, true, true, true)
var n1RowID int
MustScan(t, "getting rowid", db.QueryRow("SELECT rowid FROM notes WHERE uuid = ?", n1UUID), &n1RowID)
// execute
_, err := GetActiveNote(db, n1RowID)
// test
if err == nil {
t.Error("Should have returned an error")
}
if err != nil && err != sql.ErrNoRows {
t.Error(errors.Wrap(err, "executing"))
}
})
}
func TestUpdateNoteContent(t *testing.T) {
// set up
db := InitTestDB(t, "../tmp/dnote-test.db", nil)
defer TeardownTestDB(t, db)
uuid := "n1-uuid"
MustExec(t, "inserting n1", db, "INSERT INTO notes (uuid, book_uuid, body, added_on, edited_on, usn, public, deleted, dirty) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", uuid, "b1-uuid", "n1 content", 1542058875, 0, 1, false, false, false)
var rowid int
MustScan(t, "getting rowid", db.QueryRow("SELECT rowid FROM notes WHERE uuid = ?", uuid), &rowid)
// execute
c := clock.NewMock()
now := time.Date(2017, time.March, 14, 21, 15, 0, 0, time.UTC)
c.SetNow(now)
err := UpdateNoteContent(db, c, rowid, "n1 content updated")
if err != nil {
t.Fatal(errors.Wrap(err, "executing"))
}
var content string
var editedOn int
var dirty bool
MustScan(t, "getting the note record", db.QueryRow("SELECT body, edited_on, dirty FROM notes WHERE rowid = ?", rowid), &content, &editedOn, &dirty)
assert.Equal(t, content, "n1 content updated", "content mismatch")
assert.Equal(t, int64(editedOn), now.UnixNano(), "editedOn mismatch")
assert.Equal(t, dirty, true, "dirty mismatch")
}
func TestUpdateNoteBook(t *testing.T) {
// set up
db := InitTestDB(t, "../tmp/dnote-test.db", nil)
defer TeardownTestDB(t, db)
b1UUID := "b1-uuid"
b2UUID := "b2-uuid"
MustExec(t, "inserting b1", db, "INSERT INTO books (uuid, label, usn, deleted, dirty) VALUES (?, ?, ?, ?, ?)", b1UUID, "b1-label", 8, false, false)
MustExec(t, "inserting b2", db, "INSERT INTO books (uuid, label, usn, deleted, dirty) VALUES (?, ?, ?, ?, ?)", b2UUID, "b2-label", 9, false, false)
uuid := "n1-uuid"
MustExec(t, "inserting n1", db, "INSERT INTO notes (uuid, book_uuid, body, added_on, edited_on, usn, public, deleted, dirty) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", uuid, b1UUID, "n1 content", 1542058875, 0, 1, false, false, false)
var rowid int
MustScan(t, "getting rowid", db.QueryRow("SELECT rowid FROM notes WHERE uuid = ?", uuid), &rowid)
// execute
c := clock.NewMock()
now := time.Date(2017, time.March, 14, 21, 15, 0, 0, time.UTC)
c.SetNow(now)
err := UpdateNoteBook(db, c, rowid, b2UUID)
if err != nil {
t.Fatal(errors.Wrap(err, "executing"))
}
var bookUUID string
var editedOn int
var dirty bool
MustScan(t, "getting the note record", db.QueryRow("SELECT book_uuid, edited_on, dirty FROM notes WHERE rowid = ?", rowid), &bookUUID, &editedOn, &dirty)
assert.Equal(t, bookUUID, b2UUID, "content mismatch")
assert.Equal(t, int64(editedOn), now.UnixNano(), "editedOn mismatch")
assert.Equal(t, dirty, true, "dirty mismatch")
}
func TestUpdateBookName(t *testing.T) {
// set up
db := InitTestDB(t, "../tmp/dnote-test.db", nil)
defer TeardownTestDB(t, db)
b1UUID := "b1-uuid"
MustExec(t, "inserting b1", db, "INSERT INTO books (uuid, label, usn, deleted, dirty) VALUES (?, ?, ?, ?, ?)", b1UUID, "b1-label", 8, false, false)
// execute
err := UpdateBookName(db, b1UUID, "b1-label-edited")
if err != nil {
t.Fatal(errors.Wrap(err, "executing"))
}
// test
var b1 Book
MustScan(t, "getting the note record", db.QueryRow("SELECT uuid, label, dirty, usn, deleted FROM books WHERE uuid = ?", b1UUID), &b1.UUID, &b1.Label, &b1.Dirty, &b1.USN, &b1.Deleted)
assert.Equal(t, b1.UUID, b1UUID, "UUID mismatch")
assert.Equal(t, b1.Label, "b1-label-edited", "Label mismatch")
assert.Equal(t, b1.Dirty, true, "Dirty mismatch")
assert.Equal(t, b1.USN, 8, "USN mismatch")
assert.Equal(t, b1.Deleted, false, "Deleted mismatch")
}