diff options
| author | Po Lu | 2025-03-02 16:02:46 +0800 |
|---|---|---|
| committer | Po Lu | 2025-03-02 16:05:04 +0800 |
| commit | a8988ce80004af57f3741dc059c5a97cb83dca64 (patch) | |
| tree | d32e2b21cb04bd61b18ba46c67e3d42dad17359e /test | |
| parent | 7fcb01e76ba9b2c74019f3863975cfe32c8b0da0 (diff) | |
| download | emacs-a8988ce80004af57f3741dc059c5a97cb83dca64.tar.gz emacs-a8988ce80004af57f3741dc059c5a97cb83dca64.zip | |
Run Android tests in the initial frame
* test/infra/android/early-init.el: New file.
* test/infra/android/test-controller.el (ats-connect): Upload
`early-init.el' to the staging directory and configure that
directory as the Emacs instance's initialization directory.
(ats-run-test): Always append to the test buffer. Execute tests
within terminal-frame.
(ats-run-all-tests): Gracefully respond to errors.
(ats-cmd-error): New function.
(ats-execute-tests-batch): Accept a number of command line
arguments.
Diffstat (limited to 'test')
| -rw-r--r-- | test/infra/android/early-init.el | 33 | ||||
| -rw-r--r-- | test/infra/android/test-controller.el | 223 |
2 files changed, 204 insertions, 52 deletions
diff --git a/test/infra/android/early-init.el b/test/infra/android/early-init.el new file mode 100644 index 00000000000..abf8eed2692 --- /dev/null +++ b/test/infra/android/early-init.el | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | ;;; Suppress deletion of the initial frame by `frame-initialize'. | ||
| 2 | |||
| 3 | ;; Copyright (C) 2025 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 8 | ;; it under the terms of the GNU General Public License as published by | ||
| 9 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 10 | ;; (at your option) any later version. | ||
| 11 | |||
| 12 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | ;; GNU General Public License for more details. | ||
| 16 | |||
| 17 | ;; You should have received a copy of the GNU General Public License | ||
| 18 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | |||
| 21 | |||
| 22 | (message "Loading early-init.el...") | ||
| 23 | |||
| 24 | (advice-add 'frame-initialize :around | ||
| 25 | (lambda (oldfun &rest args) | ||
| 26 | (let ((subr (symbol-function 'delete-frame)) | ||
| 27 | (terminal-frame terminal-frame)) | ||
| 28 | (unwind-protect | ||
| 29 | (progn | ||
| 30 | (message "Suppressed deletion of the initial frame.") | ||
| 31 | (fset 'delete-frame #'ignore) | ||
| 32 | (apply oldfun args)) | ||
| 33 | (fset 'delete-frame subr))))) | ||
diff --git a/test/infra/android/test-controller.el b/test/infra/android/test-controller.el index 38d486c3c02..4a8b592648b 100644 --- a/test/infra/android/test-controller.el +++ b/test/infra/android/test-controller.el | |||
| @@ -1764,13 +1764,25 @@ this machine and an SSH daemon be executing on the host)." | |||
| 1764 | device emacs-username "org.gnu.emacs" "org.gnu.emacs" user)))))) | 1764 | device emacs-username "org.gnu.emacs" "org.gnu.emacs" user)))))) |
| 1765 | ;; Upload the test driver. | 1765 | ;; Upload the test driver. |
| 1766 | (let* ((ats-adb-host host) | 1766 | (let* ((ats-adb-host host) |
| 1767 | (staging-directory (ats-get-staging-directory device | ||
| 1768 | "org.gnu.emacs" | ||
| 1769 | user)) | ||
| 1767 | (ats-file (let ((file (and ats-file-directory | 1770 | (ats-file (let ((file (and ats-file-directory |
| 1768 | (concat (file-name-as-directory | 1771 | (concat (file-name-as-directory |
| 1769 | ats-file-directory) | 1772 | ats-file-directory) |
| 1770 | "test-driver.el")))) | 1773 | "test-driver.el")))) |
| 1771 | (or (and file (file-exists-p file) file) | 1774 | (or (and file (file-exists-p file) file) |
| 1772 | (read-file-name "ATS test driver file: ")))) | 1775 | (read-file-name "ATS test driver file: ")))) |
| 1776 | (ats-early-init-file | ||
| 1777 | (let ((file (and ats-file-directory | ||
| 1778 | (concat (file-name-as-directory | ||
| 1779 | ats-file-directory) | ||
| 1780 | "early-init.el")))) | ||
| 1781 | (or (and file (file-exists-p file) file) | ||
| 1782 | (read-file-name "ATS early-init file: ")))) | ||
| 1773 | (file (ats-upload device ats-file "org.gnu.emacs" user)) | 1783 | (file (ats-upload device ats-file "org.gnu.emacs" user)) |
| 1784 | (_ (ats-upload device ats-early-init-file | ||
| 1785 | "org.gnu.emacs" user)) | ||
| 1774 | ;; Start the server. | 1786 | ;; Start the server. |
| 1775 | (server-port (ats-start-server)) | 1787 | (server-port (ats-start-server)) |
| 1776 | ;; Forward the server to the ADB host. | 1788 | ;; Forward the server to the ADB host. |
| @@ -1806,7 +1818,13 @@ this machine and an SSH daemon be executing on the host)." | |||
| 1806 | device user | 1818 | device user |
| 1807 | `((:component . "org.gnu.emacs/.EmacsActivity") | 1819 | `((:component . "org.gnu.emacs/.EmacsActivity") |
| 1808 | ("org.gnu.emacs.STARTUP_ARGUMENTS" | 1820 | ("org.gnu.emacs.STARTUP_ARGUMENTS" |
| 1809 | "-q" "--load" ,file "--eval" | 1821 | "--load" ,file |
| 1822 | ;; Set the Emacs home directory to the ATS staging | ||
| 1823 | ;; directory, where an early-init.el should be | ||
| 1824 | ;; uploaded that inhibits the deletion of the | ||
| 1825 | ;; initial frame. | ||
| 1826 | "--init-directory" ,staging-directory | ||
| 1827 | "--eval" | ||
| 1810 | ,(format "(ats-establish-connection \"localhost\" %d \"%s\")" | 1828 | ,(format "(ats-establish-connection \"localhost\" %d \"%s\")" |
| 1811 | remote-port uuid)))) | 1829 | remote-port uuid)))) |
| 1812 | (setq process | 1830 | (setq process |
| @@ -1837,7 +1855,12 @@ this machine and an SSH daemon be executing on the host)." | |||
| 1837 | device user | 1855 | device user |
| 1838 | `((:component . "org.gnu.emacs/.EmacsActivity") | 1856 | `((:component . "org.gnu.emacs/.EmacsActivity") |
| 1839 | ("org.gnu.emacs.STARTUP_ARGUMENTS" | 1857 | ("org.gnu.emacs.STARTUP_ARGUMENTS" |
| 1840 | "-q" "--load" ,file "--eval" | 1858 | "--load" ,file |
| 1859 | ;; Set the Emacs home directory to the ATS staging | ||
| 1860 | ;; directory, where an early-init.el should be uploaded that | ||
| 1861 | ;; inhibits the deletion of the initial frame. | ||
| 1862 | "--init-directory" ,staging-directory | ||
| 1863 | "--eval" | ||
| 1841 | ,(format "(ats-initiate-connection %S)" commfile)))) | 1864 | ,(format "(ats-initiate-connection %S)" commfile)))) |
| 1842 | (let* ((portno (with-timeout | 1865 | (let* ((portno (with-timeout |
| 1843 | (ats-await-connection-timeout | 1866 | (ats-await-connection-timeout |
| @@ -2422,6 +2445,7 @@ Display the output of the tests executed in a buffer." | |||
| 2422 | ;; Delete all tests, load the byte-compiled test file, and execute | 2445 | ;; Delete all tests, load the byte-compiled test file, and execute |
| 2423 | ;; those tests just defined subject to SELECTOR. | 2446 | ;; those tests just defined subject to SELECTOR. |
| 2424 | (with-current-buffer (get-buffer-create "*Test Output*") | 2447 | (with-current-buffer (get-buffer-create "*Test Output*") |
| 2448 | (goto-char (point-max)) | ||
| 2425 | (insert (format "=== Executing %s on %s ===\n" test device)) | 2449 | (insert (format "=== Executing %s on %s ===\n" test device)) |
| 2426 | (redisplay) | 2450 | (redisplay) |
| 2427 | (setq rc (ats-eval process | 2451 | (setq rc (ats-eval process |
| @@ -2429,23 +2453,23 @@ Display the output of the tests executed in a buffer." | |||
| 2429 | (require 'ert) | 2453 | (require 'ert) |
| 2430 | (ert-delete-all-tests) | 2454 | (ert-delete-all-tests) |
| 2431 | (load ,file-name) | 2455 | (load ,file-name) |
| 2432 | (with-temp-buffer | 2456 | (with-selected-frame terminal-frame |
| 2433 | (let* ((temp-buffer (current-buffer)) | 2457 | (with-temp-buffer |
| 2434 | (standard-output temp-buffer) | 2458 | (let* ((temp-buffer (current-buffer)) |
| 2435 | ;; Disable remote tests for the | 2459 | (standard-output temp-buffer) |
| 2436 | ;; present... | 2460 | ;; Disable remote tests for the |
| 2437 | (ert-remote-temporary-file-directory | 2461 | ;; present... |
| 2438 | null-device) | 2462 | (ert-remote-temporary-file-directory |
| 2439 | (overriding-text-conversion-style nil) | 2463 | null-device) |
| 2440 | (set-message-function | 2464 | (overriding-text-conversion-style nil) |
| 2441 | (lambda (message) | 2465 | (message-log-max t) |
| 2442 | (with-current-buffer temp-buffer | 2466 | ;; It isn't possible for |
| 2443 | (insert message "\n"))))) | 2467 | ;; Vset_message_function to take |
| 2444 | (let ((noninteractive t)) | 2468 | ;; effect when the initial frame |
| 2445 | ;; Prevent activation of the mark and | 2469 | ;; is selected. |
| 2446 | ;; other actions taken by the tests | 2470 | (messages-buffer-name |
| 2447 | ;; from affecting the test buffer. | 2471 | (buffer-name temp-buffer))) |
| 2448 | (with-temp-buffer | 2472 | (let ((noninteractive t)) |
| 2449 | (ert-run-tests-batch ',selector))) | 2473 | (ert-run-tests-batch ',selector))) |
| 2450 | (insert "=== Test execution complete ===\n") | 2474 | (insert "=== Test execution complete ===\n") |
| 2451 | (buffer-substring-no-properties | 2475 | (buffer-substring-no-properties |
| @@ -2480,10 +2504,18 @@ subject to SELECTOR, as in `ert-run-tests'." | |||
| 2480 | (let ((tests (ats-list-tests process))) | 2504 | (let ((tests (ats-list-tests process))) |
| 2481 | (dolist-with-progress-reporter (test tests) | 2505 | (dolist-with-progress-reporter (test tests) |
| 2482 | "Running tests..." | 2506 | "Running tests..." |
| 2483 | (ats-run-test process test selector)))) | 2507 | (condition-case err |
| 2508 | (ats-run-test process test selector) | ||
| 2509 | (t (progn | ||
| 2510 | (message "Error in executing `%s': %S" test err))))))) | ||
| 2484 | 2511 | ||
| 2485 | 2512 | ||
| 2486 | 2513 | ||
| 2514 | (defun ats-cmd-error (format &rest args) | ||
| 2515 | "Print an error message FORMAT, formatted with ARGS, and exit." | ||
| 2516 | (apply #'message format args) | ||
| 2517 | (kill-emacs 1)) | ||
| 2518 | |||
| 2487 | ;; Batch mode text execution. | 2519 | ;; Batch mode text execution. |
| 2488 | (defun ats-execute-tests-batch () | 2520 | (defun ats-execute-tests-batch () |
| 2489 | "Execute tests in batch mode, in the manner of `test/Makefile'. | 2521 | "Execute tests in batch mode, in the manner of `test/Makefile'. |
| @@ -2491,46 +2523,133 @@ Prompt for a device and execute tests on the same. Save log | |||
| 2491 | files to a directory specified by the user. | 2523 | files to a directory specified by the user. |
| 2492 | Call this function from the command line, with, for example: | 2524 | Call this function from the command line, with, for example: |
| 2493 | 2525 | ||
| 2494 | $ emacs --batch -l test-controller.el -f ats-execute-tests-batch" | 2526 | $ emacs --batch -l test-controller.el -f ats-execute-tests-batch |
| 2527 | |||
| 2528 | The following command-line arguments are also accepted: | ||
| 2529 | |||
| 2530 | -h Print help text. | ||
| 2531 | --device, -s DEVICE Serial number of a device to which to connect. | ||
| 2532 | --user, -a UID ID of the user as which to execute tests. | ||
| 2533 | --stub-file Name of `stub.zip' wrapper required on Android <= 4.4. | ||
| 2534 | --test-dir Directory in which Emacs's tests are situated. | ||
| 2535 | --output-dir, -o DIR Name of a directory into which to save test logs. | ||
| 2536 | --no-upload Don't upload tests; only run those which already exist." | ||
| 2495 | (let* ((ats-adb-host (getenv "ATS_ADB_HOST")) | 2537 | (let* ((ats-adb-host (getenv "ATS_ADB_HOST")) |
| 2496 | (devices (ats-enumerate-devices | 2538 | (devices (ats-enumerate-devices |
| 2497 | (lambda (name state _) | 2539 | (lambda (name state _) |
| 2498 | (and (equal state "device") | 2540 | (and (equal state "device") |
| 2499 | (ignore-errors | 2541 | (ignore-errors |
| 2500 | (ats-get-package-aid name "org.gnu.emacs"))))))) | 2542 | (ats-get-package-aid name "org.gnu.emacs")))))) |
| 2501 | (message "These devices are presently available for test execution:") | 2543 | (cmd-device nil) |
| 2502 | (let ((nth 0)) | 2544 | (cmd-user nil) |
| 2503 | (dolist (device devices) | 2545 | (cmd-output-dir nil) |
| 2504 | (message "%2d. %-24s(API level %d, %s)" | 2546 | (cmd-no-upload nil)) |
| 2505 | (setq nth (1+ nth)) (car device) | 2547 | ;; Read command-line arguments. |
| 2506 | (ats-get-sdk-version (car device)) | 2548 | (let (arg) |
| 2507 | (ats-getprop (car device) "ro.product.cpu.abi")))) | 2549 | (while (setq arg (pop argv)) |
| 2508 | (let* ((number (string-to-number | 2550 | (cond ((equal arg "-f") (pop argv)) ;; Do nothing. Emacs does |
| 2509 | (read-string | 2551 | ;; not remove this from argv |
| 2510 | "Select a device by typing its number, and Return: "))) | 2552 | ;; for unknown reasons. |
| 2511 | (device (if (or (< number 1) (> number (length devices))) | 2553 | ((equal arg "-h") |
| 2512 | (user-error "Invalid selection: %s" number) | 2554 | (message "Execute this file from the command line, with,\ |
| 2513 | (car (nth (1- number) devices)))) | 2555 | for example: |
| 2556 | |||
| 2557 | $ emacs --batch -l test-controller.el -f ats-execute-tests-batch | ||
| 2558 | |||
| 2559 | The following command-line arguments are also accepted: | ||
| 2560 | |||
| 2561 | --h Print this help text. | ||
| 2562 | --device, -s DEVICE Serial number of a device to which to connect. | ||
| 2563 | --user, -a UID ID of the user as which to execute tests. | ||
| 2564 | --stub-file Name of `stub.zip' wrapper required on Android <= 4.4. | ||
| 2565 | --test-dir Directory in which Emacs's tests are situated. | ||
| 2566 | --output-dir, -o DIR Name of a directory into which to save test logs. | ||
| 2567 | --no-upload Don't upload tests; only run those which already exist.") | ||
| 2568 | (kill-emacs 0)) | ||
| 2569 | ((or (equal arg "-s") (equal arg "--device")) | ||
| 2570 | (setq cmd-device | ||
| 2571 | (or (pop argv) | ||
| 2572 | (ats-cmd-error | ||
| 2573 | "Expected argument to `--device' option")))) | ||
| 2574 | ((or (equal arg "-a") (equal arg "--user")) | ||
| 2575 | (setq cmd-user | ||
| 2576 | (or (pop argv) | ||
| 2577 | (ats-cmd-error | ||
| 2578 | "Expected argument to `--user' option")))) | ||
| 2579 | ((or (equal arg "-o") (equal arg "--output-dir")) | ||
| 2580 | (setq cmd-output-dir | ||
| 2581 | (or (pop argv) | ||
| 2582 | (ats-cmd-error | ||
| 2583 | "Expected argument to `--output-dir' option")))) | ||
| 2584 | ((equal arg "--stub-file") | ||
| 2585 | (setq ats-working-stub-file | ||
| 2586 | (or (pop argv) | ||
| 2587 | (ats-cmd-error | ||
| 2588 | "Expected argument to `--stub-file' option.")))) | ||
| 2589 | ((equal arg "--test-dir") | ||
| 2590 | (setq ats-emacs-test-directory | ||
| 2591 | (or (pop argv) | ||
| 2592 | (ats-cmd-error | ||
| 2593 | "Expected argument to `--test-dir' option.")))) | ||
| 2594 | ((equal arg "--no-upload") | ||
| 2595 | (setq cmd-no-upload t)) | ||
| 2596 | (t (ats-cmd-error "Unknown command line argument `%s'" arg))))) | ||
| 2597 | ;; Validate and apply command-line arguments or prompt the user for | ||
| 2598 | ;; parameters in their absence. | ||
| 2599 | (if cmd-device | ||
| 2600 | (unless (member cmd-device (mapcar #'car devices)) | ||
| 2601 | (ats-cmd-error | ||
| 2602 | "Device `%s' does not exist or has no installation of Emacs" | ||
| 2603 | cmd-device)) | ||
| 2604 | (message "These devices are presently available for test execution:") | ||
| 2605 | (let ((nth 0)) | ||
| 2606 | (dolist (device devices) | ||
| 2607 | (message "%2d. %-24s(API level %d, %s)" | ||
| 2608 | (setq nth (1+ nth)) (car device) | ||
| 2609 | (ats-get-sdk-version (car device)) | ||
| 2610 | (ats-getprop (car device) "ro.product.cpu.abi"))))) | ||
| 2611 | (let* ((number (and (not cmd-device) | ||
| 2612 | (string-to-number | ||
| 2613 | (read-string | ||
| 2614 | "Select a device by typing its number, and Return: ")))) | ||
| 2615 | (device (or cmd-device | ||
| 2616 | (if (or (< number 1) (> number (length devices))) | ||
| 2617 | (ats-cmd-error "Invalid selection: %s" number) | ||
| 2618 | (car (nth (1- number) devices))))) | ||
| 2514 | (users (ats-list-users device)) | 2619 | (users (ats-list-users device)) |
| 2515 | (nth 0)) | 2620 | (nth 0) |
| 2516 | (dolist (user users) | 2621 | (user nil)) |
| 2517 | (message "%2d. %s (id=%d)" (setq nth (1+ nth)) | 2622 | (if cmd-user |
| 2518 | (cadr user) (car user))) | 2623 | (progn |
| 2519 | (setq number (string-to-number | 2624 | (let ((valid-number (string-match-p "^[[:digit:]]+$" cmd-user)) |
| 2520 | (read-string | 2625 | (uid (string-to-number cmd-user))) |
| 2521 | "As which user should tests be executed? "))) | 2626 | (unless valid-number |
| 2522 | (when (or (< number 1) (> number (length users))) | 2627 | (ats-cmd-error "Invalid value for `--user' argument: %s" |
| 2523 | (user-error "Invalid selection: %s" number)) | 2628 | cmd-user)) |
| 2524 | (let* ((user (car (nth (1- number) users))) | 2629 | (unless (assq uid users) |
| 2630 | (ats-cmd-error "No such user exists: %d" uid)) | ||
| 2631 | ;; Don't prompt the user afterwards. | ||
| 2632 | (setq user uid))) | ||
| 2633 | (dolist (user users) | ||
| 2634 | (message "%2d. %s (id=%d)" (setq nth (1+ nth)) | ||
| 2635 | (cadr user) (car user))) | ||
| 2636 | (setq number (string-to-number | ||
| 2637 | (read-string | ||
| 2638 | "As which user should tests be executed? "))) | ||
| 2639 | (when (or (< number 1) (> number (length users))) | ||
| 2640 | (ats-cmd-error "Invalid selection: %s" number))) | ||
| 2641 | (let* ((user (or user (car (nth (1- number) users)))) | ||
| 2525 | (connection (ats-connect device user))) | 2642 | (connection (ats-connect device user))) |
| 2526 | (ats-upload-all-tests | 2643 | (unless cmd-no-upload |
| 2527 | connection | 2644 | (ats-upload-all-tests |
| 2528 | (or ats-emacs-test-directory | 2645 | connection |
| 2529 | (read-directory-name "Test base directory: " | 2646 | (or ats-emacs-test-directory |
| 2530 | nil nil t))) | 2647 | (read-directory-name "Test base directory: " |
| 2648 | nil nil t)))) | ||
| 2531 | (let ((output-directory | 2649 | (let ((output-directory |
| 2532 | (read-directory-name | 2650 | (or cmd-output-dir |
| 2533 | "Where to save test log files? "))) | 2651 | (read-directory-name |
| 2652 | "Where to save test log files? ")))) | ||
| 2534 | (mkdir output-directory t) | 2653 | (mkdir output-directory t) |
| 2535 | (let ((tests (ats-list-tests connection))) | 2654 | (let ((tests (ats-list-tests connection))) |
| 2536 | (dolist (test tests) | 2655 | (dolist (test tests) |