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
17 #include <fstream>
18
19 #include "contrib/zopfli/sandboxed.h"
20 #include "contrib/zopfli/utils/utils_zopfli.h"
21 #include "sandboxed_api/util/path.h"
22 #include "sandboxed_api/util/status_matchers.h"
23 #include "sandboxed_api/util/temp_file.h"
24
25 namespace {
26
27 using ::sapi::IsOk;
28 using ::testing::IsEmpty;
29 using ::testing::Not;
30
GetTestFilePath(const std::string & filename)31 std::string GetTestFilePath(const std::string& filename) {
32 return sapi::file::JoinPath(getenv("TEST_FILES_DIR"), filename);
33 }
34
GetTemporaryFile(const std::string & filename)35 std::string GetTemporaryFile(const std::string& filename) {
36 absl::StatusOr<std::string> tmp_file =
37 sapi::CreateNamedTempFileAndClose(filename);
38 if (!tmp_file.ok()) {
39 return "";
40 }
41
42 return sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), *tmp_file);
43 }
44
45 class TestText : public testing::TestWithParam<ZopfliFormat> {};
46 class TestBinary : public testing::TestWithParam<ZopfliFormat> {};
47 class TestTextFD : public testing::TestWithParam<ZopfliFormat> {};
48 class TestBinaryFD : public testing::TestWithParam<ZopfliFormat> {};
49
TEST_P(TestText,Compress)50 TEST_P(TestText, Compress) {
51 ZopfliSapiSandbox sandbox;
52 ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
53 ZopfliApi api(&sandbox);
54
55 std::string infile_s = GetTestFilePath("text");
56 std::string outfile_s = GetTemporaryFile("text.out");
57 ASSERT_THAT(outfile_s, Not(IsEmpty()));
58
59 std::ifstream infile(infile_s, std::ios::binary);
60 ASSERT_TRUE(infile.is_open());
61
62 std::ofstream outfile(outfile_s, std::ios::binary);
63 ASSERT_TRUE(outfile.is_open());
64
65 absl::Status status = Compress(api, infile, outfile, GetParam());
66 ASSERT_THAT(status, IsOk()) << "Unable to compress file";
67
68 ASSERT_LT(outfile.tellp(), infile.tellg());
69 }
70
71 INSTANTIATE_TEST_SUITE_P(SandboxTest, TestText,
72 testing::Values(ZOPFLI_FORMAT_DEFLATE,
73 ZOPFLI_FORMAT_GZIP,
74 ZOPFLI_FORMAT_ZLIB));
75
TEST_P(TestBinary,Compress)76 TEST_P(TestBinary, Compress) {
77 ZopfliSapiSandbox sandbox;
78 ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
79 ZopfliApi api(&sandbox);
80
81 std::string infile_s = GetTestFilePath("binary");
82 std::string outfile_s = GetTemporaryFile("binary.out");
83 ASSERT_THAT(outfile_s, Not(IsEmpty()));
84
85 std::ifstream infile(infile_s, std::ios::binary);
86 ASSERT_TRUE(infile.is_open());
87
88 std::ofstream outfile(outfile_s, std::ios::binary);
89 ASSERT_TRUE(outfile.is_open());
90
91 absl::Status status = Compress(api, infile, outfile, GetParam());
92 ASSERT_THAT(status, IsOk()) << "Unable to compress file";
93
94 ASSERT_LT(outfile.tellp(), infile.tellg());
95 }
96
97 INSTANTIATE_TEST_SUITE_P(SandboxTest, TestBinary,
98 testing::Values(ZOPFLI_FORMAT_DEFLATE,
99 ZOPFLI_FORMAT_GZIP,
100 ZOPFLI_FORMAT_ZLIB));
101
TEST_P(TestTextFD,Compress)102 TEST_P(TestTextFD, Compress) {
103 ZopfliSapiSandbox sandbox;
104 ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
105 ZopfliApi api = ZopfliApi(&sandbox);
106
107 std::string infile_s = GetTestFilePath("text");
108 std::string outfile_s = GetTemporaryFile("text.out");
109 ASSERT_THAT(outfile_s, Not(IsEmpty()));
110
111 sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
112 ASSERT_GE(infd.GetValue(), 0);
113
114 sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
115 ASSERT_GE(outfd.GetValue(), 0);
116
117 absl::Status status = CompressFD(api, infd, outfd, GetParam());
118 ASSERT_THAT(status, IsOk()) << "Unable to compress file";
119
120 off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
121 EXPECT_GE(inpos, 0);
122
123 off_t outpos = lseek(outfd.GetValue(), 0, SEEK_END);
124 EXPECT_GE(outpos, 0);
125
126 EXPECT_LT(outpos, inpos);
127 }
128
129 INSTANTIATE_TEST_SUITE_P(SandboxTest, TestTextFD,
130 testing::Values(ZOPFLI_FORMAT_DEFLATE,
131 ZOPFLI_FORMAT_GZIP,
132 ZOPFLI_FORMAT_ZLIB));
133
TEST_P(TestBinaryFD,Compress)134 TEST_P(TestBinaryFD, Compress) {
135 ZopfliSapiSandbox sandbox;
136 ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
137 ZopfliApi api = ZopfliApi(&sandbox);
138
139 std::string infile_s = GetTestFilePath("binary");
140 std::string outfile_s = GetTemporaryFile("binary.out");
141 ASSERT_THAT(outfile_s, Not(IsEmpty()));
142
143 sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
144 ASSERT_GE(infd.GetValue(), 0);
145
146 sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
147 ASSERT_GE(outfd.GetValue(), 0);
148
149 absl::Status status = CompressFD(api, infd, outfd, GetParam());
150 ASSERT_THAT(status, IsOk()) << "Unable to compress file";
151
152 off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
153 EXPECT_GE(inpos, 0);
154
155 off_t outpos = lseek(outfd.GetValue(), 0, SEEK_END);
156 EXPECT_GE(outpos, 0);
157
158 EXPECT_LT(outpos, inpos);
159 }
160
161 INSTANTIATE_TEST_SUITE_P(SandboxTest, TestBinaryFD,
162 testing::Values(ZOPFLI_FORMAT_DEFLATE,
163 ZOPFLI_FORMAT_GZIP,
164 ZOPFLI_FORMAT_ZLIB));
165 } // namespace
166