1 : // Copyright 2014 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/ar/ar_writer.h"
16 :
17 : #include "base/files/file_util.h"
18 : #include "base/memory/scoped_vector.h"
19 : #include "gmock/gmock.h"
20 : #include "gtest/gtest.h"
21 : #include "syzygy/ar/ar_reader.h"
22 : #include "syzygy/ar/unittest_util.h"
23 : #include "syzygy/core/unittest_util.h"
24 :
25 : namespace ar {
26 :
27 : namespace {
28 :
29 : // A selection of files from zlib.lib, and the number of symbols that should be
30 : // found in each of them when added to an ArWriter.
31 : const wchar_t* kObjectFiles[] = {
32 : L"syzygy\\ar\\test_data\\adler32.obj",
33 : L"syzygy\\ar\\test_data\\compress.obj" };
34 : const size_t kSymbolCounts[] = { 3, 3 };
35 :
36 : // Test fixture.
37 : class ArWriterTest : public testing::Test {
38 : public:
39 E : virtual void SetUp() override {
40 E : for (size_t i = 0; i < arraysize(kObjectFiles); ++i)
41 E : object_files_.push_back(testing::GetSrcRelativePath(kObjectFiles[i]));
42 :
43 E : ASSERT_TRUE(base::CreateNewTempDirectory(L"ArWriterTest",
44 : &temp_dir_));
45 :
46 E : lib_path_ = temp_dir_.Append(L"foo.lib");
47 E : }
48 :
49 E : virtual void TearDown() override {
50 E : ASSERT_TRUE(base::DeleteFile(temp_dir_, true));
51 E : }
52 :
53 E : void AddObjectFiles() {
54 E : for (size_t i = 0; i < object_files_.size(); ++i) {
55 E : size_t old_symbol_count = writer_.symbols().size();
56 E : EXPECT_TRUE(writer_.AddFile(object_files_[i]));
57 E : size_t new_symbol_count = writer_.symbols().size();
58 E : size_t symbol_count = new_symbol_count - old_symbol_count;
59 E : EXPECT_EQ(symbol_count, kSymbolCounts[0]);
60 E : }
61 E : }
62 :
63 E : void AddDuplicateObjectFile() {
64 E : ASSERT_TRUE(contents_.empty());
65 :
66 E : size_t old_symbol_count = writer_.symbols().size();
67 :
68 : // Add the same object file again but with a different name. This should
69 : // cause duplicate symbols to be encountered, but it should't be a problem.
70 E : int64 size = 0;
71 E : ASSERT_TRUE(base::GetFileSize(object_files_[0], &size));
72 E : contents_.resize(size);
73 E : ASSERT_TRUE(base::ReadFile(object_files_[0],
74 : reinterpret_cast<char*>(contents_.data()),
75 : contents_.size()));
76 E : EXPECT_TRUE(writer_.AddFile("foo.obj", base::Time::Now(), 0, &contents_));
77 :
78 E : size_t new_symbol_count = writer_.symbols().size();
79 E : EXPECT_EQ(old_symbol_count, new_symbol_count);
80 E : }
81 :
82 : // The object under test.
83 : ArWriter writer_;
84 :
85 : std::vector<base::FilePath> object_files_;
86 : base::FilePath temp_dir_;
87 : base::FilePath lib_path_;
88 :
89 : // Used by 'AddFirstObjectFileWithNewName'.
90 : DataBuffer contents_;
91 : };
92 :
93 : } // namespace
94 :
95 E : TEST_F(ArWriterTest, AddValidFiles) {
96 E : EXPECT_NO_FATAL_FAILURE(AddObjectFiles());
97 E : EXPECT_NO_FATAL_FAILURE(AddDuplicateObjectFile());
98 E : }
99 :
100 E : TEST_F(ArWriterTest, AddEmptyFileFails) {
101 E : DataBuffer contents;
102 E : EXPECT_FALSE(writer_.AddFile("foo.obj", base::Time::Now(), 0, &contents));
103 E : EXPECT_TRUE(writer_.files().empty());
104 E : EXPECT_TRUE(writer_.symbols().empty());
105 :
106 E : base::FilePath empty_file = temp_dir_.Append(L"empty.obj");
107 E : ASSERT_EQ(0, base::WriteFile(empty_file, NULL, 0));
108 E : ASSERT_TRUE(base::PathExists(empty_file));
109 E : EXPECT_FALSE(writer_.AddFile(empty_file));
110 E : EXPECT_TRUE(writer_.files().empty());
111 E : EXPECT_TRUE(writer_.symbols().empty());
112 E : }
113 :
114 E : TEST_F(ArWriterTest, AddInvalidObjectFileFails) {
115 : static const char kContent[] = "hey there";
116 E : base::FilePath dummy_file = temp_dir_.Append(L"dummy.obj");
117 : ASSERT_EQ(arraysize(kContent),
118 E : base::WriteFile(dummy_file, kContent, arraysize(kContent)));
119 E : ASSERT_TRUE(base::PathExists(dummy_file));
120 E : EXPECT_FALSE(writer_.AddFile(dummy_file));
121 E : EXPECT_TRUE(writer_.files().empty());
122 E : EXPECT_TRUE(writer_.symbols().empty());
123 E : }
124 :
125 E : TEST_F(ArWriterTest, AddRepeatedFiles) {
126 E : EXPECT_EQ(0u, writer_.files().size());
127 E : EXPECT_EQ(0u, writer_.symbols().size());
128 E : EXPECT_TRUE(writer_.AddFile(object_files_[0]));
129 E : EXPECT_EQ(1u, writer_.files().size());
130 E : EXPECT_EQ(kSymbolCounts[0], writer_.symbols().size());
131 E : EXPECT_TRUE(writer_.AddFile(object_files_[0]));
132 E : EXPECT_EQ(2u, writer_.files().size());
133 E : EXPECT_EQ(kSymbolCounts[0], writer_.symbols().size());
134 E : }
135 :
136 E : TEST_F(ArWriterTest, TestArWriterRoundTrip) {
137 E : EXPECT_NO_FATAL_FAILURE(AddObjectFiles());
138 :
139 E : EXPECT_TRUE(writer_.Write(lib_path_));
140 E : EXPECT_TRUE(base::PathExists(lib_path_));
141 :
142 : // Read the file to validate it.
143 E : ArReader reader;
144 E : EXPECT_TRUE(reader.Init(lib_path_));
145 E : EXPECT_EQ(2u, reader.offsets().size());
146 E : EXPECT_EQ(6u, reader.symbols().size());
147 E : EXPECT_TRUE(reader.BuildFileIndex());
148 E : while (reader.HasNext()) {
149 E : ParsedArFileHeader header;
150 E : EXPECT_TRUE(reader.ExtractNext(&header, NULL));
151 E : }
152 E : }
153 :
154 E : TEST_F(ArWriterTest, TestArWriterRoundTripDuplicateSymbols) {
155 E : for (size_t i = 0; i < object_files_.size(); ++i)
156 E : EXPECT_TRUE(writer_.AddFile(object_files_[i]));
157 E : EXPECT_NO_FATAL_FAILURE(AddDuplicateObjectFile());
158 :
159 E : EXPECT_TRUE(writer_.Write(lib_path_));
160 E : EXPECT_TRUE(base::PathExists(lib_path_));
161 :
162 : // Read the file to validate it.
163 E : ArReader reader;
164 E : EXPECT_TRUE(reader.Init(lib_path_));
165 E : EXPECT_EQ(3u, reader.offsets().size());
166 E : EXPECT_EQ(6u, reader.symbols().size());
167 E : EXPECT_TRUE(reader.BuildFileIndex());
168 E : while (reader.HasNext()) {
169 E : ParsedArFileHeader header;
170 E : EXPECT_TRUE(reader.ExtractNext(&header, NULL));
171 E : }
172 E : }
173 :
174 E : TEST_F(ArWriterTest, TestArWriterRoundTripWeakSymbols) {
175 : base::FilePath lib1 = testing::GetSrcRelativePath(
176 E : testing::kWeakSymbolArchiveFile);
177 E : ArReader reader1;
178 E : ASSERT_TRUE(reader1.Init(lib1));
179 :
180 E : base::FilePath lib2 = temp_dir_.Append(L"weak.lib");
181 E : ArWriter writer;
182 E : ScopedVector<DataBuffer> buffers;
183 E : while (reader1.HasNext()) {
184 E : ParsedArFileHeader header;
185 E : scoped_ptr<DataBuffer> contents(new DataBuffer);
186 E : ASSERT_TRUE(reader1.ExtractNext(&header, contents.get()));
187 : EXPECT_TRUE(writer.AddFile(header.name, header.timestamp, header.mode,
188 E : contents.get()));
189 E : buffers.push_back(contents.release());
190 E : }
191 E : EXPECT_THAT(writer.symbols(), testing::ContainerEq(reader1.symbols()));
192 E : EXPECT_TRUE(writer.Write(lib2));
193 :
194 E : ArReader reader2;
195 E : EXPECT_TRUE(reader2.Init(lib2));
196 E : EXPECT_THAT(reader2.symbols(), testing::ContainerEq(reader1.symbols()));
197 E : }
198 :
199 E : TEST_F(ArWriterTest, TestArWriterRoundTripRepeatedFileNames) {
200 : base::FilePath lib1 = testing::GetSrcRelativePath(
201 E : testing::kDuplicatesArchiveFile);
202 E : ArReader reader1;
203 E : ASSERT_TRUE(reader1.Init(lib1));
204 :
205 E : base::FilePath lib2 = temp_dir_.Append(L"duplicates.lib");
206 E : ArWriter writer;
207 E : ScopedVector<DataBuffer> buffers;
208 E : while (reader1.HasNext()) {
209 E : ParsedArFileHeader header;
210 E : scoped_ptr<DataBuffer> contents(new DataBuffer);
211 E : ASSERT_TRUE(reader1.ExtractNext(&header, contents.get()));
212 : EXPECT_TRUE(writer.AddFile(header.name, header.timestamp, header.mode,
213 E : contents.get()));
214 :
215 E : buffers.push_back(contents.release());
216 E : }
217 E : EXPECT_THAT(writer.symbols(), testing::ContainerEq(reader1.symbols()));
218 E : EXPECT_TRUE(writer.Write(lib2));
219 :
220 E : ArReader reader2;
221 E : EXPECT_TRUE(reader2.Init(lib2));
222 E : EXPECT_THAT(reader2.symbols(), testing::ContainerEq(reader1.symbols()));
223 E : }
224 :
225 : } // namespace ar
|