Merge from Ben Finney's RCS unittest patch
authorW. Trevor King <wking@drexel.edu>
Sun, 21 Jun 2009 11:28:48 +0000 (07:28 -0400)
committerW. Trevor King <wking@drexel.edu>
Sun, 21 Jun 2009 11:28:48 +0000 (07:28 -0400)
This involved an `upgrade' of BE's bzr repo
Previous version (via `bzr info path/to/repo`): pack-0.92
Current version: rich-root-pack

The whole rich-root thing is a bzr features-vs-backwards-compatability
thing they've been wrestling with [1,2,3,4,...].  It seems that BE was
in some sort of unstable equilibrium [5], so I'll follow Ben's lead
and make the official switch.  Note that you'll need to use bzr>=1.5
to make the shift [6].  For the sake of completeness, the whole
rich-root thing was introduced here [7], but I don't understand enough
of bzr to make sense of the diff.  It just versions the repo's root
directory the same way it versions other directories [3].  The bzr
people seem to be planning to phase out non-rich-root formats in favor
of brisbane-core, aka 2.0beta [8], by bzr 2.0 [8], which is apparently
on the horizon [9,10,11].  What a headache.

Citations are all titles/X-List-Received-Date from
  https://lists.ubuntu.com/archives/bazaar/
with the exception of the URL [11].

[1] [RFC] rich root pack as default in 1.8 ?
  Sat, 06 Sep 2008 03:33:46 -0000
  (conclusion: none)
[2] Re: 1.9rc1 countdown
  Thu, 30 Oct 2008 08:44:53 -0000
  (conclusion: "primary" format should be rich-root next time we make a new format)
[3] So many repo formats
  Fri, 14 Nov 2008 08:41:33 -0000
  Mon, 17 Nov 2008 07:37:47 -0000  (explains rich-root format)
  Mon, 17 Nov 2008 22:37:39 -0000  (explains no-return policy)
  Mon, 17 Nov 2008 20:57:08 -0000  (explicitly lists non-svn reasons for rich-root)
[4] Branch fails from 'pack-0.92' repo to 'rich-root-pack' repo.
  Wed, 27 Aug 2008 11:31:11 -0000
  (we're not sure again)
[5] Branch fails from 'pack-0.92' repo to 'rich-root-pack' repo.
  Sun, 20 Apr 2008 12:58:09 -0000
[6] Branch fails from 'pack-0.92' repo to 'rich-root-pack' repo.
  Fri, 29 Aug 2008 13:23:52 -0000
[7] [RFC] Knit format 2
  Fri, 25 Aug 2006 22:55:36 -0000
[8] bazaar 2.0beta format for launchpad release
  Fri, 29 May 2009 06:00:03 -0000
[9] Upgrading loggerhead to 1.9-rich-root
  Mon, 11 May 2009 22:35:28 -0000
  (mentions eventual switch to rich-root in 2.0)
[10] bzr 1.16rc1 released!
  Fri, 12 Jun 2009 08:00:08 -0000
  (confirms eventual switch to rich-root in 2.0)
[11] https://launchpad.net/bzr/+announcement/2733
  (current outstanding releases: 1.17, 2.0)

1  2 
libbe/arch.py
libbe/bzr.py
libbe/git.py
libbe/hg.py
libbe/rcs.py

diff --cc libbe/arch.py
index a2d6bde47bb0036aa16836ee955d7e4d9ada6b17,73bef35096fcd22ef35389c271092cb3e79ee64e..cd0f3b24832dba689452ba895158a02eb201d71e
  #    You should have received a copy of the GNU General Public License
  #    along with this program; if not, write to the Free Software
  #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 -import sys
 +import codecs
  import os
 +import re
  import shutil
++import sys
  import time
 -import re
  import unittest
  import doctest
  
  import config
  from beuuid import uuid_gen
- from rcs import RCS, RCStestCase, CommandError
+ import rcs
+ from rcs import RCS
  
 -client = config.get_val("arch_client")
 -if client is None:
 -    client = "tla"
 -    config.set_val("arch_client", client)
 +DEFAULT_CLIENT = "tla"
 +
 +client = config.get_val("arch_client", default=DEFAULT_CLIENT)
  
  def new():
      return Arch()
diff --cc libbe/bzr.py
index 38af6bb397887b2af38dd68e41cb64ac2d9cf964,4a01d8ab822eb9872599374145d315759db37f59..98ca571e61575c1a98464c4a979e2ef8a385a8ff
  #    You should have received a copy of the GNU General Public License
  #    along with this program; if not, write to the Free Software
  #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 -import sys
  import os
  import re
++import sys
  import unittest
  import doctest
  
diff --cc libbe/git.py
index e57014f213343d0fbaa848c670f9453a9f5033e7,4a1ddee5b3f419123dc5872370b7ae602f98bc8b..401b5e5bddcbf131000ab7fb547758a53740e80f
  #    You should have received a copy of the GNU General Public License
  #    along with this program; if not, write to the Free Software
  #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 -import sys
  import os
  import re
++import sys
  import unittest
  import doctest
  
diff --cc libbe/hg.py
index c00d7e2c16d8f4c1d87715c9ff4b5d518e3e7e9a,52f8a96802c52bafe99bdf984798cbb8ab935745..a7413af22f5909add063d706acd0e1002cba3b0a
  #    You should have received a copy of the GNU General Public License
  #    along with this program; if not, write to the Free Software
  #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 -import sys
  import os
  import re
++import sys
  import unittest
  import doctest
  
diff --cc libbe/rcs.py
index 786f9dd591928c7ce045a146e9490abb076876ef,a5a1769eabaa40d41b1e8bb915ccfce4e12eabd9..c0b92e7d033c9b4ea81c7480e7f76fb49bc90d31
  #    You should have received a copy of the GNU General Public License
  #    along with this program; if not, write to the Free Software
  #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++
  from subprocess import Popen, PIPE
 +import codecs
  import os
  import os.path
 -from socket import gethostname
  import re
 +from socket import gethostname
 +import shutil
  import sys
  import tempfile
 -import shutil
  import unittest
  import doctest
  
@@@ -550,97 -543,274 +551,274 @@@ class RCS(object)
          body.lstrip('\n')
          if len(body) == 0:
              body = None
 -        f.close
 +        f.close()
          return (summary, body)
          
\f
+ def setup_rcs_test_fixtures(testcase):
+     """Set up test fixtures for RCS test case."""
+     testcase.rcs = testcase.Class()
+     testcase.dir = Dir()
+     testcase.dirname = testcase.dir.path
+     testcase.rcs_supports_uninitialized_user_id = (
+         testcase.rcs.name not in ["git"])
+     testcase.rcs_supports_set_user_id = (
+         testcase.rcs.name not in ["None", "hg"])
+     if not testcase.rcs.installed():
+         testcase.fail(
+             "%(name)s RCS not found" % vars(testcase.Class))
+     if testcase.Class.name != "None":
+         testcase.failIf(
+             testcase.rcs.detect(testcase.dirname),
+             "Detected %(name)s RCS before initialising"
+                 % vars(testcase.Class))
+     testcase.rcs.init(testcase.dirname)
+ class RCSTestCase(unittest.TestCase):
+     """Test cases for base RCS class."""
  
- class RCStestCase(unittest.TestCase):
      Class = RCS
      def __init__(self, *args, **kwargs):
-         unittest.TestCase.__init__(self, *args, **kwargs)
+         super(RCSTestCase, self).__init__(*args, **kwargs)
          self.dirname = None
-     def instantiateRCS(self):
-         return self.Class()
      def setUp(self):
-         self.dir = Dir()
-         self.dirname = self.dir.path
-         self.rcs = self.instantiateRCS()
+         super(RCSTestCase, self).setUp()
+         setup_rcs_test_fixtures(self)
      def tearDown(self):
          del(self.rcs)
-         del(self.dirname)
-     def fullPath(self, path):
-         return os.path.join(self.dirname, path)
-     def assertPathExists(self, path):
-         fullpath = self.fullPath(path)
-         self.failUnless(os.path.exists(fullpath)==True,
-                         "path %s does not exist" % fullpath)
-     def uidTest(self):
+         super(RCSTestCase, self).tearDown()
+     def full_path(self, rel_path):
+         return os.path.join(self.dirname, rel_path)
+ class RCS_init_TestCase(RCSTestCase):
+     """Test cases for RCS.init method."""
+     def test_detect_should_succeed_after_init(self):
+         """Should detect RCS in directory after initialization."""
+         self.failUnless(
+             self.rcs.detect(self.dirname),
+             "Did not detect %(name)s RCS after initialising"
+                 % vars(self.Class))
+     def test_rcs_rootdir_in_specified_root_path(self):
+         """RCS root directory should be in specified root path."""
+         rp = os.path.realpath(self.rcs.rootdir)
+         dp = os.path.realpath(self.dirname)
+         rcs_name = self.Class.name
+         self.failUnless(
+             dp == rp or rp == None,
+             "%(rcs_name)s RCS root in wrong dir (%(dp)s %(rp)s)" % vars())
+ class RCS_get_user_id_TestCase(RCSTestCase):
+     """Test cases for RCS.get_user_id method."""
+     def test_gets_existing_user_id(self):
+         """Should get the existing user ID."""
+         if not self.rcs_supports_uninitialized_user_id:
+             return
          user_id = self.rcs.get_user_id()
-         self.failUnless(user_id != None,
-                         "unable to get a user id")
-         user_idB = "John Doe <jdoe@example.com>"
-         if self.rcs.name in ["None", "hg"]:
-             self.assertRaises(SettingIDnotSupported, self.rcs.set_user_id,
-                               user_idB)
+         self.failUnless(
+             user_id is not None,
+             "unable to get a user id")
+ class RCS_set_user_id_TestCase(RCSTestCase):
+     """Test cases for RCS.set_user_id method."""
+     def setUp(self):
+         super(RCS_set_user_id_TestCase, self).setUp()
+         if self.rcs_supports_uninitialized_user_id:
+             self.prev_user_id = self.rcs.get_user_id()
          else:
-             self.rcs.set_user_id(user_idB)
-             self.failUnless(self.rcs.get_user_id() == user_idB,
-                             "user id not set correctly (was %s, is %s)" \
-                                 % (user_id, self.rcs.get_user_id()))
-             self.failUnless(self.rcs.set_user_id(user_id) == None,
-                             "unable to restore user id %s" % user_id)
-             self.failUnless(self.rcs.get_user_id() == user_id,
-                             "unable to restore user id %s" % user_id)
-     def versionTest(self, path):
-         origpath = path
-         path = self.fullPath(path)
-         contentsA = "Lorem ipsum"
-         contentsB = "dolor sit amet"
-         self.rcs.set_file_contents(path,contentsA)
-         self.failUnless(self.rcs.get_file_contents(path)==contentsA,
-                         "File contents not set or read correctly")
-         revision = self.rcs.commit("Commit current status")
-         self.failUnless(self.rcs.get_file_contents(path)==contentsA,
-                         "Committing File contents not set or read correctly")
-         if self.rcs.versioned == True:
-             self.rcs.set_file_contents(path,contentsB)
-             self.failUnless(self.rcs.get_file_contents(path)==contentsB,
-                             "File contents not set correctly after commit")
-             contentsArev = self.rcs.get_file_contents(path, revision)
-             self.failUnless(contentsArev==contentsA, \
-                 "Original file contents not saved in revision %s\n%s\n%s\n" \
-                                 % (revision, contentsA, contentsArev))
-             dup = self.rcs.duplicate_repo(revision)
-             duppath = os.path.join(dup, origpath)
-             dupcont = file(duppath, "rb").read()
-             self.failUnless(dupcont == contentsA)
+             self.prev_user_id = "Uninitialized identity <bogus@example.org>"
+         if self.rcs_supports_set_user_id:
+             self.test_new_user_id = "John Doe <jdoe@example.com>"
+             self.rcs.set_user_id(self.test_new_user_id)
+     def tearDown(self):
+         if self.rcs_supports_set_user_id:
+             self.rcs.set_user_id(self.prev_user_id)
+         super(RCS_set_user_id_TestCase, self).tearDown()
+     def test_raises_error_in_unsupported_vcs(self):
+         """Should raise an error in a VCS that doesn't support it."""
+         if self.rcs_supports_set_user_id:
+             return
+         self.assertRaises(
+             SettingIDnotSupported,
+             self.rcs.set_user_id, "foo")
+     def test_updates_user_id_in_supporting_rcs(self):
+         """Should update the user ID in an RCS that supports it."""
+         if not self.rcs_supports_set_user_id:
+             return
+         user_id = self.rcs.get_user_id()
+         self.failUnlessEqual(
+             self.test_new_user_id, user_id,
+             "user id not set correctly (expected %s, got %s)"
+                 % (self.test_new_user_id, user_id))
+ def setup_rcs_revision_test_fixtures(testcase):
+     """Set up revision test fixtures for RCS test case."""
+     testcase.test_dirs = ['a', 'a/b', 'c']
+     for path in testcase.test_dirs:
+         testcase.rcs.mkdir(testcase.full_path(path))
+     testcase.test_files = ['a/text', 'a/b/text']
+     testcase.test_contents = {
+         'rev_1': "Lorem ipsum",
+         'uncommitted': "dolor sit amet",
+         }
+ class RCS_mkdir_TestCase(RCSTestCase):
+     """Test cases for RCS.mkdir method."""
+     def setUp(self):
+         super(RCS_mkdir_TestCase, self).setUp()
+         setup_rcs_revision_test_fixtures(self)
+     def tearDown(self):
+         for path in reversed(sorted(self.test_dirs)):
+             self.rcs.recursive_remove(self.full_path(path))
+         super(RCS_mkdir_TestCase, self).tearDown()
+     def test_mkdir_creates_directory(self):
+         """Should create specified directory in filesystem."""
+         for path in self.test_dirs:
+             full_path = self.full_path(path)
+             self.failUnless(
+                 os.path.exists(full_path),
+                 "path %(full_path)s does not exist" % vars())
+ class RCS_commit_TestCase(RCSTestCase):
+     """Test cases for RCS.commit method."""
+     def setUp(self):
+         super(RCS_commit_TestCase, self).setUp()
+         setup_rcs_revision_test_fixtures(self)
+     def tearDown(self):
+         for path in reversed(sorted(self.test_dirs)):
+             self.rcs.recursive_remove(self.full_path(path))
+         super(RCS_commit_TestCase, self).tearDown()
+     def test_file_contents_as_specified(self):
+         """Should set file contents as specified."""
+         test_contents = self.test_contents['rev_1']
+         for path in self.test_files:
+             full_path = self.full_path(path)
+             self.rcs.set_file_contents(full_path, test_contents)
+             current_contents = self.rcs.get_file_contents(full_path)
+             self.failUnlessEqual(test_contents, current_contents)
+     def test_file_contents_as_committed(self):
+         """Should have file contents as specified after commit."""
+         test_contents = self.test_contents['rev_1']
+         for path in self.test_files:
+             full_path = self.full_path(path)
+             self.rcs.set_file_contents(full_path, test_contents)
+             revision = self.rcs.commit("Initial file contents.")
+             current_contents = self.rcs.get_file_contents(full_path)
+             self.failUnlessEqual(test_contents, current_contents)
+     def test_file_contents_as_set_when_uncommitted(self):
+         """Should set file contents as specified after commit."""
+         if not self.rcs.versioned:
+             return
+         for path in self.test_files:
+             full_path = self.full_path(path)
+             self.rcs.set_file_contents(
+                 full_path, self.test_contents['rev_1'])
+             revision = self.rcs.commit("Initial file contents.")
+             self.rcs.set_file_contents(
+                 full_path, self.test_contents['uncommitted'])
+             current_contents = self.rcs.get_file_contents(full_path)
+             self.failUnlessEqual(
+                 self.test_contents['uncommitted'], current_contents)
+     def test_revision_file_contents_as_committed(self):
+         """Should get file contents as committed to specified revision."""
+         if not self.rcs.versioned:
+             return
+         for path in self.test_files:
+             full_path = self.full_path(path)
+             self.rcs.set_file_contents(
+                 full_path, self.test_contents['rev_1'])
+             revision = self.rcs.commit("Initial file contents.")
+             self.rcs.set_file_contents(
+                 full_path, self.test_contents['uncommitted'])
+             committed_contents = self.rcs.get_file_contents(
+                 full_path, revision)
+             self.failUnlessEqual(
+                 self.test_contents['rev_1'], committed_contents)
+ class RCS_duplicate_repo_TestCase(RCSTestCase):
+     """Test cases for RCS.duplicate_repo method."""
+     def setUp(self):
+         super(RCS_duplicate_repo_TestCase, self).setUp()
+         setup_rcs_revision_test_fixtures(self)
+     def tearDown(self):
+         self.rcs.remove_duplicate_repo()
+         for path in reversed(sorted(self.test_dirs)):
+             self.rcs.recursive_remove(self.full_path(path))
+         super(RCS_duplicate_repo_TestCase, self).tearDown()
+     def test_revision_file_contents_as_committed(self):
+         """Should match file contents as committed to specified revision."""
+         if not self.rcs.versioned:
+             return
+         for path in self.test_files:
+             full_path = self.full_path(path)
+             self.rcs.set_file_contents(
+                 full_path, self.test_contents['rev_1'])
+             revision = self.rcs.commit("Commit current status")
+             self.rcs.set_file_contents(
+                 full_path, self.test_contents['uncommitted'])
+             dup_repo_path = self.rcs.duplicate_repo(revision)
+             dup_file_path = os.path.join(dup_repo_path, path)
+             dup_file_contents = file(dup_file_path, 'rb').read()
+             self.failUnlessEqual(
+                 self.test_contents['rev_1'], dup_file_contents)
              self.rcs.remove_duplicate_repo()
-     def testRun(self):
-         self.failUnless(self.rcs.installed() == True,
-                         "%s RCS not found" % self.Class.name)
-         if self.Class.name != "None":
-             self.failUnless(self.rcs.detect(self.dirname)==False,
-                             "Detected %s RCS before initializing" \
-                                 % self.Class.name)
-         self.rcs.init(self.dirname)
-         self.failUnless(self.rcs.detect(self.dirname)==True,
-                         "Did not detect %s RCS after initializing" \
-                             % self.Class.name)
-         rp = os.path.realpath(self.rcs.rootdir)
-         dp = os.path.realpath(self.dirname)
-         self.failUnless(dp == rp or rp == None,
-                         "%s RCS root in wrong dir (%s %s)" \
-                             % (self.Class.name, dp, rp))
-         self.uidTest()
-         self.rcs.mkdir(self.fullPath('a'))
-         self.rcs.mkdir(self.fullPath('a/b'))
-         self.rcs.mkdir(self.fullPath('c'))
-         self.assertPathExists('a')
-         self.assertPathExists('a/b')
-         self.assertPathExists('c')
-         self.versionTest('a/text')
-         self.versionTest('a/b/text')
-         self.rcs.recursive_remove(self.fullPath('a'))
- unitsuite = unittest.TestLoader().loadTestsFromTestCase(RCStestCase)
+ def make_rcs_testcase_subclasses(rcs_class, namespace):
+     """Make RCSTestCase subclasses for rcs_class in the namespace."""
+     rcs_testcase_classes = [
+         c for c in (
+             ob for ob in globals().values() if isinstance(ob, type))
+         if issubclass(c, RCSTestCase)]
+     for base_class in rcs_testcase_classes:
+         testcase_class_name = rcs_class.__name__ + base_class.__name__
+         testcase_class_bases = (base_class,)
+         testcase_class_dict = dict(base_class.__dict__)
+         testcase_class_dict['Class'] = rcs_class
+         testcase_class = type(
+             testcase_class_name, testcase_class_bases, testcase_class_dict)
+         setattr(namespace, testcase_class_name, testcase_class)
+ unitsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
  suite = unittest.TestSuite([unitsuite, doctest.DocTestSuite()])