add cereal library
[platform/upstream/iotivity.git] / extlibs / cereal / cereal / unittests / polymorphic.cpp
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 struct PolyBase
31 {
32   PolyBase() {}
33   PolyBase( int xx, float yy ) : x(xx), y(yy) {}
34   int x;
35   float y;
36
37   template <class Archive>
38   void serialize( Archive & ar )
39   {
40     ar( x, y );
41   }
42
43   virtual void foo() = 0;
44
45   bool operator==( PolyBase const & other ) const
46   {
47     return x == other.x && std::abs(y - other.y) < 1e-5;
48   }
49 };
50
51 struct PolyDerived : PolyBase
52 {
53   PolyDerived() {}
54   PolyDerived( int xx, float yy, bool aa, double bb ) :
55     PolyBase( xx, yy ), a(aa), b(bb) {}
56
57   bool a;
58   double b;
59
60   template <class Archive>
61   void serialize( Archive & ar )
62   {
63     ar( cereal::base_class<PolyBase>( this ),
64         a, b );
65   }
66
67   bool operator==( PolyDerived const & other ) const
68   {
69     return PolyBase::operator==( other ) && a == other.a && std::abs(b - other.b) < 1e-5;
70   }
71
72   void foo() {}
73 };
74
75 struct PolyLA : std::enable_shared_from_this<PolyLA>
76 {
77   virtual void foo() = 0;
78 };
79
80 struct PolyDerivedLA : public PolyLA
81 {
82   PolyDerivedLA( int xx ) : x( xx ) { }
83
84   int x;
85   std::vector<std::shared_ptr<PolyLA>> vec;
86
87   template <class Archive>
88   void serialize( Archive & ar )
89   {
90     ar( x );
91     ar( vec );
92   }
93
94   template <class Archive>
95   static void load_and_construct( Archive & ar, cereal::construct<PolyDerivedLA> & construct )
96   {
97     int xx;
98     ar( xx );
99     construct( xx );
100     ar( construct->vec );
101   }
102
103   void foo() {}
104
105   bool operator==( PolyDerivedLA const & other ) const
106   {
107     if( x != other.x )
108       return false;
109     if( vec.size() != other.vec.size() )
110       return false;
111     for( size_t i = 0; i < vec.size(); ++i )
112       if( !(*std::dynamic_pointer_cast<PolyDerivedLA>(vec[i]) == *std::dynamic_pointer_cast<PolyDerivedLA>(other.vec[i])) )
113         return false;
114
115     return true;
116   }
117 };
118
119 std::ostream& operator<<(std::ostream& os, PolyDerivedLA const & s)
120 {
121     os << "[x: " << s.x << "] ";
122     for( auto const & v : s.vec )
123       os << " child: " << (*std::dynamic_pointer_cast<PolyDerivedLA>(v));
124     return os;
125 }
126
127 std::ostream& operator<<(std::ostream& os, PolyDerived const & s)
128 {
129     os << "[x: " << s.x << " y: " << s.y << " a: " << s.a << " b: " << s.b << "]";
130     return os;
131 }
132
133 CEREAL_REGISTER_TYPE(PolyDerived)
134 CEREAL_REGISTER_TYPE(PolyDerivedLA)
135
136 template <class IArchive, class OArchive>
137 void test_polymorphic()
138 {
139   std::random_device rd;
140   std::mt19937 gen(rd());
141
142   auto rngB = [&](){ return random_value<int>( gen ) % 2 == 0; };
143   auto rngI = [&](){ return random_value<int>( gen ); };
144   auto rngF = [&](){ return random_value<float>( gen ); };
145   auto rngD = [&](){ return random_value<double>( gen ); };
146
147   for(int ii=0; ii<100; ++ii)
148   {
149     std::shared_ptr<PolyBase> o_shared = std::make_shared<PolyDerived>( rngI(), rngF(), rngB(), rngD() );
150     std::weak_ptr<PolyBase>   o_weak = o_shared;
151     std::unique_ptr<PolyBase> o_unique( new PolyDerived( rngI(), rngF(), rngB(), rngD() ) );
152
153     auto pda = std::make_shared<PolyDerivedLA>( rngI() );
154     pda->vec.emplace_back( std::make_shared<PolyDerivedLA>( rngI() ) );
155     std::shared_ptr<PolyLA>   o_sharedLA = pda;
156
157     std::ostringstream os;
158     {
159       OArchive oar(os);
160
161       oar( o_shared, o_weak, o_unique );
162       oar( o_sharedLA );
163     }
164
165     decltype(o_shared) i_shared;
166     decltype(o_weak) i_weak;
167     decltype(o_unique) i_unique;
168     decltype(o_sharedLA) i_sharedLA;
169
170     std::istringstream is(os.str());
171     {
172       IArchive iar(is);
173
174       iar( i_shared, i_weak, i_unique );
175       iar( i_sharedLA );
176     }
177
178     auto i_locked = i_weak.lock();
179     auto o_locked = o_weak.lock();
180
181     auto i_sharedLA2 = i_sharedLA->shared_from_this();
182
183     BOOST_CHECK_EQUAL(i_shared.get(), i_locked.get());
184     BOOST_CHECK_EQUAL(*((PolyDerived*)i_shared.get()), *((PolyDerived*)o_shared.get()));
185     BOOST_CHECK_EQUAL(*((PolyDerived*)i_shared.get()), *((PolyDerived*)i_locked.get()));
186     BOOST_CHECK_EQUAL(*((PolyDerived*)i_locked.get()), *((PolyDerived*)o_locked.get()));
187     BOOST_CHECK_EQUAL(*((PolyDerived*)i_unique.get()), *((PolyDerived*)o_unique.get()));
188     BOOST_CHECK_EQUAL(*((PolyDerivedLA*)i_sharedLA.get()), *((PolyDerivedLA*)o_sharedLA.get()));
189     BOOST_CHECK_EQUAL(*((PolyDerivedLA*)i_sharedLA2.get()), *((PolyDerivedLA*)o_sharedLA.get()));
190   }
191 }
192
193 BOOST_AUTO_TEST_CASE( binary_polymorphic )
194 {
195   test_polymorphic<cereal::BinaryInputArchive, cereal::BinaryOutputArchive>();
196 }
197
198 BOOST_AUTO_TEST_CASE( portable_binary_polymorphic )
199 {
200   test_polymorphic<cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive>();
201 }
202
203 BOOST_AUTO_TEST_CASE( xml_polymorphic )
204 {
205   test_polymorphic<cereal::XMLInputArchive, cereal::XMLOutputArchive>();
206 }
207
208 BOOST_AUTO_TEST_CASE( json_polymorphic )
209 {
210   test_polymorphic<cereal::JSONInputArchive, cereal::JSONOutputArchive>();
211 }
212