/** * DailyNotificationDatabaseTest.java * * Unit tests for SQLite database functionality * Tests schema creation, WAL mode, and basic operations * * @author Matthew Raymer * @version 1.0.0 */ package com.timesafari.dailynotification; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.test.AndroidTestCase; import android.test.mock.MockContext; import java.io.File; /** * Unit tests for DailyNotificationDatabase * * Tests the core SQLite functionality including: * - Database creation and schema * - WAL mode configuration * - Table and index creation * - Schema version management */ public class DailyNotificationDatabaseTest extends AndroidTestCase { private DailyNotificationDatabase database; private Context mockContext; @Override protected void setUp() throws Exception { super.setUp(); // Create mock context mockContext = new MockContext() { @Override public File getDatabasePath(String name) { return new File(getContext().getCacheDir(), name); } }; // Create database instance database = new DailyNotificationDatabase(mockContext); } @Override protected void tearDown() throws Exception { if (database != null) { database.close(); } super.tearDown(); } /** * Test database creation and schema */ public void testDatabaseCreation() { assertNotNull("Database should not be null", database); SQLiteDatabase db = database.getReadableDatabase(); assertNotNull("Readable database should not be null", db); assertTrue("Database should be open", db.isOpen()); db.close(); } /** * Test WAL mode configuration */ public void testWALModeConfiguration() { SQLiteDatabase db = database.getWritableDatabase(); // Check journal mode android.database.Cursor cursor = db.rawQuery("PRAGMA journal_mode", null); assertTrue("Should have journal mode result", cursor.moveToFirst()); String journalMode = cursor.getString(0); assertEquals("Journal mode should be WAL", "wal", journalMode.toLowerCase()); cursor.close(); // Check synchronous mode cursor = db.rawQuery("PRAGMA synchronous", null); assertTrue("Should have synchronous result", cursor.moveToFirst()); int synchronous = cursor.getInt(0); assertEquals("Synchronous mode should be NORMAL", 1, synchronous); cursor.close(); // Check foreign keys cursor = db.rawQuery("PRAGMA foreign_keys", null); assertTrue("Should have foreign_keys result", cursor.moveToFirst()); int foreignKeys = cursor.getInt(0); assertEquals("Foreign keys should be enabled", 1, foreignKeys); cursor.close(); db.close(); } /** * Test table creation */ public void testTableCreation() { SQLiteDatabase db = database.getWritableDatabase(); // Check if tables exist assertTrue("notif_contents table should exist", tableExists(db, DailyNotificationDatabase.TABLE_NOTIF_CONTENTS)); assertTrue("notif_deliveries table should exist", tableExists(db, DailyNotificationDatabase.TABLE_NOTIF_DELIVERIES)); assertTrue("notif_config table should exist", tableExists(db, DailyNotificationDatabase.TABLE_NOTIF_CONFIG)); db.close(); } /** * Test index creation */ public void testIndexCreation() { SQLiteDatabase db = database.getWritableDatabase(); // Check if indexes exist assertTrue("notif_idx_contents_slot_time index should exist", indexExists(db, "notif_idx_contents_slot_time")); assertTrue("notif_idx_deliveries_slot index should exist", indexExists(db, "notif_idx_deliveries_slot")); db.close(); } /** * Test schema version management */ public void testSchemaVersion() { SQLiteDatabase db = database.getWritableDatabase(); // Check user_version android.database.Cursor cursor = db.rawQuery("PRAGMA user_version", null); assertTrue("Should have user_version result", cursor.moveToFirst()); int userVersion = cursor.getInt(0); assertEquals("User version should match database version", DailyNotificationDatabase.DATABASE_VERSION, userVersion); cursor.close(); db.close(); } /** * Test basic insert operations */ public void testBasicInsertOperations() { SQLiteDatabase db = database.getWritableDatabase(); // Test inserting into notif_contents android.content.ContentValues values = new android.content.ContentValues(); values.put(DailyNotificationDatabase.COL_CONTENTS_SLOT_ID, "test_slot_1"); values.put(DailyNotificationDatabase.COL_CONTENTS_PAYLOAD_JSON, "{\"title\":\"Test\"}"); values.put(DailyNotificationDatabase.COL_CONTENTS_FETCHED_AT, System.currentTimeMillis()); long rowId = db.insert(DailyNotificationDatabase.TABLE_NOTIF_CONTENTS, null, values); assertTrue("Insert should succeed", rowId > 0); // Test inserting into notif_config values.clear(); values.put(DailyNotificationDatabase.COL_CONFIG_K, "test_key"); values.put(DailyNotificationDatabase.COL_CONFIG_V, "test_value"); rowId = db.insert(DailyNotificationDatabase.TABLE_NOTIF_CONFIG, null, values); assertTrue("Config insert should succeed", rowId > 0); db.close(); } /** * Test database file operations */ public void testDatabaseFileOperations() { String dbPath = database.getDatabasePath(); assertNotNull("Database path should not be null", dbPath); assertTrue("Database path should not be empty", !dbPath.isEmpty()); // Database should exist after creation assertTrue("Database file should exist", database.databaseExists()); // Database size should be greater than 0 long size = database.getDatabaseSize(); assertTrue("Database size should be greater than 0", size > 0); } /** * Helper method to check if table exists */ private boolean tableExists(SQLiteDatabase db, String tableName) { android.database.Cursor cursor = db.rawQuery( "SELECT name FROM sqlite_master WHERE type='table' AND name=?", new String[]{tableName}); boolean exists = cursor.moveToFirst(); cursor.close(); return exists; } /** * Helper method to check if index exists */ private boolean indexExists(SQLiteDatabase db, String indexName) { android.database.Cursor cursor = db.rawQuery( "SELECT name FROM sqlite_master WHERE type='index' AND name=?", new String[]{indexName}); boolean exists = cursor.moveToFirst(); cursor.close(); return exists; } }