Home | History | Annotate | Download | only in win
      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