Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: chrome/browser/extensions/api/declarative/declarative_rule_unittest.cc

Issue 11572061: Create DeclarativeConditionSet, DeclarativeActionSet, and DeclarativeRule templates (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix Dominic's comments Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 "chrome/browser/extensions/api/declarative/declarative_rule.h"
6
7 #include "base/message_loop.h"
8 #include "base/test/values_test_util.h"
9 #include "base/values.h"
10 #include "chrome/common/extensions/matcher/url_matcher_constants.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace extensions {
15
16 using json_schema_compiler::any::Any;
17 using base::test::ParseJson;
18
19 struct RecordingCondition {
20 typedef int MatchData;
21
22 URLMatcherConditionFactory* factory;
23 scoped_ptr<base::Value> value;
24
25 void GetURLMatcherConditionSets(
26 URLMatcherConditionSet::Vector* condition_sets) const {
27 // No condition sets.
28 }
29
30 bool has_url_matcher_condition_set() const {
31 return false;
32 }
33
34 static scoped_ptr<RecordingCondition> Create(
35 URLMatcherConditionFactory* url_matcher_condition_factory,
36 const base::Value& condition,
37 std::string* error) {
38 const base::DictionaryValue* dict = NULL;
39 if (condition.GetAsDictionary(&dict) &&
40 dict->HasKey("bad_key")) {
not at google - send to devlin 2013/01/16 23:15:20 can fit on 1 line?
41 *error = "Found error key";
42 return scoped_ptr<RecordingCondition>();
43 }
44
45 scoped_ptr<RecordingCondition> result(new RecordingCondition());
46 result->factory = url_matcher_condition_factory;
47 result->value.reset(condition.DeepCopy());
48 return result.Pass();
49 }
50 };
51 typedef DeclarativeConditionSet<RecordingCondition> RecordingConditionSet;
52
53 TEST(DeclarativeConditionTest, ErrorConditionSet) {
54 URLMatcher matcher;
55 RecordingConditionSet::AnyVector conditions;
56 conditions.push_back(make_linked_ptr(new Any(ParseJson("{\"key\": 1}"))));
57 conditions.push_back(make_linked_ptr(new Any(ParseJson("{\"bad_key\": 2}"))));
58
59 std::string error;
60 scoped_ptr<RecordingConditionSet> result =
61 RecordingConditionSet::Create(matcher.condition_factory(),
62 conditions, &error);
63 EXPECT_EQ("Found error key", error);
64 ASSERT_FALSE(result);
65 }
66
67 TEST(DeclarativeConditionTest, CreateConditionSet) {
68 URLMatcher matcher;
69 RecordingConditionSet::AnyVector conditions;
70 conditions.push_back(make_linked_ptr(new Any(ParseJson("{\"key\": 1}"))));
71 conditions.push_back(make_linked_ptr(new Any(ParseJson("[\"val1\", 2]"))));
72
73 // Test insertion
74 std::string error;
75 scoped_ptr<RecordingConditionSet> result =
76 RecordingConditionSet::Create(matcher.condition_factory(),
77 conditions, &error);
78 EXPECT_EQ("", error);
79 ASSERT_TRUE(result);
80 EXPECT_EQ(2u, result->conditions().size());
81
82 EXPECT_EQ(matcher.condition_factory(), result->conditions()[0]->factory);
83 EXPECT_TRUE(ParseJson("{\"key\": 1}")->Equals(
84 result->conditions()[0]->value.get()));
85 }
86
87 struct FulfillableCondition {
88 typedef int MatchData;
89
90 scoped_refptr<URLMatcherConditionSet> condition_set;
91 int condition_set_id;
92 int max_value;
93
94 URLMatcherConditionSet::ID url_matcher_condition_set_id() const {
95 return condition_set_id;
96 }
97
98 bool has_url_matcher_condition_set() const {
99 return true;
100 }
101
102 scoped_refptr<URLMatcherConditionSet> url_matcher_condition_set() const {
103 return condition_set;
104 }
105
106 void GetURLMatcherConditionSets(
107 URLMatcherConditionSet::Vector* condition_sets) const {
108 if (condition_set)
109 condition_sets->push_back(condition_set);
110 }
111
112 bool IsFulfilled(const std::set<URLMatcherConditionSet::ID>& url_matches,
113 int match_data) const {
114 if (condition_set_id != -1 && !ContainsKey(url_matches, condition_set_id))
115 return false;
116 return match_data <= max_value;
117 }
118
119 static scoped_ptr<FulfillableCondition> Create(
120 URLMatcherConditionFactory* url_matcher_condition_factory,
121 const base::Value& condition,
122 std::string* error) {
123 scoped_ptr<FulfillableCondition> result(new FulfillableCondition());
124 const base::DictionaryValue* dict;
125 if (!condition.GetAsDictionary(&dict)) {
126 *error = "Expected dict";
127 return result.Pass();
128 }
129 if (!dict->GetInteger("url_id", &result->condition_set_id))
130 result->condition_set_id = -1;
131 if (!dict->GetInteger("max", &result->max_value))
132 *error = "Expected integer at ['max']";
133 if (result->condition_set_id != -1) {
134 result->condition_set = new URLMatcherConditionSet(
135 result->condition_set_id,
136 URLMatcherConditionSet::Conditions());
137 }
138 return result.Pass();
139 }
140 };
141
142 TEST(DeclarativeConditionTest, FulfillConditionSet) {
143 typedef DeclarativeConditionSet<FulfillableCondition> FulfillableConditionSet;
144 FulfillableConditionSet::AnyVector conditions;
145 conditions.push_back(make_linked_ptr(new Any(ParseJson(
146 "{\"url_id\": 1, \"max\": 3}"))));
147 conditions.push_back(make_linked_ptr(new Any(ParseJson(
148 "{\"url_id\": 2, \"max\": 5}"))));
149 conditions.push_back(make_linked_ptr(new Any(ParseJson(
150 "{\"url_id\": 3, \"max\": 1}"))));
151 conditions.push_back(make_linked_ptr(new Any(ParseJson(
152 "{\"max\": -5}")))); // No url.
153
154 // Test insertion
155 std::string error;
156 scoped_ptr<FulfillableConditionSet> result =
157 FulfillableConditionSet::Create(NULL, conditions, &error);
158 ASSERT_EQ("", error);
159 ASSERT_TRUE(result);
160 EXPECT_EQ(4u, result->conditions().size());
161
162 std::set<URLMatcherConditionSet::ID> url_matches;
163 EXPECT_FALSE(result->IsFulfilled(1, url_matches, 0))
164 << "Testing an ID that's not in url_matches forwards to the Condition, "
165 << "which doesn't match.";
166 EXPECT_FALSE(result->IsFulfilled(-1, url_matches, 0))
167 << "Testing the 'no ID' value tries to match the 4th condition, but "
168 << "its max is too low.";
169 EXPECT_TRUE(result->IsFulfilled(-1, url_matches, -5))
170 << "Testing the 'no ID' value tries to match the 4th condition, and "
171 << "this value is low enough.";
172
173 url_matches.insert(1);
174 EXPECT_TRUE(result->IsFulfilled(1, url_matches, 3))
175 << "Tests a condition with a url matcher, for a matching value.";
176 EXPECT_FALSE(result->IsFulfilled(1, url_matches, 4))
177 << "Tests a condition with a url matcher, for a non-matching value "
178 << "that would match a different condition.";
179 url_matches.insert(2);
180 EXPECT_TRUE(result->IsFulfilled(2, url_matches, 4))
181 << "Tests with 2 elements in the match set.";
182
183 // Check the condition sets:
184 URLMatcherConditionSet::Vector condition_sets;
185 result->GetURLMatcherConditionSets(&condition_sets);
186 ASSERT_EQ(3U, condition_sets.size());
187 EXPECT_EQ(1, condition_sets[0]->id());
188 EXPECT_EQ(2, condition_sets[1]->id());
189 EXPECT_EQ(3, condition_sets[2]->id());
190 }
191
192 // DeclarativeAction
193
194 struct SummingAction {
195 typedef int ApplyInfo;
196
197 int increment;
198 int min_priority;
199
200 static scoped_ptr<SummingAction> Create(const base::Value& action,
201 std::string* error,
202 bool* bad_message) {
203 scoped_ptr<SummingAction> result(new SummingAction());
204 const base::DictionaryValue* dict = NULL;
205 EXPECT_TRUE(action.GetAsDictionary(&dict));
206 if (dict->HasKey("error")) {
207 EXPECT_TRUE(dict->GetString("error", error));
208 return result.Pass();
209 }
210 if (dict->HasKey("bad")) {
211 *bad_message = true;
212 return result.Pass();
213 }
214
215 EXPECT_TRUE(dict->GetInteger("value", &result->increment));
216 dict->GetInteger("priority", &result->min_priority);
217 return result.Pass();
218 }
219
220 void Apply(const std::string& extension_id,
221 const base::Time& install_time,
222 int* sum) const {
223 *sum += increment;
224 }
225
226 int GetMinimumPriority() const {
227 return min_priority;
228 }
229 };
230 typedef DeclarativeActionSet<SummingAction> SummingActionSet;
231
232 TEST(DeclarativeActionTest, ErrorActionSet) {
233 SummingActionSet::AnyVector actions;
234 actions.push_back(make_linked_ptr(new Any(ParseJson("{\"value\": 1}"))));
235 actions.push_back(make_linked_ptr(new Any(ParseJson(
236 "{\"error\": \"the error\"}"))));
237
238 std::string error;
239 bool bad = false;
240 scoped_ptr<SummingActionSet> result =
241 SummingActionSet::Create(actions, &error, &bad);
242 EXPECT_EQ("the error", error);
243 EXPECT_FALSE(bad);
244 EXPECT_FALSE(result);
245
246 actions.clear();
247 actions.push_back(make_linked_ptr(new Any(ParseJson("{\"value\": 1}"))));
248 actions.push_back(make_linked_ptr(new Any(ParseJson("{\"bad\": 3}"))));
249 result = SummingActionSet::Create(actions, &error, &bad);
250 EXPECT_EQ("", error);
251 EXPECT_TRUE(bad);
252 EXPECT_FALSE(result);
253 }
254
255 TEST(DeclarativeActionTest, ApplyActionSet) {
256 SummingActionSet::AnyVector actions;
257 actions.push_back(make_linked_ptr(new Any(ParseJson(
258 "{\"value\": 1,"
259 " \"priority\": 5}"))));
260 actions.push_back(make_linked_ptr(new Any(ParseJson("{\"value\": 2}"))));
261
262 // Test insertion
263 std::string error;
264 bool bad = false;
265 scoped_ptr<SummingActionSet> result =
266 SummingActionSet::Create(actions, &error, &bad);
267 EXPECT_EQ("", error);
268 EXPECT_FALSE(bad);
269 ASSERT_TRUE(result);
270 EXPECT_EQ(2u, result->actions().size());
271
272 int sum = 0;
273 result->Apply("ext_id", base::Time(), &sum);
274 EXPECT_EQ(3, sum);
275 EXPECT_EQ(5, result->GetMinimumPriority());
276 }
277
278 TEST(DeclarativeRuleTest, Create) {
279 typedef DeclarativeRule<FulfillableCondition, SummingAction> Rule;
280 linked_ptr<Rule::JsonRule> json_rule(new Rule::JsonRule);
281 ASSERT_TRUE(Rule::JsonRule::Populate(
282 *ParseJson("{ \n"
283 " \"id\": \"rule1\", \n"
284 " \"conditions\": [ \n"
285 " {\"url_id\": 1, \"max\": 3}, \n"
286 " {\"url_id\": 2, \"max\": 5}, \n"
287 " ], \n"
288 " \"actions\": [ \n"
289 " { \n"
290 " \"value\": 2 \n"
291 " } \n"
292 " ], \n"
293 " \"priority\": 200 \n"
294 "}"),
295 json_rule.get()));
296
297 const char kExtensionId[] = "ext1";
298
299 base::Time install_time = base::Time::Now();
300
301 URLMatcher matcher;
302 std::string error;
303 scoped_ptr<Rule> rule(Rule::Create(matcher.condition_factory(), kExtensionId,
304 install_time, json_rule, NULL, &error));
305 EXPECT_EQ("", error);
306 ASSERT_TRUE(rule.get());
307
308 EXPECT_EQ(kExtensionId, rule->id().first);
309 EXPECT_EQ("rule1", rule->id().second);
310
311 EXPECT_EQ(200, rule->priority());
312
313 const Rule::ConditionSet& condition_set = rule->conditions();
314 const Rule::ConditionSet::Conditions& conditions =
315 condition_set.conditions();
316 ASSERT_EQ(2u, conditions.size());
317 EXPECT_EQ(3, conditions[0]->max_value);
318 EXPECT_EQ(5, conditions[1]->max_value);
319
320 const Rule::ActionSet& action_set = rule->actions();
321 const Rule::ActionSet::Actions& actions = action_set.actions();
322 ASSERT_EQ(1u, actions.size());
323 EXPECT_EQ(2, actions[0]->increment);
324
325 int sum = 0;
326 rule->Apply(&sum);
327 EXPECT_EQ(2, sum);
328 }
329
330 bool AtLeastOneCondition(
331 const DeclarativeConditionSet<FulfillableCondition>* conditions,
332 const DeclarativeActionSet<SummingAction>* actions,
333 std::string* error) {
334 if (conditions->conditions().empty()) {
335 *error = "No conditions";
336 return false;
337 }
338 return true;
339 }
340
341 TEST(DeclarativeRuleTest, CheckConsistency) {
342 typedef DeclarativeRule<FulfillableCondition, SummingAction> Rule;
343 URLMatcher matcher;
344 std::string error;
345 linked_ptr<Rule::JsonRule> json_rule(new Rule::JsonRule);
346 const char kExtensionId[] = "ext1";
347
348 ASSERT_TRUE(Rule::JsonRule::Populate(
349 *ParseJson("{ \n"
350 " \"id\": \"rule1\", \n"
351 " \"conditions\": [ \n"
352 " {\"url_id\": 1, \"max\": 3}, \n"
353 " {\"url_id\": 2, \"max\": 5}, \n"
354 " ], \n"
355 " \"actions\": [ \n"
356 " { \n"
357 " \"value\": 2 \n"
358 " } \n"
359 " ], \n"
360 " \"priority\": 200 \n"
361 "}"),
362 json_rule.get()));
363 scoped_ptr<Rule> rule(
364 Rule::Create(matcher.condition_factory(), kExtensionId, base::Time(),
365 json_rule, &AtLeastOneCondition, &error));
366 EXPECT_TRUE(rule);
367 EXPECT_EQ("", error);
368
369 ASSERT_TRUE(Rule::JsonRule::Populate(
370 *ParseJson("{ \n"
371 " \"id\": \"rule1\", \n"
372 " \"conditions\": [ \n"
373 " ], \n"
374 " \"actions\": [ \n"
375 " { \n"
376 " \"value\": 2 \n"
377 " } \n"
378 " ], \n"
379 " \"priority\": 200 \n"
380 "}"),
381 json_rule.get()));
382 rule = Rule::Create(matcher.condition_factory(), kExtensionId, base::Time(),
383 json_rule, &AtLeastOneCondition, &error);
384 EXPECT_FALSE(rule);
385 EXPECT_EQ("No conditions", error);
386 }
387
388 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698