Improve constructor/destructor tracking

This commit rewrites the examples that look for constructor/destructor
calls to do so via static variable tracking rather than output parsing.

The added ConstructorStats class provides methods to keep track of
constructors and destructors, number of default/copy/move constructors,
and number of copy/move assignments.  It also provides a mechanism for
storing values (e.g. for value construction), and then allows all of
this to be checked at the end of a test by getting the statistics for a
C++ (or python mapping) class.

By not relying on the precise pattern of constructions/destructions,
but rather simply ensuring that every construction is matched with a
destruction on the same object, we ensure that everything that gets
created also gets destroyed as expected.

This replaces all of the various "std::cout << whatever" code in
constructors/destructors with
`print_created(this)`/`print_destroyed(this)`/etc. functions which
provide similar output, but now has a unified format across the
different examples, including a new ### prefix that makes mixed example
output and lifecycle events easier to distinguish.

With this change, relaxed mode is no longer needed, which enables
testing for proper destruction under MSVC, and under any other compiler
that generates code calling extra constructors, or optimizes away any
constructors.  GCC/clang are used as the baseline for move
constructors; the tests are adapted to allow more move constructors to
be evoked (but other types are constructors much have matching counts).

This commit also disables output buffering of tests, as the buffering
sometimes results in C++ output ending up in the middle of python
output (or vice versa), depending on the OS/python version.
This commit is contained in:
Jason Rhinelander
2016-08-11 18:16:04 -04:00
parent 85557b1dec
commit 3f589379ec
36 changed files with 969 additions and 495 deletions
+22 -13
View File
@@ -1,8 +1,8 @@
Constructing ExampleVirt..
### ExampleVirt @ 0x2073a90 created 10
Original implementation of ExampleVirt::run(state=10, value=20)
30
Caught expected exception: Tried to call pure virtual function "ExampleVirt::pure_virtual"
Constructing ExampleVirt..
### ExampleVirt @ 0x2076a00 created 11
ExtendedExampleVirt::run(20), calling parent..
Original implementation of ExampleVirt::run(state=11, value=21)
32
@@ -78,20 +78,29 @@ VI_DT says: quack quack quack
Unlucky = 1234
Lucky = -4.25
2^2 * 3^2 =
NonCopyable destructor @ 0x1a6c3f0; value = (null)
### NonCopyable @ 0x207df10 created 4 9
### NonCopyable @ 0x7ffcfe866228 created via move constructor
### NonCopyable @ 0x207df10 destroyed
36
NonCopyable destructor @ 0x7ffc6d1fbaa8; value = 36
### NonCopyable @ 0x7ffcfe866228 destroyed
4 + 5 =
Movable @ 0x7ffc6d1fbacc copy constructor
### Movable @ 0x207e230 created 4 5
### Movable @ 0x7ffcfe86624c created via copy constructor
9
Movable destructor @ 0x7ffc6d1fbacc; value = 9
### Movable @ 0x7ffcfe86624c destroyed
7 + 7 =
Movable @ 0x7ffc6d1fbacc move constructor
Movable destructor @ 0x1a6c4d0; value = 14
### Movable @ 0x20259e0 created 7 7
### Movable @ 0x7ffcfe86624c created via move constructor
### Movable @ 0x20259e0 destroyed
14
Movable destructor @ 0x7ffc6d1fbacc; value = 14
### Movable @ 0x7ffcfe86624c destroyed
### NonCopyable @ 0x2025a00 created 9 9
Caught expected exception
NonCopyable destructor @ 0x29a64b0; value = 81
Movable destructor @ 0x1a6c410; value = 9
Destructing ExampleVirt..
Destructing ExampleVirt..
### ExampleVirt @ 0x2073a90 destroyed
### ExampleVirt @ 0x2076a00 destroyed
### Movable @ 0x207e230 destroyed
### NonCopyable @ 0x2025a00 destroyed
Instances not destroyed: [0, 0, 0]
Constructor values: [['10', '11'], ['4', '9', '9', '9'], ['4', '5', '7', '7']]
Copy constructions: [0, 0, 1]
Move constructions: [True, True]