1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "page.h"
18
19 #include <android-base/file.h>
20 #include <gtest/gtest.h>
21
22 #include <memory>
23 #include <string>
24
25 // Goes first due to conflicts.
26 #include "document.h"
27 #include "rect.h"
28 // #include "file/base/path.h"
29 #include "cpp/fpdf_scopers.h"
30 #include "fpdfview.h"
31
32 namespace {
33
34 using ::pdfClient::Document;
35 using ::pdfClient::Page;
36 using ::pdfClient::Rectangle_i;
37
38 static const std::string kTestdata = "testdata";
39 static const std::string kSekretNoPassword = "sekret_no_password.pdf";
40
GetTestDataDir()41 std::string GetTestDataDir() {
42 return android::base::GetExecutableDirectory();
43 }
44
GetTestFile(std::string filename)45 std::string GetTestFile(std::string filename) {
46 return GetTestDataDir() + "/" + kTestdata + "/" + filename;
47 }
48
LoadTestDocument(const std::string filename)49 ScopedFPDFDocument LoadTestDocument(const std::string filename) {
50 return ScopedFPDFDocument(FPDF_LoadDocument(GetTestFile(filename).c_str(), nullptr));
51 }
52
53 // Note on coordinates used in below tests:
54 // This document has height == 792. Due to constraints of rect.h functions
55 // that require top < bottom, top/bottom are flipped from what page
56 // coordinates normally would be in these examples. So expected values when
57 // we consume the rectangles in this test are: top = (792 - bottom),
58 // bottom = (792 - top).
59
60 /*
61 * Test that when a single rectangle is passed to NotifyInvalidRect
62 * invalid_rect_ will match its coordinates.
63 */
TEST(Test,NotifyInvalidRectSingleRectTest)64 TEST(Test, NotifyInvalidRectSingleRectTest) {
65 Document doc(LoadTestDocument(kSekretNoPassword), false);
66
67 std::shared_ptr<Page> page = doc.GetPage(0);
68 EXPECT_FALSE(page->HasInvalidRect());
69 page->NotifyInvalidRect(pdfClient::IntRect(100, 100, 200, 200));
70
71 EXPECT_TRUE(page->HasInvalidRect());
72 Rectangle_i expected = Rectangle_i{100, 592, 200, 692};
73 ASSERT_EQ(expected, page->ConsumeInvalidRect());
74 }
75
76 /*
77 * Tests the coalescing of rectangles. Result should be the minimal rectangle
78 * that covers all rectangles that have been added.
79 */
TEST(Test,NotifyInvalidRectCoalesceTest)80 TEST(Test, NotifyInvalidRectCoalesceTest) {
81 Document doc(LoadTestDocument(kSekretNoPassword), false);
82
83 std::shared_ptr<Page> page = doc.GetPage(0);
84 EXPECT_FALSE(page->HasInvalidRect());
85
86 page->NotifyInvalidRect(pdfClient::IntRect(100, 100, 200, 200));
87 page->NotifyInvalidRect(pdfClient::IntRect(400, 100, 500, 200));
88 page->NotifyInvalidRect(pdfClient::IntRect(100, 400, 200, 500));
89 EXPECT_TRUE(page->HasInvalidRect());
90 Rectangle_i expected = Rectangle_i{100, 292, 500, 692};
91 ASSERT_EQ(expected, page->ConsumeInvalidRect());
92 }
93
94 /*
95 * Tests adding a rectangle to invalid_rect_ whose area is already covered by
96 * the existing rect. Should not change boundaries.
97 */
TEST(Test,NotifyInvalidRectAlreadyCoveredTest)98 TEST(Test, NotifyInvalidRectAlreadyCoveredTest) {
99 Document doc(LoadTestDocument(kSekretNoPassword), false);
100
101 std::shared_ptr<Page> page = doc.GetPage(0);
102 EXPECT_FALSE(page->HasInvalidRect());
103
104 page->NotifyInvalidRect(pdfClient::IntRect(100, 100, 200, 200));
105 page->NotifyInvalidRect(pdfClient::IntRect(400, 100, 500, 200));
106 page->NotifyInvalidRect(pdfClient::IntRect(100, 400, 200, 500));
107 // add a rectangle that's already covered by existing one
108 page->NotifyInvalidRect(pdfClient::IntRect(400, 400, 500, 500));
109 EXPECT_TRUE(page->HasInvalidRect());
110 Rectangle_i expected = Rectangle_i{100, 292, 500, 692};
111 ASSERT_EQ(expected, page->ConsumeInvalidRect());
112 }
113
114 /**
115 * Try calling NotifyInvalidRect with negative indices. No error should be
116 * thrown. Confirm all rectangles have been ignored by the page.
117 */
TEST(Test,NotifyInvalidRectNegativeIndicesTest)118 TEST(Test, NotifyInvalidRectNegativeIndicesTest) {
119 Document doc(LoadTestDocument(kSekretNoPassword), false);
120 std::shared_ptr<Page> page = doc.GetPage(0);
121
122 page->NotifyInvalidRect(pdfClient::IntRect(-100, 100, 200, 200));
123 page->NotifyInvalidRect(pdfClient::IntRect(400, -100, 500, 200));
124 page->NotifyInvalidRect(pdfClient::IntRect(100, 400, -200, 500));
125 page->NotifyInvalidRect(pdfClient::IntRect(400, 400, 500, -500));
126 EXPECT_FALSE(page->HasInvalidRect());
127 }
128
129 /**
130 * Try calling NotifyInvalidRect with empty rectangles. No error should be
131 * thrown. Confirm all rectangles have been ignored by the page.
132 */
TEST(Test,NotifyInvalidRectEmptyRectanglesTest)133 TEST(Test, NotifyInvalidRectEmptyRectanglesTest) {
134 Document doc(LoadTestDocument(kSekretNoPassword), false);
135 std::shared_ptr<Page> page = doc.GetPage(0);
136
137 page->NotifyInvalidRect(pdfClient::IntRect(100, 200, 100, 500));
138 page->NotifyInvalidRect(pdfClient::IntRect(100, 400, 500, 400));
139 page->NotifyInvalidRect(pdfClient::Rectangle_i{100, 200, 0, 500});
140 page->NotifyInvalidRect(pdfClient::Rectangle_i{100, 400, 500, 0});
141 EXPECT_FALSE(page->HasInvalidRect());
142 }
143
144 /**
145 * Test that calling ConsumeInvalidRect resets the rectangle in the Page.
146 */
TEST(Test,ConsumeInvalidRectResetsRectTest)147 TEST(Test, ConsumeInvalidRectResetsRectTest) {
148 Document doc(LoadTestDocument(kSekretNoPassword), false);
149 std::shared_ptr<Page> page = doc.GetPage(0);
150
151 // doesn't have one
152 EXPECT_FALSE(page->HasInvalidRect());
153 page->NotifyInvalidRect(pdfClient::IntRect(100, 100, 200, 200));
154
155 // now has one
156 page->NotifyInvalidRect(pdfClient::IntRect(100, 100, 200, 200));
157 EXPECT_TRUE(page->HasInvalidRect());
158
159 // no longer has one
160 page->ConsumeInvalidRect();
161 EXPECT_FALSE(page->HasInvalidRect());
162
163 // if we call Consume anyway we will receive empty rect
164 Rectangle_i expected = Rectangle_i{0, 0, 0, 0};
165 ASSERT_EQ(expected, page->ConsumeInvalidRect());
166 }
167
168 } // namespace