OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/network/onc/onc_validator.h" | 5 #include "chromeos/network/onc/onc_validator.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
| 10 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
11 #include "base/values.h" | 12 #include "base/values.h" |
12 #include "chromeos/network/onc/onc_constants.h" | 13 #include "chromeos/network/onc/onc_constants.h" |
13 #include "chromeos/network/onc/onc_signature.h" | 14 #include "chromeos/network/onc/onc_signature.h" |
14 #include "chromeos/network/onc/onc_test_utils.h" | 15 #include "chromeos/network/onc/onc_test_utils.h" |
15 #include "chromeos/network/onc/onc_utils.h" | 16 #include "chromeos/network/onc/onc_utils.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
17 | 18 |
18 namespace chromeos { | 19 namespace chromeos { |
19 namespace onc { | 20 namespace onc { |
| 21 |
| 22 class ONCValidatorTest : public ::testing::Test { |
| 23 public: |
| 24 // Validate |onc_object| with the given |signature|. The object is considered |
| 25 // to be managed if |managed_onc| is true. A strict validator is used if |
| 26 // |strict| is true. |onc_object| and the resulting repaired object of the |
| 27 // validation is stored, so that expectations can be checked afterwards using |
| 28 // one of the Expect* functions below. |
| 29 void Validate(bool strict, |
| 30 scoped_ptr<base::DictionaryValue> onc_object, |
| 31 const OncValueSignature* signature, |
| 32 bool managed_onc) { |
| 33 scoped_ptr<Validator> validator; |
| 34 if (strict) { |
| 35 // Create a strict validator that complains about every error. |
| 36 validator.reset(new Validator(true, true, true, managed_onc)); |
| 37 } else { |
| 38 // Create a liberal validator that ignores or repairs non-critical errors. |
| 39 validator.reset(new Validator(false, false, false, managed_onc)); |
| 40 } |
| 41 original_object_ = onc_object.Pass(); |
| 42 repaired_object_ = validator->ValidateAndRepairObject(signature, |
| 43 *original_object_, |
| 44 &validation_result_); |
| 45 } |
| 46 |
| 47 void ExpectValid() { |
| 48 EXPECT_EQ(Validator::VALID, validation_result_); |
| 49 EXPECT_TRUE(test_utils::Equals(original_object_.get(), |
| 50 repaired_object_.get())); |
| 51 } |
| 52 |
| 53 void ExpectRepairWithWarnings( |
| 54 const base::DictionaryValue& expected_repaired) { |
| 55 EXPECT_EQ(Validator::VALID_WITH_WARNINGS, validation_result_); |
| 56 EXPECT_TRUE(test_utils::Equals(&expected_repaired, repaired_object_.get())); |
| 57 } |
| 58 |
| 59 void ExpectInvalid() { |
| 60 EXPECT_EQ(Validator::INVALID, validation_result_); |
| 61 EXPECT_EQ(NULL, repaired_object_.get()); |
| 62 } |
| 63 |
| 64 private: |
| 65 Validator::Result validation_result_; |
| 66 scoped_ptr<const base::DictionaryValue> original_object_; |
| 67 scoped_ptr<const base::DictionaryValue> repaired_object_; |
| 68 }; |
| 69 |
20 namespace { | 70 namespace { |
21 | 71 |
22 // Create a strict validator that complains about every error. | 72 struct OncParams { |
23 scoped_ptr<Validator> CreateStrictValidator(bool managed_onc) { | 73 // |location_of_object| is a string to identify the object to be tested. It |
24 return make_scoped_ptr(new Validator(true, true, true, managed_onc)); | 74 // may be used as a filename or as a dictionary key. |
25 } | 75 OncParams(std::string location_of_object, |
26 | 76 const OncValueSignature* onc_signature, |
27 // Create a liberal validator that ignores or repairs non-critical errors. | 77 bool is_managed_onc) |
28 scoped_ptr<Validator> CreateLiberalValidator(bool managed_onc) { | 78 : location(location_of_object), |
29 return make_scoped_ptr(new Validator(false, false, false, managed_onc)); | 79 signature(onc_signature), |
30 } | 80 is_managed(is_managed_onc) { |
| 81 } |
| 82 |
| 83 std::string location; |
| 84 const OncValueSignature* signature; |
| 85 bool is_managed; |
| 86 }; |
| 87 |
| 88 ::std::ostream& operator<<(::std::ostream& os, const OncParams& onc) { |
| 89 return os << "(" << onc.location << ", " << onc.signature << ", " |
| 90 << (onc.is_managed ? "managed" : "unmanaged") << ")"; |
| 91 } |
| 92 |
31 } // namespace | 93 } // namespace |
32 | 94 |
33 TEST(ONCValidatorValidTest, EmptyUnencryptedConfiguration) { | 95 // Ensure that the constant |kEmptyUnencryptedConfiguration| describes a valid |
34 scoped_ptr<Validator> validator(CreateStrictValidator(true)); | 96 // ONC toplevel object. |
35 scoped_ptr<const base::DictionaryValue> original( | 97 TEST_F(ONCValidatorTest, EmptyUnencryptedConfiguration) { |
36 ReadDictionaryFromJson(kEmptyUnencryptedConfiguration)); | 98 Validate(true, ReadDictionaryFromJson(kEmptyUnencryptedConfiguration), |
37 | 99 &kToplevelConfigurationSignature, false); |
38 Validator::Result result; | 100 ExpectValid(); |
39 scoped_ptr<const base::DictionaryValue> repaired( | 101 } |
40 validator->ValidateAndRepairObject(&kToplevelConfigurationSignature, | 102 |
41 *original, &result)); | 103 // This test case is about validating valid ONC objects without any errors. Both |
42 EXPECT_EQ(Validator::VALID, result); | 104 // the strict and the liberal validator accept the object. |
43 EXPECT_TRUE(test_utils::Equals(original.get(), repaired.get())); | 105 class ONCValidatorValidTest : public ONCValidatorTest, |
44 } | 106 public ::testing::WithParamInterface<OncParams> { |
45 | 107 }; |
46 // This test case is about validating valid ONC objects. | 108 |
47 class ONCValidatorValidTest | 109 TEST_P(ONCValidatorValidTest, StrictValidationValid) { |
48 : public ::testing::TestWithParam< | 110 OncParams onc = GetParam(); |
49 std::pair<std::string, const OncValueSignature*> > { | 111 Validate(true, test_utils::ReadTestDictionary(onc.location), onc.signature, |
50 protected: | 112 onc.is_managed); |
51 std::string GetFilename() const { | 113 ExpectValid(); |
52 return GetParam().first; | 114 } |
53 } | 115 |
54 | 116 TEST_P(ONCValidatorValidTest, LiberalValidationValid) { |
55 const OncValueSignature* GetSignature() const { | 117 OncParams onc = GetParam(); |
56 return GetParam().second; | 118 Validate(false, test_utils::ReadTestDictionary(onc.location), onc.signature, |
57 } | 119 onc.is_managed); |
58 }; | 120 ExpectValid(); |
59 | 121 } |
60 TEST_P(ONCValidatorValidTest, ValidPolicyOnc) { | 122 |
61 scoped_ptr<Validator> validator(CreateStrictValidator(true)); | 123 // The parameters are: |
62 scoped_ptr<const base::DictionaryValue> original( | 124 // OncParams(string: Filename of a ONC file that is to be validated, |
63 test_utils::ReadTestDictionary(GetFilename())); | 125 // OncValueSignature: signature of that ONC, |
64 | 126 // bool: true if the ONC is managed). |
65 Validator::Result result; | |
66 scoped_ptr<const base::DictionaryValue> repaired( | |
67 validator->ValidateAndRepairObject(GetSignature(), *original, &result)); | |
68 EXPECT_EQ(Validator::VALID, result); | |
69 EXPECT_TRUE(test_utils::Equals(original.get(), repaired.get())); | |
70 } | |
71 | |
72 INSTANTIATE_TEST_CASE_P( | 127 INSTANTIATE_TEST_CASE_P( |
73 ONCValidatorValidTest, | 128 ONCValidatorValidTest, |
74 ONCValidatorValidTest, | 129 ONCValidatorValidTest, |
75 ::testing::Values(std::make_pair("managed_toplevel.onc", | 130 ::testing::Values(OncParams("managed_toplevel.onc", |
76 &kToplevelConfigurationSignature), | 131 &kToplevelConfigurationSignature, |
77 std::make_pair("encrypted.onc", | 132 true), |
78 &kToplevelConfigurationSignature), | 133 OncParams("encrypted.onc", |
79 std::make_pair("managed_vpn.onc", | 134 &kToplevelConfigurationSignature, |
80 &kNetworkConfigurationSignature), | 135 true), |
81 std::make_pair("managed_ethernet.onc", | 136 OncParams("managed_vpn.onc", |
82 &kNetworkConfigurationSignature), | 137 &kNetworkConfigurationSignature, |
83 // Ignore recommended arrays in unmanaged ONC: | 138 true), |
84 std::make_pair("recommended_in_unmanaged.onc", | 139 OncParams("managed_ethernet.onc", |
85 &kNetworkConfigurationSignature))); | 140 &kNetworkConfigurationSignature, |
86 | 141 true))); |
87 // Validate invalid ONC objects and check the resulting repaired object. This | 142 |
88 // test fixture loads a test json file into |invalid_| containing several test | 143 namespace { |
89 // objects which can be accessed by their path. The test boolean parameter | 144 |
90 // determines wether to use the strict or the liberal validator. | 145 struct RepairParams { |
91 class ONCValidatorInvalidTest : public ::testing::TestWithParam<bool> { | 146 // Both arguments are strings to identify the object that is expected as the |
| 147 // validation result. They may either be used as filenames or as dictionary |
| 148 // keys. |
| 149 RepairParams(std::string strict_repaired, |
| 150 std::string liberal_repaired) |
| 151 : location_of_strict_repaired(strict_repaired), |
| 152 location_of_liberal_repaired(liberal_repaired) { |
| 153 } |
| 154 |
| 155 std::string location_of_strict_repaired; |
| 156 std::string location_of_liberal_repaired; |
| 157 }; |
| 158 |
| 159 ::std::ostream& operator<<(::std::ostream& os, const RepairParams& rp) { |
| 160 return os << "(" << rp.location_of_strict_repaired << ", " |
| 161 << rp.location_of_liberal_repaired << ")"; |
| 162 } |
| 163 |
| 164 } // namespace |
| 165 |
| 166 // This test case is about validating ONC objects that contain errors which can |
| 167 // be repaired (then the errors count as warnings). If a location of the |
| 168 // expected repaired object is given, then it is checked that the validator |
| 169 // (either strict or liberal) returns this repaired object and the result is |
| 170 // VALID_WITH_WARNINGS. If the location is the empty string, then it is expected |
| 171 // that the validator returns NULL and the result INVALID. |
| 172 class ONCValidatorTestRepairable |
| 173 : public ONCValidatorTest, |
| 174 public ::testing::WithParamInterface<std::pair<OncParams, |
| 175 RepairParams> > { |
92 public: | 176 public: |
93 // Validate the entry at |path_to_object| with the given | 177 // Load the common test data and return the dictionary at the field with |
94 // |signature|. Depending on |managed_onc| the object is interpreted as a | 178 // name |name|. |
95 // managed onc (with recommended fields) or not. The resulting repaired object | 179 scoped_ptr<base::DictionaryValue> GetDictionaryFromTestFile( |
96 // must match the entry at |path_to_repaired| if the liberal validator is | 180 const std::string &name) { |
97 // used. | 181 scoped_ptr<const base::DictionaryValue> dict( |
98 void ValidateInvalid(const std::string& path_to_object, | 182 test_utils::ReadTestDictionary("invalid_settings_with_repairs.json")); |
99 const std::string& path_to_repaired, | 183 const base::DictionaryValue* onc_object = NULL; |
100 const OncValueSignature* signature, | 184 CHECK(dict->GetDictionary(name, &onc_object)); |
101 bool managed_onc) { | 185 return make_scoped_ptr(onc_object->DeepCopy()); |
102 scoped_ptr<Validator> validator; | 186 } |
103 if (GetParam()) | 187 }; |
104 validator = CreateStrictValidator(managed_onc); | 188 |
105 else | 189 TEST_P(ONCValidatorTestRepairable, StrictValidation) { |
106 validator = CreateLiberalValidator(managed_onc); | 190 OncParams onc = GetParam().first; |
107 | 191 Validate(true, GetDictionaryFromTestFile(onc.location), onc.signature, |
108 const base::DictionaryValue* object = NULL; | 192 onc.is_managed); |
109 ASSERT_TRUE(invalid_->GetDictionary(path_to_object, &object)); | 193 std::string location_of_repaired = |
110 | 194 GetParam().second.location_of_strict_repaired; |
111 Validator::Result result; | 195 if (location_of_repaired.empty()) |
112 scoped_ptr<base::DictionaryValue> actual_repaired = | 196 ExpectInvalid(); |
113 validator->ValidateAndRepairObject(signature, *object, &result); | 197 else |
114 if (GetParam() || path_to_repaired == "") { | 198 ExpectRepairWithWarnings(*GetDictionaryFromTestFile(location_of_repaired)); |
115 EXPECT_EQ(Validator::INVALID, result); | 199 } |
116 EXPECT_EQ(NULL, actual_repaired.get()); | 200 |
117 } else { | 201 TEST_P(ONCValidatorTestRepairable, LiberalValidation) { |
118 EXPECT_EQ(Validator::VALID_WITH_WARNINGS, result); | 202 OncParams onc = GetParam().first; |
119 const base::DictionaryValue* expected_repaired = NULL; | 203 Validate(false, GetDictionaryFromTestFile(onc.location), onc.signature, |
120 invalid_->GetDictionary(path_to_repaired, &expected_repaired); | 204 onc.is_managed); |
121 EXPECT_TRUE(test_utils::Equals(expected_repaired, actual_repaired.get())); | 205 std::string location_of_repaired = |
122 } | 206 GetParam().second.location_of_liberal_repaired; |
123 } | 207 if (location_of_repaired.empty()) |
124 | 208 ExpectInvalid(); |
125 virtual void SetUp() { | 209 else |
126 invalid_ = | 210 ExpectRepairWithWarnings(*GetDictionaryFromTestFile(location_of_repaired)); |
127 test_utils::ReadTestDictionary("invalid_settings_with_repairs.json"); | 211 } |
128 } | 212 |
129 | 213 // The parameters for all test case instantations below are: |
130 scoped_ptr<const base::DictionaryValue> invalid_; | 214 // OncParams(string: A fieldname in the dictionary from the file |
131 }; | 215 // "invalid_settings_with_repairs.json". That nested |
132 | 216 // dictionary will be tested. |
133 TEST_P(ONCValidatorInvalidTest, UnknownFieldName) { | 217 // OncValueSignature: signature of that ONC, |
134 ValidateInvalid("network-unknown-fieldname", | 218 // bool: true if the ONC is managed). |
135 "network-repaired", | 219 // RepairParams(string: A fieldname in the dictionary from the file |
136 &kNetworkConfigurationSignature, false); | 220 // "invalid_settings_with_repairs.json". That nested |
137 ValidateInvalid("managed-network-unknown-fieldname", | 221 // dictionary is the expected result from strict |
138 "managed-network-repaired", | 222 // validation, |
139 &kNetworkConfigurationSignature, true); | 223 // string: A fieldname in the dictionary from the file |
140 } | 224 // "invalid_settings_with_repairs.json". That nested |
141 | 225 // dictionary is the expected result from liberal |
142 TEST_P(ONCValidatorInvalidTest, UnknownType) { | 226 // validation). |
143 ValidateInvalid("network-unknown-type", | 227 |
144 "", | 228 // Strict validator returns INVALID. Liberal validator repairs. |
145 &kNetworkConfigurationSignature, false); | 229 INSTANTIATE_TEST_CASE_P( |
146 ValidateInvalid("managed-network-unknown-type", | 230 StrictInvalidLiberalRepair, |
147 "", | 231 ONCValidatorTestRepairable, |
148 &kNetworkConfigurationSignature, true); | 232 ::testing::Values( |
149 } | 233 std::make_pair(OncParams("network-unknown-fieldname", |
150 | 234 &kNetworkConfigurationSignature, |
151 TEST_P(ONCValidatorInvalidTest, UnknownRecommendedFieldName) { | 235 false), |
152 ValidateInvalid("managed-network-unknown-recommended", | 236 RepairParams("", "network-repaired")), |
153 "managed-network-repaired", | 237 std::make_pair(OncParams("managed-network-unknown-fieldname", |
154 &kNetworkConfigurationSignature, true); | 238 &kNetworkConfigurationSignature, |
155 } | 239 true), |
156 | 240 RepairParams("", "managed-network-repaired")), |
157 TEST_P(ONCValidatorInvalidTest, DictionaryRecommended) { | 241 std::make_pair(OncParams("managed-network-unknown-recommended", |
158 ValidateInvalid("managed-network-dict-recommended", | 242 &kNetworkConfigurationSignature, |
159 "managed-network-repaired", | 243 true), |
160 &kNetworkConfigurationSignature, true); | 244 RepairParams("", "managed-network-repaired")), |
161 } | 245 std::make_pair(OncParams("managed-network-dict-recommended", |
162 | 246 &kNetworkConfigurationSignature, |
163 TEST_P(ONCValidatorInvalidTest, MissingRequiredField) { | 247 true), |
164 ValidateInvalid("network-missing-required", | 248 RepairParams("", "managed-network-repaired")), |
165 "network-missing-required", | 249 std::make_pair(OncParams("network-missing-required", |
166 &kNetworkConfigurationSignature, false); | 250 &kNetworkConfigurationSignature, |
167 ValidateInvalid("managed-network-missing-required", | 251 false), |
168 "managed-network-missing-required", | 252 RepairParams("", "network-missing-required")), |
169 &kNetworkConfigurationSignature, true); | 253 std::make_pair(OncParams("managed-network-missing-required", |
170 } | 254 &kNetworkConfigurationSignature, |
171 | 255 true), |
172 TEST_P(ONCValidatorInvalidTest, RecommendedInUnmanaged) { | 256 RepairParams("", "managed-network-missing-required")))); |
173 ValidateInvalid("network-illegal-recommended", | 257 |
174 "network-repaired", | 258 // Strict and liberal validator repair identically. |
175 &kNetworkConfigurationSignature, false); | 259 INSTANTIATE_TEST_CASE_P( |
176 } | 260 StrictAndLiberalRepairIdentically, |
177 | 261 ONCValidatorTestRepairable, |
178 INSTANTIATE_TEST_CASE_P(ONCValidatorInvalidTest, | 262 ::testing::Values( |
179 ONCValidatorInvalidTest, | 263 std::make_pair(OncParams("toplevel-invalid-network", |
180 ::testing::Bool()); | 264 &kToplevelConfigurationSignature, |
| 265 false), |
| 266 RepairParams("toplevel-repaired", |
| 267 "toplevel-repaired")), |
| 268 std::make_pair(OncParams("toplevel-invalid-network", |
| 269 &kToplevelConfigurationSignature, |
| 270 true), |
| 271 RepairParams("toplevel-repaired", |
| 272 "toplevel-repaired")), |
| 273 // Ignore recommended arrays in unmanaged ONC. |
| 274 std::make_pair(OncParams("network-with-illegal-recommended", |
| 275 &kNetworkConfigurationSignature, |
| 276 false), |
| 277 RepairParams("network-repaired", "network-repaired")))); |
| 278 |
| 279 // Strict and liberal validator return both INVALID. |
| 280 INSTANTIATE_TEST_CASE_P( |
| 281 StrictAndLiberalInvalid, |
| 282 ONCValidatorTestRepairable, |
| 283 ::testing::Values( |
| 284 std::make_pair(OncParams("network-unknown-value", |
| 285 &kNetworkConfigurationSignature, false), |
| 286 RepairParams("", "")), |
| 287 std::make_pair(OncParams("managed-network-unknown-value", |
| 288 &kNetworkConfigurationSignature, true), |
| 289 RepairParams("", "")), |
| 290 std::make_pair(OncParams("network-value-out-of-range", |
| 291 &kNetworkConfigurationSignature, false), |
| 292 RepairParams("", "")), |
| 293 std::make_pair(OncParams("managed-network-value-out-of-range", |
| 294 &kNetworkConfigurationSignature, true), |
| 295 RepairParams("", "")), |
| 296 std::make_pair(OncParams("network-wrong-type", |
| 297 &kNetworkConfigurationSignature, false), |
| 298 RepairParams("", "")), |
| 299 std::make_pair(OncParams("managed-network-wrong-type", |
| 300 &kNetworkConfigurationSignature, true), |
| 301 RepairParams("", "")))); |
181 | 302 |
182 } // namespace onc | 303 } // namespace onc |
183 } // namespace chromeos | 304 } // namespace chromeos |
OLD | NEW |