172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <algorithm>
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string>
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/escape.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/i18n/icu_string_conversions.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/gtest/include/gtest/gtest.h"
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const size_t kNpos = string16::npos;
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct EscapeCase {
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const wchar_t* input;
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const wchar_t* output;
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct UnescapeURLCase {
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const wchar_t* input;
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UnescapeRule::Type rules;
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const wchar_t* output;
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct UnescapeURLCaseASCII {
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* input;
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UnescapeRule::Type rules;
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* output;
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct UnescapeAndDecodeCase {
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* input;
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The expected output when run through UnescapeURL.
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* url_unescaped;
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The expected output when run through UnescapeQuery.
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* query_unescaped;
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The expected output when run through UnescapeAndDecodeURLComponent.
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const wchar_t* decoded;
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct AdjustOffsetCase {
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* input;
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t input_offset;
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t output_offset;
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct EscapeForHTMLCase {
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* input;
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* expected_output;
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(EscapeTest, EscapeTextForFormSubmission) {
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const EscapeCase escape_cases[] = {
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"foo", L"foo"},
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"foo bar", L"foo+bar"},
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"foo++", L"foo%2B%2B"}
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < arraysize(escape_cases); ++i) {
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EscapeCase value = escape_cases[i];
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_EQ(WideToUTF16Hack(value.output),
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              EscapeQueryParamValueUTF8(WideToUTF16Hack(value.input), true));
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const EscapeCase escape_cases_no_plus[] = {
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"foo", L"foo"},
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"foo bar", L"foo%20bar"},
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"foo++", L"foo%2B%2B"}
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < arraysize(escape_cases_no_plus); ++i) {
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EscapeCase value = escape_cases_no_plus[i];
8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_EQ(WideToUTF16Hack(value.output),
8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              EscapeQueryParamValueUTF8(WideToUTF16Hack(value.input), false));
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Test all the values in we're supposed to be escaping.
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const std::string no_escape(
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "abcdefghijklmnopqrstuvwxyz"
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "0123456789"
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "!'()*-._~");
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < 256; ++i) {
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string in;
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    in.push_back(i);
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string out = EscapeQueryParamValue(in, true);
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (0 == i) {
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_EQ(out, std::string("%00"));
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else if (32 == i) {
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Spaces are plus escaped like web forms.
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_EQ(out, std::string("+"));
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else if (no_escape.find(in) == std::string::npos) {
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Check %hex escaping
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      std::string expected = base::StringPrintf("%%%02X", i);
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_EQ(expected, out);
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // No change for things in the no_escape list.
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_EQ(out, in);
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check to see if EscapeQueryParamValueUTF8 is the same as
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // EscapeQueryParamValue(..., kCodepageUTF8,)
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  string16 test_str;
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  test_str.reserve(5000);
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 1; i < 5000; ++i) {
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    test_str.push_back(i);
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  string16 wide;
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(EscapeQueryParamValue(test_str, base::kCodepageUTF8, true,
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    &wide));
12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_EQ(wide, EscapeQueryParamValueUTF8(test_str, true));
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(EscapeQueryParamValue(test_str, base::kCodepageUTF8, false,
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    &wide));
12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_EQ(wide, EscapeQueryParamValueUTF8(test_str, false));
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(EscapeTest, EscapePath) {
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_EQ(
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Most of the character space we care about, un-escaped
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EscapePath(
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "\x02\n\x1d !\"#$%&'()*+,-./0123456789:;"
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "[\\]^_`abcdefghijklmnopqrstuvwxyz"
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "{|}~\x7f\x80\xff"),
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Escaped
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "%02%0A%1D%20!%22%23$%25&'()*+,-./0123456789%3A;"
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "%3C=%3E%3F@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz"
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "%7B%7C%7D~%7F%80%FF");
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(EscapeTest, EscapeUrlEncodedData) {
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_EQ(
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Most of the character space we care about, un-escaped
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EscapeUrlEncodedData(
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "\x02\n\x1d !\"#$%&'()*+,-./0123456789:;"
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "[\\]^_`abcdefghijklmnopqrstuvwxyz"
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "{|}~\x7f\x80\xff"),
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Escaped
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "%02%0A%1D+!%22%23%24%25%26%27()*%2B,-./0123456789:%3B"
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ"
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz"
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "%7B%7C%7D~%7F%80%FF");
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(EscapeTest, UnescapeURLComponentASCII) {
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const UnescapeURLCaseASCII unescape_cases[] = {
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"", UnescapeRule::NORMAL, ""},
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"%2", UnescapeRule::NORMAL, "%2"},
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"%%%%%%", UnescapeRule::NORMAL, "%%%%%%"},
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"Don't escape anything", UnescapeRule::NORMAL, "Don't escape anything"},
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"Invalid %escape %2", UnescapeRule::NORMAL, "Invalid %escape %2"},
16521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {"Some%20random text %25%2dOK", UnescapeRule::NONE,
16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     "Some%20random text %25%2dOK"},
16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {"Some%20random text %25%2dOK", UnescapeRule::NORMAL,
16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     "Some%20random text %25-OK"},
16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {"Some%20random text %25%2dOK", UnescapeRule::SPACES,
17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     "Some random text %25-OK"},
17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {"Some%20random text %25%2dOK", UnescapeRule::URL_SPECIAL_CHARS,
17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     "Some%20random text %-OK"},
17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {"Some%20random text %25%2dOK",
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS,
17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     "Some random text %-OK"},
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"%A0%B1%C2%D3%E4%F5", UnescapeRule::NORMAL, "\xA0\xB1\xC2\xD3\xE4\xF5"},
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"%Aa%Bb%Cc%Dd%Ee%Ff", UnescapeRule::NORMAL, "\xAa\xBb\xCc\xDd\xEe\xFf"},
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Certain URL-sensitive characters should not be unescaped unless asked.
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"Hello%20%13%10world %23# %3F? %3D= %26& %25% %2B+", UnescapeRule::SPACES,
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     "Hello %13%10world %23# %3F? %3D= %26& %25% %2B+"},
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"Hello%20%13%10world %23# %3F? %3D= %26& %25% %2B+",
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     UnescapeRule::URL_SPECIAL_CHARS,
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     "Hello%20%13%10world ## ?? == && %% ++"},
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Control characters.
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"%01%02%03%04%05%06%07%08%09 %25", UnescapeRule::URL_SPECIAL_CHARS,
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     "%01%02%03%04%05%06%07%08%09 %"},
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"%01%02%03%04%05%06%07%08%09 %25", UnescapeRule::CONTROL_CHARS,
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     "\x01\x02\x03\x04\x05\x06\x07\x08\x09 %25"},
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"Hello%20%13%10%02", UnescapeRule::SPACES, "Hello %13%10%02"},
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"Hello%20%13%10%02", UnescapeRule::CONTROL_CHARS, "Hello%20\x13\x10\x02"},
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < arraysize(unescape_cases); i++) {
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string str(unescape_cases[i].input);
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(std::string(unescape_cases[i].output),
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              UnescapeURLComponent(str, unescape_cases[i].rules));
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Test the NULL character unescaping (which wouldn't work above since those
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // are just char pointers).
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string input("Null");
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  input.push_back(0);  // Also have a NULL in the input.
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  input.append("%00%39Test");
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // When we're unescaping NULLs
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string expected("Null");
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected.push_back(0);
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected.push_back(0);
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected.append("9Test");
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected, UnescapeURLComponent(input, UnescapeRule::CONTROL_CHARS));
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // When we're not unescaping NULLs.
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected = "Null";
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected.push_back(0);
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected.append("%009Test");
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected, UnescapeURLComponent(input, UnescapeRule::NORMAL));
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(EscapeTest, UnescapeURLComponent) {
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const UnescapeURLCase unescape_cases[] = {
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"", UnescapeRule::NORMAL, L""},
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"%2", UnescapeRule::NORMAL, L"%2"},
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"%%%%%%", UnescapeRule::NORMAL, L"%%%%%%"},
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"Don't escape anything", UnescapeRule::NORMAL, L"Don't escape anything"},
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"Invalid %escape %2", UnescapeRule::NORMAL, L"Invalid %escape %2"},
22621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {L"Some%20random text %25%2dOK", UnescapeRule::NONE,
22721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     L"Some%20random text %25%2dOK"},
22821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {L"Some%20random text %25%2dOK", UnescapeRule::NORMAL,
22921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     L"Some%20random text %25-OK"},
23021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {L"Some%20random text %25%2dOK", UnescapeRule::SPACES,
23121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     L"Some random text %25-OK"},
23221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {L"Some%20random text %25%2dOK", UnescapeRule::URL_SPECIAL_CHARS,
23321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     L"Some%20random text %-OK"},
23421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {L"Some%20random text %25%2dOK",
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS,
23621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     L"Some random text %-OK"},
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"%A0%B1%C2%D3%E4%F5", UnescapeRule::NORMAL, L"\xA0\xB1\xC2\xD3\xE4\xF5"},
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"%Aa%Bb%Cc%Dd%Ee%Ff", UnescapeRule::NORMAL, L"\xAa\xBb\xCc\xDd\xEe\xFf"},
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Certain URL-sensitive characters should not be unescaped unless asked.
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"Hello%20%13%10world %23# %3F? %3D= %26& %25% %2B+", UnescapeRule::SPACES,
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"Hello %13%10world %23# %3F? %3D= %26& %25% %2B+"},
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"Hello%20%13%10world %23# %3F? %3D= %26& %25% %2B+",
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     UnescapeRule::URL_SPECIAL_CHARS,
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"Hello%20%13%10world ## ?? == && %% ++"},
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We can neither escape nor unescape '@' since some websites expect it to
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // be preserved as either '@' or "%40".
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // See http://b/996720 and http://crbug.com/23933 .
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    {L"me@my%40example", UnescapeRule::NORMAL, L"me@my%40example"},
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Control characters.
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"%01%02%03%04%05%06%07%08%09 %25", UnescapeRule::URL_SPECIAL_CHARS,
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"%01%02%03%04%05%06%07%08%09 %"},
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"%01%02%03%04%05%06%07%08%09 %25", UnescapeRule::CONTROL_CHARS,
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"\x01\x02\x03\x04\x05\x06\x07\x08\x09 %25"},
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"Hello%20%13%10%02", UnescapeRule::SPACES, L"Hello %13%10%02"},
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"Hello%20%13%10%02", UnescapeRule::CONTROL_CHARS,
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"Hello%20\x13\x10\x02"},
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {L"Hello\x9824\x9827", UnescapeRule::CONTROL_CHARS,
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"Hello\x9824\x9827"},
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < arraysize(unescape_cases); i++) {
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    string16 str(WideToUTF16(unescape_cases[i].input));
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(WideToUTF16(unescape_cases[i].output),
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              UnescapeURLComponent(str, unescape_cases[i].rules));
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Test the NULL character unescaping (which wouldn't work above since those
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // are just char pointers).
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  string16 input(WideToUTF16(L"Null"));
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  input.push_back(0);  // Also have a NULL in the input.
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  input.append(WideToUTF16(L"%00%39Test"));
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // When we're unescaping NULLs
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  string16 expected(WideToUTF16(L"Null"));
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected.push_back(0);
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected.push_back(0);
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected.append(ASCIIToUTF16("9Test"));
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected, UnescapeURLComponent(input, UnescapeRule::CONTROL_CHARS));
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // When we're not unescaping NULLs.
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected = WideToUTF16(L"Null");
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected.push_back(0);
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected.append(WideToUTF16(L"%009Test"));
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected, UnescapeURLComponent(input, UnescapeRule::NORMAL));
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(EscapeTest, UnescapeAndDecodeUTF8URLComponent) {
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const UnescapeAndDecodeCase unescape_cases[] = {
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "%",
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "%",
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "%",
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"%"},
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "+",
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "+",
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      " ",
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"+"},
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "%2+",
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "%2+",
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "%2 ",
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"%2+"},
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "+%%%+%%%",
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "+%%%+%%%",
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      " %%% %%%",
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"+%%%+%%%"},
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "Don't escape anything",
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "Don't escape anything",
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "Don't escape anything",
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"Don't escape anything"},
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "+Invalid %escape %2+",
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "+Invalid %escape %2+",
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      " Invalid %escape %2 ",
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"+Invalid %escape %2+"},
31321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    { "Some random text %25%2dOK",
31421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      "Some random text %25-OK",
31521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      "Some random text %25-OK",
31621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     L"Some random text %25-OK"},
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "%01%02%03%04%05%06%07%08%09",
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "%01%02%03%04%05%06%07%08%09",
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "%01%02%03%04%05%06%07%08%09",
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"%01%02%03%04%05%06%07%08%09"},
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "%E4%BD%A0+%E5%A5%BD",
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "\xE4\xBD\xA0+\xE5\xA5\xBD",
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "\xE4\xBD\xA0 \xE5\xA5\xBD",
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"\x4f60+\x597d"},
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "%ED%ED",  // Invalid UTF-8.
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "\xED\xED",
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "\xED\xED",
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     L"%ED%ED"},  // Invalid UTF-8 -> kept unescaped.
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < arraysize(unescape_cases); i++) {
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string unescaped = UnescapeURLComponent(unescape_cases[i].input,
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                 UnescapeRule::NORMAL);
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(std::string(unescape_cases[i].url_unescaped), unescaped);
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    unescaped = UnescapeURLComponent(unescape_cases[i].input,
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     UnescapeRule::REPLACE_PLUS_WITH_SPACE);
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(std::string(unescape_cases[i].query_unescaped), unescaped);
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // TODO: Need to test unescape_spaces and unescape_percent.
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    string16 decoded = UnescapeAndDecodeUTF8URLComponent(
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        unescape_cases[i].input, UnescapeRule::NORMAL, NULL);
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(WideToUTF16Hack(std::wstring(unescape_cases[i].decoded)),
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              decoded);
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(EscapeTest, AdjustOffset) {
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const AdjustOffsetCase adjust_cases[] = {
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"", 0, std::wstring::npos},
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"test", 0, 0},
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"test", 2, 2},
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"test", 4, std::wstring::npos},
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"test", std::wstring::npos, std::wstring::npos},
35521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {"%2dtest", 6, 4},
35621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {"%2dtest", 2, std::wstring::npos},
35721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    {"test%2d", 2, 2},
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"%E4%BD%A0+%E5%A5%BD", 9, 1},
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"%E4%BD%A0+%E5%A5%BD", 6, std::wstring::npos},
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {"%ED%B0%80+%E5%A5%BD", 6, 6},
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < arraysize(adjust_cases); i++) {
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    size_t offset = adjust_cases[i].input_offset;
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UnescapeAndDecodeUTF8URLComponent(adjust_cases[i].input,
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      UnescapeRule::NORMAL, &offset);
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(adjust_cases[i].output_offset, offset);
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(EscapeTest, EscapeForHTML) {
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const EscapeForHTMLCase tests[] = {
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "hello", "hello" },
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "<hello>", "&lt;hello&gt;" },
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "don\'t mess with me", "don&#39;t mess with me" },
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < arraysize(tests); ++i) {
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string result = EscapeForHTML(std::string(tests[i].input));
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(std::string(tests[i].expected_output), result);
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(EscapeTest, UnescapeForHTML) {
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const EscapeForHTMLCase tests[] = {
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "", "" },
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "&lt;hello&gt;", "<hello>" },
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "don&#39;t mess with me", "don\'t mess with me" },
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "&lt;&gt;&amp;&quot;&#39;", "<>&\"'" },
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "& lt; &amp ; &; '", "& lt; &amp ; &; '" },
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "&amp;", "&" },
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "&quot;", "\"" },
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "&#39;", "'" },
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "&lt;", "<" },
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "&gt;", ">" },
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    { "&amp; &", "& &" },
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < arraysize(tests); ++i) {
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    string16 result = UnescapeForHTML(ASCIIToUTF16(tests[i].input));
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(ASCIIToUTF16(tests[i].expected_output), result);
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST(EscapeTest, AdjustEncodingOffset) {
404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Imagine we have strings as shown in the following cases where the
405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // %XX's represent encoded characters
406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // 1: abc%ECdef ==> abcXdef
408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::vector<size_t> offsets;
409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t t = 0; t < 9; ++t)
410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    offsets.push_back(t);
411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  AdjustEncodingOffset::Adjustments adjustments;
412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  adjustments.push_back(3);
413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::for_each(offsets.begin(), offsets.end(),
414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                AdjustEncodingOffset(adjustments));
415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  size_t expected_1[] = {0, 1, 2, 3, kNpos, kNpos, 4, 5, 6};
416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(offsets.size(), arraysize(expected_1));
417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < arraysize(expected_1); ++i)
418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_EQ(expected_1[i], offsets[i]);
419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // 2: %ECabc%EC%ECdef%EC ==> XabcXXdefX
422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  offsets.clear();
423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t t = 0; t < 18; ++t)
424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    offsets.push_back(t);
425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  adjustments.clear();
426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  adjustments.push_back(0);
427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  adjustments.push_back(6);
428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  adjustments.push_back(9);
429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  adjustments.push_back(15);
430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::for_each(offsets.begin(), offsets.end(),
431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                AdjustEncodingOffset(adjustments));
432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  size_t expected_2[] = {0, kNpos, kNpos, 1, 2, 3, 4, kNpos, kNpos, 5, kNpos,
433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                         kNpos, 6, 7, 8, 9, kNpos, kNpos};
434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(offsets.size(), arraysize(expected_2));
435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < arraysize(expected_2); ++i)
436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_EQ(expected_2[i], offsets[i]);
437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
438