summaryrefslogtreecommitdiff
path: root/tests/test-org-agenda-build-list.el
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test-org-agenda-build-list.el')
-rw-r--r--tests/test-org-agenda-build-list.el294
1 files changed, 0 insertions, 294 deletions
diff --git a/tests/test-org-agenda-build-list.el b/tests/test-org-agenda-build-list.el
deleted file mode 100644
index 6b424200..00000000
--- a/tests/test-org-agenda-build-list.el
+++ /dev/null
@@ -1,294 +0,0 @@
-;;; test-org-agenda-build-list.el --- Tests for cj/build-org-agenda-list -*- lexical-binding: t; -*-
-
-;;; Commentary:
-;; Unit tests for cj/build-org-agenda-list caching logic.
-;; Tests cache behavior, TTL expiration, force rebuild, and async build flag.
-
-;;; Code:
-
-(require 'ert)
-
-;; Add modules to load path
-(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
-
-;; Stub dependencies before loading the module
-(defvar inbox-file "/tmp/test-inbox.org")
-(defvar schedule-file "/tmp/test-schedule.org")
-(defvar gcal-file "/tmp/test-gcal.org")
-(defvar projects-dir "/tmp/test-projects/")
-
-;; Now load the actual production module
-(require 'org-agenda-config)
-
-;;; Setup and Teardown
-
-(defun test-org-agenda-setup ()
- "Reset cache and state before each test."
- (setq cj/org-agenda-files-cache nil)
- (setq cj/org-agenda-files-cache-time nil)
- (setq cj/org-agenda-files-building nil)
- (setq org-agenda-files nil))
-
-(defun test-org-agenda-teardown ()
- "Clean up after each test."
- (setq cj/org-agenda-files-cache nil)
- (setq cj/org-agenda-files-cache-time nil)
- (setq cj/org-agenda-files-building nil)
- (setq org-agenda-files nil))
-
-;;; Normal Cases
-
-(ert-deftest test-org-agenda-build-list-normal-first-call-builds-cache ()
- "Test that first call builds cache from scratch.
-
-When cache is empty, function should:
-1. Scan directory for todo.org files
-2. Build agenda files list
-3. Populate cache
-4. Set cache timestamp"
- (test-org-agenda-setup)
- (unwind-protect
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern &optional _include-dirs) '("/tmp/project/todo.org"))))
-
- ;; Before call: cache empty
- (should (null cj/org-agenda-files-cache))
- (should (null cj/org-agenda-files-cache-time))
-
- ;; Build agenda files
- (cj/build-org-agenda-list)
-
- ;; After call: cache populated
- (should cj/org-agenda-files-cache)
- (should cj/org-agenda-files-cache-time)
- (should org-agenda-files)
-
- ;; Cache matches org-agenda-files
- (should (equal cj/org-agenda-files-cache org-agenda-files))
-
- ;; Contains base files (inbox, schedule, gcal) plus project files
- (should (>= (length org-agenda-files) 3)))
- (test-org-agenda-teardown)))
-
-(ert-deftest test-org-agenda-build-list-normal-second-call-uses-cache ()
- "Test that second call uses cache instead of rebuilding.
-
-When cache is valid (not expired):
-1. Should NOT scan directories again
-2. Should restore files from cache
-3. Should NOT update cache timestamp"
- (test-org-agenda-setup)
- (unwind-protect
- (let ((scan-count 0))
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern &optional _include-dirs)
- (setq scan-count (1+ scan-count))
- '("/tmp/project/todo.org"))))
-
- ;; First call: builds cache
- (cj/build-org-agenda-list)
- (should (= scan-count 1)) ; 1 directory scanned
-
- (let ((cached-time cj/org-agenda-files-cache-time)
- (cached-files cj/org-agenda-files-cache))
-
- ;; Second call: uses cache
- (cj/build-org-agenda-list)
-
- ;; Scan count unchanged (cache hit)
- (should (= scan-count 1))
-
- ;; Cache unchanged
- (should (equal cj/org-agenda-files-cache-time cached-time))
- (should (equal cj/org-agenda-files-cache cached-files)))))
- (test-org-agenda-teardown)))
-
-(ert-deftest test-org-agenda-build-list-normal-force-rebuild-bypasses-cache ()
- "Test that force-rebuild parameter bypasses cache.
-
-When force-rebuild is non-nil:
-1. Should ignore valid cache
-2. Should rebuild from scratch
-3. Should update cache with new data"
- (test-org-agenda-setup)
- (unwind-protect
- (let ((scan-count 0))
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern &optional _include-dirs)
- (setq scan-count (1+ scan-count))
- (if (> scan-count 1)
- '("/tmp/project/todo.org" "/tmp/project2/todo.org") ; New file on rebuild
- '("/tmp/project/todo.org")))))
-
- ;; First call: builds cache
- (cj/build-org-agenda-list)
- (let ((initial-count (length org-agenda-files)))
-
- ;; Force rebuild
- (cj/build-org-agenda-list 'force)
-
- ;; Scanned again
- (should (= scan-count 2))
-
- ;; New files include additional project
- (should (> (length org-agenda-files) initial-count)))))
- (test-org-agenda-teardown)))
-
-;;; Boundary Cases
-
-(ert-deftest test-org-agenda-build-list-boundary-cache-expires-after-ttl ()
- "Test that cache expires after TTL period.
-
-When cache timestamp exceeds TTL:
-1. Should rebuild files list
-2. Should update cache timestamp
-3. Should rescan directory"
- (test-org-agenda-setup)
- (unwind-protect
- (let ((scan-count 0))
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern &optional _include-dirs)
- (setq scan-count (1+ scan-count))
- '("/tmp/project/todo.org"))))
-
- ;; First call: builds cache
- (cj/build-org-agenda-list)
- (should (= scan-count 1))
-
- ;; Simulate cache expiration (set time to 2 hours ago)
- (setq cj/org-agenda-files-cache-time
- (- (float-time) (* 2 3600)))
-
- ;; Second call: cache expired, rebuild
- (cj/build-org-agenda-list)
-
- ;; Scanned again (cache was expired)
- (should (= scan-count 2))
-
- ;; Cache timestamp updated to current time
- (should (< (- (float-time) cj/org-agenda-files-cache-time) 1))))
- (test-org-agenda-teardown)))
-
-(ert-deftest test-org-agenda-build-list-boundary-empty-directory-creates-minimal-list ()
- "Test behavior when directory contains no todo.org files.
-
-When directory scan returns empty:
-1. Should still create base files (inbox, schedule)
-2. Should not fail or error
-3. Should cache the minimal result"
- (test-org-agenda-setup)
- (unwind-protect
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern &optional _include-dirs) nil))) ; No files found
-
- (cj/build-org-agenda-list)
-
- ;; Should have base files only (inbox, schedule, gcal)
- (should (= (length org-agenda-files) 3))
-
- ;; Cache should contain base files
- (should cj/org-agenda-files-cache)
- (should (= (length cj/org-agenda-files-cache) 3)))
- (test-org-agenda-teardown)))
-
-(ert-deftest test-org-agenda-build-list-boundary-building-flag-set-during-build ()
- "Test that building flag is set during build and cleared after.
-
-During build:
-1. Flag should be set to prevent concurrent builds
-2. Flag should clear even if build fails
-3. Flag state should be consistent"
- (test-org-agenda-setup)
- (unwind-protect
- (let ((flag-during-build nil))
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern &optional _include-dirs)
- ;; Capture flag state during directory scan
- (setq flag-during-build cj/org-agenda-files-building)
- '("/tmp/project/todo.org"))))
-
- ;; Before build
- (should (null cj/org-agenda-files-building))
-
- ;; Build
- (cj/build-org-agenda-list)
-
- ;; Flag was set during build
- (should flag-during-build)
-
- ;; Flag cleared after build
- (should (null cj/org-agenda-files-building))))
- (test-org-agenda-teardown)))
-
-(ert-deftest test-org-agenda-build-list-boundary-building-flag-clears-on-error ()
- "Test that building flag clears even if build errors.
-
-When build encounters error:
-1. Flag should still be cleared (unwind-protect)
-2. Prevents permanently locked state
-3. Next build can proceed"
- (test-org-agenda-setup)
- (unwind-protect
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern &optional _include-dirs)
- (error "Simulated scan failure"))))
-
- ;; Build will error
- (should-error (cj/build-org-agenda-list))
-
- ;; Flag cleared despite error (unwind-protect)
- (should (null cj/org-agenda-files-building)))
- (test-org-agenda-teardown)))
-
-;;; Error Cases
-
-(ert-deftest test-org-agenda-build-list-error-nil-cache-with-old-timestamp ()
- "Test handling of inconsistent state (nil cache but timestamp set).
-
-When cache is nil but timestamp exists:
-1. Should recognize cache as invalid
-2. Should rebuild files list
-3. Should set both cache and timestamp"
- (test-org-agenda-setup)
- (unwind-protect
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern &optional _include-dirs) '("/tmp/project/todo.org"))))
-
- ;; Set inconsistent state
- (setq cj/org-agenda-files-cache nil)
- (setq cj/org-agenda-files-cache-time (float-time))
-
- ;; Build should recognize invalid state
- (cj/build-org-agenda-list)
-
- ;; Cache now populated
- (should cj/org-agenda-files-cache)
- (should cj/org-agenda-files-cache-time)
- (should org-agenda-files))
- (test-org-agenda-teardown)))
-
-(ert-deftest test-org-agenda-build-list-error-directory-scan-failure-propagates ()
- "Test that directory scan failures propagate as errors.
-
-When directory-files-recursively errors:
-1. Error should propagate to caller
-2. Cache should not be corrupted
-3. Building flag should clear"
- (test-org-agenda-setup)
- (unwind-protect
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern &optional _include-dirs)
- (error "Permission denied"))))
-
- ;; Should propagate error
- (should-error (cj/build-org-agenda-list))
-
- ;; Cache not corrupted (still nil)
- (should (null cj/org-agenda-files-cache))
-
- ;; Building flag cleared
- (should (null cj/org-agenda-files-building)))
- (test-org-agenda-teardown)))
-
-(provide 'test-org-agenda-build-list)
-;;; test-org-agenda-build-list.el ends here