blob: ae78b8fbd1577a21934dbd7b28af82f8e4558703 [file] [log] [blame]
// Copyright 2014 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/ar/ar_reader.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "syzygy/ar/unittest_util.h"
#include "syzygy/core/unittest_util.h"
namespace ar {
namespace {
// Test fixture.
class ArReaderTest : public testing::Test {
public:
virtual void SetUp() OVERRIDE {
lib_path_ = testing::GetSrcRelativePath(testing::kArchiveFile);
}
void InverseIsCorrect(const ArReader& reader) {
ArReader::FileNameMap::const_iterator file_it =
reader.files_inverse().begin();
for (; file_it != reader.files_inverse().end(); ++file_it)
EXPECT_EQ(file_it->first, reader.files()[file_it->second]);
}
base::FilePath lib_path_;
};
} // namespace
TEST_F(ArReaderTest, InitAndBuildFileIndex) {
ArReader reader;
EXPECT_TRUE(reader.path().empty());
EXPECT_TRUE(reader.symbols().empty());
EXPECT_TRUE(reader.offsets().empty());
EXPECT_TRUE(reader.files().empty());
EXPECT_TRUE(reader.files_inverse().empty());
EXPECT_TRUE(reader.Init(lib_path_));
EXPECT_EQ(lib_path_, reader.path());
EXPECT_EQ(testing::kArchiveSymbolCount, reader.symbols().size());
EXPECT_EQ(testing::kArchiveFileCount, reader.offsets().size());
EXPECT_TRUE(reader.files().empty());
EXPECT_TRUE(reader.files_inverse().empty());
// Check some of the symbols for accuracy.
SymbolIndexMap symbols;
symbols.insert(std::make_pair(std::string("_MOZ_Z_crc32"), 12));
SymbolIndexMap::const_iterator sym_it = symbols.begin();
for (; sym_it != symbols.end(); ++sym_it) {
SymbolIndexMap::const_iterator sym_it2 = reader.symbols().find(
sym_it->first);
ASSERT_TRUE(sym_it2 != reader.symbols().end());
EXPECT_EQ(*sym_it, *sym_it2);
}
// Build the filename map.
EXPECT_TRUE(reader.BuildFileIndex());
EXPECT_EQ(lib_path_, reader.path());
EXPECT_EQ(testing::kArchiveSymbolCount, reader.symbols().size());
EXPECT_EQ(testing::kArchiveFileCount, reader.offsets().size());
EXPECT_EQ(15u, reader.files().size());
EXPECT_EQ(15u, reader.files_inverse().size());
// Double check the filename map inverts properly.
EXPECT_NO_FATAL_FAILURE(InverseIsCorrect(reader));
typedef std::pair<std::string, uint64> FileInfo;
typedef std::vector<FileInfo> FileInfos;
FileInfos expected, observed;
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\zutil.obj"), 6179ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\uncompr.obj"), 3172ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\trees.obj"), 38365ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\inftrees.obj"), 7710ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\inflate.obj"), 38078ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\inffast.obj"), 7577ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\infback.obj"), 19688ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\gzwrite.obj"), 14454ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\gzread.obj"), 21369ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\gzlib.obj"), 17426ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\gzclose.obj"), 3843ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\deflate.obj"), 46559ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\crc32.obj"), 21713ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\compress.obj"), 4302ul));
expected.push_back(std::make_pair(std::string(
"..\\..\\build\\Debug\\obj\\zlib\\adler32.obj"), 6738ul));
// Ensure that all of the streams have the name and size that we expect.
ParsedArFileHeader header;
DataBuffer data, data7;
for (size_t i = 0; i < reader.offsets().size(); ++i) {
EXPECT_TRUE(reader.HasNext());
EXPECT_TRUE(reader.ExtractNext(&header, &data));
EXPECT_EQ(data.size(), header.size);
observed.push_back(std::make_pair(header.name, header.size));
// Keep around the data from one of the streams.
if (i == 7)
std::swap(data, data7);
}
EXPECT_FALSE(reader.HasNext());
EXPECT_THAT(observed, testing::ContainerEq(expected));
// Ensure that a random access read works as expected.
EXPECT_TRUE(reader.Extract(7, &header, &data));
EXPECT_EQ(data7, data);
EXPECT_TRUE(reader.HasNext());
}
TEST_F(ArReaderTest, NoFilenameTable) {
base::FilePath lib = testing::GetSrcRelativePath(
testing::kWeakSymbolArchiveFile);
ArReader reader;
EXPECT_TRUE(reader.Init(lib));
EXPECT_TRUE(reader.BuildFileIndex());
EXPECT_EQ(testing::kWeakSymbolArchiveSymbolCount, reader.symbols().size());
EXPECT_EQ(testing::kWeakSymbolArchiveFileCount, reader.offsets().size());
EXPECT_EQ(testing::kWeakSymbolArchiveFileCount, reader.files().size());
}
TEST_F(ArReaderTest, DuplicateFileNames) {
base::FilePath lib = testing::GetSrcRelativePath(
testing::kDuplicatesArchiveFile);
ArReader reader;
EXPECT_TRUE(reader.Init(lib));
EXPECT_TRUE(reader.BuildFileIndex());
EXPECT_EQ(reader.files().size(), reader.files_inverse().size());
EXPECT_NO_FATAL_FAILURE(InverseIsCorrect(reader));
std::set<std::string> unique_files;
for (size_t i = 0; i < reader.files().size(); ++i)
unique_files.insert(reader.files()[i]);
EXPECT_LT(unique_files.size(), reader.files().size());
}
TEST_F(ArReaderTest, EmptyFiles) {
base::FilePath lib = testing::GetSrcRelativePath(
testing::kEmptyFilesArchiveFile);
ArReader reader;
EXPECT_TRUE(reader.Init(lib));
EXPECT_EQ(1u, reader.offsets().size());
EXPECT_TRUE(reader.BuildFileIndex());
EXPECT_EQ(1u, reader.files().size());
}
} // namespace ar