1 /*
2 Copyright (c) 2014, Randolph Voorhies, Shane Grant
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of cereal nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #ifndef CEREAL_TEST_VERSIONING_H_
28 #define CEREAL_TEST_VERSIONING_H_
29 #include "common.hpp"
30
31 #if CEREAL_THREAD_SAFE
32 #include <future>
33 #endif
34
35 namespace Nested
36 {
37 struct NestedClass
38 {
39 int x;
40
41 template <class Archive>
serializeNested::NestedClass42 void serialize( Archive & ar )
43 { ar( x ); }
44 };
45 }
46
47 CEREAL_CLASS_VERSION( Nested::NestedClass, 1 )
48
49 class VersionStructMS
50 {
51 public:
52 bool x;
53 std::uint32_t v;
54
55 private:
56 friend class cereal::access;
57 template <class Archive>
serialize(Archive & ar,std::uint32_t const version)58 void serialize( Archive & ar, std::uint32_t const version )
59 {
60 ar( x );
61 v = version;
62 }
63 };
64
65 struct VersionStructMSP
66 {
67 uint8_t x;
68 std::uint32_t v;
69 template <class Archive>
saveVersionStructMSP70 void save( Archive & ar, std::uint32_t const /*version*/ ) const
71 {
72 ar( x );
73 }
74
75 template <class Archive>
loadVersionStructMSP76 void load( Archive & ar, std::uint32_t const version )
77 {
78 ar( x );
79 v = version;
80 }
81 };
82
83 struct VersionStructNMS
84 {
85 std::int32_t x;
86 std::uint32_t v;
87 };
88
89 template <class Archive>
serialize(Archive & ar,VersionStructNMS & vnms,const std::uint32_t version)90 void serialize( Archive & ar, VersionStructNMS & vnms, const std::uint32_t version )
91 {
92 ar( vnms.x );
93 vnms.v = version;
94 }
95
96 struct VersionStructNMSP
97 {
98 double x;
99 std::uint32_t v;
100 };
101
102 template <class Archive>
save(Archive & ar,VersionStructNMSP const & vnms,const std::uint32_t)103 void save( Archive & ar, VersionStructNMSP const & vnms, const std::uint32_t /*version*/ )
104 {
105 ar( vnms.x );
106 }
107
108 template <class Archive>
load(Archive & ar,VersionStructNMSP & vnms,const std::uint32_t version)109 void load( Archive & ar, VersionStructNMSP & vnms, const std::uint32_t version )
110 {
111 ar( vnms.x );
112 vnms.v = version;
113 }
114
115 CEREAL_CLASS_VERSION( VersionStructMSP, 33 )
116 CEREAL_CLASS_VERSION( VersionStructNMS, 66 )
117 CEREAL_CLASS_VERSION( VersionStructNMSP, 99 )
118
119 template <class IArchive, class OArchive> inline
test_versioning()120 void test_versioning()
121 {
122 std::random_device rd;
123 std::mt19937 gen(rd());
124
125 #if CEREAL_THREAD_SAFE
126 #include <future>
127 static std::mutex testMutex;
128 #endif
129
130 for(size_t i=0; i<100; ++i)
131 {
132 VersionStructMS o_MS = {random_value<uint8_t>(gen) % 2 ? true : false, 1};
133 VersionStructMSP o_MSP = {random_value<uint8_t>(gen), 1};
134 VersionStructNMS o_NMS = {random_value<int32_t>(gen), 1};
135 VersionStructNMSP o_NMSP = {random_value<double>(gen), 1};
136 VersionStructMS o_MS2 = {random_value<uint8_t>(gen) % 2 ? true : false, 1};
137 VersionStructMSP o_MSP2 = {random_value<uint8_t>(gen), 1};
138 VersionStructNMS o_NMS2 = {random_value<int32_t>(gen), 1};
139 VersionStructNMSP o_NMSP2 = {random_value<double>(gen), 1};
140
141 std::ostringstream os;
142 {
143 OArchive oar(os);
144 oar( o_MS );
145 oar( o_MSP );
146 oar( o_NMS );
147 oar( o_NMSP );
148 oar( o_MS2 );
149 oar( o_MSP2 );
150 oar( o_NMS2 );
151 oar( o_NMSP2 );
152 }
153
154 decltype(o_MS) i_MS;
155 decltype(o_MSP) i_MSP;
156 decltype(o_NMS) i_NMS;
157 decltype(o_NMSP) i_NMSP;
158 decltype(o_MS2) i_MS2;
159 decltype(o_MSP2) i_MSP2;
160 decltype(o_NMS2) i_NMS2;
161 decltype(o_NMSP2) i_NMSP2;
162
163 std::istringstream is(os.str());
164 {
165 IArchive iar(is);
166 iar( i_MS );
167 iar( i_MSP );
168 iar( i_NMS );
169 iar( i_NMSP );
170 iar( i_MS2 );
171 iar( i_MSP2 );
172 iar( i_NMS2 );
173 iar( i_NMSP2 );
174 }
175
176 #if CEREAL_THREAD_SAFE
177 std::lock_guard<std::mutex> lock( testMutex );
178 #endif
179
180 CHECK_EQ(o_MS.x, i_MS.x);
181 CHECK_EQ(i_MS.v, 0u);
182 CHECK_EQ(o_MSP.x, i_MSP.x);
183 CHECK_EQ(i_MSP.v, 33u);
184 CHECK_EQ(o_NMS.x, i_NMS.x);
185 CHECK_EQ(i_NMS.v, 66u);
186 CHECK_EQ(o_NMSP.x, doctest::Approx(i_NMSP.x).epsilon(1e-5));
187 CHECK_EQ(i_NMSP.v, 99u);
188
189 CHECK_EQ(o_MS2.x, i_MS2.x);
190 CHECK_EQ(i_MS2.v, 0u);
191 CHECK_EQ(o_MSP2.x, i_MSP2.x);
192 CHECK_EQ(i_MSP2.v, 33u);
193 CHECK_EQ(o_NMS2.x, i_NMS2.x);
194 CHECK_EQ(i_NMS2.v, 66u);
195 CHECK_EQ(o_NMSP2.x, doctest::Approx(i_NMSP2.x).epsilon(1e-5));
196 CHECK_EQ(i_NMSP2.v, 99u);
197 }
198 }
199
200 #if CEREAL_THREAD_SAFE
201 template <class IArchive, class OArchive> inline
test_versioning_threading()202 void test_versioning_threading()
203 {
204 std::vector<std::future<bool>> pool;
205 for( size_t i = 0; i < 100; ++i )
206 pool.emplace_back( std::async( std::launch::async,
207 [](){ test_versioning<IArchive, OArchive>(); return true; } ) );
208
209 for( auto & future : pool )
210 future.wait();
211
212 for( auto & future : pool )
213 CHECK_UNARY( future.get() );
214 }
215 #endif // CEREAL_THREAD_SAFE
216
217 #endif // CEREAL_TEST_VERSIONING_H_
218