1 : // -*- mode: c++; fill-column: 79 -*-
2 : // $Id: test_writeread.cc 2 2010-04-14 07:34:58Z tb $
3 :
4 : /*
5 : * STX Constant B-Tree Database Template Classes v0.7.0
6 : * Copyright (C) 2010 Timo Bingmann
7 : *
8 : * This library is free software; you can redistribute it and/or modify it
9 : * under the terms of the GNU Lesser General Public License as published by the
10 : * Free Software Foundation; either version 2.1 of the License, or (at your
11 : * option) any later version.
12 : *
13 : * This library is distributed in the hope that it will be useful, but WITHOUT
14 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 : * for more details.
17 : *
18 : * You should have received a copy of the GNU Lesser General Public License
19 : * along with this library; if not, write to the Free Software Foundation,
20 : * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 : */
22 :
23 : /*
24 : * Extensively test Writer, WriterSequential and Reader
25 : * classes. Creates databases using different number of items and
26 : * different key_types. "Stores" databases to stringstreams and reads
27 : * them back using all access functions in Reader.
28 : */
29 :
30 : #define CBTREEDB_SELF_VERIFY
31 : #include "stx-cbtreedb.h"
32 :
33 : #include <iostream>
34 : #include <sstream>
35 : #include <assert.h>
36 :
37 : template <typename cbtreedb>
38 : std::string run_writer(unsigned int items,
39 35 : typename cbtreedb::key_type (*key_mapping)(unsigned int idx, unsigned int items) )
40 : {
41 35 : std::cout << "items " << items << " -> ";
42 :
43 : // write new database using Writer
44 :
45 35 : typename cbtreedb::Writer writer;
46 35 : writer.SetSignature("cbtestdb");
47 :
48 1081410 : for(unsigned int i = 0; i <= items; ++i)
49 : {
50 1081375 : typename cbtreedb::key_type key = key_mapping(i, items);
51 :
52 1081375 : writer.Add(2*key, &key, sizeof(key));
53 : }
54 :
55 35 : assert( writer.Size() == items+1 );
56 :
57 35 : std::ostringstream testdb;
58 35 : writer.Write(testdb);
59 :
60 35 : std::string dbstr = testdb.str();
61 :
62 35 : std::cout << "dbsize " << dbstr.size() << std::endl;
63 :
64 35 : return dbstr;
65 : }
66 :
67 : template <typename cbtreedb>
68 : std::string run_writersequential(unsigned int items,
69 30 : typename cbtreedb::key_type (*key_mapping)(unsigned int idx, unsigned int items) )
70 :
71 : {
72 30 : std::cout << "items " << items << " -> ";
73 :
74 : // write new database using WriterSequential
75 :
76 30 : typename cbtreedb::WriterSequential writer;
77 30 : writer.SetSignature("cbtestdb");
78 :
79 65592 : for(unsigned int i = 0; i <= items; ++i)
80 : {
81 : // phase 1: declare key and datasize mappings.
82 :
83 65562 : typename cbtreedb::key_type key = key_mapping(i, items);
84 :
85 65562 : writer.Add(2*key, sizeof(key));
86 : }
87 :
88 30 : std::ostringstream testdb;
89 :
90 30 : writer.WriteHeader(testdb); // write header and btree
91 :
92 65592 : for(unsigned int i = 0; i <= items; ++i)
93 : {
94 : // phase 2: write value objects
95 :
96 65562 : typename cbtreedb::key_type key = key_mapping(i, items);
97 :
98 65562 : writer.WriteValue(2*key, &key, sizeof(key));
99 : }
100 :
101 30 : assert( writer.Size() == items+1 );
102 :
103 30 : writer.WriteFinalize();
104 :
105 30 : std::string dbstr = testdb.str();
106 :
107 30 : std::cout << "dbsize " << dbstr.size() << std::endl;
108 :
109 30 : return dbstr;
110 : }
111 :
112 : template <typename cbtreedb>
113 : void run_reader(unsigned int items, const std::string& dbstr,
114 65 : typename cbtreedb::key_type (*key_mapping)(unsigned int idx, unsigned int items) )
115 : {
116 65 : typename cbtreedb::Reader reader;
117 65 : reader.SetSignature("cbtestdb");
118 :
119 65 : typename cbtreedb::PageCache cache(128);
120 65 : reader.SetPageCache(&cache);
121 :
122 65 : std::istringstream testdb(dbstr);
123 65 : reader.Open(testdb);
124 :
125 65 : assert( reader.Verify() );
126 :
127 65 : assert( reader.VerifyBTree() ); // these are actually included in Verify().
128 65 : assert( reader.VerifyBTreeChecksum() );
129 65 : assert( reader.VerifyValueChecksum() );
130 :
131 65 : assert( reader.Size() == items+1 );
132 :
133 2293939 : for(unsigned int i = 0; i < 2*items + 2; ++i)
134 : {
135 2293874 : if (i % 2 == 0)
136 1146937 : assert( reader.Exists(i) );
137 : else
138 1146937 : assert( !reader.Exists(i) );
139 : }
140 :
141 2293939 : for(unsigned int i = 0; i < 2*items + 2; ++i)
142 : {
143 2293874 : std::string str;
144 2293874 : assert( reader.Lookup(i, str) || i % 2 == 1 );
145 :
146 2293874 : if ( i % 2 == 0 )
147 1146937 : assert( *reinterpret_cast<const uint32_t*>(str.data()) == static_cast<uint32_t>(i/2) );
148 : else
149 1146937 : assert( str.empty() );
150 :
151 : uint32_t value;
152 2293874 : assert( reader.Lookup(i, &value, sizeof(value)) || i % 2 == 1 );
153 :
154 2293874 : if ( i % 2 == 0 )
155 1146937 : assert( value == i/2 );
156 :
157 2293874 : if ( i % 2 == 0 )
158 : {
159 1146937 : uint32_t i2 = i/2;
160 1146937 : assert( reader[i] == std::string(reinterpret_cast<char*>(&i2), sizeof(i2)) );
161 : }
162 : else
163 : {
164 1146937 : assert( reader[i] == std::string() );
165 : }
166 : }
167 :
168 65 : typename cbtreedb::Reader reader2 = reader;
169 :
170 1147002 : for(unsigned int i = 0; i <= items; ++i)
171 : {
172 : uint32_t key;
173 : uint32_t value;
174 1146937 : std::string outvalue;
175 :
176 1146937 : typename cbtreedb::key_type expectedkey = key_mapping(i,items);
177 :
178 1146937 : assert(reader2.GetIndex(i, key) == 4);
179 1146937 : assert(key == 2 * expectedkey);
180 :
181 1146937 : assert(reader2.GetIndex(i, key, &value, sizeof(value)) == 4);
182 1146937 : assert(key == 2 * expectedkey);
183 1146937 : assert(value == expectedkey);
184 :
185 1146937 : assert(reader2.GetIndex(i, key, outvalue) == 4);
186 1146937 : assert(key == 2 * expectedkey);
187 1146937 : assert(outvalue == std::string(reinterpret_cast<char*>(&expectedkey), sizeof(expectedkey)));
188 : }
189 :
190 65 : reader.Close();
191 65 : }
192 :
193 2228312 : uint32_t key_identity(unsigned int idx, unsigned int)
194 : {
195 2228312 : return idx;
196 : }
197 :
198 131124 : uint32_t key_reverse(unsigned int idx, unsigned int items)
199 : {
200 131124 : return items - idx;
201 : }
202 :
203 1 : int main()
204 : {
205 1 : const unsigned int maxitems = 32768;
206 :
207 1 : std::cout << "Running random writer and reader tests" << std::endl;
208 :
209 21 : for(unsigned int items = 0; items < maxitems * 32; items*=2)
210 : {
211 : typedef stx::CBTreeDB<> cbtreedb;
212 :
213 20 : std::string dbstr = run_writer<cbtreedb>(items, key_identity);
214 :
215 20 : run_reader<cbtreedb>(items, dbstr, key_identity);
216 :
217 20 : if (items < 1) ++items;
218 : }
219 :
220 1 : std::cout << "Running sequential writer and reader tests" << std::endl;
221 :
222 16 : for(unsigned int items = 0; items < maxitems; items*=2)
223 : {
224 : typedef stx::CBTreeDB<> cbtreedb;
225 :
226 15 : std::string dbstr = run_writersequential<cbtreedb>(items, key_identity);
227 :
228 15 : run_reader<cbtreedb>(items, dbstr, key_identity);
229 :
230 15 : if (items < 1) ++items;
231 : }
232 :
233 1 : std::cout << "Running reverse-order random writer and reader tests" << std::endl;
234 :
235 16 : for(unsigned int items = 0; items < maxitems; items*=2)
236 : {
237 : typedef stx::CBTreeDB< uint32_t, std::greater<uint32_t> > cbtreedb;
238 :
239 15 : std::string dbstr = run_writer<cbtreedb>(items, key_identity);
240 :
241 15 : run_reader<cbtreedb>(items, dbstr, key_reverse);
242 :
243 15 : if (items < 1) ++items;
244 : }
245 :
246 1 : std::cout << "Running reverse-order sequential writer and reader tests" << std::endl;
247 :
248 16 : for(unsigned int items = 0; items < maxitems; items*=2)
249 : {
250 : typedef stx::CBTreeDB< uint32_t, std::greater<uint32_t> > cbtreedb;
251 :
252 15 : std::string dbstr = run_writersequential<cbtreedb>(items, key_reverse);
253 :
254 15 : run_reader<cbtreedb>(items, dbstr, key_reverse);
255 :
256 15 : if (items < 1) ++items;
257 : }
258 :
259 1 : return 0;
260 3 : }
|