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 #include "common.hpp"
28 #include <boost/test/unit_test.hpp>
29 
30 class MemberMinimal
31 {
32   public:
33     MemberMinimal() = default;
MemberMinimal(std::string const & str)34     MemberMinimal( std::string const & str ) : x( str ) {}
35 
36   protected:
37     friend class cereal::access;
38 
39     template <class Archive>
save_minimal(Archive const &) const40     std::string save_minimal( Archive const & ) const
41     {
42       return x;
43     }
44 
45     template <class Archive>
load_minimal(Archive const &,std::string const & str)46     void load_minimal( Archive const &, std::string const & str )
47     {
48       x = str;
49     }
50 
51   public:
52     std::string x;
53 };
54 
55 class MemberMinimalVersioned
56 {
57   public:
58     MemberMinimalVersioned() = default;
MemberMinimalVersioned(double d)59     MemberMinimalVersioned( double d ) : x( d ) {}
60 
61   protected:
62     friend class cereal::access;
63 
64     template <class Archive>
save_minimal(Archive const &,const std::uint32_t) const65     double save_minimal( Archive const &, const std::uint32_t ) const
66     {
67       return x;
68     }
69 
70     template <class Archive>
load_minimal(Archive const &,double const & d,const std::uint32_t)71     void load_minimal( Archive const &, double const & d, const std::uint32_t )
72     {
73       x = d;
74     }
75 
76   public:
77     double x;
78 };
79 
80 struct NonMemberMinimal
81 {
82   NonMemberMinimal() = default;
NonMemberMinimalNonMemberMinimal83   NonMemberMinimal( std::uint32_t xx ) : x(xx) {}
84   std::uint32_t x;
85 };
86 
87 template <class Archive>
save_minimal(Archive const &,NonMemberMinimal const & nmm)88 std::uint32_t save_minimal( Archive const &, NonMemberMinimal const & nmm )
89 {
90   return nmm.x;
91 }
92 
93 template <class Archive>
load_minimal(Archive const &,NonMemberMinimal & nmm,std::uint32_t const & data)94 void load_minimal( Archive const &, NonMemberMinimal & nmm, std::uint32_t const & data )
95 {
96   nmm.x = data;
97 }
98 
99 struct NonMemberMinimalVersioned
100 {
101   NonMemberMinimalVersioned() = default;
NonMemberMinimalVersionedNonMemberMinimalVersioned102   NonMemberMinimalVersioned( bool xx ) : x(xx) {}
103   bool x;
104 };
105 
106 template <class Archive>
save_minimal(Archive const &,NonMemberMinimalVersioned const & nmm,std::uint32_t const)107 bool save_minimal( Archive const &, NonMemberMinimalVersioned const & nmm, std::uint32_t const )
108 {
109   return nmm.x;
110 }
111 
112 template <class Archive>
load_minimal(Archive const &,NonMemberMinimalVersioned & nmm,bool const & data,std::uint32_t const)113 void load_minimal( Archive const &, NonMemberMinimalVersioned & nmm, bool const & data, std::uint32_t const )
114 {
115   nmm.x = data;
116 }
117 
118 struct TestStruct
119 {
120   TestStruct() = default;
TestStructTestStruct121   TestStruct( std::string const & s, double d, std::uint32_t u, bool b ) :
122     mm(s), mmv(d), nmm(u), nmmv(b) {}
123 
124   template <class Archive>
serializeTestStruct125   void serialize( Archive & ar )
126   {
127     ar( mm, mmv );
128     ar( nmm, nmmv );
129   }
130 
131   MemberMinimal mm;
132   MemberMinimalVersioned mmv;
133   NonMemberMinimal nmm;
134   NonMemberMinimalVersioned nmmv;
135 };
136 
137 struct Issue79Struct
138 {
139   Issue79Struct() = default;
Issue79StructIssue79Struct140   Issue79Struct( std::int32_t xx ) : x(xx) {}
141   std::int32_t x;
142 };
143 
144 template <class Archive, cereal::traits::DisableIf<std::is_same<Archive, cereal::BinaryOutputArchive>::value ||
145                                                    std::is_same<Archive, cereal::PortableBinaryOutputArchive>::value> = cereal::traits::sfinae>
save_minimal(Archive const &,Issue79Struct const & val)146 std::string save_minimal( Archive const &, Issue79Struct const & val )
147 {
148   return std::to_string( val.x );
149 }
150 
151 template <class Archive, cereal::traits::DisableIf<std::is_same<Archive, cereal::BinaryInputArchive>::value ||
152                                                    std::is_same<Archive, cereal::PortableBinaryInputArchive>::value> = cereal::traits::sfinae>
load_minimal(Archive const &,Issue79Struct & val,std::string const & str)153 void load_minimal( Archive const &, Issue79Struct & val, std::string const & str )
154 {
155   val.x = std::stoi( str );
156 }
157 
158 template <class Archive, cereal::traits::EnableIf<std::is_same<Archive, cereal::BinaryOutputArchive>::value ||
159                                                   std::is_same<Archive, cereal::PortableBinaryOutputArchive>::value> = cereal::traits::sfinae>
save_minimal(Archive const &,Issue79Struct const & val)160 std::int32_t save_minimal( Archive const &, Issue79Struct const & val )
161 {
162   return val.x;
163 }
164 
165 template <class Archive, cereal::traits::EnableIf<std::is_same<Archive, cereal::BinaryInputArchive>::value ||
166                                                   std::is_same<Archive, cereal::PortableBinaryInputArchive>::value> = cereal::traits::sfinae>
load_minimal(Archive const &,Issue79Struct & val,std::int32_t const & xx)167 void load_minimal( Archive const &, Issue79Struct & val, std::int32_t const & xx )
168 {
169   val.x = xx;
170 }
171 
172 struct Issue79StructInternal
173 {
174   Issue79StructInternal() = default;
Issue79StructInternalIssue79StructInternal175   Issue79StructInternal( std::int32_t xx ) : x(xx) {}
176   std::int32_t x;
177 
178   template <class Archive, cereal::traits::DisableIf<std::is_same<Archive, cereal::BinaryOutputArchive>::value ||
179                                                      std::is_same<Archive, cereal::PortableBinaryOutputArchive>::value> = cereal::traits::sfinae>
save_minimalIssue79StructInternal180   std::string save_minimal( Archive const & ) const
181   {
182     return std::to_string( x );
183   }
184 
185   template <class Archive, cereal::traits::DisableIf<std::is_same<Archive, cereal::BinaryInputArchive>::value ||
186                                                      std::is_same<Archive, cereal::PortableBinaryInputArchive>::value> = cereal::traits::sfinae>
load_minimalIssue79StructInternal187   void load_minimal( Archive const &, std::string const & str )
188   {
189     x = std::stoi( str );
190   }
191 
192   template <class Archive, cereal::traits::EnableIf<std::is_same<Archive, cereal::BinaryOutputArchive>::value ||
193                                                     std::is_same<Archive, cereal::PortableBinaryOutputArchive>::value> = cereal::traits::sfinae>
save_minimalIssue79StructInternal194   std::int32_t save_minimal( Archive const & ) const
195   {
196     return x;
197   }
198 
199   template <class Archive, cereal::traits::EnableIf<std::is_same<Archive, cereal::BinaryInputArchive>::value ||
200                                                     std::is_same<Archive, cereal::PortableBinaryInputArchive>::value> = cereal::traits::sfinae>
load_minimalIssue79StructInternal201   void load_minimal( Archive const &, std::int32_t const & xx )
202   {
203     x = xx;
204   }
205 };
206 
207 template <class IArchive, class OArchive>
test_structs_minimal()208 void test_structs_minimal()
209 {
210   std::random_device rd;
211   std::mt19937 gen(rd());
212 
213   for(int ii=0; ii<100; ++ii)
214   {
215     TestStruct o_struct = { random_basic_string<char>(gen), random_value<double>(gen),
216                             random_value<std::uint32_t>(gen), random_value<uint8_t>(gen) % 2 ? true : false };
217 
218     Issue79Struct o_struct2 = { random_value<std::int32_t>(gen) };
219     Issue79StructInternal o_struct3 = { random_value<std::int32_t>(gen) };
220 
221     std::ostringstream os;
222     {
223       OArchive oar(os);
224       oar( o_struct );
225       oar( o_struct2 );
226       oar( o_struct3 );
227     }
228 
229     decltype(o_struct) i_struct;
230     decltype(o_struct2) i_struct2;
231     decltype(o_struct3) i_struct3;
232 
233     std::istringstream is(os.str());
234     {
235       IArchive iar(is);
236       iar( i_struct );
237       iar( i_struct2 );
238       iar( i_struct3 );
239     }
240 
241     BOOST_CHECK(o_struct.mm.x == i_struct.mm.x);
242     BOOST_CHECK_CLOSE(o_struct.mmv.x, i_struct.mmv.x, 1e-5);
243 
244     BOOST_CHECK(o_struct.nmm.x == i_struct.nmm.x);
245     BOOST_CHECK(o_struct.nmmv.x == i_struct.nmmv.x);
246 
247     BOOST_CHECK(o_struct2.x == i_struct2.x);
248 
249     BOOST_CHECK(o_struct3.x == i_struct3.x);
250   }
251 }
252 
BOOST_AUTO_TEST_CASE(binary_structs_minimal)253 BOOST_AUTO_TEST_CASE( binary_structs_minimal )
254 {
255   test_structs_minimal<cereal::BinaryInputArchive, cereal::BinaryOutputArchive>();
256 }
257 
BOOST_AUTO_TEST_CASE(portable_binary_structs_minimal)258 BOOST_AUTO_TEST_CASE( portable_binary_structs_minimal )
259 {
260   test_structs_minimal<cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive>();
261 }
262 
BOOST_AUTO_TEST_CASE(xml_structs_minimal)263 BOOST_AUTO_TEST_CASE( xml_structs_minimal )
264 {
265   test_structs_minimal<cereal::XMLInputArchive, cereal::XMLOutputArchive>();
266 }
267 
BOOST_AUTO_TEST_CASE(json_structs_minimal)268 BOOST_AUTO_TEST_CASE( json_structs_minimal )
269 {
270   test_structs_minimal<cereal::JSONInputArchive, cereal::JSONOutputArchive>();
271 }
272