| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright 2016 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 "net/http2/tools/random_decoder_test.h" |  | 
| 6 |  | 
| 7 #include <stddef.h> |  | 
| 8 |  | 
| 9 #include <algorithm> |  | 
| 10 #include <memory> |  | 
| 11 |  | 
| 12 #include "base/logging.h" |  | 
| 13 #include "base/strings/string_number_conversions.h" |  | 
| 14 #include "base/strings/string_piece.h" |  | 
| 15 #include "net/http2/decoder/decode_buffer.h" |  | 
| 16 #include "net/http2/decoder/decode_status.h" |  | 
| 17 #include "net/http2/http2_constants.h" |  | 
| 18 #include "net/http2/tools/failure.h" |  | 
| 19 #include "testing/gtest/include/gtest/gtest.h" |  | 
| 20 |  | 
| 21 // It's rather time consuming to decode large buffers one at a time, |  | 
| 22 // especially with the log level cranked up. So, by default we don't do |  | 
| 23 // that unless explicitly requested. |  | 
| 24 |  | 
| 25 using ::testing::AssertionFailure; |  | 
| 26 using ::testing::AssertionResult; |  | 
| 27 using ::testing::AssertionSuccess; |  | 
| 28 using base::StringPiece; |  | 
| 29 |  | 
| 30 namespace net { |  | 
| 31 namespace test { |  | 
| 32 |  | 
| 33 std::string HexEncode(StringPiece s) { |  | 
| 34   return base::HexEncode(s.data(), s.size()); |  | 
| 35 } |  | 
| 36 |  | 
| 37 RandomDecoderTest::RandomDecoderTest() {} |  | 
| 38 |  | 
| 39 bool RandomDecoderTest::StopDecodeOnDone() { |  | 
| 40   return stop_decode_on_done_; |  | 
| 41 } |  | 
| 42 |  | 
| 43 DecodeStatus RandomDecoderTest::DecodeSegments(DecodeBuffer* original, |  | 
| 44                                                const SelectSize& select_size) { |  | 
| 45   DecodeStatus status = DecodeStatus::kDecodeInProgress; |  | 
| 46   bool first = true; |  | 
| 47   VLOG(2) << "DecodeSegments: input size=" << original->Remaining(); |  | 
| 48   while (first || original->HasData()) { |  | 
| 49     size_t remaining = original->Remaining(); |  | 
| 50     size_t size = std::min( |  | 
| 51         remaining, select_size.Run(first, original->Offset(), remaining)); |  | 
| 52     DecodeBuffer db(original->cursor(), size); |  | 
| 53     VLOG(2) << "Decoding " << size << " bytes of " << remaining << " remaining"; |  | 
| 54     if (first) { |  | 
| 55       first = false; |  | 
| 56       status = StartDecoding(&db); |  | 
| 57     } else { |  | 
| 58       status = ResumeDecoding(&db); |  | 
| 59     } |  | 
| 60     // A decoder MUST consume some input (if any is available), else we could |  | 
| 61     // get stuck in infinite loops. |  | 
| 62     if (db.Offset() == 0 && db.HasData() && |  | 
| 63         status != DecodeStatus::kDecodeError) { |  | 
| 64       ADD_FAILURE() << "Decoder didn't make any progress; db.FullSize=" |  | 
| 65                     << db.FullSize() |  | 
| 66                     << "   original.Offset=" << original->Offset(); |  | 
| 67       return DecodeStatus::kDecodeError; |  | 
| 68     } |  | 
| 69     original->AdvanceCursor(db.Offset()); |  | 
| 70     switch (status) { |  | 
| 71       case DecodeStatus::kDecodeDone: |  | 
| 72         if (original->Empty() || StopDecodeOnDone()) { |  | 
| 73           return DecodeStatus::kDecodeDone; |  | 
| 74         } |  | 
| 75         continue; |  | 
| 76       case DecodeStatus::kDecodeInProgress: |  | 
| 77         continue; |  | 
| 78       case DecodeStatus::kDecodeError: |  | 
| 79         return DecodeStatus::kDecodeError; |  | 
| 80     } |  | 
| 81   } |  | 
| 82   return status; |  | 
| 83 } |  | 
| 84 |  | 
| 85 // Decode |original| multiple times, with different segmentations, validating |  | 
| 86 // after each decode, returning on the first failure. |  | 
| 87 AssertionResult RandomDecoderTest::DecodeAndValidateSeveralWays( |  | 
| 88     DecodeBuffer* original, |  | 
| 89     bool return_non_zero_on_first, |  | 
| 90     const Validator& validator) { |  | 
| 91   const uint32_t original_remaining = original->Remaining(); |  | 
| 92   VLOG(1) << "DecodeAndValidateSeveralWays - Start, remaining = " |  | 
| 93           << original_remaining; |  | 
| 94   uint32_t first_consumed; |  | 
| 95   { |  | 
| 96     // Fast decode (no stopping unless decoder does so). |  | 
| 97     DecodeBuffer input(original->cursor(), original_remaining); |  | 
| 98     VLOG(2) << "DecodeSegmentsAndValidate with SelectRemaining"; |  | 
| 99     VERIFY_SUCCESS(DecodeSegmentsAndValidate( |  | 
| 100         &input, base::Bind(&SelectRemaining), validator)) |  | 
| 101         << "\nFailed with SelectRemaining; input.Offset=" << input.Offset() |  | 
| 102         << "; input.Remaining=" << input.Remaining(); |  | 
| 103     first_consumed = input.Offset(); |  | 
| 104   } |  | 
| 105   if (original_remaining <= 30) { |  | 
| 106     // Decode again, one byte at a time. |  | 
| 107     DecodeBuffer input(original->cursor(), original_remaining); |  | 
| 108     VLOG(2) << "DecodeSegmentsAndValidate with SelectOne"; |  | 
| 109     VERIFY_SUCCESS( |  | 
| 110         DecodeSegmentsAndValidate(&input, base::Bind(&SelectOne), validator)) |  | 
| 111         << "\nFailed with SelectOne; input.Offset=" << input.Offset() |  | 
| 112         << "; input.Remaining=" << input.Remaining(); |  | 
| 113     VERIFY_EQ(first_consumed, input.Offset()) << "\nFailed with SelectOne"; |  | 
| 114   } |  | 
| 115   if (original_remaining <= 20) { |  | 
| 116     // Decode again, one or zero bytes at a time. |  | 
| 117     DecodeBuffer input(original->cursor(), original_remaining); |  | 
| 118     VLOG(2) << "DecodeSegmentsAndValidate with SelectZeroAndOne"; |  | 
| 119     bool zero_next = !return_non_zero_on_first; |  | 
| 120     VERIFY_SUCCESS(DecodeSegmentsAndValidate( |  | 
| 121         &input, base::Bind(&SelectZeroAndOne, &zero_next), validator)) |  | 
| 122         << "\nFailed with SelectZeroAndOne"; |  | 
| 123     VERIFY_EQ(first_consumed, input.Offset()) |  | 
| 124         << "\nFailed with SelectZeroAndOne; input.Offset=" << input.Offset() |  | 
| 125         << "; input.Remaining=" << input.Remaining(); |  | 
| 126   } |  | 
| 127   { |  | 
| 128     // Decode again, with randomly selected segment sizes. |  | 
| 129     DecodeBuffer input(original->cursor(), original_remaining); |  | 
| 130     VLOG(2) << "DecodeSegmentsAndValidate with SelectRandom"; |  | 
| 131     VERIFY_SUCCESS(DecodeSegmentsAndValidate( |  | 
| 132         &input, base::Bind(&RandomDecoderTest::SelectRandom, |  | 
| 133                            base::Unretained(this), return_non_zero_on_first), |  | 
| 134         validator)) |  | 
| 135         << "\nFailed with SelectRandom; input.Offset=" << input.Offset() |  | 
| 136         << "; input.Remaining=" << input.Remaining(); |  | 
| 137     VERIFY_EQ(first_consumed, input.Offset()) << "\nFailed with SelectRandom"; |  | 
| 138   } |  | 
| 139   VERIFY_EQ(original_remaining, original->Remaining()); |  | 
| 140   original->AdvanceCursor(first_consumed); |  | 
| 141   VLOG(1) << "DecodeAndValidateSeveralWays - SUCCESS"; |  | 
| 142   return ::testing::AssertionSuccess(); |  | 
| 143 } |  | 
| 144 |  | 
| 145 // static |  | 
| 146 size_t RandomDecoderTest::SelectZeroAndOne(bool* zero_next, |  | 
| 147                                            bool first, |  | 
| 148                                            size_t offset, |  | 
| 149                                            size_t remaining) { |  | 
| 150   if (*zero_next) { |  | 
| 151     *zero_next = false; |  | 
| 152     return 0; |  | 
| 153   } else { |  | 
| 154     *zero_next = true; |  | 
| 155     return 1; |  | 
| 156   } |  | 
| 157 } |  | 
| 158 |  | 
| 159 size_t RandomDecoderTest::SelectRandom(bool return_non_zero_on_first, |  | 
| 160                                        bool first, |  | 
| 161                                        size_t offset, |  | 
| 162                                        size_t remaining) { |  | 
| 163   uint32_t r = random_.Rand32(); |  | 
| 164   if (first && return_non_zero_on_first) { |  | 
| 165     CHECK_LT(0u, remaining); |  | 
| 166     if (remaining == 1) { |  | 
| 167       return 1; |  | 
| 168     } |  | 
| 169     return 1 + (r % remaining);  // size in range [1, remaining). |  | 
| 170   } |  | 
| 171   return r % (remaining + 1);  // size in range [0, remaining]. |  | 
| 172 } |  | 
| 173 |  | 
| 174 uint32_t RandomDecoderTest::RandStreamId() { |  | 
| 175   return random_.Rand32() & StreamIdMask(); |  | 
| 176 } |  | 
| 177 |  | 
| 178 }  // namespace test |  | 
| 179 }  // namespace net |  | 
| OLD | NEW | 
|---|