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 "contrib/woff2/woff2_sapi.h"
16
17 #include <woff2/encode.h>
18
19 #include <cstddef>
20 #include <cstdlib>
21 #include <fstream>
22 #include <iostream>
23 #include <optional>
24
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
27 #include "contrib/woff2/woff2_wrapper.h"
28 #include "sandboxed_api/testing.h"
29 #include "sandboxed_api/util/fileops.h"
30 #include "sandboxed_api/util/path.h"
31 #include "sandboxed_api/util/status_matchers.h"
32 #include "woff2_sapi.sapi.h" // NOLINT(build/include)
33
34 namespace {
35
36 using ::sapi::IsOk;
37 using ::testing::Eq;
38 using ::testing::IsNull;
39 using ::testing::Not;
40 using ::testing::StrEq;
41
42 class Woff2SapiSandboxTest : public testing::Test {
43 protected:
SetUpTestSuite()44 static void SetUpTestSuite() {
45 test_data_dir_ = ::getenv("TEST_DATA_DIR");
46 ASSERT_THAT(test_data_dir_, Not(IsNull()));
47 sandbox_ = new ::sapi_woff2::Woff2SapiSandbox();
48 ASSERT_THAT(sandbox_->Init(), IsOk());
49 api_ = new ::sapi_woff2::WOFF2Api(sandbox_);
50 }
TearDownTestSuite()51 static void TearDownTestSuite() {
52 delete api_;
53 delete sandbox_;
54 }
55 static absl::StatusOr<std::vector<uint8_t>> ReadFile(
56 const char* in_file, size_t expected_size = SIZE_MAX);
57 static const char* test_data_dir_;
58 static ::sapi_woff2::WOFF2Api* api_;
59
60 private:
61 static ::sapi_woff2::Woff2SapiSandbox* sandbox_;
62 };
63
64 ::sapi_woff2::Woff2SapiSandbox* Woff2SapiSandboxTest::sandbox_;
65 ::sapi_woff2::WOFF2Api* Woff2SapiSandboxTest::api_;
66 const char* Woff2SapiSandboxTest::test_data_dir_;
67
GetStreamSize(std::ifstream & stream)68 std::streamsize GetStreamSize(std::ifstream& stream) {
69 stream.seekg(0, std::ios_base::end);
70 std::streamsize ssize = stream.tellg();
71 stream.seekg(0, std::ios_base::beg);
72
73 return ssize;
74 }
75
ReadFile(const char * in_file,size_t expected_size)76 absl::StatusOr<std::vector<uint8_t>> Woff2SapiSandboxTest::ReadFile(
77 const char* in_file, size_t expected_size) {
78 auto env = absl::StrCat(test_data_dir_, "/", in_file);
79 std::ifstream f(env);
80 if (!f.is_open()) {
81 return absl::UnavailableError("File could not be opened");
82 }
83 std::streamsize ssize = GetStreamSize(f);
84 if (expected_size != SIZE_MAX && ssize != expected_size) {
85 return absl::UnavailableError("Incorrect size of file");
86 }
87 std::vector<uint8_t> inbuf((ssize));
88 f.read(reinterpret_cast<char*>(inbuf.data()), ssize);
89 if (ssize != f.gcount()) {
90 return absl::UnavailableError("Premature end of file");
91 }
92 if (f.fail() || f.eof()) {
93 return absl::UnavailableError("Error reading file");
94 }
95 return inbuf;
96 }
97
TEST_F(Woff2SapiSandboxTest,Compress)98 TEST_F(Woff2SapiSandboxTest, Compress) {
99 auto result = ReadFile("Roboto-Regular.ttf");
100 ASSERT_THAT(result, IsOk());
101 sapi::v::Array array(result->data(), result->size());
102 sapi::v::GenericPtr p;
103 sapi::v::IntBase<size_t> out_length;
104 auto compress_result = api_->WOFF2_ConvertTTFToWOFF2(
105 array.PtrBefore(), result->size(), p.PtrAfter(), out_length.PtrAfter());
106 ASSERT_THAT(compress_result, IsOk());
107 ASSERT_TRUE(compress_result.value());
108 ASSERT_THAT(p.GetValue(), Not(Eq(0)));
109 auto ptr = sapi::v::RemotePtr{reinterpret_cast<void*>(p.GetValue())};
110 ASSERT_THAT(api_->WOFF2_Free(&ptr), IsOk());
111 }
112
TEST_F(Woff2SapiSandboxTest,Decompress)113 TEST_F(Woff2SapiSandboxTest, Decompress) {
114 auto result = ReadFile("Roboto-Regular.woff2");
115 ASSERT_THAT(result, IsOk());
116 sapi::v::Array array(result->data(), result->size());
117 sapi::v::GenericPtr p;
118 sapi::v::IntBase<size_t> out_length;
119 auto decompress_result = api_->WOFF2_ConvertWOFF2ToTTF(
120 array.PtrBefore(), result->size(), p.PtrAfter(), out_length.PtrAfter(),
121 1 << 25);
122 ASSERT_THAT(decompress_result, IsOk());
123 ASSERT_TRUE(decompress_result.value());
124 ASSERT_THAT(p.GetValue(), Not(Eq(0)));
125 auto ptr = sapi::v::RemotePtr{reinterpret_cast<void*>(p.GetValue())};
126 ASSERT_THAT(api_->WOFF2_Free(&ptr), IsOk());
127 }
128
129 } // namespace
130