You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
8.0 KiB
217 lines
8.0 KiB
/**
|
|
* DailyNotificationTTLEnforcerTest.java
|
|
*
|
|
* Unit tests for TTL-at-fire enforcement functionality
|
|
* Tests freshness validation, TTL violation logging, and skip logic
|
|
*
|
|
* @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 DailyNotificationTTLEnforcer
|
|
*
|
|
* Tests the core TTL enforcement functionality including:
|
|
* - Freshness validation before arming
|
|
* - TTL violation detection and logging
|
|
* - Skip logic for stale content
|
|
* - Configuration retrieval from storage
|
|
*/
|
|
public class DailyNotificationTTLEnforcerTest extends AndroidTestCase {
|
|
|
|
private DailyNotificationTTLEnforcer ttlEnforcer;
|
|
private Context mockContext;
|
|
private DailyNotificationDatabase database;
|
|
|
|
@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 database instance
|
|
database = new DailyNotificationDatabase(mockContext);
|
|
|
|
// Create TTL enforcer with SQLite storage
|
|
ttlEnforcer = new DailyNotificationTTLEnforcer(mockContext, database, true);
|
|
}
|
|
|
|
@Override
|
|
protected void tearDown() throws Exception {
|
|
if (database != null) {
|
|
database.close();
|
|
}
|
|
super.tearDown();
|
|
}
|
|
|
|
/**
|
|
* Test freshness validation with fresh content
|
|
*/
|
|
public void testFreshContentValidation() {
|
|
long currentTime = System.currentTimeMillis();
|
|
long scheduledTime = currentTime + TimeUnit.MINUTES.toMillis(30); // 30 minutes from now
|
|
long fetchedAt = currentTime - TimeUnit.MINUTES.toMillis(5); // 5 minutes ago
|
|
|
|
boolean isFresh = ttlEnforcer.isContentFresh("test_slot_1", scheduledTime, fetchedAt);
|
|
|
|
assertTrue("Content should be fresh (5 min old, scheduled 30 min from now)", isFresh);
|
|
}
|
|
|
|
/**
|
|
* Test freshness validation with stale content
|
|
*/
|
|
public void testStaleContentValidation() {
|
|
long currentTime = System.currentTimeMillis();
|
|
long scheduledTime = currentTime + TimeUnit.MINUTES.toMillis(30); // 30 minutes from now
|
|
long fetchedAt = currentTime - TimeUnit.HOURS.toMillis(2); // 2 hours ago
|
|
|
|
boolean isFresh = ttlEnforcer.isContentFresh("test_slot_2", scheduledTime, fetchedAt);
|
|
|
|
assertFalse("Content should be stale (2 hours old, exceeds 1 hour TTL)", isFresh);
|
|
}
|
|
|
|
/**
|
|
* Test TTL violation detection
|
|
*/
|
|
public void testTTLViolationDetection() {
|
|
long currentTime = System.currentTimeMillis();
|
|
long scheduledTime = currentTime + TimeUnit.MINUTES.toMillis(30);
|
|
long fetchedAt = currentTime - TimeUnit.HOURS.toMillis(2); // 2 hours ago
|
|
|
|
// This should trigger a TTL violation
|
|
boolean isFresh = ttlEnforcer.isContentFresh("test_slot_3", scheduledTime, fetchedAt);
|
|
|
|
assertFalse("Should detect TTL violation", isFresh);
|
|
|
|
// Check that violation was logged (we can't easily test the actual logging,
|
|
// but we can verify the method returns false as expected)
|
|
}
|
|
|
|
/**
|
|
* Test validateBeforeArming with fresh content
|
|
*/
|
|
public void testValidateBeforeArmingFresh() {
|
|
long currentTime = System.currentTimeMillis();
|
|
long scheduledTime = currentTime + TimeUnit.MINUTES.toMillis(30);
|
|
long fetchedAt = currentTime - TimeUnit.MINUTES.toMillis(5);
|
|
|
|
NotificationContent content = new NotificationContent();
|
|
content.setId("test_slot_4");
|
|
content.setScheduledTime(scheduledTime);
|
|
content.setFetchedAt(fetchedAt);
|
|
content.setTitle("Test Notification");
|
|
content.setBody("Test body");
|
|
|
|
boolean shouldArm = ttlEnforcer.validateBeforeArming(content);
|
|
|
|
assertTrue("Should arm fresh content", shouldArm);
|
|
}
|
|
|
|
/**
|
|
* Test validateBeforeArming with stale content
|
|
*/
|
|
public void testValidateBeforeArmingStale() {
|
|
long currentTime = System.currentTimeMillis();
|
|
long scheduledTime = currentTime + TimeUnit.MINUTES.toMillis(30);
|
|
long fetchedAt = currentTime - TimeUnit.HOURS.toMillis(2);
|
|
|
|
NotificationContent content = new NotificationContent();
|
|
content.setId("test_slot_5");
|
|
content.setScheduledTime(scheduledTime);
|
|
content.setFetchedAt(fetchedAt);
|
|
content.setTitle("Test Notification");
|
|
content.setBody("Test body");
|
|
|
|
boolean shouldArm = ttlEnforcer.validateBeforeArming(content);
|
|
|
|
assertFalse("Should not arm stale content", shouldArm);
|
|
}
|
|
|
|
/**
|
|
* Test edge case: content fetched exactly at TTL limit
|
|
*/
|
|
public void testTTLBoundaryCase() {
|
|
long currentTime = System.currentTimeMillis();
|
|
long scheduledTime = currentTime + TimeUnit.MINUTES.toMillis(30);
|
|
long fetchedAt = currentTime - TimeUnit.HOURS.toMillis(1); // Exactly 1 hour ago (TTL limit)
|
|
|
|
boolean isFresh = ttlEnforcer.isContentFresh("test_slot_6", scheduledTime, fetchedAt);
|
|
|
|
assertTrue("Content at TTL boundary should be considered fresh", isFresh);
|
|
}
|
|
|
|
/**
|
|
* Test edge case: content fetched just over TTL limit
|
|
*/
|
|
public void testTTLBoundaryCaseOver() {
|
|
long currentTime = System.currentTimeMillis();
|
|
long scheduledTime = currentTime + TimeUnit.MINUTES.toMillis(30);
|
|
long fetchedAt = currentTime - TimeUnit.HOURS.toMillis(1) - TimeUnit.SECONDS.toMillis(1); // 1 hour + 1 second ago
|
|
|
|
boolean isFresh = ttlEnforcer.isContentFresh("test_slot_7", scheduledTime, fetchedAt);
|
|
|
|
assertFalse("Content just over TTL limit should be considered stale", isFresh);
|
|
}
|
|
|
|
/**
|
|
* Test TTL violation statistics
|
|
*/
|
|
public void testTTLViolationStats() {
|
|
// Generate some TTL violations
|
|
long currentTime = System.currentTimeMillis();
|
|
long scheduledTime = currentTime + TimeUnit.MINUTES.toMillis(30);
|
|
long fetchedAt = currentTime - TimeUnit.HOURS.toMillis(2);
|
|
|
|
// Trigger TTL violations
|
|
ttlEnforcer.isContentFresh("test_slot_8", scheduledTime, fetchedAt);
|
|
ttlEnforcer.isContentFresh("test_slot_9", scheduledTime, fetchedAt);
|
|
|
|
String stats = ttlEnforcer.getTTLViolationStats();
|
|
|
|
assertNotNull("TTL violation stats should not be null", stats);
|
|
assertTrue("Stats should contain violation count", stats.contains("violations"));
|
|
}
|
|
|
|
/**
|
|
* Test error handling with invalid parameters
|
|
*/
|
|
public void testErrorHandling() {
|
|
// Test with null slot ID
|
|
boolean result = ttlEnforcer.isContentFresh(null, System.currentTimeMillis(), System.currentTimeMillis());
|
|
assertFalse("Should handle null slot ID gracefully", result);
|
|
|
|
// Test with invalid timestamps
|
|
result = ttlEnforcer.isContentFresh("test_slot_10", 0, 0);
|
|
assertTrue("Should handle invalid timestamps gracefully", result);
|
|
}
|
|
|
|
/**
|
|
* Test TTL configuration retrieval
|
|
*/
|
|
public void testTTLConfiguration() {
|
|
// Test that TTL enforcer can retrieve configuration
|
|
// This is indirectly tested through the freshness checks
|
|
long currentTime = System.currentTimeMillis();
|
|
long scheduledTime = currentTime + TimeUnit.MINUTES.toMillis(30);
|
|
long fetchedAt = currentTime - TimeUnit.MINUTES.toMillis(30); // 30 minutes ago
|
|
|
|
boolean isFresh = ttlEnforcer.isContentFresh("test_slot_11", scheduledTime, fetchedAt);
|
|
|
|
// Should be fresh (30 min < 1 hour TTL)
|
|
assertTrue("Should retrieve TTL configuration correctly", isFresh);
|
|
}
|
|
}
|
|
|