From 4cd1e8e63d885d8de2728dc76d4f35f0eb597037 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Tue, 28 Apr 2026 14:21:18 -0500 Subject: test: add gloss-core test suite (red phase) The commit lands eight per-function test files and a shared testutil. 32 tests across Normal/Boundary/Error categories cover the public API (lookup, save, list, find-buffer-position) and the internals that need observable behavior tests (mtime invalidation, corrupt-file resilience, alphabetical insert, first-call file creation). All 32 fail with void-function on the gloss-core symbols. That is the intended red-phase signal. The next commit lands the implementation that turns them green. testutil-gloss provides a with-temp-glossary macro. It binds gloss-file to a temp file, resets the cache before and after, and cleans up the visiting buffer. --- tests/test-gloss-core--alphabetical-insert.el | 42 +++++++++++ ...est-gloss-core--corrupt-file-preserves-cache.el | 32 +++++++++ tests/test-gloss-core--find-buffer-position.el | 49 +++++++++++++ tests/test-gloss-core--first-call-creates-file.el | 56 +++++++++++++++ tests/test-gloss-core--invalidate-on-mtime.el | 49 +++++++++++++ tests/test-gloss-core--list.el | 36 ++++++++++ tests/test-gloss-core--lookup.el | 73 +++++++++++++++++++ tests/test-gloss-core--save.el | 82 ++++++++++++++++++++++ tests/testutil-gloss.el | 62 ++++++++++++++++ 9 files changed, 481 insertions(+) create mode 100644 tests/test-gloss-core--alphabetical-insert.el create mode 100644 tests/test-gloss-core--corrupt-file-preserves-cache.el create mode 100644 tests/test-gloss-core--find-buffer-position.el create mode 100644 tests/test-gloss-core--first-call-creates-file.el create mode 100644 tests/test-gloss-core--invalidate-on-mtime.el create mode 100644 tests/test-gloss-core--list.el create mode 100644 tests/test-gloss-core--lookup.el create mode 100644 tests/test-gloss-core--save.el create mode 100644 tests/testutil-gloss.el diff --git a/tests/test-gloss-core--alphabetical-insert.el b/tests/test-gloss-core--alphabetical-insert.el new file mode 100644 index 0000000..69c6c95 --- /dev/null +++ b/tests/test-gloss-core--alphabetical-insert.el @@ -0,0 +1,42 @@ +;;; test-gloss-core--alphabetical-insert.el --- Tests for alphabetical insert -*- lexical-binding: t -*- + +;; SPDX-License-Identifier: GPL-3.0-or-later + +;;; Commentary: +;; Tests that `gloss-core-save' inserts new entries at the correct +;; alphabetical position (case-insensitive ordering). + +;;; Code: + +(require 'ert) +(require 'gloss-core) +(require 'testutil-gloss) + +(ert-deftest test-gloss-core-alphabetical-insert-correct-position () + "Normal: terms saved out of order land in alphabetical order." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (gloss-core-save "Charlie" "Third." 'manual) + (gloss-core-save "Alpha" "First." 'manual) + (gloss-core-save "Bravo" "Second." 'manual) + (should (equal (gloss-core-list) '("Alpha" "Bravo" "Charlie"))))) + +(ert-deftest test-gloss-core-alphabetical-insert-case-insensitive-ordering () + "Boundary: ordering uses a case-insensitive compare." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (gloss-core-save "banana" "Fruit." 'manual) + (gloss-core-save "Apple" "Also fruit." 'manual) + (should (equal (gloss-core-list) '("Apple" "banana"))))) + +(ert-deftest test-gloss-core-alphabetical-insert-on-disk-matches-list () + "Boundary: the on-disk file order matches the list order." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (gloss-core-save "zebra" "Last." 'manual) + (gloss-core-save "alpha" "First." 'manual) + (let ((file-content (with-temp-buffer + (insert-file-contents gloss-file) + (buffer-string)))) + (should (< (string-match "^\\* alpha" file-content) + (string-match "^\\* zebra" file-content)))))) + +(provide 'test-gloss-core--alphabetical-insert) +;;; test-gloss-core--alphabetical-insert.el ends here diff --git a/tests/test-gloss-core--corrupt-file-preserves-cache.el b/tests/test-gloss-core--corrupt-file-preserves-cache.el new file mode 100644 index 0000000..6cc6cfc --- /dev/null +++ b/tests/test-gloss-core--corrupt-file-preserves-cache.el @@ -0,0 +1,32 @@ +;;; test-gloss-core--corrupt-file-preserves-cache.el --- Tests for corrupt-file resilience -*- lexical-binding: t -*- + +;; SPDX-License-Identifier: GPL-3.0-or-later + +;;; Commentary: +;; Tests that a parser failure during cache reload does not destroy the +;; existing cache; previously-cached lookups still succeed and the user +;; sees an informative message. + +;;; Code: + +(require 'cl-lib) +(require 'ert) +(require 'gloss-core) +(require 'testutil-gloss) + +(ert-deftest test-gloss-core-corrupt-file-preserves-existing-cache () + "Error: parser failure during reload preserves the existing cache." + (gloss-test--with-temp-glossary gloss-test--sample-content + ;; Prime cache. + (should (gloss-core-lookup "anaphora")) + ;; Force mtime change to trigger a reload attempt. + (set-file-times gloss-file (time-add (current-time) 5)) + ;; Mock the parse helper to fail. + (cl-letf (((symbol-function 'gloss-core--parse-file-into-cache) + (lambda () (error "simulated parse failure")))) + (let ((inhibit-message t)) + ;; Lookup must not propagate the error; cached entry remains findable. + (should (gloss-core-lookup "anaphora")))))) + +(provide 'test-gloss-core--corrupt-file-preserves-cache) +;;; test-gloss-core--corrupt-file-preserves-cache.el ends here diff --git a/tests/test-gloss-core--find-buffer-position.el b/tests/test-gloss-core--find-buffer-position.el new file mode 100644 index 0000000..1e63309 --- /dev/null +++ b/tests/test-gloss-core--find-buffer-position.el @@ -0,0 +1,49 @@ +;;; test-gloss-core--find-buffer-position.el --- Tests for gloss-core-find-buffer-position -*- lexical-binding: t -*- + +;; SPDX-License-Identifier: GPL-3.0-or-later + +;;; Commentary: +;; Tests for `gloss-core-find-buffer-position' covering N/B/E cases. + +;;; Code: + +(require 'ert) +(require 'gloss-core) +(require 'testutil-gloss) + +(ert-deftest test-gloss-core-find-buffer-position-existing-term-returns-marker () + "Normal: returns a marker pointing at the term's heading." + (gloss-test--with-temp-glossary gloss-test--sample-content + (let ((marker (gloss-core-find-buffer-position "anaphora"))) + (should (markerp marker)) + (with-current-buffer (marker-buffer marker) + (goto-char marker) + (should (looking-at-p "^\\* anaphora")))))) + +(ert-deftest test-gloss-core-find-buffer-position-second-term-returns-marker () + "Normal: marker for second term points at its heading, not the first." + (gloss-test--with-temp-glossary gloss-test--sample-content + (let ((marker (gloss-core-find-buffer-position "SBIR"))) + (should (markerp marker)) + (with-current-buffer (marker-buffer marker) + (goto-char marker) + (should (looking-at-p "^\\* SBIR")))))) + +(ert-deftest test-gloss-core-find-buffer-position-missing-term-returns-nil () + "Boundary: returns nil for a term not in the glossary." + (gloss-test--with-temp-glossary gloss-test--sample-content + (should-not (gloss-core-find-buffer-position "nonexistent")))) + +(ert-deftest test-gloss-core-find-buffer-position-missing-file-returns-nil () + "Error: returns nil when the file does not exist." + (let ((gloss-file (concat temporary-file-directory "gloss-pos-nonexistent-" + (number-to-string (random 100000)) ".org"))) + (unwind-protect + (progn + (gloss-core--cache-reset) + (should-not (gloss-core-find-buffer-position "any"))) + (gloss-core--cache-reset) + (when (file-exists-p gloss-file) (delete-file gloss-file))))) + +(provide 'test-gloss-core--find-buffer-position) +;;; test-gloss-core--find-buffer-position.el ends here diff --git a/tests/test-gloss-core--first-call-creates-file.el b/tests/test-gloss-core--first-call-creates-file.el new file mode 100644 index 0000000..e168435 --- /dev/null +++ b/tests/test-gloss-core--first-call-creates-file.el @@ -0,0 +1,56 @@ +;;; test-gloss-core--first-call-creates-file.el --- Tests for first-save creates file -*- lexical-binding: t -*- + +;; SPDX-License-Identifier: GPL-3.0-or-later + +;;; Commentary: +;; Tests that `gloss-core-save' creates `gloss-file' (and any missing +;; parent directory) on first call. + +;;; Code: + +(require 'ert) +(require 'gloss-core) +(require 'testutil-gloss) + +(ert-deftest test-gloss-core-save-creates-file-when-missing () + "Normal: first save creates the file with a TITLE header." + (let ((gloss-file (concat temporary-file-directory "gloss-create-" + (number-to-string (random 100000)) ".org"))) + (unwind-protect + (progn + (gloss-core--cache-reset) + (should-not (file-exists-p gloss-file)) + (gloss-core-save "anaphora" "Reference earlier." 'manual) + (should (file-exists-p gloss-file)) + (let ((content (with-temp-buffer + (insert-file-contents gloss-file) + (buffer-string)))) + (should (string-match-p "#\\+TITLE:" content)) + (should (string-match-p "^\\* anaphora" content)))) + (gloss-core--cache-reset) + (when-let ((buf (find-buffer-visiting gloss-file))) + (with-current-buffer buf (set-buffer-modified-p nil)) + (kill-buffer buf)) + (when (file-exists-p gloss-file) (delete-file gloss-file))))) + +(ert-deftest test-gloss-core-save-creates-parent-directory () + "Boundary: first save creates missing parent directory." + (let* ((parent (concat temporary-file-directory "gloss-newdir-" + (number-to-string (random 100000)))) + (gloss-file (concat parent "/gloss.org"))) + (unwind-protect + (progn + (gloss-core--cache-reset) + (should-not (file-exists-p parent)) + (gloss-core-save "anaphora" "Reference earlier." 'manual) + (should (file-exists-p parent)) + (should (file-exists-p gloss-file))) + (gloss-core--cache-reset) + (when-let ((buf (find-buffer-visiting gloss-file))) + (with-current-buffer buf (set-buffer-modified-p nil)) + (kill-buffer buf)) + (when (file-exists-p gloss-file) (delete-file gloss-file)) + (when (file-directory-p parent) (delete-directory parent))))) + +(provide 'test-gloss-core--first-call-creates-file) +;;; test-gloss-core--first-call-creates-file.el ends here diff --git a/tests/test-gloss-core--invalidate-on-mtime.el b/tests/test-gloss-core--invalidate-on-mtime.el new file mode 100644 index 0000000..69500dd --- /dev/null +++ b/tests/test-gloss-core--invalidate-on-mtime.el @@ -0,0 +1,49 @@ +;;; test-gloss-core--invalidate-on-mtime.el --- Tests for cache mtime invalidation -*- lexical-binding: t -*- + +;; SPDX-License-Identifier: GPL-3.0-or-later + +;;; Commentary: +;; Tests that the cache reloads when `gloss-file' is edited out-of-band. + +;;; Code: + +(require 'ert) +(require 'gloss-core) +(require 'testutil-gloss) + +(ert-deftest test-gloss-core-invalidate-on-mtime-new-content-detected () + "Normal: out-of-band edit + later lookup sees the new content." + (gloss-test--with-temp-glossary gloss-test--sample-content + ;; Prime cache. + (should (gloss-core-lookup "anaphora")) + ;; Append a new entry directly to disk. + (with-temp-buffer + (insert-file-contents gloss-file) + (goto-char (point-max)) + (insert "\n* hapax\n:PROPERTIES:\n:SOURCE: manual\n:ADDED: 2026-04-28\n:END:\nA word used only once in a corpus.\n") + (write-region (point-min) (point-max) gloss-file)) + ;; Force mtime change to be visible (1-second granularity on some FSes). + (set-file-times gloss-file (time-add (current-time) 5)) + ;; Lookup detects the mtime change and reloads. + (let ((entry (gloss-core-lookup "hapax"))) + (should entry) + (should (string-match-p "used only once" (plist-get entry :body)))))) + +(ert-deftest test-gloss-core-invalidate-on-mtime-unchanged-uses-cache () + "Boundary: unchanged mtime — two consecutive lookups both succeed." + (gloss-test--with-temp-glossary gloss-test--sample-content + (should (gloss-core-lookup "anaphora")) + (should (gloss-core-lookup "anaphora")))) + +(ert-deftest test-gloss-core-invalidate-on-mtime-deleted-file-clears-cache () + "Error: file deleted out-of-band — subsequent lookup returns nil." + (gloss-test--with-temp-glossary gloss-test--sample-content + (should (gloss-core-lookup "anaphora")) + (when-let ((buf (find-buffer-visiting gloss-file))) + (with-current-buffer buf (set-buffer-modified-p nil)) + (kill-buffer buf)) + (delete-file gloss-file) + (should-not (gloss-core-lookup "anaphora")))) + +(provide 'test-gloss-core--invalidate-on-mtime) +;;; test-gloss-core--invalidate-on-mtime.el ends here diff --git a/tests/test-gloss-core--list.el b/tests/test-gloss-core--list.el new file mode 100644 index 0000000..22c988e --- /dev/null +++ b/tests/test-gloss-core--list.el @@ -0,0 +1,36 @@ +;;; test-gloss-core--list.el --- Tests for gloss-core-list -*- lexical-binding: t -*- + +;; SPDX-License-Identifier: GPL-3.0-or-later + +;;; Commentary: +;; Tests for `gloss-core-list' covering Normal/Boundary/Error cases. + +;;; Code: + +(require 'ert) +(require 'gloss-core) +(require 'testutil-gloss) + +(ert-deftest test-gloss-core-list-returns-all-terms-alphabetically () + "Normal: list returns all terms in case-insensitive alphabetical order." + (gloss-test--with-temp-glossary gloss-test--sample-content + (should (equal (gloss-core-list) '("anaphora" "SBIR"))))) + +(ert-deftest test-gloss-core-list-empty-glossary-returns-nil () + "Boundary: list against an empty file returns nil." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (should-not (gloss-core-list)))) + +(ert-deftest test-gloss-core-list-missing-file-returns-nil () + "Error: list before any save returns nil (file does not exist)." + (let ((gloss-file (concat temporary-file-directory "gloss-list-nonexistent-" + (number-to-string (random 100000)) ".org"))) + (unwind-protect + (progn + (gloss-core--cache-reset) + (should-not (gloss-core-list))) + (gloss-core--cache-reset) + (when (file-exists-p gloss-file) (delete-file gloss-file))))) + +(provide 'test-gloss-core--list) +;;; test-gloss-core--list.el ends here diff --git a/tests/test-gloss-core--lookup.el b/tests/test-gloss-core--lookup.el new file mode 100644 index 0000000..a1986a7 --- /dev/null +++ b/tests/test-gloss-core--lookup.el @@ -0,0 +1,73 @@ +;;; test-gloss-core--lookup.el --- Tests for gloss-core-lookup -*- lexical-binding: t -*- + +;; SPDX-License-Identifier: GPL-3.0-or-later + +;;; Commentary: +;; Tests for `gloss-core-lookup' covering Normal/Boundary/Error cases. + +;;; Code: + +(require 'ert) +(require 'gloss-core) +(require 'testutil-gloss) + +(ert-deftest test-gloss-core-lookup-existing-term-returns-entry () + "Normal: lookup of saved term returns entry plist with all fields." + (gloss-test--with-temp-glossary gloss-test--sample-content + (let ((entry (gloss-core-lookup "anaphora"))) + (should entry) + (should (equal (plist-get entry :term) "anaphora")) + (should (string-match-p "Reference to something earlier" + (plist-get entry :body))) + (should (eq (plist-get entry :source) 'wiktionary)) + (should (equal (plist-get entry :added) "2026-04-28"))))) + +(ert-deftest test-gloss-core-lookup-includes-marker () + "Normal: lookup result includes a :marker field at the heading." + (gloss-test--with-temp-glossary gloss-test--sample-content + (let* ((entry (gloss-core-lookup "anaphora")) + (marker (plist-get entry :marker))) + (should (markerp marker)) + (with-current-buffer (marker-buffer marker) + (goto-char marker) + (should (looking-at-p "^\\* anaphora")))))) + +(ert-deftest test-gloss-core-lookup-missing-term-returns-nil () + "Normal: lookup of unsaved term returns nil." + (gloss-test--with-temp-glossary gloss-test--sample-content + (should-not (gloss-core-lookup "nonexistent-term")))) + +(ert-deftest test-gloss-core-lookup-empty-string-returns-nil () + "Boundary: lookup of empty string returns nil, not an error." + (gloss-test--with-temp-glossary gloss-test--sample-content + (should-not (gloss-core-lookup "")))) + +(ert-deftest test-gloss-core-lookup-nil-returns-nil () + "Boundary: lookup of nil returns nil, not an error." + (gloss-test--with-temp-glossary gloss-test--sample-content + (should-not (gloss-core-lookup nil)))) + +(ert-deftest test-gloss-core-lookup-case-sensitive () + "Boundary: lookup is case-sensitive — \"Anaphora\" misses \"anaphora\"." + (gloss-test--with-temp-glossary gloss-test--sample-content + (should-not (gloss-core-lookup "Anaphora")))) + +(ert-deftest test-gloss-core-lookup-empty-glossary-file-returns-nil () + "Error: lookup against empty file returns nil." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (should-not (gloss-core-lookup "anything")))) + +(ert-deftest test-gloss-core-lookup-missing-file-returns-nil () + "Error: lookup before any save returns nil (file does not exist)." + (let ((gloss-file (concat temporary-file-directory "gloss-nonexistent-" + (number-to-string (random 100000)) ".org"))) + (unwind-protect + (progn + (gloss-core--cache-reset) + (should-not (file-exists-p gloss-file)) + (should-not (gloss-core-lookup "anything"))) + (gloss-core--cache-reset) + (when (file-exists-p gloss-file) (delete-file gloss-file))))) + +(provide 'test-gloss-core--lookup) +;;; test-gloss-core--lookup.el ends here diff --git a/tests/test-gloss-core--save.el b/tests/test-gloss-core--save.el new file mode 100644 index 0000000..c9e77d1 --- /dev/null +++ b/tests/test-gloss-core--save.el @@ -0,0 +1,82 @@ +;;; test-gloss-core--save.el --- Tests for gloss-core-save -*- lexical-binding: t -*- + +;; SPDX-License-Identifier: GPL-3.0-or-later + +;;; Commentary: +;; Tests for `gloss-core-save' covering Normal/Boundary/Error cases. + +;;; Code: + +(require 'ert) +(require 'gloss-core) +(require 'testutil-gloss) + +(ert-deftest test-gloss-core-save-new-term-returns-entry-plist () + "Normal: save new term returns the entry plist with all fields." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (let ((entry (gloss-core-save "anaphora" "Reference to..." 'wiktionary))) + (should entry) + (should (equal (plist-get entry :term) "anaphora")) + (should (equal (plist-get entry :body) "Reference to...")) + (should (eq (plist-get entry :source) 'wiktionary)) + (should (stringp (plist-get entry :added)))))) + +(ert-deftest test-gloss-core-save-then-lookup-roundtrip () + "Normal: save then lookup returns the matching entry." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (gloss-core-save "anaphora" "Reference to something earlier." 'wiktionary) + (let ((entry (gloss-core-lookup "anaphora"))) + (should entry) + (should (equal (plist-get entry :body) + "Reference to something earlier."))))) + +(ert-deftest test-gloss-core-save-multi-line-body-preserved () + "Boundary: save preserves a multi-line body." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (let ((body "First paragraph.\n\nSecond paragraph.")) + (gloss-core-save "term" body 'manual) + (let ((entry (gloss-core-lookup "term"))) + (should (equal (plist-get entry :body) body)))))) + +(ert-deftest test-gloss-core-save-empty-body-raises-error () + "Error: empty body raises a user-error." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (should-error (gloss-core-save "anaphora" "" 'wiktionary) + :type 'user-error))) + +(ert-deftest test-gloss-core-save-empty-term-raises-error () + "Error: empty term raises a user-error." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (should-error (gloss-core-save "" "Some body" 'wiktionary) + :type 'user-error))) + +(ert-deftest test-gloss-core-save-collision-replace-overwrites () + "Error: collision with action \\='replace overwrites the body and source." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (gloss-core-save "anaphora" "First definition." 'wiktionary) + (gloss-core-save "anaphora" "Second definition." 'manual 'replace) + (let ((entry (gloss-core-lookup "anaphora"))) + (should (equal (plist-get entry :body) "Second definition.")) + (should (eq (plist-get entry :source) 'manual))))) + +(ert-deftest test-gloss-core-save-collision-append-joins-bodies () + "Error: collision with action \\='append concatenates the bodies." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (gloss-core-save "anaphora" "First definition." 'wiktionary) + (gloss-core-save "anaphora" "Second definition." 'manual 'append) + (let ((entry (gloss-core-lookup "anaphora"))) + (should (string-match-p "First definition" (plist-get entry :body))) + (should (string-match-p "Second definition" (plist-get entry :body)))))) + +(ert-deftest test-gloss-core-save-collision-cancel-leaves-original () + "Error: collision with action \\='cancel leaves the original entry." + (gloss-test--with-temp-glossary "#+TITLE: Glossary\n" + (gloss-core-save "anaphora" "First definition." 'wiktionary) + (let ((result (gloss-core-save "anaphora" "Second definition." + 'manual 'cancel))) + (should-not result)) + (let ((entry (gloss-core-lookup "anaphora"))) + (should (equal (plist-get entry :body) "First definition."))))) + +(provide 'test-gloss-core--save) +;;; test-gloss-core--save.el ends here diff --git a/tests/testutil-gloss.el b/tests/testutil-gloss.el new file mode 100644 index 0000000..b70b0ea --- /dev/null +++ b/tests/testutil-gloss.el @@ -0,0 +1,62 @@ +;;; testutil-gloss.el --- Shared test fixtures for gloss -*- lexical-binding: t -*- + +;; SPDX-License-Identifier: GPL-3.0-or-later + +;;; Commentary: + +;; Fixtures used across gloss test files. Provides: +;; - `gloss-test--with-temp-glossary' macro (binds `gloss-file', cleans up). +;; - `gloss-test--sample-content' two-entry org content. +;; - `gloss-test--make-temp-glossary-file' for cases that need direct paths. + +;;; Code: + +(require 'gloss-core) + +(defconst gloss-test--sample-content + "#+TITLE: Glossary +#+STARTUP: showall + +* anaphora +:PROPERTIES: +:SOURCE: wiktionary +:ADDED: 2026-04-28 +:END: +Reference to something earlier in the discourse. + +* SBIR +:PROPERTIES: +:SOURCE: wiktionary +:ADDED: 2026-04-27 +:END: +Initialism of Small Business Innovation Research. +" + "Two-entry sample content for tests that need a populated glossary.") + +(defun gloss-test--make-temp-glossary-file (&optional initial-content) + "Create a temp file with INITIAL-CONTENT (or empty) and return its path. +The caller is responsible for cleanup." + (let ((path (make-temp-file "gloss-test-" nil ".org"))) + (when initial-content + (with-temp-file path (insert initial-content))) + path)) + +(defmacro gloss-test--with-temp-glossary (initial-content &rest body) + "Bind `gloss-file' to a fresh temp file containing INITIAL-CONTENT. +Reset the in-memory cache before BODY and after. Clean up file and any +visiting buffer." + (declare (indent 1) (debug t)) + `(let ((gloss-file (gloss-test--make-temp-glossary-file ,initial-content))) + (unwind-protect + (progn + (gloss-core--cache-reset) + ,@body) + (gloss-core--cache-reset) + (when-let ((buf (find-buffer-visiting gloss-file))) + (with-current-buffer buf (set-buffer-modified-p nil)) + (kill-buffer buf)) + (when (file-exists-p gloss-file) + (delete-file gloss-file))))) + +(provide 'testutil-gloss) +;;; testutil-gloss.el ends here -- cgit v1.2.3