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/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->GetWritablePdbStream();
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 E : EXPECT_FALSE(VisitSymbols(callback, 2 * reader->length(), true, reader));
91 E : }
92 :
93 E : TEST_F(PdbVisitSymbolsTest, FailsOnMissingStreamType) {
94 E : SetUpByteStream();
95 :
96 E : MockVisitor visitor;
97 : VisitSymbolsCallback callback = base::Bind(
98 E : &MockVisitor::Callback, base::Unretained(&visitor));
99 :
100 : // Don't expect any calls to the visitor callback.
101 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
102 E : }
103 :
104 E : TEST_F(PdbVisitSymbolsTest, FailsOnInvalidStreamType) {
105 E : SetUpByteStream();
106 E : writer->Write(static_cast<uint32>(cci::C11)); // Symbol stream type.
107 E : writer->Write(static_cast<uint16>(0)); // Symbol length.
108 :
109 E : MockVisitor visitor;
110 : VisitSymbolsCallback callback = base::Bind(
111 E : &MockVisitor::Callback, base::Unretained(&visitor));
112 :
113 : // Don't expect any calls to the visitor callback.
114 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
115 E : }
116 :
117 E : TEST_F(PdbVisitSymbolsTest, FailsOnMissingSymbolLength) {
118 E : SetUpByteStream();
119 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
120 E : writer->Write(static_cast<uint8>(1)); // Partial symbol stream length.
121 :
122 E : MockVisitor visitor;
123 : VisitSymbolsCallback callback = base::Bind(
124 E : &MockVisitor::Callback, base::Unretained(&visitor));
125 :
126 : // Don't expect any calls to the visitor callback.
127 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
128 E : }
129 :
130 E : TEST_F(PdbVisitSymbolsTest, FailsOnShortSymbolLength) {
131 E : SetUpByteStream();
132 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
133 E : writer->Write(static_cast<uint16>(1)); // Symbol length.
134 :
135 E : MockVisitor visitor;
136 : VisitSymbolsCallback callback = base::Bind(
137 E : &MockVisitor::Callback, base::Unretained(&visitor));
138 :
139 : // Don't expect any calls to the visitor callback.
140 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
141 E : }
142 :
143 E : TEST_F(PdbVisitSymbolsTest, FailsOnMissingSymbolType) {
144 E : SetUpByteStream();
145 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
146 E : writer->Write(static_cast<uint16>(4)); // Symbol length.
147 :
148 E : MockVisitor visitor;
149 : VisitSymbolsCallback callback = base::Bind(
150 E : &MockVisitor::Callback, base::Unretained(&visitor));
151 :
152 : // Don't expect any calls to the visitor callback.
153 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
154 E : }
155 :
156 E : TEST_F(PdbVisitSymbolsTest, FailsOnMissingSymbolData) {
157 E : SetUpByteStream();
158 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
159 E : writer->Write(static_cast<uint16>(4)); // Symbol length.
160 E : writer->Write(static_cast<uint16>(0x1337)); // Symbol type.
161 :
162 E : MockVisitor visitor;
163 : VisitSymbolsCallback callback = base::Bind(
164 E : &MockVisitor::Callback, base::Unretained(&visitor));
165 :
166 : // Don't expect any calls to the visitor callback.
167 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
168 E : }
169 :
170 E : TEST_F(PdbVisitSymbolsTest, SucceedsOnEmptySymbolStream) {
171 E : SetUpByteStream();
172 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
173 E : writer->Write(static_cast<uint16>(0)); // Symbol length.
174 :
175 E : MockVisitor visitor;
176 : VisitSymbolsCallback callback = base::Bind(
177 E : &MockVisitor::Callback, base::Unretained(&visitor));
178 :
179 : // Don't expect any calls to the visitor callback.
180 E : EXPECT_TRUE(VisitSymbols(callback, reader->length(), true, reader));
181 E : }
182 :
183 E : TEST_F(PdbVisitSymbolsTest, EarlyTermination) {
184 E : SetUpByteStream();
185 E : writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
186 E : writer->Write(static_cast<uint16>(4)); // Symbol length.
187 E : writer->Write(static_cast<uint16>(0x2937)); // Made up symbol type.
188 E : writer->Write(static_cast<uint16>(0)); // Dummy data.
189 :
190 E : MockVisitor visitor;
191 : VisitSymbolsCallback callback = base::Bind(
192 E : &MockVisitor::Callback, base::Unretained(&visitor));
193 :
194 E : EXPECT_CALL(visitor, Callback(_, _, _)).Times(1).WillOnce(Return(false));
195 E : EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
196 E : }
197 :
198 E : TEST_F(PdbVisitSymbolsTest, AllSymbolsVisitedNoHeader) {
199 : base::FilePath valid_sym_record_path = testing::GetSrcRelativePath(
200 E : testing::kValidPdbSymbolRecordStreamPath);
201 :
202 E : reader = testing::GetStreamFromFile(valid_sym_record_path);
203 :
204 E : MockVisitor visitor;
205 : VisitSymbolsCallback callback = base::Bind(
206 E : &MockVisitor::Callback, base::Unretained(&visitor));
207 :
208 : // There are 697 symbols in the sample symbol stream in test_data.
209 : EXPECT_CALL(visitor, Callback(_, _, _)).Times(697).
210 E : WillRepeatedly(Return(true));
211 E : EXPECT_TRUE(VisitSymbols(callback, reader->length(), false, reader));
212 E : }
213 :
214 : } // namespace pdb
|