Skip to content

Commit b77f6bf

Browse files
committed
Preprocess: add unit tests for file renaming
This adds unit tests for functions related to file renaming: build_rename_map, rename_files, and transform_relative_link.
1 parent 35a2c83 commit b77f6bf

File tree

1 file changed

+172
-1
lines changed

1 file changed

+172
-1
lines changed

tests/test_preprocess.py

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,23 @@
2121
from commands.preprocess import * #pylint: disable=unused-wildcard-import
2222
import io
2323
import os
24+
import sys
25+
import contextlib
2426
import unittest
27+
import unittest.mock
2528
from lxml import etree
2629

30+
class DummyFile(object):
31+
def write(self, x): pass
32+
33+
# From https://stackoverflow.com/a/2829036/1849769
34+
@contextlib.contextmanager
35+
def nostdout():
36+
save_stdout = sys.stdout
37+
sys.stdout = DummyFile()
38+
yield
39+
sys.stdout = save_stdout
40+
2741
class TestConvertLoaderName(unittest.TestCase):
2842
def test_convert_loader_name(self):
2943
url = 'http://en.cppreference.com/mwiki/load.php?debug=false&lang=en&modules=site&only=scripts&skin=cppreference2&*'
@@ -225,7 +239,6 @@ def check_output(self, expected_file):
225239
actual = buf.getvalue()
226240

227241
self.assertEqual(expected, actual)
228-
pass
229242

