1 //  Copyright (c) 2014 Thomas Heller
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <hpx/runtime/serialization/serialize.hpp>
7 #include <hpx/runtime/serialization/list.hpp>
8 
9 #include <hpx/runtime/serialization/input_archive.hpp>
10 #include <hpx/runtime/serialization/output_archive.hpp>
11 
12 #include <hpx/util/lightweight_test.hpp>
13 
14 #include <cstddef>
15 #include <list>
16 #include <vector>
17 
18 template <typename T>
19 struct A
20 {
AA21     A() {}
22 
AA23     A(T t) : t_(t) {}
24     T t_;
25 
operator =A26     A & operator=(T t) { t_ = t; return *this; }
27 
28     template <typename Archive>
serializeA29     void serialize(Archive & ar, unsigned)
30     {
31         ar & t_;
32     }
33 };
34 
35 // non-default constructible
36 struct B
37 {
38     const int a;
39     double b;
40 
41 public:
42     B() = delete;
BB43     B(int a): a(a) {}
44 
45     template <class Archive>
serializeB46     void serialize(Archive& ar, unsigned)
47     {
48         ar & b;
49     }
50 
get_aB51     int get_a() const
52     {
53         return a;
54     }
55 
set_bB56     void set_b(short b)
57     {
58         this->b = b;
59     }
60 
get_bB61     short get_b() const
62     {
63         return b;
64     }
65 };
66 
67 template <class Archive>
save_construct_data(Archive & ar,const B * b,unsigned)68 void save_construct_data(Archive& ar, const B* b, unsigned)
69 {
70     ar << b->get_a();
71 }
72 
73 template <class Archive>
load_construct_data(Archive & ar,B * b,unsigned)74 void load_construct_data(Archive& ar, B* b, unsigned)
75 {
76     int a = 0;
77     ar >> a;
78     ::new (b) B(a);
79 }
80 
test_bool()81 void test_bool()
82 {
83     {
84         std::vector<char> buffer;
85         hpx::serialization::output_archive oarchive(buffer);
86 
87         std::list<bool> os;
88         os.push_back(true);
89         os.push_back(false);
90         os.push_back(false);
91         os.push_back(true);
92         oarchive << os;
93 
94         hpx::serialization::input_archive iarchive(buffer);
95         std::list<bool> is;
96         iarchive >> is;
97         HPX_TEST_EQ(os.size(), is.size());
98         for (auto ot = os.begin(), it = is.begin();
99              ot != os.end(); ++ot, ++it)
100         {
101             HPX_TEST_EQ(*ot, *it);
102         }
103     }
104     {
105         std::vector<char> buffer;
106         hpx::serialization::output_archive oarchive(buffer);
107 
108         std::list<A<bool> > os;
109         os.push_back(true);
110         os.push_back(false);
111         os.push_back(false);
112         os.push_back(true);
113         oarchive << os;
114 
115         hpx::serialization::input_archive iarchive(buffer);
116         std::list<A<bool> > is;
117         iarchive >> is;
118         HPX_TEST_EQ(os.size(), is.size());
119         for (auto ot = os.begin(), it = is.begin();
120              ot != os.end(); ++ot, ++it)
121         {
122             HPX_TEST_EQ(ot->t_, it->t_);
123         }
124     }
125 }
126 
127 template <typename T>
test(T min,T max)128 void test(T min, T max)
129 {
130     {
131         std::vector<char> buffer;
132         hpx::serialization::output_archive oarchive(buffer);
133         std::list<T> os;
134         for (T c = min; c < max; ++c)
135         {
136             os.push_back(c);
137         }
138         oarchive << os;
139         hpx::serialization::input_archive iarchive(buffer);
140         std::list<T> is;
141         iarchive >> is;
142         HPX_TEST_EQ(os.size(), is.size());
143         for (auto ot = os.begin(), it = is.begin();
144              ot != os.end(); ++ot, ++it)
145         {
146             HPX_TEST_EQ(*ot, *it);
147         }
148     }
149     {
150         std::vector<char> buffer;
151         hpx::serialization::output_archive oarchive(buffer);
152         std::list<A<T> > os;
153         for (T c = min; c < max; ++c)
154         {
155             os.push_back(c);
156         }
157         oarchive << os;
158         hpx::serialization::input_archive iarchive(buffer);
159         std::list<A<T> > is;
160         iarchive >> is;
161         HPX_TEST_EQ(os.size(), is.size());
162         for (auto ot = os.begin(), it = is.begin();
163              ot != os.end(); ++ot, ++it)
164         {
165             HPX_TEST_EQ(ot->t_, it->t_);
166         }
167     }
168 }
169 
170 template <typename T>
test_fp(T min,T max)171 void test_fp(T min, T max)
172 {
173     {
174         std::vector<char> buffer;
175         hpx::serialization::output_archive oarchive(buffer);
176         std::list<T> os;
177         for (T c = min; c < max; c += static_cast<T>(0.5))
178         {
179             os.push_back(c);
180         }
181         oarchive << os;
182         hpx::serialization::input_archive iarchive(buffer);
183         std::list<T> is;
184         iarchive >> is;
185         HPX_TEST_EQ(os.size(), is.size());
186         for (auto ot = os.begin(), it = is.begin();
187              ot != os.end(); ++ot, ++it)
188         {
189             HPX_TEST_EQ(*ot++, *it++);
190         }
191     }
192     {
193         std::vector<char> buffer;
194         hpx::serialization::output_archive oarchive(buffer);
195         std::list<A<T> > os;
196         for (T c = min; c < max; c += static_cast<T>(0.5))
197         {
198             os.push_back(c);
199         }
200         oarchive << os;
201         hpx::serialization::input_archive iarchive(buffer);
202         std::list<A<T> > is;
203         iarchive >> is;
204         HPX_TEST_EQ(os.size(), is.size());
205         for (auto ot = os.begin(), it = is.begin();
206              ot != os.end(); ++ot, ++it)
207         {
208             HPX_TEST_EQ(ot->t_, it->t_);
209         }
210     }
211 }
212 
test_non_default_constructible()213 void test_non_default_constructible()
214 {
215     std::vector<char> buffer;
216     hpx::serialization::output_archive oarchive(buffer);
217 
218     std::list<B> os;
219     os.push_back(1);
220     os.push_back(2);
221     os.push_back(3);
222     os.push_back(4);
223 
224     short b = 1;
225     for (auto& i: os) {
226         i.set_b(b);
227         ++b;
228     }
229 
230     oarchive << os;
231 
232     hpx::serialization::input_archive iarchive(buffer);
233     std::list<B> is;
234     iarchive >> is;
235     HPX_TEST_EQ(os.size(), is.size());
236     for (auto ot = os.begin(), it = is.begin();
237          ot != os.end(); ++ot, ++it)
238     {
239         HPX_TEST_EQ(ot->get_a(), it->get_a());
240         HPX_TEST_EQ(ot->get_b(), it->get_b());
241     }
242 }
243 
main()244 int main()
245 {
246     test_bool();
247     test<char>((std::numeric_limits<char>::min)(),
248         (std::numeric_limits<char>::max)());
249     test<int>((std::numeric_limits<int>::min)(),
250         (std::numeric_limits<int>::min)() + 100);
251     test<int>((std::numeric_limits<int>::max)() - 100,
252         (std::numeric_limits<int>::max)());
253     test<int>(-100, 100);
254     test<unsigned>((std::numeric_limits<unsigned>::min)(),
255         (std::numeric_limits<unsigned>::min)() + 100);
256     test<unsigned>((std::numeric_limits<unsigned>::max)() - 100,
257         (std::numeric_limits<unsigned>::max)());
258     test<long>((std::numeric_limits<long>::min)(),
259         (std::numeric_limits<long>::min)() + 100);
260     test<long>((std::numeric_limits<long>::max)() - 100,
261         (std::numeric_limits<long>::max)());
262     test<long>(-100, 100);
263     test<unsigned long>((std::numeric_limits<unsigned long>::min)(),
264         (std::numeric_limits<unsigned long>::min)() + 100);
265     test<unsigned long>((std::numeric_limits<unsigned long>::max)() - 100,
266         (std::numeric_limits<unsigned long>::max)());
267     test_fp<float>((std::numeric_limits<float>::min)(),
268         (std::numeric_limits<float>::min)() + 100);
269     test_fp<float>((std::numeric_limits<float>::max)() - 100,
270         (std::numeric_limits<float>::max)()); //it's incorrect
271     // because floatmax() - 100 causes cancellations error,
272     // digits are not affected
273     test_fp<float>(-100, 100);
274     test<double>((std::numeric_limits<double>::min)(),
275         (std::numeric_limits<double>::min)() + 100);
276     test<double>((std::numeric_limits<double>::max)() - 100,
277         (std::numeric_limits<double>::max)()); //it's the same
278     test<double>(-100, 100);
279 
280     test_non_default_constructible();
281 
282     return hpx::util::report_errors();
283 }
284