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 <string>
6
7#include "base/memory/scoped_ptr.h"
8#include "base/values.h"
9#include "extensions/common/event_filter.h"
10#include "extensions/common/event_filtering_info.h"
11#include "extensions/common/event_matcher.h"
12#include "ipc/ipc_message.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15using base::DictionaryValue;
16using base::ListValue;
17using base::Value;
18
19namespace extensions {
20
21class EventFilterUnittest : public testing::Test {
22 public:
23  EventFilterUnittest() {
24    google_event_.SetURL(GURL("http://google.com"));
25    yahoo_event_.SetURL(GURL("http://yahoo.com"));
26    random_url_event_.SetURL(GURL("http://www.something-else.com"));
27    empty_url_event_.SetURL(GURL());
28  }
29
30 protected:
31  scoped_ptr<base::Value> HostSuffixDict(const std::string& host_suffix) {
32    scoped_ptr<base::DictionaryValue> dict(new DictionaryValue());
33    dict->Set("hostSuffix", new base::StringValue(host_suffix));
34    return scoped_ptr<base::Value>(dict.release());
35  }
36
37  scoped_ptr<base::ListValue> ValueAsList(scoped_ptr<base::Value> value) {
38    scoped_ptr<base::ListValue> result(new base::ListValue());
39    result->Append(value.release());
40    return result.Pass();
41  }
42
43  scoped_ptr<EventMatcher> AllURLs() {
44    return scoped_ptr<EventMatcher>(new EventMatcher(
45        scoped_ptr<DictionaryValue>(new DictionaryValue), MSG_ROUTING_NONE));
46  }
47
48  scoped_ptr<EventMatcher> HostSuffixMatcher(const std::string& host_suffix) {
49    return MatcherFromURLFilterList(ValueAsList(HostSuffixDict(host_suffix)));
50  }
51
52  scoped_ptr<EventMatcher> MatcherFromURLFilterList(
53      scoped_ptr<ListValue> url_filter_list) {
54    scoped_ptr<DictionaryValue> filter_dict(new DictionaryValue);
55    filter_dict->Set("url", url_filter_list.release());
56    return scoped_ptr<EventMatcher>(
57        new EventMatcher(filter_dict.Pass(), MSG_ROUTING_NONE));
58  }
59
60  EventFilter event_filter_;
61  EventFilteringInfo empty_event_;
62  EventFilteringInfo google_event_;
63  EventFilteringInfo yahoo_event_;
64  EventFilteringInfo random_url_event_;
65  EventFilteringInfo empty_url_event_;
66};
67
68TEST_F(EventFilterUnittest, NoMatchersMatchIfEmpty) {
69  std::set<int> matches = event_filter_.MatchEvent("some-event",
70                                                   empty_event_,
71                                                   MSG_ROUTING_NONE);
72  ASSERT_EQ(0u, matches.size());
73}
74
75TEST_F(EventFilterUnittest, AddingEventMatcherDoesntCrash) {
76  event_filter_.AddEventMatcher("event1", AllURLs());
77}
78
79TEST_F(EventFilterUnittest,
80    DontMatchAgainstMatchersForDifferentEvents) {
81  event_filter_.AddEventMatcher("event1", AllURLs());
82  std::set<int> matches = event_filter_.MatchEvent("event2",
83                                                   empty_event_,
84                                                   MSG_ROUTING_NONE);
85  ASSERT_EQ(0u, matches.size());
86}
87
88TEST_F(EventFilterUnittest, DoMatchAgainstMatchersForSameEvent) {
89  int id = event_filter_.AddEventMatcher("event1", AllURLs());
90  std::set<int> matches = event_filter_.MatchEvent("event1",
91      google_event_, MSG_ROUTING_NONE);
92  ASSERT_EQ(1u, matches.size());
93  ASSERT_EQ(1u, matches.count(id));
94}
95
96TEST_F(EventFilterUnittest, DontMatchUnlessMatcherMatches) {
97  EventFilteringInfo info;
98  info.SetURL(GURL("http://www.yahoo.com"));
99  event_filter_.AddEventMatcher("event1", HostSuffixMatcher("google.com"));
100  std::set<int> matches = event_filter_.MatchEvent(
101      "event1", info, MSG_ROUTING_NONE);
102  ASSERT_TRUE(matches.empty());
103}
104
105TEST_F(EventFilterUnittest, RemovingAnEventMatcherStopsItMatching) {
106  int id = event_filter_.AddEventMatcher("event1", AllURLs());
107  event_filter_.RemoveEventMatcher(id);
108  std::set<int> matches = event_filter_.MatchEvent("event1",
109                                                   empty_event_,
110                                                   MSG_ROUTING_NONE);
111  ASSERT_TRUE(matches.empty());
112}
113
114TEST_F(EventFilterUnittest, MultipleEventMatches) {
115  int id1 = event_filter_.AddEventMatcher("event1", AllURLs());
116  int id2 = event_filter_.AddEventMatcher("event1", AllURLs());
117  std::set<int> matches = event_filter_.MatchEvent("event1",
118      google_event_, MSG_ROUTING_NONE);
119  ASSERT_EQ(2u, matches.size());
120  ASSERT_EQ(1u, matches.count(id1));
121  ASSERT_EQ(1u, matches.count(id2));
122}
123
124TEST_F(EventFilterUnittest, TestURLMatching) {
125  EventFilteringInfo info;
126  info.SetURL(GURL("http://www.google.com"));
127  int id = event_filter_.AddEventMatcher("event1",
128                                         HostSuffixMatcher("google.com"));
129  std::set<int> matches = event_filter_.MatchEvent(
130      "event1", info, MSG_ROUTING_NONE);
131  ASSERT_EQ(1u, matches.size());
132  ASSERT_EQ(1u, matches.count(id));
133}
134
135TEST_F(EventFilterUnittest, TestMultipleURLFiltersMatchOnAny) {
136  scoped_ptr<base::ListValue> filters(new base::ListValue());
137  filters->Append(HostSuffixDict("google.com").release());
138  filters->Append(HostSuffixDict("yahoo.com").release());
139
140  scoped_ptr<EventMatcher> matcher(MatcherFromURLFilterList(filters.Pass()));
141  int id = event_filter_.AddEventMatcher("event1", matcher.Pass());
142
143  {
144    std::set<int> matches = event_filter_.MatchEvent("event1",
145        google_event_, MSG_ROUTING_NONE);
146    ASSERT_EQ(1u, matches.size());
147    ASSERT_EQ(1u, matches.count(id));
148  }
149  {
150    std::set<int> matches = event_filter_.MatchEvent("event1",
151        yahoo_event_, MSG_ROUTING_NONE);
152    ASSERT_EQ(1u, matches.size());
153    ASSERT_EQ(1u, matches.count(id));
154  }
155  {
156    std::set<int> matches = event_filter_.MatchEvent("event1",
157        random_url_event_, MSG_ROUTING_NONE);
158    ASSERT_EQ(0u, matches.size());
159  }
160}
161
162TEST_F(EventFilterUnittest, TestStillMatchesAfterRemoval) {
163  int id1 = event_filter_.AddEventMatcher("event1", AllURLs());
164  int id2 = event_filter_.AddEventMatcher("event1", AllURLs());
165
166  event_filter_.RemoveEventMatcher(id1);
167  {
168    std::set<int> matches = event_filter_.MatchEvent("event1",
169        google_event_, MSG_ROUTING_NONE);
170    ASSERT_EQ(1u, matches.size());
171    ASSERT_EQ(1u, matches.count(id2));
172  }
173}
174
175TEST_F(EventFilterUnittest, TestMatchesOnlyAgainstPatternsForCorrectEvent) {
176  int id1 = event_filter_.AddEventMatcher("event1", AllURLs());
177  event_filter_.AddEventMatcher("event2", AllURLs());
178
179  {
180    std::set<int> matches = event_filter_.MatchEvent("event1",
181        google_event_, MSG_ROUTING_NONE);
182    ASSERT_EQ(1u, matches.size());
183    ASSERT_EQ(1u, matches.count(id1));
184  }
185}
186
187TEST_F(EventFilterUnittest, TestGetMatcherCountForEvent) {
188  ASSERT_EQ(0, event_filter_.GetMatcherCountForEvent("event1"));
189  int id1 = event_filter_.AddEventMatcher("event1", AllURLs());
190  ASSERT_EQ(1, event_filter_.GetMatcherCountForEvent("event1"));
191  int id2 = event_filter_.AddEventMatcher("event1", AllURLs());
192  ASSERT_EQ(2, event_filter_.GetMatcherCountForEvent("event1"));
193  event_filter_.RemoveEventMatcher(id1);
194  ASSERT_EQ(1, event_filter_.GetMatcherCountForEvent("event1"));
195  event_filter_.RemoveEventMatcher(id2);
196  ASSERT_EQ(0, event_filter_.GetMatcherCountForEvent("event1"));
197}
198
199TEST_F(EventFilterUnittest, RemoveEventMatcherReturnsEventName) {
200  int id1 = event_filter_.AddEventMatcher("event1", AllURLs());
201  int id2 = event_filter_.AddEventMatcher("event1", AllURLs());
202  int id3 = event_filter_.AddEventMatcher("event2", AllURLs());
203
204  ASSERT_EQ("event1", event_filter_.RemoveEventMatcher(id1));
205  ASSERT_EQ("event1", event_filter_.RemoveEventMatcher(id2));
206  ASSERT_EQ("event2", event_filter_.RemoveEventMatcher(id3));
207}
208
209TEST_F(EventFilterUnittest, InvalidURLFilterCantBeAdded) {
210  scoped_ptr<base::ListValue> filter_list(new base::ListValue());
211  filter_list->Append(new base::ListValue());  // Should be a dict.
212  scoped_ptr<EventMatcher> matcher(MatcherFromURLFilterList(
213      filter_list.Pass()));
214  int id1 = event_filter_.AddEventMatcher("event1", matcher.Pass());
215  EXPECT_TRUE(event_filter_.IsURLMatcherEmpty());
216  ASSERT_EQ(-1, id1);
217}
218
219TEST_F(EventFilterUnittest, EmptyListOfURLFiltersMatchesAllURLs) {
220  scoped_ptr<base::ListValue> filter_list(new base::ListValue());
221  scoped_ptr<EventMatcher> matcher(MatcherFromURLFilterList(
222      scoped_ptr<ListValue>(new ListValue)));
223  int id = event_filter_.AddEventMatcher("event1", matcher.Pass());
224  std::set<int> matches = event_filter_.MatchEvent("event1",
225      google_event_, MSG_ROUTING_NONE);
226  ASSERT_EQ(1u, matches.size());
227  ASSERT_EQ(1u, matches.count(id));
228}
229
230TEST_F(EventFilterUnittest,
231    InternalURLMatcherShouldBeEmptyWhenThereAreNoEventMatchers) {
232  ASSERT_TRUE(event_filter_.IsURLMatcherEmpty());
233  int id = event_filter_.AddEventMatcher("event1",
234                                         HostSuffixMatcher("google.com"));
235  ASSERT_FALSE(event_filter_.IsURLMatcherEmpty());
236  event_filter_.RemoveEventMatcher(id);
237  ASSERT_TRUE(event_filter_.IsURLMatcherEmpty());
238}
239
240TEST_F(EventFilterUnittest, EmptyURLsShouldBeMatchedByEmptyURLFilters) {
241  int id = event_filter_.AddEventMatcher("event1", AllURLs());
242  std::set<int> matches = event_filter_.MatchEvent(
243      "event1", empty_url_event_, MSG_ROUTING_NONE);
244  ASSERT_EQ(1u, matches.size());
245  ASSERT_EQ(1u, matches.count(id));
246}
247
248TEST_F(EventFilterUnittest,
249    EmptyURLsShouldBeMatchedByEmptyURLFiltersWithAnEmptyItem) {
250  scoped_ptr<EventMatcher> matcher(MatcherFromURLFilterList(ValueAsList(
251      scoped_ptr<Value>(new DictionaryValue()))));
252  int id = event_filter_.AddEventMatcher("event1", matcher.Pass());
253  std::set<int> matches = event_filter_.MatchEvent(
254      "event1", empty_url_event_, MSG_ROUTING_NONE);
255  ASSERT_EQ(1u, matches.size());
256  ASSERT_EQ(1u, matches.count(id));
257}
258
259}  // namespace extensions
260