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