1 // Copyright (c) 2011 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 "base/string_number_conversions.h" 6 #include "base/string_util.h" 7 #include "base/utf_string_conversions.h" 8 #include "chrome/browser/autocomplete/autocomplete.h" 9 #include "chrome/browser/autocomplete/autocomplete_match.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 class AutocompleteResultTest : public testing::Test { 13 public: 14 struct TestData { 15 // Used to build a url for the AutocompleteMatch. The URL becomes 16 // 'http://' + |url_id|. 17 int url_id; 18 19 // ID of the provider. 20 int provider_id; 21 22 // Relevance score. 23 int relevance; 24 }; 25 26 AutocompleteResultTest() {} 27 28 // Configures |match| from |data|. 29 static void PopulateAutocompleteMatch(const TestData& data, 30 AutocompleteMatch* match); 31 32 // Adds |count| AutocompleteMatches to |matches|. 33 static void PopulateAutocompleteMatches(const TestData* data, 34 size_t count, 35 ACMatches* matches); 36 37 // Asserts that |result| has |expected_count| matches matching |expected|. 38 void AssertResultMatches(const AutocompleteResult& result, 39 const TestData* expected, 40 size_t expected_count); 41 42 // Creates an AutocompleteResult from |last| and |current|. The two are 43 // merged by |CopyOldMatches| and compared by |AssertResultMatches|. 44 void RunCopyOldMatchesTest(const TestData* last, size_t last_size, 45 const TestData* current, size_t current_size, 46 const TestData* expected, size_t expected_size); 47 48 private: 49 DISALLOW_COPY_AND_ASSIGN(AutocompleteResultTest); 50 }; 51 52 // static 53 void AutocompleteResultTest::PopulateAutocompleteMatch( 54 const TestData& data, 55 AutocompleteMatch* match) { 56 match->provider = reinterpret_cast<AutocompleteProvider*>(data.provider_id); 57 match->fill_into_edit = base::IntToString16(data.url_id); 58 std::string url_id(1, data.url_id + 'a'); 59 match->destination_url = GURL("http://" + url_id); 60 match->relevance = data.relevance; 61 } 62 63 // static 64 void AutocompleteResultTest::PopulateAutocompleteMatches( 65 const TestData* data, 66 size_t count, 67 ACMatches* matches) { 68 for (size_t i = 0; i < count; ++i) { 69 AutocompleteMatch match; 70 PopulateAutocompleteMatch(data[i], &match); 71 matches->push_back(match); 72 } 73 } 74 75 void AutocompleteResultTest::AssertResultMatches( 76 const AutocompleteResult& result, 77 const TestData* expected, 78 size_t expected_count) { 79 ASSERT_EQ(expected_count, result.size()); 80 for (size_t i = 0; i < expected_count; ++i) { 81 AutocompleteMatch expected_match; 82 PopulateAutocompleteMatch(expected[i], &expected_match); 83 const AutocompleteMatch& match = *(result.begin() + i); 84 EXPECT_EQ(expected_match.provider, match.provider) << i; 85 EXPECT_EQ(expected_match.relevance, match.relevance) << i; 86 EXPECT_EQ(expected_match.destination_url.spec(), 87 match.destination_url.spec()) << i; 88 } 89 } 90 91 void AutocompleteResultTest::RunCopyOldMatchesTest( 92 const TestData* last, size_t last_size, 93 const TestData* current, size_t current_size, 94 const TestData* expected, size_t expected_size) { 95 AutocompleteInput input(ASCIIToUTF16("a"), string16(), false, false, false, 96 AutocompleteInput::ALL_MATCHES); 97 98 ACMatches last_matches; 99 PopulateAutocompleteMatches(last, last_size, &last_matches); 100 AutocompleteResult last_result; 101 last_result.AppendMatches(last_matches); 102 last_result.SortAndCull(input); 103 104 ACMatches current_matches; 105 PopulateAutocompleteMatches(current, current_size, ¤t_matches); 106 AutocompleteResult current_result; 107 current_result.AppendMatches(current_matches); 108 current_result.SortAndCull(input); 109 current_result.CopyOldMatches(input, last_result); 110 111 AssertResultMatches(current_result, expected, expected_size); 112 } 113 114 // Assertion testing for AutocompleteResult::Swap. 115 TEST_F(AutocompleteResultTest, Swap) { 116 AutocompleteResult r1; 117 AutocompleteResult r2; 118 119 // Swap with empty shouldn't do anything interesting. 120 r1.Swap(&r2); 121 EXPECT_EQ(r1.end(), r1.default_match()); 122 EXPECT_EQ(r2.end(), r2.default_match()); 123 124 // Swap with a single match. 125 ACMatches matches; 126 AutocompleteMatch match; 127 AutocompleteInput input(ASCIIToUTF16("a"), string16(), false, false, false, 128 AutocompleteInput::ALL_MATCHES); 129 matches.push_back(match); 130 r1.AppendMatches(matches); 131 r1.SortAndCull(input); 132 EXPECT_EQ(r1.begin(), r1.default_match()); 133 EXPECT_EQ("http://a/", r1.alternate_nav_url().spec()); 134 r1.Swap(&r2); 135 EXPECT_TRUE(r1.empty()); 136 EXPECT_EQ(r1.end(), r1.default_match()); 137 EXPECT_TRUE(r1.alternate_nav_url().is_empty()); 138 ASSERT_FALSE(r2.empty()); 139 EXPECT_EQ(r2.begin(), r2.default_match()); 140 EXPECT_EQ("http://a/", r2.alternate_nav_url().spec()); 141 } 142 143 // Tests that if the new results have a lower max relevance score than last, 144 // any copied results have their relevance shifted down. 145 TEST_F(AutocompleteResultTest, CopyOldMatches) { 146 TestData last[] = { 147 { 0, 0, 1000 }, 148 { 1, 0, 500 }, 149 }; 150 TestData current[] = { 151 { 2, 0, 400 }, 152 }; 153 TestData result[] = { 154 { 2, 0, 400 }, 155 { 1, 0, 399 }, 156 }; 157 158 ASSERT_NO_FATAL_FAILURE( 159 RunCopyOldMatchesTest(last, ARRAYSIZE_UNSAFE(last), 160 current, ARRAYSIZE_UNSAFE(current), 161 result, ARRAYSIZE_UNSAFE(result))); 162 } 163 164 // Tests that matches are copied correctly from two distinct providers. 165 TEST_F(AutocompleteResultTest, CopyOldMatches2) { 166 TestData last[] = { 167 { 0, 0, 1000 }, 168 { 1, 1, 500 }, 169 { 2, 0, 400 }, 170 { 3, 1, 300 }, 171 }; 172 TestData current[] = { 173 { 4, 0, 1100 }, 174 { 5, 1, 550 }, 175 }; 176 TestData result[] = { 177 { 4, 0, 1100 }, 178 { 5, 1, 550 }, 179 { 2, 0, 400 }, 180 { 3, 1, 300 }, 181 }; 182 183 ASSERT_NO_FATAL_FAILURE( 184 RunCopyOldMatchesTest(last, ARRAYSIZE_UNSAFE(last), 185 current, ARRAYSIZE_UNSAFE(current), 186 result, ARRAYSIZE_UNSAFE(result))); 187 } 188