]> rtime.felk.cvut.cz Git - sojka/company-mode.git/blob - company-tests.el
company-sort-by-occurrence: continue search after predicate fails
[sojka/company-mode.git] / company-tests.el
1 ;;; company-tests.el --- company-mode tests  -*- lexical-binding: t -*-
2
3 ;; Copyright (C) 2011, 2013-2014  Free Software Foundation, Inc.
4
5 ;; Author: Nikolaj Schumacher
6
7 ;; This file is part of GNU Emacs.
8
9 ;; GNU Emacs is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
21
22
23 ;;; Commentary:
24 ;;
25
26 ;;; Code:
27
28 (require 'ert)
29 (require 'company)
30 (require 'company-keywords)
31 (require 'company-clang)
32
33 ;;; Core
34
35 (ert-deftest company-sorted-keywords ()
36   "Test that keywords in `company-keywords-alist' are in alphabetical order."
37   (dolist (pair company-keywords-alist)
38     (when (consp (cdr pair))
39       (let ((prev (cadr pair)))
40         (dolist (next (cddr pair))
41           (should (not (equal prev next)))
42           (should (string< prev next))
43           (setq prev next))))))
44
45 (ert-deftest company-good-prefix ()
46   (let ((company-minimum-prefix-length 5)
47         company-abort-manual-when-too-short
48         company--manual-action            ;idle begin
49         (company-selection-changed t))    ;has no effect
50     (should (eq t (company--good-prefix-p "!@#$%")))
51     (should (eq nil (company--good-prefix-p "abcd")))
52     (should (eq nil (company--good-prefix-p 'stop)))
53     (should (eq t (company--good-prefix-p '("foo" . 5))))
54     (should (eq nil (company--good-prefix-p '("foo" . 4))))
55     (should (eq t (company--good-prefix-p '("foo" . t))))))
56
57 (ert-deftest company--manual-prefix-set-and-unset ()
58   (with-temp-buffer
59     (insert "ab")
60     (company-mode)
61     (let (company-frontends
62           (company-backends
63            (list (lambda (command &optional arg)
64                    (cl-case command
65                      (prefix (buffer-substring (point-min) (point)))
66                      (candidates '("abc" "abd")))))))
67       (company-manual-begin)
68       (should (equal "ab" company--manual-prefix))
69       (company-abort)
70       (should (null company--manual-prefix)))))
71
72 (ert-deftest company-abort-manual-when-too-short ()
73   (let ((company-minimum-prefix-length 5)
74         (company-abort-manual-when-too-short t)
75         (company-selection-changed t))    ;has not effect
76     (let ((company--manual-action nil))   ;idle begin
77       (should (eq t (company--good-prefix-p "!@#$%")))
78       (should (eq t (company--good-prefix-p '("foo" . 5))))
79       (should (eq t (company--good-prefix-p '("foo" . t)))))
80     (let ((company--manual-action t)
81           (company--manual-prefix "abc")) ;manual begin from this prefix
82       (should (eq t (company--good-prefix-p "!@#$")))
83       (should (eq nil (company--good-prefix-p "ab")))
84       (should (eq nil (company--good-prefix-p 'stop)))
85       (should (eq t (company--good-prefix-p '("foo" . 4))))
86       (should (eq t (company--good-prefix-p "abcd")))
87       (should (eq t (company--good-prefix-p "abc")))
88       (should (eq t (company--good-prefix-p '("bar" . t)))))))
89
90 (ert-deftest company-multi-backend-with-lambdas ()
91   (let ((company-backend
92          (list (lambda (command &optional arg &rest ignore)
93                  (cl-case command
94                    (prefix "z")
95                    (candidates '("a" "b"))))
96                (lambda (command &optional arg &rest ignore)
97                  (cl-case command
98                    (prefix "z")
99                    (candidates '("c" "d")))))))
100     (should (equal (company-call-backend 'candidates "z") '("a" "b" "c" "d")))))
101
102 (ert-deftest company-multi-backend-filters-backends-by-prefix ()
103   (let ((company-backend
104          (list (lambda (command &optional arg &rest ignore)
105                  (cl-case command
106                    (prefix (cons "z" t))
107                    (candidates '("a" "b"))))
108                (lambda (command &optional arg &rest ignore)
109                  (cl-case command
110                    (prefix "t")
111                    (candidates '("c" "d"))))
112                (lambda (command &optional arg &rest ignore)
113                  (cl-case command
114                    (prefix "z")
115                    (candidates '("e" "f")))))))
116     (should (equal (company-call-backend 'candidates "z") '("a" "b" "e" "f")))))
117
118 (ert-deftest company-multi-backend-remembers-candidate-backend ()
119   (let ((company-backend
120          (list (lambda (command &optional arg)
121                  (cl-case command
122                    (ignore-case nil)
123                    (annotation "1")
124                    (candidates '("a" "c"))
125                    (post-completion "13")))
126                (lambda (command &optional arg)
127                  (cl-case command
128                    (ignore-case t)
129                    (annotation "2")
130                    (candidates '("b" "d"))
131                    (post-completion "42")))
132                (lambda (command &optional arg)
133                  (cl-case command
134                    (annotation "3")
135                    (candidates '("e"))
136                    (post-completion "74"))))))
137     (let ((candidates (company-calculate-candidates nil)))
138       (should (equal candidates '("a" "b" "c" "d" "e")))
139       (should (equal t (company-call-backend 'ignore-case)))
140       (should (equal "1" (company-call-backend 'annotation (nth 0 candidates))))
141       (should (equal "2" (company-call-backend 'annotation (nth 1 candidates))))
142       (should (equal "13" (company-call-backend 'post-completion (nth 2 candidates))))
143       (should (equal "42" (company-call-backend 'post-completion (nth 3 candidates))))
144       (should (equal "3" (company-call-backend 'annotation (nth 4 candidates))))
145       (should (equal "74" (company-call-backend 'post-completion (nth 4 candidates)))))))
146
147 (ert-deftest company-multi-backend-handles-keyword-with ()
148   (let ((primo (lambda (command &optional arg)
149                  (cl-case command
150                    (prefix "a")
151                    (candidates '("abb" "abc" "abd")))))
152         (secundo (lambda (command &optional arg)
153                    (cl-case command
154                      (prefix "a")
155                      (candidates '("acc" "acd"))))))
156     (let ((company-backend (list 'ignore 'ignore :with secundo)))
157       (should (null (company-call-backend 'prefix))))
158     (let ((company-backend (list 'ignore primo :with secundo)))
159       (should (equal "a" (company-call-backend 'prefix)))
160       (should (equal '("abb" "abc" "abd" "acc" "acd")
161                      (company-call-backend 'candidates "a"))))))
162
163 (ert-deftest company-begin-backend-failure-doesnt-break-company-backends ()
164   (with-temp-buffer
165     (insert "a")
166     (company-mode)
167     (should-error
168      (company-begin-backend (lambda (command &rest ignore))))
169     (let (company-frontends
170           (company-backends
171            (list (lambda (command &optional arg)
172                    (cl-case command
173                      (prefix "a")
174                      (candidates '("a" "ab" "ac")))))))
175       (let (this-command)
176         (company-call 'complete))
177       (should (eq 3 company-candidates-length)))))
178
179 (ert-deftest company-require-match-explicit ()
180   (with-temp-buffer
181     (insert "ab")
182     (company-mode)
183     (let (company-frontends
184           (company-require-match 'company-explicit-action-p)
185           (company-backends
186            (list (lambda (command &optional arg)
187                    (cl-case command
188                      (prefix (buffer-substring (point-min) (point)))
189                      (candidates '("abc" "abd")))))))
190       (let (this-command)
191         (company-complete))
192       (let ((last-command-event ?e))
193         (company-call 'self-insert-command 1))
194       (should (eq 2 company-candidates-length))
195       (should (eq 3 (point))))))
196
197 (ert-deftest company-dont-require-match-when-idle ()
198   (with-temp-buffer
199     (insert "ab")
200     (company-mode)
201     (let (company-frontends
202           (company-minimum-prefix-length 2)
203           (company-require-match 'company-explicit-action-p)
204           (company-backends
205            (list (lambda (command &optional arg)
206                    (cl-case command
207                      (prefix (buffer-substring (point-min) (point)))
208                      (candidates '("abc" "abd")))))))
209       (company-idle-begin (current-buffer) (selected-window)
210                           (buffer-chars-modified-tick) (point))
211       (should (eq 2 company-candidates-length))
212       (let ((last-command-event ?e))
213         (company-call 'self-insert-command 1))
214       (should (eq nil company-candidates-length))
215       (should (eq 4 (point))))))
216
217 (ert-deftest company-dont-require-match-if-old-prefix-ended-and-was-a-match ()
218   (with-temp-buffer
219     (insert "ab")
220     (company-mode)
221     (let (company-frontends
222           (company-require-match 'company-explicit-action-p)
223           (company-backends
224            (list (lambda (command &optional arg)
225                    (cl-case command
226                      (prefix (company-grab-word))
227                      (candidates '("abc" "ab" "abd"))
228                      (sorted t))))))
229       (let (this-command)
230         (company-complete))
231       (let ((last-command-event ?e))
232         (company-call 'self-insert-command 1))
233       (should (eq 3 company-candidates-length))
234       (should (eq 3 (point)))
235       (let ((last-command-event ? ))
236         (company-call 'self-insert-command 1))
237       (should (null company-candidates-length))
238       (should (eq 4 (point))))))
239
240 (ert-deftest company-should-complete-whitelist ()
241   (with-temp-buffer
242     (insert "ab")
243     (company-mode)
244     (let (company-frontends
245           company-begin-commands
246           (company-backends
247            (list (lambda (command &optional arg)
248                    (cl-case command
249                      (prefix (buffer-substring (point-min) (point)))
250                      (candidates '("abc" "abd")))))))
251       (let ((company-continue-commands nil))
252         (let (this-command)
253           (company-complete))
254         (company-call 'backward-delete-char 1)
255         (should (null company-candidates-length)))
256       (let ((company-continue-commands '(backward-delete-char)))
257         (let (this-command)
258           (company-complete))
259         (company-call 'backward-delete-char 1)
260         (should (eq 2 company-candidates-length))))))
261
262 (ert-deftest company-should-complete-blacklist ()
263   (with-temp-buffer
264     (insert "ab")
265     (company-mode)
266     (let (company-frontends
267           company-begin-commands
268           (company-backends
269            (list (lambda (command &optional arg)
270                    (cl-case command
271                      (prefix (buffer-substring (point-min) (point)))
272                      (candidates '("abc" "abd")))))))
273       (let ((company-continue-commands '(not backward-delete-char)))
274         (let (this-command)
275           (company-complete))
276         (company-call 'backward-delete-char 1)
277         (should (null company-candidates-length)))
278       (let ((company-continue-commands '(not backward-delete-char-untabify)))
279         (let (this-command)
280           (company-complete))
281         (company-call 'backward-delete-char 1)
282         (should (eq 2 company-candidates-length))))))
283
284 (ert-deftest company-auto-complete-explicit ()
285   (with-temp-buffer
286     (insert "ab")
287     (company-mode)
288     (let (company-frontends
289           (company-auto-complete 'company-explicit-action-p)
290           (company-auto-complete-chars '(? ))
291           (company-backends
292            (list (lambda (command &optional arg)
293                    (cl-case command
294                      (prefix (buffer-substring (point-min) (point)))
295                      (candidates '("abcd" "abef")))))))
296       (let (this-command)
297         (company-complete))
298       (let ((last-command-event ? ))
299         (company-call 'self-insert-command 1))
300       (should (string= "abcd " (buffer-string))))))
301
302 (ert-deftest company-no-auto-complete-when-idle ()
303   (with-temp-buffer
304     (insert "ab")
305     (company-mode)
306     (let (company-frontends
307           (company-auto-complete 'company-explicit-action-p)
308           (company-auto-complete-chars '(? ))
309           (company-minimum-prefix-length 2)
310           (company-backends
311            (list (lambda (command &optional arg)
312                    (cl-case command
313                      (prefix (buffer-substring (point-min) (point)))
314                      (candidates '("abcd" "abef")))))))
315       (company-idle-begin (current-buffer) (selected-window)
316                           (buffer-chars-modified-tick) (point))
317       (let ((last-command-event ? ))
318         (company-call 'self-insert-command 1))
319       (should (string= "ab " (buffer-string))))))
320
321 (ert-deftest company-clears-explicit-action-when-no-matches ()
322   (with-temp-buffer
323     (company-mode)
324     (let (company-frontends
325           company-backends)
326       (company-call 'manual-begin) ;; fails
327       (should (null company-candidates))
328       (should (null (company-explicit-action-p))))))
329
330 (ert-deftest company-ignore-case-replaces-prefix ()
331   (with-temp-buffer
332     (company-mode)
333     (let (company-frontends
334           company-end-of-buffer-workaround
335           (company-backends
336            (list (lambda (command &optional arg)
337                    (cl-case command
338                      (prefix (buffer-substring (point-min) (point)))
339                      (candidates '("abcd" "abef"))
340                      (ignore-case t))))))
341       (insert "A")
342       (let (this-command)
343         (company-complete))
344       (should (string= "ab" (buffer-string)))
345       (delete-char -2)
346       (insert "A") ; hack, to keep it in one test
347       (company-complete-selection)
348       (should (string= "abcd" (buffer-string))))))
349
350 (ert-deftest company-ignore-case-with-keep-prefix ()
351   (with-temp-buffer
352     (insert "AB")
353     (company-mode)
354     (let (company-frontends
355           (company-backends
356            (list (lambda (command &optional arg)
357                    (cl-case command
358                      (prefix (buffer-substring (point-min) (point)))
359                      (candidates '("abcd" "abef"))
360                      (ignore-case 'keep-prefix))))))
361       (let (this-command)
362         (company-complete))
363       (company-complete-selection)
364       (should (string= "ABcd" (buffer-string))))))
365
366 (ert-deftest company-non-prefix-completion ()
367   (with-temp-buffer
368     (insert "tc")
369     (company-mode)
370     (let (company-frontends
371           company-end-of-buffer-workaround
372           (company-backends
373            (list (lambda (command &optional arg)
374                    (cl-case command
375                      (prefix (buffer-substring (point-min) (point)))
376                      (candidates '("tea-cup" "teal-color")))))))
377       (let (this-command)
378         (company-complete))
379       (should (string= "tc" (buffer-string)))
380       (company-complete-selection)
381       (should (string= "tea-cup" (buffer-string))))))
382
383 (ert-deftest company-pseudo-tooltip-does-not-get-displaced ()
384   :tags '(interactive)
385   (with-temp-buffer
386     (save-window-excursion
387       (set-window-buffer nil (current-buffer))
388       (save-excursion (insert " ff"))
389       (company-mode)
390       (let ((company-frontends '(company-pseudo-tooltip-frontend))
391             (company-begin-commands '(self-insert-command))
392             (company-backends
393              (list (lambda (c &optional arg)
394                      (cl-case c (prefix "") (candidates '("a" "b" "c")))))))
395         (let (this-command)
396           (company-call 'complete))
397         (company-call 'open-line 1)
398         (should (eq 2 (overlay-start company-pseudo-tooltip-overlay)))))))
399
400 (ert-deftest company-pseudo-tooltip-show ()
401   :tags '(interactive)
402   (with-temp-buffer
403     (save-window-excursion
404     (set-window-buffer nil (current-buffer))
405     (insert "aaaa\n  bb\nccccccc\nddd")
406     (search-backward "bb")
407     (let ((col (company--column))
408           (company-candidates-length 2)
409           (company-candidates '("123" "45"))
410           (company-backend 'ignore))
411       (company-pseudo-tooltip-show (company--row) col 0)
412       (let ((ov company-pseudo-tooltip-overlay))
413         ;; With margins.
414         (should (eq (overlay-get ov 'company-width) 5))
415         ;; FIXME: Make it 2?
416         (should (eq (overlay-get ov 'company-height) company-tooltip-limit))
417         (should (eq (overlay-get ov 'company-column) col))
418         (should (string= (overlay-get ov 'company-after)
419                          "  123 \nc 45  c\nddd\n")))))))
420
421 (ert-deftest company-pseudo-tooltip-edit-updates-width ()
422   :tags '(interactive)
423   (with-temp-buffer
424     (set-window-buffer nil (current-buffer))
425     (let ((company-candidates-length 5)
426           (company-candidates '("123" "45" "67" "89" "1011"))
427           (company-backend 'ignore)
428           (company-tooltip-limit 4)
429           (company-tooltip-offset-display 'scrollbar))
430       (company-pseudo-tooltip-show (company--row)
431                                    (company--column)
432                                    0)
433       (should (eq (overlay-get company-pseudo-tooltip-overlay 'company-width)
434                   6))
435       (company-pseudo-tooltip-edit 4)
436       (should (eq (overlay-get company-pseudo-tooltip-overlay 'company-width)
437                   7)))))
438
439 (ert-deftest company-preview-show-with-annotations ()
440   :tags '(interactive)
441   (with-temp-buffer
442     (save-window-excursion
443       (set-window-buffer nil (current-buffer))
444       (save-excursion (insert "\n"))
445       (let ((company-candidates-length 1)
446             (company-candidates '("123")))
447         (company-preview-show-at-point (point))
448         (let ((ov company-preview-overlay))
449           (should (string= (overlay-get ov 'display) "123\n")))))))
450
451 (ert-deftest company-pseudo-tooltip-show-with-annotations ()
452   :tags '(interactive)
453   (with-temp-buffer
454     (save-window-excursion
455       (set-window-buffer nil (current-buffer))
456       (insert " ")
457       (save-excursion (insert "\n"))
458       (let ((company-candidates-length 2)
459             (company-backend (lambda (action &optional arg &rest _ignore)
460                                (when (eq action 'annotation)
461                                  (cdr (assoc arg '(("123" . "(4)")))))))
462             (company-candidates '("123" "45"))
463             company-tooltip-align-annotations)
464         (company-pseudo-tooltip-show-at-point (point) 0)
465         (let ((ov company-pseudo-tooltip-overlay))
466           ;; With margins.
467           (should (eq (overlay-get ov 'company-width) 8))
468           (should (string= (overlay-get ov 'company-after)
469                            " 123(4) \n 45     \n")))))))
470
471 (ert-deftest company-pseudo-tooltip-show-with-annotations-right-aligned ()
472   :tags '(interactive)
473   (with-temp-buffer
474     (save-window-excursion
475       (set-window-buffer nil (current-buffer))
476       (insert " ")
477       (save-excursion (insert "\n"))
478       (let ((company-candidates-length 3)
479             (company-backend (lambda (action &optional arg &rest _ignore)
480                                (when (eq action 'annotation)
481                                  (cdr (assoc arg '(("123" . "(4)")
482                                                    ("67" . "(891011)")))))))
483             (company-candidates '("123" "45" "67"))
484             (company-tooltip-align-annotations t))
485         (company-pseudo-tooltip-show-at-point (point) 0)
486         (let ((ov company-pseudo-tooltip-overlay))
487           ;; With margins.
488           (should (eq (overlay-get ov 'company-width) 13))
489           (should (string= (overlay-get ov 'company-after)
490                            " 123     (4) \n 45          \n 67 (891011) \n")))))))
491
492 (ert-deftest company-create-lines-shows-numbers ()
493   (let ((company-show-numbers t)
494         (company-candidates '("x" "y" "z"))
495         (company-candidates-length 3)
496         (company-backend 'ignore))
497     (should (equal '(" x 1 " " y 2 " " z 3 ")
498                    (company--create-lines 0 999)))))
499
500 (ert-deftest company-create-lines-truncates-annotations ()
501   (let* ((ww (company--window-width))
502          (data `(("1" . "(123)")
503                  ("2" . nil)
504                  ("3" . ,(concat "(" (make-string (- ww 2) ?4) ")"))
505                  (,(make-string ww ?4) . "<4>")))
506          (company-candidates (mapcar #'car data))
507          (company-candidates-length 4)
508          (company-tooltip-margin 1)
509          (company-backend (lambda (cmd &optional arg)
510                             (when (eq cmd 'annotation)
511                               (cdr (assoc arg data)))))
512          company-tooltip-align-annotations)
513     (should (equal (list (format " 1(123)%s " (company-space-string (- ww 8)))
514                          (format " 2%s " (company-space-string (- ww 3)))
515                          (format " 3(444%s " (make-string (- ww 7) ?4))
516                          (format " %s " (make-string (- ww 2) ?4)))
517                    (company--create-lines 0 999)))
518     (let ((company-tooltip-align-annotations t))
519       (should (equal (list (format " 1%s(123) " (company-space-string (- ww 8)))
520                            (format " 2%s " (company-space-string (- ww 3)))
521                            (format " 3 (444%s " (make-string (- ww 8) ?4))
522                            (format " %s " (make-string (- ww 2) ?4)))
523                      (company--create-lines 0 999))))))
524
525 (ert-deftest company-column-with-composition ()
526   (with-temp-buffer
527     (insert "lambda ()")
528     (compose-region 1 (1+ (length "lambda")) "\\")
529     (should (= (company--column) 4))))
530
531 (ert-deftest company-column-with-line-prefix ()
532   (with-temp-buffer
533     (insert "foo")
534     (put-text-property (point-min) (point) 'line-prefix "  ")
535     (should (= (company--column) 5))))
536
537 (ert-deftest company-column-wth-line-prefix-on-empty-line ()
538   (with-temp-buffer
539     (insert "\n")
540     (forward-char -1)
541     (put-text-property (point-min) (point-max) 'line-prefix "  ")
542     (should (= (company--column) 2))))
543
544 (ert-deftest company-plainify ()
545   (let ((tab-width 8))
546     (should (equal-including-properties
547              (company-plainify "\tabc\td\t")
548              (concat "        "
549                      "abc     "
550                      "d       "))))
551   (should (equal-including-properties
552            (company-plainify (propertize "foobar" 'line-prefix "-*-"))
553            "-*-foobar")))
554
555 (ert-deftest company-modify-line ()
556   (let ((str "-*-foobar"))
557     (should (equal-including-properties
558              (company-modify-line str "zz" 4)
559              "-*-fzzbar"))
560     (should (equal-including-properties
561              (company-modify-line str "xx" 0)
562              "xx-foobar"))
563     (should (equal-including-properties
564              (company-modify-line str "zz" 10)
565              "-*-foobar zz"))))
566
567 (ert-deftest company-scrollbar-bounds ()
568   (should (equal nil (company--scrollbar-bounds 0 3 3)))
569   (should (equal nil (company--scrollbar-bounds 0 4 3)))
570   (should (equal '(0 . 0) (company--scrollbar-bounds 0 1 2)))
571   (should (equal '(1 . 1) (company--scrollbar-bounds 2 2 4)))
572   (should (equal '(2 . 3) (company--scrollbar-bounds 7 4 12)))
573   (should (equal '(1 . 2) (company--scrollbar-bounds 3 4 12)))
574   (should (equal '(1 . 3) (company--scrollbar-bounds 4 5 11))))
575
576 ;;; Async
577
578 (defun company-async-backend (command &optional arg)
579   (pcase command
580     (`prefix "foo")
581     (`candidates
582      (cons :async
583            (lambda (cb)
584              (run-with-timer 0.05 nil
585                              #'funcall cb '("abc" "abd")))))))
586
587 (ert-deftest company-call-backend-forces-sync ()
588   (let ((company-backend 'company-async-backend)
589         (company-async-timeout 0.1))
590     (should (equal '("abc" "abd") (company-call-backend 'candidates)))))
591
592 (ert-deftest company-call-backend-errors-on-timeout ()
593   (with-temp-buffer
594     (let* ((company-backend (lambda (command &optional _arg)
595                               (pcase command
596                                 (`candidates (cons :async 'ignore)))))
597            (company-async-timeout 0.1)
598            (err (should-error (company-call-backend 'candidates "foo"))))
599       (should (string-match-p "async timeout" (cadr err))))))
600
601 (ert-deftest company-call-backend-raw-passes-return-value-verbatim ()
602   (let ((company-backend 'company-async-backend))
603     (should (equal "foo" (company-call-backend-raw 'prefix)))
604     (should (equal :async (car (company-call-backend-raw 'candidates "foo"))))
605     (should (equal 'closure (cadr (company-call-backend-raw 'candidates "foo"))))))
606
607 (ert-deftest company-manual-begin-forces-async-candidates-to-sync ()
608   (with-temp-buffer
609     (company-mode)
610     (let (company-frontends
611           company-transformers
612           (company-backends (list 'company-async-backend)))
613       (company-manual-begin)
614       (should (equal "foo" company-prefix))
615       (should (equal '("abc" "abd") company-candidates)))))
616
617 (ert-deftest company-idle-begin-allows-async-candidates ()
618   (with-temp-buffer
619     (company-mode)
620     (let (company-frontends
621           company-transformers
622           (company-backends (list 'company-async-backend)))
623       (company-idle-begin (current-buffer) (selected-window)
624                           (buffer-chars-modified-tick) (point))
625       (should (null company-candidates))
626       (sleep-for 0.1)
627       (should (equal "foo" company-prefix))
628       (should (equal '("abc" "abd") company-candidates)))))
629
630 (ert-deftest company-idle-begin-cancels-async-candidates-if-buffer-changed ()
631   (with-temp-buffer
632     (company-mode)
633     (let (company-frontends
634           (company-backends (list 'company-async-backend)))
635       (company-idle-begin (current-buffer) (selected-window)
636                           (buffer-chars-modified-tick) (point))
637       (should (null company-candidates))
638       (insert "a")
639       (sleep-for 0.1)
640       (should (null company-candidates)))))
641
642 (ert-deftest company-idle-begin-async-allows-immediate-callbacks ()
643   (with-temp-buffer
644     (company-mode)
645     (let (company-frontends
646           (company-backends
647            (list (lambda (command &optional arg)
648                    (pcase command
649                      (`prefix (buffer-substring (point-min) (point)))
650                      (`candidates
651                       (let ((c (all-completions arg '("abc" "def"))))
652                         (cons :async
653                               (lambda (cb) (funcall cb c)))))
654                      (`no-cache t)))))
655           (company-minimum-prefix-length 0))
656       (company-idle-begin (current-buffer) (selected-window)
657                           (buffer-chars-modified-tick) (point))
658       (should (equal '("abc" "def") company-candidates))
659       (let ((last-command-event ?a))
660         (company-call 'self-insert-command 1))
661       (should (equal '("abc") company-candidates)))))
662
663 (ert-deftest company-multi-backend-forces-prefix-to-sync ()
664   (with-temp-buffer
665     (let ((company-backend (list 'ignore
666                                  (lambda (command)
667                                    (should (eq command 'prefix))
668                                    (cons :async
669                                          (lambda (cb)
670                                            (run-with-timer
671                                             0.01 nil
672                                             (lambda () (funcall cb nil))))))
673                                  (lambda (command)
674                                    (should (eq command 'prefix))
675                                    "foo"))))
676       (should (equal "foo" (company-call-backend-raw 'prefix))))
677     (let ((company-backend (list (lambda (_command)
678                                    (cons :async
679                                          (lambda (cb)
680                                            (run-with-timer
681                                             0.01 nil
682                                             (lambda () (funcall cb "bar"))))))
683                                  (lambda (_command)
684                                    "foo"))))
685       (should (equal "bar" (company-call-backend-raw 'prefix))))))
686
687 (ert-deftest company-multi-backend-merges-deferred-candidates ()
688   (with-temp-buffer
689     (let* ((immediate (lambda (command &optional arg)
690                         (pcase command
691                           (`prefix "foo")
692                           (`candidates
693                            (cons :async
694                                  (lambda (cb) (funcall cb '("f"))))))))
695            (company-backend (list 'ignore
696                                   (lambda (command &optional arg)
697                                     (pcase command
698                                       (`prefix "foo")
699                                       (`candidates
700                                        (should (equal arg "foo"))
701                                        (cons :async
702                                              (lambda (cb)
703                                                (run-with-timer
704                                                 0.01 nil
705                                                 (lambda () (funcall cb '("a" "b")))))))))
706                                   (lambda (command &optional arg)
707                                     (pcase command
708                                       (`prefix "foo")
709                                       (`candidates '("c" "d" "e"))))
710                                   immediate)))
711       (should (equal :async (car (company-call-backend-raw 'candidates "foo"))))
712       (should (equal '("a" "b" "c" "d" "e" "f")
713                      (company-call-backend 'candidates "foo")))
714       (let ((company-backend (list immediate)))
715         (should (equal '("f") (company-call-backend 'candidates "foo")))))))
716
717 ;;; Template
718
719 (ert-deftest company-template-removed-after-the-last-jump ()
720   (with-temp-buffer
721     (insert "{ }")
722     (goto-char 2)
723     (let ((tpl (company-template-declare-template (point) (1- (point-max)))))
724       (save-excursion
725         (dotimes (i 2)
726           (insert " ")
727           (company-template-add-field tpl (point) "foo")))
728       (company-call 'template-forward-field)
729       (should (= 3 (point)))
730       (company-call 'template-forward-field)
731       (should (= 7 (point)))
732       (company-call 'template-forward-field)
733       (should (= 11 (point)))
734       (should (zerop (length (overlay-get tpl 'company-template-fields))))
735       (should (null (overlay-buffer tpl))))))
736
737 (ert-deftest company-template-removed-after-input-and-jump ()
738   (with-temp-buffer
739     (insert "{ }")
740     (goto-char 2)
741     (let ((tpl (company-template-declare-template (point) (1- (point-max)))))
742       (save-excursion
743         (insert " ")
744         (company-template-add-field tpl (point) "bar"))
745       (company-call 'template-move-to-first tpl)
746       (should (= 3 (point)))
747       (dolist (c (string-to-list "tee"))
748         (let ((last-command-event c))
749           (company-call 'self-insert-command 1)))
750       (should (string= "{ tee }" (buffer-string)))
751       (should (overlay-buffer tpl))
752       (company-call 'template-forward-field)
753       (should (= 7 (point)))
754       (should (null (overlay-buffer tpl))))))
755
756 (defun company-call (name &rest args)
757   (let* ((maybe (intern (format "company-%s" name)))
758          (command (if (fboundp maybe) maybe name)))
759     (let ((this-command command))
760       (run-hooks 'pre-command-hook))
761     (apply command args)
762     (let ((this-command command))
763       (run-hooks 'post-command-hook))))
764
765 (ert-deftest company-template-c-like-templatify ()
766   (with-temp-buffer
767     (let ((text "foo(int a, short b)"))
768       (insert text)
769       (company-template-c-like-templatify text)
770       (should (equal "foo(arg0, arg1)" (buffer-string)))
771       (should (looking-at "arg0"))
772       (should (equal "int a"
773                      (overlay-get (company-template-field-at) 'display))))))
774
775 (ert-deftest company-template-c-like-templatify-trims-after-closing-paren ()
776   (with-temp-buffer
777     (let ((text "foo(int a, short b)!@ #1334 a"))
778       (insert text)
779       (company-template-c-like-templatify text)
780       (should (equal "foo(arg0, arg1)" (buffer-string)))
781       (should (looking-at "arg0")))))
782
783 ;;; Clang
784
785 (ert-deftest company-clang-objc-templatify ()
786   (with-temp-buffer
787     (let ((text "createBookWithTitle:andAuthor:"))
788       (insert text)
789       (company-clang-objc-templatify text)
790       (should (equal "createBookWithTitle:arg0 andAuthor:arg1" (buffer-string)))
791       (should (looking-at "arg0"))
792       (should (null (overlay-get (company-template-field-at) 'display))))))