blob: aec50bbe94ab42166f1f82f182d674dc7dc4bdab [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/files/file_util.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "syzygy/common/binary_stream.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->GetWritableStream();
}
scoped_refptr<PdbStream> reader;
scoped_refptr<WritablePdbStream> writer;
};
class MockVisitorImpl {
public:
MOCK_METHOD3(Callback, bool(uint16_t, uint16_t, common::BinaryStreamReader*));
};
typedef testing::StrictMock<MockVisitorImpl> MockVisitor;
} // namespace
#if 0
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));
}
#endif
TEST_F(PdbVisitSymbolsTest, FailsOnInvalidTableSize) {
SetUpByteStream();
writer->Write(static_cast<uint32_t>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint16_t>(4)); // Symbol length.
writer->Write(static_cast<uint16_t>(0x2937)); // Made up symbol type.
writer->Write(static_cast<uint16_t>(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, 0, 2 * reader->length(), true, reader.get()));
}
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, 0, reader->length(), true, reader.get()));
}
TEST_F(PdbVisitSymbolsTest, FailsOnInvalidStreamType) {
SetUpByteStream();
writer->Write(static_cast<uint32_t>(cci::C11)); // Symbol stream type.
writer->Write(static_cast<uint16_t>(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, 0, reader->length(), true, reader.get()));
}
TEST_F(PdbVisitSymbolsTest, FailsOnMissingSymbolLength) {
SetUpByteStream();
writer->Write(static_cast<uint32_t>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint8_t>(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, 0, reader->length(), true, reader.get()));
}
TEST_F(PdbVisitSymbolsTest, FailsOnShortSymbolLength) {
SetUpByteStream();
writer->Write(static_cast<uint32_t>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint16_t>(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, 0, reader->length(), true, reader.get()));
}
TEST_F(PdbVisitSymbolsTest, FailsOnMissingSymbolType) {
SetUpByteStream();
writer->Write(static_cast<uint32_t>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint16_t>(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, 0, reader->length(), true, reader.get()));
}
TEST_F(PdbVisitSymbolsTest, FailsOnMissingSymbolData) {
SetUpByteStream();
writer->Write(static_cast<uint32_t>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint16_t>(4)); // Symbol length.
writer->Write(static_cast<uint16_t>(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, 0, reader->length(), true, reader.get()));
}
TEST_F(PdbVisitSymbolsTest, SucceedsOnEmptySymbolStream) {
SetUpByteStream();
writer->Write(static_cast<uint32_t>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint16_t>(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, 0, reader->length(), true, reader.get()));
}
TEST_F(PdbVisitSymbolsTest, EarlyTermination) {
SetUpByteStream();
writer->Write(static_cast<uint32_t>(cci::C13)); // Symbol stream type.
writer->Write(static_cast<uint16_t>(4)); // Symbol length.
writer->Write(static_cast<uint16_t>(0x2937)); // Made up symbol type.
writer->Write(static_cast<uint16_t>(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, 0, reader->length(), true, reader.get()));
}
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, 0, reader->length(), false, reader.get()));
}
} // namespace pdb