xref: /aosp_15_r20/external/sandboxed-api/contrib/brotli/test/brotli_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 
17 #include <fstream>
18 
19 #include "contrib/brotli/sandboxed.h"
20 #include "contrib/brotli/utils/utils_brotli.h"
21 #include "contrib/brotli/utils/utils_brotli_dec.h"
22 #include "contrib/brotli/utils/utils_brotli_enc.h"
23 #include "sandboxed_api/util/path.h"
24 #include "sandboxed_api/util/status_matchers.h"
25 
26 namespace {
27 
28 using ::sapi::IsOk;
29 
30 class BrotliBase : public testing::Test {
31  protected:
GetTestFilePath(const std::string & filename)32   std::string GetTestFilePath(const std::string& filename) {
33     return sapi::file::JoinPath(test_dir_, filename);
34   }
35 
36   void SetUp() override;
37 
38   std::unique_ptr<BrotliSandbox> sandbox_;
39   std::unique_ptr<BrotliEncoder> enc_;
40   std::unique_ptr<BrotliDecoder> dec_;
41   const char* test_dir_;
42 };
43 
44 class BrotliMultiFile : public BrotliBase,
45                         public testing::WithParamInterface<std::string> {};
46 
SetUp()47 void BrotliBase::SetUp() {
48   sandbox_ = std::make_unique<BrotliSapiSandbox>();
49   ASSERT_THAT(sandbox_.get()->Init(), IsOk());
50 
51   enc_ = std::make_unique<BrotliEncoder>(sandbox_.get());
52   ASSERT_TRUE(enc_.get()->IsInit());
53 
54   dec_ = std::make_unique<BrotliDecoder>(sandbox_.get());
55   ASSERT_TRUE(dec_.get()->IsInit());
56 
57   test_dir_ = getenv("TEST_FILES_DIR");
58   ASSERT_NE(test_dir_, nullptr);
59 }
60 
TEST_F(BrotliBase,SetParamEnc)61 TEST_F(BrotliBase, SetParamEnc) {
62   ASSERT_THAT(enc_.get()->SetParameter(BROTLI_PARAM_QUALITY, 5), IsOk());
63 }
64 
TEST_F(BrotliBase,SetParamDec)65 TEST_F(BrotliBase, SetParamDec) {
66   ASSERT_THAT(dec_.get()->SetParameter(
67                   BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION, 100),
68               IsOk());
69 }
70 
TEST_F(BrotliBase,Compress)71 TEST_F(BrotliBase, Compress) {
72   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> bufin,
73                             ReadFile(GetTestFilePath("text")));
74 
75   ASSERT_THAT(enc_.get()->Compress(bufin), IsOk());
76 
77   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> bufout,
78                             enc_.get()->TakeOutput());
79   ASSERT_LT(bufout.size(), bufin.size());
80 }
81 
TEST_F(BrotliBase,CompressDecompress)82 TEST_F(BrotliBase, CompressDecompress) {
83   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> bufin,
84                             ReadFile(GetTestFilePath("text")));
85 
86   ASSERT_THAT(enc_.get()->Compress(bufin), IsOk());
87 
88   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> bufcomp,
89                             enc_.get()->TakeOutput());
90   ASSERT_LT(bufcomp.size(), bufin.size());
91 
92   SAPI_ASSERT_OK_AND_ASSIGN(BrotliDecoderResult result,
93                             dec_.get()->Decompress(bufcomp));
94   ASSERT_THAT(result, BROTLI_DECODER_RESULT_SUCCESS);
95 
96   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> bufout,
97                             dec_.get()->TakeOutput());
98   ASSERT_EQ(bufin, bufout);
99 }
100 
TEST_F(BrotliBase,CompressStreamDecompress)101 TEST_F(BrotliBase, CompressStreamDecompress) {
102   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> buforig,
103                             ReadFile(GetTestFilePath("text")));
104 
105   for (auto it = buforig.begin(); it != buforig.end();) {
106     int nsize = std::min<size_t>(512, buforig.end() - it);
107     BrotliEncoderOperation op = BROTLI_OPERATION_PROCESS;
108     if (it + nsize == buforig.end()) {
109       op = BROTLI_OPERATION_FINISH;
110     }
111     std::vector<uint8_t> bufin(it, it + nsize);
112 
113     ASSERT_THAT(enc_.get()->Compress(bufin, op), IsOk());
114     it += nsize;
115   }
116 
117   bool empty = false;
118   std::vector<uint8_t> bufcomp;
119   while (!empty) {
120     SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> takebuf,
121                               enc_.get()->TakeOutput());
122     empty = takebuf.empty();
123     if (!empty) {
124       bufcomp.insert(bufcomp.end(), takebuf.begin(), takebuf.end());
125     }
126   }
127 
128   SAPI_ASSERT_OK_AND_ASSIGN(BrotliDecoderResult result,
129                             dec_.get()->Decompress(bufcomp));
130   ASSERT_THAT(result, BROTLI_DECODER_RESULT_SUCCESS);
131 
132   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> bufout,
133                             dec_.get()->TakeOutput());
134   ASSERT_EQ(buforig, bufout);
135 }
136 
TEST_P(BrotliMultiFile,Decompress)137 TEST_P(BrotliMultiFile, Decompress) {
138   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> buforig,
139                             ReadFile(GetTestFilePath("text")));
140   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> bufin,
141                             ReadFile(GetTestFilePath(GetParam())));
142 
143   SAPI_ASSERT_OK_AND_ASSIGN(BrotliDecoderResult result,
144                             dec_.get()->Decompress(bufin));
145   ASSERT_THAT(result, BROTLI_DECODER_RESULT_SUCCESS);
146 
147   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> bufout,
148                             dec_.get()->TakeOutput());
149   ASSERT_EQ(buforig, bufout);
150 }
151 
TEST_P(BrotliMultiFile,DecompressCharStream)152 TEST_P(BrotliMultiFile, DecompressCharStream) {
153   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> buforig,
154                             ReadFile(GetTestFilePath("text")));
155   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> bufcomp,
156                             ReadFile(GetTestFilePath(GetParam())));
157 
158   BrotliDecoderResult result;
159   std::vector<uint8_t> bufout;
160 
161   for (auto it = bufcomp.begin(); it != bufcomp.end(); ++it) {
162     std::vector<uint8_t> tmp(it, it + 1);
163 
164     SAPI_ASSERT_OK_AND_ASSIGN(result, dec_.get()->Decompress(tmp));
165     if (result == BROTLI_DECODER_RESULT_SUCCESS) {
166       SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> bufuncomptmp,
167                                 dec_.get()->TakeOutput());
168       bufout.insert(bufout.end(), bufuncomptmp.begin(), bufuncomptmp.end());
169     }
170   }
171   ASSERT_THAT(result, BROTLI_DECODER_RESULT_SUCCESS);
172 
173   ASSERT_EQ(buforig, bufout);
174 }
175 
TEST_P(BrotliMultiFile,DecompressChunksStream)176 TEST_P(BrotliMultiFile, DecompressChunksStream) {
177   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> buforig,
178                             ReadFile(GetTestFilePath("text")));
179   SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> bufcomp,
180                             ReadFile(GetTestFilePath(GetParam())));
181 
182   std::vector<size_t> chunks = {128, 256, 13, 37, 99, 10, 42};
183 
184   BrotliDecoderResult result;
185   std::vector<uint8_t> bufout;
186   std::vector<uint8_t>::iterator it = bufcomp.begin();
187 
188   for (int i = 0; it != bufcomp.end(); ++i) {
189     size_t nsize =
190         std::min<size_t>(bufcomp.end() - it, chunks[i % chunks.size()]);
191     std::vector<uint8_t> tmp(it, it + nsize);
192     it += nsize;
193 
194     SAPI_ASSERT_OK_AND_ASSIGN(result, dec_.get()->Decompress(tmp));
195     if (result == BROTLI_DECODER_RESULT_SUCCESS) {
196       SAPI_ASSERT_OK_AND_ASSIGN(std::vector<uint8_t> bufuncomptmp,
197                                 dec_.get()->TakeOutput());
198       bufout.insert(bufout.end(), bufuncomptmp.begin(), bufuncomptmp.end());
199     }
200   }
201 
202   ASSERT_THAT(result, BROTLI_DECODER_RESULT_SUCCESS);
203   ASSERT_EQ(buforig, bufout);
204 }
205 
206 INSTANTIATE_TEST_SUITE_P(BrotliBase, BrotliMultiFile,
207                          testing::Values("text.full.brotli",
208                                          "text.chunk.brotli"));
209 }  // namespace
210