diff --git a/tests/test_trials.py b/tests/test_trials.py index 21df0fb..8029fe3 100644 --- a/tests/test_trials.py +++ b/tests/test_trials.py @@ -25,3 +25,31 @@ def test_start_trial_is_idempotent_resets(tracker): tracker.start_trial("Some-Pack") tracker.start_trial("Some-Pack") assert len(tracker.get_trials()) == 1 + + +def _ahead(days): + return datetime.now(timezone.utc) + timedelta(days=days) + + +def test_tick_increments_only_on_new_day(tracker): + tracker.start_trial("Pack") # enable day, counter 0 + tracker.tick_boot_days() # same day -> no change + assert tracker.get_trials()[0]["unused_boot_days"] == 0 + + with patch("tracker.datetime") as m: + m.now.return_value = _ahead(1) + tracker.tick_boot_days() # new day -> 1 + tracker.tick_boot_days() # same (mocked) day -> still 1 + assert tracker.get_trials()[0]["unused_boot_days"] == 1 + + +def test_tick_reaches_expiry(tracker): + tracker.start_trial("Pack") + for d in range(1, DEFAULT_TRIAL_BUDGET + 1): + with patch("tracker.datetime") as m: + m.now.return_value = _ahead(d) + tracker.tick_boot_days() + t = tracker.get_trials()[0] + assert t["unused_boot_days"] == DEFAULT_TRIAL_BUDGET + assert t["expired"] is True + assert t["days_remaining"] == 0 diff --git a/tracker.py b/tracker.py index ef27109..76ce991 100644 --- a/tracker.py +++ b/tracker.py @@ -432,6 +432,24 @@ class UsageTracker: result.append(d) return result + def tick_boot_days(self): + """Once per distinct calendar day, age every active trial by one boot-day.""" + today = datetime.now(timezone.utc).date().isoformat() + with self._lock: + self._ensure_db() + conn = self._connect() + try: + conn.execute( + """UPDATE trial_packages + SET unused_boot_days = unused_boot_days + 1, + last_boot_day = ? + WHERE last_boot_day != ?""", + (today, today), + ) + conn.commit() + finally: + conn.close() + def reset(self): """Clear all tracked data.""" with self._lock: