branch: elpa/logview commit 1fdeaec361abe67cdb3a31285c2fe37ce4be99dc Author: Paul Pogonyshev <pogonys...@gmail.com> Commit: Paul Pogonyshev <pogonys...@gmail.com>
Fix section commands and also a few commands added earlier to behave properly when narrowing is in effect. --- logview.el | 110 +++++++++------- test/log4j/sections-1.log | 38 +++--- test/logview.el | 324 ++++++++++++++++++++++++---------------------- 3 files changed, 253 insertions(+), 219 deletions(-) diff --git a/logview.el b/logview.el index 0c5dd16aff..ccba975091 100644 --- a/logview.el +++ b/logview.el @@ -1806,7 +1806,8 @@ can use command `\\<logview-mode-map>\\[logview-set-section-view]' to change tha ;; Second "p" is only needed so that SET-VIEW-IF-NEEDED is non-nil when called ;; interactively. (interactive "p\np") - (logview--do-forward-section-as-command set-view-if-needed (if n (1- n) 0))) + (logview--std-temporarily-widening + (logview--do-forward-section-as-command set-view-if-needed (if n (1- n) 0)))) (defun logview-go-to-section-end (&optional n set-view-if-needed) "Move point to the end of current section. @@ -1824,7 +1825,8 @@ can use command `\\<logview-mode-map>\\[logview-set-section-view]' to change tha ;; Second "p" is only needed so that SET-VIEW-IF-NEEDED is non-nil when called ;; interactively. (interactive "p\np") - (logview--do-forward-section-as-command set-view-if-needed (if n (1- n) 0) t)) + (logview--std-temporarily-widening + (logview--do-forward-section-as-command set-view-if-needed (if n (1- n) 0) t))) (defun logview-next-section (&optional n set-view-if-needed) "Move point down N (1 by default) log sections. @@ -1835,7 +1837,8 @@ visible entry (usually the header) of the resulting section" (interactive "p\np") (unless n (setf n 1)) - (logview--maybe-complain-about-movement n (logview--do-forward-section-as-command set-view-if-needed n) 'section)) + (logview--std-temporarily-widening + (logview--maybe-complain-about-movement n (logview--do-forward-section-as-command set-view-if-needed n) 'section))) (defun logview-previous-section (&optional n set-view-if-needed) "Move point up N (1 by default) log sections. @@ -1877,7 +1880,8 @@ visible entry (usually the header) of the section." (interactive "p") (unless (region-active-p) (push-mark)) - (logview--do-forward-section-as-command set-view-if-needed most-negative-fixnum)) + (logview--std-temporarily-widening + (logview--do-forward-section-as-command set-view-if-needed most-negative-fixnum))) (defun logview-last-section (&optional set-view-if-needed) "Move point to the last (visible) section in this thread. @@ -1888,8 +1892,9 @@ visible entry (usually the header) of the section." (interactive "p") (unless (region-active-p) (push-mark)) - (when (> (logview--do-forward-section-as-command set-view-if-needed most-positive-fixnum) 0) - (logview--forward-section 0))) + (logview--std-temporarily-widening + (when (> (logview--do-forward-section-as-command set-view-if-needed most-positive-fixnum) 0) + (logview--forward-section 0)))) (defun logview-first-section-any-thread (&optional set-view-if-needed) "Move point to the first (visible) section regardless of thread. @@ -1947,40 +1952,46 @@ the argument is positive, non-bound otherwise." ;; The logic of this code is pretty much impossible to follow. Just trust it as long ;; as it passes the tests. (let* ((forward (or (> n 0) (and (= n 0) go-to-end))) + (limit (if forward (logview--point-max) (logview--point-min))) (section-thread (when (logview-sections-thread-bound-p) (logview--entry-group last-valid-entry last-valid-start logview--thread-group))) (header-filter (cdr logview--section-header-filter)) ;; Current section is always visible. (visible-section t) (callback (lambda (entry start) - ;; Ignore entries belonging to a "wrong" thread and continue. - (or (and section-thread (not (string= (logview--entry-group entry start logview--thread-group) section-thread))) - (let ((header (funcall header-filter entry start))) - (if (and (= n 0) forward go-to-end header) - nil - (let ((invisible (invisible-p start))) - (when header - (unless (or invisible forward) - (setf visible-section t)) - (when visible-section - (setf n (if forward (1- n) (1+ n)))) - (when forward - (setf visible-section nil))) - (or invisible - (progn - (setf last-valid-entry entry - last-valid-start start) - (when (or forward (not header)) - (setf visible-section t)) - (or (if forward - (or (> n 0) go-to-end) - (when (if go-to-end - (or (< n 0) header) - (or (<= n 0) (not header))) - (when header - (setf visible-section nil)) - t)) - (progn (setf n 0) nil))))))))))) + ;; See comment above iterating calls. + (and (if forward (<= start limit) (> (logview--entry-end entry start) limit)) + ;; Ignore entries belonging to a "wrong" thread and continue. + (or (and section-thread (not (string= (logview--entry-group entry start logview--thread-group) section-thread))) + (let ((header (funcall header-filter entry start))) + (if (and (= n 0) forward go-to-end header) + nil + (let ((invisible (invisible-p start))) + (when header + (unless (or invisible forward) + (setf visible-section t)) + (when visible-section + (setf n (if forward (1- n) (1+ n)))) + (when forward + (setf visible-section nil))) + (or invisible + (progn + (setf last-valid-entry entry + last-valid-start start) + (when (or forward (not header)) + (setf visible-section t)) + (or (if forward + (or (> n 0) go-to-end) + (when (if go-to-end + (or (< n 0) header) + (or (<= n 0) (not header))) + (when header + (setf visible-section nil)) + t)) + (progn (setf n 0) nil)))))))))))) + ;; We don't skip invisible entries, since we need to detect section bounds even if + ;; the headers are filtered out. Therefore, the callback needs to take narrowing + ;; into account explicitly. (if forward (logview--iterate-entries-forward last-valid-start callback nil nil t) (logview--iterate-entries-backward last-valid-start callback)) @@ -2303,14 +2314,14 @@ entry after the gap." (logview--assert 'thread)) (unless n (setq n 1)) - (logview--locate-current-entry started-at-entry started-at - (let ((thread (when same-thread-only - (logview--entry-group started-at-entry started-at logview--thread-group)))) - (when (< n 0) - (logview--forward-entry -1 (when thread - (lambda (entry start) - (string-equal (logview--entry-group entry start logview--thread-group) thread))))) - (logview--std-temporarily-widening + (logview--std-temporarily-widening + (logview--locate-current-entry started-at-entry started-at + (let ((thread (when same-thread-only + (logview--entry-group started-at-entry started-at logview--thread-group)))) + (when (< n 0) + (logview--forward-entry -1 (when thread + (lambda (entry start) + (string-equal (logview--entry-group entry start logview--thread-group) thread))))) (logview--locate-current-entry entry start (let ((remaining (logview--forward-entry n (logview--entry-timestamp-gap-validator entry start thread))) (success (when logview--last-found-large-gap @@ -2976,7 +2987,11 @@ returns non-nil." "Return the entry around POSITION and its beginning. If POSITION is nil, take the current value of point as the position, and also signal a user-level error if no entries can be -located." +located. + +This function may misbehave if any narrowing is in effect. Make +sure to cancel it using `logview--std-temporarily-widening' or +something similar first." (let* ((entry-at (or position (point))) (entry (or (get-text-property entry-at 'logview-entry) (progn (logview--find-region-entries entry-at (+ entry-at logview--lazy-region-size)) @@ -3013,7 +3028,7 @@ CALLBACK." (when entry+start (let ((entry (car entry+start)) (entry-at (cdr entry+start)) - (limit (1+ (buffer-size)))) + (limit (if only-visible (logview--point-max) (1+ (buffer-size))))) (unless (and skip-current (>= (setq entry-at (logview--entry-end entry entry-at)) limit)) (while (progn (setq entry (or (get-text-property entry-at 'logview-entry) (progn (logview--find-region-entries entry-at (+ entry-at logview--lazy-region-size)) @@ -3029,8 +3044,9 @@ See `logview--iterate-entries-forward' for details." (let ((entry+start (logview--do-locate-current-entry position))) (when entry+start (let ((entry (car entry+start)) - (entry-at (cdr entry+start))) - (unless (and skip-current (<= (setq entry-at (1- entry-at)) 0 )) + (entry-at (cdr entry+start)) + (limit (if only-visible (logview--point-min) 1))) + (unless (and skip-current (< (setq entry-at (1- entry-at)) limit)) (while (and (setq entry (or (get-text-property entry-at 'logview-entry) (progn (logview--find-region-entries (max 1 (- entry-at logview--lazy-region-size)) (1+ entry-at) t) (get-text-property entry-at 'logview-entry)))) @@ -3039,7 +3055,7 @@ See `logview--iterate-entries-forward' for details." (when (or (and only-visible (invisible-p entry-at)) (and validator (not (funcall validator entry entry-at))) (funcall callback entry entry-at)) - (> (setq entry-at (1- entry-at)) 0)))))))))) + (>= (setq entry-at (1- entry-at)) limit)))))))))) (defun logview--iterate-successive-entries (position n callback &optional only-visible validator) (when (/= n 0) diff --git a/test/log4j/sections-1.log b/test/log4j/sections-1.log index 4332cb0235..8afe2ddd0f 100644 --- a/test/log4j/sections-1.log +++ b/test/log4j/sections-1.log @@ -1,19 +1,19 @@ -2010-03-10 20:03:44.332 [thread 1] DEBUG my.Startup - starting up -2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - before any sections -2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - before any sections continued -2010-03-10 20:03:44.332 [thread 1] INFO my.Server - serving request 1 -2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - inside section 1 -2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - doing stuff (section 1) -2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - doing more stuff (section 1) -2010-03-10 20:03:44.332 [thread 1] INFO my.Server - serving request 2 -2010-03-10 20:03:44.332 [thread 2] INFO my.Server - serving request 3 (in a different thread) -2010-03-10 20:03:44.332 [thread 2] DEBUG my.Class - inside section 3 -2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - inside section 2 -2010-03-10 20:03:44.332 [thread 2] DEBUG my.Class - doing stuff (section 3) -2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - doing stuff (section 2) -2010-03-10 20:03:44.332 [thread 2] DEBUG my.Class - doing more stuff (section 3) -2010-03-10 20:03:44.332 [thread 2] INFO my.Server - serving request 4 (in a different thread) -2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - doing more stuff (section 2) -2010-03-10 20:03:44.332 [thread 2] DEBUG my.Class - inside section 4 -2010-03-10 20:03:44.332 [thread 2] DEBUG my.Class - doing stuff (section 4) -2010-03-10 20:03:44.332 [thread 2] DEBUG my.Class - doing more stuff (section 4) +2010-03-10 20:03:44.000 [thread 1] DEBUG my.Startup - starting up +2010-03-10 20:03:44.100 [thread 1] DEBUG my.Class - before any sections +2010-03-10 20:03:44.200 [thread 1] DEBUG my.Class - before any sections continued +2010-03-10 20:03:45.000 [thread 1] INFO my.Server - serving request 1 +2010-03-10 20:03:45.100 [thread 1] DEBUG my.Class - inside section 1 +2010-03-10 20:03:45.200 [thread 1] DEBUG my.Class - doing stuff (section 1) +2010-03-10 20:03:45.300 [thread 1] DEBUG my.Class - doing more stuff (section 1) +2010-03-10 20:03:46.000 [thread 1] INFO my.Server - serving request 2 +2010-03-10 20:03:46.100 [thread 2] INFO my.Server - serving request 3 (in a different thread) +2010-03-10 20:03:46.200 [thread 2] DEBUG my.Class - inside section 3 +2010-03-10 20:03:46.300 [thread 1] DEBUG my.Class - inside section 2 +2010-03-10 20:03:46.400 [thread 2] DEBUG my.Class - doing stuff (section 3) +2010-03-10 20:03:46.500 [thread 1] DEBUG my.Class - doing stuff (section 2) +2010-03-10 20:03:46.600 [thread 2] DEBUG my.Class - doing more stuff (section 3) +2010-03-10 20:03:47.000 [thread 2] INFO my.Server - serving request 4 (in a different thread) +2010-03-10 20:03:47.100 [thread 1] DEBUG my.Class - doing more stuff (section 2) +2010-03-10 20:03:47.200 [thread 2] DEBUG my.Class - inside section 4 +2010-03-10 20:03:47.300 [thread 2] DEBUG my.Class - doing stuff (section 4) +2010-03-10 20:03:47.400 [thread 2] DEBUG my.Class - doing more stuff (section 4) diff --git a/test/logview.el b/test/logview.el index 80afae4011..aefb440e20 100644 --- a/test/logview.el +++ b/test/logview.el @@ -60,14 +60,24 @@ (defun logview--test-current-message () - (logview--locate-current-entry entry start - (string-trim (logview--entry-message entry start)))) + (logview--std-temporarily-widening + (logview--locate-current-entry entry start + (string-trim (logview--entry-message entry start))))) (defun logview--test-position-at-entry-with (message) (goto-char (point-min)) (re-search-forward (rx-to-string `(seq ,message eol)))) +(defmacro logview--subtest (save-excursion operation &rest etc) + (declare (debug (form form body)) + (indent 2)) + `(,(if (eval save-excursion t) 'save-excursion 'progn) + (ert-info ((format "operation: %S" ',operation)) + ,operation + ,@etc))) + + (ert-deftest logview-test-log4j-standard-1 () (logview--test-with-file "log4j/en-1.log" (should (equal logview--submode-name "SLF4J")) @@ -299,15 +309,6 @@ (should (equal (logview--locate-current-entry entry nil (logview--entry-level entry)) 7)))) -(defmacro logview--subtest (save-excursion operation &rest etc) - (declare (debug (form form body)) - (indent 2)) - `(,(if (eval save-excursion t) 'save-excursion 'progn) - (ert-info ((format "operation: %S" ',operation)) - ,operation - ,@etc))) - - ;; This is a huge test, but I find it easier to test various combinations this way. ;; ;; Expected results of `logview-*-section-any-thread' may seem wrong, but remember that @@ -322,148 +323,165 @@ (logview--views-initialized t) (logview--views-need-saving nil)) (logview-set-section-view "sections") - ;; "Section zero", i.e. before any section headers. - (dolist (message '("starting up" "before any sections" "before any sections continued")) - (logview--test-position-at-entry-with message) - (ert-info ((format "operating from line \"%s\"" message)) - (logview--subtest t (logview-go-to-section-beginning) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-go-to-section-end) - (should (string= (logview--test-current-message) "before any sections continued"))) - (logview--subtest t (logview-next-section) - (should (string= (logview--test-current-message) "serving request 1"))) - ;; There is no previous section, obviously. - (logview--subtest t (should-error (logview-previous-section) :type 'user-error) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-next-section-any-thread) - (should (string= (logview--test-current-message) "serving request 1"))) - (logview--subtest t (should-error (logview-previous-section-any-thread) :type 'user-error) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-first-section) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-first-section-any-thread) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-last-section) - (should (string= (logview--test-current-message) "serving request 2"))) - (logview--subtest t (logview-last-section-any-thread) - (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))))) - ;; First real section. - (dolist (message '("serving request 1" "inside section 1" "doing stuff (section 1)" "doing more stuff (section 1)")) - (logview--test-position-at-entry-with message) - (ert-info ((format "operating from line \"%s\"" message)) - (logview--subtest t (logview-go-to-section-beginning) - (should (string= (logview--test-current-message) "serving request 1"))) - (logview--subtest t (logview-go-to-section-end) - (should (string= (logview--test-current-message) "doing more stuff (section 1)"))) - (logview--subtest t (logview-next-section) - (should (string= (logview--test-current-message) "serving request 2"))) - (logview--subtest t (logview-previous-section) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-next-section-any-thread) - (should (string= (logview--test-current-message) "serving request 2"))) - (logview--subtest t (logview-previous-section-any-thread) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-first-section) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-first-section-any-thread) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-last-section) - (should (string= (logview--test-current-message) "serving request 2"))) - (logview--subtest t (logview-last-section-any-thread) - (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))))) - ;; Second real section, intervined with sections 3 and 4 in a different thread. - (dolist (message '("serving request 2" "inside section 2" "doing stuff (section 2)" "doing more stuff (section 2)")) - (logview--test-position-at-entry-with message) - (ert-info ((format "operating from line \"%s\"" message)) - (logview--subtest t (logview-go-to-section-beginning) - (should (string= (logview--test-current-message) "serving request 2"))) - (logview--subtest t (logview-go-to-section-end) - (should (string= (logview--test-current-message) "doing more stuff (section 2)"))) - ;; There is no next section in this thread. - (logview--subtest t (should-error (logview-next-section) :type 'user-error) - (should (string= (logview--test-current-message) "doing more stuff (section 2)"))) - (logview--subtest t (logview-previous-section) - (should (string= (logview--test-current-message) "serving request 1"))) - ;; Results of `logview-*-section-any-thread' depend on the starting line. - (pcase message - ("serving request 2" - (logview--subtest t (logview-next-section-any-thread) - (should (string= (logview--test-current-message) "serving request 3 (in a different thread)")))) - ("doing more stuff (section 2)" - (logview--subtest t (should-error (logview-next-section-any-thread) :type 'user-error) - (should (string= (logview--test-current-message) "doing more stuff (section 4)")))) - (_ - (logview--subtest t (logview-next-section-any-thread) - (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))))) - (pcase message - ("serving request 2" - (logview--subtest t (logview-previous-section-any-thread) - (should (string= (logview--test-current-message) "serving request 1")))) - ("doing more stuff (section 2)" - (logview--subtest t (logview-previous-section-any-thread) - (should (string= (logview--test-current-message) "serving request 3 (in a different thread)")))) - (_ - (logview--subtest t (logview-previous-section-any-thread) - (should (string= (logview--test-current-message) "serving request 2"))))) - (logview--subtest t (logview-first-section) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-first-section-any-thread) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-last-section) - (should (string= (logview--test-current-message) "serving request 2"))) - (logview--subtest t (logview-last-section-any-thread) - (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))))) - ;; Third real section, intervined with section 2 in a different thread. - (dolist (message '("serving request 3 (in a different thread)" "inside section 3" "doing stuff (section 3)" "doing more stuff (section 3)")) - (logview--test-position-at-entry-with message) - (ert-info ((format "operating from line \"%s\"" message)) - (logview--subtest t (logview-go-to-section-beginning) - (should (string= (logview--test-current-message) "serving request 3 (in a different thread)"))) - (logview--subtest t (logview-go-to-section-end) - (should (string= (logview--test-current-message) "doing more stuff (section 3)"))) - (logview--subtest t (logview-next-section) - (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))) - ;; No previous section in _this thread_. - (logview--subtest t (should-error (logview-previous-section) :type 'user-error) - (should (string= (logview--test-current-message) "serving request 3 (in a different thread)"))) - (logview--subtest t (logview-next-section-any-thread) - (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))) - (logview--subtest t (logview-previous-section-any-thread) - (should (string= (logview--test-current-message) "serving request 2"))) - (logview--subtest t (logview-first-section) - (should (string= (logview--test-current-message) "serving request 3 (in a different thread)"))) - (logview--subtest t (logview-first-section-any-thread) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-last-section) - (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))) - (logview--subtest t (logview-last-section-any-thread) - (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))))) - ;; Fourth section, the very last in the file. - (dolist (message '("serving request 4 (in a different thread)" "inside section 4" "doing stuff (section 4)" "doing more stuff (section 4)")) - (logview--test-position-at-entry-with message) - (ert-info ((format "operating from line \"%s\"" message)) - (logview--subtest t (logview-go-to-section-beginning) - (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))) - (logview--subtest t (logview-go-to-section-end) - (should (string= (logview--test-current-message) "doing more stuff (section 4)"))) - ;; There is no next section in this thread. - (logview--subtest t (should-error (logview-next-section) :type 'user-error) - (should (string= (logview--test-current-message) "doing more stuff (section 4)"))) - (logview--subtest t (logview-previous-section) - (should (string= (logview--test-current-message) "serving request 3 (in a different thread)"))) - ;; No next section at all. - (logview--subtest t (should-error (logview-next-section-any-thread) :type 'user-error) - (should (string= (logview--test-current-message) "doing more stuff (section 4)"))) - (logview--subtest t (logview-previous-section-any-thread) - (should (string= (logview--test-current-message) "serving request 3 (in a different thread)"))) - (logview--subtest t (logview-first-section) - (should (string= (logview--test-current-message) "serving request 3 (in a different thread)"))) - (logview--subtest t (logview-first-section-any-thread) - (should (string= (logview--test-current-message) "starting up"))) - (logview--subtest t (logview-last-section) - (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))) - (logview--subtest t (logview-last-section-any-thread) - (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))))))) + (dolist (narrowing '((1 . 1) (2 . 1))) + (save-restriction + (when (> (car narrowing) 1) + (goto-char (point-min)) + (logview-next-entry (1- (car narrowing))) + (logview-narrow-from-this-entry)) + (when (> (cdr narrowing) 1) + (goto-char (point-max)) + (logview-previous-entry (1- (cdr narrowing))) + (logview-narrow-up-to-this-entry)) + (ert-info ((format "narrowing in effect: %s" + (if (equal narrowing '(1 . 1)) + "none" + (format "%s-%s" (if (= (car narrowing) 1) "" (car narrowing)) (if (= (cdr narrowing) 1) "" (cdr narrowing)))))) + (let* ((have-first-line (= (car narrowing) 1)) + (first-visible-message (if have-first-line "starting up" "before any sections"))) + ;; "Section zero", i.e. before any section headers. + (dolist (message '("starting up" "before any sections" "before any sections continued")) + (when (or have-first-line (not (string= message "starting up"))) + (logview--test-position-at-entry-with message) + (ert-info ((format "operating from line \"%s\"" message)) + (logview--subtest t (logview-go-to-section-beginning) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-go-to-section-end) + (should (string= (logview--test-current-message) "before any sections continued"))) + (logview--subtest t (logview-next-section) + (should (string= (logview--test-current-message) "serving request 1"))) + ;; There is no previous section, obviously. + (logview--subtest t (should-error (logview-previous-section) :type 'user-error) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-next-section-any-thread) + (should (string= (logview--test-current-message) "serving request 1"))) + (logview--subtest t (should-error (logview-previous-section-any-thread) :type 'user-error) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-first-section) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-first-section-any-thread) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-last-section) + (should (string= (logview--test-current-message) "serving request 2"))) + (logview--subtest t (logview-last-section-any-thread) + (should (string= (logview--test-current-message) "serving request 4 (in a different thread)")))))) + ;; First real section. + (dolist (message '("serving request 1" "inside section 1" "doing stuff (section 1)" "doing more stuff (section 1)")) + (logview--test-position-at-entry-with message) + (ert-info ((format "operating from line \"%s\"" message)) + (logview--subtest t (logview-go-to-section-beginning) + (should (string= (logview--test-current-message) "serving request 1"))) + (logview--subtest t (logview-go-to-section-end) + (should (string= (logview--test-current-message) "doing more stuff (section 1)"))) + (logview--subtest t (logview-next-section) + (should (string= (logview--test-current-message) "serving request 2"))) + (logview--subtest t (logview-previous-section) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-next-section-any-thread) + (should (string= (logview--test-current-message) "serving request 2"))) + (logview--subtest t (logview-previous-section-any-thread) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-first-section) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-first-section-any-thread) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-last-section) + (should (string= (logview--test-current-message) "serving request 2"))) + (logview--subtest t (logview-last-section-any-thread) + (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))))) + ;; Second real section, intervined with sections 3 and 4 in a different thread. + (dolist (message '("serving request 2" "inside section 2" "doing stuff (section 2)" "doing more stuff (section 2)")) + (logview--test-position-at-entry-with message) + (ert-info ((format "operating from line \"%s\"" message)) + (logview--subtest t (logview-go-to-section-beginning) + (should (string= (logview--test-current-message) "serving request 2"))) + (logview--subtest t (logview-go-to-section-end) + (should (string= (logview--test-current-message) "doing more stuff (section 2)"))) + ;; There is no next section in this thread. + (logview--subtest t (should-error (logview-next-section) :type 'user-error) + (should (string= (logview--test-current-message) "doing more stuff (section 2)"))) + (logview--subtest t (logview-previous-section) + (should (string= (logview--test-current-message) "serving request 1"))) + ;; Results of `logview-*-section-any-thread' depend on the starting line. + (pcase message + ("serving request 2" + (logview--subtest t (logview-next-section-any-thread) + (should (string= (logview--test-current-message) "serving request 3 (in a different thread)")))) + ("doing more stuff (section 2)" + (logview--subtest t (should-error (logview-next-section-any-thread) :type 'user-error) + (should (string= (logview--test-current-message) "doing more stuff (section 4)")))) + (_ + (logview--subtest t (logview-next-section-any-thread) + (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))))) + (pcase message + ("serving request 2" + (logview--subtest t (logview-previous-section-any-thread) + (should (string= (logview--test-current-message) "serving request 1")))) + ("doing more stuff (section 2)" + (logview--subtest t (logview-previous-section-any-thread) + (should (string= (logview--test-current-message) "serving request 3 (in a different thread)")))) + (_ + (logview--subtest t (logview-previous-section-any-thread) + (should (string= (logview--test-current-message) "serving request 2"))))) + (logview--subtest t (logview-first-section) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-first-section-any-thread) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-last-section) + (should (string= (logview--test-current-message) "serving request 2"))) + (logview--subtest t (logview-last-section-any-thread) + (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))))) + ;; Third real section, intervined with section 2 in a different thread. + (dolist (message '("serving request 3 (in a different thread)" "inside section 3" "doing stuff (section 3)" "doing more stuff (section 3)")) + (logview--test-position-at-entry-with message) + (ert-info ((format "operating from line \"%s\"" message)) + (logview--subtest t (logview-go-to-section-beginning) + (should (string= (logview--test-current-message) "serving request 3 (in a different thread)"))) + (logview--subtest t (logview-go-to-section-end) + (should (string= (logview--test-current-message) "doing more stuff (section 3)"))) + (logview--subtest t (logview-next-section) + (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))) + ;; No previous section in _this thread_. + (logview--subtest t (should-error (logview-previous-section) :type 'user-error) + (should (string= (logview--test-current-message) "serving request 3 (in a different thread)"))) + (logview--subtest t (logview-next-section-any-thread) + (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))) + (logview--subtest t (logview-previous-section-any-thread) + (should (string= (logview--test-current-message) "serving request 2"))) + (logview--subtest t (logview-first-section) + (should (string= (logview--test-current-message) "serving request 3 (in a different thread)"))) + (logview--subtest t (logview-first-section-any-thread) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-last-section) + (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))) + (logview--subtest t (logview-last-section-any-thread) + (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))))) + ;; Fourth section, the very last in the file. + (dolist (message '("serving request 4 (in a different thread)" "inside section 4" "doing stuff (section 4)" "doing more stuff (section 4)")) + (logview--test-position-at-entry-with message) + (ert-info ((format "operating from line \"%s\"" message)) + (logview--subtest t (logview-go-to-section-beginning) + (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))) + (logview--subtest t (logview-go-to-section-end) + (should (string= (logview--test-current-message) "doing more stuff (section 4)"))) + ;; There is no next section in this thread. + (logview--subtest t (should-error (logview-next-section) :type 'user-error) + (should (string= (logview--test-current-message) "doing more stuff (section 4)"))) + (logview--subtest t (logview-previous-section) + (should (string= (logview--test-current-message) "serving request 3 (in a different thread)"))) + ;; No next section at all. + (logview--subtest t (should-error (logview-next-section-any-thread) :type 'user-error) + (should (string= (logview--test-current-message) "doing more stuff (section 4)"))) + (logview--subtest t (logview-previous-section-any-thread) + (should (string= (logview--test-current-message) "serving request 3 (in a different thread)"))) + (logview--subtest t (logview-first-section) + (should (string= (logview--test-current-message) "serving request 3 (in a different thread)"))) + (logview--subtest t (logview-first-section-any-thread) + (should (string= (logview--test-current-message) first-visible-message))) + (logview--subtest t (logview-last-section) + (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))) + (logview--subtest t (logview-last-section-any-thread) + (should (string= (logview--test-current-message) "serving request 4 (in a different thread)"))))))))))) (define-derived-mode logview--test-derived-mode logview-mode