#749 closed defect (fixed)

Tahoe-LAFS fails unit tests when the "-OO" flag is passed to Python to optimize and strip docstrings

Reported by: zooko Owned by: somebody
Priority: major Milestone: 1.5.0
Component: code Version: 1.4.1
Keywords: Cc:
Launchpad Bug:

Description

These six unit tests fail if optimization is turned on:

$ PYTHONOPTIMIZE=2 PYTHONPATH=./support/lib/python2.6/site-packages/ trial allmydata.test.test_mutable.Roundtrip.test_corrupt_all_verbyte allmydata.test.test_uri.Constraint.test_constraint allmydata.test.test_web.Web.test_GET_unhandled_URI allmydata.test.test_web.Web.test_GET_unhandled_URI_named allmydata.test.test_web.Web.test_GET_unhandled_URI allmydata.test.test_web.Web.test_GET_unhandled_URI_named
allmydata.test.test_mutable.Roundtrip.test_corrupt_all_verbyte allmydata.test.test_uri.Constraint.test_constraint allmydata.test.test_web.Web.test_GET_unhandled_URI allmydata.test.test_web.Web.test_GET_unhandled_URI_named allmydata.test.test_web.Web.test_GET_unhandled_URI allmydata.test.test_web.Web.test_GET_unhandled_URI_named

...

allmydata.test.test_uri
  Constraint
    test_constraint ...                                                  [FAIL]
allmydata.test.test_mutable
  Roundtrip
    test_corrupt_all_verbyte ...                                         [FAIL]
allmydata.test.test_web
  Web
    test_GET_unhandled_URI ...                                           [FAIL]
                                         [ERROR]
    test_GET_unhandled_URI_named ...                                     [FAIL]
                                   [ERROR]

===============================================================================
[FAIL]: allmydata.test.test_uri.Constraint.test_constraint

Traceback (most recent call last):
  File "/home/zooko/playground/allmydata/tahoe/trunk/optimize_directories/src/allmydata/test/test_uri.py", line 189, in test_constraint
    self.failUnlessRaises(AssertionError, uri.NewDirectoryURI.init_from_string, good)
twisted.trial.unittest.FailTest: <type 'exceptions.AttributeError'> raised instead of AssertionError:
 Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/trial/unittest.py", line 752, in _run
    self.getSuppress(), method)
  File "/usr/local/lib/python2.6/dist-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/internet/defer.py", line 106, in maybeDeferred
    result = f(*args, **kw)
  File "/usr/local/lib/python2.6/dist-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/internet/utils.py", line 191, in runWithWarningsSuppressed
    result = f(*a, **kw)
  File "/home/zooko/playground/allmydata/tahoe/trunk/optimize_directories/src/allmydata/test/test_uri.py", line 189, in test_constraint
    self.failUnlessRaises(AssertionError, uri.NewDirectoryURI.init_from_string, good)
--- <exception caught here> ---
  File "/usr/local/lib/python2.6/dist-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/trial/unittest.py", line 235, in failUnlessRaises
    result = f(*args, **kwargs)
  File "/home/zooko/playground/allmydata/tahoe/trunk/optimize_directories/src/allmydata/uri.py", line 337, in init_from_string
    bits = uri[mo.end():]
exceptions.AttributeError: 'NoneType' object has no attribute 'end'

===============================================================================
[FAIL]: allmydata.test.test_mutable.Roundtrip.test_corrupt_all_verbyte

Traceback (most recent call last):
  File "/home/zooko/playground/allmydata/tahoe/trunk/optimize_directories/src/allmydata/test/test_mutable.py", line 1033, in _do_retrieve
    self.failUnless(substring in "".join(allproblems))
twisted.trial.unittest.FailTest: None
===============================================================================
[FAIL]: allmydata.test.test_web.Web.test_GET_unhandled_URI

Traceback (most recent call last):
  File "/home/zooko/playground/allmydata/tahoe/trunk/optimize_directories/src/allmydata/test/test_web.py", line 341, in done
    % (which, substring, str(res)))
twisted.trial.unittest.FailTest: test_GET_unhandled_URI: substring '400 Bad Request' not in '[Failure instance: Traceback (failure with no frames): <class 'twisted.web.error.Error'>: 500 Internal Server Error
]'
===============================================================================
[FAIL]: allmydata.test.test_web.Web.test_GET_unhandled_URI_named

