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 "net/spdy/spdy_test_utils.h"
6
7#include <cstring>
8
9#include "base/logging.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/sys_byteorder.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace net {
15
16namespace test {
17
18std::string HexDumpWithMarks(const unsigned char* data, int length,
19                             const bool* marks, int mark_length) {
20  static const char kHexChars[] = "0123456789abcdef";
21  static const int kColumns = 4;
22
23  const int kSizeLimit = 1024;
24  if (length > kSizeLimit || mark_length > kSizeLimit) {
25    LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes.";
26    length = std::min(length, kSizeLimit);
27    mark_length = std::min(mark_length, kSizeLimit);
28  }
29
30  std::string hex;
31  for (const unsigned char* row = data; length > 0;
32       row += kColumns, length -= kColumns) {
33    for (const unsigned char *p = row; p < row + 4; ++p) {
34      if (p < row + length) {
35        const bool mark =
36            (marks && (p - data) < mark_length && marks[p - data]);
37        hex += mark ? '*' : ' ';
38        hex += kHexChars[(*p & 0xf0) >> 4];
39        hex += kHexChars[*p & 0x0f];
40        hex += mark ? '*' : ' ';
41      } else {
42        hex += "    ";
43      }
44    }
45    hex = hex + "  ";
46
47    for (const unsigned char *p = row; p < row + 4 && p < row + length; ++p)
48      hex += (*p >= 0x20 && *p <= 0x7f) ? (*p) : '.';
49
50    hex = hex + '\n';
51  }
52  return hex;
53}
54
55void CompareCharArraysWithHexError(
56    const std::string& description,
57    const unsigned char* actual,
58    const int actual_len,
59    const unsigned char* expected,
60    const int expected_len) {
61  const int min_len = std::min(actual_len, expected_len);
62  const int max_len = std::max(actual_len, expected_len);
63  scoped_ptr<bool[]> marks(new bool[max_len]);
64  bool identical = (actual_len == expected_len);
65  for (int i = 0; i < min_len; ++i) {
66    if (actual[i] != expected[i]) {
67      marks[i] = true;
68      identical = false;
69    } else {
70      marks[i] = false;
71    }
72  }
73  for (int i = min_len; i < max_len; ++i) {
74    marks[i] = true;
75  }
76  if (identical) return;
77  ADD_FAILURE()
78      << "Description:\n"
79      << description
80      << "\n\nExpected:\n"
81      << HexDumpWithMarks(expected, expected_len, marks.get(), max_len)
82      << "\nActual:\n"
83      << HexDumpWithMarks(actual, actual_len, marks.get(), max_len);
84}
85
86void SetFrameFlags(SpdyFrame* frame, uint8 flags, int spdy_version) {
87  switch (spdy_version) {
88    case 2:
89    case 3:
90      frame->data()[4] = flags;
91      break;
92    case 4:
93      frame->data()[3] = flags;
94      break;
95    default:
96      LOG(FATAL) << "Unsupported SPDY version.";
97  }
98}
99
100void SetFrameLength(SpdyFrame* frame, size_t length, int spdy_version) {
101  switch (spdy_version) {
102    case 2:
103    case 3:
104      CHECK_EQ(0u, length & ~kLengthMask);
105      {
106        int32 wire_length = base::HostToNet32(length);
107        // The length field in SPDY 2 and 3 is a 24-bit (3B) integer starting at
108        // offset 5.
109        memcpy(frame->data() + 5, reinterpret_cast<char*>(&wire_length) + 1, 3);
110      }
111      break;
112    case 4:
113      CHECK_GT(1u<<16, length);
114      {
115        int32 wire_length = base::HostToNet16(static_cast<uint16>(length));
116        memcpy(frame->data(),
117               reinterpret_cast<char*>(&wire_length),
118               sizeof(uint16));
119      }
120      break;
121    default:
122      LOG(FATAL) << "Unsupported SPDY version.";
123  }
124}
125
126
127}  // namespace test
128
129}  // namespace net
130