link_header_util_unittest.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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. #include "components/link_header_util/link_header_util.h"
  5. #include "base/run_loop.h"
  6. #include "testing/gtest/include/gtest/gtest.h"
  7. namespace link_header_util {
  8. namespace {
  9. void SplitLinkHeaderForTesting(const std::string& header,
  10. std::vector<std::string>* values) {
  11. std::vector<StringIteratorPair> values_iterators = SplitLinkHeader(header);
  12. values->clear();
  13. for (const auto& pair : values_iterators)
  14. values->push_back(std::string(pair.first, pair.second));
  15. }
  16. bool ParseLinkHeaderValueForTesting(
  17. std::string value,
  18. std::string* url,
  19. std::unordered_map<std::string, absl::optional<std::string>>* params) {
  20. return ParseLinkHeaderValue(value.begin(), value.end(), url, params);
  21. }
  22. TEST(LinkHeaderTest, SplitEmpty) {
  23. std::vector<std::string> values;
  24. SplitLinkHeaderForTesting("", &values);
  25. ASSERT_EQ(0u, values.size());
  26. }
  27. TEST(LinkHeaderTest, SplitSimple) {
  28. std::vector<std::string> values;
  29. SplitLinkHeaderForTesting("hello", &values);
  30. ASSERT_EQ(1u, values.size());
  31. EXPECT_EQ("hello", values[0]);
  32. SplitLinkHeaderForTesting("foo, bar", &values);
  33. ASSERT_EQ(2u, values.size());
  34. EXPECT_EQ("foo", values[0]);
  35. EXPECT_EQ("bar", values[1]);
  36. SplitLinkHeaderForTesting(" 1\t,\t2,3", &values);
  37. ASSERT_EQ(3u, values.size());
  38. EXPECT_EQ("1", values[0]);
  39. EXPECT_EQ("2", values[1]);
  40. EXPECT_EQ("3", values[2]);
  41. }
  42. TEST(LinkHeaderTest, SplitSkipsEmpty) {
  43. std::vector<std::string> values;
  44. SplitLinkHeaderForTesting(", foo, , \t, bar", &values);
  45. ASSERT_EQ(2u, values.size());
  46. EXPECT_EQ("foo", values[0]);
  47. EXPECT_EQ("bar", values[1]);
  48. }
  49. TEST(LinkHeaderTest, SplitQuotes) {
  50. std::vector<std::string> values;
  51. SplitLinkHeaderForTesting("\"foo,bar\", 'bar,foo', <hel,lo>", &values);
  52. ASSERT_EQ(4u, values.size());
  53. EXPECT_EQ("\"foo,bar\"", values[0]);
  54. EXPECT_EQ("'bar", values[1]);
  55. EXPECT_EQ("foo'", values[2]);
  56. EXPECT_EQ("<hel,lo>", values[3]);
  57. }
  58. TEST(LinkHeaderTest, SplitEscapedQuotes) {
  59. std::vector<std::string> values;
  60. SplitLinkHeaderForTesting("\"f\\\"oo,bar\", 'b\\'ar,foo', <hel\\>,lo>",
  61. &values);
  62. ASSERT_EQ(5u, values.size());
  63. EXPECT_EQ("\"f\\\"oo,bar\"", values[0]);
  64. EXPECT_EQ("'b\\'ar", values[1]);
  65. EXPECT_EQ("foo'", values[2]);
  66. EXPECT_EQ("<hel\\>", values[3]);
  67. EXPECT_EQ("lo>", values[4]);
  68. }
  69. struct SimpleParseTestData {
  70. const char* link;
  71. bool valid;
  72. const char* url;
  73. const char* rel;
  74. const char* as;
  75. };
  76. void PrintTo(const SimpleParseTestData& test, std::ostream* os) {
  77. *os << ::testing::PrintToString(test.link);
  78. }
  79. class SimpleParseTest : public ::testing::TestWithParam<SimpleParseTestData> {};
  80. TEST_P(SimpleParseTest, Simple) {
  81. const SimpleParseTestData test = GetParam();
  82. std::string url;
  83. std::unordered_map<std::string, absl::optional<std::string>> params;
  84. EXPECT_EQ(test.valid,
  85. ParseLinkHeaderValueForTesting(test.link, &url, &params));
  86. if (test.valid) {
  87. EXPECT_EQ(test.url, url);
  88. EXPECT_EQ(test.rel, params["rel"].value_or(""));
  89. EXPECT_EQ(test.as, params["as"].value_or(""));
  90. }
  91. }
  92. // Test data mostly copied from blink::LinkHeaderTest. Expectations for a small
  93. // subset of test cases are different though. Mostly because blink::LinkHeader
  94. // factors in knowledge about semantics of Link headers (parameters that are
  95. // required to have a value if they occur, some parameters are auto-lower-cased,
  96. // headers with an "anchor" parameter are rejected by base::LinkHeader).
  97. // The code this tests purely parses without actually interpreting the data, as
  98. // it is expected that another layer on top will do more specific validations.
  99. const SimpleParseTestData simple_parse_tests[] = {
  100. {"</images/cat.jpg>; rel=prefetch", true, "/images/cat.jpg", "prefetch",
  101. ""},
  102. {"</images/cat.jpg>;rel=prefetch", true, "/images/cat.jpg", "prefetch", ""},
  103. {"</images/cat.jpg> ;rel=prefetch", true, "/images/cat.jpg", "prefetch",
  104. ""},
  105. {"</images/cat.jpg> ; rel=prefetch", true, "/images/cat.jpg",
  106. "prefetch", ""},
  107. {"< /images/cat.jpg> ; rel=prefetch", true, "/images/cat.jpg",
  108. "prefetch", ""},
  109. {"</images/cat.jpg > ; rel=prefetch", true, "/images/cat.jpg",
  110. "prefetch", ""},
  111. {"</images/cat.jpg wutwut> ; rel=prefetch", true,
  112. "/images/cat.jpg wutwut", "prefetch", ""},
  113. {"</images/cat.jpg wutwut \t > ; rel=prefetch", true,
  114. "/images/cat.jpg wutwut", "prefetch", ""},
  115. {"</images/cat.jpg>; rel=prefetch ", true, "/images/cat.jpg", "prefetch",
  116. ""},
  117. {"</images/cat.jpg>; Rel=prefetch ", true, "/images/cat.jpg", "prefetch",
  118. ""},
  119. {"</images/cat.jpg>; Rel=PReFetCh ", true, "/images/cat.jpg", "PReFetCh",
  120. ""},
  121. {"</images/cat.jpg>; rel=prefetch; rel=somethingelse", true,
  122. "/images/cat.jpg", "prefetch", ""},
  123. {"</images/cat.jpg>\t\t ; \trel=prefetch \t ", true, "/images/cat.jpg",
  124. "prefetch", ""},
  125. {"</images/cat.jpg>; rel= prefetch", true, "/images/cat.jpg", "prefetch",
  126. ""},
  127. {"<../images/cat.jpg?dog>; rel= prefetch", true, "../images/cat.jpg?dog",
  128. "prefetch", ""},
  129. {"</images/cat.jpg>; rel =prefetch", true, "/images/cat.jpg", "prefetch",
  130. ""},
  131. {"</images/cat.jpg>; rel pel=prefetch", false},
  132. {"< /images/cat.jpg>", true, "/images/cat.jpg", "", ""},
  133. {"</images/cat.jpg>; wut=sup; rel =prefetch", true, "/images/cat.jpg",
  134. "prefetch", ""},
  135. {"</images/cat.jpg>; wut=sup ; rel =prefetch", true, "/images/cat.jpg",
  136. "prefetch", ""},
  137. {"</images/cat.jpg>; wut=sup ; rel =prefetch \t ;", true,
  138. "/images/cat.jpg", "prefetch", ""},
  139. {"</images/cat.jpg> wut=sup ; rel =prefetch \t ;", false},
  140. {"< /images/cat.jpg", false},
  141. {"< http://wut.com/ sdfsdf ?sd>; rel=dns-prefetch", true,
  142. "http://wut.com/ sdfsdf ?sd", "dns-prefetch", ""},
  143. {"< http://wut.com/%20%20%3dsdfsdf?sd>; rel=dns-prefetch", true,
  144. "http://wut.com/%20%20%3dsdfsdf?sd", "dns-prefetch", ""},
  145. {"< http://wut.com/dfsdf?sdf=ghj&wer=rty>; rel=prefetch", true,
  146. "http://wut.com/dfsdf?sdf=ghj&wer=rty", "prefetch", ""},
  147. {"< http://wut.com/dfsdf?sdf=ghj&wer=rty>;;;;; rel=prefetch", true,
  148. "http://wut.com/dfsdf?sdf=ghj&wer=rty", "prefetch", ""},
  149. {"< http://wut.com/%20%20%3dsdfsdf?sd>; rel=preload;as=image", true,
  150. "http://wut.com/%20%20%3dsdfsdf?sd", "preload", "image"},
  151. {"< http://wut.com/%20%20%3dsdfsdf?sd>; rel=preload;as=whatever", true,
  152. "http://wut.com/%20%20%3dsdfsdf?sd", "preload", "whatever"},
  153. {"</images/cat.jpg>; rel=prefetch;", true, "/images/cat.jpg", "prefetch",
  154. ""},
  155. {"</images/cat.jpg>; rel=prefetch ;", true, "/images/cat.jpg",
  156. "prefetch", ""},
  157. {"</images/ca,t.jpg>; rel=prefetch ;", true, "/images/ca,t.jpg",
  158. "prefetch", ""},
  159. {"<simple.css>; rel=stylesheet; title=\"title with a DQUOTE and "
  160. "backslash\"",
  161. true, "simple.css", "stylesheet", ""},
  162. {"<simple.css>; rel=stylesheet; title=\"title with a DQUOTE \\\" and "
  163. "backslash: \\\"",
  164. false},
  165. {"<simple.css>; title=\"title with a DQUOTE \\\" and backslash: \"; "
  166. "rel=stylesheet; ",
  167. true, "simple.css", "stylesheet", ""},
  168. {"<simple.css>; title=\'title with a DQUOTE \\\' and backslash: \'; "
  169. "rel=stylesheet; ",
  170. true, "simple.css", "stylesheet", ""},
  171. {"<simple.css>; title=\"title with a DQUOTE \\\" and ;backslash,: \"; "
  172. "rel=stylesheet; ",
  173. true, "simple.css", "stylesheet", ""},
  174. {"<simple.css>; title=\"title with a DQUOTE \' and ;backslash,: \"; "
  175. "rel=stylesheet; ",
  176. true, "simple.css", "stylesheet", ""},
  177. {"<simple.css>; title=\"\"; rel=stylesheet; ", true, "simple.css",
  178. "stylesheet", ""},
  179. {"<simple.css>; title=\"\"; rel=\"stylesheet\"; ", true, "simple.css",
  180. "stylesheet", ""},
  181. {"<simple.css>; rel=stylesheet; title=\"", false},
  182. {"<simple.css>; rel=stylesheet; title=\"\"", true, "simple.css",
  183. "stylesheet", ""},
  184. {"<simple.css>; rel=\"stylesheet\"; title=\"", false},
  185. {"<simple.css>; rel=\";style,sheet\"; title=\"", false},
  186. {"<simple.css>; rel=\"bla'sdf\"; title=\"", false},
  187. {"<simple.css>; rel=\"\"; title=\"\"", true, "simple.css", "", ""},
  188. {"<simple.css>; rel=''; title=\"\"", true, "simple.css", "''", ""},
  189. {"<simple.css>; rel=''; bla", true, "simple.css", "''", ""},
  190. {"<simple.css>; rel='prefetch", true, "simple.css", "'prefetch", ""},
  191. {"<simple.css>; rel=\"prefetch", false},
  192. {"<simple.css>; rel=\"", false},
  193. {"simple.css; rel=prefetch", false},
  194. {"<simple.css>; rel=prefetch; rel=foobar", true, "simple.css", "prefetch",
  195. ""},
  196. };
  197. INSTANTIATE_TEST_SUITE_P(LinkHeaderTest,
  198. SimpleParseTest,
  199. testing::ValuesIn(simple_parse_tests));
  200. } // namespace
  201. } // namespace link_header_util