12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/declarative/declarative_rule.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/test/values_test_util.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
11d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)#include "components/url_matcher/url_matcher_constants.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension_builder.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::test::ParseJson;
17d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)using url_matcher::URLMatcher;
18d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)using url_matcher::URLMatcherConditionFactory;
19d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)using url_matcher::URLMatcherConditionSet;
20d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
21d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)namespace extensions {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T>
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)linked_ptr<T> ScopedToLinkedPtr(scoped_ptr<T> ptr) {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return linked_ptr<T>(ptr.release());
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)scoped_ptr<DictionaryValue> SimpleManifest() {
318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return DictionaryBuilder()
328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      .Set("name", "extension")
338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      .Set("manifest_version", 2)
348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      .Set("version", "1.0")
358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      .Build();
368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct RecordingCondition {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef int MatchData;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLMatcherConditionFactory* factory;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> value;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void GetURLMatcherConditionSets(
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      URLMatcherConditionSet::Vector* condition_sets) const {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // No condition sets.
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static scoped_ptr<RecordingCondition> Create(
528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      const Extension* extension,
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      URLMatcherConditionFactory* url_matcher_condition_factory,
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::Value& condition,
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string* error) {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue* dict = NULL;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (condition.GetAsDictionary(&dict) && dict->HasKey("bad_key")) {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *error = "Found error key";
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return scoped_ptr<RecordingCondition>();
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<RecordingCondition> result(new RecordingCondition());
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result->factory = url_matcher_condition_factory;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result->value.reset(condition.DeepCopy());
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return result.Pass();
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef DeclarativeConditionSet<RecordingCondition> RecordingConditionSet;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(DeclarativeConditionTest, ErrorConditionSet) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLMatcher matcher;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RecordingConditionSet::AnyVector conditions;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  conditions.push_back(ScopedToLinkedPtr(ParseJson("{\"key\": 1}")));
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  conditions.push_back(ScopedToLinkedPtr(ParseJson("{\"bad_key\": 2}")));
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error;
778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  scoped_ptr<RecordingConditionSet> result = RecordingConditionSet::Create(
788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      NULL, matcher.condition_factory(), conditions, &error);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("Found error key", error);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(result);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(DeclarativeConditionTest, CreateConditionSet) {
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLMatcher matcher;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RecordingConditionSet::AnyVector conditions;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  conditions.push_back(ScopedToLinkedPtr(ParseJson("{\"key\": 1}")));
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  conditions.push_back(ScopedToLinkedPtr(ParseJson("[\"val1\", 2]")));
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test insertion
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error;
918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  scoped_ptr<RecordingConditionSet> result = RecordingConditionSet::Create(
928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      NULL, matcher.condition_factory(), conditions, &error);
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("", error);
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(result);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2u, result->conditions().size());
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(matcher.condition_factory(), result->conditions()[0]->factory);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(ParseJson("{\"key\": 1}")->Equals(
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result->conditions()[0]->value.get()));
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct FulfillableCondition {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct MatchData {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int value;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::set<URLMatcherConditionSet::ID>& url_matches;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<URLMatcherConditionSet> condition_set;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int condition_set_id;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int max_value;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLMatcherConditionSet::ID url_matcher_condition_set_id() const {
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return condition_set_id;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<URLMatcherConditionSet> url_matcher_condition_set() const {
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return condition_set;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void GetURLMatcherConditionSets(
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      URLMatcherConditionSet::Vector* condition_sets) const {
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (condition_set.get())
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      condition_sets->push_back(condition_set);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsFulfilled(const MatchData& match_data) const {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (condition_set_id != -1 &&
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        !ContainsKey(match_data.url_matches, condition_set_id))
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return match_data.value <= max_value;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static scoped_ptr<FulfillableCondition> Create(
1348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      const Extension* extension,
1358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      URLMatcherConditionFactory* url_matcher_condition_factory,
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::Value& condition,
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string* error) {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<FulfillableCondition> result(new FulfillableCondition());
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue* dict;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!condition.GetAsDictionary(&dict)) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *error = "Expected dict";
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return result.Pass();
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!dict->GetInteger("url_id", &result->condition_set_id))
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result->condition_set_id = -1;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!dict->GetInteger("max", &result->max_value))
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *error = "Expected integer at ['max']";
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (result->condition_set_id != -1) {
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result->condition_set = new URLMatcherConditionSet(
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          result->condition_set_id,
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          URLMatcherConditionSet::Conditions());
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return result.Pass();
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(DeclarativeConditionTest, FulfillConditionSet) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef DeclarativeConditionSet<FulfillableCondition> FulfillableConditionSet;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FulfillableConditionSet::AnyVector conditions;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  conditions.push_back(ScopedToLinkedPtr(ParseJson(
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "{\"url_id\": 1, \"max\": 3}")));
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  conditions.push_back(ScopedToLinkedPtr(ParseJson(
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "{\"url_id\": 2, \"max\": 5}")));
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  conditions.push_back(ScopedToLinkedPtr(ParseJson(
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "{\"url_id\": 3, \"max\": 1}")));
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  conditions.push_back(ScopedToLinkedPtr(ParseJson(
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "{\"max\": -5}")));  // No url.
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test insertion
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<FulfillableConditionSet> result =
1728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      FulfillableConditionSet::Create(NULL, NULL, conditions, &error);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ("", error);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(result);
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(4u, result->conditions().size());
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::set<URLMatcherConditionSet::ID> url_matches;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FulfillableCondition::MatchData match_data = { 0, url_matches };
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(result->IsFulfilled(1, match_data))
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "Testing an ID that's not in url_matches forwards to the Condition, "
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "which doesn't match.";
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(result->IsFulfilled(-1, match_data))
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "Testing the 'no ID' value tries to match the 4th condition, but "
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "its max is too low.";
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  match_data.value = -5;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(result->IsFulfilled(-1, match_data))
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "Testing the 'no ID' value tries to match the 4th condition, and "
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "this value is low enough.";
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_matches.insert(1);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  match_data.value = 3;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(result->IsFulfilled(1, match_data))
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "Tests a condition with a url matcher, for a matching value.";
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  match_data.value = 4;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(result->IsFulfilled(1, match_data))
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "Tests a condition with a url matcher, for a non-matching value "
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "that would match a different condition.";
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_matches.insert(2);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(result->IsFulfilled(2, match_data))
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "Tests with 2 elements in the match set.";
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check the condition sets:
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLMatcherConditionSet::Vector condition_sets;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result->GetURLMatcherConditionSets(&condition_sets);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(3U, condition_sets.size());
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, condition_sets[0]->id());
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2, condition_sets[1]->id());
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(3, condition_sets[2]->id());
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DeclarativeAction
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class SummingAction : public base::RefCounted<SummingAction> {
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef int ApplyInfo;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SummingAction(int increment, int min_priority)
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : increment_(increment), min_priority_(min_priority) {}
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  static scoped_refptr<const SummingAction> Create(const Extension* extension,
2218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                   const base::Value& action,
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                   std::string* error,
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                   bool* bad_message) {
22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int increment = 0;
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int min_priority = 0;
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue* dict = NULL;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(action.GetAsDictionary(&dict));
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (dict->HasKey("error")) {
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_TRUE(dict->GetString("error", error));
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return scoped_refptr<const SummingAction>(NULL);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (dict->HasKey("bad")) {
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *bad_message = true;
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return scoped_refptr<const SummingAction>(NULL);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    EXPECT_TRUE(dict->GetInteger("value", &increment));
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    dict->GetInteger("priority", &min_priority);
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return scoped_refptr<const SummingAction>(
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        new SummingAction(increment, min_priority));
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Apply(const std::string& extension_id,
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             const base::Time& install_time,
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             int* sum) const {
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *sum += increment_;
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int increment() const { return increment_; }
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int minimum_priority() const {
25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return min_priority_;
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  friend class base::RefCounted<SummingAction>;
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~SummingAction() {}
25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int increment_;
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int min_priority_;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef DeclarativeActionSet<SummingAction> SummingActionSet;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(DeclarativeActionTest, ErrorActionSet) {
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SummingActionSet::AnyVector actions;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  actions.push_back(ScopedToLinkedPtr(ParseJson("{\"value\": 1}")));
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  actions.push_back(ScopedToLinkedPtr(ParseJson("{\"error\": \"the error\"}")));
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error;
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool bad = false;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SummingActionSet> result =
2718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      SummingActionSet::Create(NULL, actions, &error, &bad);
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("the error", error);
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(bad);
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(result);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  actions.clear();
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  actions.push_back(ScopedToLinkedPtr(ParseJson("{\"value\": 1}")));
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  actions.push_back(ScopedToLinkedPtr(ParseJson("{\"bad\": 3}")));
2798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  result = SummingActionSet::Create(NULL, actions, &error, &bad);
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("", error);
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(bad);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(result);
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(DeclarativeActionTest, ApplyActionSet) {
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SummingActionSet::AnyVector actions;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  actions.push_back(ScopedToLinkedPtr(ParseJson(
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "{\"value\": 1,"
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      " \"priority\": 5}")));
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  actions.push_back(ScopedToLinkedPtr(ParseJson("{\"value\": 2}")));
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test insertion
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error;
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool bad = false;
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SummingActionSet> result =
2968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      SummingActionSet::Create(NULL, actions, &error, &bad);
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("", error);
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(bad);
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(result);
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2u, result->actions().size());
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int sum = 0;
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result->Apply("ext_id", base::Time(), &sum);
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(3, sum);
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(5, result->GetMinimumPriority());
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(DeclarativeRuleTest, Create) {
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef DeclarativeRule<FulfillableCondition, SummingAction> Rule;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  linked_ptr<Rule::JsonRule> json_rule(new Rule::JsonRule);
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(Rule::JsonRule::Populate(
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *ParseJson("{ \n"
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  \"id\": \"rule1\", \n"
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  \"conditions\": [ \n"
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "    {\"url_id\": 1, \"max\": 3}, \n"
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "    {\"url_id\": 2, \"max\": 5}, \n"
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  ], \n"
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  \"actions\": [ \n"
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "    { \n"
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "      \"value\": 2 \n"
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "    } \n"
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  ], \n"
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  \"priority\": 200 \n"
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "}"),
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      json_rule.get()));
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kExtensionId[] = "ext1";
3288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  scoped_refptr<Extension> extension = ExtensionBuilder()
3298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                           .SetManifest(SimpleManifest())
3308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                           .SetID(kExtensionId)
3318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                           .Build();
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Time install_time = base::Time::Now();
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLMatcher matcher;
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error;
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<Rule> rule(Rule::Create(matcher.condition_factory(),
3388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                     extension.get(),
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     install_time,
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     json_rule,
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     Rule::ConsistencyChecker(),
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     &error));
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("", error);
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(rule.get());
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kExtensionId, rule->id().first);
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("rule1", rule->id().second);
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(200, rule->priority());
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Rule::ConditionSet& condition_set = rule->conditions();
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Rule::ConditionSet::Conditions& conditions =
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      condition_set.conditions();
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(2u, conditions.size());
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(3, conditions[0]->max_value);
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(5, conditions[1]->max_value);
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Rule::ActionSet& action_set = rule->actions();
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Rule::ActionSet::Actions& actions = action_set.actions();
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1u, actions.size());
36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(2, actions[0]->increment());
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int sum = 0;
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rule->Apply(&sum);
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2, sum);
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AtLeastOneCondition(
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DeclarativeConditionSet<FulfillableCondition>* conditions,
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DeclarativeActionSet<SummingAction>* actions,
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string* error) {
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (conditions->conditions().empty()) {
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *error = "No conditions";
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(DeclarativeRuleTest, CheckConsistency) {
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef DeclarativeRule<FulfillableCondition, SummingAction> Rule;
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLMatcher matcher;
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error;
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  linked_ptr<Rule::JsonRule> json_rule(new Rule::JsonRule);
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kExtensionId[] = "ext1";
3858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  scoped_refptr<Extension> extension = ExtensionBuilder()
3868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                           .SetManifest(SimpleManifest())
3878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                           .SetID(kExtensionId)
3888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                           .Build();
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(Rule::JsonRule::Populate(
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *ParseJson("{ \n"
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  \"id\": \"rule1\", \n"
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  \"conditions\": [ \n"
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "    {\"url_id\": 1, \"max\": 3}, \n"
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "    {\"url_id\": 2, \"max\": 5}, \n"
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  ], \n"
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  \"actions\": [ \n"
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "    { \n"
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "      \"value\": 2 \n"
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "    } \n"
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  ], \n"
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  \"priority\": 200 \n"
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "}"),
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      json_rule.get()));
4058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  scoped_ptr<Rule> rule(Rule::Create(matcher.condition_factory(),
4068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                     extension.get(),
4078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                     base::Time(),
4088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                     json_rule,
4098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                     base::Bind(AtLeastOneCondition),
4108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                     &error));
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(rule);
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("", error);
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(Rule::JsonRule::Populate(
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *ParseJson("{ \n"
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  \"id\": \"rule1\", \n"
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  \"conditions\": [ \n"
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  ], \n"
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  \"actions\": [ \n"
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "    { \n"
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "      \"value\": 2 \n"
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "    } \n"
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  ], \n"
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "  \"priority\": 200 \n"
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "}"),
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      json_rule.get()));
4278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  rule = Rule::Create(matcher.condition_factory(),
4288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                      extension.get(),
4298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                      base::Time(),
4308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                      json_rule,
4318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                      base::Bind(AtLeastOneCondition),
4328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                      &error);
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(rule);
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("No conditions", error);
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
438