aboutsummaryrefslogtreecommitdiffstats
path: root/test/src/thread-tests.el
diff options
context:
space:
mode:
Diffstat (limited to 'test/src/thread-tests.el')
-rw-r--r--test/src/thread-tests.el218
1 files changed, 169 insertions, 49 deletions
diff --git a/test/src/thread-tests.el b/test/src/thread-tests.el
index 10b2f0761df..75d67140a90 100644
--- a/test/src/thread-tests.el
+++ b/test/src/thread-tests.el
@@ -1,6 +1,6 @@
1;;; threads.el --- tests for threads. 1;;; thread-tests.el --- tests for threads. -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2012-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -19,39 +19,74 @@
19 19
20;;; Code: 20;;; Code:
21 21
22(require 'thread)
23
24;; Declare the functions in case Emacs has been configured --without-threads.
25(declare-function all-threads "thread.c" ())
26(declare-function condition-mutex "thread.c" (cond))
27(declare-function condition-name "thread.c" (cond))
28(declare-function condition-notify "thread.c" (cond &optional all))
29(declare-function condition-wait "thread.c" (cond))
30(declare-function current-thread "thread.c" ())
31(declare-function make-condition-variable "thread.c" (mutex &optional name))
32(declare-function make-mutex "thread.c" (&optional name))
33(declare-function make-thread "thread.c" (function &optional name))
34(declare-function mutex-lock "thread.c" (mutex))
35(declare-function mutex-unlock "thread.c" (mutex))
36(declare-function thread--blocker "thread.c" (thread))
37(declare-function thread-live-p "thread.c" (thread))
38(declare-function thread-join "thread.c" (thread))
39(declare-function thread-last-error "thread.c" (&optional cleanup))
40(declare-function thread-name "thread.c" (thread))
41(declare-function thread-signal "thread.c" (thread error-symbol data))
42(declare-function thread-yield "thread.c" ())
43(defvar main-thread)
44
22(ert-deftest threads-is-one () 45(ert-deftest threads-is-one ()
23 "test for existence of a thread" 46 "Test for existence of a thread."
47 (skip-unless (featurep 'threads))
24 (should (current-thread))) 48 (should (current-thread)))
25 49
26(ert-deftest threads-threadp () 50(ert-deftest threads-threadp ()
27 "test of threadp" 51 "Test of threadp."
52 (skip-unless (featurep 'threads))
28 (should (threadp (current-thread)))) 53 (should (threadp (current-thread))))
29 54
30(ert-deftest threads-type () 55(ert-deftest threads-type ()
31 "test of thread type" 56 "Test of thread type."
57 (skip-unless (featurep 'threads))
32 (should (eq (type-of (current-thread)) 'thread))) 58 (should (eq (type-of (current-thread)) 'thread)))
33 59
34(ert-deftest threads-name () 60(ert-deftest threads-name ()
35 "test for name of a thread" 61 "Test for name of a thread."
62 (skip-unless (featurep 'threads))
36 (should 63 (should
37 (string= "hi bob" (thread-name (make-thread #'ignore "hi bob"))))) 64 (string= "hi bob" (thread-name (make-thread #'ignore "hi bob")))))
38 65
39(ert-deftest threads-alive () 66(ert-deftest threads-live ()
40 "test for thread liveness" 67 "Test for thread liveness."
68 (skip-unless (featurep 'threads))
41 (should 69 (should
42 (thread-alive-p (make-thread #'ignore)))) 70 (thread-live-p (make-thread #'ignore))))
43 71
44(ert-deftest threads-all-threads () 72(ert-deftest threads-all-threads ()
45 "simple test for all-threads" 73 "Simple test for `all-threads'."
74 (skip-unless (featurep 'threads))
46 (should (listp (all-threads)))) 75 (should (listp (all-threads))))
47 76
77(ert-deftest threads-main-thread ()
78 "Simple test for `all-threads'."
79 (skip-unless (featurep 'threads))
80 (should (eq main-thread (car (all-threads)))))
81
48(defvar threads-test-global nil) 82(defvar threads-test-global nil)
49 83
50(defun threads-test-thread1 () 84(defun threads-test-thread1 ()
51 (setq threads-test-global 23)) 85 (setq threads-test-global 23))
52 86
53(ert-deftest threads-basic () 87(ert-deftest threads-basic ()
54 "basic thread test" 88 "Basic thread test."
89 (skip-unless (featurep 'threads))
55 (should 90 (should
56 (progn 91 (progn
57 (setq threads-test-global nil) 92 (setq threads-test-global nil)
@@ -61,19 +96,30 @@
61 threads-test-global))) 96 threads-test-global)))
62 97
63(ert-deftest threads-join () 98(ert-deftest threads-join ()
64 "test of thread-join" 99 "Test of `thread-join'."
100 (skip-unless (featurep 'threads))
65 (should 101 (should
66 (progn 102 (progn
67 (setq threads-test-global nil) 103 (setq threads-test-global nil)
68 (let ((thread (make-thread #'threads-test-thread1))) 104 (let ((thread (make-thread #'threads-test-thread1)))
69 (thread-join thread) 105 (and (= (thread-join thread) 23)
70 (and threads-test-global 106 (= threads-test-global 23)
71 (not (thread-alive-p thread))))))) 107 (not (thread-live-p thread)))))))
72 108
73(ert-deftest threads-join-self () 109(ert-deftest threads-join-self ()
74 "cannot thread-join the current thread" 110 "Cannot `thread-join' the current thread."
111 (skip-unless (featurep 'threads))
75 (should-error (thread-join (current-thread)))) 112 (should-error (thread-join (current-thread))))
76 113
114(ert-deftest threads-join-error ()
115 "Test of error signaling from `thread-join'."
116 :tags '(:unstable)
117 (skip-unless (featurep 'threads))
118 (let ((thread (make-thread #'threads-call-error)))
119 (while (thread-live-p thread)
120 (thread-yield))
121 (should-error (thread-join thread))))
122
77(defvar threads-test-binding nil) 123(defvar threads-test-binding nil)
78 124
79(defun threads-test-thread2 () 125(defun threads-test-thread2 ()
@@ -82,7 +128,8 @@
82 (setq threads-test-global 23)) 128 (setq threads-test-global 23))
83 129
84(ert-deftest threads-let-binding () 130(ert-deftest threads-let-binding ()
85 "simple test of threads and let bindings" 131 "Simple test of threads and let bindings."
132 (skip-unless (featurep 'threads))
86 (should 133 (should
87 (progn 134 (progn
88 (setq threads-test-global nil) 135 (setq threads-test-global nil)
@@ -93,19 +140,23 @@
93 threads-test-global)))) 140 threads-test-global))))
94 141
95(ert-deftest threads-mutexp () 142(ert-deftest threads-mutexp ()
96 "simple test of mutexp" 143 "Simple test of `mutexp'."
144 (skip-unless (featurep 'threads))
97 (should-not (mutexp 'hi))) 145 (should-not (mutexp 'hi)))
98 146
99(ert-deftest threads-mutexp-2 () 147(ert-deftest threads-mutexp-2 ()
100 "another simple test of mutexp" 148 "Another simple test of `mutexp'."
149 (skip-unless (featurep 'threads))
101 (should (mutexp (make-mutex)))) 150 (should (mutexp (make-mutex))))
102 151
103(ert-deftest threads-mutex-type () 152(ert-deftest threads-mutex-type ()
104 "type-of mutex" 153 "type-of mutex."
154 (skip-unless (featurep 'threads))
105 (should (eq (type-of (make-mutex)) 'mutex))) 155 (should (eq (type-of (make-mutex)) 'mutex)))
106 156
107(ert-deftest threads-mutex-lock-unlock () 157(ert-deftest threads-mutex-lock-unlock ()
108 "test mutex-lock and unlock" 158 "Test `mutex-lock' and unlock."
159 (skip-unless (featurep 'threads))
109 (should 160 (should
110 (let ((mx (make-mutex))) 161 (let ((mx (make-mutex)))
111 (mutex-lock mx) 162 (mutex-lock mx)
@@ -113,7 +164,8 @@
113 t))) 164 t)))
114 165
115(ert-deftest threads-mutex-recursive () 166(ert-deftest threads-mutex-recursive ()
116 "test mutex-lock and unlock" 167 "Test mutex recursion."
168 (skip-unless (featurep 'threads))
117 (should 169 (should
118 (let ((mx (make-mutex))) 170 (let ((mx (make-mutex)))
119 (mutex-lock mx) 171 (mutex-lock mx)
@@ -133,7 +185,8 @@
133 (mutex-unlock threads-mutex)) 185 (mutex-unlock threads-mutex))
134 186
135(ert-deftest threads-mutex-contention () 187(ert-deftest threads-mutex-contention ()
136 "test of mutex contention" 188 "Test of mutex contention."
189 (skip-unless (featurep 'threads))
137 (should 190 (should
138 (progn 191 (progn
139 (setq threads-mutex (make-mutex)) 192 (setq threads-mutex (make-mutex))
@@ -153,8 +206,9 @@
153 (mutex-lock threads-mutex)) 206 (mutex-lock threads-mutex))
154 207
155(ert-deftest threads-mutex-signal () 208(ert-deftest threads-mutex-signal ()
156 "test signaling a blocked thread" 209 "Test signaling a blocked thread."
157 (should 210 (skip-unless (featurep 'threads))
211 (should-error
158 (progn 212 (progn
159 (setq threads-mutex (make-mutex)) 213 (setq threads-mutex (make-mutex))
160 (setq threads-mutex-key nil) 214 (setq threads-mutex-key nil)
@@ -163,14 +217,17 @@
163 (while (not threads-mutex-key) 217 (while (not threads-mutex-key)
164 (thread-yield)) 218 (thread-yield))
165 (thread-signal thr 'quit nil) 219 (thread-signal thr 'quit nil)
166 (thread-join thr)) 220 ;; `quit' is not catched by `should-error'. We must indicate it.
167 t))) 221 (condition-case nil
222 (thread-join thr)
223 (quit (signal 'error nil)))))))
168 224
169(defun threads-test-io-switch () 225(defun threads-test-io-switch ()
170 (setq threads-test-global 23)) 226 (setq threads-test-global 23))
171 227
172(ert-deftest threads-io-switch () 228(ert-deftest threads-io-switch ()
173 "test that accept-process-output causes thread switch" 229 "Test that `accept-process-output' causes thread switch."
230 (skip-unless (featurep 'threads))
174 (should 231 (should
175 (progn 232 (progn
176 (setq threads-test-global nil) 233 (setq threads-test-global nil)
@@ -180,60 +237,72 @@
180 threads-test-global))) 237 threads-test-global)))
181 238
182(ert-deftest threads-condvarp () 239(ert-deftest threads-condvarp ()
183 "simple test of condition-variable-p" 240 "Simple test of `condition-variable-p'."
241 (skip-unless (featurep 'threads))
184 (should-not (condition-variable-p 'hi))) 242 (should-not (condition-variable-p 'hi)))
185 243
186(ert-deftest threads-condvarp-2 () 244(ert-deftest threads-condvarp-2 ()
187 "another simple test of condition-variable-p" 245 "Another simple test of `condition-variable-p'."
246 (skip-unless (featurep 'threads))
188 (should (condition-variable-p (make-condition-variable (make-mutex))))) 247 (should (condition-variable-p (make-condition-variable (make-mutex)))))
189 248
190(ert-deftest threads-condvar-type () 249(ert-deftest threads-condvar-type ()
191 "type-of condvar" 250 "type-of condvar"
251 (skip-unless (featurep 'threads))
192 (should (eq (type-of (make-condition-variable (make-mutex))) 252 (should (eq (type-of (make-condition-variable (make-mutex)))
193 'condition-variable))) 253 'condition-variable)))
194 254
195(ert-deftest threads-condvar-mutex () 255(ert-deftest threads-condvar-mutex ()
196 "simple test of condition-mutex" 256 "Simple test of `condition-mutex'."
257 (skip-unless (featurep 'threads))
197 (should 258 (should
198 (let ((m (make-mutex))) 259 (let ((m (make-mutex)))
199 (eq m (condition-mutex (make-condition-variable m)))))) 260 (eq m (condition-mutex (make-condition-variable m))))))
200 261
201(ert-deftest threads-condvar-name () 262(ert-deftest threads-condvar-name ()
202 "simple test of condition-name" 263 "Simple test of `condition-name'."
264 (skip-unless (featurep 'threads))
203 (should 265 (should
204 (eq nil (condition-name (make-condition-variable (make-mutex)))))) 266 (eq nil (condition-name (make-condition-variable (make-mutex))))))
205 267
206(ert-deftest threads-condvar-name-2 () 268(ert-deftest threads-condvar-name-2 ()
207 "another simple test of condition-name" 269 "Another simple test of `condition-name'."
270 (skip-unless (featurep 'threads))
208 (should 271 (should
209 (string= "hi bob" 272 (string= "hi bob"
210 (condition-name (make-condition-variable (make-mutex) 273 (condition-name (make-condition-variable (make-mutex)
211 "hi bob"))))) 274 "hi bob")))))
212(defun call-error () 275
276(defun threads-call-error ()
213 "Call `error'." 277 "Call `error'."
214 (error "Error is called")) 278 (error "Error is called"))
215 279
216;; This signals an error internally; the error should be caught. 280;; This signals an error internally; the error should be caught.
217(defun thread-custom () 281(defun threads-custom ()
218 (defcustom thread-custom-face 'highlight 282 (defcustom threads-custom-face 'highlight
219 "Face used for thread customizations." 283 "Face used for thread customizations."
220 :type 'face 284 :type 'face
221 :group 'widget-faces)) 285 :group 'widget-faces))
222 286
223(ert-deftest thread-errors () 287(ert-deftest threads-errors ()
224 "Test what happens when a thread signals an error." 288 "Test what happens when a thread signals an error."
289 (skip-unless (featurep 'threads))
225 (let (th1 th2) 290 (let (th1 th2)
226 (setq th1 (make-thread #'call-error "call-error")) 291 (setq th1 (make-thread #'threads-call-error "call-error"))
227 (should (threadp th1)) 292 (should (threadp th1))
228 (while (thread-alive-p th1) 293 (while (thread-live-p th1)
229 (thread-yield)) 294 (thread-yield))
230 (should (equal (thread-last-error) 295 (should (equal (thread-last-error)
231 '(error "Error is called"))) 296 '(error "Error is called")))
232 (setq th2 (make-thread #'thread-custom "thread-custom")) 297 (should (equal (thread-last-error 'cleanup)
298 '(error "Error is called")))
299 (should-not (thread-last-error))
300 (setq th2 (make-thread #'threads-custom "threads-custom"))
233 (should (threadp th2)))) 301 (should (threadp th2))))
234 302
235(ert-deftest thread-sticky-point () 303(ert-deftest threads-sticky-point ()
236 "Test bug #25165 with point movement in cloned buffer." 304 "Test bug #25165 with point movement in cloned buffer."
305 (skip-unless (featurep 'threads))
237 (with-temp-buffer 306 (with-temp-buffer
238 (insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") 307 (insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
239 (goto-char (point-min)) 308 (goto-char (point-min))
@@ -242,16 +311,36 @@
242 (sit-for 1) 311 (sit-for 1)
243 (should (= (point) 21)))) 312 (should (= (point) 21))))
244 313
245(ert-deftest thread-signal-early () 314(ert-deftest threads-signal-early ()
246 "Test signaling a thread as soon as it is started by the OS." 315 "Test signaling a thread as soon as it is started by the OS."
316 (skip-unless (featurep 'threads))
247 (let ((thread 317 (let ((thread
248 (make-thread #'(lambda () 318 (make-thread (lambda ()
249 (while t (thread-yield)))))) 319 (while t (thread-yield))))))
250 (thread-signal thread 'error nil) 320 (thread-signal thread 'error nil)
251 (sit-for 1) 321 (sit-for 1)
252 (should-not (thread-alive-p thread)) 322 (should-not (thread-live-p thread))
253 (should (equal (thread-last-error) '(error))))) 323 (should (equal (thread-last-error) '(error)))))
254 324
325(ert-deftest threads-signal-main-thread ()
326 "Test signaling the main thread."
327 (skip-unless (featurep 'threads))
328 ;; We cannot use `ert-with-message-capture', because threads do not
329 ;; know let-bound variables.
330 (with-current-buffer "*Messages*"
331 (let (buffer-read-only)
332 (erase-buffer))
333 (let ((thread
334 (make-thread (lambda () (thread-signal main-thread 'error nil)))))
335 (while (thread-live-p thread)
336 (thread-yield))
337 (read-event nil nil 0.1)
338 ;; No error has been raised, which is part of the test.
339 (should
340 (string-match
341 (format-message "Error %s: (error nil)" thread)
342 (buffer-string ))))))
343
255(defvar threads-condvar nil) 344(defvar threads-condvar nil)
256 345
257(defun threads-test-condvar-wait () 346(defun threads-test-condvar-wait ()
@@ -263,7 +352,8 @@
263 (condition-wait threads-condvar))) 352 (condition-wait threads-condvar)))
264 353
265(ert-deftest threads-condvar-wait () 354(ert-deftest threads-condvar-wait ()
266 "test waiting on conditional variable" 355 "Test waiting on conditional variable."
356 (skip-unless (featurep 'threads))
267 (let ((cv-mutex (make-mutex)) 357 (let ((cv-mutex (make-mutex))
268 new-thread) 358 new-thread)
269 ;; We could have spurious threads from the previous tests still 359 ;; We could have spurious threads from the previous tests still
@@ -274,7 +364,7 @@
274 (setq new-thread (make-thread #'threads-test-condvar-wait)) 364 (setq new-thread (make-thread #'threads-test-condvar-wait))
275 365
276 ;; Make sure new-thread is alive. 366 ;; Make sure new-thread is alive.
277 (should (thread-alive-p new-thread)) 367 (should (thread-live-p new-thread))
278 (should (= (length (all-threads)) 2)) 368 (should (= (length (all-threads)) 2))
279 ;; Wait for new-thread to become blocked on the condvar. 369 ;; Wait for new-thread to become blocked on the condvar.
280 (while (not (eq (thread--blocker new-thread) threads-condvar)) 370 (while (not (eq (thread--blocker new-thread) threads-condvar))
@@ -287,7 +377,7 @@
287 (sleep-for 0.1) 377 (sleep-for 0.1)
288 ;; Make sure the thread is still there. This used to fail due to 378 ;; Make sure the thread is still there. This used to fail due to
289 ;; a bug in thread.c:condition_wait_callback. 379 ;; a bug in thread.c:condition_wait_callback.
290 (should (thread-alive-p new-thread)) 380 (should (thread-live-p new-thread))
291 (should (= (length (all-threads)) 2)) 381 (should (= (length (all-threads)) 2))
292 (should (eq (thread--blocker new-thread) threads-condvar)) 382 (should (eq (thread--blocker new-thread) threads-condvar))
293 383
@@ -298,4 +388,34 @@
298 (should (= (length (all-threads)) 1)) 388 (should (= (length (all-threads)) 1))
299 (should (equal (thread-last-error) '(error "Die, die, die!"))))) 389 (should (equal (thread-last-error) '(error "Die, die, die!")))))
300 390
301;;; threads.el ends here 391(ert-deftest threads-test-bug33073 ()
392 (skip-unless (fboundp 'make-thread))
393 (let ((th (make-thread 'ignore)))
394 (should-not (equal th main-thread))))
395
396(defvar threads-test--var 'global)
397
398(ert-deftest threads-test-bug48990 ()
399 (skip-unless (fboundp 'make-thread))
400 (let ((buf1 (generate-new-buffer " thread-test"))
401 (buf2 (generate-new-buffer " thread-test")))
402 (with-current-buffer buf1
403 (setq-local threads-test--var 'local1))
404 (with-current-buffer buf2
405 (setq-local threads-test--var 'local2))
406 (let ((seen nil))
407 (with-current-buffer buf1
408 (should (eq threads-test--var 'local1))
409 (make-thread (lambda () (setq seen threads-test--var))))
410 (with-current-buffer buf2
411 (should (eq threads-test--var 'local2))
412 (let ((threads-test--var 'let2))
413 (should (eq threads-test--var 'let2))
414 (while (not seen)
415 (thread-yield))
416 (should (eq threads-test--var 'let2))
417 (should (eq seen 'local1)))
418 (should (eq threads-test--var 'local2)))
419 (should (eq threads-test--var 'global)))))
420
421;;; thread-tests.el ends here