15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/logging/win/mof_data_parser.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A test fixture for Mof parser tests. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MofDataParserTest : public ::testing::Test { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE* MakeEventWithDataOfSize(size_t size); 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template<typename T> EVENT_TRACE* MakeEventWithBlittedValue(T value) { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE* event = MakeEventWithDataOfSize(sizeof(value)); 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *reinterpret_cast<T*>(event->MofData) = value; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return event; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE* MakeEventWithDWORD(DWORD value); 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE* MakeEventWithPointerArray(const void* const* pointers, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE* MakeEventWithString(const char* a_string, size_t length); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<uint8> buffer_; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EVENT_TRACE* MofDataParserTest::MakeEventWithDataOfSize(size_t size) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_.assign(sizeof(EVENT_TRACE) + size, 0); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE* event = reinterpret_cast<EVENT_TRACE*>(&buffer_[0]); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->MofLength = size; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->MofData = &buffer_[sizeof(EVENT_TRACE)]; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return event; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EVENT_TRACE* MofDataParserTest::MakeEventWithDWORD(DWORD value) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MakeEventWithBlittedValue(value); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EVENT_TRACE* MofDataParserTest::MakeEventWithPointerArray( 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* const* pointers, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE* event = 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MakeEventWithDataOfSize(sizeof(DWORD) + sizeof(*pointers) * size); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *reinterpret_cast<DWORD*>(event->MofData) = size; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::memcpy(reinterpret_cast<DWORD*>(event->MofData) + 1, pointers, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(*pointers) * size); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return event; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |length| is the number of bytes to put in (i.e., include the terminator if 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// you want one). 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EVENT_TRACE* MofDataParserTest::MakeEventWithString(const char* a_string, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t length) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE* event = MakeEventWithDataOfSize(length); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::memcpy(event->MofData, a_string, length); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return event; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests reading a primitive value. ReadDWORD, ReadInt, and ReadPointer share 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the same implementation, so this test covers all three. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MofDataParserTest, ReadPrimitive) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read a valid DWORD. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE* event = MakeEventWithDWORD(5); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD value = 0; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging_win::MofDataParser parser(event); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.empty()); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.ReadDWORD(&value)); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(5UL, value); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.empty()); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try again if there's insufficient data. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --(event->MofLength); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD value = 0; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging_win::MofDataParser parser(event); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.empty()); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.ReadDWORD(&value)); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0UL, value); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests reading an array of pointer-sized values. These arrays are encoded by 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// writing a DWORD item count followed by the items. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MofDataParserTest, ReadPointerArray) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* const pointers[] = { this, &buffer_ }; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DWORD array_size = arraysize(pointers); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read a valid array of two pointers. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE* event = MakeEventWithPointerArray(&pointers[0], array_size); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size = 0; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const intptr_t* values = NULL; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging_win::MofDataParser parser(event); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.empty()); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.ReadDWORD(&size)); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(array_size, size); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.ReadPointerArray(size, &values)); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, ::memcmp(&pointers[0], values, sizeof(*values) * size)); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.empty()); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try again if there's insufficient data. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --(event->MofLength); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size = 0; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const intptr_t* values = NULL; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging_win::MofDataParser parser(event); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.empty()); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.ReadDWORD(&size)); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(array_size, size); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.ReadPointerArray(size, &values)); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.empty()); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests reading a structure. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MofDataParserTest, ReadStructure) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Spam { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int blorf; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char spiffy; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Spam canned_meat = { 47, 'Y' }; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read a pointer to a structure. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE* event = MakeEventWithBlittedValue(canned_meat); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Spam* value = NULL; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging_win::MofDataParser parser(event); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.empty()); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.ReadStructure(&value)); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(canned_meat.blorf, value->blorf); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(canned_meat.spiffy, value->spiffy); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.empty()); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try again if there's insufficient data. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --(event->MofLength); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Spam* value = NULL; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging_win::MofDataParser parser(event); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.empty()); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.ReadStructure(&value)); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.empty()); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests reading null-terminated string. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MofDataParserTest, ReadString) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char a_string_nl[] = "sometimes i get lost in my own thoughts.\n"; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char a_string[] = "sometimes i get lost in my own thoughts."; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read a string with a trailing newline. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE* event = 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MakeEventWithString(a_string_nl, arraysize(a_string_nl)); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece value; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging_win::MofDataParser parser(event); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.empty()); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.ReadString(&value)); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(base::StringPiece(&a_string_nl[0], arraysize(a_string_nl) - 2), 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.empty()); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read a string without a trailing newline. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event = MakeEventWithString(a_string, arraysize(a_string)); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece value; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging_win::MofDataParser parser(event); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.empty()); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.ReadString(&value)); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(base::StringPiece(&a_string[0], arraysize(a_string) - 1), value); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.empty()); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try a string that isn't terminated. 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event = MakeEventWithString(a_string, arraysize(a_string) - 1); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece value; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging_win::MofDataParser parser(event); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.empty()); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.ReadString(&value)); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.empty()); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 192