1 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
2 | // test_new_operator.cpp |
3 | |
4 | // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . |
5 | // Use, modification and distribution is subject to the Boost Software |
6 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
7 | // http://www.boost.org/LICENSE_1_0.txt) |
8 | |
9 | // should pass compilation and execution |
10 | |
11 | #include <cstddef> // NULL |
12 | #include <cstdio> // remove |
13 | #include <fstream> |
14 | #include <new> |
15 | |
16 | #include <boost/config.hpp> |
17 | #if defined(BOOST_NO_STDC_NAMESPACE) |
18 | namespace std{ |
19 | using ::remove; |
20 | } |
21 | #endif |
22 | |
23 | #include <boost/serialization/access.hpp> |
24 | |
25 | #include "test_tools.hpp" |
26 | |
27 | #include "A.hpp" |
28 | #include "A.ipp" |
29 | |
30 | class ANew : public A { |
31 | friend class boost::serialization::access; |
32 | template<class Archive> |
33 | void serialize(Archive & ar, const unsigned /*file_version*/){ |
34 | ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(A); |
35 | } |
36 | public: |
37 | static unsigned int m_new_calls; |
38 | static unsigned int m_delete_calls; |
39 | // implement class specific new/delete in terms standard |
40 | // implementation - we're testing serialization |
41 | // not "new" here. |
42 | static void * operator new(size_t s){ |
43 | ++m_new_calls; |
44 | return ::operator new(s); |
45 | } |
46 | static void operator delete(void *p, std::size_t){ |
47 | ++m_delete_calls; |
48 | ::operator delete(p); |
49 | } |
50 | }; |
51 | unsigned int ANew::m_new_calls = 0; |
52 | unsigned int ANew::m_delete_calls = 0; |
53 | |
54 | class ANew1 : public A { |
55 | friend class boost::serialization::access; |
56 | template<class Archive> |
57 | void serialize(Archive & ar, const unsigned /*file_version*/){ |
58 | ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(A); |
59 | } |
60 | public: |
61 | static unsigned int m_new_calls; |
62 | static unsigned int m_delete_calls; |
63 | // implement class specific new/delete in terms standard |
64 | // implementation - we're testing serialization |
65 | // not "new" here. |
66 | static void * operator new(size_t s){ |
67 | ++m_new_calls; |
68 | return ::operator new(s); |
69 | } |
70 | static void operator delete(void *p){ |
71 | ++m_delete_calls; |
72 | ::operator delete(p); |
73 | } |
74 | }; |
75 | unsigned int ANew1::m_new_calls = 0; |
76 | unsigned int ANew1::m_delete_calls = 0; |
77 | |
78 | |
79 | class ANew2 : public A { |
80 | friend class boost::serialization::access; |
81 | template<class Archive> |
82 | void serialize(Archive & ar, const unsigned /*file_version*/){ |
83 | ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(A); |
84 | } |
85 | public: |
86 | static unsigned int m_new_calls; |
87 | static unsigned int m_delete_calls; |
88 | // implement class specific new/delete in terms standard |
89 | // implementation - we're testing serialization |
90 | // not "new" here. |
91 | static void * operator new(size_t s){ |
92 | ++m_new_calls; |
93 | return ::operator new(s); |
94 | } |
95 | }; |
96 | unsigned int ANew2::m_new_calls = 0; |
97 | unsigned int ANew2::m_delete_calls = 0; |
98 | |
99 | template<typename T> |
100 | int test(){ |
101 | const char * testfile = boost::archive::tmpnam(NULL); |
102 | |
103 | BOOST_REQUIRE(NULL != testfile); |
104 | |
105 | |
106 | T *ta = new T(); |
107 | |
108 | BOOST_CHECK(1 == T::m_new_calls); |
109 | BOOST_CHECK(0 == T::m_delete_calls); |
110 | |
111 | T *ta1 = NULL; |
112 | |
113 | { |
114 | test_ostream os(testfile, TEST_STREAM_FLAGS); |
115 | test_oarchive oa(os, TEST_ARCHIVE_FLAGS); |
116 | oa << boost::serialization::make_nvp("ta" , ta); |
117 | } |
118 | { |
119 | test_istream is(testfile, TEST_STREAM_FLAGS); |
120 | test_iarchive ia(is, TEST_ARCHIVE_FLAGS); |
121 | ia >> boost::serialization::make_nvp("ta" , ta1); |
122 | } |
123 | BOOST_CHECK(ta != ta1); |
124 | BOOST_CHECK(*ta == *ta1); |
125 | |
126 | BOOST_CHECK(2 == T::m_new_calls); |
127 | BOOST_CHECK(0 == T::m_delete_calls); |
128 | |
129 | std::remove(filename: testfile); |
130 | |
131 | delete ta; |
132 | delete ta1; |
133 | |
134 | BOOST_CHECK(2 == T::m_new_calls); |
135 | BOOST_CHECK(2 == T::m_delete_calls); |
136 | |
137 | return EXIT_SUCCESS; |
138 | } |
139 | int test_main( int /* argc */, char* /* argv */[] ){ |
140 | if(EXIT_SUCCESS != test<ANew>()) |
141 | return EXIT_FAILURE; |
142 | if(EXIT_SUCCESS != test<ANew1>()) |
143 | return EXIT_FAILURE; |
144 | // Note the following test fails. To see why this is, look into the file |
145 | // iserializer line # 247. Feel free to send a patch to detect the absence |
146 | // of a class specific delete. |
147 | /* |
148 | if(EXIT_SUCCESS != test<ANew2>()) |
149 | return EXIT_FAILURE; |
150 | */ |
151 | return EXIT_SUCCESS; |
152 | } |
153 | |
154 | // EOF |
155 | |