Home | History | Annotate | Download | only in cctest
      1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
      2 //
      3 // Tests of logging utilities from log-utils.h
      4 
      5 #ifdef ENABLE_LOGGING_AND_PROFILING
      6 
      7 #include "v8.h"
      8 
      9 #include "log-utils.h"
     10 #include "cctest.h"
     11 
     12 using v8::internal::CStrVector;
     13 using v8::internal::EmbeddedVector;
     14 using v8::internal::LogDynamicBuffer;
     15 using v8::internal::LogRecordCompressor;
     16 using v8::internal::MutableCStrVector;
     17 using v8::internal::ScopedVector;
     18 using v8::internal::Vector;
     19 using v8::internal::StrLength;
     20 
     21 // Fills 'ref_buffer' with test data: a sequence of two-digit
     22 // hex numbers: '0001020304...'. Then writes 'ref_buffer' contents to 'dynabuf'.
     23 static void WriteData(LogDynamicBuffer* dynabuf, Vector<char>* ref_buffer) {
     24   static const char kHex[] = "0123456789ABCDEF";
     25   CHECK_GT(ref_buffer->length(), 0);
     26   CHECK_GT(513, ref_buffer->length());
     27   for (int i = 0, half_len = ref_buffer->length() >> 1; i < half_len; ++i) {
     28     (*ref_buffer)[i << 1] = kHex[i >> 4];
     29     (*ref_buffer)[(i << 1) + 1] = kHex[i & 15];
     30   }
     31   if (ref_buffer->length() & 1) {
     32     ref_buffer->last() = kHex[ref_buffer->length() >> 5];
     33   }
     34   CHECK_EQ(ref_buffer->length(),
     35            dynabuf->Write(ref_buffer->start(), ref_buffer->length()));
     36 }
     37 
     38 
     39 static int ReadData(
     40     LogDynamicBuffer* dynabuf, int start_pos, i::Vector<char>* buffer) {
     41   return dynabuf->Read(start_pos, buffer->start(), buffer->length());
     42 }
     43 
     44 
     45 // Helper function used by CHECK_EQ to compare Vectors. Templatized to
     46 // accept both "char" and "const char" vector contents.
     47 template <typename E, typename V>
     48 static inline void CheckEqualsHelper(const char* file, int line,
     49                                      const char* expected_source,
     50                                      const Vector<E>& expected,
     51                                      const char* value_source,
     52                                      const Vector<V>& value) {
     53   if (expected.length() != value.length()) {
     54     V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n"
     55              "#   Vectors lengths differ: %d expected, %d found\n"
     56              "#   Expected: %.*s\n"
     57              "#   Found: %.*s",
     58              expected_source, value_source,
     59              expected.length(), value.length(),
     60              expected.length(), expected.start(),
     61              value.length(), value.start());
     62   }
     63   if (strncmp(expected.start(), value.start(), expected.length()) != 0) {
     64     V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n"
     65              "#   Vectors contents differ:\n"
     66              "#   Expected: %.*s\n"
     67              "#   Found: %.*s",
     68              expected_source, value_source,
     69              expected.length(), expected.start(),
     70              value.length(), value.start());
     71   }
     72 }
     73 
     74 
     75 TEST(DynaBufSingleBlock) {
     76   LogDynamicBuffer dynabuf(32, 32, "", 0);
     77   EmbeddedVector<char, 32> ref_buf;
     78   WriteData(&dynabuf, &ref_buf);
     79   EmbeddedVector<char, 32> buf;
     80   CHECK_EQ(32, dynabuf.Read(0, buf.start(), buf.length()));
     81   CHECK_EQ(32, ReadData(&dynabuf, 0, &buf));
     82   CHECK_EQ(ref_buf, buf);
     83 
     84   // Verify that we can't read and write past the end.
     85   CHECK_EQ(0, dynabuf.Read(32, buf.start(), buf.length()));
     86   CHECK_EQ(0, dynabuf.Write(buf.start(), buf.length()));
     87 }
     88 
     89 
     90 TEST(DynaBufCrossBlocks) {
     91   LogDynamicBuffer dynabuf(32, 128, "", 0);
     92   EmbeddedVector<char, 48> ref_buf;
     93   WriteData(&dynabuf, &ref_buf);
     94   CHECK_EQ(48, dynabuf.Write(ref_buf.start(), ref_buf.length()));
     95   // Verify that we can't write data when remaining buffer space isn't enough.
     96   CHECK_EQ(0, dynabuf.Write(ref_buf.start(), ref_buf.length()));
     97   EmbeddedVector<char, 48> buf;
     98   CHECK_EQ(48, ReadData(&dynabuf, 0, &buf));
     99   CHECK_EQ(ref_buf, buf);
    100   CHECK_EQ(48, ReadData(&dynabuf, 48, &buf));
    101   CHECK_EQ(ref_buf, buf);
    102   CHECK_EQ(0, ReadData(&dynabuf, 48 * 2, &buf));
    103 }
    104 
    105 
    106 TEST(DynaBufReadTruncation) {
    107   LogDynamicBuffer dynabuf(32, 128, "", 0);
    108   EmbeddedVector<char, 128> ref_buf;
    109   WriteData(&dynabuf, &ref_buf);
    110   EmbeddedVector<char, 128> buf;
    111   CHECK_EQ(128, ReadData(&dynabuf, 0, &buf));
    112   CHECK_EQ(ref_buf, buf);
    113   // Try to read near the end with a buffer larger than remaining data size.
    114   EmbeddedVector<char, 48> tail_buf;
    115   CHECK_EQ(32, ReadData(&dynabuf, 128 - 32, &tail_buf));
    116   CHECK_EQ(ref_buf.SubVector(128 - 32, 128), tail_buf.SubVector(0, 32));
    117 }
    118 
    119 
    120 TEST(DynaBufSealing) {
    121   const char* seal = "Sealed";
    122   const int seal_size = StrLength(seal);
    123   LogDynamicBuffer dynabuf(32, 128, seal, seal_size);
    124   EmbeddedVector<char, 100> ref_buf;
    125   WriteData(&dynabuf, &ref_buf);
    126   // Try to write data that will not fit in the buffer.
    127   CHECK_EQ(0, dynabuf.Write(ref_buf.start(), 128 - 100 - seal_size + 1));
    128   // Now the buffer is sealed, writing of any amount of data is forbidden.
    129   CHECK_EQ(0, dynabuf.Write(ref_buf.start(), 1));
    130   EmbeddedVector<char, 100> buf;
    131   CHECK_EQ(100, ReadData(&dynabuf, 0, &buf));
    132   CHECK_EQ(ref_buf, buf);
    133   // Check the seal.
    134   EmbeddedVector<char, 50> seal_buf;
    135   CHECK_EQ(seal_size, ReadData(&dynabuf, 100, &seal_buf));
    136   CHECK_EQ(CStrVector(seal), seal_buf.SubVector(0, seal_size));
    137   // Verify that there's no data beyond the seal.
    138   CHECK_EQ(0, ReadData(&dynabuf, 100 + seal_size, &buf));
    139 }
    140 
    141 
    142 TEST(CompressorStore) {
    143   LogRecordCompressor comp(2);
    144   const Vector<const char> empty = CStrVector("");
    145   CHECK(comp.Store(empty));
    146   CHECK(!comp.Store(empty));
    147   CHECK(!comp.Store(empty));
    148   const Vector<const char> aaa = CStrVector("aaa");
    149   CHECK(comp.Store(aaa));
    150   CHECK(!comp.Store(aaa));
    151   CHECK(!comp.Store(aaa));
    152   CHECK(comp.Store(empty));
    153   CHECK(!comp.Store(empty));
    154   CHECK(!comp.Store(empty));
    155 }
    156 
    157 
    158 void CheckCompression(LogRecordCompressor* comp,
    159                       const Vector<const char>& after) {
    160   EmbeddedVector<char, 100> result;
    161   CHECK(comp->RetrievePreviousCompressed(&result));
    162   CHECK_EQ(after, result);
    163 }
    164 
    165 
    166 void CheckCompression(LogRecordCompressor* comp,
    167                       const char* after) {
    168   CheckCompression(comp, CStrVector(after));
    169 }
    170 
    171 
    172 TEST(CompressorNonCompressed) {
    173   LogRecordCompressor comp(0);
    174   CHECK(!comp.RetrievePreviousCompressed(NULL));
    175   const Vector<const char> empty = CStrVector("");
    176   CHECK(comp.Store(empty));
    177   CHECK(!comp.RetrievePreviousCompressed(NULL));
    178   const Vector<const char> a_x_20 = CStrVector("aaaaaaaaaaaaaaaaaaaa");
    179   CHECK(comp.Store(a_x_20));
    180   CheckCompression(&comp, empty);
    181   CheckCompression(&comp, empty);
    182   CHECK(comp.Store(empty));
    183   CheckCompression(&comp, a_x_20);
    184   CheckCompression(&comp, a_x_20);
    185 }
    186 
    187 
    188 TEST(CompressorSingleLine) {
    189   LogRecordCompressor comp(1);
    190   const Vector<const char> string_1 = CStrVector("eee,ddd,ccc,bbb,aaa");
    191   CHECK(comp.Store(string_1));
    192   const Vector<const char> string_2 = CStrVector("fff,ddd,ccc,bbb,aaa");
    193   CHECK(comp.Store(string_2));
    194   // string_1 hasn't been compressed.
    195   CheckCompression(&comp, string_1);
    196   CheckCompression(&comp, string_1);
    197   const Vector<const char> string_3 = CStrVector("hhh,ggg,ccc,bbb,aaa");
    198   CHECK(comp.Store(string_3));
    199   // string_2 compressed using string_1.
    200   CheckCompression(&comp, "fff#1:3");
    201   CheckCompression(&comp, "fff#1:3");
    202   CHECK(!comp.Store(string_3));
    203   // Expecting no changes.
    204   CheckCompression(&comp, "fff#1:3");
    205   CHECK(!comp.Store(string_3));
    206   // Expecting no changes.
    207   CheckCompression(&comp, "fff#1:3");
    208   const Vector<const char> string_4 = CStrVector("iii,hhh,ggg,ccc,bbb,aaa");
    209   CHECK(comp.Store(string_4));
    210   // string_3 compressed using string_2.
    211   CheckCompression(&comp, "hhh,ggg#1:7");
    212   const Vector<const char> string_5 = CStrVector("nnn,mmm,lll,kkk,jjj");
    213   CHECK(comp.Store(string_5));
    214   // string_4 compressed using string_3.
    215   CheckCompression(&comp, "iii,#1");
    216   const Vector<const char> string_6 = CStrVector("nnn,mmmmmm,lll,kkk,jjj");
    217   CHECK(comp.Store(string_6));
    218   // string_5 hasn't been compressed.
    219   CheckCompression(&comp, string_5);
    220   CHECK(comp.Store(string_5));
    221   // string_6 compressed using string_5.
    222   CheckCompression(&comp, "nnn,mmm#1:4");
    223   const Vector<const char> string_7 = CStrVector("nnnnnn,mmm,lll,kkk,jjj");
    224   CHECK(comp.Store(string_7));
    225   // string_5 compressed using string_6.
    226   CheckCompression(&comp, "nnn,#1:7");
    227   const Vector<const char> string_8 = CStrVector("xxn,mmm,lll,kkk,jjj");
    228   CHECK(comp.Store(string_8));
    229   // string_7 compressed using string_5.
    230   CheckCompression(&comp, "nnn#1");
    231   const Vector<const char> string_9 =
    232       CStrVector("aaaaaaaaaaaaa,bbbbbbbbbbbbbbbbb");
    233   CHECK(comp.Store(string_9));
    234   // string_8 compressed using string_7.
    235   CheckCompression(&comp, "xx#1:5");
    236   const Vector<const char> string_10 =
    237       CStrVector("aaaaaaaaaaaaa,cccccccbbbbbbbbbb");
    238   CHECK(comp.Store(string_10));
    239   // string_9 hasn't been compressed.
    240   CheckCompression(&comp, string_9);
    241   CHECK(comp.Store(string_1));
    242   // string_10 compressed using string_9.
    243   CheckCompression(&comp, "aaaaaaaaaaaaa,ccccccc#1:21");
    244 }
    245 
    246 
    247 
    248 TEST(CompressorMultiLines) {
    249   const int kWindowSize = 3;
    250   LogRecordCompressor comp(kWindowSize);
    251   const Vector<const char> string_1 = CStrVector("eee,ddd,ccc,bbb,aaa");
    252   CHECK(comp.Store(string_1));
    253   const Vector<const char> string_2 = CStrVector("iii,hhh,ggg,fff,aaa");
    254   CHECK(comp.Store(string_2));
    255   const Vector<const char> string_3 = CStrVector("mmm,lll,kkk,jjj,aaa");
    256   CHECK(comp.Store(string_3));
    257   const Vector<const char> string_4 = CStrVector("nnn,hhh,ggg,fff,aaa");
    258   CHECK(comp.Store(string_4));
    259   const Vector<const char> string_5 = CStrVector("ooo,lll,kkk,jjj,aaa");
    260   CHECK(comp.Store(string_5));
    261   // string_4 compressed using string_2.
    262   CheckCompression(&comp, "nnn#2:3");
    263   CHECK(comp.Store(string_1));
    264   // string_5 compressed using string_3.
    265   CheckCompression(&comp, "ooo#2:3");
    266   CHECK(comp.Store(string_4));
    267   // string_1 is out of buffer by now, so it shouldn't be compressed.
    268   CHECK_GE(3, kWindowSize);
    269   CheckCompression(&comp, string_1);
    270   CHECK(comp.Store(string_2));
    271   // string_4 compressed using itself.
    272   CheckCompression(&comp, "#3");
    273 }
    274 
    275 
    276 TEST(CompressorBestSelection) {
    277   LogRecordCompressor comp(3);
    278   const Vector<const char> string_1 = CStrVector("eee,ddd,ccc,bbb,aaa");
    279   CHECK(comp.Store(string_1));
    280   const Vector<const char> string_2 = CStrVector("ddd,ccc,bbb,aaa");
    281   CHECK(comp.Store(string_2));
    282   const Vector<const char> string_3 = CStrVector("fff,eee,ddd,ccc,bbb,aaa");
    283   CHECK(comp.Store(string_3));
    284   // string_2 compressed using string_1.
    285   CheckCompression(&comp, "#1:4");
    286   const Vector<const char> string_4 = CStrVector("nnn,hhh,ggg,fff,aaa");
    287   CHECK(comp.Store(string_4));
    288   // Compressing string_3 using string_1 gives a better compression than
    289   // using string_2.
    290   CheckCompression(&comp, "fff,#2");
    291 }
    292 
    293 
    294 TEST(CompressorCompressibility) {
    295   LogRecordCompressor comp(2);
    296   const Vector<const char> string_1 = CStrVector("eee,ddd,ccc,bbb,aaa");
    297   CHECK(comp.Store(string_1));
    298   const Vector<const char> string_2 = CStrVector("ccc,bbb,aaa");
    299   CHECK(comp.Store(string_2));
    300   const Vector<const char> string_3 = CStrVector("aaa");
    301   CHECK(comp.Store(string_3));
    302   // string_2 compressed using string_1.
    303   CheckCompression(&comp, "#1:8");
    304   const Vector<const char> string_4 = CStrVector("xxx");
    305   CHECK(comp.Store(string_4));
    306   // string_3 can't be compressed using string_2 --- too short.
    307   CheckCompression(&comp, string_3);
    308 }
    309 
    310 #endif  // ENABLE_LOGGING_AND_PROFILING
    311