blob: 4297b670fcea4c22585c9e919cbec03b9c7e86b0 [file] [log] [blame]
// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "syzygy/pdb/pdb_symbol_record.h"
#include "base/bind.h"
#include "base/file_util.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "syzygy/core/unittest_util.h"
#include "syzygy/pdb/pdb_byte_stream.h"
#include "syzygy/pdb/unittest_util.h"
#include "third_party/cci/Files/CvInfo.h"
namespace cci = Microsoft_Cci_Pdb;
namespace pdb {
namespace {
using testing::_;
using testing::Return;
class PdbVisitSymbolsTest : public testing::Test {
public:
void SetUpByteStream() {
reader = new PdbByteStream();
writer = reader->GetWritablePdbStream();
}
scoped_refptr<PdbStream> reader;
scoped_refptr<WritablePdbStream> writer;
};
class MockVisitorImpl {
public:
MOCK_METHOD3(Callback, bool(uint16, uint16, PdbStream*));
};
typedef testing::StrictMock<MockVisitorImpl> MockVisitor;
} // namespace
TEST(PdbReadSymbolRecordTest, ReadValidSymRecordStream) {
base::FilePath valid_sym_record_path = testing::GetSrcRelativePath(
testing::kValidPdbSymbolRecordStreamPath);
scoped_refptr<pdb::PdbFileStream> valid_sym_record_stream =
testing::GetStreamFromFile(valid_sym_record_path);
SymbolRecordVector symbol_vector;
EXPECT_TRUE(ReadSymbolRecord(valid_sym_record_stream.get(),
valid_sym_record_stream->length(),
&symbol_vector));
}
TEST(PdbReadSymbolRecordTest, ReadInvalidSymRecordStream) {
base::FilePath invalid_sym_record_path = testing::GetSrcRelativePath(
testing::kInvalidPdbSymbolRecordStreamPath);
scoped_refptr<pdb::PdbFileStream> invalid_sym_record_stream =
testing::GetStreamFromFile(invalid_sym_record_path);
SymbolRecordVector symbol_vector;
EXPECT_FALSE(ReadSymbolRecord(invalid_sym_record_stream.get(),
invalid_sym_record_stream->length(),
&symbol_vector));
}
TEST_F(PdbVisitSymbolsTest, FailsOnInvalidTableSize) {
SetUpByteStream();
writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint16>(4)); // Symbol length.
writer->Write(static_cast<uint16>(0x2937)); // Made up symbol type.
writer->Write(static_cast<uint16>(0)); // Dummy data.
MockVisitor visitor;
VisitSymbolsCallback callback = base::Bind(
&MockVisitor::Callback, base::Unretained(&visitor));
// Don't expect any calls to the visitor callback.
EXPECT_FALSE(VisitSymbols(callback, 2 * reader->length(), true, reader));
}
TEST_F(PdbVisitSymbolsTest, FailsOnMissingStreamType) {
SetUpByteStream();
MockVisitor visitor;
VisitSymbolsCallback callback = base::Bind(
&MockVisitor::Callback, base::Unretained(&visitor));
// Don't expect any calls to the visitor callback.
EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
}
TEST_F(PdbVisitSymbolsTest, FailsOnInvalidStreamType) {
SetUpByteStream();
writer->Write(static_cast<uint32>(cci::C11)); // Symbol stream type.
writer->Write(static_cast<uint16>(0)); // Symbol length.
MockVisitor visitor;
VisitSymbolsCallback callback = base::Bind(
&MockVisitor::Callback, base::Unretained(&visitor));
// Don't expect any calls to the visitor callback.
EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
}
TEST_F(PdbVisitSymbolsTest, FailsOnMissingSymbolLength) {
SetUpByteStream();
writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint8>(1)); // Partial symbol stream length.
MockVisitor visitor;
VisitSymbolsCallback callback = base::Bind(
&MockVisitor::Callback, base::Unretained(&visitor));
// Don't expect any calls to the visitor callback.
EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
}
TEST_F(PdbVisitSymbolsTest, FailsOnShortSymbolLength) {
SetUpByteStream();
writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint16>(1)); // Symbol length.
MockVisitor visitor;
VisitSymbolsCallback callback = base::Bind(
&MockVisitor::Callback, base::Unretained(&visitor));
// Don't expect any calls to the visitor callback.
EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
}
TEST_F(PdbVisitSymbolsTest, FailsOnMissingSymbolType) {
SetUpByteStream();
writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint16>(4)); // Symbol length.
MockVisitor visitor;
VisitSymbolsCallback callback = base::Bind(
&MockVisitor::Callback, base::Unretained(&visitor));
// Don't expect any calls to the visitor callback.
EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
}
TEST_F(PdbVisitSymbolsTest, FailsOnMissingSymbolData) {
SetUpByteStream();
writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint16>(4)); // Symbol length.
writer->Write(static_cast<uint16>(0x1337)); // Symbol type.
MockVisitor visitor;
VisitSymbolsCallback callback = base::Bind(
&MockVisitor::Callback, base::Unretained(&visitor));
// Don't expect any calls to the visitor callback.
EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
}
TEST_F(PdbVisitSymbolsTest, SucceedsOnEmptySymbolStream) {
SetUpByteStream();
writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint16>(0)); // Symbol length.
MockVisitor visitor;
VisitSymbolsCallback callback = base::Bind(
&MockVisitor::Callback, base::Unretained(&visitor));
// Don't expect any calls to the visitor callback.
EXPECT_TRUE(VisitSymbols(callback, reader->length(), true, reader));
}
TEST_F(PdbVisitSymbolsTest, EarlyTermination) {
SetUpByteStream();
writer->Write(static_cast<uint32>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint16>(4)); // Symbol length.
writer->Write(static_cast<uint16>(0x2937)); // Made up symbol type.
writer->Write(static_cast<uint16>(0)); // Dummy data.
MockVisitor visitor;
VisitSymbolsCallback callback = base::Bind(
&MockVisitor::Callback, base::Unretained(&visitor));
EXPECT_CALL(visitor, Callback(_, _, _)).Times(1).WillOnce(Return(false));
EXPECT_FALSE(VisitSymbols(callback, reader->length(), true, reader));
}
TEST_F(PdbVisitSymbolsTest, AllSymbolsVisitedNoHeader) {
base::FilePath valid_sym_record_path = testing::GetSrcRelativePath(
testing::kValidPdbSymbolRecordStreamPath);
reader = testing::GetStreamFromFile(valid_sym_record_path);
MockVisitor visitor;
VisitSymbolsCallback callback = base::Bind(
&MockVisitor::Callback, base::Unretained(&visitor));
// There are 697 symbols in the sample symbol stream in test_data.
EXPECT_CALL(visitor, Callback(_, _, _)).Times(697).
WillRepeatedly(Return(true));
EXPECT_TRUE(VisitSymbols(callback, reader->length(), false, reader));
}
} // namespace pdb