new_contents: #!/usr/bin/env python
  
  """
  Tests for `util` module.
  
  Credit of test for the @retry decorator:
  http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/
  """
  
  import logging
  import os
  import unittest
  
  from plumbery.util import retry
  
  
  class RetryableError(Exception):
      pass
  
  
  class AnotherRetryableError(Exception):
      pass
  
  
  class UnexpectedError(Exception):
      pass
  
  
  class TestPlumberyUtil(unittest.TestCase):
  
      def test_no_retry_required(self):
          self.counter = 0
  
          @retry(RetryableError, tries=4, delay=0.1)
          def succeeds():
              self.counter += 1
              return 'success'
  
          r = succeeds()
  
          self.assertEqual(r, 'success')
          self.assertEqual(self.counter, 1)
  
      def test_retries_once(self):
          self.counter = 0
  
          @retry(RetryableError, tries=4, delay=0.1)
          def fails_once():
              self.counter += 1
              if self.counter < 2:
                  raise RetryableError('failed')
              else:
                  return 'success'
  
          r = fails_once()
          self.assertEqual(r, 'success')
          self.assertEqual(self.counter, 2)
  
      def test_limit_is_reached(self):
          self.counter = 0
  
          @retry(RetryableError, tries=4, delay=0.1)
          def always_fails():
              self.counter += 1
              raise RetryableError('failed')
  
          with self.assertRaises(RetryableError):
              always_fails()
          self.assertEqual(self.counter, 4)
  
      def test_multiple_exception_types(self):
          self.counter = 0
  
          @retry((RetryableError, AnotherRetryableError), tries=4, delay=0.1)
          def raise_multiple_exceptions():
              self.counter += 1
              if self.counter == 1:
                  raise RetryableError('a retryable error')
              elif self.counter == 2:
                  raise AnotherRetryableError('another retryable error')
              else:
                  return 'success'
  
          r = raise_multiple_exceptions()
          self.assertEqual(r, 'success')
          self.assertEqual(self.counter, 3)
  
      def test_unexpected_exception_does_not_retry(self):
  
          @retry(RetryableError, tries=4, delay=0.1)
          def raise_unexpected_error():
              raise UnexpectedError('unexpected error')
  
          with self.assertRaises(UnexpectedError):
              raise_unexpected_error()
  
      def test_using_a_logger(self):
          self.counter = 0
  
          sh = logging.StreamHandler()
          logger = logging.getLogger(__name__)
          logger.addHandler(sh)
  
          @retry(RetryableError, tries=4, delay=0.1, logger=logger)
          def fails_once():
              self.counter += 1
              if self.counter < 2:
                  raise RetryableError('failed')
              else:
                  return 'success'
  
          fails_once()
  
  if __name__ == '__main__':
      import sys
      sys.exit(unittest.main())
  
subject: add tests to util.py