1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6 #include <stdint.h>
7
8 #include <vector>
9
10 #include "base/stl_util.h"
11 #include "chrome/test/logging/win/mof_data_parser.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 // A test fixture for Mof parser tests.
15 class MofDataParserTest : public ::testing::Test {
16 protected:
17 EVENT_TRACE* MakeEventWithDataOfSize(size_t size);
MakeEventWithBlittedValue(T value)18 template<typename T> EVENT_TRACE* MakeEventWithBlittedValue(T value) {
19 EVENT_TRACE* event = MakeEventWithDataOfSize(sizeof(value));
20 *reinterpret_cast<T*>(event->MofData) = value;
21 return event;
22 }
23 EVENT_TRACE* MakeEventWithDWORD(DWORD value);
24 EVENT_TRACE* MakeEventWithPointerArray(const void* const* pointers,
25 DWORD size);
26 EVENT_TRACE* MakeEventWithString(const char* a_string, size_t length);
27
28 std::vector<uint8_t> buffer_;
29 };
30
MakeEventWithDataOfSize(size_t size)31 EVENT_TRACE* MofDataParserTest::MakeEventWithDataOfSize(size_t size) {
32 buffer_.assign(sizeof(EVENT_TRACE) + size, 0);
33 EVENT_TRACE* event = reinterpret_cast<EVENT_TRACE*>(&buffer_[0]);
34 event->MofLength = size;
35 event->MofData = &buffer_[sizeof(EVENT_TRACE)];
36 return event;
37 }
38
MakeEventWithDWORD(DWORD value)39 EVENT_TRACE* MofDataParserTest::MakeEventWithDWORD(DWORD value) {
40 return MakeEventWithBlittedValue(value);
41 }
42
MakeEventWithPointerArray(const void * const * pointers,DWORD size)43 EVENT_TRACE* MofDataParserTest::MakeEventWithPointerArray(
44 const void* const* pointers,
45 DWORD size) {
46 EVENT_TRACE* event =
47 MakeEventWithDataOfSize(sizeof(DWORD) + sizeof(*pointers) * size);
48 *reinterpret_cast<DWORD*>(event->MofData) = size;
49 ::memcpy(reinterpret_cast<DWORD*>(event->MofData) + 1, pointers,
50 sizeof(*pointers) * size);
51 return event;
52 }
53
54 // |length| is the number of bytes to put in (i.e., include the terminator if
55 // you want one).
MakeEventWithString(const char * a_string,size_t length)56 EVENT_TRACE* MofDataParserTest::MakeEventWithString(const char* a_string,
57 size_t length) {
58 EVENT_TRACE* event = MakeEventWithDataOfSize(length);
59 ::memcpy(event->MofData, a_string, length);
60 return event;
61 }
62
63 // Tests reading a primitive value. ReadDWORD, ReadInt, and ReadPointer share
64 // the same implementation, so this test covers all three.
TEST_F(MofDataParserTest,ReadPrimitive)65 TEST_F(MofDataParserTest, ReadPrimitive) {
66
67 // Read a valid DWORD.
68 EVENT_TRACE* event = MakeEventWithDWORD(5);
69 {
70 DWORD value = 0;
71 logging_win::MofDataParser parser(event);
72 EXPECT_FALSE(parser.empty());
73 EXPECT_TRUE(parser.ReadDWORD(&value));
74 EXPECT_EQ(5UL, value);
75 EXPECT_TRUE(parser.empty());
76 }
77
78 // Try again if there's insufficient data.
79 --(event->MofLength);
80 {
81 DWORD value = 0;
82 logging_win::MofDataParser parser(event);
83 EXPECT_FALSE(parser.empty());
84 EXPECT_FALSE(parser.ReadDWORD(&value));
85 EXPECT_EQ(0UL, value);
86 }
87 }
88
89 // Tests reading an array of pointer-sized values. These arrays are encoded by
90 // writing a DWORD item count followed by the items.
TEST_F(MofDataParserTest,ReadPointerArray)91 TEST_F(MofDataParserTest, ReadPointerArray) {
92 const void* const pointers[] = { this, &buffer_ };
93 const DWORD array_size = base::size(pointers);
94
95 // Read a valid array of two pointers.
96 EVENT_TRACE* event = MakeEventWithPointerArray(&pointers[0], array_size);
97 {
98 DWORD size = 0;
99 const intptr_t* values = NULL;
100
101 logging_win::MofDataParser parser(event);
102 EXPECT_FALSE(parser.empty());
103 EXPECT_TRUE(parser.ReadDWORD(&size));
104 EXPECT_EQ(array_size, size);
105 EXPECT_TRUE(parser.ReadPointerArray(size, &values));
106 EXPECT_EQ(0, ::memcmp(&pointers[0], values, sizeof(*values) * size));
107 EXPECT_TRUE(parser.empty());
108 }
109
110 // Try again if there's insufficient data.
111 --(event->MofLength);
112 {
113 DWORD size = 0;
114 const intptr_t* values = NULL;
115
116 logging_win::MofDataParser parser(event);
117 EXPECT_FALSE(parser.empty());
118 EXPECT_TRUE(parser.ReadDWORD(&size));
119 EXPECT_EQ(array_size, size);
120 EXPECT_FALSE(parser.ReadPointerArray(size, &values));
121 EXPECT_FALSE(parser.empty());
122 }
123 }
124
125 // Tests reading a structure.
TEST_F(MofDataParserTest,ReadStructure)126 TEST_F(MofDataParserTest, ReadStructure) {
127 struct Spam {
128 int blorf;
129 char spiffy;
130 };
131 const Spam canned_meat = { 47, 'Y' };
132
133 // Read a pointer to a structure.
134 EVENT_TRACE* event = MakeEventWithBlittedValue(canned_meat);
135 {
136 const Spam* value = NULL;
137 logging_win::MofDataParser parser(event);
138 EXPECT_FALSE(parser.empty());
139 EXPECT_TRUE(parser.ReadStructure(&value));
140 EXPECT_EQ(canned_meat.blorf, value->blorf);
141 EXPECT_EQ(canned_meat.spiffy, value->spiffy);
142 EXPECT_TRUE(parser.empty());
143 }
144
145 // Try again if there's insufficient data.
146 --(event->MofLength);
147 {
148 const Spam* value = NULL;
149 logging_win::MofDataParser parser(event);
150 EXPECT_FALSE(parser.empty());
151 EXPECT_FALSE(parser.ReadStructure(&value));
152 EXPECT_FALSE(parser.empty());
153 }
154 }
155
156 // Tests reading null-terminated string.
TEST_F(MofDataParserTest,ReadString)157 TEST_F(MofDataParserTest, ReadString) {
158 const char a_string_nl[] = "sometimes i get lost in my own thoughts.\n";
159 const char a_string[] = "sometimes i get lost in my own thoughts.";
160
161 // Read a string with a trailing newline.
162 EVENT_TRACE* event =
163 MakeEventWithString(a_string_nl, base::size(a_string_nl));
164 {
165 base::StringPiece value;
166 logging_win::MofDataParser parser(event);
167 EXPECT_FALSE(parser.empty());
168 EXPECT_TRUE(parser.ReadString(&value));
169 EXPECT_EQ(base::StringPiece(&a_string_nl[0], base::size(a_string_nl) - 2),
170 value);
171 EXPECT_TRUE(parser.empty());
172 }
173
174 // Read a string without a trailing newline.
175 event = MakeEventWithString(a_string, base::size(a_string));
176 {
177 base::StringPiece value;
178 logging_win::MofDataParser parser(event);
179 EXPECT_FALSE(parser.empty());
180 EXPECT_TRUE(parser.ReadString(&value));
181 EXPECT_EQ(base::StringPiece(&a_string[0], base::size(a_string) - 1), value);
182 EXPECT_TRUE(parser.empty());
183 }
184
185 // Try a string that isn't terminated.
186 event = MakeEventWithString(a_string, base::size(a_string) - 1);
187 {
188 base::StringPiece value;
189 logging_win::MofDataParser parser(event);
190 EXPECT_FALSE(parser.empty());
191 EXPECT_FALSE(parser.ReadString(&value));
192 EXPECT_FALSE(parser.empty());
193 }
194 }
195