Line data Source code
1 : /*
2 : * (C) Copyright 2010 Marek Dopiera
3 : *
4 : * This file is part of CoherentDB.
5 : *
6 : * CoherentDB is free software: you can redistribute it and/or modify it
7 : * under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation, either version 3 of the License, or
9 : * (at your option) any later version.
10 : *
11 : * CoherentDB is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public
17 : * License along with CoherentDB. If not, see
18 : * http://www.gnu.org/licenses/.
19 : */
20 :
21 : #include <cstring>
22 : #include <cstdlib>
23 :
24 : #include <util/multi_buffer.h>
25 : #include <config/config.h>
26 : #include <debug/asserts.h>
27 : #include <log/log.h>
28 :
29 : namespace coherent {
30 : namespace util {
31 : namespace unittests {
32 :
33 : using namespace log4cxx;
34 : using namespace coherent::config;
35 : using namespace coherent::log;
36 :
37 : static uint32_t const buf_size = 32000;
38 :
39 : struct test_pattern
40 : {
41 1 : test_pattern() : buf(new char[buf_size])
42 : {
43 32001 : for (uint32_t i = 0; i < buf_size; ++i)
44 32000 : buf[i] = random();
45 1 : }
46 :
47 21 : test_pattern(test_pattern const & o) : buf(new char[buf_size])
48 : {
49 21 : memcpy(this->buf, o.buf, buf_size);
50 21 : }
51 :
52 22 : ~test_pattern()
53 : {
54 22 : delete[] buf;
55 22 : }
56 :
57 : char * buf;
58 : };
59 :
60 1 : test_pattern pattern;
61 :
62 2142 : static void check_buffers(char const * b1, char const * b2, uint32_t size)
63 : {
64 17524428 : for (uint32_t i = 0; i < size; ++i)
65 : r_assert(
66 : b1[i] == b2[i],
67 : "mismatch at byte " << i << " expected " << static_cast<int>(b1[i])
68 : << " but got " << static_cast<int>(b2[i])
69 : );
70 2142 : }
71 :
72 21 : void single_test(uint32_t left_off)
73 : {
74 21 : uint32_t cur_off = left_off;
75 42 : multi_buffer::buffer_list bufs;
76 21 : uint32_t total_size = 0;
77 :
78 42 : test_pattern pattern_save(pattern);
79 :
80 4455 : while (true) {
81 4476 : uint32_t const size = random() % 300 + 1;
82 4476 : if (cur_off + size > buf_size)
83 : break;
84 4455 : if (cur_off == left_off) {
85 : //first frame
86 42 : multi_buffer::buffer_ptr buf(new buffer(size + left_off));
87 21 : memcpy(buf->get_data(), pattern.buf, size + left_off);
88 21 : bufs.push_back(buf);
89 : LOG(TRACE, "Added buffer off=0" << " size=" << size + left_off);
90 : }
91 : else
92 : {
93 8868 : multi_buffer::buffer_ptr buf(new buffer(size));
94 4434 : memcpy(buf->get_data(), pattern.buf + cur_off, size);
95 4434 : bufs.push_back(buf);
96 : LOG(TRACE, "Added buffer off=" << cur_off << " size=" << size);
97 : }
98 4455 : total_size += size;
99 4455 : cur_off += size;
100 : }
101 : LOG(TRACE, "left_off=" << left_off << ", total_size=" << total_size <<
102 : " cur_off=" << cur_off
103 : );
104 42 : multi_buffer mbuf(bufs, total_size, left_off);
105 42 : multi_buffer mbuf2(mbuf);
106 :
107 : //read whole mbuf
108 : {
109 21 : char tmp[total_size];
110 21 : mbuf.read(tmp, total_size, 0);
111 21 : check_buffers(pattern.buf + left_off, tmp, total_size);
112 : }
113 :
114 4221 : for (uint32_t i = 0; i < 200; ++i)
115 : {
116 4200 : uint32_t const start = random() % total_size + 1;
117 4200 : uint32_t const size = (i == 100) ? 0 : (random() % (total_size - start));
118 :
119 4200 : char buf[size];
120 4200 : if (i % 2) {
121 16500953 : for (uint32_t i = 0; i < size; ++i)
122 16498853 : pattern.buf[i+left_off + start] = buf[i] = random();
123 2100 : mbuf.write(buf, size, start);
124 : }
125 : else
126 : {
127 2100 : mbuf.read(buf, size, start);
128 2100 : check_buffers(pattern.buf + left_off + start, buf, size);
129 : }
130 :
131 : }
132 : {
133 : //verify c-o-w
134 21 : char tmp[total_size];
135 21 : mbuf2.read(tmp, total_size, 0);
136 21 : check_buffers(pattern_save.buf + left_off, tmp, total_size);
137 : }
138 21 : }
139 1 : int start_test(const int argc, const char *const *const argv)
140 : {
141 2 : scoped_test_enabler test_setup(argc, argv);
142 :
143 1 : Logger::getLogger("coherent.util")->setLevel(log_TRACE);
144 :
145 1 : single_test(0);
146 21 : for (uint32_t i = 0; i < 20; ++i)
147 20 : single_test(random() % 100 + 1);
148 :
149 1 : return 0;
150 : }
151 :
152 : } // namespace unittests
153 : } // namespace util
154 : } // namespace coherent
155 :
156 1 : int main(const int argc, const char * const * const argv)
157 : {
158 1 : return coherent::util::unittests::start_test(argc, argv);
159 3 : }
|