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
15namespace {
16
17class MockIndirectObjectHolder : public CPDF_IndirectObjectHolder {
18 public:
19  MockIndirectObjectHolder() {}
20  ~MockIndirectObjectHolder() override {}
21
22  MOCK_METHOD1(ParseIndirectObject,
23               std::unique_ptr<CPDF_Object>(uint32_t objnum));
24};
25
26}  // namespace
27
28TEST(CPDF_IndirectObjectHolderTest, RecursiveParseOfSameObject) {
29  MockIndirectObjectHolder mock_holder;
30  // ParseIndirectObject should not be called again on recursively same object
31  // parse request.
32  EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_))
33      .WillOnce(::testing::WithArg<0>(::testing::Invoke(
34          [&mock_holder](uint32_t objnum) -> std::unique_ptr<CPDF_Object> {
35            const CPDF_Object* same_parse =
36                mock_holder.GetOrParseIndirectObject(objnum);
37            CHECK(!same_parse);
38            return pdfium::MakeUnique<CPDF_Null>();
39          })));
40
41  EXPECT_TRUE(mock_holder.GetOrParseIndirectObject(1000));
42}
43
44TEST(CPDF_IndirectObjectHolderTest, GetObjectMethods) {
45  static constexpr uint32_t kObjNum = 1000;
46  MockIndirectObjectHolder mock_holder;
47
48  EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0);
49  EXPECT_FALSE(mock_holder.GetIndirectObject(kObjNum));
50  ::testing::Mock::VerifyAndClearExpectations(&mock_holder);
51
52  EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_))
53      .WillOnce(::testing::WithArg<0>(::testing::Invoke(
54          [](uint32_t objnum) -> std::unique_ptr<CPDF_Object> {
55            return pdfium::MakeUnique<CPDF_Null>();
56          })));
57  EXPECT_TRUE(mock_holder.GetOrParseIndirectObject(kObjNum));
58  ::testing::Mock::VerifyAndClearExpectations(&mock_holder);
59
60  EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0);
61  ASSERT_TRUE(mock_holder.GetIndirectObject(kObjNum));
62  ::testing::Mock::VerifyAndClearExpectations(&mock_holder);
63
64  EXPECT_EQ(kObjNum, mock_holder.GetIndirectObject(kObjNum)->GetObjNum());
65}
66
67TEST(CPDF_IndirectObjectHolderTest, ParseInvalidObjNum) {
68  MockIndirectObjectHolder mock_holder;
69
70  EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0);
71  EXPECT_FALSE(
72      mock_holder.GetOrParseIndirectObject(CPDF_Object::kInvalidObjNum));
73}
74
75TEST(CPDF_IndirectObjectHolderTest, ReplaceObjectWithInvalidObjNum) {
76  MockIndirectObjectHolder mock_holder;
77
78  EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0);
79  EXPECT_FALSE(mock_holder.ReplaceIndirectObjectIfHigherGeneration(
80      CPDF_Object::kInvalidObjNum, pdfium::MakeUnique<CPDF_Null>()));
81}
82