123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790 |
- package storage
- import (
- "database/sql"
- "errors"
- "log"
- "testing"
- _ "github.com/mattn/go-sqlite3"
- "github.com/stretchr/testify/assert"
- )
- const badPostsTable = `
- CREATE TABLE IF NOT EXISTS posts(
- row INTEGER PRIMARY KEY AUTOINCREMENT
- );
- `
- const badImagesTable = `
- CREATE TABLE IF NOT EXISTS images(
- row INTEGER PRIMARY KEY AUTOINCREMENT
- );
- `
- const badMenuItemsTable = `
- CREATE TABLE IF NOT EXISTS menu(
- row INTEGER PRIMARY KEY AUTOINCREMENT
- );
- `
- const badNavbarItemsTable = `
- CREATE TABLE IF NOT EXISTS navbar(
- row INTEGER PRIMARY KEY AUTOINCREMENT
- );`
- const badAssetTable = `
- CREATE TABLE IF NOT EXISTS assets(
- row INTEGER PRIMARY KEY AUTOINCREMENT
- );
- `
- const badAdminTable = `
- CREATE TABLE IF NOT EXISTS admin(
- row INTEGER PRIMARY KEY AUTOINCREMENT
- );
- `
- var unpopulatedTables = []string{badPostsTable, badImagesTable, badMenuItemsTable, badMenuItemsTable, badAssetTable, badAdminTable}
- /*
- creates in memory db and SQLiteRepo struct
- :param tmp: path to the temp directory for the filesystem IO struct to write images to
- :param migrate: choose to 'migrate' the database and create all the tables
- */
- func newTestDb(tmp string, migrate bool) (*SQLiteRepo, *sql.DB) {
- db, err := sql.Open("sqlite3", ":memory:")
- if err != nil {
- log.Fatal(err)
- }
- testDb := &SQLiteRepo{db: db, imageIO: FilesystemImageIO{RootDir: tmp}}
- if migrate {
- err = testDb.Migrate(RequiredTables)
- } else {
- err = testDb.Migrate(unpopulatedTables)
- }
- if err != nil {
- log.Fatal("failed to start the test database: ", err)
- }
- return testDb, db
- }
- func TestMigrate(t *testing.T) {
- requiredTables := []string{
- "posts",
- "images",
- "menu",
- "navbar",
- "assets",
- "admin",
- }
- db, err := sql.Open("sqlite3", ":memory:")
- if err != nil {
- log.Fatal(err)
- }
- testDb := &SQLiteRepo{db: db}
- err = testDb.Migrate(RequiredTables)
- if err != nil {
- t.Error(err)
- }
- for i := range requiredTables {
- name := requiredTables[i]
- row := db.QueryRow("SELECT name FROM sqlite_master WHERE type='table' AND name='?'", name)
- if row.Err() != nil {
- t.Errorf("error querying table: %s", name)
- }
- if row == nil {
- t.Errorf("no table returned: %s", name)
- }
- }
- }
- func TestGetDropdownElements(t *testing.T) {
- type testcase struct {
- seed []LinkPair
- }
- testDb, db := newTestDb(t.TempDir(), true)
- for _, tc := range []testcase{
- {
- seed: []LinkPair{
- {
- Text: "abc123",
- Link: "/abc/123",
- },
- },
- },
- } {
- stmt, _ := db.Prepare("INSERT INTO menu(link, text) VALUES (?,?)")
- for i := range tc.seed {
- _, err := stmt.Exec(tc.seed[i].Link, tc.seed[i].Text)
- if err != nil {
- t.Errorf("failed to seed: %s", err)
- }
- }
- got := testDb.GetDropdownElements()
- assert.Equal(t, got, tc.seed)
- }
- }
- func TestGetNavBarLinks(t *testing.T) {
- type testcase struct {
- seed []NavBarItem
- }
- testDb, db := newTestDb(t.TempDir(), true)
- for _, tc := range []testcase{
- {
- seed: []NavBarItem{
- {
- Link: "/abc/123",
- Redirect: "/abc/123/site",
- Png: []byte("xzy123abc098"),
- },
- },
- },
- } {
- stmt, _ := db.Prepare("INSERT INTO navbar(png, link, redirect) VALUES (?,?,?)")
- for i := range tc.seed {
- _, err := stmt.Exec(tc.seed[i].Png, tc.seed[i].Link, tc.seed[i].Redirect)
- if err != nil {
- t.Errorf("failed to seed: %s", err)
- }
- }
- got := testDb.GetNavBarLinks()
- assert.Equal(t, tc.seed, got)
- }
- }
- func TestGetAssets(t *testing.T) {
- type testcase struct {
- seed []Asset
- }
- testDb, db := newTestDb(t.TempDir(), true)
- for _, tc := range []testcase{
- {
- seed: []Asset{
- {
- Data: []byte("abc123xyz098"),
- Name: "asset1",
- },
- },
- },
- } {
- stmt, _ := db.Prepare("INSERT INTO assets(data, name) VALUES (?,?)")
- for i := range tc.seed {
- _, err := stmt.Exec(tc.seed[i].Data, tc.seed[i].Name)
- if err != nil {
- t.Error(err)
- }
- }
- got := testDb.GetAssets()
- assert.Equal(t, tc.seed, got)
- }
- }
- func TestGetAdminTables(t *testing.T) {
- type testcase struct {
- seed AdminPage
- }
- testDb, db := newTestDb(t.TempDir(), true)
- for _, tc := range []testcase{
- {
- seed: AdminPage{
- Tables: map[string][]TableData{
- "test": {
- {
- DisplayName: "abc123",
- Link: "xyz098",
- },
- },
- },
- },
- },
- } {
- stmt, _ := db.Prepare("INSERT INTO admin(display_name, link, category) VALUES (?,?,?)")
- for k, table := range tc.seed.Tables {
- for i := range table {
- _, err := stmt.Exec(table[i].DisplayName, table[i].Link, k)
- if err != nil {
- t.Error(err)
- }
- }
- }
- got := testDb.GetAdminTables()
- assert.Equal(t, tc.seed, got)
- }
- }
- func TestGetDocument(t *testing.T) {
- type testcase struct {
- seed Document
- }
- testDb, db := newTestDb(t.TempDir(), true)
- for _, tc := range []testcase{
- {
- seed: Document{
- Ident: Identifier("qwerty"),
- Title: "abc 123",
- Created: "2024-12-31",
- Body: "blog post body etc",
- Category: BLOG,
- Sample: "this is a sample",
- },
- },
- } {
- stmt, _ := db.Prepare("INSERT INTO posts(id, title, created, body, category, sample) VALUES (?,?,?,?,?,?)")
- _, err := stmt.Exec(tc.seed.Ident, tc.seed.Title, tc.seed.Created, tc.seed.Body, tc.seed.Category, tc.seed.Sample)
- if err != nil {
- t.Error(err)
- }
- got, _ := testDb.GetDocument(Identifier("qwerty"))
- assert.Equal(t, tc.seed, got)
- }
- }
- func TestGetByCategory(t *testing.T) {
- type testcase struct {
- seed []Document
- }
- testDb, db := newTestDb(t.TempDir(), true)
- for _, tc := range []testcase{
- {
- seed: []Document{
- {
- Row: 1,
- Ident: Identifier("qwerty"),
- Title: "abc 123",
- Created: "2024-12-31",
- Body: "blog post body etc",
- Category: BLOG,
- Sample: "this is a sample",
- },
- {
- Row: 2,
- Ident: Identifier("poiuyt"),
- Title: "abc 123",
- Created: "2024-12-31",
- Body: "blog post body etc",
- Category: BLOG,
- Sample: "this is a sample",
- },
- },
- },
- } {
- stmt, _ := db.Prepare("INSERT INTO posts(id, title, created, body, category, sample) VALUES (?,?,?,?,?,?)")
- for i := range tc.seed {
- _, err := stmt.Exec(tc.seed[i].Ident, tc.seed[i].Title, tc.seed[i].Created, tc.seed[i].Body, tc.seed[i].Category, tc.seed[i].Sample)
- if err != nil {
- t.Error(err)
- }
- }
- got := testDb.GetByCategory(BLOG)
- assert.Equal(t, tc.seed, got)
- }
- }
- func TestGetImage(t *testing.T) {
- testDb, db := newTestDb(t.TempDir(), true)
- type testcase struct {
- seed Image
- shouldSeed bool
- err error
- }
- for _, tc := range []testcase{
- {
- seed: Image{
- Ident: Identifier("abc123"),
- Title: "xyz098",
- Desc: "description",
- Created: "2024-12-31",
- Data: []byte("abc123xyz098"),
- },
- shouldSeed: true,
- err: nil,
- },
- {
- seed: Image{
- Ident: Identifier("zxcvbnm"),
- },
- shouldSeed: false,
- err: ErrNotExists,
- },
- } {
- if tc.shouldSeed {
- _, err := db.Exec("INSERT INTO images (id, title, desc, created) VALUES (?,?,?,?)", string(tc.seed.Ident), tc.seed.Title, tc.seed.Desc, "2024-12-31")
- if err != nil {
- t.Error(err)
- }
- testDb.imageIO.Put(tc.seed.Data, tc.seed.Ident)
- }
- got, err := testDb.GetImage(tc.seed.Ident)
- if err != nil {
- assert.Equal(t, tc.err, err)
- } else {
- assert.Equal(t, tc.seed, got)
- }
- }
- }
- func TestGetAllImages(t *testing.T) {
- testDb, db := newTestDb(t.TempDir(), true)
- type testcase struct {
- seed []Image
- }
- for _, tc := range []testcase{
- {
- seed: []Image{
- {
- Ident: Identifier("abc123"),
- Title: "xyz098",
- Data: []byte("abc123xyz098"),
- Created: "2024-12-31",
- Desc: "description",
- },
- {
- Ident: Identifier("xyz098"),
- Title: "abc123",
- Data: []byte("abc123xyz098"),
- Created: "2024-12-31",
- Desc: "description",
- },
- },
- },
- } {
- for i := range tc.seed {
- _, err := db.Exec("INSERT INTO images (id, title, desc, created) VALUES (?,?,?,?)", string(tc.seed[i].Ident), tc.seed[i].Title, tc.seed[i].Desc, tc.seed[i].Created)
- if err != nil {
- t.Error(err)
- }
- testDb.imageIO.Put(tc.seed[i].Data, tc.seed[i].Ident)
- }
- got := testDb.GetAllImages()
- assert.Equal(t, tc.seed, got)
- }
- }
- func TestAllDocuments(t *testing.T) {
- testDb, db := newTestDb(t.TempDir(), true)
- type testcase struct {
- seed []Document
- }
- for _, tc := range []testcase{
- {
- seed: []Document{
- {
- Row: 1,
- Ident: Identifier("qwerty"),
- Title: "abc 123",
- Created: "2024-12-31",
- Body: "blog post body etc",
- Category: BLOG,
- Sample: "this is a sample",
- },
- {
- Row: 2,
- Ident: Identifier("poiuyt"),
- Title: "abc 123",
- Created: "2024-12-31",
- Body: "blog post body etc",
- Category: BLOG,
- Sample: "this is a sample",
- },
- },
- },
- } {
- stmt, _ := db.Prepare("INSERT INTO posts(id, title, created, body, category, sample) VALUES (?,?,?,?,?,?)")
- for i := range tc.seed {
- _, err := stmt.Exec(tc.seed[i].Ident, tc.seed[i].Title, tc.seed[i].Created, tc.seed[i].Body, tc.seed[i].Category, tc.seed[i].Sample)
- if err != nil {
- t.Error(err)
- }
- }
- got := testDb.AllDocuments()
- assert.Equal(t, tc.seed, got)
- }
- }
- func TestUpdateDocument(t *testing.T) {
- type testcase struct {
- migrate bool
- seed Document
- input Document
- err error
- }
- for _, tc := range []testcase{
- {
- migrate: true,
- seed: Document{
- Row: 1,
- Ident: Identifier("qwerty"),
- Title: "abc 123",
- Created: "2024-12-31",
- Body: "blog post body etc",
- Category: BLOG,
- Sample: "this is a sample",
- },
- input: Document{
- Row: 1,
- Ident: Identifier("qwerty"),
- Title: "new title",
- Created: "2024-12-31",
- Body: "new updated post that must be reflected after the update",
- Category: BLOG,
- Sample: "new updated post that must be reflected after the update",
- },
- err: nil,
- },
- {
- migrate: true,
- seed: Document{
- Row: 1,
- Ident: Identifier("asdf"),
- Title: "abc 123",
- Created: "2024-12-31",
- Body: "blog post body etc",
- Category: BLOG,
- Sample: "this is a sample",
- },
- input: Document{
- Row: 1,
- Ident: Identifier("This id does not exist"),
- Title: "new title",
- Created: "2024-12-31",
- Body: "new updated post that must be reflected after the update",
- Category: BLOG,
- Sample: "new updated post that must be reflected after the update",
- },
- err: ErrNotExists,
- },
- {
- migrate: false, // not creating the database tables so we can error out the SQL statement execution
- seed: Document{
- Row: 1,
- Ident: Identifier("asdf"),
- Title: "abc 123",
- Created: "2024-12-31",
- Body: "blog post body etc",
- Category: BLOG,
- Sample: "this is a sample",
- },
- input: Document{
- Row: 1,
- Ident: Identifier("This id does not exist"),
- Title: "new title",
- Created: "2024-12-31",
- Body: "new updated post that must be reflected after the update",
- Category: BLOG,
- Sample: "new updated post that must be reflected after the update",
- },
- err: errors.New("no such column: title"),
- },
- } {
- testDb, db := newTestDb(t.TempDir(), tc.migrate)
- if tc.migrate {
- stmt, _ := db.Prepare("INSERT INTO posts(id, title, created, body, category, sample) VALUES (?,?,?,?,?,?)")
- _, err := stmt.Exec(tc.seed.Ident, tc.seed.Title, tc.seed.Created, tc.seed.Body, tc.seed.Category, tc.seed.Sample)
- if err != nil {
- t.Error(err)
- }
- }
- err := testDb.UpdateDocument(tc.input)
- if err != nil {
- assert.Equal(t, tc.err.Error(), err.Error())
- } else {
- row := db.QueryRow("SELECT * FROM posts WHERE id = ?", tc.seed.Ident)
- var got Document
- if err := row.Scan(&got.Row, &got.Ident, &got.Title, &got.Created, &got.Body, &got.Category, &got.Sample); err != nil {
- assert.Equal(t, tc.err, err)
- }
- assert.Equal(t, tc.input, got)
- }
- }
- }
- func TestAddImage(t *testing.T) {
- type testcase struct {
- data []byte
- title string
- desc string
- err error
- }
- testDb, _ := newTestDb(t.TempDir(), true)
- for _, tc := range []testcase{
- {
- data: []byte("abc123xyz098"),
- title: "dont matter",
- desc: "also dont matter",
- },
- } {
- id, err := testDb.AddImage(tc.data, tc.title, tc.desc)
- if err != nil {
- assert.Equal(t, tc.err, err)
- } else {
- b, err := testDb.imageIO.Get(id)
- if err != nil {
- t.Error(err)
- }
- assert.Equal(t, tc.data, b)
- }
- }
- }
- func TestAddMenuItem(t *testing.T) {
- type testcase struct {
- input []LinkPair
- err error
- }
- testDb, db := newTestDb(t.TempDir(), true)
- for _, tc := range []testcase{
- {
- input: []LinkPair{
- {
- Text: "abc 123",
- Link: "/abc/123",
- },
- },
- err: nil,
- },
- } {
- for i := range tc.input {
- err := testDb.AddMenuItem(tc.input[i])
- if err != nil {
- assert.Equal(t, tc.err, err)
- }
- rows, err := db.Query("SELECT * FROM menu")
- var got []LinkPair
- defer rows.Close()
- for rows.Next() {
- var id int
- var item LinkPair
- err = rows.Scan(&id, &item.Link, &item.Text)
- if err != nil {
- log.Fatal(err)
- }
- got = append(got, item)
- }
- assert.Equal(t, tc.input, got)
- }
- }
- }
- func TestAddNavbarItem(t *testing.T) {
- type testcase struct {
- input []NavBarItem
- err error
- }
- testDb, db := newTestDb(t.TempDir(), true)
- for _, tc := range []testcase{
- {
- input: []NavBarItem{
- {
- Redirect: "",
- Link: "",
- Png: []byte(""),
- },
- },
- },
- } {
- for i := range tc.input {
- err := testDb.AddNavbarItem(tc.input[i])
- if err != nil {
- assert.Equal(t, tc.err, err)
- }
- }
- rows, err := db.Query("SELECT * FROM navbar")
- var got []NavBarItem
- defer rows.Close()
- for rows.Next() {
- var item NavBarItem
- var id int
- err = rows.Scan(&id, &item.Png, &item.Link, &item.Redirect)
- if err != nil {
- log.Fatal(err)
- }
- got = append(got, item)
- }
- assert.Equal(t, tc.input, got)
- }
- }
- func TestAddAsset(t *testing.T) {
- type testcase struct {
- input []Asset
- err error
- }
- testDb, db := newTestDb(t.TempDir(), true)
- for _, tc := range []testcase{
- {
- input: []Asset{
- {
- Data: []byte(""),
- Name: "",
- },
- },
- },
- } {
- for i := range tc.input {
- err := testDb.AddAsset(tc.input[i].Name, tc.input[i].Data)
- if err != nil {
- assert.Equal(t, tc.err, err)
- }
- }
- rows, err := db.Query("SELECT * FROM assets")
- var assets []Asset
- defer rows.Close()
- for rows.Next() {
- var item Asset
- var id int
- err = rows.Scan(&id, &item.Name, &item.Data)
- if err != nil {
- log.Fatal(err)
- }
- assets = append(assets, item)
- }
- }
- }
- func TestAddDocument(t *testing.T) {
- testDb, db := newTestDb(t.TempDir(), true)
- type testcase struct {
- seed Document
- err error
- }
- for _, tc := range []testcase{
- {
- seed: Document{
- Title: "abc 123",
- Body: "blog post body etc",
- Created: "2024-12-31",
- Category: BLOG,
- Sample: "this is a sample",
- },
- err: nil,
- },
- } {
- id, err := testDb.AddDocument(tc.seed)
- if err != nil {
- assert.Equal(t, tc.err, err)
- }
- row := db.QueryRow("SELECT * FROM posts WHERE id = ?", id)
- var got Document
- var rowNum int
- if err := row.Scan(&rowNum, &got.Ident, &got.Title, &got.Created, &got.Body, &got.Category, &got.Sample); err != nil {
- assert.Equal(t, tc.err, err)
- }
- want := Document{
- Ident: id,
- Title: tc.seed.Title,
- Body: tc.seed.Body,
- Category: tc.seed.Category,
- Created: tc.seed.Created,
- Sample: tc.seed.MakeSample(),
- }
- assert.Equal(t, want, got)
- }
- }
- func TestAddAdminTableEntry(t *testing.T) {
- type testcase struct {
- input AdminPage
- err error
- }
- testDb, db := newTestDb(t.TempDir(), true)
- for _, tc := range []testcase{
- {
- input: AdminPage{
- Tables: map[string][]TableData{
- "test category": {
- {
- DisplayName: "abc 123",
- Link: "/abc/123",
- },
- },
- },
- },
- err: nil,
- },
- } {
- for ctg, tables := range tc.input.Tables {
- for i := range tables {
- err := testDb.AddAdminTableEntry(tables[i], ctg)
- if err != nil {
- assert.Equal(t, tc.err, err)
- }
- }
- }
- rows, err := db.Query("SELECT * FROM admin")
- got := AdminPage{Tables: map[string][]TableData{}}
- defer rows.Close()
- for rows.Next() {
- var item TableData
- var id int
- var category string
- err = rows.Scan(&id, &item.DisplayName, &item.Link, &category)
- if err != nil {
- log.Fatal(err)
- }
- got.Tables[category] = append(got.Tables[category], item)
- }
- assert.Equal(t, tc.input, got)
- }
- }
- func TestDeleteDocument(t *testing.T) {
- type testcase struct {
- input Document
- err error
- }
- testDb, db := newTestDb(t.TempDir(), true)
- for _, tc := range []testcase{
- {
- input: Document{
- Title: "abc 123",
- Body: "blog post body etc",
- Created: "2024-12-31",
- Category: BLOG,
- Sample: "this is a sample",
- },
- err: nil,
- },
- } {
- id, err := testDb.AddDocument(tc.input)
- if err != nil {
- t.Error("failed to add doc: ", err)
- }
- err = testDb.DeleteDocument(id)
- if err != nil {
- assert.Equal(t, tc.err, err)
- }
- row, _ := db.Query("SELECT * FROM posts")
- if row.Next() {
- t.Error("Too many rows returned after deleting")
- }
- }
- }
- func TestGetImageStore(t *testing.T) {
- // testDb, db := newTestDb(t.TempDir(), true)
- }
- func TestNewIdentifier(t *testing.T) {
- // testDb, db := newTestDb(t.TempDir(), true)
- }
|