mirror of
https://github.com/nkanaev/yarr.git
synced 2025-09-14 02:10:04 +00:00
331 lines
8.7 KiB
Go
331 lines
8.7 KiB
Go
package storage
|
|
|
|
import (
|
|
"log"
|
|
"reflect"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
/*
|
|
- folder1
|
|
- feed11
|
|
- item111 (unread)
|
|
- item112 (read)
|
|
- item113 (starred)
|
|
- feed12
|
|
- item121 (unread)
|
|
- item122 (read)
|
|
- folder2
|
|
- feed21
|
|
- item211 (read)
|
|
- item212 (starred)
|
|
- feed01
|
|
- item011 (unread)
|
|
- item012 (read)
|
|
- item013 (starred)
|
|
*/
|
|
|
|
type testItemScope struct {
|
|
feed11, feed12 *Feed
|
|
feed21, feed01 *Feed
|
|
folder1, folder2 *Folder
|
|
}
|
|
|
|
func testItemsSetup(db *Storage) testItemScope {
|
|
folder1 := db.CreateFolder("folder1")
|
|
folder2 := db.CreateFolder("folder2")
|
|
|
|
feed11 := db.CreateFeed("feed11", "", "", "http://test.com/feed11.xml", &folder1.Id)
|
|
feed12 := db.CreateFeed("feed12", "", "", "http://test.com/feed12.xml", &folder1.Id)
|
|
feed21 := db.CreateFeed("feed21", "", "", "http://test.com/feed21.xml", &folder2.Id)
|
|
feed01 := db.CreateFeed("feed01", "", "", "http://test.com/feed01.xml", nil)
|
|
|
|
now := time.Now()
|
|
db.CreateItems([]Item{
|
|
// feed11
|
|
{GUID: "item111", FeedId: feed11.Id, Title: "title111", Date: now.Add(time.Hour * 24 * 1)},
|
|
{GUID: "item112", FeedId: feed11.Id, Title: "title112", Date: now.Add(time.Hour * 24 * 2)}, // read
|
|
{GUID: "item113", FeedId: feed11.Id, Title: "title113", Date: now.Add(time.Hour * 24 * 3)}, // starred
|
|
// feed12
|
|
{GUID: "item121", FeedId: feed12.Id, Title: "title121", Date: now.Add(time.Hour * 24 * 4)},
|
|
{GUID: "item122", FeedId: feed12.Id, Title: "title122", Date: now.Add(time.Hour * 24 * 5)}, // read
|
|
// feed21
|
|
{GUID: "item211", FeedId: feed21.Id, Title: "title211", Date: now.Add(time.Hour * 24 * 6)}, // read
|
|
{GUID: "item212", FeedId: feed21.Id, Title: "title212", Date: now.Add(time.Hour * 24 * 7)}, // starred
|
|
// feed01
|
|
{GUID: "item011", FeedId: feed01.Id, Title: "title011", Date: now.Add(time.Hour * 24 * 8)},
|
|
{GUID: "item012", FeedId: feed01.Id, Title: "title012", Date: now.Add(time.Hour * 24 * 9)}, // read
|
|
{GUID: "item013", FeedId: feed01.Id, Title: "title013", Date: now.Add(time.Hour * 24 * 10)}, // starred
|
|
})
|
|
db.db.Exec(`update items set status = ? where guid in ("item112", "item122", "item211", "item012")`, READ)
|
|
db.db.Exec(`update items set status = ? where guid in ("item113", "item212", "item013")`, STARRED)
|
|
|
|
return testItemScope{
|
|
feed11: feed11,
|
|
feed12: feed12,
|
|
feed21: feed21,
|
|
feed01: feed01,
|
|
folder1: folder1,
|
|
folder2: folder2,
|
|
}
|
|
}
|
|
|
|
func getItem(db *Storage, guid string) *Item {
|
|
i := &Item{}
|
|
err := db.db.QueryRow(`
|
|
select
|
|
i.id, i.guid, i.feed_id, i.title, i.link, i.content,
|
|
i.date, i.status, i.image, i.podcast_url
|
|
from items i
|
|
where i.guid = ?
|
|
`, guid).Scan(
|
|
&i.Id, &i.GUID, &i.FeedId, &i.Title, &i.Link, &i.Content,
|
|
&i.Date, &i.Status, &i.ImageURL, &i.AudioURL,
|
|
)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
return i
|
|
}
|
|
|
|
func getItemGuids(items []Item) []string {
|
|
guids := make([]string, 0)
|
|
for _, item := range items {
|
|
guids = append(guids, item.GUID)
|
|
}
|
|
return guids
|
|
}
|
|
|
|
func TestListItems(t *testing.T) {
|
|
db := testDB()
|
|
scope := testItemsSetup(db)
|
|
|
|
// filter by folder_id
|
|
|
|
have := getItemGuids(db.ListItems(ItemFilter{FolderID: &scope.folder1.Id}, 10, false, false))
|
|
want := []string{"item111", "item112", "item113", "item121", "item122"}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
|
|
have = getItemGuids(db.ListItems(ItemFilter{FolderID: &scope.folder2.Id}, 10, false, false))
|
|
want = []string{"item211", "item212"}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
|
|
// filter by feed_id
|
|
|
|
have = getItemGuids(db.ListItems(ItemFilter{FeedID: &scope.feed11.Id}, 10, false, false))
|
|
want = []string{"item111", "item112", "item113"}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
|
|
have = getItemGuids(db.ListItems(ItemFilter{FeedID: &scope.feed01.Id}, 10, false, false))
|
|
want = []string{"item011", "item012", "item013"}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
|
|
// filter by status
|
|
|
|
var starred ItemStatus = STARRED
|
|
have = getItemGuids(db.ListItems(ItemFilter{Status: &starred}, 10, false, false))
|
|
want = []string{"item113", "item212", "item013"}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
|
|
var unread ItemStatus = UNREAD
|
|
have = getItemGuids(db.ListItems(ItemFilter{Status: &unread}, 10, false, false))
|
|
want = []string{"item111", "item121", "item011"}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
|
|
// limit
|
|
|
|
have = getItemGuids(db.ListItems(ItemFilter{}, 2, false, false))
|
|
want = []string{"item111", "item112"}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
|
|
// filter by search
|
|
db.SyncSearch()
|
|
search1 := "title111"
|
|
have = getItemGuids(db.ListItems(ItemFilter{Search: &search1}, 4, true, false))
|
|
want = []string{"item111"}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
|
|
// sort by date
|
|
have = getItemGuids(db.ListItems(ItemFilter{}, 4, true, false))
|
|
want = []string{"item013", "item012", "item011", "item212"}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
}
|
|
|
|
func TestListItemsPaginated(t *testing.T) {
|
|
db := testDB()
|
|
testItemsSetup(db)
|
|
|
|
item012 := getItem(db, "item012")
|
|
item121 := getItem(db, "item121")
|
|
|
|
// all, newest first
|
|
have := getItemGuids(db.ListItems(ItemFilter{After: &item012.Id}, 3, true, false))
|
|
want := []string{"item011", "item212", "item211"}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
|
|
// unread, newest first
|
|
unread := UNREAD
|
|
have = getItemGuids(db.ListItems(ItemFilter{After: &item012.Id, Status: &unread}, 3, true, false))
|
|
want = []string{"item011", "item121", "item111"}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
|
|
// starred, oldest first
|
|
starred := STARRED
|
|
have = getItemGuids(db.ListItems(ItemFilter{After: &item121.Id, Status: &starred}, 3, false, false))
|
|
want = []string{"item212", "item013"}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
}
|
|
|
|
func TestMarkItemsRead(t *testing.T) {
|
|
// NOTE: starred items must not be marked as read
|
|
var read ItemStatus = READ
|
|
|
|
db1 := testDB()
|
|
testItemsSetup(db1)
|
|
db1.MarkItemsRead(MarkFilter{})
|
|
have := getItemGuids(db1.ListItems(ItemFilter{Status: &read}, 10, false, false))
|
|
want := []string{
|
|
"item111", "item112", "item121", "item122",
|
|
"item211", "item011", "item012",
|
|
}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
|
|
db2 := testDB()
|
|
scope2 := testItemsSetup(db2)
|
|
db2.MarkItemsRead(MarkFilter{FolderID: &scope2.folder1.Id})
|
|
have = getItemGuids(db2.ListItems(ItemFilter{Status: &read}, 10, false, false))
|
|
want = []string{
|
|
"item111", "item112", "item121", "item122",
|
|
"item211", "item012",
|
|
}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
|
|
db3 := testDB()
|
|
scope3 := testItemsSetup(db3)
|
|
db3.MarkItemsRead(MarkFilter{FeedID: &scope3.feed11.Id})
|
|
have = getItemGuids(db3.ListItems(ItemFilter{Status: &read}, 10, false, false))
|
|
want = []string{
|
|
"item111", "item112", "item122",
|
|
"item211", "item012",
|
|
}
|
|
if !reflect.DeepEqual(have, want) {
|
|
t.Logf("want: %#v", want)
|
|
t.Logf("have: %#v", have)
|
|
t.Fail()
|
|
}
|
|
}
|
|
|
|
func TestDeleteOldItems(t *testing.T) {
|
|
extraItems := 10
|
|
|
|
now := time.Now().UTC()
|
|
db := testDB()
|
|
feed := db.CreateFeed("feed", "", "", "http://test.com/feed11.xml", nil)
|
|
|
|
items := make([]Item, 0)
|
|
for i := 0; i < itemsKeepSize+extraItems; i++ {
|
|
istr := strconv.Itoa(i)
|
|
items = append(items, Item{
|
|
GUID: istr,
|
|
FeedId: feed.Id,
|
|
Title: istr,
|
|
Date: now.Add(time.Hour * time.Duration(i)),
|
|
})
|
|
}
|
|
db.CreateItems(items)
|
|
|
|
db.SetFeedSize(feed.Id, itemsKeepSize)
|
|
var feedSize int
|
|
err := db.db.QueryRow(
|
|
`select size from feed_sizes where feed_id = ?`, feed.Id,
|
|
).Scan(&feedSize)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if feedSize != itemsKeepSize {
|
|
t.Fatalf(
|
|
"expected feed size to get updated\nwant: %d\nhave: %d",
|
|
itemsKeepSize+extraItems,
|
|
feedSize,
|
|
)
|
|
}
|
|
|
|
// expire only the first 3 articles
|
|
_, err = db.db.Exec(
|
|
`update items set date_arrived = ?
|
|
where id in (select id from items limit 3)`,
|
|
now.Add(-time.Hour*time.Duration(itemsKeepDays*24)),
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
db.DeleteOldItems()
|
|
feedItems := db.ListItems(ItemFilter{FeedID: &feed.Id}, 1000, false, false)
|
|
if len(feedItems) != len(items)-3 {
|
|
t.Fatalf(
|
|
"invalid number of old items kept\nwant: %d\nhave: %d",
|
|
len(items)-3,
|
|
len(feedItems),
|
|
)
|
|
}
|
|
}
|