mirror of
https://github.com/dnote/dnote
synced 2026-03-14 22:45:50 +01:00
851 lines
26 KiB
Go
851 lines
26 KiB
Go
/* Copyright 2025 Dnote Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package database
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/dnote/dnote/pkg/assert"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func TestNewNote(t *testing.T) {
|
|
testCases := []struct {
|
|
uuid string
|
|
bookUUID string
|
|
body string
|
|
addedOn int64
|
|
editedOn int64
|
|
usn int
|
|
deleted bool
|
|
dirty bool
|
|
}{
|
|
{
|
|
uuid: "n1-uuid",
|
|
bookUUID: "b1-uuid",
|
|
body: "n1-body",
|
|
addedOn: 1542058875,
|
|
editedOn: 0,
|
|
usn: 0,
|
|
deleted: false,
|
|
dirty: false,
|
|
},
|
|
{
|
|
uuid: "n2-uuid",
|
|
bookUUID: "b2-uuid",
|
|
body: "n2-body",
|
|
addedOn: 1542058875,
|
|
editedOn: 1542058876,
|
|
usn: 1008,
|
|
deleted: true,
|
|
dirty: true,
|
|
},
|
|
}
|
|
|
|
for idx, tc := range testCases {
|
|
got := NewNote(tc.uuid, tc.bookUUID, tc.body, tc.addedOn, tc.editedOn, tc.usn, tc.deleted, tc.dirty)
|
|
|
|
assert.Equal(t, got.UUID, tc.uuid, fmt.Sprintf("UUID mismatch for test case %d", idx))
|
|
assert.Equal(t, got.BookUUID, tc.bookUUID, fmt.Sprintf("BookUUID mismatch for test case %d", idx))
|
|
assert.Equal(t, got.Body, tc.body, fmt.Sprintf("Body mismatch for test case %d", idx))
|
|
assert.Equal(t, got.AddedOn, tc.addedOn, fmt.Sprintf("AddedOn mismatch for test case %d", idx))
|
|
assert.Equal(t, got.EditedOn, tc.editedOn, fmt.Sprintf("EditedOn mismatch for test case %d", idx))
|
|
assert.Equal(t, got.USN, tc.usn, fmt.Sprintf("USN mismatch for test case %d", idx))
|
|
assert.Equal(t, got.Deleted, tc.deleted, fmt.Sprintf("Deleted mismatch for test case %d", idx))
|
|
assert.Equal(t, got.Dirty, tc.dirty, fmt.Sprintf("Dirty mismatch for test case %d", idx))
|
|
}
|
|
}
|
|
|
|
func TestNoteInsert(t *testing.T) {
|
|
testCases := []struct {
|
|
uuid string
|
|
bookUUID string
|
|
body string
|
|
addedOn int64
|
|
editedOn int64
|
|
usn int
|
|
deleted bool
|
|
dirty bool
|
|
}{
|
|
{
|
|
uuid: "n1-uuid",
|
|
bookUUID: "b1-uuid",
|
|
body: "n1-body",
|
|
addedOn: 1542058875,
|
|
editedOn: 0,
|
|
usn: 0,
|
|
deleted: false,
|
|
dirty: false,
|
|
},
|
|
{
|
|
uuid: "n2-uuid",
|
|
bookUUID: "b2-uuid",
|
|
body: "n2-body",
|
|
addedOn: 1542058875,
|
|
editedOn: 1542058876,
|
|
usn: 1008,
|
|
deleted: true,
|
|
dirty: true,
|
|
},
|
|
}
|
|
|
|
for idx, tc := range testCases {
|
|
func() {
|
|
// Setup
|
|
db := InitTestMemoryDB(t)
|
|
|
|
n := Note{
|
|
UUID: tc.uuid,
|
|
BookUUID: tc.bookUUID,
|
|
Body: tc.body,
|
|
AddedOn: tc.addedOn,
|
|
EditedOn: tc.editedOn,
|
|
USN: tc.usn,
|
|
Deleted: tc.deleted,
|
|
Dirty: tc.dirty,
|
|
}
|
|
|
|
// execute
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
t.Fatal(errors.Wrap(err, fmt.Sprintf("beginning a transaction for test case %d", idx)).Error())
|
|
}
|
|
|
|
if err := n.Insert(tx); err != nil {
|
|
tx.Rollback()
|
|
t.Fatal(errors.Wrap(err, fmt.Sprintf("executing for test case %d", idx)).Error())
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
// test
|
|
var uuid, bookUUID, body string
|
|
var addedOn, editedOn int64
|
|
var usn int
|
|
var deleted, dirty bool
|
|
MustScan(t, "getting n1",
|
|
db.QueryRow("SELECT uuid, book_uuid, body, added_on, edited_on, usn, deleted, dirty FROM notes WHERE uuid = ?", tc.uuid),
|
|
&uuid, &bookUUID, &body, &addedOn, &editedOn, &usn, &deleted, &dirty)
|
|
|
|
assert.Equal(t, uuid, tc.uuid, fmt.Sprintf("uuid mismatch for test case %d", idx))
|
|
assert.Equal(t, bookUUID, tc.bookUUID, fmt.Sprintf("bookUUID mismatch for test case %d", idx))
|
|
assert.Equal(t, body, tc.body, fmt.Sprintf("body mismatch for test case %d", idx))
|
|
assert.Equal(t, addedOn, tc.addedOn, fmt.Sprintf("addedOn mismatch for test case %d", idx))
|
|
assert.Equal(t, editedOn, tc.editedOn, fmt.Sprintf("editedOn mismatch for test case %d", idx))
|
|
assert.Equal(t, usn, tc.usn, fmt.Sprintf("usn mismatch for test case %d", idx))
|
|
assert.Equal(t, deleted, tc.deleted, fmt.Sprintf("deleted mismatch for test case %d", idx))
|
|
assert.Equal(t, dirty, tc.dirty, fmt.Sprintf("dirty mismatch for test case %d", idx))
|
|
}()
|
|
}
|
|
}
|
|
|
|
func TestNoteUpdate(t *testing.T) {
|
|
testCases := []struct {
|
|
uuid string
|
|
bookUUID string
|
|
body string
|
|
addedOn int64
|
|
editedOn int64
|
|
usn int
|
|
deleted bool
|
|
dirty bool
|
|
newBookUUID string
|
|
newBody string
|
|
newEditedOn int64
|
|
newUSN int
|
|
newDeleted bool
|
|
newDirty bool
|
|
}{
|
|
{
|
|
uuid: "n1-uuid",
|
|
bookUUID: "b1-uuid",
|
|
body: "n1-body",
|
|
addedOn: 1542058875,
|
|
editedOn: 0,
|
|
usn: 0,
|
|
deleted: false,
|
|
dirty: false,
|
|
newBookUUID: "b1-uuid",
|
|
newBody: "n1-body edited",
|
|
newEditedOn: 1542058879,
|
|
newUSN: 0,
|
|
newDeleted: false,
|
|
newDirty: false,
|
|
},
|
|
{
|
|
uuid: "n1-uuid",
|
|
bookUUID: "b1-uuid",
|
|
body: "n1-body",
|
|
addedOn: 1542058875,
|
|
editedOn: 0,
|
|
usn: 0,
|
|
deleted: false,
|
|
dirty: true,
|
|
newBookUUID: "b2-uuid",
|
|
newBody: "n1-body",
|
|
newEditedOn: 1542058879,
|
|
newUSN: 0,
|
|
newDeleted: false,
|
|
newDirty: false,
|
|
},
|
|
{
|
|
uuid: "n1-uuid",
|
|
bookUUID: "b1-uuid",
|
|
body: "n1-body",
|
|
addedOn: 1542058875,
|
|
editedOn: 0,
|
|
usn: 10,
|
|
deleted: false,
|
|
dirty: false,
|
|
newBookUUID: "",
|
|
newBody: "",
|
|
newEditedOn: 1542058879,
|
|
newUSN: 151,
|
|
newDeleted: true,
|
|
newDirty: false,
|
|
},
|
|
{
|
|
uuid: "n1-uuid",
|
|
bookUUID: "b1-uuid",
|
|
body: "n1-body",
|
|
addedOn: 1542058875,
|
|
editedOn: 0,
|
|
usn: 0,
|
|
deleted: false,
|
|
dirty: false,
|
|
newBookUUID: "",
|
|
newBody: "",
|
|
newEditedOn: 1542058879,
|
|
newUSN: 15,
|
|
newDeleted: true,
|
|
newDirty: false,
|
|
},
|
|
}
|
|
|
|
for idx, tc := range testCases {
|
|
func() {
|
|
// Setup
|
|
db := InitTestMemoryDB(t)
|
|
|
|
n1 := Note{
|
|
UUID: tc.uuid,
|
|
BookUUID: tc.bookUUID,
|
|
Body: tc.body,
|
|
AddedOn: tc.addedOn,
|
|
EditedOn: tc.editedOn,
|
|
USN: tc.usn,
|
|
Deleted: tc.deleted,
|
|
Dirty: tc.dirty,
|
|
}
|
|
n2 := Note{
|
|
UUID: "n2-uuid",
|
|
BookUUID: "b10-uuid",
|
|
Body: "n2 body",
|
|
AddedOn: 1542058875,
|
|
EditedOn: 0,
|
|
USN: 39,
|
|
Deleted: false,
|
|
Dirty: false,
|
|
}
|
|
|
|
MustExec(t, fmt.Sprintf("inserting n1 for test case %d", idx), db, "INSERT INTO notes (uuid, book_uuid, usn, added_on, edited_on, body, deleted, dirty) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", n1.UUID, n1.BookUUID, n1.USN, n1.AddedOn, n1.EditedOn, n1.Body, n1.Deleted, n1.Dirty)
|
|
MustExec(t, fmt.Sprintf("inserting n2 for test case %d", idx), db, "INSERT INTO notes (uuid, book_uuid, usn, added_on, edited_on, body, deleted, dirty) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", n2.UUID, n2.BookUUID, n2.USN, n2.AddedOn, n2.EditedOn, n2.Body, n2.Deleted, n2.Dirty)
|
|
|
|
// execute
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
t.Fatal(errors.Wrap(err, fmt.Sprintf("beginning a transaction for test case %d", idx)).Error())
|
|
}
|
|
|
|
n1.BookUUID = tc.newBookUUID
|
|
n1.Body = tc.newBody
|
|
n1.EditedOn = tc.newEditedOn
|
|
n1.USN = tc.newUSN
|
|
n1.Deleted = tc.newDeleted
|
|
n1.Dirty = tc.newDirty
|
|
|
|
if err := n1.Update(tx); err != nil {
|
|
tx.Rollback()
|
|
t.Fatal(errors.Wrap(err, fmt.Sprintf("executing for test case %d", idx)).Error())
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
// test
|
|
var n1Record, n2Record Note
|
|
MustScan(t, "getting n1",
|
|
db.QueryRow("SELECT uuid, book_uuid, body, added_on, edited_on, usn, deleted, dirty FROM notes WHERE uuid = ?", tc.uuid),
|
|
&n1Record.UUID, &n1Record.BookUUID, &n1Record.Body, &n1Record.AddedOn, &n1Record.EditedOn, &n1Record.USN, &n1Record.Deleted, &n1Record.Dirty)
|
|
MustScan(t, "getting n2",
|
|
db.QueryRow("SELECT uuid, book_uuid, body, added_on, edited_on, usn, deleted, dirty FROM notes WHERE uuid = ?", n2.UUID),
|
|
&n2Record.UUID, &n2Record.BookUUID, &n2Record.Body, &n2Record.AddedOn, &n2Record.EditedOn, &n2Record.USN, &n2Record.Deleted, &n2Record.Dirty)
|
|
|
|
assert.Equal(t, n1Record.UUID, n1.UUID, fmt.Sprintf("n1 uuid mismatch for test case %d", idx))
|
|
assert.Equal(t, n1Record.BookUUID, tc.newBookUUID, fmt.Sprintf("n1 bookUUID mismatch for test case %d", idx))
|
|
assert.Equal(t, n1Record.Body, tc.newBody, fmt.Sprintf("n1 body mismatch for test case %d", idx))
|
|
assert.Equal(t, n1Record.AddedOn, n1.AddedOn, fmt.Sprintf("n1 addedOn mismatch for test case %d", idx))
|
|
assert.Equal(t, n1Record.EditedOn, tc.newEditedOn, fmt.Sprintf("n1 editedOn mismatch for test case %d", idx))
|
|
assert.Equal(t, n1Record.USN, tc.newUSN, fmt.Sprintf("n1 usn mismatch for test case %d", idx))
|
|
assert.Equal(t, n1Record.Deleted, tc.newDeleted, fmt.Sprintf("n1 deleted mismatch for test case %d", idx))
|
|
assert.Equal(t, n1Record.Dirty, tc.newDirty, fmt.Sprintf("n1 dirty mismatch for test case %d", idx))
|
|
|
|
assert.Equal(t, n2Record.UUID, n2.UUID, fmt.Sprintf("n2 uuid mismatch for test case %d", idx))
|
|
assert.Equal(t, n2Record.BookUUID, n2.BookUUID, fmt.Sprintf("n2 bookUUID mismatch for test case %d", idx))
|
|
assert.Equal(t, n2Record.Body, n2.Body, fmt.Sprintf("n2 body mismatch for test case %d", idx))
|
|
assert.Equal(t, n2Record.AddedOn, n2.AddedOn, fmt.Sprintf("n2 addedOn mismatch for test case %d", idx))
|
|
assert.Equal(t, n2Record.EditedOn, n2.EditedOn, fmt.Sprintf("n2 editedOn mismatch for test case %d", idx))
|
|
assert.Equal(t, n2Record.USN, n2.USN, fmt.Sprintf("n2 usn mismatch for test case %d", idx))
|
|
assert.Equal(t, n2Record.Deleted, n2.Deleted, fmt.Sprintf("n2 deleted mismatch for test case %d", idx))
|
|
assert.Equal(t, n2Record.Dirty, n2.Dirty, fmt.Sprintf("n2 dirty mismatch for test case %d", idx))
|
|
}()
|
|
}
|
|
}
|
|
|
|
func TestNoteUpdateUUID(t *testing.T) {
|
|
testCases := []struct {
|
|
newUUID string
|
|
}{
|
|
{
|
|
newUUID: "n1-new-uuid",
|
|
},
|
|
{
|
|
newUUID: "n2-new-uuid",
|
|
},
|
|
}
|
|
|
|
for idx, tc := range testCases {
|
|
t.Run(fmt.Sprintf("testCase%d", idx), func(t *testing.T) {
|
|
// Setup
|
|
db := InitTestMemoryDB(t)
|
|
|
|
n1 := Note{
|
|
UUID: "n1-uuid",
|
|
BookUUID: "b1-uuid",
|
|
AddedOn: 1542058874,
|
|
Body: "n1-body",
|
|
USN: 1,
|
|
Deleted: true,
|
|
Dirty: false,
|
|
}
|
|
n2 := Note{
|
|
UUID: "n2-uuid",
|
|
BookUUID: "b1-uuid",
|
|
AddedOn: 1542058874,
|
|
Body: "n2-body",
|
|
USN: 1,
|
|
Deleted: true,
|
|
Dirty: false,
|
|
}
|
|
|
|
MustExec(t, "inserting n1", db, "INSERT INTO notes (uuid, book_uuid, body, added_on, usn, deleted, dirty) VALUES (?, ?, ?, ?, ?, ?, ?)", n1.UUID, n1.BookUUID, n1.Body, n1.AddedOn, n1.USN, n1.Deleted, n1.Dirty)
|
|
MustExec(t, "inserting n2", db, "INSERT INTO notes (uuid, book_uuid, body, added_on, usn, deleted, dirty) VALUES (?, ?, ?, ?, ?, ?, ?)", n2.UUID, n2.BookUUID, n2.Body, n2.AddedOn, n2.USN, n2.Deleted, n2.Dirty)
|
|
|
|
// execute
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
t.Fatal(errors.Wrap(err, "beginning a transaction").Error())
|
|
}
|
|
if err := n1.UpdateUUID(tx, tc.newUUID); err != nil {
|
|
tx.Rollback()
|
|
t.Fatal(errors.Wrap(err, "executing").Error())
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
// test
|
|
var n1Record, n2Record Note
|
|
MustScan(t, "getting n1",
|
|
db.QueryRow("SELECT uuid, body, usn, deleted, dirty FROM notes WHERE body = ?", "n1-body"),
|
|
&n1Record.UUID, &n1Record.Body, &n1Record.USN, &n1Record.Deleted, &n1Record.Dirty)
|
|
MustScan(t, "getting n2",
|
|
db.QueryRow("SELECT uuid, body, usn, deleted, dirty FROM notes WHERE body = ?", "n2-body"),
|
|
&n2Record.UUID, &n2Record.Body, &n2Record.USN, &n2Record.Deleted, &n2Record.Dirty)
|
|
|
|
assert.Equal(t, n1.UUID, tc.newUUID, "n1 original reference uuid mismatch")
|
|
assert.Equal(t, n1Record.UUID, tc.newUUID, "n1 uuid mismatch")
|
|
assert.Equal(t, n2Record.UUID, n2.UUID, "n2 uuid mismatch")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNoteExpunge(t *testing.T) {
|
|
// Setup
|
|
db := InitTestMemoryDB(t)
|
|
|
|
n1 := Note{
|
|
UUID: "n1-uuid",
|
|
BookUUID: "b9-uuid",
|
|
Body: "n1 body",
|
|
AddedOn: 1542058874,
|
|
EditedOn: 0,
|
|
USN: 22,
|
|
Deleted: false,
|
|
Dirty: false,
|
|
}
|
|
n2 := Note{
|
|
UUID: "n2-uuid",
|
|
BookUUID: "b10-uuid",
|
|
Body: "n2 body",
|
|
AddedOn: 1542058875,
|
|
EditedOn: 0,
|
|
USN: 39,
|
|
Deleted: false,
|
|
Dirty: false,
|
|
}
|
|
|
|
MustExec(t, "inserting n1", db, "INSERT INTO notes (uuid, book_uuid, usn, added_on, edited_on, body, deleted, dirty) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", n1.UUID, n1.BookUUID, n1.USN, n1.AddedOn, n1.EditedOn, n1.Body, n1.Deleted, n1.Dirty)
|
|
MustExec(t, "inserting n2", db, "INSERT INTO notes (uuid, book_uuid, usn, added_on, edited_on, body, deleted, dirty) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", n2.UUID, n2.BookUUID, n2.USN, n2.AddedOn, n2.EditedOn, n2.Body, n2.Deleted, n2.Dirty)
|
|
|
|
// execute
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
t.Fatal(errors.Wrap(err, "beginning a transaction").Error())
|
|
}
|
|
|
|
if err := n1.Expunge(tx); err != nil {
|
|
tx.Rollback()
|
|
t.Fatal(errors.Wrap(err, "executing").Error())
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
// test
|
|
var noteCount int
|
|
MustScan(t, "counting notes", db.QueryRow("SELECT count(*) FROM notes"), ¬eCount)
|
|
|
|
assert.Equalf(t, noteCount, 1, "note count mismatch")
|
|
|
|
var n2Record Note
|
|
MustScan(t, "getting n2",
|
|
db.QueryRow("SELECT uuid, book_uuid, body, added_on, edited_on, usn, deleted, dirty FROM notes WHERE uuid = ?", n2.UUID),
|
|
&n2Record.UUID, &n2Record.BookUUID, &n2Record.Body, &n2Record.AddedOn, &n2Record.EditedOn, &n2Record.USN, &n2Record.Deleted, &n2Record.Dirty)
|
|
|
|
assert.Equal(t, n2Record.UUID, n2.UUID, "n2 uuid mismatch")
|
|
assert.Equal(t, n2Record.BookUUID, n2.BookUUID, "n2 bookUUID mismatch")
|
|
assert.Equal(t, n2Record.Body, n2.Body, "n2 body mismatch")
|
|
assert.Equal(t, n2Record.AddedOn, n2.AddedOn, "n2 addedOn mismatch")
|
|
assert.Equal(t, n2Record.EditedOn, n2.EditedOn, "n2 editedOn mismatch")
|
|
assert.Equal(t, n2Record.USN, n2.USN, "n2 usn mismatch")
|
|
assert.Equal(t, n2Record.Deleted, n2.Deleted, "n2 deleted mismatch")
|
|
assert.Equal(t, n2Record.Dirty, n2.Dirty, "n2 dirty mismatch")
|
|
}
|
|
|
|
func TestNewBook(t *testing.T) {
|
|
testCases := []struct {
|
|
uuid string
|
|
label string
|
|
usn int
|
|
deleted bool
|
|
dirty bool
|
|
}{
|
|
{
|
|
uuid: "b1-uuid",
|
|
label: "b1-label",
|
|
usn: 0,
|
|
deleted: false,
|
|
dirty: false,
|
|
},
|
|
{
|
|
uuid: "b2-uuid",
|
|
label: "b2-label",
|
|
usn: 1008,
|
|
deleted: false,
|
|
dirty: true,
|
|
},
|
|
}
|
|
|
|
for idx, tc := range testCases {
|
|
got := NewBook(tc.uuid, tc.label, tc.usn, tc.deleted, tc.dirty)
|
|
|
|
assert.Equal(t, got.UUID, tc.uuid, fmt.Sprintf("UUID mismatch for test case %d", idx))
|
|
assert.Equal(t, got.Label, tc.label, fmt.Sprintf("Label mismatch for test case %d", idx))
|
|
assert.Equal(t, got.USN, tc.usn, fmt.Sprintf("USN mismatch for test case %d", idx))
|
|
assert.Equal(t, got.Deleted, tc.deleted, fmt.Sprintf("Deleted mismatch for test case %d", idx))
|
|
assert.Equal(t, got.Dirty, tc.dirty, fmt.Sprintf("Dirty mismatch for test case %d", idx))
|
|
}
|
|
}
|
|
|
|
func TestBookInsert(t *testing.T) {
|
|
testCases := []struct {
|
|
uuid string
|
|
label string
|
|
usn int
|
|
deleted bool
|
|
dirty bool
|
|
}{
|
|
{
|
|
uuid: "b1-uuid",
|
|
label: "b1-label",
|
|
usn: 10808,
|
|
deleted: false,
|
|
dirty: false,
|
|
},
|
|
{
|
|
uuid: "b1-uuid",
|
|
label: "b1-label",
|
|
usn: 10808,
|
|
deleted: false,
|
|
dirty: true,
|
|
},
|
|
}
|
|
|
|
for idx, tc := range testCases {
|
|
func() {
|
|
// Setup
|
|
db := InitTestMemoryDB(t)
|
|
|
|
b := Book{
|
|
UUID: tc.uuid,
|
|
Label: tc.label,
|
|
USN: tc.usn,
|
|
Dirty: tc.dirty,
|
|
Deleted: tc.deleted,
|
|
}
|
|
|
|
// execute
|
|
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
t.Fatal(errors.Wrap(err, fmt.Sprintf("beginning a transaction for test case %d", idx)).Error())
|
|
}
|
|
|
|
if err := b.Insert(tx); err != nil {
|
|
tx.Rollback()
|
|
t.Fatal(errors.Wrap(err, fmt.Sprintf("executing for test case %d", idx)).Error())
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
// test
|
|
var uuid, label string
|
|
var usn int
|
|
var deleted, dirty bool
|
|
MustScan(t, "getting b1",
|
|
db.QueryRow("SELECT uuid, label, usn, deleted, dirty FROM books WHERE uuid = ?", tc.uuid),
|
|
&uuid, &label, &usn, &deleted, &dirty)
|
|
|
|
assert.Equal(t, uuid, tc.uuid, fmt.Sprintf("uuid mismatch for test case %d", idx))
|
|
assert.Equal(t, label, tc.label, fmt.Sprintf("label mismatch for test case %d", idx))
|
|
assert.Equal(t, usn, tc.usn, fmt.Sprintf("usn mismatch for test case %d", idx))
|
|
assert.Equal(t, deleted, tc.deleted, fmt.Sprintf("deleted mismatch for test case %d", idx))
|
|
assert.Equal(t, dirty, tc.dirty, fmt.Sprintf("dirty mismatch for test case %d", idx))
|
|
}()
|
|
}
|
|
}
|
|
|
|
func TestBookUpdate(t *testing.T) {
|
|
testCases := []struct {
|
|
uuid string
|
|
label string
|
|
usn int
|
|
deleted bool
|
|
dirty bool
|
|
newLabel string
|
|
newUSN int
|
|
newDeleted bool
|
|
newDirty bool
|
|
}{
|
|
{
|
|
uuid: "b1-uuid",
|
|
label: "b1-label",
|
|
usn: 0,
|
|
deleted: false,
|
|
dirty: false,
|
|
newLabel: "b1-label-edited",
|
|
newUSN: 0,
|
|
newDeleted: false,
|
|
newDirty: true,
|
|
},
|
|
{
|
|
uuid: "b1-uuid",
|
|
label: "b1-label",
|
|
usn: 0,
|
|
deleted: false,
|
|
dirty: false,
|
|
newLabel: "",
|
|
newUSN: 10,
|
|
newDeleted: true,
|
|
newDirty: false,
|
|
},
|
|
}
|
|
|
|
for idx, tc := range testCases {
|
|
func() {
|
|
// Setup
|
|
db := InitTestMemoryDB(t)
|
|
|
|
b1 := Book{
|
|
UUID: "b1-uuid",
|
|
Label: "b1-label",
|
|
USN: 1,
|
|
Deleted: true,
|
|
Dirty: false,
|
|
}
|
|
b2 := Book{
|
|
UUID: "b2-uuid",
|
|
Label: "b2-label",
|
|
USN: 1,
|
|
Deleted: true,
|
|
Dirty: false,
|
|
}
|
|
|
|
MustExec(t, fmt.Sprintf("inserting b1 for test case %d", idx), db, "INSERT INTO books (uuid, label, usn, deleted, dirty) VALUES (?, ?, ?, ?, ?)", b1.UUID, b1.Label, b1.USN, b1.Deleted, b1.Dirty)
|
|
MustExec(t, fmt.Sprintf("inserting b2 for test case %d", idx), db, "INSERT INTO books (uuid, label, usn, deleted, dirty) VALUES (?, ?, ?, ?, ?)", b2.UUID, b2.Label, b2.USN, b2.Deleted, b2.Dirty)
|
|
|
|
// execute
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
t.Fatal(errors.Wrap(err, fmt.Sprintf("beginning a transaction for test case %d", idx)).Error())
|
|
}
|
|
|
|
b1.Label = tc.newLabel
|
|
b1.USN = tc.newUSN
|
|
b1.Deleted = tc.newDeleted
|
|
b1.Dirty = tc.newDirty
|
|
|
|
if err := b1.Update(tx); err != nil {
|
|
tx.Rollback()
|
|
t.Fatal(errors.Wrap(err, fmt.Sprintf("executing for test case %d", idx)).Error())
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
// test
|
|
var b1Record, b2Record Book
|
|
MustScan(t, "getting b1",
|
|
db.QueryRow("SELECT uuid, label, usn, deleted, dirty FROM books WHERE uuid = ?", tc.uuid),
|
|
&b1Record.UUID, &b1Record.Label, &b1Record.USN, &b1Record.Deleted, &b1Record.Dirty)
|
|
MustScan(t, "getting b2",
|
|
db.QueryRow("SELECT uuid, label, usn, deleted, dirty FROM books WHERE uuid = ?", b2.UUID),
|
|
&b2Record.UUID, &b2Record.Label, &b2Record.USN, &b2Record.Deleted, &b2Record.Dirty)
|
|
|
|
assert.Equal(t, b1Record.UUID, b1.UUID, fmt.Sprintf("b1 uuid mismatch for test case %d", idx))
|
|
assert.Equal(t, b1Record.Label, tc.newLabel, fmt.Sprintf("b1 label mismatch for test case %d", idx))
|
|
assert.Equal(t, b1Record.USN, tc.newUSN, fmt.Sprintf("b1 usn mismatch for test case %d", idx))
|
|
assert.Equal(t, b1Record.Deleted, tc.newDeleted, fmt.Sprintf("b1 deleted mismatch for test case %d", idx))
|
|
assert.Equal(t, b1Record.Dirty, tc.newDirty, fmt.Sprintf("b1 dirty mismatch for test case %d", idx))
|
|
|
|
assert.Equal(t, b2Record.UUID, b2.UUID, fmt.Sprintf("b2 uuid mismatch for test case %d", idx))
|
|
assert.Equal(t, b2Record.Label, b2.Label, fmt.Sprintf("b2 label mismatch for test case %d", idx))
|
|
assert.Equal(t, b2Record.USN, b2.USN, fmt.Sprintf("b2 usn mismatch for test case %d", idx))
|
|
assert.Equal(t, b2Record.Deleted, b2.Deleted, fmt.Sprintf("b2 deleted mismatch for test case %d", idx))
|
|
assert.Equal(t, b2Record.Dirty, b2.Dirty, fmt.Sprintf("b2 dirty mismatch for test case %d", idx))
|
|
}()
|
|
}
|
|
}
|
|
|
|
func TestBookUpdateUUID(t *testing.T) {
|
|
testCases := []struct {
|
|
newUUID string
|
|
}{
|
|
{
|
|
newUUID: "b1-new-uuid",
|
|
},
|
|
{
|
|
newUUID: "b2-new-uuid",
|
|
},
|
|
}
|
|
|
|
for idx, tc := range testCases {
|
|
t.Run(fmt.Sprintf("testCase%d", idx), func(t *testing.T) {
|
|
|
|
// Setup
|
|
db := InitTestMemoryDB(t)
|
|
|
|
b1 := Book{
|
|
UUID: "b1-uuid",
|
|
Label: "b1-label",
|
|
USN: 1,
|
|
Deleted: true,
|
|
Dirty: false,
|
|
}
|
|
b2 := Book{
|
|
UUID: "b2-uuid",
|
|
Label: "b2-label",
|
|
USN: 1,
|
|
Deleted: true,
|
|
Dirty: false,
|
|
}
|
|
|
|
MustExec(t, "inserting b1", db, "INSERT INTO books (uuid, label, usn, deleted, dirty) VALUES (?, ?, ?, ?, ?)", b1.UUID, b1.Label, b1.USN, b1.Deleted, b1.Dirty)
|
|
MustExec(t, "inserting b2", db, "INSERT INTO books (uuid, label, usn, deleted, dirty) VALUES (?, ?, ?, ?, ?)", b2.UUID, b2.Label, b2.USN, b2.Deleted, b2.Dirty)
|
|
|
|
// execute
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
t.Fatal(errors.Wrap(err, "beginning a transaction").Error())
|
|
}
|
|
if err := b1.UpdateUUID(tx, tc.newUUID); err != nil {
|
|
tx.Rollback()
|
|
t.Fatal(errors.Wrap(err, "executing").Error())
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
// test
|
|
var b1Record, b2Record Book
|
|
MustScan(t, "getting b1",
|
|
db.QueryRow("SELECT uuid, label, usn, deleted, dirty FROM books WHERE label = ?", "b1-label"),
|
|
&b1Record.UUID, &b1Record.Label, &b1Record.USN, &b1Record.Deleted, &b1Record.Dirty)
|
|
MustScan(t, "getting b2",
|
|
db.QueryRow("SELECT uuid, label, usn, deleted, dirty FROM books WHERE label = ?", "b2-label"),
|
|
&b2Record.UUID, &b2Record.Label, &b2Record.USN, &b2Record.Deleted, &b2Record.Dirty)
|
|
|
|
assert.Equal(t, b1.UUID, tc.newUUID, "b1 original reference uuid mismatch")
|
|
assert.Equal(t, b1Record.UUID, tc.newUUID, "b1 uuid mismatch")
|
|
assert.Equal(t, b2Record.UUID, b2.UUID, "b2 uuid mismatch")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBookExpunge(t *testing.T) {
|
|
// Setup
|
|
db := InitTestMemoryDB(t)
|
|
|
|
b1 := Book{
|
|
UUID: "b1-uuid",
|
|
Label: "b1-label",
|
|
USN: 1,
|
|
Deleted: true,
|
|
Dirty: false,
|
|
}
|
|
b2 := Book{
|
|
UUID: "b2-uuid",
|
|
Label: "b2-label",
|
|
USN: 1,
|
|
Deleted: true,
|
|
Dirty: false,
|
|
}
|
|
|
|
MustExec(t, "inserting b1", db, "INSERT INTO books (uuid, label, usn, deleted, dirty) VALUES (?, ?, ?, ?, ?)", b1.UUID, b1.Label, b1.USN, b1.Deleted, b1.Dirty)
|
|
MustExec(t, "inserting b2", db, "INSERT INTO books (uuid, label, usn, deleted, dirty) VALUES (?, ?, ?, ?, ?)", b2.UUID, b2.Label, b2.USN, b2.Deleted, b2.Dirty)
|
|
|
|
// execute
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
t.Fatal(errors.Wrap(err, "beginning a transaction").Error())
|
|
}
|
|
|
|
if err := b1.Expunge(tx); err != nil {
|
|
tx.Rollback()
|
|
t.Fatal(errors.Wrap(err, "executing").Error())
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
// test
|
|
var bookCount int
|
|
MustScan(t, "counting books", db.QueryRow("SELECT count(*) FROM books"), &bookCount)
|
|
|
|
assert.Equalf(t, bookCount, 1, "book count mismatch")
|
|
|
|
var b2Record Book
|
|
MustScan(t, "getting b2",
|
|
db.QueryRow("SELECT uuid, label, usn, deleted, dirty FROM books WHERE uuid = ?", "b2-uuid"),
|
|
&b2Record.UUID, &b2Record.Label, &b2Record.USN, &b2Record.Deleted, &b2Record.Dirty)
|
|
|
|
assert.Equal(t, b2Record.UUID, b2.UUID, "b2 uuid mismatch")
|
|
assert.Equal(t, b2Record.Label, b2.Label, "b2 label mismatch")
|
|
assert.Equal(t, b2Record.USN, b2.USN, "b2 usn mismatch")
|
|
assert.Equal(t, b2Record.Deleted, b2.Deleted, "b2 deleted mismatch")
|
|
assert.Equal(t, b2Record.Dirty, b2.Dirty, "b2 dirty mismatch")
|
|
}
|
|
|
|
// TestNoteFTS tests that note full text search indices stay in sync with the notes after insert, update and delete
|
|
func TestNoteFTS(t *testing.T) {
|
|
// set up
|
|
db := InitTestMemoryDB(t)
|
|
|
|
// execute - insert
|
|
n := Note{
|
|
UUID: "n1-uuid",
|
|
BookUUID: "b1-uuid",
|
|
Body: "foo bar",
|
|
AddedOn: 1542058875,
|
|
EditedOn: 0,
|
|
USN: 0,
|
|
Deleted: false,
|
|
Dirty: false,
|
|
}
|
|
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
t.Fatal(errors.Wrap(err, "beginning a transaction").Error())
|
|
}
|
|
|
|
if err := n.Insert(tx); err != nil {
|
|
tx.Rollback()
|
|
t.Fatal(errors.Wrap(err, "inserting").Error())
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
// test
|
|
var noteCount, noteFtsCount, noteSearchCount int
|
|
MustScan(t, "counting notes", db.QueryRow("SELECT count(*) FROM notes"), ¬eCount)
|
|
MustScan(t, "counting note_fts", db.QueryRow("SELECT count(*) FROM note_fts"), ¬eFtsCount)
|
|
MustScan(t, "counting search results", db.QueryRow("SELECT count(*) FROM note_fts WHERE note_fts MATCH ?", "foo"), ¬eSearchCount)
|
|
|
|
assert.Equal(t, noteCount, 1, "noteCount mismatch")
|
|
assert.Equal(t, noteFtsCount, 1, "noteFtsCount mismatch")
|
|
assert.Equal(t, noteSearchCount, 1, "noteSearchCount mismatch")
|
|
|
|
// execute - update
|
|
tx, err = db.Begin()
|
|
if err != nil {
|
|
t.Fatal(errors.Wrap(err, "beginning a transaction").Error())
|
|
}
|
|
|
|
n.Body = "baz quz"
|
|
if err := n.Update(tx); err != nil {
|
|
tx.Rollback()
|
|
t.Fatal(errors.Wrap(err, "updating").Error())
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
// test
|
|
MustScan(t, "counting notes", db.QueryRow("SELECT count(*) FROM notes"), ¬eCount)
|
|
MustScan(t, "counting note_fts", db.QueryRow("SELECT count(*) FROM note_fts"), ¬eFtsCount)
|
|
assert.Equal(t, noteCount, 1, "noteCount mismatch")
|
|
assert.Equal(t, noteFtsCount, 1, "noteFtsCount mismatch")
|
|
|
|
MustScan(t, "counting search results", db.QueryRow("SELECT count(*) FROM note_fts WHERE note_fts MATCH ?", "foo"), ¬eSearchCount)
|
|
assert.Equal(t, noteSearchCount, 0, "noteSearchCount for foo mismatch")
|
|
MustScan(t, "counting search results", db.QueryRow("SELECT count(*) FROM note_fts WHERE note_fts MATCH ?", "baz"), ¬eSearchCount)
|
|
assert.Equal(t, noteSearchCount, 1, "noteSearchCount for baz mismatch")
|
|
|
|
// execute - delete
|
|
tx, err = db.Begin()
|
|
if err != nil {
|
|
t.Fatal(errors.Wrap(err, "beginning a transaction").Error())
|
|
}
|
|
|
|
if err := n.Expunge(tx); err != nil {
|
|
tx.Rollback()
|
|
t.Fatal(errors.Wrap(err, "expunging").Error())
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
// test
|
|
MustScan(t, "counting notes", db.QueryRow("SELECT count(*) FROM notes"), ¬eCount)
|
|
MustScan(t, "counting note_fts", db.QueryRow("SELECT count(*) FROM note_fts"), ¬eFtsCount)
|
|
|
|
assert.Equal(t, noteCount, 0, "noteCount mismatch")
|
|
assert.Equal(t, noteFtsCount, 0, "noteFtsCount mismatch")
|
|
}
|