/** * DailyNotificationRollingWindowTest.java * * Unit tests for rolling window safety functionality * Tests window maintenance, capacity management, and platform-specific limits * * @author Matthew Raymer * @version 1.0.0 */ package com.timesafari.dailynotification; import android.content.Context; import android.test.AndroidTestCase; import android.test.mock.MockContext; import java.util.concurrent.TimeUnit; /** * Unit tests for DailyNotificationRollingWindow * * Tests the rolling window safety functionality including: * - Window maintenance and state updates * - Capacity limit enforcement * - Platform-specific behavior (iOS vs Android) * - Statistics and maintenance timing */ public class DailyNotificationRollingWindowTest extends AndroidTestCase { private DailyNotificationRollingWindow rollingWindow; private Context mockContext; private DailyNotificationScheduler mockScheduler; private DailyNotificationTTLEnforcer mockTTLEnforcer; private DailyNotificationStorage mockStorage; @Override protected void setUp() throws Exception { super.setUp(); // Create mock context mockContext = new MockContext() { @Override public android.content.SharedPreferences getSharedPreferences(String name, int mode) { return getContext().getSharedPreferences(name, mode); } }; // Create mock components mockScheduler = new MockDailyNotificationScheduler(); mockTTLEnforcer = new MockDailyNotificationTTLEnforcer(); mockStorage = new MockDailyNotificationStorage(); // Create rolling window for Android platform rollingWindow = new DailyNotificationRollingWindow( mockContext, mockScheduler, mockTTLEnforcer, mockStorage, false // Android platform ); } @Override protected void tearDown() throws Exception { super.tearDown(); } /** * Test rolling window initialization */ public void testRollingWindowInitialization() { assertNotNull("Rolling window should be initialized", rollingWindow); // Test Android platform limits String stats = rollingWindow.getRollingWindowStats(); assertNotNull("Stats should not be null", stats); assertTrue("Stats should contain Android platform info", stats.contains("Android")); } /** * Test rolling window maintenance */ public void testRollingWindowMaintenance() { // Test that maintenance can be forced rollingWindow.forceMaintenance(); // Test maintenance timing assertFalse("Maintenance should not be needed immediately after forcing", rollingWindow.isMaintenanceNeeded()); // Test time until next maintenance long timeUntilNext = rollingWindow.getTimeUntilNextMaintenance(); assertTrue("Time until next maintenance should be positive", timeUntilNext > 0); } /** * Test iOS platform behavior */ public void testIOSPlatformBehavior() { // Create rolling window for iOS platform DailyNotificationRollingWindow iosRollingWindow = new DailyNotificationRollingWindow( mockContext, mockScheduler, mockTTLEnforcer, mockStorage, true // iOS platform ); String stats = iosRollingWindow.getRollingWindowStats(); assertNotNull("iOS stats should not be null", stats); assertTrue("Stats should contain iOS platform info", stats.contains("iOS")); } /** * Test maintenance timing */ public void testMaintenanceTiming() { // Initially, maintenance should not be needed assertFalse("Maintenance should not be needed initially", rollingWindow.isMaintenanceNeeded()); // Force maintenance rollingWindow.forceMaintenance(); // Should not be needed immediately after assertFalse("Maintenance should not be needed after forcing", rollingWindow.isMaintenanceNeeded()); } /** * Test statistics retrieval */ public void testStatisticsRetrieval() { String stats = rollingWindow.getRollingWindowStats(); assertNotNull("Statistics should not be null", stats); assertTrue("Statistics should contain pending count", stats.contains("pending")); assertTrue("Statistics should contain daily count", stats.contains("daily")); assertTrue("Statistics should contain platform info", stats.contains("platform")); } /** * Test error handling */ public void testErrorHandling() { // Test with null components (should not crash) try { DailyNotificationRollingWindow errorWindow = new DailyNotificationRollingWindow( null, null, null, null, false ); // Should not crash during construction } catch (Exception e) { // Expected to handle gracefully } } /** * Mock DailyNotificationScheduler for testing */ private static class MockDailyNotificationScheduler extends DailyNotificationScheduler { public MockDailyNotificationScheduler() { super(null, null); } @Override public boolean scheduleNotification(NotificationContent content) { return true; // Always succeed for testing } } /** * Mock DailyNotificationTTLEnforcer for testing */ private static class MockDailyNotificationTTLEnforcer extends DailyNotificationTTLEnforcer { public MockDailyNotificationTTLEnforcer() { super(null, null, false); } @Override public boolean validateBeforeArming(NotificationContent content) { return true; // Always pass validation for testing } } /** * Mock DailyNotificationStorage for testing */ private static class MockDailyNotificationStorage extends DailyNotificationStorage { public MockDailyNotificationStorage() { super(null); } } }