1 : // Copyright 2012 Google Inc. All Rights Reserved.
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 : // http://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 "syzygy/pdb/mutators/add_named_stream_mutator.h"
16 :
17 : #include "gmock/gmock.h"
18 : #include "gtest/gtest.h"
19 : #include "syzygy/core/unittest_util.h"
20 : #include "syzygy/pdb/pdb_byte_stream.h"
21 : #include "syzygy/pdb/pdb_reader.h"
22 : #include "syzygy/pdb/unittest_util.h"
23 :
24 : namespace pdb {
25 : namespace mutators {
26 :
27 : namespace {
28 :
29 : using testing::_;
30 : using testing::Invoke;
31 : using testing::Ref;
32 : using testing::Return;
33 : using testing::StrictMock;
34 :
35 : class MockAddNamedStreamMutator
36 : : public AddNamedStreamMutatorImpl<MockAddNamedStreamMutator> {
37 : public:
38 : static const char kMutatorName[];
39 :
40 E : MOCK_METHOD1(AddNamedStreams, bool(const PdbFile& pdb_file));
41 :
42 E : bool AddFooStream(const PdbFile& pdb_file) {
43 E : scoped_refptr<PdbByteStream> stream(new PdbByteStream());
44 E : EXPECT_TRUE(stream->Init(reinterpret_cast<const uint8*>(kMutatorName),
45 : ::strlen(kMutatorName)));
46 E : added_stream_ = stream;
47 E : EXPECT_TRUE(SetNamedStream("foo", stream.get()));
48 E : return true;
49 E : }
50 :
51 E : bool GetAndReplaceFooStream(const PdbFile& pdb_file) {
52 E : scoped_refptr<PdbStream> foo = GetNamedStream("foo");
53 E : EXPECT_TRUE(foo.get() != NULL);
54 :
55 E : scoped_refptr<PdbByteStream> stream(new PdbByteStream());
56 E : EXPECT_TRUE(stream->Init(foo.get()));
57 :
58 E : added_stream_ = stream;
59 E : EXPECT_FALSE(SetNamedStream("foo", stream.get()));
60 E : return true;
61 E : }
62 :
63 : scoped_refptr<PdbStream> added_stream_;
64 : };
65 :
66 : const char MockAddNamedStreamMutator::kMutatorName[] =
67 : "MockAddNamedStreamMutator";
68 :
69 : class AddNamedStreamMutatorTest : public testing::Test {
70 : public:
71 E : virtual void SetUp() override { testing::Test::SetUp(); }
72 :
73 : void ReadActualPdb() {
74 : base::FilePath pdb_path =
75 : testing::GetSrcRelativePath(testing::kTestPdbFilePath);
76 : PdbReader pdb_reader;
77 : EXPECT_TRUE(pdb_reader.Read(pdb_path, &pdb_file_));
78 : }
79 :
80 E : void CheckFooStreamAdded() {
81 : // Read the named stream map and ensure the stream was properly added.
82 E : PdbInfoHeader70 header = {};
83 E : NameStreamMap name_stream_map;
84 E : ASSERT_TRUE(pdb::ReadHeaderInfoStream(pdb_file_, &header,
85 : &name_stream_map));
86 E : ASSERT_TRUE(name_stream_map.count("foo"));
87 E : size_t stream_id = name_stream_map["foo"];
88 E : ASSERT_GT(pdb_file_.StreamCount(), stream_id);
89 E : scoped_refptr<PdbStream> stream(pdb_file_.GetStream(stream_id));
90 E : ASSERT_EQ(mutator_.added_stream_.get(), stream.get());
91 E : }
92 :
93 : StrictMock<MockAddNamedStreamMutator> mutator_;
94 : PdbFile pdb_file_;
95 : };
96 :
97 : } // namespace
98 :
99 E : TEST_F(AddNamedStreamMutatorTest, FailsWithNoHeaderInfoStream) {
100 E : EXPECT_FALSE(mutator_.MutatePdb(&pdb_file_));
101 E : }
102 :
103 E : TEST_F(AddNamedStreamMutatorTest, FailsIfAddNamedStreamsFails) {
104 E : ASSERT_NO_FATAL_FAILURE(testing::InitMockPdbFile(&pdb_file_));
105 : EXPECT_CALL(mutator_, AddNamedStreams(Ref(pdb_file_))).Times(1).
106 E : WillOnce(Return(false));
107 E : EXPECT_FALSE(mutator_.MutatePdb(&pdb_file_));
108 E : }
109 :
110 E : TEST_F(AddNamedStreamMutatorTest, SucceedsWithNoInsertion) {
111 E : ASSERT_NO_FATAL_FAILURE(testing::InitMockPdbFile(&pdb_file_));
112 : EXPECT_CALL(mutator_, AddNamedStreams(Ref(pdb_file_))).Times(1).
113 E : WillOnce(Return(true));
114 E : EXPECT_TRUE(mutator_.MutatePdb(&pdb_file_));
115 E : }
116 :
117 E : TEST_F(AddNamedStreamMutatorTest, SucceedsWithInsertionAndReplacement) {
118 E : ASSERT_NO_FATAL_FAILURE(testing::InitMockPdbFile(&pdb_file_));
119 :
120 : EXPECT_CALL(mutator_, AddNamedStreams(Ref(pdb_file_))).Times(1).
121 E : WillOnce(Invoke(&mutator_, &MockAddNamedStreamMutator::AddFooStream));
122 E : EXPECT_TRUE(mutator_.MutatePdb(&pdb_file_));
123 :
124 E : ASSERT_NO_FATAL_FAILURE(CheckFooStreamAdded());
125 :
126 : EXPECT_CALL(mutator_, AddNamedStreams(Ref(pdb_file_))).Times(1).
127 : WillOnce(Invoke(&mutator_,
128 E : &MockAddNamedStreamMutator::GetAndReplaceFooStream));
129 E : EXPECT_TRUE(mutator_.MutatePdb(&pdb_file_));
130 :
131 E : ASSERT_NO_FATAL_FAILURE(CheckFooStreamAdded());
132 E : }
133 :
134 : } // namespace mutators
135 : } // namespace pdb
|