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