Subject: bug#61637: 30.0.50; Fix Eglot tests that need HOME=~USER

From: "Basil L. Contovounesios" <[email-masked]>
Date: Sun, 19 Feb 2023 19:10:03 +0000

Severity: minor
Tags: patch

With pylsp and rust-analyzer installed, I have been seeing some or all
of these failures for quite a while now:

The main problem is that:
0. test/Makefile.in sets HOME=/nonexistent
1. lisp/emacs-lisp/ert-x.el sets HOME=/tmp :(
2. eglot--call-with-fixture tries to detect when HOME is nonexistent,
   but /tmp exists, so that's left unchanged
3. The Rust tools look under HOME=/tmp for which toolchain to use, but
   the answer is under ~USER, so they give up

The following patch temporarily sets HOME=~USER in only those tests that
need it.  The patch consolidates some let-bindings into a single form to
minimise collateral indentation changes.  It also bumps the
rust-analyzer client/registerCapability timeout from 1 second to 3,
because sometimes 1 second was too short a wait.  Finally, it updates
the expected autopep8 reformatting results to what I see locally, and
skips a test that fails without YASnippet.

>From 825d0781522f87c6a2cc954a85b2c48a499d4857 Mon Sep 17 00:00:00 2001
From: "Basil L. Contovounesios" <[email-masked]>
Date: Sun, 19 Feb 2023 17:41:48 +0000
Subject: [PATCH 1/2] Fix eglot-tests.el that need HOME=~USER

* test/lisp/progmodes/eglot-tests.el (eglot-tests--real-home-env):
New helper function.
(eglot-test-rust-analyzer-watches-files)
(eglot-test-diagnostic-tags-unnecessary-code)
(eglot-test-rust-analyzer-hover-after-edit)
(eglot-test-rust-on-type-formatting)
(eglot-test-project-wide-diagnostics-rust-analyzer): Use it to run
cargo and rust-analyzer under HOME=~USER.

(eglot-test-python-autopep-formatting): Update expected formats for
latest autopep8.
(eglot-test-json-basic): Skip when YASnippet is missing.
---
 test/lisp/progmodes/eglot-tests.el | 108 +++++++++++++++++------------
 1 file changed, 63 insertions(+), 45 deletions(-)

diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el
index 4b6528351b2..4e1b025e63f 100644
--- a/test/lisp/progmodes/eglot-tests.el
+++ b/test/lisp/progmodes/eglot-tests.el
@@ -86,6 +86,14 @@ eglot--make-file-or-dir
           (t
            (eglot--error "Expected a string or a directory spec")))))
 