Traceback (most recent call last):
  File "/home/zooko/playground/allmydata/tahoe/trunk/optimize_directories/src/allmydata/test/test_web.py", line 341, in done
    % (which, substring, str(res)))
twisted.trial.unittest.FailTest: GET_unhandled_URI_named: substring '400 Bad Request' not in '[Failure instance: Traceback (failure with no frames): <class 'twisted.web.error.Error'>: 500 Internal Server Error
]'
===============================================================================
[ERROR]: allmydata.test.test_web.Web.test_GET_unhandled_URI

Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/internet/defer.py", line 106, in maybeDeferred
    result = f(*args, **kw)
  File "/home/zooko/playground/allmydata/tahoe/trunk/optimize_directories/src/allmydata/web/common.py", line 220, in renderHTTP
    return m(ctx)
  File "/home/zooko/playground/allmydata/tahoe/trunk/optimize_directories/src/allmydata/web/filenode.py", line 181, in render_GET
    if self.node.is_mutable():
  File "/home/zooko/playground/allmydata/tahoe/trunk/optimize_directories/src/allmydata/test/common.py", line 183, in is_mutable
    return self.my_uri.is_mutable()
exceptions.AttributeError: CHKFileVerifierURI instance has no attribute 'is_mutable'
===============================================================================
[ERROR]: allmydata.test.test_web.Web.test_GET_unhandled_URI_named

Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/internet/defer.py", line 106, in maybeDeferred
    result = f(*args, **kw)
  File "/home/zooko/playground/allmydata/tahoe/trunk/optimize_directories/src/allmydata/web/common.py", line 220, in renderHTTP
    return m(ctx)
  File "/home/zooko/playground/allmydata/tahoe/trunk/optimize_directories/src/allmydata/web/filenode.py", line 181, in render_GET
    if self.node.is_mutable():
  File "/home/zooko/playground/allmydata/tahoe/trunk/optimize_directories/src/allmydata/test/common.py", line 183, in is_mutable
    return self.my_uri.is_mutable()
exceptions.AttributeError: CHKFileVerifierURI instance has no attribute 'is_mutable'
-------------------------------------------------------------------------------
Ran 4 tests in 0.586s

FAILED (failures=4, errors=2)

Change History (3)

comment:1 Changed at 2009-07-15T04:09:26Z by zooko

  • Milestone changed from 1.5.0 to eventually

Not urgent for TahoeLAFS v1.5, so I'm bumping it. Note that aside from the general "curiousness" that our code (or more likely our unit tests) rely on assertion-checking to be correct, turning on Python's -OO optimization mode might reduce CPU load a bit. I thought I observed that when benchmarking for #329/#752, but I'm not sure if it was real or an artifact of noisy benchmarking.

comment:2 Changed at 2009-07-15T06:50:18Z by warner

  • Milestone changed from eventually to 1.5.0
  • Resolution set to fixed
  • Status changed from new to closed

I had some time, so I fixed it, in d8ba8c2eb5d4b1b5. All were cases where we intentionally do something wrong so as to trigger an (assertion) exception and then check the resulting behavior. All were fixed by replacing the AssertionError with something more specific.

The best rule to follow is probably this:

  • if an exception is worth testing, it's part of the API
  • AssertionError should never be part of the API

OTOH, it's a bother to create a whole new exception type and add an "if" clause (and then fret about whether the code-coverage stats are going to go down) just to do something that should be highly encouraged like adding preconditions and internal consistency checks. Maybe it means we're being overzealous in our unit tests and exercising things that we shouldn't or don't need to exercise.

comment:3 Changed at 2009-07-15T16:49:31Z by swillden

I'm no expert on unit testing, but I think it makes sense that assertions (preconditions, postconditions, etc.) are things that don't need to be tested. I see them not as code which must be validated for correctness, but instead as code that does correctness validation, like the unit tests.

Said another way, assertions and other design-by-contract artifacts are actually tests. They're just tests that are normally run all the time rather than only when we choose to explicitly invoke a test run.

If you need to write test code to test your assertions, don't you also need to write test code to test your unit tests? And test code to test the test code that tests your tests, and... (try saying that five times fast) :-)

Note: See TracTickets for help on using tickets.