Coverage for core\test_leoFind.py: 100%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2#@+leo-ver=5-thin
3#@+node:ekr.20210829124658.1: * @file ../unittests/core/test_leoFind.py
4#@@first
5"""Tests for leo.core.leoFind"""
7import re
8from leo.core import leoGlobals as g
9import leo.core.leoFind as leoFind
10from leo.core.leoGui import StringFindTabManager
11from leo.core.leoTest2 import LeoUnitTest
13#@+others
14#@+node:ekr.20200216063538.1: ** class TestFind(LeoUnitTest)
15class TestFind(LeoUnitTest):
16 """Test cases for leoFind.py"""
17 #@+others
18 #@+node:ekr.20210110073117.57: *3* TestFind.setUp
19 def setUp(self):
20 """setUp for TestFind class"""
21 super().setUp()
22 c = self.c
23 c.findCommands = self.x = x = leoFind.LeoFind(c)
24 x.ftm = StringFindTabManager(c)
25 self.settings = x.default_settings()
26 self.make_test_tree()
27 #@+node:ekr.20210110073117.56: *3* TestFind.make_test_tree
28 def make_test_tree(self):
29 """Make a test tree for other tests"""
30 c = self.c
31 root = c.rootPosition()
32 root.h = 'Root'
33 root.b = "def root():\n pass\n"
34 last = root
36 def make_child(n, p):
37 p2 = p.insertAsLastChild()
38 p2.h = f"child {n}"
39 p2.b = f"def child{n}():\n v{n} = 2\n"
40 return p2
42 def make_top(n, sib):
43 p = sib.insertAfter()
44 p.h = f"Node {n}"
45 p.b = f"def top{n}():\n v{n} = 3\n"
46 return p
48 for n in range(0, 4, 3):
49 last = make_top(n + 1, last)
50 child = make_child(n + 2, last)
51 make_child(n + 3, child)
53 for p in c.all_positions():
54 p.v.clearDirty()
55 p.v.clearVisited()
57 # Always start with the root selected.
58 c.selectPosition(c.rootPosition())
59 #@+node:ekr.20210110073117.59: *3* Tests of Commands...
60 #@+node:ekr.20210110073117.67: *4* TestFind.change-all
61 def test_change_all(self):
62 c, settings, x = self.c, self.settings, self.x
63 root = c.rootPosition()
65 def init():
66 self.make_test_tree() # Reinit the whole tree.
67 settings.change_text = '_DEF_'
68 settings.find_text = 'def'
69 settings.ignore_case = False
70 settings.node_only = False
71 settings.pattern_match = False
72 settings.suboutline_only = False
73 settings.whole_word = True
75 # Default settings.
76 init()
77 x.do_change_all(settings)
78 # Plain search, ignore case.
79 init()
80 settings.whole_word = False
81 settings.ignore_case = True
82 x.do_change_all(settings)
83 # Node only.
84 init()
85 settings.node_only = True
86 x.do_change_all(settings)
87 # Suboutline only.
88 init()
89 settings.suboutline_only = True
90 x.do_change_all(settings)
91 # Pattern match.
92 init()
93 settings.pattern_match = True
94 x.do_change_all(settings)
95 # Pattern match, ignore case.
96 init()
97 settings.pattern_match = True
98 settings.ignore_case = True
99 x.do_change_all(settings)
100 # Pattern match, with groups.
101 init()
102 settings.pattern_match = True
103 settings.find_text = r'^(def)'
104 settings.change_text = '*\1*'
105 x.do_change_all(settings)
106 # Ignore case
107 init()
108 settings.ignore_case = True
109 x.do_change_all(settings)
110 # Word, ignore case.
111 init()
112 settings.ignore_case = True
113 settings.whole_word = True
114 x.do_change_all(settings)
115 # Multiple matches
116 init()
117 root.h = 'abc'
118 root.b = 'abc\nxyz abc\n'
119 settings.find_text = settings.change_text = 'abc'
120 x.do_change_all(settings)
121 # Set ancestor @file node dirty.
122 root.h = '@file xyzzy'
123 settings.find_text = settings.change_text = 'child1'
124 x.do_change_all(settings)
125 #@+node:ekr.20210220091434.1: *4* TestFind.change-all (@file node)
126 def test_change_all_with_at_file_node(self):
127 c, settings, x = self.c, self.settings, self.x
128 root = c.rootPosition().next() # Must have children.
129 settings.find_text = 'def'
130 settings.change_text = '_DEF_'
131 settings.ignore_case = False
132 settings.match_word = True
133 settings.pattern_match = False
134 settings.suboutline_only = False
135 # Ensure that the @file node is marked dirty.
136 root.h = '@file xyzzy.py'
137 root.b = ''
138 root.v.clearDirty()
139 assert root.anyAtFileNodeName()
140 x.do_change_all(settings)
141 assert root.v.isDirty(), root.h
143 #@+node:ekr.20210220091434.2: *4* TestFind.change-all (headline)
144 def test_change_all_headline(self):
145 settings, x = self.settings, self.x
146 settings.find_text = 'child'
147 settings.change_text = '_CHILD_'
148 settings.ignore_case = False
149 settings.in_headline = True
150 settings.match_word = True
151 settings.pattern_match = False
152 settings.suboutline_only = False
153 x.do_change_all(settings)
154 #@+node:ekr.20210110073117.60: *4* TestFind.clone-find-all
155 def test_clone_find_all(self):
156 settings, x = self.settings, self.x
157 # Regex find.
158 settings.find_text = r'^def\b'
159 settings.change_text = 'def' # Don't actually change anything!
160 settings.pattern_match = True
161 x.do_clone_find_all(settings)
162 # Word find.
163 settings.find_text = 'def'
164 settings.match_word = True
165 settings.pattern_match = False
166 x.do_clone_find_all(settings)
167 # Suboutline only.
168 settings.suboutline_only = True
169 x.do_clone_find_all(settings)
170 #@+node:ekr.20210110073117.61: *4* TestFind.clone-find-all-flattened
171 def test_clone_find_all_flattened(self):
172 settings, x = self.settings, self.x
173 # regex find.
174 settings.find_text = r'^def\b'
175 settings.pattern_match = True
176 x.do_clone_find_all_flattened(settings)
177 # word find.
178 settings.find_text = 'def'
179 settings.match_word = True
180 settings.pattern_match = False
181 x.do_clone_find_all_flattened(settings)
182 # Suboutline only.
183 settings.suboutline_only = True
184 x.do_clone_find_all_flattened(settings)
185 #@+node:ekr.20210617072622.1: *4* TestFind.clone-find-marked
186 def test_clone_find_marked(self):
187 c, x = self.c, self.x
188 root = c.rootPosition()
189 root.setMarked()
190 x.cloneFindAllMarked()
191 x.cloneFindAllFlattenedMarked()
192 root.setMarked()
193 #@+node:ekr.20210615084049.1: *4* TestFind.clone-find-parents
194 def test_clone_find_parents(self):
196 c, x = self.c, self.x
197 root = c.rootPosition()
198 p = root.next().firstChild()
199 p.clone() # c.p must be a clone.
200 c.selectPosition(p)
201 x.cloneFindParents()
203 #@+node:ekr.20210110073117.62: *4* TestFind.clone-find-tag
204 def test_clone_find_tag(self):
205 c, x = self.c, self.x
207 class DummyTagController:
209 def __init__(self, clones):
210 self.clones = clones
212 def get_tagged_nodes(self, tag):
213 return self.clones
215 def show_all_tags(self):
216 pass
218 c.theTagController = DummyTagController([c.rootPosition()])
219 x.do_clone_find_tag('test')
220 c.theTagController = DummyTagController([])
221 x.do_clone_find_tag('test')
222 c.theTagController = None
223 x.do_clone_find_tag('test')
224 #@+node:ekr.20210110073117.63: *4* TestFind.find-all
225 def test_find_all(self):
226 settings, x = self.settings, self.x
228 def init():
229 self.make_test_tree() # Reinit the whole tree.
230 x.findAllUniqueFlag = False
231 x.unique_matches = set()
232 settings.change_text = '_DEF_'
233 settings.find_text = 'def'
234 settings.ignore_case = False
235 settings.node_only = False
236 settings.pattern_match = False
237 settings.suboutline_only = False
238 settings.whole_word = True
240 # Test 1.
241 init()
242 settings.pattern_match = True
243 x.do_find_all(settings)
244 # Test 2.
245 init()
246 settings.suboutline_only = True
247 x.do_find_all(settings)
248 # Test 3.
249 init()
250 settings.search_headline = False
251 settings.p.setVisited()
252 x.do_find_all(settings)
253 # Test 4.
254 init()
255 x.findAllUniqueFlag = True
256 settings.pattern_match = True
257 settings.find_text = r'^(def)'
258 settings.change_text = '*\1*'
259 x.do_find_all(settings)
260 # Test 5: no match.
261 init()
262 settings.find_text = 'not-found-xyzzy'
263 x.do_find_all(settings)
265 #@+node:ekr.20210110073117.65: *4* TestFind.find-def
266 def test_find_def(self):
267 settings, x = self.settings, self.x
268 # Test methods called by x.find_def.
269 # It would be wrong to call these methods from x.do_find_def.
270 x._save_before_find_def(x.c.rootPosition()) # Also tests _restore_after_find_def.
271 x._compute_find_def_settings('my-find-pattern')
272 #
273 # Now the main tests...
274 # Test 1.
275 for bool_val in (True, False):
276 x.reverse_find_defs = bool_val
277 p, pos, newpos = x.do_find_def(settings, word='child5', strict=True)
278 assert p
279 self.assertEqual(p.h, 'child 5')
280 s = p.b[pos:newpos]
281 self.assertEqual(s, 'def child5')
282 # Test 2: switch style.
283 p, pos, newpos = x.do_find_def(settings, word='child_5', strict=False)
284 assert p
285 self.assertEqual(p.h, 'child 5')
286 # Test 3: not found after switching style.
287 p, pos, newpos = x.do_find_def(settings, word='xyzzy', strict=False)
288 assert p is None, repr(p)
289 #@+node:ekr.20210110073117.64: *4* TestFind.find-next
290 def test_find_next(self):
291 settings, x = self.settings, self.x
292 settings.find_text = 'def top1'
293 p, pos, newpos = x.do_find_next(settings)
294 assert p
295 self.assertEqual(p.h, 'Node 1')
296 s = p.b[pos:newpos]
297 self.assertEqual(s, settings.find_text)
298 #@+node:ekr.20210220072631.1: *4* TestFind.find-next (suboutline-only)
299 def test_find_next_suboutline_only(self):
300 settings, x = self.settings, self.x
301 settings.find_text = 'def root()'
302 settings.suboutline_only = True # init_ivars_from_settings will set the ivar.
303 p, pos, newpos = x.do_find_next(settings)
304 assert p
305 self.assertEqual(p.h, 'Root')
306 s = p.b[pos:newpos]
307 self.assertEqual(s, settings.find_text)
308 #@+node:ekr.20210924032146.1: *4* TestFind.change-then-find (headline)
309 def test_change_then_find_in_headline(self):
310 # Test #2220:
311 # https://github.com/leo-editor/leo-editor/issues/2220
312 # Let block.
313 settings, c, x = self.settings, self.c, self.x
314 # Set up the search.
315 settings.find_text = 'Test'
316 settings.change_text = 'XX'
317 # Create the tree.
318 test_p = self.c.rootPosition().insertAfter()
319 test_p.h = 'Test1 Test2 Test3'
320 after_p = test_p.insertAfter()
321 after_p.h = 'After'
322 # Find test_p.
323 p, pos, newpos = x.do_find_next(settings)
324 self.assertEqual(p, test_p)
325 w = c.edit_widget(p)
326 self.assertEqual(test_p.h, w.getAllText())
327 self.assertEqual(w.getSelectionRange(), (pos, newpos))
328 # Do change-then-find.
329 ok = x.do_change_then_find(settings)
330 self.assertTrue(ok)
331 p = c.p
332 self.assertEqual(p, test_p)
333 self.assertEqual(p.h, 'XX1 Test2 Test3')
334 #@+node:ekr.20210216094444.1: *4* TestFind.find-prev
335 def test_find_prev(self):
336 c, settings, x = self.c, self.settings, self.x
337 settings.find_text = 'def top1'
338 # Start at end, so we stay in the node.
339 grand_child = g.findNodeAnywhere(c, 'child 6')
340 settings.p = grand_child
341 assert settings.p
342 settings.find_text = 'def child2'
343 # Set c.p in the command.
344 x.c.selectPosition(grand_child)
345 p, pos, newpos = x.do_find_prev(settings)
346 assert p
347 self.assertEqual(p.h, 'child 2')
348 s = p.b[pos:newpos]
349 self.assertEqual(s, settings.find_text)
350 #@+node:ekr.20210110073117.66: *4* TestFind.find-var
351 def test_find_var(self):
352 settings, x = self.settings, self.x
353 p, pos, newpos = x.do_find_var(settings, word='v5')
354 assert p
355 self.assertEqual(p.h, 'child 5')
356 s = p.b[pos:newpos]
357 self.assertEqual(s, 'v5 =')
358 #@+node:ekr.20210110073117.68: *4* TestFind.replace-then-find
359 def test_replace_then_find(self):
360 settings, w, x = self.settings, self.c.frame.body.wrapper, self.x
361 settings.find_text = 'def top1'
362 settings.change_text = 'def top'
363 # find-next
364 p, pos, newpos = x.do_find_next(settings)
365 assert p
366 self.assertEqual(p.h, 'Node 1')
367 s = p.b[pos:newpos]
368 self.assertEqual(s, settings.find_text)
369 # replace-then-find
370 w.setSelectionRange(pos, newpos, insert=pos)
371 x.do_change_then_find(settings)
372 # Failure exit.
373 w.setSelectionRange(0, 0)
374 x.do_change_then_find(settings)
376 def test_replace_then_find_regex(self):
377 settings, w, x = self.settings, self.c.frame.body.wrapper, self.x
378 settings.find_text = r'(def) top1'
379 settings.change_text = r'\1\1'
380 settings.pattern_match = True
381 # find-next
382 p, pos, newpos = x.do_find_next(settings)
383 s = p.b[pos:newpos]
384 self.assertEqual(s, 'def top1')
385 # replace-then-find
386 w.setSelectionRange(pos, newpos, insert=pos)
387 x.do_change_then_find(settings)
389 def test_replace_then_find_in_headline(self):
390 settings, x = self.settings, self.x
391 p = settings.p
392 settings.find_text = 'Node 1'
393 settings.change_text = 'Node 1a'
394 settings.in_headline = True
395 # find-next
396 p, pos, newpos = x.do_find_next(settings)
397 assert p
398 self.assertEqual(p.h, settings.find_text)
399 w = self.c.edit_widget(p)
400 assert w
401 s = p.h[pos:newpos]
402 self.assertEqual(s, settings.find_text)
403 #@+node:ekr.20210110073117.69: *4* TestFind.tag-children
404 def test_tag_children(self):
406 c, x = self.c, self.x
408 class DummyTagController:
409 def add_tag(self, p, tag):
410 pass
412 p = c.rootPosition().next()
413 c.theTagController = None
414 x.do_tag_children(p, 'test')
415 c.theTagController = DummyTagController()
416 x.do_tag_children(p, 'test')
417 #@+node:ekr.20210219181001.1: *4* testFind.test_batch_change_regex
418 def test_batch_change_regex(self):
419 c, x = self.c, self.x
420 # self.dump_tree()
421 # Test 1: Match in body.
422 settings = dict(
423 ignore_case=False,
424 node_only=False,
425 pattern_match=True,
426 search_body=True,
427 search_headline=True,
428 suboutline_only=False,
429 whole_word=False,
430 )
431 # Test 1: Match in body.
432 n = x.batch_change(
433 root=c.rootPosition(),
434 replacements=((r'^def\b', 'DEF'),),
435 settings=settings)
436 assert n > 3, n # Test 1.
437 # Test 2: Match in headline.
438 n = x.batch_change(
439 root=c.rootPosition(),
440 replacements=((r'^Node\b', 'DEF'),),
441 settings=settings)
442 self.assertEqual(n, 2)
443 # Test 3: node-only.
444 settings['node_only'] = True
445 n = x.batch_change(
446 root=c.rootPosition(),
447 replacements=((r'^DEF\b', 'def'),),
448 settings=settings)
449 self.assertEqual(n, 1)
450 # Test 4: suboutline-only.
451 settings['node_only'] = False
452 settings['suboutline_only'] = True
453 n = x.batch_change(
454 root=c.rootPosition(),
455 replacements=((r'^def\b', 'DEF'),),
456 settings=settings)
457 self.assertEqual(n, 1)
458 #@+node:ekr.20210219175850.1: *4* testFind.test_batch_change_word
459 def test_batch_change_word(self):
460 # settings, x = self.settings, self.x
461 c, x = self.c, self.x
462 settings = dict(
463 ignore_case=False,
464 node_only=False,
465 pattern_match=False,
466 search_body=True,
467 search_headline=True,
468 suboutline_only=False,
469 whole_word=True,
470 )
471 n = x.batch_change(
472 root=c.rootPosition(),
473 replacements=(('def', 'DEF'),),
474 settings=settings)
475 assert n > 0
477 #@+node:ekr.20210110073117.58: *4* TestFind.test_tree
478 def test_tree(self):
479 c = self.c
480 table = (
481 (0, 'Root'),
482 (0, 'Node 1'),
483 (1, 'child 2'),
484 (2, 'child 3'),
485 (0, 'Node 4'),
486 (1, 'child 5'),
487 (2, 'child 6'),
488 )
489 for level, h in table:
490 p = g.findNodeAnywhere(c, h)
491 self.assertEqual(p.h, h)
492 self.assertEqual(p.level(), level)
493 #@+node:ekr.20210110073117.70: *3* Tests of Helpers...
494 #@+node:ekr.20210110073117.72: *4* TestFind.test_argument_errors
495 def test_argument_errors(self):
497 settings, x = self.settings, self.x
498 # Bad search pattern.
499 settings.find_text = r'^def\b(('
500 settings.pattern_match = True
501 x.do_clone_find_all(settings)
502 x.find_next_match(p=None)
503 x.do_change_all(settings)
504 #@+node:ekr.20210110073117.74: *4* TestFind.test_batch_plain_replace
505 def test_batch_plain_replace(self):
506 settings, x = self.settings, self.x
507 settings.find_text = 'b'
508 settings.change_text = 'B'
509 for ignore in (True, False):
510 settings.ignore_case = ignore
511 x.init_ivars_from_settings(settings)
512 s = 'abc b z'
513 count, s2 = x.batch_plain_replace(s)
514 self.assertEqual(count, 2, msg=f"ignore: {ignore}")
515 self.assertEqual(s2, 'aBc B z', msg=f"ignore: {ignore}")
516 #@+node:ekr.20210110073117.75: *4* TestFind.test_batch_regex_replace
517 def test_batch_regex_replace(self):
518 settings, x = self.settings, self.x
519 s = 'abc b z'
520 table = (
521 (1, 2, 'B', 'B', 'aBc B z'),
522 (0, 2, 'b', 'B', 'aBc B z'),
523 (1, 2, r'([BX])', 'B', 'aBc B z'),
524 )
525 for ignore, count, find, change, expected_s in table:
526 settings.ignore_case = bool(ignore)
527 settings.find_text = find
528 settings.change_text = change
529 x.init_ivars_from_settings(settings)
530 actual_count, actual_s = x.batch_regex_replace(s)
531 self.assertEqual(actual_count, count, msg=find)
532 self.assertEqual(actual_s, expected_s, msg=find)
533 #@+node:ekr.20210110073117.73: *4* TestFind.test_batch_word_replace
534 def test_batch_word_replace(self):
535 settings, x = self.settings, self.x
536 settings.find_text = 'b'
537 settings.change_text = 'B'
538 for ignore in (True, False):
539 settings.ignore_case = ignore
540 x.init_ivars_from_settings(settings)
541 s = 'abc b z'
542 count, s2 = x.batch_word_replace(s)
543 self.assertEqual(count, 1)
544 self.assertEqual(s2, 'abc B z')
545 #@+node:ekr.20210110073117.71: *4* TestFind.test_cfa_backwards_search
546 def test_cfa_backwards_search(self):
547 settings, x = self.settings, self.x
548 pattern = 'def'
549 for nocase in (True, False):
550 settings.ignore_case = nocase
551 for word in (True, False):
552 for s in ('def spam():\n', 'define spam'):
553 settings.whole_word = word
554 x.init_ivars_from_settings(settings)
555 x._inner_search_backward(s, 0, len(s), pattern, nocase, word)
556 x._inner_search_backward(s, 0, 0, pattern, nocase, word)
557 #@+node:ekr.20210110073117.80: *4* TestFind.test_cfa_find_next_match
558 def test_cfa_find_next_match(self):
559 c, settings, x = self.c, self.settings, self.x
560 p = c.rootPosition()
561 for find in ('xxx', 'def'):
562 settings.find_text = find
563 x._cfa_find_next_match(p)
564 #@+node:ekr.20210110073117.83: *4* TestFind.test_cfa_match_word
565 def test_cfa_match_word(self):
566 x = self.x
567 x._inner_search_match_word("def spam():", 0, "spam")
568 x._inner_search_match_word("def spam():", 0, "xxx")
570 #@+node:ekr.20210110073117.85: *4* TestFind.test_cfa_plain_search
571 def test_cfa_plain_search(self):
572 settings, x = self.settings, self.x
573 pattern = 'def'
574 for nocase in (True, False):
575 settings.ignore_case = nocase
576 for word in (True, False):
577 for s in ('def spam():\n', 'define'):
578 settings.whole_word = word
579 x.init_ivars_from_settings(settings)
580 x._inner_search_plain(s, 0, len(s), pattern, nocase, word)
581 x._inner_search_plain(s, 0, 0, pattern, nocase, word)
582 #@+node:ekr.20210110073117.88: *4* TestFind.test_cfa_regex_search
583 def test_cfa_regex_search(self):
584 x = self.x
585 pattern = r'(.*)pattern'
586 x.re_obj = re.compile(pattern)
587 table = (
588 'test pattern', # Match.
589 'xxx', # No match.
590 )
591 for backwards in (True, False):
592 for nocase in (True, False):
593 for s in table:
594 if backwards:
595 i = j = len(s)
596 else:
597 i = j = 0
598 x._inner_search_regex(s, i, j, pattern, backwards, nocase)
599 # Error test.
600 x.re_obj = None
601 backwards = pattern = nocase = None
602 x._inner_search_regex("", 0, 0, pattern, backwards, nocase)
603 #@+node:ekr.20210110073117.76: *4* TestFind.test_check_args
604 def test_check_args(self):
605 # Bad search patterns..
606 x = self.x
607 settings = self.settings
608 # Not searching headline or body.
609 settings.search_body = False
610 settings.search_headline = False
611 x.do_clone_find_all(settings)
612 # Empty find pattern.
613 settings.search_body = True
614 settings.find_text = ''
615 x.do_clone_find_all(settings)
616 x.do_clone_find_all_flattened(settings)
617 x.do_find_all(settings)
618 x.do_find_next(settings)
619 x.do_find_next(settings)
620 x.do_find_prev(settings)
621 x.do_change_all(settings)
622 x.do_change_then_find(settings)
623 #@+node:ekr.20210829203927.10: *4* TestFind.test_clean_init
624 def test_clean_init(self):
625 c = self.c
626 x = leoFind.LeoFind(c)
627 table = (
628 'ignore_case', 'node_only', 'pattern_match',
629 'search_headline', 'search_body', 'suboutline_only',
630 'mark_changes', 'mark_finds', 'whole_word',
631 )
632 for ivar in table:
633 assert getattr(x, ivar) is None, ivar
634 assert x.reverse is False
635 #@+node:ekr.20210110073117.77: *4* TestFind.test_compute_result_status
636 def test_compute_result_status(self):
637 x = self.x
638 # find_all_flag is True
639 all_settings = x.default_settings()
640 all_settings.ignore_case = True
641 all_settings.pattern_match = True
642 all_settings.whole_word = True
643 all_settings.wrapping = True
644 x.init_ivars_from_settings(all_settings)
645 x.compute_result_status(find_all_flag=True)
646 # find_all_flag is False
647 partial_settings = x.default_settings()
648 partial_settings.search_body = True
649 partial_settings.search_headline = True
650 partial_settings.node_only = True
651 partial_settings.suboutline_only = True
652 partial_settings.wrapping = True
653 x.init_ivars_from_settings(partial_settings)
654 x.compute_result_status(find_all_flag=False)
655 #@+node:ekr.20210829203927.12: *4* TestFind.test_inner_search_backward
656 def test_inner_search_backward(self):
657 c = self.c
658 x = leoFind.LeoFind(c)
660 def test(table, table_name, nocase, word):
661 test_n = 0
662 for pattern, s, i, j, expected, expected_i, expected_j in table:
663 test_n += 1
664 if j == -1:
665 j = len(s)
666 got_i, got_j = x._inner_search_backward(s, i, j,
667 pattern, nocase=nocase, word=word)
668 got = s[got_i:got_j]
669 assert expected == got and got_i == expected_i and got_j == expected_j, (
670 '\n table: %s'
671 '\n i test: %s'
672 '\n pattern: %r'
673 '\n s: %r'
674 '\n expected: %r'
675 '\n got: %r'
676 '\nexpected i: %s'
677 '\n got i: %s'
678 '\nexpected j: %s'
679 '\n got j: %s'
680 % (table_name, test_n, pattern, s, expected, got, expected_i, got_i, expected_j, got_j))
682 plain_table = (
683 # pattern s i, j expected, expected_i, expected_j
684 ('a', 'abaca', 0, -1, 'a', 4, 5),
685 ('A', 'Abcde', 0, -1, 'A', 0, 1),
686 )
687 nocase_table = (
688 # pattern s i, j expected, expected_i, expected_j
689 ('a', 'abaAca', 0, -1, 'a', 5, 6),
690 ('A', 'Abcdca', 0, -1, 'a', 5, 6),
691 )
692 word_table = (
693 # pattern s i, j expected, expected_i, expected_j
694 ('a', 'abaAca', 0, -1, '', -1, -1),
695 ('A', 'AA A AB', 0, -1, 'A', 3, 4),
696 )
697 test(plain_table, 'plain_table', nocase=False, word=False)
698 test(nocase_table, 'nocase_table', nocase=True, word=False)
699 test(word_table, 'word_table', nocase=False, word=True)
700 #@+node:ekr.20210829203927.13: *4* TestFind.test_inner_search_plain
701 def test_inner_search_plain(self):
702 c = self.c
703 x = leoFind.LeoFind(c)
705 def test(table, table_name, nocase, word):
706 test_n = 0
707 for pattern, s, i, j, expected, expected_i, expected_j in table:
708 test_n += 1
709 if j == -1:
710 j = len(s)
711 got_i, got_j = x._inner_search_plain(s, i, j, pattern,
712 nocase=nocase, word=word)
713 got = s[got_i:got_j]
714 assert expected == got and got_i == expected_i and got_j == expected_j, (
715 '\n table: %s'
716 '\n i test: %s'
717 '\n pattern: %r'
718 '\n s: %r'
719 '\n expected: %r'
720 '\n got: %r'
721 '\nexpected i: %s'
722 '\n got i: %s'
723 '\nexpected j: %s'
724 '\n got j: %s'
725 % (table_name, test_n, pattern, s, expected, got, expected_i, got_i, expected_j, got_j))
727 plain_table = (
728 # pattern s i, j expected, expected_i, expected_j
729 ('a', 'baca', 0, -1, 'a', 1, 2),
730 ('A', 'bAcde', 0, -1, 'A', 1, 2),
731 )
732 nocase_table = (
733 # pattern s i, j expected, expected_i, expected_j
734 ('a', 'abaAca', 0, -1, 'a', 0, 1),
735 ('A', 'abcdca', 0, -1, 'a', 0, 1),
736 )
737 word_table = (
738 # pattern s i, j expected, expected_i, expected_j
739 ('a', 'abaAca', 0, -1, '', -1, -1),
740 ('A', 'AA A AAB', 0, -1, 'A', 3, 4),
741 )
742 test(plain_table, 'plain_table', nocase=False, word=False)
743 test(nocase_table, 'nocase_table', nocase=True, word=False)
744 test(word_table, 'word_table', nocase=False, word=True)
745 #@+node:ekr.20210829203927.11: *4* TestFind.test_inner_search_regex
746 def test_inner_search_regex(self):
747 c = self.c
748 x = leoFind.LeoFind(c)
750 def test(table, table_name, back, nocase):
751 for pattern, s, expected in table:
752 flags = re.IGNORECASE if nocase else 0
753 x.re_obj = re.compile(pattern, flags)
754 pos, new_pos = x._inner_search_regex(s, 0, len(s),
755 pattern, backwards=back, nocase=nocase)
756 got = s[pos:new_pos]
757 assert expected == got, (
758 '\n table: %s'
759 '\n pattern: %r'
760 '\n s: %r'
761 '\nexpected: %r'
762 '\n got: %r' % (table_name, pattern, s, expected, got)
763 )
765 plain_table = (
766 # pattern s expected
767 (r'.', 'A', 'A'),
768 (r'A', 'xAy', 'A'),
769 )
770 nocase_table = (
771 # pattern s expected
772 (r'.', 'A', 'A'),
773 (r'.', 'a', 'a'),
774 (r'A', 'xay', 'a'),
775 (r'a', 'xAy', 'A'),
776 )
777 back_table = (
778 # pattern s expected
779 (r'a.b', 'a1b a2b', 'a2b'),
780 )
781 test(plain_table, 'plain_table', back=False, nocase=False)
782 test(nocase_table, 'nocase_table', back=False, nocase=True)
783 test(back_table, 'back_table', back=True, nocase=False)
784 #@+node:ekr.20210110073117.82: *4* TestFind.test_make_regex_subs
785 def test_make_regex_subs(self):
786 x = self.x
787 x.re_obj = re.compile(r'(.*)pattern') # The search pattern.
788 m = x.re_obj.search('test pattern') # The find pattern.
789 change_text = r'\1Pattern\2' # \2 is non-matching group.
790 x.make_regex_subs(change_text, m.groups())
791 #@+node:ekr.20210110073117.84: *4* TestFind.test_next_node_after_fail
792 def test_fnm_next_after_fail(self):
793 settings, x = self.settings, self.x
794 for reverse in (True, False):
795 settings.reverse = reverse
796 for wrapping in (True, False):
797 settings.wrapping = wrapping
798 x.init_ivars_from_settings(settings)
799 x._fnm_next_after_fail(settings.p)
800 #@+node:ekr.20210110073117.86: *4* TestFind.test_replace_all_helper
801 def test_replace_all_helper(self):
802 settings, x = self.settings, self.x
803 settings.find_text = 'xyzzy'
804 settings.change_text = 'xYzzy'
805 s = 'abc xyzzy done'
806 x.replace_all_helper('') # Error test.
807 for regex in (True, False):
808 settings.pattern_match = regex
809 for word in (True, False):
810 settings.whole_word = word
811 x.init_ivars_from_settings(settings)
812 x.replace_all_helper(s)
813 #@+node:ekr.20210829203927.2: *4* TestFind.test_replace_all_plain_search
814 def test_replace_all_plain_search(self):
815 c = self.c
816 fc = c.findCommands
817 plain_table = (
818 # s find change count result
819 ('aA', 'a', 'C', 1, 'CA'),
820 ('Aa', 'A', 'C', 1, 'Ca'),
821 ('Aba', 'b', 'C', 1, 'ACa'),
822 )
823 for s, find, change, count, result in plain_table:
824 fc.ignore_case = False
825 fc.find_text = find
826 fc.change_text = change
827 count2, result2 = fc._change_all_plain(s)
828 self.assertEqual(result, result2)
829 self.assertEqual(count, count2)
830 #@+node:ekr.20210829203927.3: *4* TestFind.test_replace_all_plain_search_ignore_case
831 def test_replace_all_plain_search_ignore_case(self):
832 c = self.c
833 fc = c.findCommands
834 plain_table = (
835 # s find change count result
836 ('aA', 'a', 'C', 2, 'CC'),
837 ('AbBa', 'b', 'C', 2, 'ACCa'),
838 )
839 for s, find, change, count, result in plain_table:
840 fc.ignore_case = True
841 fc.find_text = find
842 fc.change_text = change
843 count2, result2 = fc._change_all_plain(s)
844 self.assertEqual(result, result2)
845 self.assertEqual(count, count2)
846 #@+node:ekr.20210829203927.4: *4* TestFind.test_replace_all_regex_search
847 def test_replace_all_regex_search(self):
848 c = self.c
849 fc = c.findCommands
850 regex_table = (
851 # s find change count result
852 ('a ba aa a ab a', r'\b\w+\b', 'C', 6, 'C C C C C C'),
853 ('a AA aa aab ab a', r'\baa\b', 'C', 1, 'a AA C aab ab a'),
854 # Multi-line
855 ('aaa AA\naa aab', r'\baa\b', 'C', 1, 'aaa AA\nC aab'),
856 )
857 for s, find, change, count, result in regex_table:
858 fc.ignore_case = False
859 fc.find_text = find
860 fc.change_text = change
861 count2, result2 = fc._change_all_regex(s)
862 self.assertEqual(result, result2)
863 self.assertEqual(count, count2)
864 #@+node:ekr.20210829203927.5: *4* TestFind.test_replace_all_word_search
865 def test_replace_all_word_search(self):
866 c = self.c
867 fc = c.findCommands
868 word_table = (
869 # s find change count result
870 ('a ba aa a ab a', 'a', 'C', 3, 'C ba aa C ab C'),
871 ('a ba aa a ab a', 'aa', 'C', 1, 'a ba C a ab a'),
872 )
873 for s, find, change, count, result in word_table:
874 fc.ignore_case = False
875 fc.find_text = find
876 fc.change_text = change
877 count2, result2 = fc._change_all_word(s)
878 self.assertEqual(result, result2)
879 self.assertEqual(count, count2)
880 #@+node:ekr.20210829203927.6: *4* TestFind.test_replace_all_word_search_ignore_case
881 def test_replace_all_word_search_ignore_case(self):
882 c = self.c
883 fc = c.findCommands
884 word_table = (
885 # s find change count result
886 ('a ba aa A ab a', 'a', 'C', 3, 'C ba aa C ab C'),
887 ('a ba aa AA ab a', 'aa', 'C', 2, 'a ba C C ab a'),
888 )
889 for s, find, change, count, result in word_table:
890 fc.ignore_case = True
891 fc.find_text = find
892 fc.change_text = change
893 count2, result2 = fc._change_all_word(s)
894 self.assertEqual(result, result2)
895 self.assertEqual(count, count2)
896 #@+node:ekr.20210829203927.14: *4* TestFind.test_replace_back_slashes
897 def test_replace_back_slashes(self):
898 c = self.c
899 x = leoFind.LeoFind(c)
900 table = (
901 ('\\\\', '\\'),
902 ('\\n', '\n'),
903 ('\\t', '\t'),
904 (r'a\bc', r'a\bc'),
905 (r'a\\bc', r'a\bc'),
906 (r'a\tc', 'a\tc'), # Replace \t by a tab.
907 (r'a\nc', 'a\nc'), # Replace \n by a newline.
908 )
909 for s, expected in table:
910 got = x.replace_back_slashes(s)
911 self.assertEqual(expected, got, msg=s)
912 #@+node:ekr.20210110073117.89: *4* TestFind.test_switch_style
913 def test_switch_style(self):
914 x = self.x
915 table = (
916 ('', None),
917 ('TestClass', None),
918 ('camelCase', 'camel_case'),
919 ('under_score', 'underScore'),
920 )
921 for s, expected in table:
922 result = x._switch_style(s)
923 self.assertEqual(result, expected, msg=repr(s))
924 #@-others
925#@-others
927#@-leo