| 1 | /* Boost.MultiIndex test for serialization. |
|---|
| 2 | * |
|---|
| 3 | * Copyright 2003-2005 Joaquín M López Muñoz. |
|---|
| 4 | * Distributed under the Boost Software License, Version 1.0. |
|---|
| 5 | * (See accompanying file LICENSE_1_0.txt or copy at |
|---|
| 6 | * http://www.boost.org/LICENSE_1_0.txt) |
|---|
| 7 | * |
|---|
| 8 | * See http://www.boost.org/libs/multi_index for library home page. |
|---|
| 9 | */ |
|---|
| 10 | |
|---|
| 11 | #include "test_serialization.hpp" |
|---|
| 12 | |
|---|
| 13 | #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ |
|---|
| 14 | #include <boost/archive/text_oarchive.hpp> |
|---|
| 15 | #include <boost/archive/text_iarchive.hpp> |
|---|
| 16 | #include "pre_multi_index.hpp" |
|---|
| 17 | #include <boost/multi_index_container.hpp> |
|---|
| 18 | #include <boost/multi_index/hashed_index.hpp> |
|---|
| 19 | #include <boost/multi_index/ordered_index.hpp> |
|---|
| 20 | #include <boost/multi_index/sequenced_index.hpp> |
|---|
| 21 | #include <boost/multi_index/key_extractors.hpp> |
|---|
| 22 | #include <boost/noncopyable.hpp> |
|---|
| 23 | #include <boost/test/test_tools.hpp> |
|---|
| 24 | #include <sstream> |
|---|
| 25 | #include <string> |
|---|
| 26 | #include <vector> |
|---|
| 27 | #include "pair_of_ints.hpp" |
|---|
| 28 | |
|---|
| 29 | using namespace boost::multi_index; |
|---|
| 30 | |
|---|
| 31 | template<int N> |
|---|
| 32 | struct all_indices_equal_helper |
|---|
| 33 | { |
|---|
| 34 | template<class MultiIndexContainer> |
|---|
| 35 | static bool compare( |
|---|
| 36 | const MultiIndexContainer& m1,const MultiIndexContainer& m2) |
|---|
| 37 | { |
|---|
| 38 | if(!(get<N>(m1)==get<N>(m2))){ |
|---|
| 39 | return false; |
|---|
| 40 | } |
|---|
| 41 | return all_indices_equal_helper<N-1>::compare(m1,m2); |
|---|
| 42 | } |
|---|
| 43 | }; |
|---|
| 44 | |
|---|
| 45 | template<> |
|---|
| 46 | struct all_indices_equal_helper<0> |
|---|
| 47 | { |
|---|
| 48 | template<class MultiIndexContainer> |
|---|
| 49 | static bool compare( |
|---|
| 50 | const MultiIndexContainer& m1,const MultiIndexContainer& m2) |
|---|
| 51 | { |
|---|
| 52 | return true; |
|---|
| 53 | } |
|---|
| 54 | }; |
|---|
| 55 | |
|---|
| 56 | template<class MultiIndexContainer> |
|---|
| 57 | bool all_indices_equal( |
|---|
| 58 | const MultiIndexContainer& m1,const MultiIndexContainer& m2) |
|---|
| 59 | { |
|---|
| 60 | BOOST_STATIC_CONSTANT(int, |
|---|
| 61 | N=boost::mpl::size< |
|---|
| 62 | BOOST_DEDUCED_TYPENAME MultiIndexContainer::index_type_list>::type::value); |
|---|
| 63 | |
|---|
| 64 | return all_indices_equal_helper<N-1>::compare(m1,m2); |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | template<class MultiIndexContainer> |
|---|
| 68 | void test_serialization(const MultiIndexContainer& m) |
|---|
| 69 | { |
|---|
| 70 | typedef typename MultiIndexContainer::iterator iterator; |
|---|
| 71 | typedef typename MultiIndexContainer::const_iterator const_iterator; |
|---|
| 72 | |
|---|
| 73 | std::ostringstream oss; |
|---|
| 74 | { |
|---|
| 75 | boost::archive::text_oarchive oa(oss); |
|---|
| 76 | oa<<m; |
|---|
| 77 | |
|---|
| 78 | std::vector<const_iterator> its(m.size()); |
|---|
| 79 | const_iterator it_end=m.end(); |
|---|
| 80 | for(const_iterator it=m.begin();it!=it_end;++it){ |
|---|
| 81 | its.push_back(it); |
|---|
| 82 | oa<<const_cast<const const_iterator&>(its.back()); |
|---|
| 83 | } |
|---|
| 84 | oa<<const_cast<const const_iterator&>(it_end); |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | MultiIndexContainer m2; |
|---|
| 88 | std::istringstream iss(oss.str()); |
|---|
| 89 | boost::archive::text_iarchive ia(iss); |
|---|
| 90 | ia>>m2; |
|---|
| 91 | BOOST_CHECK(all_indices_equal(m,m2)); |
|---|
| 92 | |
|---|
| 93 | iterator it_end=m2.end(); |
|---|
| 94 | for(iterator it=m2.begin();it!=it_end;++it){ |
|---|
| 95 | iterator it2; |
|---|
| 96 | ia>>it2; |
|---|
| 97 | BOOST_CHECK(it==it2); |
|---|
| 98 | |
|---|
| 99 | /* exercise safe mode with this (unchecked) iterator */ |
|---|
| 100 | BOOST_CHECK(*it==*it2); |
|---|
| 101 | m2.erase(it,it2); |
|---|
| 102 | m2.erase(it2,it2); |
|---|
| 103 | m2.erase(it2,it); |
|---|
| 104 | iterator it3(++it2); |
|---|
| 105 | iterator it4; |
|---|
| 106 | it4=--it2; |
|---|
| 107 | BOOST_CHECK(it==it4); |
|---|
| 108 | BOOST_CHECK(it==project<0>(m2,it4)); |
|---|
| 109 | } |
|---|
| 110 | iterator it2; |
|---|
| 111 | ia>>it2; |
|---|
| 112 | BOOST_CHECK(it_end==it2); |
|---|
| 113 | BOOST_CHECK(it_end==project<0>(m2,it2)); |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | void test_hashed_index_serialization() |
|---|
| 117 | { |
|---|
| 118 | const int N=100; |
|---|
| 119 | const int SHUFFLE=10232; |
|---|
| 120 | |
|---|
| 121 | typedef multi_index_container< |
|---|
| 122 | int, |
|---|
| 123 | indexed_by< |
|---|
| 124 | hashed_unique<identity<int> >, |
|---|
| 125 | sequenced<> |
|---|
| 126 | > |
|---|
| 127 | > hashed_set; |
|---|
| 128 | |
|---|
| 129 | typedef hashed_set::iterator iterator; |
|---|
| 130 | typedef hashed_set::local_iterator local_iterator; |
|---|
| 131 | |
|---|
| 132 | hashed_set hs; |
|---|
| 133 | |
|---|
| 134 | for(int i=0;i<N;++i){ |
|---|
| 135 | hs.insert(i*SHUFFLE); |
|---|
| 136 | } |
|---|
| 137 | |
|---|
| 138 | std::ostringstream oss; |
|---|
| 139 | { |
|---|
| 140 | boost::archive::text_oarchive oa(oss); |
|---|
| 141 | oa<<const_cast<const hashed_set&>(hs); |
|---|
| 142 | |
|---|
| 143 | std::vector<iterator> its(N); |
|---|
| 144 | for(int i=0;i<N;++i){ |
|---|
| 145 | iterator it=hs.find(i*SHUFFLE); |
|---|
| 146 | its.push_back(it); |
|---|
| 147 | oa<<const_cast<const iterator&>(its.back()); |
|---|
| 148 | } |
|---|
| 149 | iterator it=hs.end(); |
|---|
| 150 | oa<<const_cast<const iterator&>(it); |
|---|
| 151 | |
|---|
| 152 | std::vector<local_iterator> lits(2*N); |
|---|
| 153 | for(std::size_t buc=0;buc<hs.bucket_count();++buc){ |
|---|
| 154 | for(local_iterator lit=hs.begin(buc),lit_end=hs.end(buc); |
|---|
| 155 | lit!=lit_end;++lit){ |
|---|
| 156 | oa<<*lit; |
|---|
| 157 | lits.push_back(lit); |
|---|
| 158 | oa<<const_cast<const local_iterator&>(lits.back()); |
|---|
| 159 | } |
|---|
| 160 | local_iterator lit2=hs.end(buc); |
|---|
| 161 | lits.push_back(lit2); |
|---|
| 162 | oa<<const_cast<const local_iterator&>(lits.back()); |
|---|
| 163 | } |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | hashed_set hs2; |
|---|
| 167 | std::istringstream iss(oss.str()); |
|---|
| 168 | boost::archive::text_iarchive ia(iss); |
|---|
| 169 | ia>>hs2; |
|---|
| 170 | BOOST_CHECK(get<1>(hs)==get<1>(hs2)); |
|---|
| 171 | |
|---|
| 172 | for(int j=0;j<N;++j){ |
|---|
| 173 | iterator it; |
|---|
| 174 | ia>>it; |
|---|
| 175 | BOOST_CHECK(*it==j*SHUFFLE); |
|---|
| 176 | } |
|---|
| 177 | iterator it; |
|---|
| 178 | ia>>it; |
|---|
| 179 | BOOST_CHECK(it==hs2.end()); |
|---|
| 180 | |
|---|
| 181 | for(std::size_t buc=0;buc<hs2.bucket_count();++buc){ |
|---|
| 182 | for(std::size_t k=0;k<hs2.bucket_size(buc);++k){ |
|---|
| 183 | int n; |
|---|
| 184 | local_iterator it; |
|---|
| 185 | ia>>n; |
|---|
| 186 | ia>>it; |
|---|
| 187 | BOOST_CHECK(*it==n); |
|---|
| 188 | } |
|---|
| 189 | local_iterator it2; |
|---|
| 190 | ia>>it2; |
|---|
| 191 | BOOST_CHECK(it2==hs2.end(buc)); |
|---|
| 192 | } |
|---|
| 193 | } |
|---|
| 194 | |
|---|
| 195 | void test_serialization() |
|---|
| 196 | { |
|---|
| 197 | { |
|---|
| 198 | typedef multi_index_container< |
|---|
| 199 | int, |
|---|
| 200 | indexed_by< |
|---|
| 201 | sequenced<>, |
|---|
| 202 | sequenced<> |
|---|
| 203 | > |
|---|
| 204 | > multi_index_t; |
|---|
| 205 | |
|---|
| 206 | multi_index_t m; |
|---|
| 207 | for(int i=0;i<100;++i)m.push_back(i); |
|---|
| 208 | m.reverse(); |
|---|
| 209 | test_serialization(m); |
|---|
| 210 | |
|---|
| 211 | m.clear(); |
|---|
| 212 | for(int j=50;j<100;++j)m.push_back(j); |
|---|
| 213 | for(int k=0;k<50;++k)m.push_back(k); |
|---|
| 214 | m.sort(); |
|---|
| 215 | test_serialization(m); |
|---|
| 216 | } |
|---|
| 217 | { |
|---|
| 218 | typedef multi_index_container< |
|---|
| 219 | int, |
|---|
| 220 | indexed_by< |
|---|
| 221 | sequenced<>, |
|---|
| 222 | ordered_non_unique<identity<int> > |
|---|
| 223 | > |
|---|
| 224 | > multi_index_t; |
|---|
| 225 | |
|---|
| 226 | multi_index_t m; |
|---|
| 227 | for(int i=0;i<100;++i){ |
|---|
| 228 | m.push_back(i); |
|---|
| 229 | m.push_back(i); |
|---|
| 230 | m.push_back(i); |
|---|
| 231 | } |
|---|
| 232 | m.reverse(); |
|---|
| 233 | test_serialization(m); |
|---|
| 234 | } |
|---|
| 235 | { |
|---|
| 236 | typedef multi_index_container< |
|---|
| 237 | pair_of_ints, |
|---|
| 238 | indexed_by< |
|---|
| 239 | ordered_unique< |
|---|
| 240 | BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first) |
|---|
| 241 | >, |
|---|
| 242 | ordered_non_unique< |
|---|
| 243 | BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second) |
|---|
| 244 | >, |
|---|
| 245 | sequenced<> |
|---|
| 246 | > |
|---|
| 247 | > multi_index_t; |
|---|
| 248 | |
|---|
| 249 | multi_index_t m; |
|---|
| 250 | test_serialization(m); |
|---|
| 251 | |
|---|
| 252 | m.insert(pair_of_ints(4,0)); |
|---|
| 253 | test_serialization(m); |
|---|
| 254 | |
|---|
| 255 | m.insert(pair_of_ints(3,1)); |
|---|
| 256 | m.insert(pair_of_ints(2,1)); |
|---|
| 257 | test_serialization(m); |
|---|
| 258 | |
|---|
| 259 | m.insert(pair_of_ints(1,1)); |
|---|
| 260 | test_serialization(m); |
|---|
| 261 | |
|---|
| 262 | m.insert(pair_of_ints(0,0)); |
|---|
| 263 | test_serialization(m); |
|---|
| 264 | |
|---|
| 265 | m.insert(pair_of_ints(5,1)); |
|---|
| 266 | m.insert(pair_of_ints(7,1)); |
|---|
| 267 | m.insert(pair_of_ints(6,1)); |
|---|
| 268 | test_serialization(m); |
|---|
| 269 | |
|---|
| 270 | m.insert(pair_of_ints(8,1)); |
|---|
| 271 | m.insert(pair_of_ints(9,1)); |
|---|
| 272 | m.insert(pair_of_ints(12,1)); |
|---|
| 273 | m.insert(pair_of_ints(11,1)); |
|---|
| 274 | m.insert(pair_of_ints(10,1)); |
|---|
| 275 | test_serialization(m); |
|---|
| 276 | } |
|---|
| 277 | test_hashed_index_serialization(); |
|---|
| 278 | } |
|---|