230243
def test_remove_noprint(self):
231244
remove_noprint(self.html)
@@ -250,3 +263,161 @@ def test_remove_fileinfo(self):
250263
def remove_unused_external(self):
251264
remove_unused_external(self.html)
252265
self.check_output("fabs_external.html")
266+
267+
class TestFileRename(unittest.TestCase):
268+
def make_rename_map(self, root):
269+
def p(*dirs):
270+
return os.path.join(root, 'dir1', *dirs)
271+
return {
272+
'invalid*.txt': 'invalid_star_.txt',
273+
'confl"ict".html': 'confl_q_ict_q_.html',
274+
'Confl"ict".html': 'Confl_q_ict_q_.html',
275+
'load.php?modules=site&only=scripts': 'site_scripts.js',
276+
'load.php?modules=someext&only=styles': 'ext.css',
277+
p('sub2', 'Conflict.html'): 'Conflict.2.html',
278+
p('sub3', 'Confl_q_ict_q_.html'): 'Confl_q_ict_q_.2.html',
279+
p('sub4', 'Conflict'): 'Conflict.2',
280+
p('sub4', 'conFlict'): 'conFlict.3',
281+
p('sub5', 'Conflict'): 'Conflict.2'
282+
}
283+
284+
def make_walk_result(self, root):
285+
def p(*dirs):
286+
return os.path.join(root, 'dir1', *dirs)
287+
return [
288+
# Nothing to do
289+
(p(), ('sub1', 'sub2', 'sub3', 'sub4', 'sub5', 'sub6'), ('f1', 'f2')),
290+
# Unwanted characters
291+
(p('sub1'), (), ('invalid*.txt', 'valid.txt')),
292+
# Case conflict
293+
(p('sub2'), (), ('conflict.html', 'Conflict.html')),
294+
# Unwanted characters + case conflict
295+
(p('sub3'), (), ('confl"ict".html', 'Confl"ict".html')),
296+
# Multiple case conflicts, no extension
297+
(p('sub4'), (), ('conflict', 'Conflict', 'conFlict')),
298+
# Case conflict in second directory
299+
(p('sub5'), (), ('conflict', 'Conflict')),
300+
# Loader links
301+
(p('sub6'), (), ('load.php?modules=site&only=scripts', 'load.php?modules=someext&only=styles'))
302+
]
303+
304+
def test_build_rename_map(self):
305+
with unittest.mock.patch('os.walk') as walk:
306+
walk.return_value = self.make_walk_result('output')
307+
308+
actual = build_rename_map('output')
309+
310+
expected = self.make_rename_map('output')
311+
self.assertEqual(expected, actual)
312+
313+
def test_rename_files(self):
314+
expected = [
315+
(('output/dir1/sub1/invalid*.txt', 'output/dir1/sub1/invalid_star_.txt'), {}),
316+
(('output/dir1/sub2/Conflict.html', 'output/dir1/sub2/Conflict.2.html'), {}),
317+
(('output/dir1/sub3/confl"ict".html', 'output/dir1/sub3/confl_q_ict_q_.html'), {}),
318+
(('output/dir1/sub3/Confl"ict".html', 'output/dir1/sub3/Confl_q_ict_q_.2.html'), {}),
319+
(('output/dir1/sub4/Conflict', 'output/dir1/sub4/Conflict.2'), {}),
320+
(('output/dir1/sub4/conFlict', 'output/dir1/sub4/conFlict.3'), {}),
321+
(('output/dir1/sub5/Conflict', 'output/dir1/sub5/Conflict.2'), {}),
322+
(('output/dir1/sub6/load.php?modules=site&only=scripts', 'output/dir1/sub6/site_scripts.js'), {}),
323+
(('output/dir1/sub6/load.php?modules=someext&only=styles', 'output/dir1/sub6/ext.css'), {})
324+
]
325+
326+
actual = []
327+
def record_call(*args, **kwargs):
328+
actual.append((args, kwargs))
329+
330+
with unittest.mock.patch('os.walk') as walk, \
331+
unittest.mock.patch('shutil.move') as move:
332+
walk.return_value = self.make_walk_result('output')
333+
move.side_effect = record_call
334+
335+
with nostdout():
336+
rename_files('output', self.make_rename_map('output'))
337+
338+
self.assertEqual(expected, actual,
339+
msg="Unexpected sequence of calls to shutil.move")
340+
341+
def test_transform_relative_link(self):
342+
entries = [
343+
# (file, target, expected)
344+
('output/dir1/sub2/conflict.html',
345+
'../f1',
346+
'../f1'),
347+
348+
('output/dir1/sub2/Conflict.html',
349+
'../f1',
350+
'../f1'),
351+
352+
('output/dir1/sub2/Conflict.html',
353+
'../f1#p2',
354+
'../f1#p2'),
355+
356+
('output/dir1/sub2/Conflict.html',
357+
'../f1?some=param',
358+
'../f1'),
359+
360+
('output/dir1/sub2/Conflict.html',
361+
'../f1?some=param#p2',
362+
'../f1#p2'),
363+
364+
('output/dir1/sub2/Conflict.html',
365+
'../mwiki/site.css',
366+
'../common/site.css'),
367+
368+
('output/dir1/sub2/Conflict.html',
369+
'../../upload.cppreference.com/mwiki/site.css',
370+
'../common/site.css'),
371+
372+
('output/dir1/f2',
373+
'sub1/invalid*.txt',
374+
'sub1/invalid_star_.txt'),
375+
376+
('output/dir1/sub0/other.html',
377+
'../sub1/invalid*.txt',
378+
'../sub1/invalid_star_.txt'),
379+
380+
('output/dir1/sub1/valid.txt',
381+
'../sub2/conflict.html',
382+
'../sub2/conflict.html'),
383+
384+
('output/dir1/sub1/valid.txt',
385+
'../sub2/Conflict.html',
386+
'../sub2/Conflict.2.html'),
387+
388+
('output/dir1/sub1/valid.txt',
389+
'../sub3/confl"ict".html',
390+
'../sub3/confl_q_ict_q_.html'),
391+
392+
('output/dir1/sub1/valid.txt',
393+
'../sub3/Confl"ict".html',
394+
'../sub3/Confl_q_ict_q_.2.html'),
395+
396+
('output/dir1/sub1/valid.txt',
397+
'../sub4/conflict',
398+
'../sub4/conflict'),
399+
400+
('output/dir1/sub1/valid.txt',
401+
'../sub4/Conflict',
402+
'../sub4/Conflict.2'),
403+
404+
('output/dir1/sub1/valid.txt',
405+
'../sub4/conFlict',
406+
'../sub4/conFlict.3'),
407+
408+
('output/dir1/sub1/valid.txt',
409+
'../sub5/conflict',
410+
'../sub5/conflict'),
411+
412+
('output/dir1/sub1/valid.txt',
413+
'../sub5/Conflict',
414+
'../sub5/Conflict.2'),
415+
]
416+
417+
# trasform_relative_link(rename_map, target, file)
418+
# target: the relative link to transform, if target is in rename map
419+
# file: path of the file that contains the link
420+
rename_map = self.make_rename_map('output')
421+
for file, target, expected in entries:
422+
self.assertEqual(expected, trasform_relative_link(rename_map, target, file),
423+
msg="target='{}', file='{}'".format(target, file))

0 commit comments

Comments
 (0)