I've attached a draft patch. This is the first time I'm building a unit test file from scratch so I tried to follow the examples in other files. If we add more unit tests it might be worth creating some macros and helper functions, but I didn't want to overdo it on the first round.
Cheers, Derek On Sun, Sep 20, 2026 at 12:19 PM Ihor Radchenko <[email protected]> wrote: > Derek Chen-Becker <[email protected]> writes: > > > It definitely looks like a bug. > > Yes, looks like a bug. > > > Ihor, I think you touched this last. I don't see any unit tests for > > org-persist, but I'm not sure if maybe I'm missing something. I'm happy > to > > add a new unit test file if needed. > > Unit tests would be welcome. > > -- > Ihor Radchenko // yantar92, > Org mode maintainer, > Learn more about Org mode at <https://orgmode.org/>. > Support Org development at <https://liberapay.com/org-mode>, > or support my work at <https://liberapay.com/yantar92> > -- +---------------------------------------------------------------+ | Derek Chen-Becker | | GPG Key available at https://keybase.io/dchenbecker and | | https://pgp.mit.edu/pks/lookup?search=derek%40chen-becker.org | | Fngrprnt: EB8A 6480 F0A3 C8EB C1E7 7F42 AFC5 AFEE 96E4 6ACC | +---------------------------------------------------------------+
From 8d2064c96722fe22082ed3ffbf2172436b114fa2 Mon Sep 17 00:00:00 2001 From: Derek Chen-Becker <[email protected]> Date: Sun, 20 Sep 2026 20:44:27 -0600 Subject: [PATCH] org-persist: Fix inverted GC age calculation Compute the age of each GC record by subtracting its time from the current time (inverted in the previous version). * lisp/org-persist.el (org-persist--refresh-gc-lock): Change age computation to properly compare against the current time. Also simplify the age computation by using time-subtract instead of float arithmetic. * testing/lisp/test-org-persist.el: Add a new unit test file for org-persist, along with a unit test specifically for `org-persist--refresh-gc-lock'. --- lisp/org-persist.el | 6 ++-- testing/lisp/test-org-persist.el | 53 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 testing/lisp/test-org-persist.el diff --git a/lisp/org-persist.el b/lisp/org-persist.el index 9f3edab82..ee3799ed1 100644 --- a/lisp/org-persist.el +++ b/lisp/org-persist.el @@ -1272,9 +1272,9 @@ Remove expired sessions timestamps." (setf (alist-get before-init-time alist nil nil #'equal) (current-time)) (dolist (record alist) - (when (< (- (float-time (cdr record)) (float-time (current-time))) - org-persist-gc-lock-expiry) - (push record new-alist))) + (let ((age (float-time (time-subtract nil (cdr record))))) + (when (< age org-persist-gc-lock-expiry) + (push record new-alist)))) (ignore-errors (org-persist--write-elisp-file file new-alist))))) (defun org-persist--gc-orphan-p () diff --git a/testing/lisp/test-org-persist.el b/testing/lisp/test-org-persist.el new file mode 100644 index 000000000..c792c4726 --- /dev/null +++ b/testing/lisp/test-org-persist.el @@ -0,0 +1,53 @@ +;;; test-org-persist.el --- Tests for org-persist.el -*- lexical-binding: t; -*- + +;; Copyright (C) 2026, Derek Chen-Becker + +;; Author: Derek Chen-Becker <oss at chen-becker dot org> + +;; This file is not part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + + +;;; Commentary: +;; + +;;; Code: + +(require 'org-test "../testing/org-test") + +(ert-deftest test-org-persist/refresh-gc-lock () + "Test that the GC lock refresh properly handles valid and expired sessions." + (let* ((org-persist-gc-lock-expiry 60) ;; Set expiry to keep test data simple + (org-persist--wrote-to-disk t) ;; Make sure we actually trigger GC + (test-directory (make-temp-file "org-persist-test" t)) + (org-persist-directory test-directory) + (lockfile (concat test-directory "/" org-persist-gc-lock-file)) + ;; Started 42 seconds ago, should stay + (current-record `(,(time-subtract nil 42) . ,(current-time))) + ;; Ended 95 seconds ago, should be expired + (expired-record `(,(time-subtract nil 120) . ,(time-subtract nil 95)))) + (unwind-protect + (progn + (org-persist--write-elisp-file lockfile (list current-record expired-record)) + (org-persist--refresh-gc-lock) + ;; Now re-read the lock file and ensure that all entries are current now + (dolist (record (org-persist--read-elisp-file lockfile)) + (should-not + (> (float-time (time-subtract nil (cdr record))) + org-persist-gc-lock-expiry)))) + (delete-directory test-directory t)))) + +(provide 'test-org-persist) +;;; test-org-persist.el ends here -- 2.43.0
