dnote/pkg/cli/migrate/legacy_test.go
2025-10-25 19:03:07 -07:00

659 lines
26 KiB
Go

/* Copyright (C) 2019, 2020, 2021, 2022, 2023, 2024, 2025 Dnote contributors
*
* 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 migrate
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"testing"
"github.com/dnote/dnote/pkg/assert"
"github.com/dnote/dnote/pkg/cli/context"
"github.com/dnote/dnote/pkg/cli/database"
"github.com/dnote/dnote/pkg/cli/testutils"
"github.com/dnote/dnote/pkg/cli/utils"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
)
func setupEnv(t *testing.T, homeDir string) context.DnoteCtx {
dnoteDir := fmt.Sprintf("%s/.dnote", homeDir)
if err := os.MkdirAll(dnoteDir, 0755); err != nil {
t.Fatal(errors.Wrap(err, "preparing dnote dir"))
}
return context.DnoteCtx{
Paths: context.Paths{
Home: homeDir,
LegacyDnote: dnoteDir,
},
}
}
func teardownEnv(t *testing.T, ctx context.DnoteCtx) {
if err := os.RemoveAll(ctx.Paths.LegacyDnote); err != nil {
t.Fatal(errors.Wrap(err, "tearing down the dnote dir"))
}
}
func TestMigrateToV1(t *testing.T) {
t.Run("yaml exists", func(t *testing.T) {
// set up
ctx := setupEnv(t, "../tmp")
defer teardownEnv(t, ctx)
yamlPath, err := filepath.Abs(filepath.Join(ctx.Paths.Home, ".dnote-yaml-archived"))
if err != nil {
panic(errors.Wrap(err, "Failed to get absolute YAML path").Error())
}
os.WriteFile(yamlPath, []byte{}, 0644)
// execute
if err := migrateToV1(ctx); err != nil {
t.Fatal(errors.Wrapf(err, "Failed to migrate").Error())
}
// test
ok, err := utils.FileExists(yamlPath)
if err != nil {
t.Fatal(errors.Wrap(err, "checking if yaml file exists"))
}
if ok {
t.Fatal("YAML archive file has not been deleted")
}
})
t.Run("yaml does not exist", func(t *testing.T) {
// set up
ctx := setupEnv(t, "../tmp")
defer teardownEnv(t, ctx)
yamlPath, err := filepath.Abs(filepath.Join(ctx.Paths.Home, ".dnote-yaml-archived"))
if err != nil {
panic(errors.Wrap(err, "Failed to get absolute YAML path").Error())
}
// execute
if err := migrateToV1(ctx); err != nil {
t.Fatal(errors.Wrapf(err, "Failed to migrate").Error())
}
// test
ok, err := utils.FileExists(yamlPath)
if err != nil {
t.Fatal(errors.Wrap(err, "checking if yaml file exists"))
}
if ok {
t.Fatal("YAML archive file must not exist")
}
})
}
func TestMigrateToV2(t *testing.T) {
ctx := setupEnv(t, "../tmp")
defer teardownEnv(t, ctx)
testutils.CopyFixture(t, ctx, "./fixtures/legacy-2-pre-dnote.json", "dnote")
// execute
if err := migrateToV2(ctx); err != nil {
t.Fatal(errors.Wrap(err, "Failed to migrate").Error())
}
// test
b := testutils.ReadFile(ctx, "dnote")
var postDnote migrateToV2PostDnote
if err := json.Unmarshal(b, &postDnote); err != nil {
t.Fatal(errors.Wrap(err, "Failed to unmarshal the result into Dnote").Error())
}
for _, book := range postDnote {
assert.NotEqual(t, book.Name, "", "Book name was not populated")
for _, note := range book.Notes {
if len(note.UUID) == 8 {
t.Errorf("Note UUID was not migrated. It has length of %d", len(note.UUID))
}
assert.NotEqual(t, note.AddedOn, int64(0), "AddedOn was not carried over")
assert.Equal(t, note.EditedOn, int64(0), "EditedOn was not created properly")
}
}
}
func TestMigrateToV3(t *testing.T) {
// set up
ctx := setupEnv(t, "../tmp")
defer teardownEnv(t, ctx)
testutils.CopyFixture(t, ctx, "./fixtures/legacy-3-pre-dnote.json", "dnote")
// execute
if err := migrateToV3(ctx); err != nil {
t.Fatal(errors.Wrap(err, "Failed to migrate").Error())
}
// test
b := testutils.ReadFile(ctx, "dnote")
var postDnote migrateToV3Dnote
if err := json.Unmarshal(b, &postDnote); err != nil {
t.Fatal(errors.Wrap(err, "Failed to unmarshal the result into Dnote").Error())
}
b = testutils.ReadFile(ctx, "actions")
var actions []migrateToV3Action
if err := json.Unmarshal(b, &actions); err != nil {
t.Fatal(errors.Wrap(err, "Failed to unmarshal the actions").Error())
}
assert.Equal(t, len(actions), 6, "actions length mismatch")
for _, book := range postDnote {
for _, note := range book.Notes {
assert.NotEqual(t, note.AddedOn, int64(0), "AddedOn was not carried over")
}
}
}
func TestMigrateToV4(t *testing.T) {
// set up
ctx := setupEnv(t, "../tmp")
defer teardownEnv(t, ctx)
defer os.Setenv("EDITOR", "")
testutils.CopyFixture(t, ctx, "./fixtures/legacy-4-pre-dnoterc.yaml", "dnoterc")
// execute
os.Setenv("EDITOR", "vim")
if err := migrateToV4(ctx); err != nil {
t.Fatal(errors.Wrap(err, "Failed to migrate").Error())
}
// test
b := testutils.ReadFile(ctx, "dnoterc")
var config migrateToV4PostConfig
if err := yaml.Unmarshal(b, &config); err != nil {
t.Fatal(errors.Wrap(err, "Failed to unmarshal the result into Dnote").Error())
}
assert.Equal(t, config.APIKey, "Oev6e1082ORasdf9rjkfjkasdfjhgei", "api key mismatch")
assert.Equal(t, config.Editor, "vim", "editor mismatch")
}
func TestMigrateToV5(t *testing.T) {
// set up
ctx := setupEnv(t, "../tmp")
defer teardownEnv(t, ctx)
testutils.CopyFixture(t, ctx, "./fixtures/legacy-5-pre-actions.json", "actions")
// execute
if err := migrateToV5(ctx); err != nil {
t.Fatal(errors.Wrap(err, "migrating").Error())
}
// test
var oldActions []migrateToV5PreAction
testutils.ReadJSON("./fixtures/legacy-5-pre-actions.json", &oldActions)
b := testutils.ReadFile(ctx, "actions")
var migratedActions []migrateToV5PostAction
if err := json.Unmarshal(b, &migratedActions); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling migrated actions").Error())
}
if len(oldActions) != len(migratedActions) {
t.Fatalf("There were %d actions but after migration there were %d", len(oldActions), len(migratedActions))
}
for idx := range migratedActions {
migrated := migratedActions[idx]
old := oldActions[idx]
assert.NotEqual(t, migrated.UUID, "", fmt.Sprintf("uuid mismatch for migrated item with index %d", idx))
assert.Equal(t, migrated.Schema, 1, fmt.Sprintf("schema mismatch for migrated item with index %d", idx))
assert.Equal(t, migrated.Timestamp, old.Timestamp, fmt.Sprintf("timestamp mismatch for migrated item with index %d", idx))
assert.Equal(t, migrated.Type, old.Type, fmt.Sprintf("timestamp mismatch for migrated item with index %d", idx))
switch migrated.Type {
case migrateToV5ActionAddNote:
var oldData, migratedData migrateToV5AddNoteData
if err := json.Unmarshal(old.Data, &oldData); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling old data").Error())
}
if err := json.Unmarshal(migrated.Data, &migratedData); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling new data").Error())
}
assert.Equal(t, oldData.BookName, migratedData.BookName, fmt.Sprintf("data book_name mismatch for item idx %d", idx))
assert.Equal(t, oldData.Content, migratedData.Content, fmt.Sprintf("data content mismatch for item idx %d", idx))
assert.Equal(t, oldData.NoteUUID, migratedData.NoteUUID, fmt.Sprintf("data note_uuid mismatch for item idx %d", idx))
case migrateToV5ActionRemoveNote:
var oldData, migratedData migrateToV5RemoveNoteData
if err := json.Unmarshal(old.Data, &oldData); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling old data").Error())
}
if err := json.Unmarshal(migrated.Data, &migratedData); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling new data").Error())
}
assert.Equal(t, oldData.BookName, migratedData.BookName, fmt.Sprintf("data book_name mismatch for item idx %d", idx))
assert.Equal(t, oldData.NoteUUID, migratedData.NoteUUID, fmt.Sprintf("data note_uuid mismatch for item idx %d", idx))
case migrateToV5ActionAddBook:
var oldData, migratedData migrateToV5AddBookData
if err := json.Unmarshal(old.Data, &oldData); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling old data").Error())
}
if err := json.Unmarshal(migrated.Data, &migratedData); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling new data").Error())
}
assert.Equal(t, oldData.BookName, migratedData.BookName, fmt.Sprintf("data book_name mismatch for item idx %d", idx))
case migrateToV5ActionRemoveBook:
var oldData, migratedData migrateToV5RemoveBookData
if err := json.Unmarshal(old.Data, &oldData); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling old data").Error())
}
if err := json.Unmarshal(migrated.Data, &migratedData); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling new data").Error())
}
assert.Equal(t, oldData.BookName, migratedData.BookName, fmt.Sprintf("data book_name mismatch for item idx %d", idx))
case migrateToV5ActionEditNote:
var oldData migrateToV5PreEditNoteData
var migratedData migrateToV5PostEditNoteData
if err := json.Unmarshal(old.Data, &oldData); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling old data").Error())
}
if err := json.Unmarshal(migrated.Data, &migratedData); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling new data").Error())
}
assert.Equal(t, oldData.NoteUUID, migratedData.NoteUUID, fmt.Sprintf("data note_uuid mismatch for item idx %d", idx))
assert.Equal(t, oldData.Content, migratedData.Content, fmt.Sprintf("data content mismatch for item idx %d", idx))
assert.Equal(t, oldData.BookName, migratedData.FromBook, "book_name should have been renamed to from_book")
assert.Equal(t, migratedData.ToBook, "", "to_book should be empty")
}
}
}
func TestMigrateToV6(t *testing.T) {
// set up
ctx := setupEnv(t, "../tmp")
defer teardownEnv(t, ctx)
testutils.CopyFixture(t, ctx, "./fixtures/legacy-6-pre-dnote.json", "dnote")
// execute
if err := migrateToV6(ctx); err != nil {
t.Fatal(errors.Wrap(err, "Failed to migrate").Error())
}
// test
b := testutils.ReadFile(ctx, "dnote")
var got migrateToV6PostDnote
if err := json.Unmarshal(b, &got); err != nil {
t.Fatal(errors.Wrap(err, "Failed to unmarshal the result into Dnote").Error())
}
b = utils.ReadFileAbs("./fixtures/legacy-6-post-dnote.json")
var expected migrateToV6PostDnote
if err := json.Unmarshal(b, &expected); err != nil {
t.Fatal(errors.Wrap(err, "Failed to unmarshal the result into Dnote").Error())
}
assert.DeepEqual(t, expected, got, "payload mismatch")
}
func TestMigrateToV7(t *testing.T) {
// set up
ctx := setupEnv(t, "../tmp")
defer teardownEnv(t, ctx)
testutils.CopyFixture(t, ctx, "./fixtures/legacy-7-pre-actions.json", "actions")
// execute
if err := migrateToV7(ctx); err != nil {
t.Fatal(errors.Wrap(err, "migrating").Error())
}
// test
b := testutils.ReadFile(ctx, "actions")
var got []migrateToV7Action
if err := json.Unmarshal(b, &got); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling the result").Error())
}
b2 := utils.ReadFileAbs("./fixtures/legacy-7-post-actions.json")
var expected []migrateToV7Action
if err := json.Unmarshal(b, &expected); err != nil {
t.Fatal(errors.Wrap(err, "unmarshalling the result into Dnote").Error())
}
assert.EqualJSON(t, string(b), string(b2), "Result does not match")
}
func TestMigrateToV8(t *testing.T) {
tmpDir := t.TempDir()
dnoteDir := tmpDir + "/.dnote"
if err := os.MkdirAll(dnoteDir, 0755); err != nil {
t.Fatal(errors.Wrap(err, "creating legacy dnote directory"))
}
db := database.InitTestMemoryDBRaw(t, "./fixtures/local-1-pre-schema.sql")
ctx := context.DnoteCtx{
Paths: context.Paths{
Home: tmpDir,
LegacyDnote: dnoteDir,
},
DB: db,
}
// set up
testutils.CopyFixture(t, ctx, "./fixtures/legacy-8-actions.json", "actions")
testutils.CopyFixture(t, ctx, "./fixtures/legacy-8-dnote.json", "dnote")
testutils.CopyFixture(t, ctx, "./fixtures/legacy-8-dnoterc.yaml", "dnoterc")
testutils.CopyFixture(t, ctx, "./fixtures/legacy-8-schema.yaml", "schema")
testutils.CopyFixture(t, ctx, "./fixtures/legacy-8-timestamps.yaml", "timestamps")
// execute
if err := migrateToV8(ctx); err != nil {
t.Fatal(errors.Wrap(err, "migrating").Error())
}
// test
// 1. test if files are migrated
dnoteFilePath := fmt.Sprintf("%s/dnote", ctx.Paths.LegacyDnote)
dnotercPath := fmt.Sprintf("%s/dnoterc", ctx.Paths.LegacyDnote)
schemaFilePath := fmt.Sprintf("%s/schema", ctx.Paths.LegacyDnote)
timestampFilePath := fmt.Sprintf("%s/timestamps", ctx.Paths.LegacyDnote)
ok, err := utils.FileExists(dnoteFilePath)
if err != nil {
t.Fatal(errors.Wrap(err, "checking if file exists"))
}
if ok {
t.Errorf("%s still exists", dnoteFilePath)
}
ok, err = utils.FileExists(schemaFilePath)
if err != nil {
t.Fatal(errors.Wrap(err, "checking if file exists"))
}
if ok {
t.Errorf("%s still exists", schemaFilePath)
}
ok, err = utils.FileExists(timestampFilePath)
if err != nil {
t.Fatal(errors.Wrap(err, "checking if file exists"))
}
if ok {
t.Errorf("%s still exists", timestampFilePath)
}
ok, err = utils.FileExists(dnotercPath)
if err != nil {
t.Fatal(errors.Wrap(err, "checking if file exists"))
}
if !ok {
t.Errorf("%s still exists", dnotercPath)
}
// 2. test if notes and books are migrated
var bookCount, noteCount int
err = db.QueryRow("SELECT count(*) FROM books").Scan(&bookCount)
if err != nil {
panic(errors.Wrap(err, "counting books"))
}
err = db.QueryRow("SELECT count(*) FROM notes").Scan(&noteCount)
if err != nil {
panic(errors.Wrap(err, "counting notes"))
}
assert.Equal(t, bookCount, 2, "book count mismatch")
assert.Equal(t, noteCount, 3, "note count mismatch")
type bookInfo struct {
label string
uuid string
}
type noteInfo struct {
id int
uuid string
bookUUID string
content string
addedOn int64
editedOn int64
public bool
}
var b1, b2 bookInfo
var n1, n2, n3 noteInfo
err = db.QueryRow("SELECT label, uuid FROM books WHERE label = ?", "js").Scan(&b1.label, &b1.uuid)
if err != nil {
panic(errors.Wrap(err, "finding book 1"))
}
err = db.QueryRow("SELECT label, uuid FROM books WHERE label = ?", "css").Scan(&b2.label, &b2.uuid)
if err != nil {
panic(errors.Wrap(err, "finding book 2"))
}
err = db.QueryRow("SELECT id, uuid, book_uuid, content, added_on, edited_on, public FROM notes WHERE uuid = ?", "d69edb54-5b31-4cdd-a4a5-34f0a0bfa153").Scan(&n1.id, &n1.uuid, &n1.bookUUID, &n1.content, &n1.addedOn, &n1.editedOn, &n1.public)
if err != nil {
panic(errors.Wrap(err, "finding note 1"))
}
err = db.QueryRow("SELECT id, uuid, book_uuid, content, added_on, edited_on, public FROM notes WHERE uuid = ?", "35cbcab1-6a2a-4cc8-97e0-e73bbbd54626").Scan(&n2.id, &n2.uuid, &n2.bookUUID, &n2.content, &n2.addedOn, &n2.editedOn, &n2.public)
if err != nil {
panic(errors.Wrap(err, "finding note 2"))
}
err = db.QueryRow("SELECT id, uuid, book_uuid, content, added_on, edited_on, public FROM notes WHERE uuid = ?", "7c1fcfb2-de8b-4350-88f0-fb3cbaf6630a").Scan(&n3.id, &n3.uuid, &n3.bookUUID, &n3.content, &n3.addedOn, &n3.editedOn, &n3.public)
if err != nil {
panic(errors.Wrap(err, "finding note 3"))
}
assert.NotEqual(t, b1.uuid, "", "book 1 uuid should have been generated")
assert.Equal(t, b1.label, "js", "book 1 label mismatch")
assert.NotEqual(t, b2.uuid, "", "book 2 uuid should have been generated")
assert.Equal(t, b2.label, "css", "book 2 label mismatch")
assert.Equal(t, n1.uuid, "d69edb54-5b31-4cdd-a4a5-34f0a0bfa153", "note 1 uuid mismatch")
assert.NotEqual(t, n1.id, 0, "note 1 id should have been generated")
assert.Equal(t, n1.bookUUID, b2.uuid, "note 1 book_uuid mismatch")
assert.Equal(t, n1.content, "css test 1", "note 1 content mismatch")
assert.Equal(t, n1.addedOn, int64(1536977237), "note 1 added_on mismatch")
assert.Equal(t, n1.editedOn, int64(1536977253), "note 1 edited_on mismatch")
assert.Equal(t, n1.public, false, "note 1 public mismatch")
assert.Equal(t, n2.uuid, "35cbcab1-6a2a-4cc8-97e0-e73bbbd54626", "note 2 uuid mismatch")
assert.NotEqual(t, n2.id, 0, "note 2 id should have been generated")
assert.Equal(t, n2.bookUUID, b1.uuid, "note 2 book_uuid mismatch")
assert.Equal(t, n2.content, "js test 1", "note 2 content mismatch")
assert.Equal(t, n2.addedOn, int64(1536977229), "note 2 added_on mismatch")
assert.Equal(t, n2.editedOn, int64(0), "note 2 edited_on mismatch")
assert.Equal(t, n2.public, false, "note 2 public mismatch")
assert.Equal(t, n3.uuid, "7c1fcfb2-de8b-4350-88f0-fb3cbaf6630a", "note 3 uuid mismatch")
assert.NotEqual(t, n3.id, 0, "note 3 id should have been generated")
assert.Equal(t, n3.bookUUID, b1.uuid, "note 3 book_uuid mismatch")
assert.Equal(t, n3.content, "js test 2", "note 3 content mismatch")
assert.Equal(t, n3.addedOn, int64(1536977230), "note 3 added_on mismatch")
assert.Equal(t, n3.editedOn, int64(0), "note 3 edited_on mismatch")
assert.Equal(t, n3.public, false, "note 3 public mismatch")
// 3. test if actions are migrated
var actionCount int
err = db.QueryRow("SELECT count(*) FROM actions").Scan(&actionCount)
if err != nil {
panic(errors.Wrap(err, "counting actions"))
}
assert.Equal(t, actionCount, 11, "action count mismatch")
type actionInfo struct {
uuid string
schema int
actionType string
data string
timestamp int
}
var a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 actionInfo
err = db.QueryRow("SELECT uuid, schema, type, data, timestamp FROM actions WHERE uuid = ?", "6145c1b7-f286-4d9f-b0f6-00d274baefc6").Scan(&a1.uuid, &a1.schema, &a1.actionType, &a1.data, &a1.timestamp)
if err != nil {
panic(errors.Wrap(err, "finding a1"))
}
err = db.QueryRow("SELECT uuid, schema, type, data, timestamp FROM actions WHERE uuid = ?", "c048a56b-179c-4f31-9995-81e9b32b7dd6").Scan(&a2.uuid, &a2.schema, &a2.actionType, &a2.data, &a2.timestamp)
if err != nil {
panic(errors.Wrap(err, "finding a2"))
}
err = db.QueryRow("SELECT uuid, schema, type, data, timestamp FROM actions WHERE uuid = ?", "f557ef48-c304-47dc-adfb-46b7306e701f").Scan(&a3.uuid, &a3.schema, &a3.actionType, &a3.data, &a3.timestamp)
if err != nil {
panic(errors.Wrap(err, "finding a3"))
}
err = db.QueryRow("SELECT uuid, schema, type, data, timestamp FROM actions WHERE uuid = ?", "8d79db34-343d-4331-ae5b-24743f17ca7f").Scan(&a4.uuid, &a4.schema, &a4.actionType, &a4.data, &a4.timestamp)
if err != nil {
panic(errors.Wrap(err, "finding a4"))
}
err = db.QueryRow("SELECT uuid, schema, type, data, timestamp FROM actions WHERE uuid = ?", "b9c1ed4a-e6b3-41f2-983b-593ec7b8b7a1").Scan(&a5.uuid, &a5.schema, &a5.actionType, &a5.data, &a5.timestamp)
if err != nil {
panic(errors.Wrap(err, "finding a5"))
}
err = db.QueryRow("SELECT uuid, schema, type, data, timestamp FROM actions WHERE uuid = ?", "06ed7ef0-f171-4bd7-ae8e-97b5d06a4c49").Scan(&a6.uuid, &a6.schema, &a6.actionType, &a6.data, &a6.timestamp)
if err != nil {
panic(errors.Wrap(err, "finding a6"))
}
err = db.QueryRow("SELECT uuid, schema, type, data, timestamp FROM actions WHERE uuid = ?", "7f173cef-1688-4177-a373-145fcd822b2f").Scan(&a7.uuid, &a7.schema, &a7.actionType, &a7.data, &a7.timestamp)
if err != nil {
panic(errors.Wrap(err, "finding a7"))
}
err = db.QueryRow("SELECT uuid, schema, type, data, timestamp FROM actions WHERE uuid = ?", "64352e08-aa7a-45f4-b760-b3f38b5e11fa").Scan(&a8.uuid, &a8.schema, &a8.actionType, &a8.data, &a8.timestamp)
if err != nil {
panic(errors.Wrap(err, "finding a8"))
}
err = db.QueryRow("SELECT uuid, schema, type, data, timestamp FROM actions WHERE uuid = ?", "82e20a12-bda8-45f7-ac42-b453b6daa5ec").Scan(&a9.uuid, &a9.schema, &a9.actionType, &a9.data, &a9.timestamp)
if err != nil {
panic(errors.Wrap(err, "finding a9"))
}
err = db.QueryRow("SELECT uuid, schema, type, data, timestamp FROM actions WHERE uuid = ?", "a29055f4-ace4-44fd-8800-3396edbccaef").Scan(&a10.uuid, &a10.schema, &a10.actionType, &a10.data, &a10.timestamp)
if err != nil {
panic(errors.Wrap(err, "finding a10"))
}
err = db.QueryRow("SELECT uuid, schema, type, data, timestamp FROM actions WHERE uuid = ?", "871a5562-1bd0-43c1-b550-5bbb727ac7c4").Scan(&a11.uuid, &a11.schema, &a11.actionType, &a11.data, &a11.timestamp)
if err != nil {
panic(errors.Wrap(err, "finding a11"))
}
assert.Equal(t, a1.uuid, "6145c1b7-f286-4d9f-b0f6-00d274baefc6", "action 1 uuid mismatch")
assert.Equal(t, a1.schema, 1, "action 1 schema mismatch")
assert.Equal(t, a1.actionType, "add_book", "action 1 type mismatch")
assert.Equal(t, a1.data, `{"book_name":"js"}`, "action 1 data mismatch")
assert.Equal(t, a1.timestamp, 1536977229, "action 1 timestamp mismatch")
assert.Equal(t, a2.uuid, "c048a56b-179c-4f31-9995-81e9b32b7dd6", "action 2 uuid mismatch")
assert.Equal(t, a2.schema, 2, "action 2 schema mismatch")
assert.Equal(t, a2.actionType, "add_note", "action 2 type mismatch")
assert.Equal(t, a2.data, `{"note_uuid":"35cbcab1-6a2a-4cc8-97e0-e73bbbd54626","book_name":"js","content":"js test 1","public":false}`, "action 2 data mismatch")
assert.Equal(t, a2.timestamp, 1536977229, "action 2 timestamp mismatch")
assert.Equal(t, a3.uuid, "f557ef48-c304-47dc-adfb-46b7306e701f", "action 3 uuid mismatch")
assert.Equal(t, a3.schema, 2, "action 3 schema mismatch")
assert.Equal(t, a3.actionType, "add_note", "action 3 type mismatch")
assert.Equal(t, a3.data, `{"note_uuid":"7c1fcfb2-de8b-4350-88f0-fb3cbaf6630a","book_name":"js","content":"js test 2","public":false}`, "action 3 data mismatch")
assert.Equal(t, a3.timestamp, 1536977230, "action 3 timestamp mismatch")
assert.Equal(t, a4.uuid, "8d79db34-343d-4331-ae5b-24743f17ca7f", "action 4 uuid mismatch")
assert.Equal(t, a4.schema, 2, "action 4 schema mismatch")
assert.Equal(t, a4.actionType, "add_note", "action 4 type mismatch")
assert.Equal(t, a4.data, `{"note_uuid":"b23a88ba-b291-4294-9795-86b394db5dcf","book_name":"js","content":"js test 3","public":false}`, "action 4 data mismatch")
assert.Equal(t, a4.timestamp, 1536977234, "action 4 timestamp mismatch")
assert.Equal(t, a5.uuid, "b9c1ed4a-e6b3-41f2-983b-593ec7b8b7a1", "action 5 uuid mismatch")
assert.Equal(t, a5.schema, 1, "action 5 schema mismatch")
assert.Equal(t, a5.actionType, "add_book", "action 5 type mismatch")
assert.Equal(t, a5.data, `{"book_name":"css"}`, "action 5 data mismatch")
assert.Equal(t, a5.timestamp, 1536977237, "action 5 timestamp mismatch")
assert.Equal(t, a6.uuid, "06ed7ef0-f171-4bd7-ae8e-97b5d06a4c49", "action 6 uuid mismatch")
assert.Equal(t, a6.schema, 2, "action 6 schema mismatch")
assert.Equal(t, a6.actionType, "add_note", "action 6 type mismatch")
assert.Equal(t, a6.data, `{"note_uuid":"d69edb54-5b31-4cdd-a4a5-34f0a0bfa153","book_name":"css","content":"js test 3","public":false}`, "action 6 data mismatch")
assert.Equal(t, a6.timestamp, 1536977237, "action 6 timestamp mismatch")
assert.Equal(t, a7.uuid, "7f173cef-1688-4177-a373-145fcd822b2f", "action 7 uuid mismatch")
assert.Equal(t, a7.schema, 2, "action 7 schema mismatch")
assert.Equal(t, a7.actionType, "edit_note", "action 7 type mismatch")
assert.Equal(t, a7.data, `{"note_uuid":"d69edb54-5b31-4cdd-a4a5-34f0a0bfa153","from_book":"css","to_book":null,"content":"css test 1","public":null}`, "action 7 data mismatch")
assert.Equal(t, a7.timestamp, 1536977253, "action 7 timestamp mismatch")
assert.Equal(t, a8.uuid, "64352e08-aa7a-45f4-b760-b3f38b5e11fa", "action 8 uuid mismatch")
assert.Equal(t, a8.schema, 1, "action 8 schema mismatch")
assert.Equal(t, a8.actionType, "add_book", "action 8 type mismatch")
assert.Equal(t, a8.data, `{"book_name":"sql"}`, "action 8 data mismatch")
assert.Equal(t, a8.timestamp, 1536977261, "action 8 timestamp mismatch")
assert.Equal(t, a9.uuid, "82e20a12-bda8-45f7-ac42-b453b6daa5ec", "action 9 uuid mismatch")
assert.Equal(t, a9.schema, 2, "action 9 schema mismatch")
assert.Equal(t, a9.actionType, "add_note", "action 9 type mismatch")
assert.Equal(t, a9.data, `{"note_uuid":"2f47d390-685b-4b84-89ac-704c6fb8d3fb","book_name":"sql","content":"blah","public":false}`, "action 9 data mismatch")
assert.Equal(t, a9.timestamp, 1536977261, "action 9 timestamp mismatch")
assert.Equal(t, a10.uuid, "a29055f4-ace4-44fd-8800-3396edbccaef", "action 10 uuid mismatch")
assert.Equal(t, a10.schema, 1, "action 10 schema mismatch")
assert.Equal(t, a10.actionType, "remove_book", "action 10 type mismatch")
assert.Equal(t, a10.data, `{"book_name":"sql"}`, "action 10 data mismatch")
assert.Equal(t, a10.timestamp, 1536977268, "action 10 timestamp mismatch")
assert.Equal(t, a11.uuid, "871a5562-1bd0-43c1-b550-5bbb727ac7c4", "action 11 uuid mismatch")
assert.Equal(t, a11.schema, 1, "action 11 schema mismatch")
assert.Equal(t, a11.actionType, "remove_note", "action 11 type mismatch")
assert.Equal(t, a11.data, `{"note_uuid":"b23a88ba-b291-4294-9795-86b394db5dcf","book_name":"js"}`, "action 11 data mismatch")
assert.Equal(t, a11.timestamp, 1536977274, "action 11 timestamp mismatch")
// 3. test if system is migrated
var systemCount int
err = db.QueryRow("SELECT count(*) FROM system").Scan(&systemCount)
if err != nil {
panic(errors.Wrap(err, "counting system"))
}
assert.Equal(t, systemCount, 3, "action count mismatch")
var lastUpgrade, lastAction, bookmark int
err = db.QueryRow("SELECT value FROM system WHERE key = ?", "last_upgrade").Scan(&lastUpgrade)
if err != nil {
panic(errors.Wrap(err, "finding last_upgrade"))
}
err = db.QueryRow("SELECT value FROM system WHERE key = ?", "last_action").Scan(&lastAction)
if err != nil {
panic(errors.Wrap(err, "finding last_action"))
}
err = db.QueryRow("SELECT value FROM system WHERE key = ?", "bookmark").Scan(&bookmark)
if err != nil {
panic(errors.Wrap(err, "finding bookmark"))
}
assert.Equal(t, lastUpgrade, 1536977220, "last_upgrade mismatch")
assert.Equal(t, lastAction, 1536977274, "last_action mismatch")
assert.Equal(t, bookmark, 9, "bookmark mismatch")
}