Hex Artifact Content
Not logged in

Artifact e664991b3e89b7b8923476d74bf6816223ea4768:


0000: 23 21 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20 70  #!/usr/bin/env p
0010: 79 74 68 6f 6e 0a 23 20 2d 2a 2d 20 63 6f 64 69  ython.# -*- codi
0020: 6e 67 3a 20 75 74 66 2d 38 20 2d 2a 2d 0a 0a 69  ng: utf-8 -*-..i
0030: 6d 70 6f 72 74 20 64 69 66 66 6c 69 62 0a 69 6d  mport difflib.im
0040: 70 6f 72 74 20 6a 73 6f 6e 0a 69 6d 70 6f 72 74  port json.import
0050: 20 6f 73 0a 69 6d 70 6f 72 74 20 72 65 0a 69 6d   os.import re.im
0060: 70 6f 72 74 20 73 75 62 70 72 6f 63 65 73 73 0a  port subprocess.
0070: 69 6d 70 6f 72 74 20 75 6e 69 74 74 65 73 74 0a  import unittest.
0080: 0a 54 45 53 54 5f 52 4f 4f 54 20 3d 20 6f 73 2e  .TEST_ROOT = os.
0090: 70 61 74 68 2e 64 69 72 6e 61 6d 65 28 5f 5f 66  path.dirname(__f
00a0: 69 6c 65 5f 5f 29 0a 50 52 4f 4a 45 43 54 5f 52  ile__).PROJECT_R
00b0: 4f 4f 54 20 3d 20 6f 73 2e 70 61 74 68 2e 64 69  OOT = os.path.di
00c0: 72 6e 61 6d 65 28 54 45 53 54 5f 52 4f 4f 54 29  rname(TEST_ROOT)
00d0: 0a 48 4f 45 44 4f 57 4e 20 3d 20 5b 6f 73 2e 70  .HOEDOWN = [os.p
00e0: 61 74 68 2e 61 62 73 70 61 74 68 28 6f 73 2e 70  ath.abspath(os.p
00f0: 61 74 68 2e 6a 6f 69 6e 28 50 52 4f 4a 45 43 54  ath.join(PROJECT
0100: 5f 52 4f 4f 54 2c 20 27 68 6f 65 64 6f 77 6e 27  _ROOT, 'hoedown'
0110: 29 29 5d 0a 54 49 44 59 20 3d 20 5b 27 74 69 64  ))].TIDY = ['tid
0120: 79 27 2c 20 27 2d 2d 73 68 6f 77 2d 62 6f 64 79  y', '--show-body
0130: 2d 6f 6e 6c 79 27 2c 20 27 31 27 2c 20 27 2d 2d  -only', '1', '--
0140: 73 68 6f 77 2d 77 61 72 6e 69 6e 67 73 27 2c 20  show-warnings', 
0150: 27 30 27 2c 0a 20 20 20 20 20 20 20 20 27 2d 2d  '0',.        '--
0160: 71 75 69 65 74 27 2c 20 27 31 27 5d 0a 43 4f 4e  quiet', '1'].CON
0170: 46 49 47 5f 50 41 54 48 20 3d 20 6f 73 2e 70 61  FIG_PATH = os.pa
0180: 74 68 2e 6a 6f 69 6e 28 54 45 53 54 5f 52 4f 4f  th.join(TEST_ROO
0190: 54 2c 20 27 63 6f 6e 66 69 67 2e 6a 73 6f 6e 27  T, 'config.json'
01a0: 29 0a 53 4c 55 47 49 46 59 5f 50 41 54 54 45 52  ).SLUGIFY_PATTER
01b0: 4e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 72  N = re.compile(r
01c0: 27 5c 57 27 29 0a 0a 0a 64 65 66 20 77 69 74 68  '\W')...def with
01d0: 5f 6d 65 74 61 63 6c 61 73 73 28 6d 65 74 61 2c  _metaclass(meta,
01e0: 20 2a 62 61 73 65 73 29 3a 0a 20 20 20 20 22 22   *bases):.    ""
01f0: 22 4d 65 74 61 63 6c 61 73 73 20 69 6e 6a 65 63  "Metaclass injec
0200: 74 69 6f 6e 20 75 74 69 6c 69 74 79 20 66 72 6f  tion utility fro
0210: 6d 20 73 69 78 2e 0a 0a 20 20 20 20 53 65 65 3a  m six...    See:
0220: 20 68 74 74 70 73 3a 2f 2f 70 79 74 68 6f 6e 68   https://pythonh
0230: 6f 73 74 65 64 2e 6f 72 67 2f 73 69 78 2f 0a 20  osted.org/six/. 
0240: 20 20 20 22 22 22 0a 20 20 20 20 63 6c 61 73 73     """.    class
0250: 20 6d 65 74 61 63 6c 61 73 73 28 6d 65 74 61 29   metaclass(meta)
0260: 3a 0a 20 20 20 20 20 20 20 20 64 65 66 20 5f 5f  :.        def __
0270: 6e 65 77 5f 5f 28 63 6c 73 2c 20 6e 61 6d 65 2c  new__(cls, name,
0280: 20 74 68 69 73 5f 62 61 73 65 73 2c 20 64 29 3a   this_bases, d):
0290: 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
02a0: 75 72 6e 20 6d 65 74 61 28 6e 61 6d 65 2c 20 62  urn meta(name, b
02b0: 61 73 65 73 2c 20 64 29 0a 20 20 20 20 72 65 74  ases, d).    ret
02c0: 75 72 6e 20 74 79 70 65 2e 5f 5f 6e 65 77 5f 5f  urn type.__new__
02d0: 28 6d 65 74 61 63 6c 61 73 73 2c 20 27 74 65 6d  (metaclass, 'tem
02e0: 70 6f 72 61 72 79 5f 63 6c 61 73 73 27 2c 20 28  porary_class', (
02f0: 29 2c 20 7b 7d 29 0a 0a 0a 63 6c 61 73 73 20 54  ), {})...class T
0300: 65 73 74 46 61 69 6c 65 64 28 41 73 73 65 72 74  estFailed(Assert
0310: 69 6f 6e 45 72 72 6f 72 29 3a 0a 20 20 20 20 64  ionError):.    d
0320: 65 66 20 5f 5f 69 6e 69 74 5f 5f 28 73 65 6c 66  ef __init__(self
0330: 2c 20 6e 61 6d 65 2c 20 65 78 70 65 63 74 65 64  , name, expected
0340: 2c 20 67 6f 74 29 3a 0a 20 20 20 20 20 20 20 20  , got):.        
0350: 73 75 70 65 72 28 54 65 73 74 46 61 69 6c 65 64  super(TestFailed
0360: 2c 20 73 65 6c 66 29 2e 5f 5f 69 6e 69 74 5f 5f  , self).__init__
0370: 28 73 65 6c 66 29 0a 20 20 20 20 20 20 20 20 64  (self).        d
0380: 69 66 66 20 3d 20 64 69 66 66 6c 69 62 2e 75 6e  iff = difflib.un
0390: 69 66 69 65 64 5f 64 69 66 66 28 0a 20 20 20 20  ified_diff(.    
03a0: 20 20 20 20 20 20 20 20 65 78 70 65 63 74 65 64          expected
03b0: 2e 73 70 6c 69 74 6c 69 6e 65 73 28 29 2c 20 67  .splitlines(), g
03c0: 6f 74 2e 73 70 6c 69 74 6c 69 6e 65 73 28 29 2c  ot.splitlines(),
03d0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 66 72 6f  .            fro
03e0: 6d 66 69 6c 65 3d 27 45 78 70 65 63 74 65 64 27  mfile='Expected'
03f0: 2c 20 74 6f 66 69 6c 65 3d 27 47 6f 74 27 2c 0a  , tofile='Got',.
0400: 20 20 20 20 20 20 20 20 29 0a 20 20 20 20 20 20          ).      
0410: 20 20 73 65 6c 66 2e 64 65 73 63 72 69 70 74 69    self.descripti
0420: 6f 6e 20 3d 20 27 7b 6e 61 6d 65 7d 5c 6e 7b 64  on = '{name}\n{d
0430: 69 66 66 7d 27 2e 66 6f 72 6d 61 74 28 0a 20 20  iff}'.format(.  
0440: 20 20 20 20 20 20 20 20 20 20 6e 61 6d 65 3d 6e            name=n
0450: 61 6d 65 2c 20 64 69 66 66 3d 27 5c 6e 27 2e 6a  ame, diff='\n'.j
0460: 6f 69 6e 28 64 69 66 66 29 2c 0a 20 20 20 20 20  oin(diff),.     
0470: 20 20 20 29 0a 0a 20 20 20 20 64 65 66 20 5f 5f     )..    def __
0480: 73 74 72 5f 5f 28 73 65 6c 66 29 3a 0a 20 20 20  str__(self):.   
0490: 20 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66       return self
04a0: 2e 64 65 73 63 72 69 70 74 69 6f 6e 0a 0a 0a 64  .description...d
04b0: 65 66 20 5f 74 65 73 74 5f 66 75 6e 63 28 74 65  ef _test_func(te
04c0: 73 74 5f 63 61 73 65 29 3a 0a 20 20 20 20 66 6c  st_case):.    fl
04d0: 61 67 73 20 3d 20 74 65 73 74 5f 63 61 73 65 2e  ags = test_case.
04e0: 67 65 74 28 27 66 6c 61 67 73 27 29 20 6f 72 20  get('flags') or 
04f0: 5b 5d 0a 20 20 20 20 68 6f 65 64 6f 77 6e 5f 70  [].    hoedown_p
0500: 72 6f 63 20 3d 20 73 75 62 70 72 6f 63 65 73 73  roc = subprocess
0510: 2e 50 6f 70 65 6e 28 0a 20 20 20 20 20 20 20 20  .Popen(.        
0520: 48 4f 45 44 4f 57 4e 20 2b 20 66 6c 61 67 73 20  HOEDOWN + flags 
0530: 2b 20 5b 6f 73 2e 70 61 74 68 2e 6a 6f 69 6e 28  + [os.path.join(
0540: 54 45 53 54 5f 52 4f 4f 54 2c 20 74 65 73 74 5f  TEST_ROOT, test_
0550: 63 61 73 65 5b 27 69 6e 70 75 74 27 5d 29 5d 2c  case['input'])],
0560: 0a 20 20 20 20 20 20 20 20 73 74 64 6f 75 74 3d  .        stdout=
0570: 73 75 62 70 72 6f 63 65 73 73 2e 50 49 50 45 2c  subprocess.PIPE,
0580: 0a 20 20 20 20 29 0a 20 20 20 20 73 74 64 6f 75  .    ).    stdou
0590: 74 64 61 74 61 20 3d 20 68 6f 65 64 6f 77 6e 5f  tdata = hoedown_
05a0: 70 72 6f 63 2e 63 6f 6d 6d 75 6e 69 63 61 74 65  proc.communicate
05b0: 28 29 5b 30 5d 0a 0a 20 20 20 20 67 6f 74 5f 74  ()[0]..    got_t
05c0: 69 64 79 5f 70 72 6f 63 20 3d 20 73 75 62 70 72  idy_proc = subpr
05d0: 6f 63 65 73 73 2e 50 6f 70 65 6e 28 0a 20 20 20  ocess.Popen(.   
05e0: 20 20 20 20 20 54 49 44 59 2c 20 73 74 64 69 6e       TIDY, stdin
05f0: 3d 73 75 62 70 72 6f 63 65 73 73 2e 50 49 50 45  =subprocess.PIPE
0600: 2c 20 73 74 64 6f 75 74 3d 73 75 62 70 72 6f 63  , stdout=subproc
0610: 65 73 73 2e 50 49 50 45 2c 0a 20 20 20 20 29 0a  ess.PIPE,.    ).
0620: 20 20 20 20 67 6f 74 20 3d 20 67 6f 74 5f 74 69      got = got_ti
0630: 64 79 5f 70 72 6f 63 2e 63 6f 6d 6d 75 6e 69 63  dy_proc.communic
0640: 61 74 65 28 69 6e 70 75 74 3d 73 74 64 6f 75 74  ate(input=stdout
0650: 64 61 74 61 29 5b 30 5d 2e 73 74 72 69 70 28 29  data)[0].strip()
0660: 0a 0a 20 20 20 20 65 78 70 65 63 74 65 64 5f 74  ..    expected_t
0670: 69 64 79 5f 70 72 6f 63 20 3d 20 73 75 62 70 72  idy_proc = subpr
0680: 6f 63 65 73 73 2e 50 6f 70 65 6e 28 0a 20 20 20  ocess.Popen(.   
0690: 20 20 20 20 20 54 49 44 59 20 2b 20 5b 6f 73 2e       TIDY + [os.
06a0: 70 61 74 68 2e 6a 6f 69 6e 28 54 45 53 54 5f 52  path.join(TEST_R
06b0: 4f 4f 54 2c 20 74 65 73 74 5f 63 61 73 65 5b 27  OOT, test_case['
06c0: 6f 75 74 70 75 74 27 5d 29 5d 2c 0a 20 20 20 20  output'])],.    
06d0: 20 20 20 20 73 74 64 6f 75 74 3d 73 75 62 70 72      stdout=subpr
06e0: 6f 63 65 73 73 2e 50 49 50 45 2c 0a 20 20 20 20  ocess.PIPE,.    
06f0: 29 0a 20 20 20 20 65 78 70 65 63 74 65 64 20 3d  ).    expected =
0700: 20 65 78 70 65 63 74 65 64 5f 74 69 64 79 5f 70   expected_tidy_p
0710: 72 6f 63 2e 63 6f 6d 6d 75 6e 69 63 61 74 65 28  roc.communicate(
0720: 29 5b 30 5d 2e 73 74 72 69 70 28 29 0a 0a 20 20  )[0].strip()..  
0730: 20 20 23 20 43 6c 65 61 6e 75 70 2e 0a 20 20 20    # Cleanup..   
0740: 20 68 6f 65 64 6f 77 6e 5f 70 72 6f 63 2e 73 74   hoedown_proc.st
0750: 64 6f 75 74 2e 63 6c 6f 73 65 28 29 0a 20 20 20  dout.close().   
0760: 20 67 6f 74 5f 74 69 64 79 5f 70 72 6f 63 2e 73   got_tidy_proc.s
0770: 74 64 6f 75 74 2e 63 6c 6f 73 65 28 29 0a 20 20  tdout.close().  
0780: 20 20 65 78 70 65 63 74 65 64 5f 74 69 64 79 5f    expected_tidy_
0790: 70 72 6f 63 2e 73 74 64 6f 75 74 2e 63 6c 6f 73  proc.stdout.clos
07a0: 65 28 29 0a 0a 20 20 20 20 74 72 79 3a 0a 20 20  e()..    try:.  
07b0: 20 20 20 20 20 20 61 73 73 65 72 74 20 65 78 70        assert exp
07c0: 65 63 74 65 64 20 3d 3d 20 67 6f 74 0a 20 20 20  ected == got.   
07d0: 20 65 78 63 65 70 74 20 41 73 73 65 72 74 69 6f   except Assertio
07e0: 6e 45 72 72 6f 72 3a 0a 20 20 20 20 20 20 20 20  nError:.        
07f0: 72 61 69 73 65 20 54 65 73 74 46 61 69 6c 65 64  raise TestFailed
0800: 28 74 65 73 74 5f 63 61 73 65 5b 27 69 6e 70 75  (test_case['inpu
0810: 74 27 5d 2c 20 65 78 70 65 63 74 65 64 2c 20 67  t'], expected, g
0820: 6f 74 29 0a 0a 0a 64 65 66 20 5f 6d 61 6b 65 5f  ot)...def _make_
0830: 74 65 73 74 28 74 65 73 74 5f 63 61 73 65 29 3a  test(test_case):
0840: 0a 20 20 20 20 72 65 74 75 72 6e 20 6c 61 6d 62  .    return lamb
0850: 64 61 20 73 65 6c 66 3a 20 5f 74 65 73 74 5f 66  da self: _test_f
0860: 75 6e 63 28 74 65 73 74 5f 63 61 73 65 29 0a 0a  unc(test_case)..
0870: 0a 63 6c 61 73 73 20 4d 61 72 6b 64 6f 77 6e 54  .class MarkdownT
0880: 65 73 74 73 4d 65 74 61 28 74 79 70 65 29 3a 0a  estsMeta(type):.
0890: 20 20 20 20 22 22 22 4d 65 74 61 20 63 6c 61 73      """Meta clas
08a0: 73 20 66 6f 72 20 60 60 4d 61 72 6b 64 6f 77 6e  s for ``Markdown
08b0: 54 65 73 74 43 61 73 65 60 60 20 74 6f 20 69 6e  TestCase`` to in
08c0: 6a 65 63 74 20 74 65 73 74 20 63 61 73 65 73 20  ject test cases 
08d0: 6f 6e 20 74 68 65 20 66 6c 79 2e 0a 20 20 20 20  on the fly..    
08e0: 22 22 22 0a 20 20 20 20 64 65 66 20 5f 5f 6e 65  """.    def __ne
08f0: 77 5f 5f 28 6d 65 74 61 2c 20 6e 61 6d 65 2c 20  w__(meta, name, 
0900: 62 61 73 65 73 2c 20 61 74 74 72 73 29 3a 0a 20  bases, attrs):. 
0910: 20 20 20 20 20 20 20 77 69 74 68 20 6f 70 65 6e         with open
0920: 28 43 4f 4e 46 49 47 5f 50 41 54 48 29 20 61 73  (CONFIG_PATH) as
0930: 20 66 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20   f:.            
0940: 63 6f 6e 66 69 67 20 3d 20 6a 73 6f 6e 2e 6c 6f  config = json.lo
0950: 61 64 28 66 29 0a 0a 20 20 20 20 20 20 20 20 66  ad(f)..        f
0960: 6f 72 20 74 65 73 74 20 69 6e 20 63 6f 6e 66 69  or test in confi
0970: 67 5b 27 74 65 73 74 73 27 5d 3a 0a 20 20 20 20  g['tests']:.    
0980: 20 20 20 20 20 20 20 20 69 6e 70 75 74 5f 6e 61          input_na
0990: 6d 65 20 3d 20 74 65 73 74 5b 27 69 6e 70 75 74  me = test['input
09a0: 27 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 61  '].            a
09b0: 74 74 72 5f 6e 61 6d 65 20 3d 20 27 74 65 73 74  ttr_name = 'test
09c0: 5f 27 20 2b 20 53 4c 55 47 49 46 59 5f 50 41 54  _' + SLUGIFY_PAT
09d0: 54 45 52 4e 2e 73 75 62 28 0a 20 20 20 20 20 20  TERN.sub(.      
09e0: 20 20 20 20 20 20 20 20 20 20 27 5f 27 2c 20 6f            '_', o
09f0: 73 2e 70 61 74 68 2e 73 70 6c 69 74 65 78 74 28  s.path.splitext(
0a00: 69 6e 70 75 74 5f 6e 61 6d 65 29 5b 30 5d 2e 6c  input_name)[0].l
0a10: 6f 77 65 72 28 29 2c 0a 20 20 20 20 20 20 20 20  ower(),.        
0a20: 20 20 20 20 29 0a 20 20 20 20 20 20 20 20 20 20      ).          
0a30: 20 20 66 75 6e 63 20 3d 20 5f 6d 61 6b 65 5f 74    func = _make_t
0a40: 65 73 74 28 74 65 73 74 29 0a 20 20 20 20 20 20  est(test).      
0a50: 20 20 20 20 20 20 66 75 6e 63 2e 5f 5f 64 6f 63        func.__doc
0a60: 5f 5f 20 3d 20 69 6e 70 75 74 5f 6e 61 6d 65 0a  __ = input_name.
0a70: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 74              if t
0a80: 65 73 74 2e 67 65 74 28 27 73 6b 69 70 27 2c 20  est.get('skip', 
0a90: 46 61 6c 73 65 29 3a 0a 20 20 20 20 20 20 20 20  False):.        
0aa0: 20 20 20 20 20 20 20 20 66 75 6e 63 20 3d 20 75          func = u
0ab0: 6e 69 74 74 65 73 74 2e 73 6b 69 70 28 69 6e 70  nittest.skip(inp
0ac0: 75 74 5f 6e 61 6d 65 29 28 66 75 6e 63 29 0a 20  ut_name)(func). 
0ad0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 74 65             if te
0ae0: 73 74 2e 67 65 74 28 27 66 61 69 6c 27 2c 20 46  st.get('fail', F
0af0: 61 6c 73 65 29 3a 0a 20 20 20 20 20 20 20 20 20  alse):.         
0b00: 20 20 20 20 20 20 20 66 75 6e 63 20 3d 20 75 6e         func = un
0b10: 69 74 74 65 73 74 2e 65 78 70 65 63 74 73 46 61  ittest.expectsFa
0b20: 69 6c 75 72 65 28 66 75 6e 63 29 0a 20 20 20 20  ilure(func).    
0b30: 20 20 20 20 20 20 20 20 61 74 74 72 73 5b 61 74          attrs[at
0b40: 74 72 5f 6e 61 6d 65 5d 20 3d 20 66 75 6e 63 0a  tr_name] = func.
0b50: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 74          return t
0b60: 79 70 65 2e 5f 5f 6e 65 77 5f 5f 28 6d 65 74 61  ype.__new__(meta
0b70: 2c 20 6e 61 6d 65 2c 20 62 61 73 65 73 2c 20 61  , name, bases, a
0b80: 74 74 72 73 29 0a 0a 0a 63 6c 61 73 73 20 4d 61  ttrs)...class Ma
0b90: 72 6b 64 6f 77 6e 54 65 73 74 73 28 77 69 74 68  rkdownTests(with
0ba0: 5f 6d 65 74 61 63 6c 61 73 73 28 4d 61 72 6b 64  _metaclass(Markd
0bb0: 6f 77 6e 54 65 73 74 73 4d 65 74 61 2c 20 75 6e  ownTestsMeta, un
0bc0: 69 74 74 65 73 74 2e 54 65 73 74 43 61 73 65 29  ittest.TestCase)
0bd0: 29 3a 0a 20 20 20 20 64 65 66 20 74 65 73 74 5f  ):.    def test_
0be0: 6c 69 6e 65 73 28 73 65 6c 66 29 3a 0a 20 20 20  lines(self):.   
0bf0: 20 20 20 20 20 66 72 6f 6d 20 6f 73 20 69 6d 70       from os imp
0c00: 6f 72 74 20 6c 69 73 74 64 69 72 0a 20 20 20 20  ort listdir.    
0c10: 20 20 20 20 66 72 6f 6d 20 6f 73 2e 70 61 74 68      from os.path
0c20: 20 69 6d 70 6f 72 74 20 69 73 66 69 6c 65 2c 20   import isfile, 
0c30: 6a 6f 69 6e 2c 20 73 70 6c 69 74 65 78 74 0a 0a  join, splitext..
0c40: 20 20 20 20 20 20 20 20 4c 49 4e 45 5f 54 45 53          LINE_TES
0c50: 54 53 20 3d 20 22 2e 2f 74 65 73 74 2f 6c 69 6e  TS = "./test/lin
0c60: 65 5f 74 65 73 74 73 22 0a 20 20 20 20 20 20 20  e_tests".       
0c70: 20 66 69 6c 65 73 20 3d 20 5b 6a 6f 69 6e 28 4c   files = [join(L
0c80: 49 4e 45 5f 54 45 53 54 53 2c 20 66 29 20 66 6f  INE_TESTS, f) fo
0c90: 72 20 66 20 69 6e 20 6c 69 73 74 64 69 72 28 4c  r f in listdir(L
0ca0: 49 4e 45 5f 54 45 53 54 53 29 0a 20 20 20 20 20  INE_TESTS).     
0cb0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 69              if i
0cc0: 73 66 69 6c 65 28 6a 6f 69 6e 28 4c 49 4e 45 5f  sfile(join(LINE_
0cd0: 54 45 53 54 53 2c 20 66 29 29 5d 0a 20 20 20 20  TESTS, f))].    
0ce0: 20 20 20 20 69 6e 64 65 78 65 73 20 3d 20 7b 7d      indexes = {}
0cf0: 0a 20 20 20 20 20 20 20 20 66 6f 72 20 66 20 69  .        for f i
0d00: 6e 20 66 69 6c 65 73 3a 0a 20 20 20 20 20 20 20  n files:.       
0d10: 20 20 20 20 20 66 69 6c 65 6e 61 6d 65 2c 20 66       filename, f
0d20: 69 6c 65 5f 65 78 74 65 6e 73 69 6f 6e 20 3d 20  ile_extension = 
0d30: 73 70 6c 69 74 65 78 74 28 66 29 0a 20 20 20 20  splitext(f).    
0d40: 20 20 20 20 20 20 20 20 69 66 20 66 69 6c 65 5f          if file_
0d50: 65 78 74 65 6e 73 69 6f 6e 20 3d 3d 20 22 2e 6d  extension == ".m
0d60: 64 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  d":.            
0d70: 20 20 20 20 69 6e 64 65 78 65 73 5b 66 5d 20 3d      indexes[f] =
0d80: 20 66 69 6c 65 6e 61 6d 65 20 2b 20 27 2e 6f 75   filename + '.ou
0d90: 74 27 0a 20 20 20 20 20 20 20 20 66 6f 72 20 69  t'.        for i
0da0: 6e 64 65 78 20 69 6e 20 69 6e 64 65 78 65 73 3a  ndex in indexes:
0db0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 63 6f 6e  .            con
0dc0: 74 65 6e 74 20 3d 20 27 27 0a 20 20 20 20 20 20  tent = ''.      
0dd0: 20 20 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20        try:.     
0de0: 20 20 20 20 20 20 20 20 20 20 20 77 69 74 68 20             with 
0df0: 6f 70 65 6e 28 69 6e 64 65 78 65 73 5b 69 6e 64  open(indexes[ind
0e00: 65 78 5d 2c 20 27 72 27 29 20 61 73 20 66 64 64  ex], 'r') as fdd
0e10: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
0e20: 20 20 20 20 20 20 63 6f 6e 74 65 6e 74 20 3d 20        content = 
0e30: 66 64 64 2e 72 65 61 64 28 29 0a 20 20 20 20 20  fdd.read().     
0e40: 20 20 20 20 20 20 20 65 78 63 65 70 74 20 45 78         except Ex
0e50: 63 65 70 74 69 6f 6e 3a 0a 20 20 20 20 20 20 20  ception:.       
0e60: 20 20 20 20 20 20 20 20 20 72 61 69 73 65 20 54           raise T
0e70: 65 73 74 46 61 69 6c 65 64 28 69 6e 64 65 78 2c  estFailed(index,
0e80: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
0e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ea0: 20 20 27 4d 69 73 73 69 6e 67 20 66 69 6c 65 3a    'Missing file:
0eb0: 20 22 7b 7d 22 27 2e 66 6f 72 6d 61 74 28 69 6e   "{}"'.format(in
0ec0: 64 65 78 65 73 5b 69 6e 64 65 78 5d 29 2c 0a 20  dexes[index]),. 
0ed0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ee0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ef0: 27 27 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  '').            
0f00: 63 68 69 6c 64 20 3d 20 73 75 62 70 72 6f 63 65  child = subproce
0f10: 73 73 2e 50 6f 70 65 6e 28 5b 22 2e 2f 74 65 73  ss.Popen(["./tes
0f20: 74 2f 74 65 73 74 65 72 22 2c 20 69 6e 64 65 78  t/tester", index
0f30: 5d 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ],.             
0f40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0f50: 20 20 20 20 20 20 20 20 73 74 64 6f 75 74 3d 73          stdout=s
0f60: 75 62 70 72 6f 63 65 73 73 2e 50 49 50 45 29 0a  ubprocess.PIPE).
0f70: 20 20 20 20 20 20 20 20 20 20 20 20 73 74 64 6f              stdo
0f80: 75 74 20 3d 20 63 68 69 6c 64 2e 63 6f 6d 6d 75  ut = child.commu
0f90: 6e 69 63 61 74 65 28 29 5b 30 5d 0a 20 20 20 20  nicate()[0].    
0fa0: 20 20 20 20 20 20 20 20 69 66 20 73 74 64 6f 75          if stdou
0fb0: 74 20 21 3d 20 63 6f 6e 74 65 6e 74 3a 0a 20 20  t != content:.  
0fc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 61                ra
0fd0: 69 73 65 20 54 65 73 74 46 61 69 6c 65 64 28 69  ise TestFailed(i
0fe0: 6e 64 65 78 2c 20 63 6f 6e 74 65 6e 74 2c 20 73  ndex, content, s
0ff0: 74 64 6f 75 74 29 0a 0a 0a 69 66 20 5f 5f 6e 61  tdout)...if __na
1000: 6d 65 5f 5f 20 3d 3d 20 27 5f 5f 6d 61 69 6e 5f  me__ == '__main_
1010: 5f 27 3a 0a 20 20 20 20 75 6e 69 74 74 65 73 74  _':.    unittest
1020: 2e 6d 61 69 6e 28 29 0a                          .main().