[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
feature/pgtk 30ac6fb: Merge remote-tracking branch 'origin/master' into
From: |
Po Lu |
Subject: |
feature/pgtk 30ac6fb: Merge remote-tracking branch 'origin/master' into feature/pgtk |
Date: |
Tue, 14 Dec 2021 04:43:27 -0500 (EST) |
branch: feature/pgtk
commit 30ac6fbbed95b3e9db530a35be7d04c257076423
Merge: da2c0e8 8c0f9be
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Merge remote-tracking branch 'origin/master' into feature/pgtk
---
.gitignore | 1 +
admin/notes/emba | 4 +
doc/lispref/functions.texi | 7 +-
doc/lispref/windows.texi | 214 ++++++++++++++++++++----------------
etc/NEWS | 7 ++
etc/NEWS.28 | 6 +-
lisp/calc/calc.el | 2 +-
lisp/completion.el | 4 +-
lisp/emacs-lisp/ert.el | 134 +++++++++++++++++++++-
lisp/emacs-lisp/generator.el | 6 +-
lisp/eshell/esh-cmd.el | 4 +-
lisp/help-macro.el | 8 +-
lisp/ielm.el | 38 +++----
lisp/international/robin.el | 8 +-
lisp/pcomplete.el | 14 +--
lisp/progmodes/python.el | 4 +-
lisp/progmodes/xscheme.el | 5 +-
lisp/tab-bar.el | 2 +-
make-dist | 11 +-
src/bignum.c | 9 ++
src/sqlite.c | 38 ++++++-
src/xdisp.c | 11 +-
test/Makefile.in | 1 +
test/README | 3 +
test/infra/Makefile.in | 6 +-
test/infra/gitlab-ci.yml | 22 ++--
test/infra/test-jobs.yml | 1 +
test/lisp/progmodes/python-tests.el | 18 ++-
test/src/sqlite-tests.el | 32 ++++++
29 files changed, 430 insertions(+), 190 deletions(-)
diff --git a/.gitignore b/.gitignore
index 25ed3bd..78557a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -159,6 +159,7 @@ test/manual/etags/CTAGS
test/manual/indent/*.new
test/lisp/gnus/mml-sec-resources/random_seed
test/lisp/play/fortune-resources/fortunes.dat
+test/**/*.xml
# ctags, etags.
TAGS
diff --git a/admin/notes/emba b/admin/notes/emba
index f1b52b2..2135c7a 100644
--- a/admin/notes/emba
+++ b/admin/notes/emba
@@ -63,6 +63,10 @@ They can be downloaded from the server, visiting the URL
<https://emba.gnu.org/emacs/emacs/-/pipelines>, and selecting the job
in question.
+Every pipeline generates a JUnit test report for the respective test
+jobs, which can be inspected on the pipeline web page. This test
+report counts completed ERT tests, aborted tests are not counted.
+
* Emba configuration
The emba configuration files are hosted on
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index 9c1fde0..46a1e57 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -1647,9 +1647,10 @@ function will be interactive and will use the
interactive spec of
@var{function}. One exception: if the interactive spec of @var{function}
is a function (i.e., a @code{lambda} expression or an @code{fbound}
symbol rather than an expression or a string), then the interactive
-spec of the combined function will be a call to that function with as sole
-argument the interactive spec of the original function. To interpret the spec
-received as argument, use @code{advice-eval-interactive-spec}.
+spec of the combined function will be a call to that function with
+the interactive spec of the original function as sole argument. To
+interpret the spec received as argument, use
+@code{advice-eval-interactive-spec}.
Note: The interactive spec of @var{function} will apply to the combined
function and should hence obey the calling convention of the combined function
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index 395b88e..c3894bc 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -4229,97 +4229,48 @@ action alist entry (@pxref{Buffer Display Action
Alists}).
@node Quitting Windows
@section Quitting Windows
-
-When you want to get rid of a window used for displaying a buffer, you
-can call @code{delete-window} or @code{delete-windows-on}
-(@pxref{Deleting Windows}) to remove that window from its frame. If the
-buffer is shown on a separate frame, you might want to call
-@code{delete-frame} (@pxref{Deleting Frames}) instead. If, on the other
-hand, a window has been reused for displaying the buffer, you might
-prefer showing the buffer previously shown in that window, by calling the
-function @code{switch-to-prev-buffer} (@pxref{Window History}).
-Finally, you might want to either bury (@pxref{Buffer List}) or kill
-(@pxref{Killing Buffers}) the window's buffer.
-
- The following command uses information on how the window for
-displaying the buffer was obtained in the first place, thus attempting
-to automate the above decisions for you.
+@cindex quitting windows
+
+After a command uses @code{display-buffer} to put a buffer on the
+screen, the user may decide to hide it and return to the previous
+configuration of the Emacs display. We call that @dfn{quitting the
+window}. The way to do this is to call @code{quit-window} while the
+window used by @code{display-buffer} is the selected window.
+
+The right way to restore the previous configuration of the display
+depends on what was done to the window where the buffer now appears.
+It might be right to delete that window, or delete its frame, or just
+display another buffer in that window. One complication is that the
+user may have changed the window configuration since the act of
+displaying that buffer, and it would be undesirable to undo the user's
+explicitly requested changes.
+
+To enable @code{quit-window} to do the right thing,
+@code{display-buffer} saves information about what it did in the
+window's @code{quit-restore} parameter (@pxref{Window Parameters}).
@deffn Command quit-window &optional kill window
This command quits @var{window} and buries its buffer. The argument
@var{window} must be a live window and defaults to the selected one.
With prefix argument @var{kill} non-@code{nil}, it kills the buffer
-instead of burying it. It calls the function @code{quit-restore-window}
-described next to deal with the window and its buffer.
+instead of burying it.
@vindex quit-window-hook
-The functions in @code{quit-window-hook} are run before doing anything
-else.
+The function @code{quit-window} first runs @code{quit-window-hook}.
+Then it calls the function @code{quit-restore-window}, described next,
+which does the hard work.
@end deffn
+You can get more control by calling @code{quit-restore-window} instead.
+
@defun quit-restore-window &optional window bury-or-kill
This function handles @var{window} and its buffer after quitting. The
optional argument @var{window} must be a live window and defaults to
-the selected one. The function's behavior is determined by the four
-elements of the list specified by @var{window}'s @code{quit-restore}
-parameter (@pxref{Window Parameters}).
-
-The first element of the @code{quit-restore} parameter is one of the
-symbols @code{window}, meaning that the window has been specially
-created by @code{display-buffer}; @code{frame}, a separate frame has
-been created; @code{same}, the window has only ever displayed this
-buffer; or @code{other}, the window showed another buffer before.
-@code{frame} and @code{window} affect how the window is quit, while
-@code{same} and @code{other} affect the redisplay of buffers
-previously shown in @var{window}.
-
-The parameter's second element is either one of the symbols
-@code{window} or @code{frame}, or a list whose elements are the buffer
-shown in @var{window} before, that buffer's window start and window
-point positions, and @var{window}'s height at that time. If that
-buffer is still live when @var{window} is quit, then this function may
-reuse @var{window} to display it.
-
-The third element is the window selected at the time the parameter was
-created. If this function deletes @var{window}, it subsequently tries
-to reselect the window named by that element.
-
-The fourth element is the buffer whose display caused the creation of
-this parameter. This function may delete @var{window} if and only if
-it still shows that buffer.
-
-This function will try to delete @var{window} if and only if (1) the
-first element of its @code{quit-restore} parameter is either
-@code{window} or @code{frame}, (2) the window has no history of
-previously-displayed buffers and (3) the fourth element of the
-@code{quit-restore} parameter specifies the buffer currently displayed
-in @var{window}. If @var{window} is part of an atomic window
-(@pxref{Atomic Windows}), it will try to delete the root of that
-atomic window instead. In either case, it tries to avoid signaling an
-error when @var{window} cannot be deleted.
-
-If @var{window} shall be deleted, is the only window on its frame and
-there are other frames on that frame's terminal, the value of the
-optional argument @var{bury-or-kill} determines how to proceed with
-the window. If @var{bury-or-kill} equals @code{kill}, the frame is
-deleted unconditionally. Otherwise, the fate of the frame is
-determined by calling @code{frame-auto-hide-function} (see below) with
-that frame as sole argument.
-
-If the second element of the @code{quit-restore} parameter is a list
-of a buffer, a window start (@pxref{Window Start and End}) and a
-window point (@pxref{Window Point}), and that buffer is still live,
-the buffer will be displayed, and start and point set accordingly.
-If, in addition, @var{window}'s buffer was temporarily resized, this
-function will also try to restore the original height of @var{window}.
-
-Otherwise, if @var{window} was previously used for displaying other
-buffers (@pxref{Window History}), the most recent buffer in that
-history will be displayed. In either case, if @var{window} is not
-deleted, its @code{quit-restore} parameter is reset to @code{nil}.
+the selected one. The function takes account of the @var{window}'s
+@code{quit-restore} parameter.
The optional argument @var{bury-or-kill} specifies how to deal with
-@var{window}'s buffer. The following values are handled:
+@var{window}'s buffer. The following values are meaningful:
@table @code
@item nil
@@ -4329,25 +4280,106 @@ consequence, if @var{window} is not deleted, invoking
@item append
This means that if @var{window} is not deleted, its buffer is moved to
-the end of @var{window}'s list of previous buffers, so it's less likely
-that a future invocation of @code{switch-to-prev-buffer} will switch to
-it. Also, it moves the buffer to the end of the frame's buffer list.
+the end of @var{window}'s list of previous buffers (@pxref{Window
+History}), so it's less likely that future invocations of
+@code{switch-to-prev-buffer} will switch to it. Also, it moves the
+buffer to the end of the frame's buffer list (@pxref{Buffer List}).
@item bury
This means that if @var{window} is not deleted, its buffer is removed
-from @var{window}'s list of previous buffers. Also, it moves the buffer
-to the end of the frame's buffer list. This value provides the most
-reliable remedy to not have @code{switch-to-prev-buffer} switch to this
-buffer again without killing the buffer.
+from @var{window}'s list of previous buffers. Also, it moves the
+buffer to the end of the frame's buffer list. This is the most
+reliable way to prevent @code{switch-to-prev-buffer} from switching to
+this buffer again, short of killing the buffer.
@item kill
This means to kill @var{window}'s buffer.
@end table
+The argument @var{bury-or-kill} also specifies what to do with
+@var{window}'s frame when @var{window} should be deleted, if it is the
+only window on its frame, and there are other frames on that frame's
+terminal. If @var{bury-or-kill} equals @code{kill}, it means to
+delete the frame. Otherwise, the fate of the frame is determined by
+calling @code{frame-auto-hide-function} (see below) with that frame as
+sole argument.
+
+This function always sets @var{window}'s @code{quit-restore} parameter
+to @code{nil} unless it deletes the window.
+@end defun
+
+The window @var{window}'s @code{quit-restore} parameter (@pxref{Window
+Parameters}) should be @code{nil} or a list of four elements:
+@c FIXME: describe what quit-restore-window does if this is nil.
+
+@lisp
+(@var{method} @var{obuffer} @var{owindow} @var{this-buffer})
+@end lisp
+
+The first element, @var{method}, is one of the four symbols
+@code{window}, @code{frame}, @code{same} and @code{other}.
+@code{frame} and @code{window} control how to delete @var{window},
+while @code{same} and @code{other} control displaying some other
+buffer in it.
+
+Specifically, @code{window} means that the window has been specially
+created by @code{display-buffer}; @code{frame} means that a separate
+frame has been created; @code{same}, that the window has only ever
+displayed this buffer; @code{other}, that the window showed another
+buffer before.
+
+The second element, @var{obuffer}, is either one of the symbols
+@code{window} or @code{frame}, or a list of the form
+
+@lisp
+(@var{prev-buffer} @var{prev-window-start} @var{prev-window-point}
@var{height})
+@end lisp
+
+@noindent
+which says which buffer was shown in @var{window} before, that
+buffer's window start (@pxref{Window Start and End}) and window point
+(@pxref{Window Point}) positions at that time, and
+@var{window}'s height at that time. If @var{prev-buffer} is still
+live when quitting @var{window}, quitting the window may reuse
+@var{window} to display @var{prev-buffer}.
+
+The third element, @var{owindow}, is the window that was selected
+just before the displaying was done. If quitting deletes
+@var{window}, it tries to select @var{owindow}.
+
+The fourth element, @var{this-buffer}, is the buffer whose displaying
+set the @code{quit-restore} parameter. Quitting @var{window} may delete
+that window only if it still shows that buffer.
+
+Quitting @var{window} tries to delete it if and only if (1)
+@var{method} is either @code{window} or @code{frame}, (2) the window
+has no history of previously-displayed buffers and (3)
+@var{this-buffer} equals the buffer currently displayed in
+@var{window}. If @var{window} is part of an atomic window
+(@pxref{Atomic Windows}), quitting will try to delete the root of that
+atomic window instead. In either case, it tries to avoid signaling an
+error when @var{window} cannot be deleted.
+
+If @var{obuffer} is a list, and @var{prev-buffer} is still live,
+quitting displays @var{prev-buffer} in @var{window} according to the
+rest of the elements of @var{obuffer}. This includes resizing the
+window to @var{height} if it was temporarily resized to display
+@var{this-buffer}.
+
+Otherwise, if @var{window} was previously used for displaying other
+buffers (@pxref{Window History}), the most recent buffer in that
+history will be displayed.
+
+@ignore
+@c FIXME: Should we document display-buffer-reuse-window?
+If we document display-buffer-record-window, it should be with @defun.
+And maybe not here.
+
+
Typically, the display routines run by @code{display-buffer} will set
-the @code{quit-restore} window parameter correctly. It's also
-possible to set it manually, using the following code for displaying
-@var{buffer} in @var{window}:
+the @code{quit-restore} window parameter correctly. You can also set
+it manually, using the following code for displaying @var{buffer} in
+@var{window}:
@example
@group
@@ -4361,11 +4393,10 @@ possible to set it manually, using the following code
for displaying
Setting the window history to @code{nil} ensures that a future call to
@code{quit-window} can delete the window altogether.
+@end ignore
-@end defun
-
-The following option specifies how to deal with a frame containing just
-one window that should be either quit, or whose buffer should be buried.
+The following option specifies a function to do the right thing with a
+frame containing one window when quitting that window.
@defopt frame-auto-hide-function
The function specified by this option is called to automatically hide
@@ -4394,7 +4425,6 @@ that frame's @code{auto-hide-function} frame parameter
(@pxref{Frame
Interaction Parameters}).
@end defopt
-
@node Side Windows
@section Side Windows
@cindex side windows
diff --git a/etc/NEWS b/etc/NEWS
index b55b306..8d83b2a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -163,6 +163,12 @@ the previous definition to be discarded, which was
probably not
intended when this occurs in batch mode. To remedy the error, rename
tests so that they all have unique names.
++++
+*** ERT can generate JUnit test reports.
+When environment variable 'EMACS_TEST_JUNIT_REPORT' is set, ERT
+generates a JUnit test report under this file name. This is useful
+for Emacs integration into CI/CD test environments.
+
** Emoji
+++
@@ -1143,6 +1149,7 @@ This variable is bound to t during the preparation of a
"*Help*" buffer.
** 'date-to-time' now assumes earliest values if its argument lacks
month, day, or time. For example, (date-to-time "2021-12-04") now
assumes a time of 00:00 instead of signaling an error.
+
* Changes in Emacs 29.1 on Non-Free Operating Systems
diff --git a/etc/NEWS.28 b/etc/NEWS.28
index eb65213..d2565e5 100644
--- a/etc/NEWS.28
+++ b/etc/NEWS.28
@@ -1588,9 +1588,9 @@ and the result is not truncated in any way.
It no longer has lower precedence than '+' and '-'.
---
-*** Calc now marks its windows dedicated.
-The new user option 'calc-make-windows-dedicated' controls this. It
-is t by default; set to nil to get back the old behavior.
+*** New user option 'calc-make-windows-dedicated'.
+When this user option is non-nil, Calc will mark its windows as
+dedicated.
** Calendar
diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el
index 9774ddf..d426e28 100644
--- a/lisp/calc/calc.el
+++ b/lisp/calc/calc.el
@@ -1423,7 +1423,7 @@ commands given here will actually operate on the
*Calculator* stack."
(require 'calc-ext)
(calc-set-language calc-language calc-language-option t)))
-(defcustom calc-make-windows-dedicated t
+(defcustom calc-make-windows-dedicated nil
"If non-nil, windows displaying Calc buffers will be marked dedicated.
See `window-dedicated-p' for what that means."
:version "28.1"
diff --git a/lisp/completion.el b/lisp/completion.el
index 643f2da..a77cccd 100644
--- a/lisp/completion.el
+++ b/lisp/completion.el
@@ -492,7 +492,7 @@ Used to decide whether to save completions.")
table))
;; Old name, non-namespace-clean.
-(defvaralias 'cmpl-syntax-table 'completion-syntax-table)
+(define-obsolete-variable-alias 'cmpl-syntax-table 'completion-syntax-table
"29.1")
(defvar-local completion-syntax-table completion-standard-syntax-table
"This variable holds the current completion syntax table.")
@@ -2220,7 +2220,7 @@ TYPE is the type of the wrapper to be added. Can be
:before or :under."
(completion-def-wrapper 'delete-backward-char-untabify :backward)
;; Old name, non-namespace-clean.
-(defalias 'initialize-completions #'completion-initialize)
+(define-obsolete-function-alias 'initialize-completions
#'completion-initialize "29.1")
(provide 'completion)
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index 946193e..981e239 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -65,6 +65,8 @@
(require 'pp)
(require 'map)
+(autoload 'xml-escape-string "xml.el")
+
;;; UI customization options.
(defgroup ert ()
@@ -247,7 +249,6 @@ in batch mode, an error is signalled.
"%s\\(\\s-\\|$\\)")
"The regexp the `find-function' mechanisms use for finding test
definitions.")
-
(define-error 'ert-test-failed "Test failed")
(define-error 'ert-test-skipped "Test skipped")
@@ -677,7 +678,6 @@ and is displayed in front of the value of MESSAGE-FORM."
,@body))
-
;;; Facilities for running a single test.
(defvar ert-debug-on-error nil
@@ -1437,7 +1437,9 @@ Returns the stats object."
(if (getenv "EMACS_TEST_VERBOSE")
(ert-reason-for-test-result result)
""))))
- (message "%s" "")))))
+ (message "%s" ""))
+ (when (getenv "EMACS_TEST_JUNIT_REPORT")
+ (ert-write-junit-test-report stats)))))
(test-started)
(test-ended
(cl-destructuring-bind (stats test result) event-args
@@ -1525,6 +1527,128 @@ the tests)."
(backtrace))
(kill-emacs 2))))
+(defun ert-write-junit-test-report (stats)
+ "Write a JUnit test report, generated from STATS."
+ ;;
https://www.ibm.com/docs/de/developer-for-zos/14.1.0?topic=formats-junit-xml-format
+ ;; https://llg.cubic.org/docs/junit/
+ (unless (zerop (length (ert--stats-tests stats)))
+ (when-let ((test-file
+ (symbol-file
+ (ert-test-name (aref (ert--stats-tests stats) 0))
'ert--test)))
+ (with-temp-file (file-name-with-extension test-file "xml")
+ (insert "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
+ (insert (format "<testsuites name=\"%s\" tests=\"%s\" failures=\"%s\"
skipped=\"%s\" time=\"%s\">\n"
+ (file-name-nondirectory test-file)
+ (ert-stats-total stats)
+ (ert-stats-completed-unexpected stats)
+ (ert-stats-skipped stats)
+ (float-time
+ (time-subtract
+ (ert--stats-end-time stats)
+ (ert--stats-start-time stats)))))
+ (insert (format " <testsuite id=\"0\" name=\"%s\" tests=\"%s\"
failures=\"%s\" skipped=\"%s\" time=\"%s\" timestamp=\"%s\">\n"
+ (file-name-nondirectory test-file)
+ (ert-stats-total stats)
+ (ert-stats-completed-unexpected stats)
+ (ert-stats-skipped stats)
+ (float-time
+ (time-subtract
+ (ert--stats-end-time stats)
+ (ert--stats-start-time stats)))
+ (ert--format-time-iso8601 (ert--stats-end-time
stats))))
+ (insert " <properties>\n"
+ (format " <property name=\"selector\" value=\"%s\"/>\n"
+ (ert--stats-selector stats))
+ " </properties>\n")
+ (cl-loop for test across (ert--stats-tests stats)
+ for result = (ert-test-most-recent-result test) do
+ (insert (format " <testcase name=\"%s\" status=\"%s\"
time=\"%s\""
+ (xml-escape-string
+ (symbol-name (ert-test-name test)))
+ (ert-string-for-test-result
+ result
+ (ert-test-result-expected-p test result))
+ (ert-test-result-duration result)))
+ (if (and (ert-test-result-expected-p test result)
+ (not (ert-test-skipped-p result))
+ (zerop (length (ert-test-result-messages result))))
+ (insert "/>\n")
+ (insert ">\n")
+ (if (ert-test-skipped-p result)
+ (insert (format " <skipped message=\"%s\"
type=\"%s\">\n"
+ (xml-escape-string
+ (string-trim
+ (ert-reason-for-test-result result)))
+ (ert-string-for-test-result
+ result
+ (ert-test-result-expected-p
+ test result)))
+ (xml-escape-string
+ (string-trim
+ (ert-reason-for-test-result result)))
+ "\n"
+ " </skipped>\n")
+ (unless
+ (ert-test-result-type-p
+ result (ert-test-expected-result-type test))
+ (insert (format " <failure message=\"%s\"
type=\"%s\">\n"
+ (xml-escape-string
+ (string-trim
+ (ert-reason-for-test-result result)))
+ (ert-string-for-test-result
+ result
+ (ert-test-result-expected-p
+ test result)))
+ (xml-escape-string
+ (string-trim
+ (ert-reason-for-test-result result)))
+ "\n"
+ " </failure>\n")))
+ (unless (zerop (length (ert-test-result-messages result)))
+ (insert " <system-out>\n"
+ (xml-escape-string
+ (ert-test-result-messages result))
+ " </system-out>\n"))
+ (insert " </testcase>\n")))
+ (insert " </testsuite>\n")
+ (insert "</testsuites>\n")))))
+
+(defun ert-write-junit-test-summary-report (&rest logfiles)
+ "Write a JUnit summary test report, generated from LOGFILES."
+ (let ((report (file-name-with-extension
+ (getenv "EMACS_TEST_JUNIT_REPORT") "xml"))
+ (tests 0) (failures 0) (skipped 0) (time 0) (id 0))
+ (with-temp-file report
+ (dolist (logfile logfiles)
+ (let ((test-file (file-name-with-extension logfile "xml")))
+ (when (file-readable-p test-file)
+ (insert-file-contents-literally test-file)
+ (when (looking-at-p
+ (regexp-quote "<?xml version=\"1.0\" encoding=\"utf-8\"?>"))
+ (delete-region (point) (line-beginning-position 2)))
+ (when (looking-at
+ "<testsuites name=\".+\" tests=\"\\(.+\\)\"
failures=\"\\(.+\\)\" skipped=\"\\(.+\\)\" time=\"\\(.+\\)\">")
+ (cl-incf tests (string-to-number (match-string 1)))
+ (cl-incf failures (string-to-number (match-string 2)))
+ (cl-incf skipped (string-to-number (match-string 3)))
+ (cl-incf time (string-to-number (match-string 4)))
+ (delete-region (point) (line-beginning-position 2)))
+ (when (looking-at " <testsuite id=\"\\(0\\)\"")
+ (replace-match (number-to-string id) nil nil nil 1)
+ (cl-incf id 1))
+ (goto-char (point-max))
+ (beginning-of-line 0)
+ (when (looking-at-p "</testsuites>")
+ (delete-region (point) (line-beginning-position 2)))
+ (narrow-to-region (point-max) (point-max)))))
+
+ (insert "</testsuites>\n")
+ (widen)
+ (goto-char (point-min))
+ (insert "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
+ (insert (format "<testsuites name=\"%s\" tests=\"%s\" failures=\"%s\"
skipped=\"%s\" time=\"%s\">\n"
+ (file-name-nondirectory report)
+ tests failures skipped time)))))
(defun ert-summarize-tests-batch-and-exit (&optional high)
"Summarize the results of testing.
@@ -1540,6 +1664,8 @@ If HIGH is a natural number, the HIGH long lasting tests
are summarized."
;; behavior.
(setq attempt-stack-overflow-recovery nil
attempt-orderly-shutdown-on-fatal-signal nil)
+ (when (getenv "EMACS_TEST_JUNIT_REPORT")
+ (apply #'ert-write-junit-test-summary-report command-line-args-left))
(let ((nlogs (length command-line-args-left))
(ntests 0) (nrun 0) (nexpected 0) (nunexpected 0) (nskipped 0)
nnotrun logfile notests badtests unexpected skipped tests)
@@ -1855,7 +1981,6 @@ Also sets `ert--results-progress-bar-button-begin'."
;; should test it again.)
"\n")))
-
(defvar ert-test-run-redisplay-interval-secs .1
"How many seconds ERT should wait between redisplays while running tests.
@@ -2037,7 +2162,6 @@ STATS is the stats object; LISTENER is the results
listener."
(goto-char (1- (point-max)))
buffer)))))
-
(defvar ert--selector-history nil
"List of recent test selectors read from terminal.")
diff --git a/lisp/emacs-lisp/generator.el b/lisp/emacs-lisp/generator.el
index cb02410..ac14127 100644
--- a/lisp/emacs-lisp/generator.el
+++ b/lisp/emacs-lisp/generator.el
@@ -143,8 +143,7 @@ the CPS state machinery."
(setf ,static-var ,dynamic-var)))))
(defmacro cps--with-dynamic-binding (dynamic-var static-var &rest body)
- "Evaluate BODY such that generated atomic evaluations run with
-DYNAMIC-VAR bound to STATIC-VAR."
+ "Run BODY's atomic evaluations run with DYNAMIC-VAR bound to STATIC-VAR."
(declare (indent 2))
`(cps--with-value-wrapper
(cps--make-dynamic-binding-wrapper ,dynamic-var ,static-var)
@@ -645,12 +644,11 @@ modified copy."
(iter-close iterator)))))
iterator))))
-(defun iter-yield (value)
+(defun iter-yield (_value)
"When used inside a generator, yield control to caller.
The caller of `iter-next' receives VALUE, and the next call to
`iter-next' resumes execution with the form immediately following this
`iter-yield' call."
- (identity value)
(error "`iter-yield' used outside a generator"))
(defmacro iter-yield-from (value)
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index a2464ad..213b7ab 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -945,12 +945,12 @@ at the moment are:
;; In that case, unwrap the value before checking the delimiter
;; value.
(if (and val
- (not (processp val))
+ (not (eshell-processp val))
(not (eq val t)))
(error "Unmatched delimiter: %S" val)
;; Eshell-command expect a list like (<process>) to know if the
;; command should be async or not.
- (or (and (processp val) delim) val)))))
+ (or (and (eshell-processp val) delim) val)))))
(defun eshell-resume-command (proc status)
"Resume the current command when a process ends."
diff --git a/lisp/help-macro.el b/lisp/help-macro.el
index cd1b51e..ecc7eba 100644
--- a/lisp/help-macro.el
+++ b/lisp/help-macro.el
@@ -167,14 +167,18 @@ and then returns."
(let ((cursor-in-echo-area t)
(overriding-local-map local-map))
(setq key (read-key-sequence
- (format "Type one of the options listed%s: "
+ (format "Type one of listed options%s: "
(if (pos-visible-in-window-p
(point-max))
""
(concat ", or "
(help--key-description-fontified (kbd "<PageDown>"))
- " or "
+ "/"
(help--key-description-fontified (kbd "<PageUp>"))
+ "/"
+
(help--key-description-fontified (kbd "SPC"))
+ "/"
+
(help--key-description-fontified (kbd "DEL"))
" to scroll"))))
char (aref key 0)))
diff --git a/lisp/ielm.el b/lisp/ielm.el
index 39820a8..ec7f010 100644
--- a/lisp/ielm.el
+++ b/lisp/ielm.el
@@ -148,28 +148,28 @@ such as `edebug-defun' to work with such inputs."
This variable is buffer-local.")
(defvar ielm-header
- "*** Welcome to IELM *** Type (describe-mode) for help.\n"
+ (substitute-command-keys
+ "*** Welcome to IELM *** Type (describe-mode) or press \
+\\[describe-mode] for help.\n")
"Message to display when IELM is started.")
(defvaralias 'inferior-emacs-lisp-mode-map 'ielm-map)
-(defvar ielm-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\t" 'ielm-tab)
- (define-key map "\C-m" 'ielm-return)
- (define-key map "\e\C-m" 'ielm-return-for-effect)
- (define-key map "\C-j" 'ielm-send-input)
- (define-key map "\e\C-x" 'eval-defun) ; for consistency with
- (define-key map "\e\t" 'completion-at-point) ; lisp-interaction-mode
- ;; These bindings are from `lisp-mode-shared-map' -- can you inherit
- ;; from more than one keymap??
- (define-key map "\e\C-q" 'indent-sexp)
- (define-key map "\177" 'backward-delete-char-untabify)
- ;; Some convenience bindings for setting the working buffer
- (define-key map "\C-c\C-b" 'ielm-change-working-buffer)
- (define-key map "\C-c\C-f" 'ielm-display-working-buffer)
- (define-key map "\C-c\C-v" 'ielm-print-working-buffer)
- map)
- "Keymap for IELM mode.")
+(defvar-keymap ielm-map
+ :doc "Keymap for IELM mode."
+ "TAB" #'ielm-tab
+ "RET" #'ielm-return
+ "M-RET" #'ielm-return-for-effect
+ "C-j" #'ielm-send-input
+ "C-M-x" #'eval-defun ; for consistency with
+ "M-TAB" #'completion-at-point ; lisp-interaction-mode
+ ;; These bindings are from `lisp-mode-shared-map' -- can you inherit
+ ;; from more than one keymap??
+ "C-M-q" #'indent-sexp
+ "DEL" #'backward-delete-char-untabify
+ ;; Some convenience bindings for setting the working buffer
+ "C-c C-b" #'ielm-change-working-buffer
+ "C-c C-f" #'ielm-display-working-buffer
+ "C-c C-v" #'ielm-print-working-buffer)
(easy-menu-define ielm-menu ielm-map
"IELM mode menu."
diff --git a/lisp/international/robin.el b/lisp/international/robin.el
index c38cd82..4c498d7 100644
--- a/lisp/international/robin.el
+++ b/lisp/international/robin.el
@@ -529,10 +529,10 @@ Use the longest match method to select a rule."
(insert (cadr tree))
(delete-char (- end begin)))))
-;; for backward compatibility
-
-(fset 'robin-transliterate-region 'robin-convert-region)
-(fset 'robin-transliterate-buffer 'robin-convert-buffer)
+(define-obsolete-function-alias 'robin-transliterate-region
+ #'robin-convert-region "29.1")
+(define-obsolete-function-alias 'robin-transliterate-buffer
+ #'robin-convert-buffer "29.1")
;;; Reverse conversion
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index 64acc41..1636e21 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -680,8 +680,8 @@ user actually typed in."
(match-string which arg)
(throw 'pcompleted nil))))
-(defalias 'pcomplete-match-beginning 'match-beginning)
-(defalias 'pcomplete-match-end 'match-end)
+(define-obsolete-function-alias 'pcomplete-match-beginning #'match-beginning
"29.1")
+(define-obsolete-function-alias 'pcomplete-match-end #'match-end "29.1")
(defsubst pcomplete--test (pred arg)
"Perform a programmable completion predicate match."
@@ -1006,7 +1006,7 @@ Arguments NO-GANGING and ARGS-FOLLOW are currently
ignored."
((eq arg-char ?*) (pcomplete-executables))
((eq arg-char ??) nil)
((eq arg-char ?.) (pcomplete-entries))
- ((eq arg-char ?\() (eval result))))))
+ ((eq arg-char ?\() (eval result t))))))
(setq index (1+ index))))))))
(defun pcomplete--here (&optional form stub paring form-only)
@@ -1040,7 +1040,7 @@ See the documentation for `pcomplete-here'."
(funcall form)
;; Old calling convention, might still be used by files
;; byte-compiled with the older code.
- (eval form)))))
+ (eval form t)))))
(defmacro pcomplete-here* (&optional form stub form-only)
@@ -1062,9 +1062,9 @@ See the documentation for `pcomplete-here'."
pcomplete-window-restore-timer nil))
(define-obsolete-function-alias 'pcomplete-event-matches-key-specifier-p
- 'eq "27.1")
+ #'eq "27.1")
-(define-obsolete-function-alias 'pcomplete-read-event 'read-event "27.1")
+(define-obsolete-function-alias 'pcomplete-read-event #'read-event "27.1")
(defun pcomplete-show-completions (completions)
"List in help buffer sorted COMPLETIONS.
@@ -1244,7 +1244,7 @@ If specific documentation can't be given, be generic."
(fboundp 'Info-goto-node))
(listp pcomplete-help)))
(if (listp pcomplete-help)
- (message "%s" (eval pcomplete-help))
+ (message "%s" (eval pcomplete-help t))
(save-window-excursion (info))
(declare-function Info-goto-node
"info" (nodename &optional fork strict-case))
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 47d8d1c..b403de8 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -2996,8 +2996,9 @@ killed."
(mapconcat #'identity args " ")))
(with-current-buffer buffer
(inferior-python-mode))
- (when show (display-buffer buffer))
(and internal (set-process-query-on-exit-flag process nil))))
+ (when show
+ (pop-to-buffer proc-buffer-name))
proc-buffer-name))))
;;;###autoload
@@ -3029,7 +3030,6 @@ process buffer for a list of commands.)"
(python-shell-make-comint
(or cmd (python-shell-calculate-command))
(python-shell-get-process-name dedicated) show)))
- (set-buffer buffer)
(get-buffer-process buffer)))
(defun run-python-internal ()
diff --git a/lisp/progmodes/xscheme.el b/lisp/progmodes/xscheme.el
index 26ffe33..e7667eb 100644
--- a/lisp/progmodes/xscheme.el
+++ b/lisp/progmodes/xscheme.el
@@ -574,9 +574,8 @@ See also the commands \\[xscheme-yank-pop] and
\\[xscheme-yank-push]."
(if (consp arg)
(exchange-point-and-mark)))
-;; Old name, to avoid errors in users' init files.
-(fset 'xscheme-yank-previous-send
- 'xscheme-yank)
+(define-obsolete-function-alias 'xscheme-yank-previous-send
+ #'xscheme-yank "29.1")
(defun xscheme-yank-pop (arg)
"Insert or replace a just-yanked expression with an older expression.
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 7a5221d..07aa0f2 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -1178,7 +1178,7 @@ which means the last tab on the tab bar. For example,
`C-u 2
<MODIFIER>-9' selects the tab before the last tab."
(interactive "p")
(tab-bar-select-tab (- (length (funcall tab-bar-tabs-function))
- (1- (or arg 1)))))
+ (1- (abs (or arg 1))))))
(defun tab-bar-switch-to-recent-tab (&optional arg)
"Switch to ARGth most recently visited tab.
diff --git a/make-dist b/make-dist
index eb04015..db7a74b 100755
--- a/make-dist
+++ b/make-dist
@@ -299,13 +299,6 @@ if [ $check = yes ]; then
echo "${bogosities}"
fi
- ## This exits with non-zero status if any .info files need
- ## rebuilding.
- if [ -r Makefile ] && [ "$with_info" = "yes" ]; then
- echo "Checking to see if info files are up-to-date..."
- make --question info || error=yes
- fi
-
## Is this a release?
case $version in
[1-9][0-9].[0-9])
@@ -392,9 +385,11 @@ manifest=MANIFEST
# other way when adding or deleting a distributed file while not using Git.
# TODO: maybe this should ignore $update, and always update MANIFEST
# if .git is present.
+# Filter out the files in msdos/autogen/, as they aren't useful in the
+# tarball, and get in the way during the build of the MSDOS port.
if ( [ $update = yes ] || [ ! -f $manifest ] ) && [ -r .git ]; then
echo "Updating $manifest"
- git ls-files > $manifest || exit
+ git ls-files | sed -e '/^msdos\/autogen\//d' > $manifest || exit
printf '%s\n' $possibly_non_vc_files $info_files >>$manifest || exit
sort -u -o $manifest $manifest || exit
fi
diff --git a/src/bignum.c b/src/bignum.c
index 1ac75c1..5c587fc 100644
--- a/src/bignum.c
+++ b/src/bignum.c
@@ -53,6 +53,15 @@ init_bignum (void)
{
eassert (mp_bits_per_limb == GMP_NUMB_BITS);
integer_width = 1 << 16;
+
+ /* FIXME: The Info node `(gmp) Custom Allocation' states: "No error
+ return is allowed from any of these functions, if they return
+ then they must have performed the specified operation. [...]
+ There's currently no defined way for the allocation functions to
+ recover from an error such as out of memory, they must terminate
+ program execution. A 'longjmp' or throwing a C++ exception will
+ have undefined results." But xmalloc and xrealloc do call
+ 'longjmp'. */
mp_set_memory_functions (xmalloc, xrealloc_for_gmp, xfree_for_gmp);
for (int i = 0; i < ARRAYELTS (mpz); i++)
diff --git a/src/sqlite.c b/src/sqlite.c
index 4968ce3..428b84b 100644
--- a/src/sqlite.c
+++ b/src/sqlite.c
@@ -247,7 +247,7 @@ If FILE is nil, an in-memory database will be opened
instead. */)
if (!NILP (file))
{
CHECK_STRING (file);
- file = encode_string (Fexpand_file_name (file, Qnil));
+ file = ENCODE_FILE (Fexpand_file_name (file, Qnil));
name = xstrdup (SSDATA (file));
}
else
@@ -591,16 +591,42 @@ DEFUN ("sqlite-load-extension", Fsqlite_load_extension,
doc: /* Load an SQlite MODULE into DB.
MODULE should be the name of an SQlite module's file, a
shared library in the system-dependent format and having a
-system-dependent file-name extension. */)
+system-dependent file-name extension.
+
+Only modules on Emacs' list of allowed modules can be loaded. */)
(Lisp_Object db, Lisp_Object module)
{
check_sqlite (db, false);
CHECK_STRING (module);
- Lisp_Object module_encoded = encode_string (Fexpand_file_name (module,
Qnil));
- sqlite3 *sdb = XSQLITE (db)->db;
- int result = sqlite3_load_extension (sdb, SSDATA (module_encoded),
- NULL, NULL);
+ /* Add names of useful and free modules here. */
+ const char *allowlist[3] = { "pcre", "csvtable", NULL };
+ char *name = SSDATA (Ffile_name_nondirectory (module));
+ /* Possibly skip past a common prefix. */
+ const char *prefix = "libsqlite3_mod_";
+ if (!strncmp (name, prefix, strlen (prefix)))
+ name += strlen (prefix);
+
+ bool do_allow = false;
+ for (const char **allow = allowlist; *allow; allow++)
+ {
+ if (strlen (*allow) < strlen (name)
+ && !strncmp (*allow, name, strlen (*allow))
+ && (!strcmp (name + strlen (*allow), ".so")
+ || !strcmp (name + strlen (*allow), ".DLL")))
+ {
+ do_allow = true;
+ break;
+ }
+ }
+
+ if (!do_allow)
+ xsignal (Qerror, build_string ("Module name not on allowlist"));
+
+ int result = sqlite3_load_extension
+ (XSQLITE (db)->db,
+ SSDATA (ENCODE_FILE (Fexpand_file_name (module, Qnil))),
+ NULL, NULL);
if (result == SQLITE_OK)
return Qt;
return Qnil;
diff --git a/src/xdisp.c b/src/xdisp.c
index 96c4347..2d45a8d 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -10423,11 +10423,12 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int
to_x, int to_y, int to_vpos
/* Move iterator IT backward by a specified y-distance DY, DY >= 0.
- If DY > 0, move IT backward at least that many pixels. DY = 0
- means move IT backward to the preceding line start or BEGV. This
- function may move over more than DY pixels if IT->current_y - DY
- ends up in the middle of a line; in this case IT->current_y will be
- set to the top of the line moved to. */
+ If DY > 0, move IT backward that many pixels.
+ DY = 0 means move IT backward to the preceding line start or to BEGV.
+ This function may move over less or more than DY pixels if
+ IT->current_y - DY ends up in the middle of a line; in this case
+ IT->current_y will be set to the top of the line either before or
+ after the exact pixel coordinate. */
void
move_it_vertically_backward (struct it *it, int dy)
diff --git a/test/Makefile.in b/test/Makefile.in
index f2c4958..eeda291 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -353,6 +353,7 @@ mostlyclean:
clean:
find . '(' -name '*.log' -o -name '*.log~' ')' $(FIND_DELETE)
+ find . '(' -name '*.xml' -a ! -path '*resources*' ')' $(FIND_DELETE)
rm -f ${srcdir}/lisp/gnus/mml-sec-resources/random_seed
rm -f $(test_module_dir)/*.o $(test_module_dir)/*.so \
$(test_module_dir)/*.dll
diff --git a/test/README b/test/README
index 4d447c9..2bd84b5 100644
--- a/test/README
+++ b/test/README
@@ -114,6 +114,9 @@ mode--only the names of the failed tests are listed. If the
$EMACS_TEST_VERBOSE environment variable is set, the failure summaries
will also include the data from the failing test.
+If the $EMACS_TEST_JUNIT_REPORT environment variable is set to a file
+name, a JUnit test report is generated under this name.
+
Some of the tests require a remote temporary directory
(autorevert-tests.el, filenotify-tests.el, shadowfile-tests.el and
tramp-tests.el). Per default, a mock-up connection method is used
diff --git a/test/infra/Makefile.in b/test/infra/Makefile.in
index fd11d36..e4f9974 100644
--- a/test/infra/Makefile.in
+++ b/test/infra/Makefile.in
@@ -93,10 +93,8 @@ all: generate-test-jobs
.PHONY: generate-test-jobs $(FILE) $(SUBDIR_TARGETS)
-generate-test-jobs: clean $(FILE) $(SUBDIR_TARGETS)
+generate-test-jobs: $(FILE) $(SUBDIR_TARGETS)
$(FILE):
$(AM_V_GEN)
-
-clean:
- @rm -f $(FILE)
+ @echo "# Generated by \"make generate-test-jobs\", don't edit." >$(FILE)
diff --git a/test/infra/gitlab-ci.yml b/test/infra/gitlab-ci.yml
index b0ea681..3903642 100644
--- a/test/infra/gitlab-ci.yml
+++ b/test/infra/gitlab-ci.yml
@@ -44,6 +44,7 @@ workflow:
variables:
GIT_STRATEGY: fetch
EMACS_EMBA_CI: 1
+ EMACS_TEST_JUNIT_REPORT: junit-test-report.xml
EMACS_TEST_TIMEOUT: 3600
EMACS_TEST_VERBOSE: 1
# Use TLS
https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
@@ -85,7 +86,7 @@ default:
# TODO: with make -j4 several of the tests were failing, for
# example shadowfile-tests, but passed without it.
- 'export PWD=$(pwd)'
- - 'docker run -i -e EMACS_EMBA_CI=${EMACS_EMBA_CI} -e
EMACS_TEST_TIMEOUT=${EMACS_TEST_TIMEOUT} -e
EMACS_TEST_VERBOSE=${EMACS_TEST_VERBOSE} --volumes-from $(docker ps -q -f
"label=com.gitlab.gitlab-runner.job.id=${CI_JOB_ID}"):ro --name ${test_name}
${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG} /bin/bash -c "git fetch ${PWD} HEAD
&& echo checking out these updated files && git diff --name-only FETCH_HEAD &&
( git diff --name-only FETCH_HEAD | xargs git checkout -f FETCH_HEAD ) && make
- [...]
+ - 'docker run -i -e EMACS_EMBA_CI=${EMACS_EMBA_CI} -e
EMACS_TEST_JUNIT_REPORT=${EMACS_TEST_JUNIT_REPORT} -e
EMACS_TEST_TIMEOUT=${EMACS_TEST_TIMEOUT} -e
EMACS_TEST_VERBOSE=${EMACS_TEST_VERBOSE} --volumes-from $(docker ps -q -f
"label=com.gitlab.gitlab-runner.job.id=${CI_JOB_ID}"):ro --name ${test_name}
${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG} /bin/bash -c "git fetch ${PWD} HEAD
&& echo checking out these updated files && git diff --name-only FETCH_HEAD &&
( git diff --name-only FET [...]
after_script:
# - docker ps -a
# - printenv
@@ -93,7 +94,8 @@ default:
# Prepare test artifacts.
- test -n "$(docker ps -aq -f name=${test_name})" && docker cp
${test_name}:checkout/test ${test_name}
- test -n "$(docker ps -aq -f name=${test_name})" && docker rm ${test_name}
- - find ${test_name} ! -name "*.log" -type f -delete
+ - find ${test_name} ! \( -name "*.log" -o -name ${EMACS_TEST_JUNIT_REPORT}
\) -type f -delete
+ # BusyBox find does not know -empty.
- find ${test_name} -type d -depth -exec rmdir {} + 2>/dev/null
.build-template:
@@ -103,7 +105,6 @@ default:
when: always
- changes:
- "**.in"
- - "**.yml"
- GNUmakefile
- aclocal.m4
- autogen.sh
@@ -112,7 +113,7 @@ default:
- lib/malloc/*.{h,c}
- lisp/emacs-lisp/*.el
- src/*.{h,c}
- - test/infra/Dockerfile.emba
+ - test/infra/*
- changes:
# gfilemonitor, kqueue
- src/gfilenotify.c
@@ -133,9 +134,11 @@ default:
name: ${test_name}
public: true
expire_in: 1 week
+ when: always
paths:
- ${test_name}/
- when: always
+ reports:
+ junit: ${test_name}/${EMACS_TEST_JUNIT_REPORT}
.gnustep-template:
rules:
@@ -143,12 +146,11 @@ default:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
changes:
- "**.in"
- - "**.yml"
- src/ns*.{h,m}
- src/macfont.{h,m}
- lisp/term/ns-win.el
- nextstep/**
- - test/infra/Dockerfile.emba
+ - test/infra/*
.filenotify-gio-template:
rules:
@@ -156,12 +158,11 @@ default:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
changes:
- "**.in"
- - "**.yml"
- lisp/autorevert.el
- lisp/filenotify.el
- lisp/net/tramp-sh.el
- src/gfilenotify.c
- - test/infra/Dockerfile.emba
+ - test/infra/*
- test/lisp/autorevert-tests.el
- test/lisp/filenotify-tests.el
@@ -171,11 +172,10 @@ default:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
changes:
- "**.in"
- - "**.yml"
- lisp/emacs-lisp/comp.el
- lisp/emacs-lisp/comp-cstr.el
- src/comp.{h,m}
- - test/infra/Dockerfile.emba
+ - test/infra/*
- test/src/comp-resources/*.el
- test/src/comp-tests.el
timeout: 8 hours
diff --git a/test/infra/test-jobs.yml b/test/infra/test-jobs.yml
index bad8575..63b052b 100644
--- a/test/infra/test-jobs.yml
+++ b/test/infra/test-jobs.yml
@@ -1,3 +1,4 @@
+# Generated by "make generate-test-jobs", don't edit.
test-lib-src-inotify:
stage: normal
diff --git a/test/lisp/progmodes/python-tests.el
b/test/lisp/progmodes/python-tests.el
index 15bda5c..2d1ccdc 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -5449,15 +5449,21 @@ buffer with overlapping strings."
(python-nav-end-of-statement)))
(should (eolp))))
-;; After call `run-python' the buffer running the python process is current.
-(ert-deftest python-tests--bug31398 ()
- "Test for https://debbugs.gnu.org/31398 ."
+;; Interactively, `run-python' focuses the buffer running the
+;; interpreter.
+(ert-deftest python-tests--run-python-selects-window ()
+ "Test for bug#31398. See also bug#44421 and bug#52380."
(skip-unless (executable-find python-tests-shell-interpreter))
- (let ((buffer (process-buffer (run-python nil nil 'show))))
- (should (eq buffer (current-buffer)))
+ (let* ((buffer (process-buffer (run-python nil nil 'show)))
+ (window (get-buffer-window buffer)))
+ ;; We look at `selected-window' rather than `current-buffer'
+ ;; because as `(elisp)Current buffer' says, the latter will only
+ ;; be synchronized with the former when returning to the "command
+ ;; loop"; until then, `current-buffer' can change arbitrarily.
+ (should (eq window (selected-window)))
(pop-to-buffer (other-buffer))
(run-python nil nil 'show)
- (should (eq buffer (current-buffer)))))
+ (should (eq window (selected-window)))))
(ert-deftest python-tests--fill-long-first-line ()
(should
diff --git a/test/src/sqlite-tests.el b/test/src/sqlite-tests.el
index 6a88f0f..d1076e4 100644
--- a/test/src/sqlite-tests.el
+++ b/test/src/sqlite-tests.el
@@ -182,4 +182,36 @@
(sqlite-close db)
(should-error (sqlite-select db "select * from test6"))))
+(ert-deftest sqlite-load-extension ()
+ (skip-unless (sqlite-available-p))
+ (let (db)
+ (setq db (sqlite-open))
+ (should-error
+ (sqlite-load-extension db "/usr/lib/sqlite3/notpcre.so"))
+ (should-error
+ (sqlite-load-extension db "/usr/lib/sqlite3/n"))
+ (should-error
+ (sqlite-load-extension db "/usr/lib/sqlite3/"))
+ (should-error
+ (sqlite-load-extension db "/usr/lib/sqlite3"))
+ (should
+ (memq
+ (sqlite-load-extension db "/usr/lib/sqlite3/pcre.so")
+ '(nil t)))
+
+ (should-error
+ (sqlite-load-extension
+ db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_notcsvtable.so"))
+ (should-error
+ (sqlite-load-extension
+ db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtablen.so"))
+ (should-error
+ (sqlite-load-extension
+ db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable"))
+ (should
+ (memq
+ (sqlite-load-extension
+ db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable.so")
+ '(nil t)))))
+
;;; sqlite-tests.el ends here