1 // Copyright 2017 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "core/fpdfapi/parser/cpdf_null.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/base/ptr_util.h"
14
15 namespace {
16
17 class MockIndirectObjectHolder final : public CPDF_IndirectObjectHolder {
18 public:
MockIndirectObjectHolder()19 MockIndirectObjectHolder() {}
~MockIndirectObjectHolder()20 ~MockIndirectObjectHolder() override {}
21
22 MOCK_METHOD1(ParseIndirectObject, RetainPtr<CPDF_Object>(uint32_t objnum));
23 };
24
25 } // namespace
26
TEST(CPDF_IndirectObjectHolderTest,RecursiveParseOfSameObject)27 TEST(CPDF_IndirectObjectHolderTest, RecursiveParseOfSameObject) {
28 MockIndirectObjectHolder mock_holder;
29 // ParseIndirectObject should not be called again on recursively same object
30 // parse request.
31 EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_))
32 .WillOnce(::testing::WithArg<0>(::testing::Invoke(
33 [&mock_holder](uint32_t objnum) -> RetainPtr<CPDF_Object> {
34 const CPDF_Object* same_parse =
35 mock_holder.GetOrParseIndirectObject(objnum);
36 CHECK(!same_parse);
37 return pdfium::MakeRetain<CPDF_Null>();
38 })));
39
40 EXPECT_TRUE(mock_holder.GetOrParseIndirectObject(1000));
41 }
42
TEST(CPDF_IndirectObjectHolderTest,GetObjectMethods)43 TEST(CPDF_IndirectObjectHolderTest, GetObjectMethods) {
44 static constexpr uint32_t kObjNum = 1000;
45 MockIndirectObjectHolder mock_holder;
46
47 EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0);
48 EXPECT_FALSE(mock_holder.GetIndirectObject(kObjNum));
49 ::testing::Mock::VerifyAndClearExpectations(&mock_holder);
50
51 EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_))
52 .WillOnce(::testing::WithArg<0>(
53 ::testing::Invoke([](uint32_t objnum) -> RetainPtr<CPDF_Object> {
54 return pdfium::MakeRetain<CPDF_Null>();
55 })));
56 EXPECT_TRUE(mock_holder.GetOrParseIndirectObject(kObjNum));
57 ::testing::Mock::VerifyAndClearExpectations(&mock_holder);
58
59 EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0);
60 ASSERT_TRUE(mock_holder.GetIndirectObject(kObjNum));
61 ::testing::Mock::VerifyAndClearExpectations(&mock_holder);
62
63 EXPECT_EQ(kObjNum, mock_holder.GetIndirectObject(kObjNum)->GetObjNum());
64 }
65
TEST(CPDF_IndirectObjectHolderTest,ParseInvalidObjNum)66 TEST(CPDF_IndirectObjectHolderTest, ParseInvalidObjNum) {
67 MockIndirectObjectHolder mock_holder;
68
69 EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0);
70 EXPECT_FALSE(
71 mock_holder.GetOrParseIndirectObject(CPDF_Object::kInvalidObjNum));
72 }
73
TEST(CPDF_IndirectObjectHolderTest,ReplaceObjectWithInvalidObjNum)74 TEST(CPDF_IndirectObjectHolderTest, ReplaceObjectWithInvalidObjNum) {
75 MockIndirectObjectHolder mock_holder;
76
77 EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0);
78 EXPECT_FALSE(mock_holder.ReplaceIndirectObjectIfHigherGeneration(
79 CPDF_Object::kInvalidObjNum, pdfium::MakeRetain<CPDF_Null>()));
80 }
81