1 /*
2 * Copyright (C) 2009 Tommi Maekitalo
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
11 * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
12 * NON-INFRINGEMENT. See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 */
19
20 #include <cstring>
21 #include <iostream>
22 #include <sstream>
23 #include <memory>
24 #include <stdexcept>
25
26 #ifdef _WIN32
27 #include <windows.h>
28 #include <fcntl.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <io.h>
32 #include <fileapi.h>
33 #endif
34
35 #include "gtest/gtest.h"
36
37 #include "../src/buffer.h"
38 #include "../src/_dirent.h"
39 #include "../src/writer/_dirent.h"
40
41 #include "tools.h"
42
43 namespace
44 {
45
46 using zim::unittests::TempFile;
47 using zim::unittests::write_to_buffer;
48
writenDirentSize(const zim::writer::Dirent & dirent)49 size_t writenDirentSize(const zim::writer::Dirent& dirent)
50 {
51 TempFile tmpFile("test_dirent");
52 const auto tmp_fd = tmpFile.fd();
53 dirent.write(tmp_fd);
54 auto size = lseek(tmp_fd, 0, SEEK_END);
55 return size;
56 }
57
TEST(DirentTest,set_get_data_dirent)58 TEST(DirentTest, set_get_data_dirent)
59 {
60 zim::Dirent dirent;
61 dirent.setUrl('A', "Bar");
62 dirent.setArticle(17, zim::cluster_index_t(45), zim::blob_index_t(1234));
63 dirent.setVersion(54346);
64
65 ASSERT_TRUE(!dirent.isRedirect());
66 ASSERT_EQ(dirent.getNamespace(), 'A');
67 ASSERT_EQ(dirent.getUrl(), "Bar");
68 ASSERT_EQ(dirent.getTitle(), "Bar");
69 ASSERT_EQ(dirent.getParameter(), "");
70 ASSERT_EQ(dirent.getClusterNumber().v, 45U);
71 ASSERT_EQ(dirent.getBlobNumber().v, 1234U);
72 ASSERT_EQ(dirent.getVersion(), 54346U);
73
74 dirent.setTitle("Foo");
75 ASSERT_EQ(dirent.getNamespace(), 'A');
76 ASSERT_EQ(dirent.getUrl(), "Bar");
77 ASSERT_EQ(dirent.getTitle(), "Foo");
78 ASSERT_EQ(dirent.getParameter(), "");
79 }
80
TEST(DirentTest,read_write_article_dirent)81 TEST(DirentTest, read_write_article_dirent)
82 {
83 zim::writer::Dirent dirent;
84 dirent.setUrl(zim::writer::Url('A', "Bar"));
85 dirent.setTitle("Foo");
86 dirent.setArticle(17, zim::cluster_index_t(45), zim::blob_index_t(1234));
87
88 ASSERT_TRUE(!dirent.isRedirect());
89 ASSERT_EQ(dirent.getNamespace(), 'A');
90 ASSERT_EQ(dirent.getUrl(), "Bar");
91 ASSERT_EQ(dirent.getTitle(), "Foo");
92 ASSERT_EQ(dirent.getClusterNumber().v, 45U);
93 ASSERT_EQ(dirent.getBlobNumber().v, 1234U);
94 ASSERT_EQ(dirent.getVersion(), 0U);
95
96 auto buffer = write_to_buffer(dirent);
97 zim::Dirent dirent2(buffer);
98
99 ASSERT_TRUE(!dirent2.isRedirect());
100 ASSERT_EQ(dirent2.getNamespace(), 'A');
101 ASSERT_EQ(dirent2.getTitle(), "Foo");
102 ASSERT_EQ(dirent2.getParameter(), "");
103 ASSERT_EQ(dirent2.getClusterNumber().v, 45U);
104 ASSERT_EQ(dirent2.getBlobNumber().v, 1234U);
105 ASSERT_EQ(dirent2.getVersion(), 0U);
106 }
107
TEST(DirentTest,read_write_article_dirent_unicode)108 TEST(DirentTest, read_write_article_dirent_unicode)
109 {
110 zim::writer::Dirent dirent;
111 dirent.setUrl(zim::writer::Url('A', "L\xc3\xbcliang"));
112 dirent.setArticle(17, zim::cluster_index_t(45), zim::blob_index_t(1234));
113
114 ASSERT_TRUE(!dirent.isRedirect());
115 ASSERT_EQ(dirent.getNamespace(), 'A');
116 ASSERT_EQ(dirent.getUrl(), "L\xc3\xbcliang");
117 ASSERT_EQ(dirent.getTitle(), "L\xc3\xbcliang");
118 ASSERT_EQ(dirent.getClusterNumber().v, 45U);
119 ASSERT_EQ(dirent.getBlobNumber().v, 1234U);
120
121 auto buffer = write_to_buffer(dirent);
122 zim::Dirent dirent2(buffer);
123
124 ASSERT_TRUE(!dirent2.isRedirect());
125 ASSERT_EQ(dirent2.getNamespace(), 'A');
126 ASSERT_EQ(dirent2.getUrl(), "L\xc3\xbcliang");
127 ASSERT_EQ(dirent2.getTitle(), "L\xc3\xbcliang");
128 ASSERT_EQ(dirent2.getParameter(), "");
129 ASSERT_EQ(dirent2.getClusterNumber().v, 45U);
130 ASSERT_EQ(dirent2.getBlobNumber().v, 1234U);
131 }
132
TEST(DirentTest,read_write_redirect_dirent)133 TEST(DirentTest, read_write_redirect_dirent)
134 {
135 zim::writer::Dirent targetDirent;
136 targetDirent.setIdx(zim::article_index_t(321));
137 zim::writer::Dirent dirent;
138 dirent.setUrl(zim::writer::Url('A', "Bar"));
139 dirent.setRedirect(&targetDirent);
140
141 ASSERT_TRUE(dirent.isRedirect());
142 ASSERT_EQ(dirent.getNamespace(), 'A');
143 ASSERT_EQ(dirent.getUrl(), "Bar");
144 ASSERT_EQ(dirent.getRedirectIndex().v, 321U);
145
146 auto buffer = write_to_buffer(dirent);
147 zim::Dirent dirent2(buffer);
148
149 ASSERT_TRUE(dirent2.isRedirect());
150 ASSERT_EQ(dirent2.getNamespace(), 'A');
151 ASSERT_EQ(dirent2.getUrl(), "Bar");
152 ASSERT_EQ(dirent2.getTitle(), "Bar");
153 ASSERT_EQ(dirent2.getRedirectIndex().v, 321U);
154 }
155
TEST(DirentTest,read_write_linktarget_dirent)156 TEST(DirentTest, read_write_linktarget_dirent)
157 {
158 zim::writer::Dirent dirent;
159 dirent.setUrl(zim::writer::Url('A', "Bar"));
160 dirent.setLinktarget();
161
162 ASSERT_TRUE(!dirent.isRedirect());
163 ASSERT_TRUE(dirent.isLinktarget());
164 ASSERT_TRUE(!dirent.isDeleted());
165 ASSERT_EQ(dirent.getNamespace(), 'A');
166 ASSERT_EQ(dirent.getUrl(), "Bar");
167
168 auto buffer = write_to_buffer(dirent);
169 zim::Dirent dirent2(buffer);
170
171 ASSERT_TRUE(!dirent2.isRedirect());
172 ASSERT_TRUE(dirent2.isLinktarget());
173 ASSERT_TRUE(!dirent2.isDeleted());
174 ASSERT_EQ(dirent2.getNamespace(), 'A');
175 ASSERT_EQ(dirent2.getUrl(), "Bar");
176 ASSERT_EQ(dirent2.getTitle(), "Bar");
177 }
178
TEST(DirentTest,read_write_deleted_dirent)179 TEST(DirentTest, read_write_deleted_dirent)
180 {
181 zim::writer::Dirent dirent;
182 dirent.setUrl(zim::writer::Url('A', "Bar"));
183 dirent.setDeleted();
184
185 ASSERT_TRUE(!dirent.isRedirect());
186 ASSERT_TRUE(!dirent.isLinktarget());
187 ASSERT_TRUE(dirent.isDeleted());
188 ASSERT_EQ(dirent.getNamespace(), 'A');
189 ASSERT_EQ(dirent.getUrl(), "Bar");
190
191 auto buffer = write_to_buffer(dirent);
192 zim::Dirent dirent2(buffer);
193
194 ASSERT_TRUE(!dirent2.isRedirect());
195 ASSERT_TRUE(!dirent2.isLinktarget());
196 ASSERT_TRUE(dirent2.isDeleted());
197 ASSERT_EQ(dirent2.getNamespace(), 'A');
198 ASSERT_EQ(dirent2.getUrl(), "Bar");
199 ASSERT_EQ(dirent2.getTitle(), "Bar");
200 }
201
TEST(DirentTest,dirent_size)202 TEST(DirentTest, dirent_size)
203 {
204 zim::writer::Dirent dirent;
205 std::string s;
206 dirent.setArticle(17, zim::cluster_index_t(45), zim::blob_index_t(1234));
207 dirent.setUrl(zim::writer::Url('A', "Bar"));
208
209 // case url set, title empty, extralen empty
210 ASSERT_EQ(dirent.getDirentSize(), writenDirentSize(dirent));
211
212 // case url set, title set, extralen empty
213 dirent.setTitle("Foo");
214 ASSERT_EQ(dirent.getDirentSize(), writenDirentSize(dirent));
215
216 // case url set, title empty
217 dirent.setTitle(std::string());
218 ASSERT_EQ(dirent.getDirentSize(), writenDirentSize(dirent));
219 }
220
TEST(DirentTest,redirect_dirent_size)221 TEST(DirentTest, redirect_dirent_size)
222 {
223 zim::writer::Dirent targetDirent;
224 targetDirent.setIdx(zim::article_index_t(321));
225 zim::writer::Dirent dirent;
226 dirent.setUrl(zim::writer::Url('A', "Bar"));
227 dirent.setRedirect(&targetDirent);
228
229 ASSERT_EQ(dirent.getDirentSize(), writenDirentSize(dirent));
230 }
231
232 } // namespace
233