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/pdb_symbol_record.h"
16 :
17 : #include "base/bind.h"
18 : #include "base/files/file_util.h"
19 : #include "gmock/gmock.h"
20 : #include "gtest/gtest.h"
21 : #include "syzygy/core/unittest_util.h"
22 : #include "syzygy/pdb/pdb_byte_stream.h"
23 : #include "syzygy/pdb/unittest_util.h"
24 : #include "third_party/cci/Files/CvInfo.h"
25 :
26 : namespace cci = Microsoft_Cci_Pdb;
27 :
28 : namespace pdb {
29 :
30 : namespace {
31 :
32 : using testing::_;
33 : using testing::Return;
34 :
35 : class PdbVisitSymbolsTest : public testing::Test {
36 : public:
37 E : void SetUpByteStream() {
38 E : reader = new PdbByteStream();
39 E : writer = reader->GetWritableStream();
40 E : }
41 :
42 : scoped_refptr<PdbStream> reader;
43 : scoped_refptr<WritablePdbStream> writer;
44 : };
45 :
46 : class MockVisitorImpl {
47 : public:
48 E : MOCK_METHOD3(Callback, bool(uint16, uint16, PdbStream*));
49 : };
50 : typedef testing::StrictMock<MockVisitorImpl> MockVisitor;
51 :
52 : } // namespace
53 :
54 E : TEST(PdbReadSymbolRecordTest, ReadValidSymRecordStream) {
55 : base::FilePath valid_sym_record_path = testing::GetSrcRelativePath(
56 E : testing::kValidPdbSymbolRecordStreamPath);
57 :
58 : scoped_refptr<pdb::PdbFileStream> valid_sym_record_stream =
59 E : testing::GetStreamFromFile(valid_sym_record_path);
60 E : SymbolRecordVector symbol_vector;
61 : EXPECT_TRUE(ReadSymbolRecord(valid_sym_record_stream.get(),
62 : valid_sym_record_stream->length(),
63 E : &symbol_vector));
64 E : }
65 :
66 E : TEST(PdbReadSymbolRecordTest, ReadInvalidSymRecordStream) {
67 : base::FilePath invalid_sym_record_path = testing::GetSrcRelativePath(
68 E : testing::kInvalidPdbSymbolRecordStreamPath);
69 :
70 : scoped_refptr<pdb::PdbFileStream> invalid_sym_record_stream =
71 E : testing::GetStreamFromFile(invalid_sym_record_path);
72 E : SymbolRecordVector symbol_vector;
73 : EXPECT_FALSE(ReadSymbolRecord(invalid_sym_record_stream.get(),
74 : invalid_sym_record_stream->length(),
75 E : &symbol_vector));
76 E : }
77 :
78 E : TEST_F(PdbVisitSymbolsTest, FailsOnInvalidTableSize) {
79 E : SetUpByteStream();
80 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
81 E : writer->Write(static_cast<uint16>(4)); // Symbol length.
82 E : writer->Write(static_cast<uint16>(0x2937)); // Made up symbol type.
83 E : writer->Write(static_cast<uint16>(0)); // Dummy data.
84 :
85 E : MockVisitor visitor;
86 : VisitSymbolsCallback callback = base::Bind(
87 E : &MockVisitor::Callback, base::Unretained(&visitor));
88 :
89 : // Don't expect any calls to the visitor callback.
90 : EXPECT_FALSE(
91 E : VisitSymbols(callback, 2 * reader->length(), true, reader.get()));
92 E : }
93 :
94 E : TEST_F(PdbVisitSymbolsTest, FailsOnMissingStreamType) {
95 E : SetUpByteStream();
96 :
97 E : MockVisitor visitor;
98 : VisitSymbolsCallback callback = base::Bind(
99 E : &MockVisitor::Callback, base::Unretained(&visitor));
100 :
101 : // Don't expect any calls to the visitor callback.
102 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader.get()));
103 E : }
104 :
105 E : TEST_F(PdbVisitSymbolsTest, FailsOnInvalidStreamType) {
106 E : SetUpByteStream();
107 E : writer->Write(static_cast<uint32>(cci::C11)); // Symbol stream type.
108 E : writer->Write(static_cast<uint16>(0)); // Symbol length.
109 :
110 E : MockVisitor visitor;
111 : VisitSymbolsCallback callback = base::Bind(
112 E : &MockVisitor::Callback, base::Unretained(&visitor));
113 :
114 : // Don't expect any calls to the visitor callback.
115 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader.get()));
116 E : }
117 :
118 E : TEST_F(PdbVisitSymbolsTest, FailsOnMissingSymbolLength) {
119 E : SetUpByteStream();
120 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
121 E : writer->Write(static_cast<uint8>(1)); // Partial symbol stream length.
122 :
123 E : MockVisitor visitor;
124 : VisitSymbolsCallback callback = base::Bind(
125 E : &MockVisitor::Callback, base::Unretained(&visitor));
126 :
127 : // Don't expect any calls to the visitor callback.
128 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader.get()));
129 E : }
130 :
131 E : TEST_F(PdbVisitSymbolsTest, FailsOnShortSymbolLength) {
132 E : SetUpByteStream();
133 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
134 E : writer->Write(static_cast<uint16>(1)); // Symbol length.
135 :
136 E : MockVisitor visitor;
137 : VisitSymbolsCallback callback = base::Bind(
138 E : &MockVisitor::Callback, base::Unretained(&visitor));
139 :
140 : // Don't expect any calls to the visitor callback.
141 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader.get()));
142 E : }
143 :
144 E : TEST_F(PdbVisitSymbolsTest, FailsOnMissingSymbolType) {
145 E : SetUpByteStream();
146 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
147 E : writer->Write(static_cast<uint16>(4)); // Symbol length.
148 :
149 E : MockVisitor visitor;
150 : VisitSymbolsCallback callback = base::Bind(
151 E : &MockVisitor::Callback, base::Unretained(&visitor));
152 :
153 : // Don't expect any calls to the visitor callback.
154 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader.get()));
155 E : }
156 :
157 E : TEST_F(PdbVisitSymbolsTest, FailsOnMissingSymbolData) {
158 E : SetUpByteStream();
159 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
160 E : writer->Write(static_cast<uint16>(4)); // Symbol length.
161 E : writer->Write(static_cast<uint16>(0x1337)); // Symbol type.
162 :
163 E : MockVisitor visitor;
164 : VisitSymbolsCallback callback = base::Bind(
165 E : &MockVisitor::Callback, base::Unretained(&visitor));
166 :
167 : // Don't expect any calls to the visitor callback.
168 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader.get()));
169 E : }
170 :
171 E : TEST_F(PdbVisitSymbolsTest, SucceedsOnEmptySymbolStream) {
172 E : SetUpByteStream();
173 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
174 E : writer->Write(static_cast<uint16>(0)); // Symbol length.
175 :
176 E : MockVisitor visitor;
177 : VisitSymbolsCallback callback = base::Bind(
178 E : &MockVisitor::Callback, base::Unretained(&visitor));
179 :
180 : // Don't expect any calls to the visitor callback.
181 E : EXPECT_TRUE(VisitSymbols(callback, reader->length(), true, reader.get()));
182 E : }
183 :
184 E : TEST_F(PdbVisitSymbolsTest, EarlyTermination) {
185 E : SetUpByteStream();
186 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
187 E : writer->Write(static_cast<uint16>(4)); // Symbol length.
188 E : writer->Write(static_cast<uint16>(0x2937)); // Made up symbol type.
189 E : writer->Write(static_cast<uint16>(0)); // Dummy data.
190 :
191 E : MockVisitor visitor;
192 : VisitSymbolsCallback callback = base::Bind(
193 E : &MockVisitor::Callback, base::Unretained(&visitor));
194 :
195 E : EXPECT_CALL(visitor, Callback(_, _, _)).Times(1).WillOnce(Return(false));
196 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader.get()));
197 E : }
198 :
199 E : TEST_F(PdbVisitSymbolsTest, AllSymbolsVisitedNoHeader) {
200 : base::FilePath valid_sym_record_path = testing::GetSrcRelativePath(
201 E : testing::kValidPdbSymbolRecordStreamPath);
202 :
203 E : reader = testing::GetStreamFromFile(valid_sym_record_path);
204 :
205 E : MockVisitor visitor;
206 : VisitSymbolsCallback callback = base::Bind(
207 E : &MockVisitor::Callback, base::Unretained(&visitor));
208 :
209 : // There are 697 symbols in the sample symbol stream in test_data.
210 : EXPECT_CALL(visitor, Callback(_, _, _)).Times(697).
211 E : WillRepeatedly(Return(true));
212 E : EXPECT_TRUE(VisitSymbols(callback, reader->length(), false, reader.get()));
213 E : }
214 :
215 : } // namespace pdb
|