restructure
Some checks failed
CI - Multi-Platform Native / Build iOS (RSSuper) (push) Has been cancelled
CI - Multi-Platform Native / Build macOS (push) Has been cancelled
CI - Multi-Platform Native / Build Android (push) Has been cancelled
CI - Multi-Platform Native / Build Linux (push) Has been cancelled
CI - Multi-Platform Native / Build Summary (push) Has been cancelled

This commit is contained in:
2026-03-30 16:39:18 -04:00
parent a8e07d52f0
commit c2e1622bd8
252 changed files with 4803 additions and 17165 deletions

View File

@@ -0,0 +1,423 @@
/*
* DatabaseTests.vala
*
* Unit tests for database layer.
*/
public class RSSuper.DatabaseTests {
private Database? db;
private string test_db_path;
public void run_subscription_crud() {
try {
test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
db = new Database(test_db_path);
} catch (DBError e) {
warning("Failed to create test database: %s", e.message);
return;
}
try {
var store = new SubscriptionStore(db);
// Create test subscription
var subscription = new FeedSubscription.with_values(
"sub_1",
"https://example.com/feed.xml",
"Example Feed",
60,
"Technology",
true,
"2024-01-01T00:00:00Z",
"2024-01-01T00:00:00Z"
);
// Test add
store.add(subscription);
var retrieved = store.get_by_id("sub_1");
if (retrieved == null) {
printerr("FAIL: Expected subscription to exist after add\n");
return;
}
// Test get
if (retrieved.title != "Example Feed") {
printerr("FAIL: Expected title 'Example Feed', got '%s'\n", retrieved.title);
return;
}
if (retrieved.url != "https://example.com/feed.xml") {
printerr("FAIL: Expected url 'https://example.com/feed.xml', got '%s'\n", retrieved.url);
return;
}
// Test update
retrieved.title = "Updated Feed";
store.update(retrieved);
var updated = store.get_by_id("sub_1");
if (updated.title != "Updated Feed") {
printerr("FAIL: Expected title 'Updated Feed', got '%s'\n", updated.title);
return;
}
// Test delete
store.remove_subscription("sub_1");
var deleted = store.get_by_id("sub_1");
if (deleted != null) {
printerr("FAIL: Expected subscription to be deleted\n");
return;
}
print("PASS: test_subscription_crud\n");
} finally {
cleanup();
}
}
public void run_subscription_list() {
try {
test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
db = new Database(test_db_path);
} catch (DBError e) {
warning("Failed to create test database: %s", e.message);
return;
}
try {
var store = new SubscriptionStore(db);
// Add multiple subscriptions
var sub1 = new FeedSubscription.with_values("sub_1", "https://feed1.com", "Feed 1");
var sub2 = new FeedSubscription.with_values("sub_2", "https://feed2.com", "Feed 2");
var sub3 = new FeedSubscription.with_values("sub_3", "https://feed3.com", "Feed 3", 60, null, false);
store.add(sub1);
store.add(sub2);
store.add(sub3);
// Test get_all
var all = store.get_all();
if (all.length != 3) {
printerr("FAIL: Expected 3 subscriptions, got %d\n", all.length);
return;
}
// Test get_enabled
var enabled = store.get_enabled();
if (enabled.length != 2) {
printerr("FAIL: Expected 2 enabled subscriptions, got %d\n", enabled.length);
return;
}
print("PASS: test_subscription_list\n");
} finally {
cleanup();
}
}
public void run_feed_item_crud() {
try {
test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
db = new Database(test_db_path);
} catch (DBError e) {
warning("Failed to create test database: %s", e.message);
return;
}
try {
var sub_store = new SubscriptionStore(db);
var item_store = new FeedItemStore(db);
// Create subscription first
var subscription = new FeedSubscription.with_values(
"sub_1", "https://example.com/feed.xml", "Example Feed"
);
sub_store.add(subscription);
// Create test item
var item = new FeedItem.with_values(
"item_1",
"Test Article",
"https://example.com/article",
"This is a test description",
"Full content of the article",
"John Doe",
"2024-01-01T12:00:00Z",
"2024-01-01T12:00:00Z",
{"Technology", "News"},
null, null, null, null,
"sub_1" // subscription_id (stored as subscription_title in DB)
);
// Test add
item_store.add(item);
var retrieved = item_store.get_by_id("item_1");
if (retrieved == null) {
printerr("FAIL: Expected item to exist after add\n");
return;
}
if (retrieved.title != "Test Article") {
printerr("FAIL: Expected title 'Test Article', got '%s'\n", retrieved.title);
return;
}
// Test get by subscription
var items = item_store.get_by_subscription("sub_1");
if (items.length != 1) {
printerr("FAIL: Expected 1 item, got %d\n", items.length);
return;
}
// Test mark as read
item_store.mark_as_read("item_1");
// Test delete
item_store.delete("item_1");
var deleted = item_store.get_by_id("item_1");
if (deleted != null) {
printerr("FAIL: Expected item to be deleted\n");
return;
}
print("PASS: test_feed_item_crud\n");
} finally {
cleanup();
}
}
public void run_feed_item_batch() {
try {
test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
db = new Database(test_db_path);
} catch (DBError e) {
warning("Failed to create test database: %s", e.message);
return;
}
try {
var sub_store = new SubscriptionStore(db);
var item_store = new FeedItemStore(db);
// Create subscription
var subscription = new FeedSubscription.with_values(
"sub_1", "https://example.com/feed.xml", "Example Feed"
);
sub_store.add(subscription);
// Create multiple items
var items = new FeedItem[5];
for (var i = 0; i < 5; i++) {
items[i] = new FeedItem.with_values(
"item_%d".printf(i),
"Article %d".printf(i),
"https://example.com/article%d".printf(i),
"Description %d".printf(i),
null,
"Author %d".printf(i),
"2024-01-%02dT12:00:00Z".printf(i + 1),
null,
null,
null, null, null, null,
"sub_1" // subscription_id
);
}
// Test batch insert
item_store.add_batch(items);
var all = item_store.get_by_subscription("sub_1");
if (all.length != 5) {
printerr("FAIL: Expected 5 items, got %d\n", all.length);
return;
}
print("PASS: test_feed_item_batch\n");
} finally {
cleanup();
}
}
public void run_search_history() {
try {
test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
db = new Database(test_db_path);
} catch (DBError e) {
warning("Failed to create test database: %s", e.message);
return;
}
try {
var store = new SearchHistoryStore(db);
// Create test queries
var query1 = SearchQuery("test query", 1, 20, null, SearchSortOption.RELEVANCE);
var query2 = SearchQuery("another search", 1, 10, null, SearchSortOption.DATE_DESC);
// Test record
store.record_search(query1, 15);
store.record_search(query2, 8);
// Test get_history
var history = store.get_history();
if (history.length != 2) {
printerr("FAIL: Expected 2 history entries, got %d\n", history.length);
return;
}
// Check that both queries are in history (order may vary due to timing)
bool found_test_query = false;
bool found_another_search = false;
foreach (var q in history) {
if (q.query == "test query") found_test_query = true;
if (q.query == "another search") found_another_search = true;
}
if (!found_test_query || !found_another_search) {
printerr("FAIL: Expected both queries in history\n");
return;
}
// Test get_recent
var recent = store.get_recent();
if (recent.length != 2) {
printerr("FAIL: Expected 2 recent entries, got %d\n", recent.length);
return;
}
print("PASS: test_search_history\n");
} finally {
cleanup();
}
}
public void run_fts_search() {
try {
test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
db = new Database(test_db_path);
} catch (DBError e) {
warning("Failed to create test database: %s", e.message);
return;
}
try {
var sub_store = new SubscriptionStore(db);
var item_store = new FeedItemStore(db);
// Create subscription
var subscription = new FeedSubscription.with_values(
"sub_1", "https://example.com/feed.xml", "Example Feed"
);
sub_store.add(subscription);
// Add items with searchable content
var item1 = new FeedItem.with_values(
"item_1",
"Swift Programming Guide",
"https://example.com/swift",
"Learn Swift programming language basics",
"A comprehensive guide to Swift",
"Apple Developer",
"2024-01-01T12:00:00Z",
null,
null,
null, null, null, null,
"sub_1" // subscription_id
);
var item2 = new FeedItem.with_values(
"item_2",
"Python for Data Science",
"https://example.com/python",
"Data analysis with Python and pandas",
"Complete Python data science tutorial",
"Data Team",
"2024-01-02T12:00:00Z",
null,
null,
null, null, null, null,
"sub_1" // subscription_id
);
item_store.add(item1);
item_store.add(item2);
// Test FTS search
var results = item_store.search("swift");
if (results.length != 1) {
printerr("FAIL: Expected 1 result for 'swift', got %d\n", results.length);
return;
}
if (results[0].title != "Swift Programming Guide") {
printerr("FAIL: Expected 'Swift Programming Guide', got '%s'\n", results[0].title);
return;
}
results = item_store.search("python");
if (results.length != 1) {
printerr("FAIL: Expected 1 result for 'python', got %d\n", results.length);
return;
}
if (results[0].title != "Python for Data Science") {
printerr("FAIL: Expected 'Python for Data Science', got '%s'\n", results[0].title);
return;
}
print("PASS: test_fts_search\n");
} finally {
cleanup();
}
}
private void cleanup() {
if (db != null) {
db.close();
db = null;
}
// Clean up test database
if (test_db_path != null && test_db_path.length > 0) {
var file = File.new_for_path(test_db_path);
if (file.query_exists()) {
try {
file.delete();
} catch (Error e) {
warning("Failed to delete test database: %s", e.message);
}
}
// Clean up WAL file
var wal_file = File.new_for_path(test_db_path + "-wal");
if (wal_file.query_exists()) {
try {
wal_file.delete();
} catch (Error e) {
warning("Failed to delete WAL file: %s", e.message);
}
}
}
}
public static int main(string[] args) {
print("Running database tests...\n");
var tests = new DatabaseTests();
print("\n=== Running subscription CRUD tests ===");
tests.run_subscription_crud();
print("\n=== Running subscription list tests ===");
tests.run_subscription_list();
print("\n=== Running feed item CRUD tests ===");
tests.run_feed_item_crud();
print("\n=== Running feed item batch tests ===");
tests.run_feed_item_batch();
print("\n=== Running search history tests ===");
tests.run_search_history();
print("\n=== Running FTS search tests ===");
tests.run_fts_search();
print("\nAll tests completed!\n");
return 0;
}
}