1 : // Copyright 2013 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/trace/service/trace_file_writer.h"
16 :
17 : #include "base/file_util.h"
18 : #include "gtest/gtest.h"
19 : #include "syzygy/common/align.h"
20 : #include "syzygy/pe/unittest_util.h"
21 : #include "syzygy/trace/protocol/call_trace_defs.h"
22 : #include "syzygy/trace/service/process_info.h"
23 :
24 : namespace trace {
25 : namespace service {
26 :
27 : namespace {
28 :
29 : class TestTraceFileWriter : public TraceFileWriter {
30 : public:
31 : using TraceFileWriter::handle_;
32 : };
33 :
34 : class TraceFileWriterTest : public testing::PELibUnitTest {
35 : public:
36 E : virtual void SetUp() OVERRIDE {
37 E : testing::PELibUnitTest::SetUp();
38 E : CreateTemporaryDir(&temp_dir);
39 E : trace_path = temp_dir.AppendASCII("trace.dat");
40 E : }
41 :
42 : base::FilePath temp_dir;
43 : base::FilePath trace_path;
44 : };
45 :
46 : } // namespace
47 :
48 E : TEST_F(TraceFileWriterTest, GenerateTraceFileBaseName) {
49 E : ProcessInfo pi;
50 E : ASSERT_TRUE(pi.Initialize(::GetCurrentProcessId()));
51 :
52 E : base::FilePath basename = TraceFileWriter::GenerateTraceFileBaseName(pi);
53 E : EXPECT_FALSE(basename.empty());
54 E : }
55 :
56 E : TEST_F(TraceFileWriterTest, Constructor) {
57 E : TestTraceFileWriter w;
58 E : EXPECT_TRUE(w.path().empty());
59 E : EXPECT_FALSE(w.handle_.IsValid());
60 E : EXPECT_EQ(0u, w.block_size());
61 E : }
62 :
63 E : TEST_F(TraceFileWriterTest, OpenFailsForBadPath) {
64 E : TestTraceFileWriter w;
65 : EXPECT_FALSE(w.Open(base::FilePath(
66 E : L"Z:\\this\\path\\should\\not\\exist\\and\\open\\should\\fail.dat")));
67 E : EXPECT_TRUE(w.path().empty());
68 E : EXPECT_FALSE(w.handle_.IsValid());
69 E : EXPECT_EQ(0u, w.block_size());
70 E : }
71 :
72 E : TEST_F(TraceFileWriterTest, OpenSucceeds) {
73 E : TestTraceFileWriter w;
74 E : EXPECT_TRUE(w.Open(trace_path));
75 E : EXPECT_EQ(trace_path, w.path());
76 E : EXPECT_TRUE(w.handle_.IsValid());
77 E : EXPECT_LT(0u, w.block_size());
78 E : EXPECT_TRUE(base::PathExists(trace_path));
79 E : }
80 :
81 E : TEST_F(TraceFileWriterTest, CloseSucceeds) {
82 E : TestTraceFileWriter w;
83 E : ASSERT_TRUE(w.Open(trace_path));
84 :
85 E : EXPECT_TRUE(w.Close());
86 E : EXPECT_TRUE(base::PathExists(trace_path));
87 E : }
88 :
89 E : TEST_F(TraceFileWriterTest, WriteHeader) {
90 E : TestTraceFileWriter w;
91 E : ASSERT_TRUE(w.Open(trace_path));
92 :
93 E : ProcessInfo pi;
94 E : ASSERT_TRUE(pi.Initialize(::GetCurrentProcessId()));
95 E : EXPECT_TRUE(w.WriteHeader(pi));
96 :
97 E : ASSERT_TRUE(w.Close());
98 E : EXPECT_TRUE(base::PathExists(trace_path));
99 :
100 E : int64 trace_file_size = 0;
101 E : ASSERT_TRUE(base::GetFileSize(trace_path, &trace_file_size));
102 E : EXPECT_LT(0, trace_file_size);
103 E : EXPECT_EQ(0, trace_file_size % w.block_size());
104 E : }
105 :
106 E : TEST_F(TraceFileWriterTest, WriteRecordFailsTooShort) {
107 E : TestTraceFileWriter w;
108 E : ASSERT_TRUE(w.Open(trace_path));
109 :
110 E : ProcessInfo pi;
111 E : ASSERT_TRUE(pi.Initialize(::GetCurrentProcessId()));
112 E : ASSERT_TRUE(w.WriteHeader(pi));
113 :
114 E : uint8 data[2] = {};
115 E : EXPECT_FALSE(w.WriteRecord(data, sizeof(data)));
116 E : }
117 :
118 E : TEST_F(TraceFileWriterTest, WriteRecordFailsInvalidRecordPrefix) {
119 E : TestTraceFileWriter w;
120 E : ASSERT_TRUE(w.Open(trace_path));
121 :
122 E : ProcessInfo pi;
123 E : ASSERT_TRUE(pi.Initialize(::GetCurrentProcessId()));
124 E : ASSERT_TRUE(w.WriteHeader(pi));
125 :
126 E : RecordPrefix record = {};
127 E : EXPECT_FALSE(w.WriteRecord(&record, sizeof(record)));
128 E : }
129 :
130 E : TEST_F(TraceFileWriterTest, WriteRecordFailsOverwritten) {
131 E : TestTraceFileWriter w;
132 E : ASSERT_TRUE(w.Open(trace_path));
133 :
134 E : ProcessInfo pi;
135 E : ASSERT_TRUE(pi.Initialize(::GetCurrentProcessId()));
136 E : ASSERT_TRUE(w.WriteHeader(pi));
137 :
138 E : std::vector<uint8> data;
139 E : data.resize(sizeof(RecordPrefix) + sizeof(TraceFileSegmentHeader) + 1);
140 E : RecordPrefix* record = reinterpret_cast<RecordPrefix*>(data.data());
141 : TraceFileSegmentHeader* header = reinterpret_cast<TraceFileSegmentHeader*>(
142 E : record + 1);
143 E : record->size = sizeof(TraceFileSegmentHeader);
144 E : record->type= TraceFileSegmentHeader::kTypeId;
145 E : record->version.hi = TRACE_VERSION_HI;
146 E : record->version.lo = TRACE_VERSION_LO;
147 E : header->segment_length = 1;
148 :
149 E : EXPECT_FALSE(w.WriteRecord(data.data(), data.size()));
150 E : }
151 :
152 E : TEST_F(TraceFileWriterTest, WriteRecordSucceeds) {
153 E : TestTraceFileWriter w;
154 E : ASSERT_TRUE(w.Open(trace_path));
155 :
156 E : ProcessInfo pi;
157 E : ASSERT_TRUE(pi.Initialize(::GetCurrentProcessId()));
158 E : ASSERT_TRUE(w.WriteHeader(pi));
159 :
160 E : std::vector<uint8> data;
161 E : data.resize(sizeof(RecordPrefix) + sizeof(TraceFileSegmentHeader) + 1);
162 E : RecordPrefix* record = reinterpret_cast<RecordPrefix*>(data.data());
163 : TraceFileSegmentHeader* header = reinterpret_cast<TraceFileSegmentHeader*>(
164 E : record + 1);
165 E : record->size = sizeof(TraceFileSegmentHeader);
166 E : record->type= TraceFileSegmentHeader::kTypeId;
167 E : record->version.hi = TRACE_VERSION_HI;
168 E : record->version.lo = TRACE_VERSION_LO;
169 E : header->segment_length = 1;
170 :
171 E : data.resize(::common::AlignUp(data.size(), w.block_size()));
172 E : EXPECT_TRUE(w.WriteRecord(data.data(), data.size()));
173 :
174 E : ASSERT_TRUE(w.Close());
175 E : EXPECT_TRUE(base::PathExists(trace_path));
176 :
177 E : int64 trace_file_size = 0;
178 E : ASSERT_TRUE(base::GetFileSize(trace_path, &trace_file_size));
179 E : EXPECT_LT(0, trace_file_size);
180 E : EXPECT_EQ(0, trace_file_size % w.block_size());
181 E : }
182 :
183 : } // namespace service
184 : } // namespace trace
|