1#include <sstream>
2#include <string>
3
4#include <marisa/tail.h>
5
6#include "assert.h"
7
8namespace {
9
10void TestBinaryTail() {
11  TEST_START();
12
13  marisa::Tail tail;
14
15  ASSERT(tail.size() == 0);
16  ASSERT(tail.empty());
17  ASSERT(tail.total_size() == sizeof(marisa::UInt32));
18
19  marisa::Vector<marisa::String> keys;
20  tail.build(keys, NULL, MARISA_BINARY_TAIL);
21
22  ASSERT(tail.size() == 0);
23  ASSERT(tail.empty());
24  ASSERT(tail.total_size() == sizeof(marisa::UInt32));
25
26  keys.push_back(marisa::String(""));
27  marisa::Vector<marisa::UInt32> offsets;
28  tail.build(keys, &offsets, MARISA_BINARY_TAIL);
29
30  ASSERT(tail.size() == 1);
31  ASSERT(tail.mode() == MARISA_BINARY_TAIL);
32  ASSERT(!tail.empty());
33  ASSERT(tail.total_size() == (sizeof(marisa::UInt32) + tail.size()));
34  ASSERT(offsets.size() == keys.size() + 1);
35  ASSERT(offsets[0] == 1);
36  ASSERT(offsets[1] == tail.size());
37
38  const char binary_key[] = { 'N', 'P', '\0', 'T', 'r', 'i', 'e' };
39  keys[0] = marisa::String(binary_key, sizeof(binary_key));
40  tail.build(keys, &offsets, MARISA_TEXT_TAIL);
41
42  ASSERT(tail.size() == sizeof(binary_key) + 1);
43  ASSERT(tail.mode() == MARISA_BINARY_TAIL);
44  ASSERT(!tail.empty());
45  ASSERT(tail.total_size() == (sizeof(marisa::UInt32) + tail.size()));
46  ASSERT(offsets.size() == keys.size() + 1);
47  ASSERT(offsets[0] == 1);
48  ASSERT(offsets[1] == tail.size());
49
50  tail.build(keys, &offsets, MARISA_BINARY_TAIL);
51
52  ASSERT(tail.size() == sizeof(binary_key) + 1);
53  ASSERT(tail.mode() == MARISA_BINARY_TAIL);
54  ASSERT(!tail.empty());
55  ASSERT(tail.total_size() == (sizeof(marisa::UInt32) + tail.size()));
56  ASSERT(offsets.size() == keys.size() + 1);
57  ASSERT(offsets[0] == 1);
58  ASSERT(offsets[1] == tail.size());
59
60  keys.clear();
61  keys.push_back(marisa::String("abc"));
62  keys.push_back(marisa::String("bc"));
63  keys.push_back(marisa::String("abc"));
64  keys.push_back(marisa::String("c"));
65  keys.push_back(marisa::String("ABC"));
66  keys.push_back(marisa::String("AB"));
67
68  tail.build(keys, NULL, MARISA_BINARY_TAIL);
69
70  ASSERT(tail.size() == 15);
71  ASSERT(tail.mode() == MARISA_BINARY_TAIL);
72  ASSERT(!tail.empty());
73  ASSERT(tail.total_size() == (sizeof(marisa::UInt32) + tail.size()));
74
75  tail.build(keys, &offsets, MARISA_BINARY_TAIL);
76
77  ASSERT(tail.size() == 15);
78  ASSERT(tail.mode() == MARISA_BINARY_TAIL);
79  ASSERT(!tail.empty());
80  ASSERT(tail.total_size() == (sizeof(marisa::UInt32) + tail.size()));
81  ASSERT(offsets.size() == 7);
82  for (marisa::UInt32 i = 0; i < keys.size(); ++i) {
83    ASSERT(marisa::String(reinterpret_cast<const char *>(tail[offsets[i]]),
84        offsets[i + 1] - offsets[i]) == keys[i]);
85  }
86
87  tail.save("tail-test.dat");
88  tail.clear();
89
90  ASSERT(tail.size() == 0);
91  ASSERT(tail.empty());
92  ASSERT(tail.total_size() == sizeof(marisa::UInt32));
93
94  marisa::Mapper mapper;
95  tail.mmap(&mapper, "tail-test.dat");
96
97  ASSERT(tail.size() == 15);
98  ASSERT(tail.mode() == MARISA_BINARY_TAIL);
99  ASSERT(!tail.empty());
100  ASSERT(tail.total_size() == (sizeof(marisa::UInt32) + tail.size()));
101  for (marisa::UInt32 i = 0; i < keys.size(); ++i) {
102    ASSERT(marisa::String(reinterpret_cast<const char *>(tail[offsets[i]]),
103        offsets[i + 1] - offsets[i]) == keys[i]);
104  }
105
106  tail.clear();
107  tail.load("tail-test.dat");
108
109  ASSERT(tail.size() == 15);
110  ASSERT(tail.mode() == MARISA_BINARY_TAIL);
111  ASSERT(!tail.empty());
112  ASSERT(tail.total_size() == (sizeof(marisa::UInt32) + tail.size()));
113  for (marisa::UInt32 i = 0; i < keys.size(); ++i) {
114    ASSERT(marisa::String(reinterpret_cast<const char *>(tail[offsets[i]]),
115        offsets[i + 1] - offsets[i]) == keys[i]);
116  }
117
118  std::stringstream stream;
119  tail.write(stream);
120
121  tail.clear();
122  tail.read(stream);
123
124  ASSERT(tail.size() == 15);
125  ASSERT(tail.mode() == MARISA_BINARY_TAIL);
126  ASSERT(!tail.empty());
127  ASSERT(tail.total_size() == (sizeof(marisa::UInt32) + tail.size()));
128  for (marisa::UInt32 i = 0; i < keys.size(); ++i) {
129    ASSERT(marisa::String(reinterpret_cast<const char *>(tail[offsets[i]]),
130        offsets[i + 1] - offsets[i]) == keys[i]);
131  }
132
133  TEST_END();
134}
135
136void TestTextTail() {
137  TEST_START();
138
139  marisa::Tail tail;
140  marisa::Vector<marisa::String> keys;
141  tail.build(keys, NULL, MARISA_TEXT_TAIL);
142
143  ASSERT(tail.size() == 0);
144  ASSERT(tail.empty());
145  ASSERT(tail.total_size() == sizeof(marisa::UInt32));
146
147  keys.push_back(marisa::String(""));
148  marisa::Vector<marisa::UInt32> offsets;
149  tail.build(keys, &offsets, MARISA_TEXT_TAIL);
150
151  ASSERT(tail.size() == 2);
152  ASSERT(tail.mode() == MARISA_TEXT_TAIL);
153  ASSERT(!tail.empty());
154  ASSERT(tail.total_size() == (sizeof(marisa::UInt32) + tail.size()));
155  ASSERT(offsets.size() == keys.size());
156  ASSERT(offsets[0] == 1);
157  ASSERT(*tail[offsets[0]] == '\0');
158
159  keys.clear();
160  keys.push_back(marisa::String("abc"));
161  keys.push_back(marisa::String("bc"));
162  keys.push_back(marisa::String("abc"));
163  keys.push_back(marisa::String("c"));
164  keys.push_back(marisa::String("ABC"));
165  keys.push_back(marisa::String("AB"));
166
167  tail.build(keys, NULL, MARISA_TEXT_TAIL);
168
169  ASSERT(tail.size() == 12);
170  ASSERT(tail.mode() == MARISA_TEXT_TAIL);
171  ASSERT(!tail.empty());
172  ASSERT(tail.total_size() == (sizeof(marisa::UInt32) + tail.size()));
173
174  tail.build(keys, &offsets, MARISA_TEXT_TAIL);
175
176  ASSERT(tail.size() == 12);
177  ASSERT(tail.mode() == MARISA_TEXT_TAIL);
178  ASSERT(!tail.empty());
179  ASSERT(tail.total_size() == (sizeof(marisa::UInt32) + tail.size()));
180  ASSERT(offsets.size() == keys.size());
181  for (marisa::UInt32 i = 0; i < keys.size(); ++i) {
182    ASSERT(marisa::String(reinterpret_cast<const char *>(
183        tail[offsets[i]])) == keys[i]);
184  }
185
186  tail.save("tail-test.dat");
187  tail.clear();
188
189  ASSERT(tail.size() == 0);
190  ASSERT(tail.empty());
191  ASSERT(tail.total_size() == sizeof(marisa::UInt32));
192
193  marisa::Mapper mapper;
194  tail.mmap(&mapper, "tail-test.dat");
195
196  ASSERT(tail.size() == 12);
197  ASSERT(tail.mode() == MARISA_TEXT_TAIL);
198  ASSERT(!tail.empty());
199  ASSERT(tail.total_size() == sizeof(marisa::UInt32) + tail.size());
200  for (marisa::UInt32 i = 0; i < keys.size(); ++i) {
201    ASSERT(marisa::String(reinterpret_cast<const char *>(
202        tail[offsets[i]])) == keys[i]);
203  }
204
205  tail.clear();
206  tail.load("tail-test.dat");
207
208  ASSERT(tail.size() == 12);
209  ASSERT(tail.mode() == MARISA_TEXT_TAIL);
210  ASSERT(!tail.empty());
211  ASSERT(tail.total_size() == sizeof(marisa::UInt32) + tail.size());
212  for (marisa::UInt32 i = 0; i < keys.size(); ++i) {
213    ASSERT(marisa::String(reinterpret_cast<const char *>(
214        tail[offsets[i]])) == keys[i]);
215  }
216
217  std::stringstream stream;
218  tail.write(stream);
219
220  tail.clear();
221  tail.read(stream);
222
223  ASSERT(tail.size() == 12);
224  ASSERT(tail.mode() == MARISA_TEXT_TAIL);
225  ASSERT(!tail.empty());
226  ASSERT(tail.total_size() == sizeof(marisa::UInt32) + tail.size());
227  for (marisa::UInt32 i = 0; i < keys.size(); ++i) {
228    ASSERT(marisa::String(reinterpret_cast<const char *>(
229        tail[offsets[i]])) == keys[i]);
230  }
231
232  TEST_END();
233}
234
235}  // namespace
236
237int main() {
238  TestBinaryTail();
239  TestTextTail();
240
241  return 0;
242}
243