1 // Copyright 2014 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.
5 #include "chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate.h"
10 #include "base/bind.h"
11 #include "base/compiler_specific.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/values.h"
14 #include "chrome/common/safe_browsing/csd.pb.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 // A basic test harness that creates a delegate instance for which it stores all
18 // incidents. Tests can push data to the delegate and verify that the test
19 // instance was provided with the expected data.
20 class PreferenceValidationDelegateTest
: public testing::Test
{
22 typedef ScopedVector
<safe_browsing::ClientIncidentReport_IncidentData
>
25 PreferenceValidationDelegateTest()
26 : kPrefPath_("atomic.pref"),
27 null_value_(base::Value::CreateNullValue()) {}
29 virtual void SetUp() override
{
30 testing::Test::SetUp();
31 invalid_keys_
.push_back(std::string("one"));
32 invalid_keys_
.push_back(std::string("two"));
33 instance_
.reset(new safe_browsing::PreferenceValidationDelegate(
34 base::Bind(&PreferenceValidationDelegateTest::AddIncident
,
35 base::Unretained(this))));
39 scoped_ptr
<safe_browsing::ClientIncidentReport_IncidentData
> data
) {
40 incidents_
.push_back(data
.release());
43 static void ExpectValueStatesEquate(
44 PrefHashStoreTransaction::ValueState store_state
,
46 ClientIncidentReport_IncidentData_TrackedPreferenceIncident_ValueState
48 typedef safe_browsing::
49 ClientIncidentReport_IncidentData_TrackedPreferenceIncident TPIncident
;
50 switch (store_state
) {
51 case PrefHashStoreTransaction::CLEARED
:
52 EXPECT_EQ(TPIncident::CLEARED
, incident_state
);
54 case PrefHashStoreTransaction::CHANGED
:
55 EXPECT_EQ(TPIncident::CHANGED
, incident_state
);
57 case PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE
:
58 EXPECT_EQ(TPIncident::UNTRUSTED_UNKNOWN_VALUE
, incident_state
);
61 FAIL() << "unexpected store state";
66 static void ExpectKeysEquate(
67 const std::vector
<std::string
>& store_keys
,
68 const google::protobuf::RepeatedPtrField
<std::string
>& incident_keys
) {
69 ASSERT_EQ(store_keys
.size(), static_cast<size_t>(incident_keys
.size()));
70 for (int i
= 0; i
< incident_keys
.size(); ++i
) {
71 EXPECT_EQ(store_keys
[i
], incident_keys
.Get(i
));
75 const std::string kPrefPath_
;
76 IncidentVector incidents_
;
77 scoped_ptr
<base::Value
> null_value_
;
78 base::DictionaryValue dict_value_
;
79 std::vector
<std::string
> invalid_keys_
;
80 scoped_ptr
<TrackedPreferenceValidationDelegate
> instance_
;
83 // Tests that a NULL value results in an incident with no value.
84 TEST_F(PreferenceValidationDelegateTest
, NullValue
) {
85 instance_
->OnAtomicPreferenceValidation(kPrefPath_
,
87 PrefHashStoreTransaction::CLEARED
,
88 TrackedPreferenceHelper::DONT_RESET
);
89 safe_browsing::ClientIncidentReport_IncidentData
* incident
=
91 EXPECT_FALSE(incident
->tracked_preference().has_atomic_value());
94 ClientIncidentReport_IncidentData_TrackedPreferenceIncident::CLEARED
,
95 incident
->tracked_preference().value_state());
98 // Tests that all supported value types can be stringified into an incident. The
99 // parameters for the test are the type of value to test and the expected value
101 class PreferenceValidationDelegateValues
102 : public PreferenceValidationDelegateTest
,
103 public testing::WithParamInterface
<
104 std::tr1::tuple
<base::Value::Type
, const char*> > {
106 virtual void SetUp() override
{
107 PreferenceValidationDelegateTest::SetUp();
108 value_type_
= std::tr1::get
<0>(GetParam());
109 expected_value_
= std::tr1::get
<1>(GetParam());
112 static scoped_ptr
<base::Value
> MakeValue(base::Value::Type value_type
) {
114 switch (value_type
) {
115 case Value::TYPE_NULL
:
116 return make_scoped_ptr(Value::CreateNullValue());
117 case Value::TYPE_BOOLEAN
:
118 return scoped_ptr
<Value
>(new base::FundamentalValue(false));
119 case Value::TYPE_INTEGER
:
120 return scoped_ptr
<Value
>(new base::FundamentalValue(47));
121 case Value::TYPE_DOUBLE
:
122 return scoped_ptr
<Value
>(new base::FundamentalValue(0.47));
123 case Value::TYPE_STRING
:
124 return scoped_ptr
<Value
>(new base::StringValue("i have a spleen"));
125 case Value::TYPE_DICTIONARY
: {
126 scoped_ptr
<base::DictionaryValue
> value(new base::DictionaryValue());
127 value
->SetInteger("twenty-two", 22);
128 value
->SetInteger("forty-seven", 47);
131 case Value::TYPE_LIST
: {
132 scoped_ptr
<base::ListValue
> value(new base::ListValue());
133 value
->AppendInteger(22);
134 value
->AppendInteger(47);
138 ADD_FAILURE() << "unsupported value type " << value_type
;
140 return scoped_ptr
<Value
>();
143 base::Value::Type value_type_
;
144 const char* expected_value_
;
147 TEST_P(PreferenceValidationDelegateValues
, Value
) {
148 instance_
->OnAtomicPreferenceValidation(kPrefPath_
,
149 MakeValue(value_type_
).get(),
150 PrefHashStoreTransaction::CLEARED
,
151 TrackedPreferenceHelper::DONT_RESET
);
152 ASSERT_EQ(1U, incidents_
.size());
153 safe_browsing::ClientIncidentReport_IncidentData
* incident
=
155 EXPECT_EQ(std::string(expected_value_
),
156 incident
->tracked_preference().atomic_value());
159 INSTANTIATE_TEST_CASE_P(
161 PreferenceValidationDelegateValues
,
162 // On Android, make_tuple(..., "null") doesn't compile due to the error:
163 // testing/gtest/include/gtest/internal/gtest-tuple.h:246:48:
164 // error: array used as initializer
166 std::tr1::make_tuple(base::Value::TYPE_NULL
,
167 const_cast<char*>("null")),
168 std::tr1::make_tuple(base::Value::TYPE_BOOLEAN
,
169 const_cast<char*>("false")),
170 std::tr1::make_tuple(base::Value::TYPE_INTEGER
,
171 const_cast<char*>("47")),
172 std::tr1::make_tuple(base::Value::TYPE_DOUBLE
,
173 const_cast<char*>("0.47")),
174 std::tr1::make_tuple(base::Value::TYPE_STRING
,
175 const_cast<char*>("i have a spleen")),
176 std::tr1::make_tuple(base::Value::TYPE_DICTIONARY
,
177 const_cast<char*>("{\"forty-seven\":47,\"twenty-two\":22}")),
178 std::tr1::make_tuple(base::Value::TYPE_LIST
,
179 const_cast<char*>("[22,47]"))));
181 // Tests that no incidents are reported for relevant combinations of ValueState.
182 class PreferenceValidationDelegateNoIncident
183 : public PreferenceValidationDelegateTest
,
184 public testing::WithParamInterface
<PrefHashStoreTransaction::ValueState
> {
186 virtual void SetUp() override
{
187 PreferenceValidationDelegateTest::SetUp();
188 value_state_
= GetParam();
191 PrefHashStoreTransaction::ValueState value_state_
;
194 TEST_P(PreferenceValidationDelegateNoIncident
, Atomic
) {
195 instance_
->OnAtomicPreferenceValidation(kPrefPath_
,
198 TrackedPreferenceHelper::DONT_RESET
);
199 EXPECT_EQ(0U, incidents_
.size());
202 TEST_P(PreferenceValidationDelegateNoIncident
, Split
) {
203 instance_
->OnSplitPreferenceValidation(kPrefPath_
,
207 TrackedPreferenceHelper::DONT_RESET
);
208 EXPECT_EQ(0U, incidents_
.size());
211 INSTANTIATE_TEST_CASE_P(
213 PreferenceValidationDelegateNoIncident
,
214 testing::Values(PrefHashStoreTransaction::UNCHANGED
,
215 PrefHashStoreTransaction::SECURE_LEGACY
,
216 PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE
));
218 // Tests that incidents are reported for relevant combinations of ValueState and
220 class PreferenceValidationDelegateWithIncident
221 : public PreferenceValidationDelegateTest
,
222 public testing::WithParamInterface
<
223 std::tr1::tuple
<PrefHashStoreTransaction::ValueState
,
224 TrackedPreferenceHelper::ResetAction
> > {
226 virtual void SetUp() override
{
227 PreferenceValidationDelegateTest::SetUp();
228 value_state_
= std::tr1::get
<0>(GetParam());
229 reset_action_
= std::tr1::get
<1>(GetParam());
232 PrefHashStoreTransaction::ValueState value_state_
;
233 TrackedPreferenceHelper::ResetAction reset_action_
;
236 TEST_P(PreferenceValidationDelegateWithIncident
, Atomic
) {
237 instance_
->OnAtomicPreferenceValidation(
238 kPrefPath_
, null_value_
.get(), value_state_
, reset_action_
);
239 ASSERT_EQ(1U, incidents_
.size());
240 safe_browsing::ClientIncidentReport_IncidentData
* incident
=
242 EXPECT_TRUE(incident
->has_tracked_preference());
243 const safe_browsing::
244 ClientIncidentReport_IncidentData_TrackedPreferenceIncident
& tp_incident
=
245 incident
->tracked_preference();
246 EXPECT_EQ(kPrefPath_
, tp_incident
.path());
247 EXPECT_EQ(0, tp_incident
.split_key_size());
248 EXPECT_TRUE(tp_incident
.has_atomic_value());
249 EXPECT_EQ(std::string("null"), tp_incident
.atomic_value());
250 EXPECT_TRUE(tp_incident
.has_value_state());
251 ExpectValueStatesEquate(value_state_
, tp_incident
.value_state());
254 TEST_P(PreferenceValidationDelegateWithIncident
, Split
) {
255 instance_
->OnSplitPreferenceValidation(
256 kPrefPath_
, &dict_value_
, invalid_keys_
, value_state_
, reset_action_
);
257 ASSERT_EQ(1U, incidents_
.size());
258 safe_browsing::ClientIncidentReport_IncidentData
* incident
=
260 EXPECT_TRUE(incident
->has_tracked_preference());
261 const safe_browsing::
262 ClientIncidentReport_IncidentData_TrackedPreferenceIncident
& tp_incident
=
263 incident
->tracked_preference();
264 EXPECT_EQ(kPrefPath_
, tp_incident
.path());
265 EXPECT_FALSE(tp_incident
.has_atomic_value());
266 ExpectKeysEquate(invalid_keys_
, tp_incident
.split_key());
267 EXPECT_TRUE(tp_incident
.has_value_state());
268 ExpectValueStatesEquate(value_state_
, tp_incident
.value_state());
271 INSTANTIATE_TEST_CASE_P(
273 PreferenceValidationDelegateWithIncident
,
275 testing::Values(PrefHashStoreTransaction::CLEARED
,
276 PrefHashStoreTransaction::CHANGED
,
277 PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE
),
278 testing::Values(TrackedPreferenceHelper::WANTED_RESET
,
279 TrackedPreferenceHelper::DO_RESET
)));