xref: /aosp_15_r20/external/sandboxed-api/contrib/zstd/test/zstd_test.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <fcntl.h>
16 #include <unistd.h>
17 
18 #include <fstream>
19 #include <string>
20 
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include "contrib/zstd/sandboxed.h"
24 #include "contrib/zstd/utils/utils_zstd.h"
25 #include "sandboxed_api/util/path.h"
26 #include "sandboxed_api/util/status_matchers.h"
27 #include "sandboxed_api/util/temp_file.h"
28 
29 namespace {
30 
31 using ::sapi::IsOk;
32 
GetTestFilePath(const std::string & filename)33 std::string GetTestFilePath(const std::string& filename) {
34   return sapi::file::JoinPath(getenv("TEST_FILES_DIR"), filename);
35 }
36 
CompareFiles(const std::string & name1,const std::string & name2)37 bool CompareFiles(const std::string& name1, const std::string& name2) {
38   std::ifstream f1(name1, std::ios::binary);
39   if (!f1.is_open()) {
40     return false;
41   }
42 
43   std::ifstream f2(name2, std::ios::binary);
44   if (!f2.is_open()) {
45     return false;
46   }
47 
48   while (!f1.eof() && !f2.eof()) {
49     char buf1[128];
50     char buf2[128];
51 
52     f1.read(buf1, sizeof(buf1));
53     f2.read(buf2, sizeof(buf2));
54 
55     if (f1.gcount() != f2.gcount()) {
56       return false;
57     }
58     if (memcmp(&buf1, &buf2, f2.gcount()) != 0) {
59       return false;
60     }
61   }
62 
63   return f1.eof() == f2.eof();
64 }
65 
TEST(SandboxTest,CheckVersion)66 TEST(SandboxTest, CheckVersion) {
67   ZstdSapiSandbox sandbox;
68   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
69   ZstdApi api = ZstdApi(&sandbox);
70 
71   absl::StatusOr<unsigned> version = api.ZSTD_versionNumber();
72   ASSERT_THAT(version, IsOk())
73       << "fatal error when invoking ZSTD_versionNumber";
74 
75   ASSERT_GE(*version, 10000);
76 }
77 
TEST(SandboxTest,CheckMinCLevel)78 TEST(SandboxTest, CheckMinCLevel) {
79   ZstdSapiSandbox sandbox;
80   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
81   ZstdApi api = ZstdApi(&sandbox);
82 
83   absl::StatusOr<int> level = api.ZSTD_minCLevel();
84   ASSERT_THAT(level, IsOk()) << "fatal error when invoking ZSTD_minCLevel";
85 
86   ASSERT_LT(*level, 0);
87 }
88 
TEST(SandboxTest,CheckMaxCLevel)89 TEST(SandboxTest, CheckMaxCLevel) {
90   ZstdSapiSandbox sandbox;
91   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
92   ZstdApi api = ZstdApi(&sandbox);
93 
94   absl::StatusOr<int> level = api.ZSTD_maxCLevel();
95   ASSERT_THAT(level, IsOk()) << "fatal error when invoking ZSTD_maxCLevel";
96 
97   ASSERT_GT(*level, 0);
98 }
99 
TEST(SandboxTest,CheckCompressInMemory)100 TEST(SandboxTest, CheckCompressInMemory) {
101   ZstdSapiSandbox sandbox;
102   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
103   ZstdApi api = ZstdApi(&sandbox);
104 
105   std::string infile_s = GetTestFilePath("text");
106 
107   SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
108                             sapi::CreateNamedTempFileAndClose("out.zstd"));
109   std::string outfile_s =
110       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
111 
112   std::ifstream infile(infile_s, std::ios::binary);
113   ASSERT_TRUE(infile.is_open());
114 
115   std::ofstream outfile(outfile_s, std::ios::binary);
116   ASSERT_TRUE(outfile.is_open());
117 
118   absl::Status status = CompressInMemory(api, infile, outfile, 0);
119   ASSERT_THAT(status, IsOk()) << "Unable to compress file in memory";
120 
121   ASSERT_LT(outfile.tellp(), infile.tellg());
122 }
123 
TEST(SandboxTest,CheckDecompressInMemory)124 TEST(SandboxTest, CheckDecompressInMemory) {
125   ZstdSapiSandbox sandbox;
126   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
127   ZstdApi api = ZstdApi(&sandbox);
128 
129   std::string infile_s = GetTestFilePath("text.blob.zstd");
130 
131   SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
132                             sapi::CreateNamedTempFileAndClose("out"));
133   std::string outfile_s =
134       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
135 
136   std::ifstream infile(infile_s, std::ios::binary);
137   ASSERT_TRUE(infile.is_open());
138 
139   std::ofstream outfile(outfile_s, std::ios::binary);
140   ASSERT_TRUE(outfile.is_open());
141 
142   absl::Status status = DecompressInMemory(api, infile, outfile);
143   ASSERT_THAT(status, IsOk()) << "Unable to decompress file in memory";
144 
145   ASSERT_GT(outfile.tellp(), infile.tellg());
146 
147   ASSERT_TRUE(CompareFiles(GetTestFilePath("text"), outfile_s));
148 }
149 
TEST(SandboxTest,CheckCompressAndDecompressInMemory)150 TEST(SandboxTest, CheckCompressAndDecompressInMemory) {
151   ZstdSapiSandbox sandbox;
152   absl::Status status;
153   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
154   ZstdApi api = ZstdApi(&sandbox);
155 
156   std::string infile_s = GetTestFilePath("text");
157 
158   SAPI_ASSERT_OK_AND_ASSIGN(std::string path_middle,
159                             sapi::CreateNamedTempFileAndClose("middle.zstd"));
160   std::string middle_s =
161       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path_middle);
162 
163   SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
164                             sapi::CreateNamedTempFileAndClose("out"));
165   std::string outfile_s =
166       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
167 
168   std::ifstream infile(infile_s, std::ios::binary);
169   ASSERT_TRUE(infile.is_open());
170 
171   std::ofstream outmiddle(middle_s, std::ios::binary);
172   ASSERT_TRUE(outmiddle.is_open());
173 
174   status = CompressInMemory(api, infile, outmiddle, 0);
175   ASSERT_THAT(status, IsOk()) << "Unable to compress file in memory";
176 
177   ASSERT_LT(outmiddle.tellp(), infile.tellg());
178 
179   std::ifstream inmiddle(middle_s, std::ios::binary);
180   ASSERT_TRUE(inmiddle.is_open());
181 
182   std::ofstream outfile(outfile_s, std::ios::binary);
183   ASSERT_TRUE(outfile.is_open());
184 
185   status = DecompressInMemory(api, inmiddle, outfile);
186   ASSERT_THAT(status, IsOk()) << "Unable to decompress file in memory";
187 
188   ASSERT_TRUE(CompareFiles(infile_s, outfile_s));
189 }
190 
TEST(SandboxTest,CheckCompressStream)191 TEST(SandboxTest, CheckCompressStream) {
192   ZstdSapiSandbox sandbox;
193   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
194   ZstdApi api = ZstdApi(&sandbox);
195 
196   std::string infile_s = GetTestFilePath("text");
197   SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
198                             sapi::CreateNamedTempFileAndClose("out.zstd"));
199   std::string outfile_s =
200       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
201 
202   std::ifstream infile(infile_s, std::ios::binary);
203   ASSERT_TRUE(infile.is_open());
204 
205   std::ofstream outfile(outfile_s, std::ios::binary);
206   ASSERT_TRUE(outfile.is_open());
207 
208   absl::Status status = CompressStream(api, infile, outfile, 0);
209   ASSERT_THAT(status, IsOk()) << "Unable to compress stream";
210 
211   infile.clear();
212 
213   ASSERT_LT(outfile.tellp(), infile.tellg());
214 }
215 
TEST(SandboxTest,CheckDecompressStream)216 TEST(SandboxTest, CheckDecompressStream) {
217   ZstdSapiSandbox sandbox;
218   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
219   ZstdApi api = ZstdApi(&sandbox);
220 
221   std::string infile_s = GetTestFilePath("text.stream.zstd");
222   SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
223                             sapi::CreateNamedTempFileAndClose("out"));
224   std::string outfile_s =
225       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
226 
227   std::ifstream infile(infile_s, std::ios::binary);
228   ASSERT_TRUE(infile.is_open());
229 
230   std::ofstream outfile(outfile_s, std::ios::binary);
231   ASSERT_TRUE(outfile.is_open());
232 
233   absl::Status status = DecompressStream(api, infile, outfile);
234   ASSERT_THAT(status, IsOk()) << "Unable to decompress stream";
235 
236   ASSERT_GT(outfile.tellp(), infile.tellg());
237 
238   ASSERT_TRUE(CompareFiles(GetTestFilePath("text"), outfile_s));
239 }
240 
TEST(SandboxTest,CheckCompressAndDecompressStream)241 TEST(SandboxTest, CheckCompressAndDecompressStream) {
242   ZstdSapiSandbox sandbox;
243   absl::Status status;
244   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
245   ZstdApi api = ZstdApi(&sandbox);
246 
247   std::string infile_s = GetTestFilePath("text");
248 
249   SAPI_ASSERT_OK_AND_ASSIGN(std::string path_middle,
250                             sapi::CreateNamedTempFileAndClose("middle.zstd"));
251   std::string middle_s =
252       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path_middle);
253 
254   SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
255                             sapi::CreateNamedTempFileAndClose("out"));
256   std::string outfile_s =
257       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
258 
259   std::ifstream infile(infile_s, std::ios::binary);
260   ASSERT_TRUE(infile.is_open());
261 
262   std::ofstream outmiddle(middle_s, std::ios::binary);
263   ASSERT_TRUE(outmiddle.is_open());
264 
265   status = CompressStream(api, infile, outmiddle, 0);
266   ASSERT_THAT(status, IsOk()) << "Unable to compress stream";
267 
268   infile.clear();
269   ASSERT_LT(outmiddle.tellp(), infile.tellg());
270 
271   std::ifstream inmiddle(middle_s, std::ios::binary);
272   ASSERT_TRUE(inmiddle.is_open());
273 
274   std::ofstream outfile(outfile_s, std::ios::binary);
275   ASSERT_TRUE(outfile.is_open());
276 
277   status = DecompressStream(api, inmiddle, outfile);
278   ASSERT_THAT(status, IsOk()) << "Unable to decompress";
279 
280   ASSERT_TRUE(CompareFiles(infile_s, outfile_s));
281 }
282 
TEST(SandboxTest,CheckCompressInMemoryFD)283 TEST(SandboxTest, CheckCompressInMemoryFD) {
284   ZstdSapiSandbox sandbox;
285   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
286   ZstdApi api = ZstdApi(&sandbox);
287 
288   std::string infile_s = GetTestFilePath("text");
289 
290   SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
291                             sapi::CreateNamedTempFileAndClose("out.zstd"));
292   std::string outfile_s =
293       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
294 
295   sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
296   ASSERT_GE(infd.GetValue(), 0);
297   sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
298   ASSERT_GE(outfd.GetValue(), 0);
299 
300   absl::Status status = CompressInMemoryFD(api, infd, outfd, 0);
301   ASSERT_THAT(status, IsOk()) << "Unable to compress file in memory";
302 
303   off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
304   EXPECT_GE(inpos, 0);
305   off_t outpos = lseek(outfd.GetValue(), 0, SEEK_END);
306   EXPECT_GE(outpos, 0);
307 
308   EXPECT_LT(outpos, inpos);
309 }
310 
TEST(SandboxTest,CheckDecompressInMemoryFD)311 TEST(SandboxTest, CheckDecompressInMemoryFD) {
312   ZstdSapiSandbox sandbox;
313   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
314   ZstdApi api = ZstdApi(&sandbox);
315 
316   std::string infile_s = GetTestFilePath("text.blob.zstd");
317   sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
318   ASSERT_GE(infd.GetValue(), 0);
319 
320   SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
321                             sapi::CreateNamedTempFileAndClose("out"));
322   std::string outfile_s =
323       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
324   sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
325   ASSERT_GE(outfd.GetValue(), 0);
326 
327   absl::Status status = DecompressInMemoryFD(api, infd, outfd);
328   ASSERT_THAT(status, IsOk()) << "Unable to compress file in memory";
329 
330   off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
331   EXPECT_GE(inpos, 0);
332 
333   off_t outpos = lseek(outfd.GetValue(), 0, SEEK_END);
334   EXPECT_GE(outpos, 0);
335 
336   EXPECT_GT(outpos, inpos);
337 
338   ASSERT_TRUE(CompareFiles(GetTestFilePath("text"), outfile_s));
339 }
340 
TEST(SandboxTest,CheckCompressAndDecompressInMemoryFD)341 TEST(SandboxTest, CheckCompressAndDecompressInMemoryFD) {
342   ZstdSapiSandbox sandbox;
343   absl::Status status;
344   int ret;
345   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
346   ZstdApi api = ZstdApi(&sandbox);
347 
348   std::string infile_s = GetTestFilePath("text");
349 
350   SAPI_ASSERT_OK_AND_ASSIGN(std::string path_middle,
351                             sapi::CreateNamedTempFileAndClose("middle.zstd"));
352   std::string middle_s =
353       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path_middle);
354 
355   SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
356                             sapi::CreateNamedTempFileAndClose("out"));
357   std::string outfile_s =
358       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
359 
360   sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
361   ASSERT_GE(infd.GetValue(), 0);
362 
363   sapi::v::Fd outmiddlefd(open(middle_s.c_str(), O_WRONLY));
364   ASSERT_GE(outmiddlefd.GetValue(), 0);
365 
366   status = CompressInMemoryFD(api, infd, outmiddlefd, 0);
367   ASSERT_THAT(status, IsOk()) << "Unable to compress file in memory";
368 
369   off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
370   EXPECT_GE(inpos, 0);
371 
372   off_t outpos = lseek(outmiddlefd.GetValue(), 0, SEEK_END);
373   EXPECT_GE(outpos, 0);
374 
375   EXPECT_LT(outpos, inpos);
376 
377   infd.CloseLocalFd();
378   outmiddlefd.CloseLocalFd();
379 
380   sapi::v::Fd inmiddlefd(open(middle_s.c_str(), O_RDONLY));
381   ASSERT_GE(inmiddlefd.GetValue(), 0);
382 
383   sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
384   ASSERT_GE(outfd.GetValue(), 0);
385 
386   status = DecompressInMemoryFD(api, inmiddlefd, outfd);
387   ASSERT_THAT(status, IsOk()) << "Unable to decompress file in memory";
388 
389   outfd.CloseLocalFd();
390   inmiddlefd.CloseLocalFd();
391 
392   ASSERT_TRUE(CompareFiles(infile_s, outfile_s));
393 }
394 
TEST(SandboxTest,CheckCompressStreamFD)395 TEST(SandboxTest, CheckCompressStreamFD) {
396   absl::Status status;
397   ZstdSapiSandbox sandbox;
398   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
399   ZstdApi api = ZstdApi(&sandbox);
400 
401   std::string infile_s = GetTestFilePath("text");
402 
403   SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
404                             sapi::CreateNamedTempFileAndClose("out.zstd"));
405   std::string outfile_s =
406       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
407 
408   sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
409   ASSERT_GE(infd.GetValue(), 0);
410 
411   sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
412   ASSERT_GE(outfd.GetValue(), 0);
413 
414   status = CompressStreamFD(api, infd, outfd, 0);
415   ASSERT_THAT(status, IsOk()) << "Unable to compress stream";
416 
417   off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
418   EXPECT_GE(inpos, 0);
419 
420   off_t outpos = lseek(outfd.GetValue(), 0, SEEK_END);
421   EXPECT_GE(outpos, 0);
422 
423   EXPECT_LT(outpos, inpos);
424 }
425 
TEST(SandboxTest,CheckDecompressStreamFD)426 TEST(SandboxTest, CheckDecompressStreamFD) {
427   absl::Status status;
428   ZstdSapiSandbox sandbox;
429   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
430   ZstdApi api = ZstdApi(&sandbox);
431 
432   std::string infile_s = GetTestFilePath("text.stream.zstd");
433 
434   SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
435                             sapi::CreateNamedTempFileAndClose("out"));
436   std::string outfile_s =
437       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
438 
439   sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
440   ASSERT_GE(infd.GetValue(), 0);
441 
442   sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
443   ASSERT_GE(outfd.GetValue(), 0);
444 
445   status = DecompressStreamFD(api, infd, outfd);
446   ASSERT_THAT(status, IsOk()) << "Unable to decompress stream";
447 
448   off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
449   EXPECT_GE(inpos, 0);
450 
451   off_t outpos = lseek(outfd.GetValue(), 0, SEEK_END);
452   EXPECT_GE(outpos, 0);
453 
454   EXPECT_GT(outpos, inpos);
455 
456   ASSERT_TRUE(CompareFiles(GetTestFilePath("text"), outfile_s));
457 }
458 
TEST(SandboxTest,CheckCompressAndDecompressStreamFD)459 TEST(SandboxTest, CheckCompressAndDecompressStreamFD) {
460   ZstdSapiSandbox sandbox;
461   absl::Status status;
462   int ret;
463   ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
464   ZstdApi api = ZstdApi(&sandbox);
465 
466   std::string infile_s = GetTestFilePath("text");
467 
468   SAPI_ASSERT_OK_AND_ASSIGN(std::string path_middle,
469                             sapi::CreateNamedTempFileAndClose("middle.zstd"));
470   std::string middle_s =
471       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path_middle);
472 
473   SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
474                             sapi::CreateNamedTempFileAndClose("out"));
475   std::string outfile_s =
476       sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
477 
478   sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
479   ASSERT_GE(infd.GetValue(), 0);
480 
481   sapi::v::Fd outmiddlefd(open(middle_s.c_str(), O_WRONLY));
482   ASSERT_GE(outmiddlefd.GetValue(), 0);
483 
484   status = CompressStreamFD(api, infd, outmiddlefd, 0);
485   ASSERT_THAT(status, IsOk()) << "Unable to compress stream";
486 
487   off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
488   EXPECT_GE(inpos, 0);
489 
490   off_t outmiddlepos = lseek(outmiddlefd.GetValue(), 0, SEEK_END);
491   EXPECT_GE(outmiddlepos, 0);
492 
493   EXPECT_LT(outmiddlepos, inpos);
494 
495   infd.CloseLocalFd();
496   outmiddlefd.CloseLocalFd();
497 
498   sapi::v::Fd inmiddlefd(open(middle_s.c_str(), O_RDONLY));
499   ASSERT_GE(inmiddlefd.GetValue(), 0);
500 
501   sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
502   ASSERT_GE(outfd.GetValue(), 0);
503 
504   status = DecompressStreamFD(api, inmiddlefd, outfd);
505   ASSERT_THAT(status, IsOk()) << "Unable to decompress stream";
506 
507   ASSERT_TRUE(CompareFiles(infile_s, outfile_s));
508 }
509 
510 }  // namespace
511