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));
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 {
72 E : testing::Test::SetUp();
73 E : }
74 :
75 : void ReadActualPdb() {
76 : base::FilePath pdb_path =
77 : testing::GetSrcRelativePath(testing::kTestPdbFilePath);
78 : PdbReader pdb_reader;
79 : EXPECT_TRUE(pdb_reader.Read(pdb_path, &pdb_file_));
80 : }
81 :
82 E : void CheckFooStreamAdded() {
83 : // Read the named stream map and ensure the stream was properly added.
84 E : PdbInfoHeader70 header = {};
85 E : NameStreamMap name_stream_map;
86 E : ASSERT_TRUE(pdb::ReadHeaderInfoStream(pdb_file_, &header,
87 : &name_stream_map));
88 E : ASSERT_TRUE(name_stream_map.count("foo"));
89 E : size_t stream_id = name_stream_map["foo"];
90 E : ASSERT_GT(pdb_file_.StreamCount(), stream_id);
91 E : scoped_refptr<PdbStream> stream(pdb_file_.GetStream(stream_id));
92 E : ASSERT_EQ(mutator_.added_stream_.get(), stream.get());
93 E : }
94 :
95 : StrictMock<MockAddNamedStreamMutator> mutator_;
96 : PdbFile pdb_file_;
97 : };
98 :
99 : } // namespace
100 :
101 E : TEST_F(AddNamedStreamMutatorTest, FailsWithNoHeaderInfoStream) {
102 E : EXPECT_FALSE(mutator_.MutatePdb(&pdb_file_));
103 E : }
104 :
105 E : TEST_F(AddNamedStreamMutatorTest, FailsIfAddNamedStreamsFails) {
106 E : ASSERT_NO_FATAL_FAILURE(testing::InitMockPdbFile(&pdb_file_));
107 : EXPECT_CALL(mutator_, AddNamedStreams(Ref(pdb_file_))).Times(1).
108 E : WillOnce(Return(false));
109 E : EXPECT_FALSE(mutator_.MutatePdb(&pdb_file_));
110 E : }
111 :
112 E : TEST_F(AddNamedStreamMutatorTest, SucceedsWithNoInsertion) {
113 E : ASSERT_NO_FATAL_FAILURE(testing::InitMockPdbFile(&pdb_file_));
114 : EXPECT_CALL(mutator_, AddNamedStreams(Ref(pdb_file_))).Times(1).
115 E : WillOnce(Return(true));
116 E : EXPECT_TRUE(mutator_.MutatePdb(&pdb_file_));
117 E : }
118 :
119 E : TEST_F(AddNamedStreamMutatorTest, SucceedsWithInsertionAndReplacement) {
120 E : ASSERT_NO_FATAL_FAILURE(testing::InitMockPdbFile(&pdb_file_));
121 :
122 : EXPECT_CALL(mutator_, AddNamedStreams(Ref(pdb_file_))).Times(1).
123 E : WillOnce(Invoke(&mutator_, &MockAddNamedStreamMutator::AddFooStream));
124 E : EXPECT_TRUE(mutator_.MutatePdb(&pdb_file_));
125 :
126 E : ASSERT_NO_FATAL_FAILURE(CheckFooStreamAdded());
127 :
128 : EXPECT_CALL(mutator_, AddNamedStreams(Ref(pdb_file_))).Times(1).
129 : WillOnce(Invoke(&mutator_,
130 E : &MockAddNamedStreamMutator::GetAndReplaceFooStream));
131 E : EXPECT_TRUE(mutator_.MutatePdb(&pdb_file_));
132 :
133 E : ASSERT_NO_FATAL_FAILURE(CheckFooStreamAdded());
134 E : }
135 :
136 : } // namespace mutators
137 : } // namespace pdb
|