+(defun eglot-tests--real-home-env ()
+  "Return a `process-environment' with user's real HOME directory.
+This uses `user-login-name' to work around cases where the HOME
+environment variable has been set to something like
+\"/nonexistent\" or `temporary-file-directory'."
+  (cons (concat "HOME=" (expand-file-name (concat "~" (user-login-name))))
+        process-environment))
+
 (defun eglot--call-with-fixture (fixture fn)
   "Helper for `eglot--with-fixture'.  Run FN under FIXTURE."
   (let* ((fixture-directory (make-nearby-temp-file "eglot--fixture" t))
@@ -394,27 +402,27 @@ eglot-test-rust-analyzer-watches-files
   "Start rust-analyzer.  Notify it when a critical file changes."
   (skip-unless (executable-find "rust-analyzer"))
   (skip-unless (executable-find "cargo"))
-  (let ((eglot-autoreconnect 1))
-    (eglot--with-fixture
-        '(("watch-project" . (("coiso.rs" . "bla")
-                              ("merdix.rs" . "bla"))))
-      (with-current-buffer
-          (eglot--find-file-noselect "watch-project/coiso.rs")
+  (eglot--with-fixture
+      '(("watch-project" . (("coiso.rs" . "bla")
+                            ("merdix.rs" . "bla"))))
+    (with-current-buffer
+        (eglot--find-file-noselect "watch-project/coiso.rs")
+      (let ((eglot-autoreconnect 1)
+            ;; Cargo doesn't work under `temporary-file-directory'.
+            (process-environment (eglot-tests--real-home-env))
+            register-id)
         (should (zerop (shell-command "cargo init")))
-        (eglot--sniffing (
-                          :server-requests s-requests
-                          :client-notifications c-notifs
-                          :client-replies c-replies
-                          )
+        (eglot--sniffing ( :server-requests s-requests
+                           :client-notifications c-notifs
+                           :client-replies c-replies)
           (should (eglot--tests-connect))
-          (let (register-id)
-            (eglot--wait-for (s-requests 1)
-                (&key id method &allow-other-keys)
-              (setq register-id id)
-              (string= method "client/registerCapability"))
-            (eglot--wait-for (c-replies 1)
-                (&key id error &allow-other-keys)
-              (and (eq id register-id) (null error))))
+          (eglot--wait-for (s-requests 3)
+              (&key id method &allow-other-keys)
+            (setq register-id id)
+            (string= method "client/registerCapability"))
+          (eglot--wait-for (c-replies 1)
+              (&key id error &allow-other-keys)
+            (and (eq id register-id) (null error)))
           (delete-file "Cargo.toml")
           (eglot--wait-for
               (c-notifs 3 "waiting for didChangeWatchedFiles notification")
@@ -453,7 +461,9 @@ eglot-test-diagnostic-tags-unnecessary-code
            "fn main() -> () { let test=3; }"))))
     (with-current-buffer
         (eglot--find-file-noselect "diagnostic-tag-project/main.rs")
-      (let ((eglot-server-programs '((rust-mode . ("rust-analyzer")))))
+      (let ((eglot-server-programs '((rust-mode . ("rust-analyzer"))))
+            ;; Cargo doesn't work under `temporary-file-directory'.
+            (process-environment (eglot-tests--real-home-env)))
         (should (zerop (shell-command "cargo init")))
         (eglot--sniffing (:server-notifications s-notifs)
           (eglot--tests-connect)
@@ -496,21 +506,20 @@ eglot-test-rust-analyzer-hover-after-edit
            "fn test() -> i32 { let test=3; return te; }"))))
     (with-current-buffer
         (eglot--find-file-noselect "hover-project/main.rs")
-      (should (zerop (shell-command "cargo init")))
-      (eglot--sniffing (
-                        :server-replies s-replies
-                        :client-requests c-reqs
-                        )
-        (eglot--tests-connect)
-        (goto-char (point-min))
-        (search-forward "return te")
-        (insert "st")
-        (progn
-          ;; simulate these two which don't happen when buffer isn't
+      (let (;; Cargo doesn't work under `temporary-file-directory'.
+            (process-environment (eglot-tests--real-home-env))
+            pending-id)
+        (should (zerop (shell-command "cargo init")))
+        (eglot--sniffing ( :server-replies s-replies
+                           :client-requests c-reqs)
+          (eglot--tests-connect)
+          (goto-char (point-min))
+          (search-forward "return te")
+          (insert "st")
+          ;; Simulate these two which don't happen when buffer isn't
           ;; visible in a window.
           (eglot--signal-textDocument/didChange)
-          (eglot--eldoc-on-demand))
-        (let (pending-id)
+          (eglot--eldoc-on-demand)
           (eglot--wait-for (c-reqs 2)
               (&key id method &allow-other-keys)
             (setq pending-id id)
@@ -683,18 +692,22 @@ eglot-test-python-autopep-formatting
     (with-current-buffer
         (eglot--find-file-noselect "project/something.py")
       (should (eglot--tests-connect))
-      ;; Try to format just the second line
+      ;; Try to format just the second line.
       (search-forward "b():pa")
       (eglot-format (line-beginning-position) (line-end-position))
-      (should (looking-at "ss"))
-      (should
-       (or (string= (buffer-string) "def a():pass\n\n\ndef b(): pass\n")
-           ;; autopep8 2.0.0 (pycodestyle: 2.9.1)
-           (string= (buffer-string) "def a():pass\n\ndef b(): pass")))
-      ;; now format the whole buffer
+      (should (looking-at-p "ss"))
+      (should (member (buffer-string)
+                      '(;; autopep8 2.0.1 (pycodestyle: 2.10.0)
+                        "def a():pass\n\ndef b():\n    pass\n"
+                        ;; autopep8 2.0.0 (pycodestyle: 2.9.1)
+                        "def a():pass\n\ndef b(): pass"
+                        "def a():pass\n\n\ndef b(): pass\n")))
+      ;; Now format the whole buffer.
       (eglot-format-buffer)
-      (should
-       (string= (buffer-string) "def a(): pass\n\n\ndef b(): pass\n")))))
+      (should (member (buffer-string)
+                      '(;; autopep8 2.0.1 (pycodestyle: 2.10.0)
+                        "def a():\n    pass\n\n\ndef b():\n    pass\n"
+                        "def a(): pass\n\n\ndef b(): pass\n"))))))
 
 (ert-deftest eglot-test-python-yapf-formatting ()
   "Test formatting in the pylsp python LSP."
@@ -728,12 +741,14 @@ eglot-test-rust-on-type-formatting
            "fn main() -> () {\n  foo\n    .bar()\n  "))))
     (with-current-buffer
         (eglot--find-file-noselect "on-type-formatting-project/main.rs")
-      (let ((eglot-server-programs '((rust-mode . ("rust-analyzer")))))
+      (let ((eglot-server-programs '((rust-mode . ("rust-analyzer"))))
+            ;; Cargo doesn't work under `temporary-file-directory'.
+            (process-environment (eglot-tests--real-home-env)))
         (should (zerop (shell-command "cargo init")))
         (eglot--sniffing (:server-notifications s-notifs)
           (should (eglot--tests-connect))
           (eglot--wait-for (s-notifs 10) (&key method &allow-other-keys)
-             (string= method "textDocument/publishDiagnostics")))
+            (string= method "textDocument/publishDiagnostics")))
         (goto-char (point-max))
         (eglot--simulate-key-event ?.)
         (should (looking-back "^    \\."))))))
@@ -808,7 +823,9 @@ eglot-test-project-wide-diagnostics-rust-analyzer
           ("other-file.rs" .
            "fn foo() -> () { let hi=3; }"))))
     (eglot--make-file-or-dir '(".git"))
-    (let ((eglot-server-programs '((rust-mode . ("rust-analyzer")))))
+    (let ((eglot-server-programs '((rust-mode . ("rust-analyzer"))))
+          ;; Cargo doesn't work under `temporary-file-directory'.
+          (process-environment (eglot-tests--real-home-env)))
       ;; Open other-file, and see diagnostics arrive for main.rs
       (with-current-buffer (eglot--find-file-noselect "project/other-file.rs")
         (should (zerop (shell-command "cargo init")))
@@ -829,6 +846,7 @@ eglot-test-project-wide-diagnostics-rust-analyzer
 (ert-deftest eglot-test-json-basic ()
   "Test basic autocompletion in vscode-json-languageserver."
   (skip-unless (executable-find "vscode-json-languageserver"))
+  (skip-unless (fboundp 'yas-minor-mode))
   (eglot--with-fixture
       '(("project" .
          (("p.json" . "{\"foo.b")
-- 
2.39.1

While putting this together, I also noticed some minor housekeeping
opportunities.  The following patch mainly removes the symbol-value pair
syntax from eglot--with-fixture.  The setting and unsetting of these
variables happened quite far away from the body, so they could not be
used to change, say, process-environment, since eglot--with-fixture
already binds that.  I think requiring the body to let-bind its own
variables is not only sufficient, but more general and less surprising.

>From 731c39a27b9a21754cbee73e7199366a7cc38d82 Mon Sep 17 00:00:00 2001
From: "Basil L. Contovounesios" <[email-masked]>
Date: Sun, 19 Feb 2023 18:09:06 +0000
Subject: [PATCH 2/2] Minor housekeeping in ert-x and eglot-tests

* lisp/emacs-lisp/ert-x.el (ert-remote-temporary-file-directory):
Don't add trailing slash to HOME.

* test/lisp/progmodes/eglot-tests.el: Move footer line to EOF.
(eglot--with-fixture): Don't allow fixture elements to be
symbol-value pairs.  This feature was used in only one test.  The
same effect can be achieved in a simpler way, and closer to the
body, with let-bindings.
(eglot--make-file-or-dir): Ensure default-directory ends with a
slash.  Simplify using with-temp-file.
(eglot--call-with-fixture): Ensure default-directory ends with a
slash.  Remove symbol setting and restoring logic.  Modify
process-environment only when needed, and simplify using
eglot-tests--real-home-env.  Leave XDG_CONFIG_HOME alone; it is
already unexported in test/Makefile.in.  Fix let-binding syntax.
(eglot--cleanup-after-test): Remove symbol restoring logic.
(eglot--eldoc-on-demand, eglot--tests-force-full-eldoc): Fix
commentary typos.
(eglot-test-ensure): Adapt c-mode-hook binding to
eglot--with-fixture changes.
---
 lisp/emacs-lisp/ert-x.el           |  2 +-
 test/lisp/progmodes/eglot-tests.el | 97 ++++++++++++------------------
 2 files changed, 39 insertions(+), 60 deletions(-)

diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el
index 98a017c8a8e..3bf9b59f874 100644
--- a/lisp/emacs-lisp/ert-x.el
+++ b/lisp/emacs-lisp/ert-x.el
@@ -563,7 +563,7 @@ ert-remote-temporary-file-directory
         ;; Emacs's Makefile sets $HOME to a nonexistent value.  Needed
         ;; in batch mode only, therefore.
         (when (and noninteractive (not (file-directory-p "~/")))
-          (setenv "HOME" temporary-file-directory))
+          (setenv "HOME" (directory-file-name temporary-file-directory)))
         (format "/mock::%s" temporary-file-directory))))
     "Temporary directory for remote file tests.")
 
diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el
index 4e1b025e63f..cce5b572521 100644
--- a/test/lisp/progmodes/eglot-tests.el
+++ b/test/lisp/progmodes/eglot-tests.el
@@ -60,28 +60,25 @@
 ;;; Helpers
 
 (defmacro eglot--with-fixture (fixture &rest body)
-  "Setup FIXTURE, call BODY, teardown FIXTURE.
+  "Set up FIXTURE, call BODY, tear down FIXTURE.
 FIXTURE is a list.  Its elements are of the form (FILE . CONTENT)
 to create a readable FILE with CONTENT.  FILE may be a directory
 name and CONTENT another (FILE . CONTENT) list to specify a
-directory hierarchy.  FIXTURE's elements can also be (SYMBOL
-VALUE) meaning SYMBOL should be bound to VALUE during BODY and
-then restored."
+directory hierarchy."
   (declare (indent 1) (debug t))
-  `(eglot--call-with-fixture
-    ,fixture #'(lambda () ,@body)))
+  `(eglot--call-with-fixture ,fixture (lambda () ,@body)))
 
 (defun eglot--make-file-or-dir (ass)
   (let ((file-or-dir-name (car ass))
         (content (cdr ass)))
     (cond ((listp content)
            (make-directory file-or-dir-name 'parents)
-           (let ((default-directory (concat default-directory "/" file-or-dir-name)))
+           (let* ((subdir (expand-file-name file-or-dir-name default-directory))
+                  (default-directory (file-name-as-directory subdir)))
              (mapcan #'eglot--make-file-or-dir content)))
           ((stringp content)
-           (with-temp-buffer
-             (insert content)
-             (write-region nil nil file-or-dir-name nil 'nomessage))
+           (with-temp-file file-or-dir-name
+             (insert content))
            (list (expand-file-name file-or-dir-name)))
           (t
            (eglot--error "Expected a string or a directory spec")))))
@@ -96,43 +93,27 @@ eglot-tests--real-home-env
 
 (defun eglot--call-with-fixture (fixture fn)
   "Helper for `eglot--with-fixture'.  Run FN under FIXTURE."
-  (let* ((fixture-directory (make-nearby-temp-file "eglot--fixture" t))
-         (default-directory fixture-directory)
-         file-specs created-files
-         syms-to-restore
+  (let* ((fixture-directory (make-nearby-temp-file "eglot--fixture-" t))
+         (default-directory (file-name-as-directory fixture-directory))
+         created-files
          new-servers
          test-body-successful-p)
-    (dolist (spec fixture)
-      (cond ((symbolp spec)
-             (push (cons spec (symbol-value spec)) syms-to-restore)
-             (set spec nil))
-            ((symbolp (car spec))
-             (push (cons (car spec) (symbol-value (car spec))) syms-to-restore)
-             (set (car spec) (cadr spec)))
-            ((stringp (car spec)) (push spec file-specs))))
     (unwind-protect
-        (let* ((home (getenv "HOME"))
-               (process-environment
-                (append
-                 `(;; Set XDF_CONFIG_HOME to /dev/null to prevent
-                   ;; user-configuration to have an influence on
-                   ;; language servers. (See github#441)
-                   "XDG_CONFIG_HOME=/dev/null"
-                   ;; ... on the flip-side, a similar technique by
-                   ;; Emacs's test makefiles means that HOME is set to
-                   ;; /nonexistent.  This breaks some common
-                   ;; installations for LSP servers like pylsp, making
-                   ;; these tests mostly useless, so we hack around it
-                   ;; here with a great big hack.
-                   ,(format "HOME=%s"
-                            (if (file-exists-p home) home
-                              (format "/home/%s" (getenv "USER")))))
-                 process-environment))
-               ;; Prevent "Can't guess python-indent-offset ..." messages.
-               (python-indent-guess-indent-offset-verbose . nil)
-               (eglot-server-initialized-hook
-                (lambda (server) (push server new-servers))))
-          (setq created-files (mapcan #'eglot--make-file-or-dir file-specs))
+        (let ((process-environment
+               (if (file-exists-p "~")
+                   process-environment
+                 ;; `test/Makefile' sets `HOME=/nonexistent' (and
+                 ;; `ert-remote-temporary-file-directory' sets it to
+                 ;; `temporary-file-directory').  This breaks some
+                 ;; common installations for LSP servers like pylsp,
+                 ;; making these tests mostly useless, so we hack
+                 ;; around it here with a great big hack.
+                 (eglot-tests--real-home-env)))
+              ;; Prevent "Can't guess python-indent-offset ..." messages.
+              (python-indent-guess-indent-offset-verbose nil)
+              (eglot-server-initialized-hook
+               (lambda (server) (push server new-servers))))
+          (setq created-files (mapcan #'eglot--make-file-or-dir fixture))
           (prog1 (funcall fn)
             (setq test-body-successful-p t)))
       (eglot--message
@@ -165,18 +146,15 @@ eglot--call-with-fixture
                         (t
                          (eglot--message "Preserved for inspection: %s"
                                          (mapconcat #'buffer-name buffers ", "))))))))
-        (eglot--cleanup-after-test fixture-directory created-files syms-to-restore)))))
+        (eglot--cleanup-after-test fixture-directory created-files)))))
 
-(defun eglot--cleanup-after-test (fixture-directory created-files syms-to-restore)
+(defun eglot--cleanup-after-test (fixture-directory created-files)
   (let ((buffers-to-delete
-         (delete nil (mapcar #'find-buffer-visiting created-files))))
-    (eglot--message "Killing %s, wiping %s, restoring %s"
+         (delq nil (mapcar #'find-buffer-visiting created-files))))
+    (eglot--message "Killing %s, wiping %s"
                     buffers-to-delete
-                    fixture-directory
-                    (mapcar #'car syms-to-restore))
-    (cl-loop for (sym . val) in syms-to-restore
-             do (set sym val))
-    (dolist (buf buffers-to-delete) ;; have to save otherwise will get prompted
+                    fixture-directory)
+    (dolist (buf buffers-to-delete) ;; Have to save otherwise will get prompted.
       (with-current-buffer buf (save-buffer) (kill-buffer)))
     (delete-directory fixture-directory 'recursive)
     ;; Delete Tramp buffers if needed.
@@ -476,11 +454,11 @@ eglot-test-diagnostic-tags-unnecessary-code
           (should (eq 'eglot-diagnostic-tag-unnecessary-face (face-at-point))))))))
 
 (defun eglot--eldoc-on-demand ()
-  ;; Trick Eldoc 1.1.0 into accepting on-demand calls.
+  ;; Trick ElDoc 1.1.0 into accepting on-demand calls.
   (eldoc t))
 
 (defun eglot--tests-force-full-eldoc ()
-  ;; FIXME: This uses some Eldoc implementation defatils.
+  ;; FIXME: This uses some ElDoc implementation details.
   (when (buffer-live-p eldoc--doc-buffer)
     (with-current-buffer eldoc--doc-buffer
       (let ((inhibit-read-only t))
@@ -898,9 +876,9 @@ eglot-test-ensure
   (skip-unless (executable-find "clangd"))
   (eglot--with-fixture
       `(("project" . (("foo.c" . "int foo() {return 42;}")
-                      ("bar.c" . "int bar() {return 42;}")))
-        (c-mode-hook (eglot-ensure)))
-    (let (server)
+                      ("bar.c" . "int bar() {return 42;}"))))
+    (let ((c-mode-hook '(eglot-ensure))
+          server)
       ;; need `ert-simulate-command' because `eglot-ensure'
       ;; relies on `post-command-hook'.
       (with-current-buffer
@@ -1331,8 +1309,9 @@ eglot-test-same-server-multi-mode
         (should (eq (eglot-current-server) server))))))
 
 (provide 'eglot-tests)
-;;; eglot-tests.el ends here
 
 ;; Local Variables:
 ;; checkdoc-force-docstrings-flag: nil
 ;; End:
+
+;;; eglot-tests.el ends here
-- 
2.39.1

WDYT?  And should any fixes go to emacs-29 or master?

Thanks,

-- 
Basil

$ pylsp --version
pylsp v1.7.1
$ autopep8 --version
autopep8 2.0.1 (pycodestyle: 2.10.0)
$ cargo --version
cargo 1.67.1 (8ecd4f20a 2023-01-10)
$ rust-analyzer --version
rust-analyzer 0.3.1402-standalone

In GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, X toolkit, cairo
 version 1.16.0, Xaw3d scroll bars) of 2023-02-19 built on tia
Repository revision: 8fba4cff1bd0b953af9e950e872e1eaecff179d7
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12101007
System Description: Debian GNU/Linux bookworm/sid

Configured using:
 'configure 'CFLAGS=-Og -ggdb3' -C --prefix=/home/blc/.local
 --enable-checking=structs --with-file-notification=yes
 --with-x-toolkit=lucid --with-x'

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NOTIFY
INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF
TOOLKIT_SCROLL_BARS TREE_SITTER WEBP X11 XAW3D XDBE XIM XINPUT2 XPM
LUCID ZLIB

Important settings:
  value of $LANG: en_IE.UTF-8
  value of $XMODIFIERS: @im=ibus
  locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message mailcap yank-media puny dired
dired-loaddefs rfc822 mml mml-sec password-cache epa derived epg rfc6068
epg-config gnus-util text-property-search time-date subr-x mm-decode
mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader
cl-loaddefs cl-lib sendmail rfc2047 rfc2045 ietf-drums mm-util
mail-prsvr mail-utils rmc iso-transl tooltip cconv eldoc paren electric
uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel
term/x-win x-win term/common-win x-dnd tool-bar dnd fontset image
regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode
prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu
timer select scroll-bar mouse jit-lock font-lock syntax font-core
term/tty-colors frame minibuffer nadvice seq simple cl-generic
indonesian philippine cham georgian utf-8-lang misc-lang vietnamese
tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
composite emoji-zwj charscript charprop case-table epa-hook
jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs
theme-loaddefs faces cus-face macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget keymap
hashtable-print-readable backquote threads dbusbind inotify lcms2
dynamic-setting system-font-setting font-render-setting cairo x-toolkit
xinput2 x multi-tty make-network-process emacs)

Memory information:
((conses 16 36554 8763)
 (symbols 48 5169 0)
 (strings 32 13853 1554)
 (string-bytes 1 377508)
 (vectors 16 9296)
 (vector-slots 8 147812 13111)
 (floats 8 23 25)
 (intervals 56 245 0)
 (buffers 984 10))