root/trunk/whisperlib/common/io/buffer/test/memory_stream_test.cc

Revision 7, 13.0 kB (checked in by whispercastorg, 2 years ago)

version 0.2.0

Line 
1 // Copyright (c) 2009, Whispersoft s.r.l.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Whispersoft s.r.l. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Catalin Popescu
31
32 #include "common/base/types.h"
33 #include "common/base/log.h"
34 #include "common/base/timer.h"
35 #include "common/base/system.h"
36
37 #include "common/io/buffer/memory_stream.h"
38 #include "common/io/num_streaming.h"
39
40 //////////////////////////////////////////////////////////////////////
41
42 DEFINE_int32(rand_seed,
43              0,
44              "Seed the random with this guy");
45
46 //////////////////////////////////////////////////////////////////////
47
48 static unsigned int rand_seed;
49
50 //
51 // This tests MemoryStream, and implicily the data_block.{h,cc} classes
52 //
53
54 void TestPipeStyle(int64 initial_ints,     // we write initially these many ints
55                    int64 num_ints,         // then we r/w these ints
56                    int64 final_ints,       // we read finally these many ints
57                    int32 min_write_size,   // in pieces of size
58                                            // between these limits
59                    int32 max_write_size) {
60   CHECK_GT(max_write_size, min_write_size);
61   int32* buffer = new int32[max_write_size];
62   int32 last_num_read = 0;
63   int32 last_num_write = 0;
64   io::MemoryStream stream;
65   int64 cb = 0;
66   int64 expected_size = 0;
67   const int64 total_ints = num_ints + initial_ints + final_ints;
68   while ( cb < total_ints ) {
69     const int32 crt_ints = (min_write_size +
70                             random() % (max_write_size - min_write_size));
71     const int32 op = random() % 2;
72     if ( (op || cb < initial_ints) && cb < num_ints + initial_ints ) {
73       // write operation
74       for ( int i = 0; i < crt_ints; ++i ) {
75         buffer[i] = last_num_write;
76         last_num_write++;
77       }
78       LOG(10) << "Writing " << crt_ints
79               << " from: " << buffer[0] << " to " << buffer[crt_ints-1];
80       const int32 cbwrite = stream.Write(buffer, crt_ints * sizeof(*buffer));
81       CHECK_EQ(cbwrite, crt_ints * sizeof(*buffer));
82       expected_size += crt_ints * sizeof(*buffer);
83     } else {
84       // read operation
85       CHECK_EQ(stream.Size(), expected_size);
86       const int32 cbread = stream.Read(buffer, crt_ints * sizeof(*buffer));
87       const int32 ints_read = cbread / sizeof(*buffer);
88       LOG(10) << "Read " << crt_ints << " got " << cbread
89               << " (" << ints_read << ") "
90               << " from: " << buffer[0] << " to " << buffer[ints_read-1];
91       CHECK_EQ(cbread, min(static_cast<int64>(sizeof(*buffer) * crt_ints),
92                            expected_size));
93       expected_size -= cbread;
94       CHECK_EQ(stream.Size(), expected_size);
95       for ( int i = 0; i < ints_read; ++i ) {
96         CHECK_EQ(last_num_read, buffer[i]);
97         last_num_read++;
98       }
99     }
100     cb += crt_ints;
101   }
102 }
103
104 //////////////////////////////////////////////////////////////////////
105
106 int32 GenerateRecord(io::MemoryStream* buf,
107                      int32* out_buf,
108                      int32 left_ints,
109                      int32 max_add_record_size) {
110   const int32 rec_size = min(
111       left_ints,
112       static_cast<int32>(rand_r(&rand_seed) %
113                          (max_add_record_size / sizeof(int32))));
114   LOG(10) << " Generating a record of " << rec_size << " int32.";
115   int32* p = out_buf;
116   for ( int32 i = 0; i < rec_size; ++i ) {
117     *p++ = rand_r(&rand_seed);
118   }
119   buf->Write(out_buf, rec_size * sizeof(*p));
120   return rec_size;
121 }
122
123 void CheckRecords(io::MemoryStream* buf,
124                   int32* check_buf,
125                   int32 left_ints,
126                   int32 max_read_record_size) {
127   buf->MarkerSet();
128   int32* p = check_buf;
129   while ( left_ints > 0 ) {
130     const int32 rec_size = min(
131         left_ints,
132         static_cast<int32>(rand_r(&rand_seed) % (max_read_record_size /
133                                      sizeof(*check_buf))));
134     LOG(10) << " Checking a record of " << rec_size << " int32.";
135     const int32 size = rec_size * sizeof(*check_buf);
136     string s;
137     buf->ReadString(&s, size);
138     CHECK_EQ(s.size(), size);
139     CHECK(!memcmp(s.data(), p, size));
140     p += rec_size;
141     left_ints -= rec_size;
142   }
143   buf->MarkerRestore();
144 }
145
146 void TestRandomAppends(bool mix_operations,
147                        int32 block_size1,
148                        int32 block_size2,
149                        int32 total_size,
150                        int32 max_add_record_size,
151                        int32 max_append_record_size,
152                        int32 max_read_record_size) {
153   int32 num_ints = total_size / sizeof(int32);
154   int32* out_buf = new int32[num_ints];
155   int32* p = out_buf;
156   io::MemoryStream buf1(common::kByteOrder, block_size1);
157   io::MemoryStream buf2(common::kByteOrder, block_size2);
158
159   LOG_INFO << "Generating buffers... ";
160   int32 size = 0;
161   int32 expected_size  = 0;
162   while ( num_ints > size ) {
163     if ( mix_operations && ((rand_r(&rand_seed) % 5) == 0) ) {
164       while ( buf1.Size() > 0 ) {
165         const int32 rec_size = min(buf1.Size(),
166                                    rand_r(&rand_seed) % max_append_record_size);
167         expected_size += rec_size;
168         buf2.AppendStream(&buf1, rec_size);
169         CHECK_EQ(buf2.Size(), expected_size)
170             << " Got: " << buf2.DetailedContent();
171       }
172     } else {
173       const int32 written = GenerateRecord(&buf1, p, num_ints - size,
174                                            max_add_record_size);
175       p += written;
176       size += written;
177     }
178   }
179
180   if ( !mix_operations ) {
181     LOG_INFO << "First check buf1... ";
182     CHECK_EQ(num_ints * sizeof(*out_buf), buf1.Size());
183     CheckRecords(&buf1, out_buf, num_ints, max_read_record_size);
184   }
185   LOG_INFO << "Appending... ";
186   buf1.MarkerSet();
187   while ( buf1.Size() > 0 ) {
188     const int32 rec_size = min(buf1.Size(),
189                                rand_r(&rand_seed) % max_append_record_size);
190     expected_size += rec_size;
191     buf2.AppendStream(&buf1, rec_size);
192     CHECK_EQ(buf2.Size(), expected_size)
193         << " Got: " << buf2.DetailedContent();
194   }
195   buf1.MarkerRestore();
196
197   if ( !mix_operations ) {
198     LOG_INFO << "Second check buf1... ";
199     CheckRecords(&buf2, out_buf, num_ints, max_read_record_size);
200     CHECK_EQ(num_ints * sizeof(*out_buf), buf1.Size());
201   }
202   LOG_INFO << "First check buf2... ";
203   CHECK_EQ(num_ints * sizeof(*out_buf), buf2.Size());
204   CheckRecords(&buf2, out_buf, num_ints, max_read_record_size);
205   delete[] out_buf;
206 }
207
208 //////////////////////////////////////////////////////////////////////
209
210 int main(int argc, char* argv[]) {
211   common::Init(argc, argv);
212   rand_seed = FLAGS_rand_seed;
213   if ( FLAGS_rand_seed > 0 ) {
214     srand(FLAGS_rand_seed);
215   }
216   LOG_INFO << "Test number BIGENDIAN";
217   io::MemoryStream ms0(common::BIGENDIAN);
218   io::NumStreamer::WriteByte(&ms0, 0xab);
219   CHECK_EQ(io::NumStreamer::ReadByte(&ms0), 0xab);
220   io::NumStreamer::WriteInt16(&ms0, 0xabcd);
221   io::NumStreamer::WriteUInt24(&ms0, 0x1234abcd);
222   io::NumStreamer::WriteInt32(&ms0, 0x12345678);
223   io::NumStreamer::WriteInt64(&ms0, 0x123456789abcdfULL);
224   io::NumStreamer::WriteFloat(&ms0, 1.23456789);
225   io::NumStreamer::WriteDouble(&ms0, 0.987654321);
226
227   CHECK_EQ(io::NumStreamer::ReadInt16(&ms0), int16(0xabcd));
228   CHECK_EQ(io::NumStreamer::ReadUInt24(&ms0), 0x34abcd);
229   CHECK_EQ(io::NumStreamer::ReadInt32(&ms0), 0x12345678);
230   CHECK_EQ(io::NumStreamer::ReadInt64(&ms0), 0x123456789abcdfULL);
231   CHECK_EQ(io::NumStreamer::ReadFloat(&ms0), static_cast<float>(1.23456789));
232   CHECK_EQ(io::NumStreamer::ReadDouble(&ms0), 0.987654321);
233
234   LOG_INFO << "Test number LILENDIAN";
235   io::MemoryStream ms1(common::LILENDIAN);
236
237   io::NumStreamer::WriteByte(&ms1, 0xab);
238   io::NumStreamer::WriteInt16(&ms1, 0xabcd);
239   io::NumStreamer::WriteUInt24(&ms0, 0x1234abcd);
240   io::NumStreamer::WriteInt32(&ms1, 0x12345678);
241   io::NumStreamer::WriteInt64(&ms1, 0x123456789abcdfULL);
242   io::NumStreamer::WriteDouble(&ms1, 0.987654321);
243   io::NumStreamer::WriteFloat(&ms1, 1.23456789);
244
245   CHECK_EQ(io::NumStreamer::ReadByte(&ms1), 0xab);
246   CHECK_EQ(io::NumStreamer::ReadInt16(&ms1), int16(0xabcd));
247   CHECK_EQ(io::NumStreamer::ReadUInt24(&ms0), 0x34abcd);
248   CHECK_EQ(io::NumStreamer::ReadInt32(&ms1), 0x12345678);
249   CHECK_EQ(io::NumStreamer::ReadInt64(&ms1), 0x123456789abcdfULL);
250   CHECK_EQ(io::NumStreamer::ReadDouble(&ms1), 0.987654321);
251   CHECK_EQ(io::NumStreamer::ReadFloat(&ms1), static_cast<float>(1.23456789));
252
253   {
254     io::MemoryStream a, b;
255     a.Write("abcdefg");
256     a.Write("123456");
257     b.AppendStreamNonDestructive(&a);
258     string s1, s2;
259     a.ReadString(&s1);
260     CHECK_EQ(s1, "abcdefg123456") << " found: " << s1;
261     b.ReadString(&s2);
262     CHECK_EQ(b.Size(), 0);
263     CHECK_EQ(s2, "abcdefg123456") << " Checking: [" << s2 << "]";
264
265     a.Write("abcdefg");
266     a.Write("123456");
267     b.AppendStreamNonDestructive(&a, 6);
268     b.ReadString(&s2);
269     CHECK_EQ(s2, "abcdef") << " found: " << s2;
270     a.Skip(7);
271     b.AppendStreamNonDestructive(&a, 6);
272     a.ReadString(&s1);
273     b.ReadString(&s2);
274     CHECK_EQ(s1, "123456") << " found: " << s1;
275     CHECK_EQ(s2, "123456") << " found: " << s2;
276   }
277
278   {
279     io::MemoryStream a(common::BIGENDIAN, 12);
280     a.Write("1234567890\r\n"
281             "abcdef\r\n"
282             "123456789012345\r\n"
283             "abcdefg\r\n"
284             "\r\n"
285             "abcd");
286     string s;
287     CHECK(a.ReadCRLFLine(&s));
288     CHECK_EQ(s, "1234567890\r\n") << " Found: [" << s << "]";
289     CHECK(a.ReadCRLFLine(&s));
290     CHECK_EQ(s, "abcdef\r\n");
291     CHECK(a.ReadCRLFLine(&s));
292     CHECK_EQ(s, "123456789012345\r\n");
293     CHECK(a.ReadCRLFLine(&s));
294     CHECK_EQ(s, "abcdefg\r\n");
295     CHECK(a.ReadCRLFLine(&s));
296     CHECK_EQ(s, "\r\n");
297     CHECK(!a.ReadCRLFLine(&s));
298   }
299   LOG_INFO << "Test Tokens";
300   {
301     io::MemoryStream a(common::BIGENDIAN, 12);
302     a.Write("{ ala bala \"porto'ca\\nla}\" xbuc'  \n  \\t' *");
303     string s;
304     CHECK_EQ(a.ReadNextAsciiToken(&s), io::TOKEN_SEP_OK);
305     CHECK_EQ(s, "{");
306     CHECK_EQ(a.ReadNextAsciiToken(&s), io::TOKEN_OK);
307     CHECK_EQ(s, "ala");
308     CHECK_EQ(a.ReadNextAsciiToken(&s), io::TOKEN_OK);
309     CHECK_EQ(s, "bala");
310     CHECK_EQ(a.ReadNextAsciiToken(&s), io::TOKEN_QUOTED_OK);
311     CHECK_EQ(s, "\"porto'ca\\nla}\"");
312     CHECK_EQ(a.ReadNextAsciiToken(&s), io::TOKEN_OK);
313     CHECK_EQ(s, "xbuc");
314     CHECK_EQ(a.ReadNextAsciiToken(&s), io::TOKEN_QUOTED_OK);
315     CHECK_EQ(s, "'  \n  \\t'");
316     CHECK_EQ(a.ReadNextAsciiToken(&s), io::TOKEN_SEP_OK);
317     CHECK_EQ(s, "*");
318     CHECK_EQ(a.ReadNextAsciiToken(&s), io::TOKEN_NO_DATA);
319   }
320
321   LOG_INFO << "TestRandomAppends /false/1";
322   TestRandomAppends(false, 16384, 16384, 10000000, 2048, 2048, 2048);
323   LOG_INFO << "TestRandomAppends /false/2";
324   TestRandomAppends(false, 1627, 2591, 10000000, 4663, 5303, 3943);
325   LOG_INFO << "TestRandomAppends /false/3";
326   TestRandomAppends(false, 5303, 3943, 100000000, 1627, 2591, 5333);
327   LOG_INFO << "TestRandomAppends /false/4";
328   TestRandomAppends(false, 16384, 12000, 10000000, 128, 160, 256);
329
330   LOG_INFO << "TestRandomAppends /true/1";
331   TestRandomAppends(true, 16384, 16384, 10000000, 2048, 2048, 2048);
332   LOG_INFO << "TestRandomAppends /true/2";
333   TestRandomAppends(true, 1627, 2591, 10000000, 4663, 5303, 3943);
334   LOG_INFO << "TestRandomAppends /true/3";
335   TestRandomAppends(true, 5303, 3943, 10000000, 1627, 2591, 5333);
336   LOG_INFO << "TestRandomAppends /true/4";
337   TestRandomAppends(true, 16384, 12000, 10000000, 128, 160, 256);
338
339   LOG_INFO << "Test 0";
340   const int two_block_plus3 = 4096 * 2 + 3;
341   TestPipeStyle(two_block_plus3, 0, two_block_plus3,
342                 two_block_plus3, two_block_plus3 + 1);
343
344   LOG_INFO << "Test 1";
345   TestPipeStyle(600, 0, 600, 100, 300);
346   LOG_INFO << "Test 2";
347   TestPipeStyle(10000, 10000000, 5000, 100, 300);
348   LOG_INFO << "Test 3";
349   TestPipeStyle(0, 100000000, 5000, 500, 1000);
350   LOG_INFO << "Test 4";
351   // TestPipeStyle(10000, 1000000000, 5000, 1, 1000);
352   LOG_INFO << "PASS";
353   common::Exit(0);
354 }
Note: See TracBrowser for help on using the browser.