3030 default = False , help = 'filter stdin through normalizer for testing' )
3131parser .add_argument ('-n' , '--number' , type = int , default = None ,
3232 help = 'only consider the test with the given number' )
33+ parser .add_argument ('--track' , metavar = 'path' ,
34+ help = 'track which test cases pass/fail in the given JSON file and only report changes' )
3335parser .add_argument ('--fuzz-corpus' ,
3436 help = 'convert test cases to fuzz corpus' )
3537args = parser .parse_args (sys .argv [1 :])
3638
3739def out (str ):
3840 sys .stdout .buffer .write (str .encode ('utf-8' ))
3941
40- def print_test_header (headertext , example_number , start_line , end_line ):
41- out ("Example %d (lines %d-%d) %s\n " % (example_number ,start_line ,end_line ,headertext ))
42+ def print_test_header (test ):
43+ out ("Example %d (lines %d-%d) %s\n "
44+ % (test ['example' ], test ['start_line' ], test ['end_line' ], test ['section' ]))
4245
43- def do_test (converter , test , normalize , result_counts ):
44- [retcode , actual_html , err ] = converter (test ['markdown' ])
45- if retcode == 0 :
46- expected_html = test ['html' ]
47- unicode_error = None
48- if normalize :
49- try :
50- passed = normalize_html (actual_html ) == normalize_html (expected_html )
51- except UnicodeDecodeError as e :
52- unicode_error = e
53- passed = False
54- else :
55- passed = actual_html == expected_html
56- if passed :
57- result_counts ['pass' ] += 1
58- else :
59- print_test_header (test ['section' ], test ['example' ], test ['start_line' ], test ['end_line' ])
46+ def do_test (converter , test , normalize , prev_result ):
47+ [retcode , actual_html_bytes , err ] = converter (test ['markdown' ])
48+ if retcode != 0 :
49+ if prev_result != 'error' :
50+ print_test_header (test )
51+ out ("program returned error code %d\n " % retcode )
52+ sys .stdout .buffer .write (err )
53+ return 'error'
54+
55+ expected_html = test ['html' ]
56+
57+ try :
58+ actual_html = actual_html_bytes
59+ except UnicodeDecodeError as e :
60+ if prev_result != 'fail' :
61+ print_test_header (test )
6062 out (test ['markdown' ] + '\n ' )
61- if unicode_error :
62- out ("Unicode error: " + str (unicode_error ) + '\n ' )
63- out ("Expected: " + repr (expected_html ) + '\n ' )
64- out ("Got: " + repr (actual_html ) + '\n ' )
65- else :
66- expected_html_lines = expected_html .splitlines (True )
67- actual_html_lines = actual_html .splitlines (True )
68- for diffline in unified_diff (expected_html_lines , actual_html_lines ,
69- "expected HTML" , "actual HTML" ):
70- out (diffline )
63+ out ("Unicode error: " + str (e ) + '\n ' )
64+ out ("Expected: " + repr (expected_html ) + '\n ' )
65+ out ("Got: " + repr (actual_html_bytes ) + '\n ' )
7166 out ('\n ' )
72- result_counts ['fail' ] += 1
73- else :
74- print_test_header (test ['section' ], test ['example' ], test ['start_line' ], test ['end_line' ])
75- out ("program returned error code %d\n " % retcode )
76- sys .stdout .buffer .write (err )
77- result_counts ['error' ] += 1
67+ return 'fail'
68+
69+ if normalize :
70+ actual_html = normalize_html (actual_html ) + '\n '
71+ expected_html = normalize_html (expected_html ) + '\n '
72+
73+ if actual_html != expected_html :
74+ if prev_result != 'fail' :
75+ print_test_header (test )
76+ out (test ['markdown' ] + '\n ' )
77+ expected_html_lines = expected_html .splitlines (True )
78+ actual_html_lines = actual_html .splitlines (True )
79+ for diffline in unified_diff (expected_html_lines , actual_html_lines ,
80+ "expected HTML" , "actual HTML" ):
81+ out (diffline )
82+ out ('\n ' )
83+ return 'fail'
84+
85+ if prev_result and prev_result != 'pass' :
86+ print_test_header (test )
87+ print ('fixed!' )
88+
89+ return 'pass'
7890
7991def get_tests (specfile ):
8092 line_number = 0
@@ -95,7 +107,7 @@ def get_tests(specfile):
95107 l = line .strip ()
96108 if l == "`" * 32 + " example" :
97109 state = 1
98- elif l == "`" * 32 :
110+ elif state == 2 and l == "`" * 32 :
99111 state = 0
100112 example_number = example_number + 1
101113 end_line = line_number
@@ -144,15 +156,35 @@ def get_tests(specfile):
144156 pattern_re = re .compile (args .pattern , re .IGNORECASE )
145157 else :
146158 pattern_re = re .compile ('.' )
147- tests = [ test for test in all_tests if re .search (pattern_re , test ['section' ]) and (not args .number or test ['example' ] == args .number ) ]
159+ tests = [ test for test in all_tests if re .search (pattern_re , test ['section' ])
160+ and (not args .number or test ['example' ] == args .number ) ]
148161 if args .dump_tests :
149162 out (json .dumps (tests , ensure_ascii = False , indent = 2 ))
150163 exit (0 )
151164 else :
152165 skipped = len (all_tests ) - len (tests )
153166 converter = CMark (prog = args .program , library_dir = args .library_dir ).to_html
154167 result_counts = {'pass' : 0 , 'fail' : 0 , 'error' : 0 , 'skip' : skipped }
168+
169+ previous = {}
170+
171+ if args .track :
172+ try :
173+ with open (args .track ) as f :
174+ previous = json .load (f )
175+ except FileNotFoundError :
176+ pass
177+
178+ results = {}
179+
155180 for test in tests :
156- do_test (converter , test , args .normalize , result_counts )
181+ result = do_test (converter , test , args .normalize , previous .get (str (test ['example' ])))
182+ result_counts [result ] += 1
183+ results [test ['example' ]] = result
184+
185+ if args .track :
186+ with open (args .track , 'w' ) as f :
187+ json .dump (results , f )
188+
157189 out ("{pass} passed, {fail} failed, {error} errored, {skip} skipped\n " .format (** result_counts ))
158190 exit (result_counts ['fail' ] + result_counts ['error' ])
0 commit comments