text: """
     Tests for the mhlib module
     Nick Mathewson
  """
  
  ### BUG: This suite doesn't currently test the mime functionality of
  ###      mhlib.  It should.
  
  import unittest
  from test.test_support import run_unittest, TESTFN, import_module
  import os, StringIO
  import sys
  mhlib = import_module('mhlib', deprecated=True)
  
  if (sys.platform.startswith("win") or sys.platform=="riscos" or
        sys.platform.startswith("atheos")):
      # mhlib.updateline() renames a file to the name of a file that already
      # exists.  That causes a reasonable OS <wink> to complain in test_sequence
      # here, like the "OSError: [Errno 17] File exists" raised on Windows.
      # mhlib's listsubfolders() and listallfolders() do something with
      # link counts, and that causes test_listfolders() here to get back
      # an empty list from its call of listallfolders().
      # The other tests here pass on Windows.
      raise unittest.SkipTest("skipped on %s -- " % sys.platform +
                              "too many Unix assumptions")
  
  _mhroot = TESTFN+"_MH"
  _mhpath = os.path.join(_mhroot, "MH")
  _mhprofile = os.path.join(_mhroot, ".mh_profile")
  
  def normF(f):
      return os.path.join(*f.split('/'))
  
  def writeFile(fname, contents):
      dir = os.path.split(fname)[0]
      if dir and not os.path.exists(dir):
          mkdirs(dir)
      f = open(fname, 'w')
      f.write(contents)
      f.close()
  
  def readFile(fname):
      f = open(fname)
      r = f.read()
      f.close()
      return r
  
  def writeProfile(dict):
      contents = [ "%s: %s\n" % (k, v) for k, v in dict.iteritems() ]
      writeFile(_mhprofile, "".join(contents))
  
  def writeContext(folder):
      folder = normF(folder)
      writeFile(os.path.join(_mhpath, "context"),
                "Current-Folder: %s\n" % folder)
  
  def writeCurMessage(folder, cur):
      folder = normF(folder)
      writeFile(os.path.join(_mhpath, folder, ".mh_sequences"),
                "cur: %s\n"%cur)
  
  def writeMessage(folder, n, headers, body):
      folder = normF(folder)
      headers = "".join([ "%s: %s\n" % (k, v) for k, v in headers.iteritems() ])
      contents = "%s\n%s\n" % (headers,body)
      mkdirs(os.path.join(_mhpath, folder))
      writeFile(os.path.join(_mhpath, folder, str(n)), contents)
  
  def getMH():
      return mhlib.MH(os.path.abspath(_mhpath), _mhprofile)
  
  def sortLines(s):
      lines = s.split("\n")
      lines = [ line.strip() for line in lines if len(line) >= 2 ]
      lines.sort()
      return lines
  
  # These next 2 functions are copied from test_glob.py.
  def mkdirs(fname):
      if os.path.exists(fname) or fname == '':
          return
      base, file = os.path.split(fname)
      mkdirs(base)
      os.mkdir(fname)
  
  def deltree(fname):
      if not os.path.exists(fname):
          return
      for f in os.listdir(fname):
          fullname = os.path.join(fname, f)
          if os.path.isdir(fullname):
              deltree(fullname)
          else:
              try:
                  os.unlink(fullname)
              except:
                  pass
      try:
          os.rmdir(fname)
      except:
          pass
  
  class MhlibTests(unittest.TestCase):
      def setUp(self):
          deltree(_mhroot)
          mkdirs(_mhpath)
          writeProfile({'Path' : os.path.abspath(_mhpath),
                        'Editor': 'emacs',
                        'ignored-attribute': 'camping holiday'})
          # Note: These headers aren't really conformant to RFC822, but
          #  mhlib shouldn't care about that.
  
          # An inbox with a couple of messages.
          writeMessage('inbox', 1,
                       {'From': 'Mrs. Premise',
                        'To': 'Mrs. Conclusion',
                        'Date': '18 July 2001'}, "Hullo, Mrs. Conclusion!\n")
          writeMessage('inbox', 2,
                       {'From': 'Mrs. Conclusion',
                        'To': 'Mrs. Premise',
                        'Date': '29 July 2001'}, "Hullo, Mrs. Premise!\n")
  
          # A folder with many messages
          for i in range(5, 101)+range(101, 201, 2):
              writeMessage('wide', i,
                           {'From': 'nowhere', 'Subject': 'message #%s' % i},
                           "This is message number %s\n" % i)
  
          # A deeply nested folder
          def deep(folder, n):
              writeMessage(folder, n,
                           {'Subject': 'Message %s/%s' % (folder, n) },
                           "This is message number %s in %s\n" % (n, folder) )
          deep('deep/f1', 1)
          deep('deep/f1', 2)
          deep('deep/f1', 3)
          deep('deep/f2', 4)
          deep('deep/f2', 6)
          deep('deep', 3)
          deep('deep/f2/f3', 1)
          deep('deep/f2/f3', 2)
  
      def tearDown(self):
          deltree(_mhroot)
  
      def test_basic(self):
          writeContext('inbox')
          writeCurMessage('inbox', 2)
          mh = getMH()
  
          eq = self.assertEqual
          eq(mh.getprofile('Editor'), 'emacs')
          eq(mh.getprofile('not-set'), None)
          eq(mh.getpath(), os.path.abspath(_mhpath))
          eq(mh.getcontext(), 'inbox')
  
          mh.setcontext('wide')
          eq(mh.getcontext(), 'wide')
          eq(readFile(os.path.join(_mhpath, 'context')),
             "Current-Folder: wide\n")
  
          mh.setcontext('inbox')
  
          inbox = mh.openfolder('inbox')
          eq(inbox.getfullname(),
             os.path.join(os.path.abspath(_mhpath), 'inbox'))
          eq(inbox.getsequencesfilename(),
             os.path.join(os.path.abspath(_mhpath), 'inbox', '.mh_sequences'))
          eq(inbox.getmessagefilename(1),
             os.path.join(os.path.abspath(_mhpath), 'inbox', '1'))
  
      def test_listfolders(self):
          mh = getMH()
          eq = self.assertEqual
  
          folders = mh.listfolders()
          folders.sort()
          eq(folders, ['deep', 'inbox', 'wide'])
  
          folders = mh.listallfolders()
          folders.sort()
          tfolders = map(normF, ['deep', 'deep/f1', 'deep/f2', 'deep/f2/f3',
                                  'inbox', 'wide'])
          tfolders.sort()
          eq(folders, tfolders)
  
          folders = mh.listsubfolders('deep')
          folders.sort()
          eq(folders, map(normF, ['deep/f1', 'deep/f2']))
  
          folders = mh.listallsubfolders('deep')
          folders.sort()
          eq(folders, map(normF, ['deep/f1', 'deep/f2', 'deep/f2/f3']))
          eq(mh.listsubfolders(normF('deep/f2')), [normF('deep/f2/f3')])
  
          eq(mh.listsubfolders('inbox'), [])
          eq(mh.listallsubfolders('inbox'), [])
  
      def test_sequence(self):
          mh = getMH()
          eq = self.assertEqual
          writeCurMessage('wide', 55)
  
          f = mh.openfolder('wide')
          all = f.listmessages()
          eq(all, range(5, 101)+range(101, 201, 2))
          eq(f.getcurrent(), 55)
          f.setcurrent(99)
          eq(readFile(os.path.join(_mhpath, 'wide', '.mh_sequences')),
             'cur: 99\n')
  
          def seqeq(seq, val):
              eq(f.parsesequence(seq), val)
  
          seqeq('5-55', range(5, 56))
          seqeq('90-108', range(90, 101)+range(101, 109, 2))
          seqeq('90-108', range(90, 101)+range(101, 109, 2))
  
          seqeq('10:10', range(10, 20))
          seqeq('10:+10', range(10, 20))
          seqeq('101:10', range(101, 121, 2))
  
          seqeq('cur', [99])
          seqeq('.', [99])
          seqeq('prev', [98])
          seqeq('next', [100])
          seqeq('cur:-3', [97, 98, 99])
          seqeq('first-cur', range(5, 100))
          seqeq('150-last', range(151, 201, 2))
          seqeq('prev-next', [98, 99, 100])
  
          lowprimes = [5, 7, 11, 13, 17, 19, 23, 29]
          lowcompos = [x for x in range(5, 31) if not x in lowprimes ]
          f.putsequences({'cur': [5],
                          'lowprime': lowprimes,
                          'lowcompos': lowcompos})
          seqs = readFile(os.path.join(_mhpath, 'wide', '.mh_sequences'))
          seqs = sortLines(seqs)
          eq(seqs, ["cur: 5",
                    "lowcompos: 6 8-10 12 14-16 18 20-22 24-28 30",
                    "lowprime: 5 7 11 13 17 19 23 29"])
  
          seqeq('lowprime', lowprimes)
          seqeq('lowprime:1', [5])
          seqeq('lowprime:2', [5, 7])
          seqeq('lowprime:-2', [23, 29])
  
          ## Not supported
          #seqeq('lowprime:first', [5])
          #seqeq('lowprime:last', [29])
          #seqeq('lowprime:prev', [29])
          #seqeq('lowprime:next', [29])
  
      def test_modify(self):
          mh = getMH()
          eq = self.assertEqual
  
          mh.makefolder("dummy1")
          self.assertIn("dummy1", mh.listfolders())
          path = os.path.join(_mhpath, "dummy1")
          self.assertTrue(os.path.exists(path))
  
          f = mh.openfolder('dummy1')
          def create(n):
              msg = "From: foo\nSubject: %s\n\nDummy Message %s\n" % (n,n)
              f.createmessage(n, StringIO.StringIO(msg))
  
          create(7)
          create(8)
          create(9)
  
          eq(readFile(f.getmessagefilename(9)),
             "From: foo\nSubject: 9\n\nDummy Message 9\n")
  
          eq(f.listmessages(), [7, 8, 9])
          files = os.listdir(path)
          files.sort()
          eq(files, ['7', '8', '9'])
  
          f.removemessages(['7', '8'])
          files = os.listdir(path)
          files.sort()
          eq(files, [',7', ',8', '9'])
          eq(f.listmessages(), [9])
          create(10)
          create(11)
          create(12)
  
          mh.makefolder("dummy2")
          f2 = mh.openfolder("dummy2")
          eq(f2.listmessages(), [])
          f.movemessage(10, f2, 3)
          f.movemessage(11, f2, 5)
          eq(f.listmessages(), [9, 12])
          eq(f2.listmessages(), [3, 5])
          eq(readFile(f2.getmessagefilename(3)),
             "From: foo\nSubject: 10\n\nDummy Message 10\n")
  
          f.copymessage(9, f2, 4)
          eq(f.listmessages(), [9, 12])
          eq(readFile(f2.getmessagefilename(4)),
             "From: foo\nSubject: 9\n\nDummy Message 9\n")
  
          f.refilemessages([9, 12], f2)
          eq(f.listmessages(), [])
          eq(f2.listmessages(), [3, 4, 5, 6, 7])
          eq(readFile(f2.getmessagefilename(7)),
             "From: foo\nSubject: 12\n\nDummy Message 12\n")
          # XXX This should check that _copysequences does the right thing.
  
          mh.deletefolder('dummy1')
          mh.deletefolder('dummy2')
          self.assertNotIn('dummy1', mh.listfolders())
          self.assertTrue(not os.path.exists(path))
  
      def test_read(self):
          mh = getMH()
          eq = self.assertEqual
  
          f = mh.openfolder('inbox')
          msg = f.openmessage(1)
          # Check some basic stuff from rfc822
          eq(msg.getheader('From'), "Mrs. Premise")
          eq(msg.getheader('To'), "Mrs. Conclusion")
  
          # Okay, we have the right message.  Let's check the stuff from
          # mhlib.
          lines = sortLines(msg.getheadertext())
          eq(lines, ["Date: 18 July 2001",
                     "From: Mrs. Premise",
                     "To: Mrs. Conclusion"])
          lines = sortLines(msg.getheadertext(lambda h: len(h)==4))
          eq(lines, ["Date: 18 July 2001",
                     "From: Mrs. Premise"])
          eq(msg.getbodytext(), "Hullo, Mrs. Conclusion!\n\n")
          eq(msg.getbodytext(0), "Hullo, Mrs. Conclusion!\n\n")
  
          # XXXX there should be a better way to reclaim the file handle
          msg.fp.close()
          del msg
  
  
  def test_main():
      run_unittest(MhlibTests)
  
  
  if __name__ == "__main__":
      test_main()
  