1*ec63e07aSXin Li // Copyright 2022 Google LLC
2*ec63e07aSXin Li //
3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License");
4*ec63e07aSXin Li // you may not use this file except in compliance with the License.
5*ec63e07aSXin Li // You may obtain a copy of the License at
6*ec63e07aSXin Li //
7*ec63e07aSXin Li // https://www.apache.org/licenses/LICENSE-2.0
8*ec63e07aSXin Li //
9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software
10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS,
11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*ec63e07aSXin Li // See the License for the specific language governing permissions and
13*ec63e07aSXin Li // limitations under the License.
14*ec63e07aSXin Li
15*ec63e07aSXin Li #include "contrib/woff2/woff2_sapi.h"
16*ec63e07aSXin Li
17*ec63e07aSXin Li #include <woff2/encode.h>
18*ec63e07aSXin Li
19*ec63e07aSXin Li #include <cstddef>
20*ec63e07aSXin Li #include <cstdlib>
21*ec63e07aSXin Li #include <fstream>
22*ec63e07aSXin Li #include <iostream>
23*ec63e07aSXin Li #include <optional>
24*ec63e07aSXin Li
25*ec63e07aSXin Li #include "gmock/gmock.h"
26*ec63e07aSXin Li #include "gtest/gtest.h"
27*ec63e07aSXin Li #include "contrib/woff2/woff2_wrapper.h"
28*ec63e07aSXin Li #include "sandboxed_api/testing.h"
29*ec63e07aSXin Li #include "sandboxed_api/util/fileops.h"
30*ec63e07aSXin Li #include "sandboxed_api/util/path.h"
31*ec63e07aSXin Li #include "sandboxed_api/util/status_matchers.h"
32*ec63e07aSXin Li #include "woff2_sapi.sapi.h" // NOLINT(build/include)
33*ec63e07aSXin Li
34*ec63e07aSXin Li namespace {
35*ec63e07aSXin Li
36*ec63e07aSXin Li using ::sapi::IsOk;
37*ec63e07aSXin Li using ::testing::Eq;
38*ec63e07aSXin Li using ::testing::IsNull;
39*ec63e07aSXin Li using ::testing::Not;
40*ec63e07aSXin Li using ::testing::StrEq;
41*ec63e07aSXin Li
42*ec63e07aSXin Li class Woff2SapiSandboxTest : public testing::Test {
43*ec63e07aSXin Li protected:
SetUpTestSuite()44*ec63e07aSXin Li static void SetUpTestSuite() {
45*ec63e07aSXin Li test_data_dir_ = ::getenv("TEST_DATA_DIR");
46*ec63e07aSXin Li ASSERT_THAT(test_data_dir_, Not(IsNull()));
47*ec63e07aSXin Li sandbox_ = new ::sapi_woff2::Woff2SapiSandbox();
48*ec63e07aSXin Li ASSERT_THAT(sandbox_->Init(), IsOk());
49*ec63e07aSXin Li api_ = new ::sapi_woff2::WOFF2Api(sandbox_);
50*ec63e07aSXin Li }
TearDownTestSuite()51*ec63e07aSXin Li static void TearDownTestSuite() {
52*ec63e07aSXin Li delete api_;
53*ec63e07aSXin Li delete sandbox_;
54*ec63e07aSXin Li }
55*ec63e07aSXin Li static absl::StatusOr<std::vector<uint8_t>> ReadFile(
56*ec63e07aSXin Li const char* in_file, size_t expected_size = SIZE_MAX);
57*ec63e07aSXin Li static const char* test_data_dir_;
58*ec63e07aSXin Li static ::sapi_woff2::WOFF2Api* api_;
59*ec63e07aSXin Li
60*ec63e07aSXin Li private:
61*ec63e07aSXin Li static ::sapi_woff2::Woff2SapiSandbox* sandbox_;
62*ec63e07aSXin Li };
63*ec63e07aSXin Li
64*ec63e07aSXin Li ::sapi_woff2::Woff2SapiSandbox* Woff2SapiSandboxTest::sandbox_;
65*ec63e07aSXin Li ::sapi_woff2::WOFF2Api* Woff2SapiSandboxTest::api_;
66*ec63e07aSXin Li const char* Woff2SapiSandboxTest::test_data_dir_;
67*ec63e07aSXin Li
GetStreamSize(std::ifstream & stream)68*ec63e07aSXin Li std::streamsize GetStreamSize(std::ifstream& stream) {
69*ec63e07aSXin Li stream.seekg(0, std::ios_base::end);
70*ec63e07aSXin Li std::streamsize ssize = stream.tellg();
71*ec63e07aSXin Li stream.seekg(0, std::ios_base::beg);
72*ec63e07aSXin Li
73*ec63e07aSXin Li return ssize;
74*ec63e07aSXin Li }
75*ec63e07aSXin Li
ReadFile(const char * in_file,size_t expected_size)76*ec63e07aSXin Li absl::StatusOr<std::vector<uint8_t>> Woff2SapiSandboxTest::ReadFile(
77*ec63e07aSXin Li const char* in_file, size_t expected_size) {
78*ec63e07aSXin Li auto env = absl::StrCat(test_data_dir_, "/", in_file);
79*ec63e07aSXin Li std::ifstream f(env);
80*ec63e07aSXin Li if (!f.is_open()) {
81*ec63e07aSXin Li return absl::UnavailableError("File could not be opened");
82*ec63e07aSXin Li }
83*ec63e07aSXin Li std::streamsize ssize = GetStreamSize(f);
84*ec63e07aSXin Li if (expected_size != SIZE_MAX && ssize != expected_size) {
85*ec63e07aSXin Li return absl::UnavailableError("Incorrect size of file");
86*ec63e07aSXin Li }
87*ec63e07aSXin Li std::vector<uint8_t> inbuf((ssize));
88*ec63e07aSXin Li f.read(reinterpret_cast<char*>(inbuf.data()), ssize);
89*ec63e07aSXin Li if (ssize != f.gcount()) {
90*ec63e07aSXin Li return absl::UnavailableError("Premature end of file");
91*ec63e07aSXin Li }
92*ec63e07aSXin Li if (f.fail() || f.eof()) {
93*ec63e07aSXin Li return absl::UnavailableError("Error reading file");
94*ec63e07aSXin Li }
95*ec63e07aSXin Li return inbuf;
96*ec63e07aSXin Li }
97*ec63e07aSXin Li
TEST_F(Woff2SapiSandboxTest,Compress)98*ec63e07aSXin Li TEST_F(Woff2SapiSandboxTest, Compress) {
99*ec63e07aSXin Li auto result = ReadFile("Roboto-Regular.ttf");
100*ec63e07aSXin Li ASSERT_THAT(result, IsOk());
101*ec63e07aSXin Li sapi::v::Array array(result->data(), result->size());
102*ec63e07aSXin Li sapi::v::GenericPtr p;
103*ec63e07aSXin Li sapi::v::IntBase<size_t> out_length;
104*ec63e07aSXin Li auto compress_result = api_->WOFF2_ConvertTTFToWOFF2(
105*ec63e07aSXin Li array.PtrBefore(), result->size(), p.PtrAfter(), out_length.PtrAfter());
106*ec63e07aSXin Li ASSERT_THAT(compress_result, IsOk());
107*ec63e07aSXin Li ASSERT_TRUE(compress_result.value());
108*ec63e07aSXin Li ASSERT_THAT(p.GetValue(), Not(Eq(0)));
109*ec63e07aSXin Li auto ptr = sapi::v::RemotePtr{reinterpret_cast<void*>(p.GetValue())};
110*ec63e07aSXin Li ASSERT_THAT(api_->WOFF2_Free(&ptr), IsOk());
111*ec63e07aSXin Li }
112*ec63e07aSXin Li
TEST_F(Woff2SapiSandboxTest,Decompress)113*ec63e07aSXin Li TEST_F(Woff2SapiSandboxTest, Decompress) {
114*ec63e07aSXin Li auto result = ReadFile("Roboto-Regular.woff2");
115*ec63e07aSXin Li ASSERT_THAT(result, IsOk());
116*ec63e07aSXin Li sapi::v::Array array(result->data(), result->size());
117*ec63e07aSXin Li sapi::v::GenericPtr p;
118*ec63e07aSXin Li sapi::v::IntBase<size_t> out_length;
119*ec63e07aSXin Li auto decompress_result = api_->WOFF2_ConvertWOFF2ToTTF(
120*ec63e07aSXin Li array.PtrBefore(), result->size(), p.PtrAfter(), out_length.PtrAfter(),
121*ec63e07aSXin Li 1 << 25);
122*ec63e07aSXin Li ASSERT_THAT(decompress_result, IsOk());
123*ec63e07aSXin Li ASSERT_TRUE(decompress_result.value());
124*ec63e07aSXin Li ASSERT_THAT(p.GetValue(), Not(Eq(0)));
125*ec63e07aSXin Li auto ptr = sapi::v::RemotePtr{reinterpret_cast<void*>(p.GetValue())};
126*ec63e07aSXin Li ASSERT_THAT(api_->WOFF2_Free(&ptr), IsOk());
127*ec63e07aSXin Li }
128*ec63e07aSXin Li
129*ec63e07aSXin Li } // namespace
130