Line data Source code
1 : ///
2 : /// @file ar/internal/extractor_tests.cpp
3 : /// @copyright (c) 2015 by Petr Zemek (s3rvac@gmail.com) and contributors
4 : /// @license MIT, see the @c LICENSE file for more details
5 : /// @brief Tests for the @c extractor module.
6 : ///
7 :
8 : #include <gtest/gtest.h>
9 :
10 : #include "ar/exceptions.h"
11 : #include "ar/extraction.h"
12 : #include "ar/file.h"
13 : #include "ar/internal/extractor.h"
14 :
15 : using namespace std::literals::string_literals;
16 :
17 : namespace ar {
18 : namespace internal {
19 : namespace tests {
20 :
21 : ///
22 : /// Base class for Extractor tests.
23 : ///
24 34 : class BaseExtractorTests: public testing::Test {
25 : protected:
26 : static Files extractArchiveWithContent(
27 : const std::string& content);
28 : };
29 :
30 : ///
31 : /// A helper method to make the extraction more readable in tests.
32 : ///
33 17 : Files BaseExtractorTests::extractArchiveWithContent(
34 : const std::string& content) {
35 34 : Extractor extractor;
36 21 : return extractor.extract(content);
37 : }
38 :
39 : ///
40 : /// Common extraction tests for all formats.
41 : ///
42 4 : class CommonExtractionTests: public BaseExtractorTests {};
43 :
44 5 : TEST_F(CommonExtractionTests,
45 : ExtractReturnsEmptyContainerForEmptyArchive) {
46 : auto files = extractArchiveWithContent(
47 : "!<arch>\n"s
48 2 : );
49 :
50 1 : ASSERT_TRUE(files.empty());
51 : }
52 :
53 5 : TEST_F(CommonExtractionTests,
54 : ExtractThrowsInvalidArchiveErrorWhenMagicStringIsNotPresent) {
55 2 : ASSERT_THROW(
56 : extractArchiveWithContent(""),
57 : InvalidArchiveError
58 1 : );
59 : }
60 :
61 : ///
62 : /// Tests for extraction of GNU archives.
63 : ///
64 30 : class GNUArchiveTests: public BaseExtractorTests {};
65 :
66 5 : TEST_F(GNUArchiveTests,
67 : ExtractReturnsSingletonContainerForArchiveWithSingleFile) {
68 : auto files = extractArchiveWithContent(
69 2 : "!<arch>\n"s +
70 4 : "test.txt/ 0 0 0 644 20 `\n"s +
71 : "contents of test.txt"s
72 2 : );
73 :
74 1 : ASSERT_EQ(1, files.size());
75 1 : auto& file = files.front();
76 1 : ASSERT_EQ("test.txt", file->getName());
77 1 : ASSERT_EQ("contents of test.txt", file->getContent());
78 : }
79 :
80 5 : TEST_F(GNUArchiveTests,
81 : ExtractReturnsSingletonContainerForArchiveWithLookupTableAndSingleFile) {
82 : auto files = extractArchiveWithContent(
83 2 : "!<arch>\n"s +
84 4 : "/ 0 0 0 0 14 `\n"s +
85 4 : "\x00\x00\x00\x10\x00\x00\x00\x52""func1\x00"s +
86 4 : "mod1.o/ 0 0 0 644 18 `\n"s +
87 : "contents of mod1.o"s
88 2 : );
89 :
90 1 : ASSERT_EQ(1, files.size());
91 1 : auto& file = files.front();
92 1 : ASSERT_EQ("mod1.o", file->getName());
93 1 : ASSERT_EQ("contents of mod1.o", file->getContent());
94 : }
95 :
96 5 : TEST_F(GNUArchiveTests,
97 : ExtractReturnsSingletonContainerForArchiveWithFileNameTableAndSingleFile) {
98 : auto files = extractArchiveWithContent(
99 2 : "!<arch>\n"s +
100 4 : "// 42 `\n"s +
101 4 : "very_long_name_of_a_module_in_archive.o/\n"s +
102 : "\n"
103 4 : "/0 0 0 0 644 22 `\n"s +
104 : "contents of the module"s
105 2 : );
106 :
107 1 : ASSERT_EQ(1, files.size());
108 1 : auto& file = files.front();
109 1 : ASSERT_EQ("very_long_name_of_a_module_in_archive.o", file->getName());
110 1 : ASSERT_EQ("contents of the module", file->getContent());
111 : }
112 :
113 5 : TEST_F(GNUArchiveTests,
114 : ExtractThrowsInvalidArchiveErrorWhenFileNameIsNotEndedWithSlash) {
115 2 : ASSERT_THROW(
116 : extractArchiveWithContent(
117 : "!<arch>\n"s +
118 : "test.txt"s
119 : ),
120 : InvalidArchiveError
121 1 : );
122 : }
123 :
124 5 : TEST_F(GNUArchiveTests,
125 : ExtractThrowsInvalidArchiveErrorWhenFileNameIsEmpty) {
126 2 : ASSERT_THROW(
127 : extractArchiveWithContent(
128 : "!<arch>\n"s +
129 : // The first '/' denotes a symbol table, the second '/' is a file
130 : // with an empty name.
131 : "/ 0 0 0 644 0 `\n"s +
132 : "/ 0 0 0 644 0 `\n"s
133 : ),
134 : InvalidArchiveError
135 1 : );
136 : }
137 :
138 5 : TEST_F(GNUArchiveTests,
139 : ExtractThrowsInvalidArchiveErrorWhenFileSizeIsMissing) {
140 2 : ASSERT_THROW(
141 : extractArchiveWithContent(
142 : "!<arch>\n"s +
143 : "test.txt/ 0 0 0 644"s
144 : ),
145 : InvalidArchiveError
146 1 : );
147 : }
148 :
149 5 : TEST_F(GNUArchiveTests,
150 : ExtractThrowsInvalidArchiveErrorWhenFileHeaderEndIsMissing) {
151 2 : ASSERT_THROW(
152 : extractArchiveWithContent(
153 : "!<arch>\n"s +
154 : "test.txt/ 0 0 0 644 20\n"s
155 : ),
156 : InvalidArchiveError
157 1 : );
158 : }
159 :
160 5 : TEST_F(GNUArchiveTests,
161 : ExtractThrowsInvalidArchiveErrorWhenReadFileContentSizeIsLessThanSpecifiedFileSize) {
162 2 : ASSERT_THROW(
163 : extractArchiveWithContent(
164 : "!<arch>\n"s +
165 : "test.txt/ 0 0 0 644 9999 `\n"s +
166 : "..."s
167 : ),
168 : InvalidArchiveError
169 1 : );
170 : }
171 :
172 5 : TEST_F(GNUArchiveTests,
173 : ExtractThrowsInvalidArchiveErrorWhenFileNameTableSizeIsMissing) {
174 2 : ASSERT_THROW(
175 : extractArchiveWithContent(
176 : "!<arch>\n"s +
177 : "//"s
178 : ),
179 : InvalidArchiveError
180 1 : );
181 : }
182 :
183 5 : TEST_F(GNUArchiveTests,
184 : ExtractThrowsInvalidArchiveErrorWhenHeaderEndOfFileNameTableIsInvalid) {
185 2 : ASSERT_THROW(
186 : extractArchiveWithContent(
187 : "!<arch>\n"s +
188 : "// XXX"s
189 : ),
190 : InvalidArchiveError
191 1 : );
192 : }
193 :
194 5 : TEST_F(GNUArchiveTests,
195 : ExtractThrowsInvalidArchiveErrorWhenHeaderEndOfFileNameTableIsMissing) {
196 2 : ASSERT_THROW(
197 : extractArchiveWithContent(
198 : "!<arch>\n"s +
199 : "// 42"s
200 : ),
201 : InvalidArchiveError
202 1 : );
203 : }
204 :
205 5 : TEST_F(GNUArchiveTests,
206 : ExtractThrowsInvalidArchiveErrorWhenFileNameTableEndsPrematurely) {
207 2 : ASSERT_THROW(
208 : extractArchiveWithContent(
209 : "!<arch>\n"s +
210 : "// 42 `\n"s
211 : ),
212 : InvalidArchiveError
213 1 : );
214 : }
215 :
216 5 : TEST_F(GNUArchiveTests,
217 : ExtractThrowsInvalidArchiveErrorWhenFileNameInFileNameTableIsEmpty) {
218 2 : ASSERT_THROW(
219 : extractArchiveWithContent(
220 : "!<arch>\n"s +
221 : "// 2 `\n"s +
222 : "/\n"s
223 : ),
224 : InvalidArchiveError
225 1 : );
226 : }
227 :
228 5 : TEST_F(GNUArchiveTests,
229 : ExtractThrowsInvalidArchiveErrorWhenIndexIntoFileNameTableDoesNotExist) {
230 2 : ASSERT_THROW(
231 : extractArchiveWithContent(
232 : "!<arch>\n"s +
233 : "// 42 `\n"s +
234 : "very_long_name_of_a_module_in_archive.o/\n"s +
235 : "\n"
236 : // The index 1 is invalid (the only valid index is 0).
237 : "/1 0 0 0 644 22 `\n"s +
238 : "contents of the module"s
239 : ),
240 : InvalidArchiveError
241 1 : );
242 : }
243 :
244 5 : TEST_F(GNUArchiveTests,
245 : ExtractThrowsInvalidArchiveErrorWhenIndexIntoFileNameTableIsInvalid) {
246 2 : ASSERT_THROW(
247 : extractArchiveWithContent(
248 : "!<arch>\n"s +
249 : "// 42 `\n"s +
250 : "very_long_name_of_a_module_in_archive.o/\n"s +
251 : "\n"
252 : // The index Z is invalid (it has to be a number).
253 : "/Z 0 0 0 644 22 `\n"s +
254 : "contents of the module"s
255 : ),
256 : InvalidArchiveError
257 1 : );
258 : }
259 :
260 : } // namespace tests
261 : } // namespace internal
262 3 : } // namespace ar
|