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

Closed
opened 2009-07-07 02:39:48 +00:00 by zooko · 3 comments

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)
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) ```
zooko added the
code
major
defect
1.4.1
labels 2009-07-07 02:39:48 +00:00
zooko added this to the 1.5.0 milestone 2009-07-07 02:39:48 +00:00
Author

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.

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.
zooko modified the milestone from 1.5.0 to eventually 2009-07-15 04:09:26 +00:00

I had some time, so I fixed it, in changeset: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.

I had some time, so I fixed it, in changeset: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.
warner added the
fixed
label 2009-07-15 06:50:18 +00:00
warner modified the milestone from eventually to 1.5.0 2009-07-15 06:50:18 +00:00
swillden commented 2009-07-15 16:49:31 +00:00
Owner

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) :-)

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) :-)
Sign in to join this conversation.
No Milestone
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Reference: tahoe-lafs/trac-2024-07-25#749
No description provided.