1 /* Copyright (c) 2013, Ford Motor Company
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following
12 * disclaimer in the documentation and/or other materials provided with the
15 * Neither the name of the Ford Motor Company nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <gtest/gtest.h>
39 #include "json/value.h"
40 #include "policy/sql_pt_representation.h"
41 #include "policy/policy_types.h"
42 #include "policy_table_interface_base/types.h"
43 #include "policy_table_interface_base/enums.h"
45 using policy::SQLPTRepresentation;
46 using policy::CheckPermissionResult;
47 using policy::EndpointUrls;
50 namespace components {
57 conn_ = qdb_connect(kDatabaseName_.c_str(), 0);
61 qdb_disconnect(conn_);
63 bool Exec(const char* query) {
64 return -1 != qdb_statement(conn_, query);
67 static qdb_hdl_t* conn_;
68 static const std::string kDatabaseName_;
70 qdb_hdl_t* DBMS::conn_ = 0;
71 const std::string DBMS::kDatabaseName_ = "policy";
76 return SQLITE_OK == sqlite3_open(kFileName_.c_str(), &conn_);
80 remove(kFileName_.c_str());
82 bool Exec(const char* query) {
83 return SQLITE_OK == sqlite3_exec(conn_, query, NULL, NULL, NULL);
86 static sqlite3* conn_;
87 static const std::string kFileName_;
89 sqlite3* DBMS::conn_ = 0;
90 const std::string DBMS::kFileName_ = "policy.sqlite";
93 class SQLPTRepresentationTest : public ::testing::Test {
96 static SQLPTRepresentation* reps;
98 static void SetUpTestCase() {
99 reps = new SQLPTRepresentation;
101 EXPECT_EQ(::policy::SUCCESS, reps->Init());
102 EXPECT_TRUE(dbms->Open());
105 static void TearDownTestCase() {
106 EXPECT_TRUE(reps->Clear());
107 EXPECT_TRUE(reps->Close());
113 DBMS* SQLPTRepresentationTest::dbms = 0;
114 SQLPTRepresentation* SQLPTRepresentationTest::reps = 0;
116 ::testing::AssertionResult IsValid(const policy_table::Table &table) {
117 if (table.is_valid()) {
118 return ::testing::AssertionSuccess();
120 ::rpc::ValidationReport report(" - table");
121 table.ReportErrors(&report);
122 return ::testing::AssertionFailure() << ::rpc::PrettyFormat(report);
126 TEST_F(SQLPTRepresentationTest, CheckPermissionsAllowed) {
127 const char* query = "INSERT OR REPLACE INTO `application` (`id`, `memory_kb`,"
128 " `watchdog_timer_ms`) VALUES ('12345', 5, 10); "
129 "INSERT OR REPLACE INTO functional_group (`id`, `name`)"
130 " VALUES (1, 'Base-4'); "
131 "INSERT OR REPLACE INTO `app_group` (`application_id`,"
132 " `functional_group_id`) VALUES ('12345', 1); "
133 "INSERT OR REPLACE INTO `rpc` (`name`, `parameter`, `hmi_level_value`,"
134 " `functional_group_id`) VALUES ('Update', 'gps', 'FULL', 1); "
135 "INSERT OR REPLACE INTO `rpc` (`name`, `parameter`, `hmi_level_value`,"
136 " `functional_group_id`) VALUES ('Update', 'speed', 'FULL', 1);";
137 ASSERT_TRUE(dbms->Exec(query));
139 CheckPermissionResult ret;
140 ret = reps->CheckPermissions("12345", "FULL", "Update");
141 EXPECT_TRUE(ret.hmi_level_permitted == ::policy::kRpcAllowed);
142 ASSERT_EQ(2, ret.list_of_allowed_params->size());
143 EXPECT_EQ("gps", (*ret.list_of_allowed_params)[0]);
144 EXPECT_EQ("speed", (*ret.list_of_allowed_params)[1]);
147 TEST_F(SQLPTRepresentationTest, CheckPermissionsAllowedWithoutParameters) {
148 const char* query = "INSERT OR REPLACE INTO `application` (`id`, `memory_kb`,"
149 " `watchdog_timer_ms`) VALUES ('12345', 5, 10); "
150 "INSERT OR REPLACE INTO functional_group (`id`, `name`)"
151 " VALUES (1, 'Base-4'); "
152 "INSERT OR REPLACE INTO `app_group` (`application_id`,"
153 " `functional_group_id`) VALUES ('12345', 1); "
154 "DELETE FROM `rpc`; "
155 "INSERT OR REPLACE INTO `rpc` (`name`, `hmi_level_value`,"
156 " `functional_group_id`) VALUES ('Update', 'LIMITED', 1);";
157 ASSERT_TRUE(dbms->Exec(query));
159 CheckPermissionResult ret;
160 ret = reps->CheckPermissions("12345", "LIMITED", "Update");
161 EXPECT_TRUE(ret.hmi_level_permitted == ::policy::kRpcAllowed);
162 EXPECT_TRUE(!ret.list_of_allowed_params);
165 TEST_F(SQLPTRepresentationTest, CheckPermissionsDisallowed) {
166 const char* query = "DELETE FROM `app_group`";
167 ASSERT_TRUE(dbms->Exec(query));
169 CheckPermissionResult ret;
170 ret = reps->CheckPermissions("12345", "FULL", "Update");
171 EXPECT_EQ(::policy::kRpcDisallowed, ret.hmi_level_permitted);
172 EXPECT_TRUE(!ret.list_of_allowed_params);
175 TEST_F(SQLPTRepresentationTest, IsPTPReloaded) {
176 const char* query = "UPDATE `module_config` SET `preloaded_pt` = 1";
177 ASSERT_TRUE(dbms->Exec(query));
178 EXPECT_TRUE(reps->IsPTPreloaded());
181 TEST_F(SQLPTRepresentationTest, GetUpdateUrls) {
182 const char* query_delete = "DELETE FROM `endpoint`; ";
183 ASSERT_TRUE(dbms->Exec(query_delete));
184 EndpointUrls ret = reps->GetUpdateUrls(7);
185 EXPECT_TRUE(ret.empty());
187 const char* query_insert =
188 "INSERT INTO `endpoint` (`application_id`, `url`, `service`) "
189 " VALUES ('12345', 'http://ford.com/cloud/1', '0x07');"
190 "INSERT INTO `endpoint` (`application_id`, `url`, `service`) "
191 " VALUES ('12345', 'http://ford.com/cloud/2', '0x07');";
193 ASSERT_TRUE(dbms->Exec(query_insert));
194 ret = reps->GetUpdateUrls(7);
195 ASSERT_EQ(2, ret.size());
196 EXPECT_EQ("http://ford.com/cloud/1", ret[0].url);
197 EXPECT_EQ("http://ford.com/cloud/2", ret[1].url);
199 ret = reps->GetUpdateUrls(0);
200 EXPECT_TRUE(ret.empty());
203 TEST_F(SQLPTRepresentationTest, IgnitionCyclesBeforeExchangeAndIncrement) {
204 const char* query_zeros = "UPDATE `module_meta` SET "
205 " `ignition_cycles_since_last_exchange` = 0; "
206 " UPDATE `module_config` SET `exchange_after_x_ignition_cycles` = 0";
207 ASSERT_TRUE(dbms->Exec(query_zeros));
208 EXPECT_EQ(0, reps->IgnitionCyclesBeforeExchange());
209 reps->IncrementIgnitionCycles();
210 EXPECT_EQ(0, reps->IgnitionCyclesBeforeExchange());
212 const char* query_less_limit = "UPDATE `module_meta` SET "
213 " `ignition_cycles_since_last_exchange` = 5; "
214 " UPDATE `module_config` SET `exchange_after_x_ignition_cycles` = 10";
215 ASSERT_TRUE(dbms->Exec(query_less_limit));
216 EXPECT_EQ(5, reps->IgnitionCyclesBeforeExchange());
217 reps->IncrementIgnitionCycles();
218 EXPECT_EQ(4, reps->IgnitionCyclesBeforeExchange());
220 const char* query_limit = "UPDATE `module_meta` SET "
221 " `ignition_cycles_since_last_exchange` = 9; "
222 " UPDATE `module_config` SET `exchange_after_x_ignition_cycles` = 10";
223 ASSERT_TRUE(dbms->Exec(query_limit));
224 EXPECT_EQ(1, reps->IgnitionCyclesBeforeExchange());
225 reps->IncrementIgnitionCycles();
226 EXPECT_EQ(0, reps->IgnitionCyclesBeforeExchange());
228 const char* query_more_limit = "UPDATE `module_meta` SET "
229 " `ignition_cycles_since_last_exchange` = 12; "
230 " UPDATE `module_config` SET `exchange_after_x_ignition_cycles` = 10";
231 ASSERT_TRUE(dbms->Exec(query_more_limit));
232 EXPECT_EQ(0, reps->IgnitionCyclesBeforeExchange());
234 const char* query_negative_limit = "UPDATE `module_meta` SET "
235 " `ignition_cycles_since_last_exchange` = 3; "
236 " UPDATE `module_config` SET `exchange_after_x_ignition_cycles` = -1";
237 ASSERT_TRUE(dbms->Exec(query_negative_limit));
238 EXPECT_EQ(0, reps->IgnitionCyclesBeforeExchange());
240 const char* query_negative_current = "UPDATE `module_meta` SET "
241 " `ignition_cycles_since_last_exchange` = -1; "
242 " UPDATE `module_config` SET `exchange_after_x_ignition_cycles` = 2";
243 ASSERT_TRUE(dbms->Exec(query_negative_current));
244 EXPECT_EQ(0, reps->IgnitionCyclesBeforeExchange());
247 TEST_F(SQLPTRepresentationTest, KilometersBeforeExchange) {
248 const char* query_zeros = "UPDATE `module_meta` SET "
249 " `pt_exchanged_at_odometer_x` = 0; "
250 " UPDATE `module_config` SET `exchange_after_x_kilometers` = 0";
251 ASSERT_TRUE(dbms->Exec(query_zeros));
252 EXPECT_EQ(0, reps->KilometersBeforeExchange(0));
253 EXPECT_EQ(0, reps->KilometersBeforeExchange(-10));
254 EXPECT_EQ(0, reps->KilometersBeforeExchange(10));
256 const char* query_negative_limit = "UPDATE `module_meta` SET "
257 " `pt_exchanged_at_odometer_x` = 10; "
258 " UPDATE `module_config` SET `exchange_after_x_kilometers` = -10";
259 ASSERT_TRUE(dbms->Exec(query_negative_limit));
260 EXPECT_EQ(0, reps->KilometersBeforeExchange(0));
261 EXPECT_EQ(0, reps->KilometersBeforeExchange(10));
263 const char* query_negative_last = "UPDATE `module_meta` SET "
264 " `pt_exchanged_at_odometer_x` = -10; "
265 " UPDATE `module_config` SET `exchange_after_x_kilometers` = 20";
266 ASSERT_TRUE(dbms->Exec(query_negative_last));
267 EXPECT_EQ(0, reps->KilometersBeforeExchange(0));
268 EXPECT_EQ(0, reps->KilometersBeforeExchange(10));
270 const char* query_limit = "UPDATE `module_meta` SET "
271 " `pt_exchanged_at_odometer_x` = 10; "
272 " UPDATE `module_config` SET `exchange_after_x_kilometers` = 100";
273 ASSERT_TRUE(dbms->Exec(query_limit));
274 EXPECT_EQ(0, reps->KilometersBeforeExchange(120));
275 EXPECT_EQ(60, reps->KilometersBeforeExchange(50));
276 EXPECT_EQ(0, reps->KilometersBeforeExchange(5));
279 TEST_F(SQLPTRepresentationTest, DaysBeforeExchange) {
280 const char* query_zeros = "UPDATE `module_meta` SET "
281 " `pt_exchanged_x_days_after_epoch` = 0; "
282 " UPDATE `module_config` SET `exchange_after_x_days` = 0";
283 ASSERT_TRUE(dbms->Exec(query_zeros));
284 EXPECT_EQ(0, reps->DaysBeforeExchange(0));
285 EXPECT_EQ(0, reps->DaysBeforeExchange(-10));
286 EXPECT_EQ(0, reps->DaysBeforeExchange(10));
288 const char* query_negative_limit = "UPDATE `module_meta` SET "
289 " `pt_exchanged_x_days_after_epoch` = 10; "
290 " UPDATE `module_config` SET `exchange_after_x_days` = -10";
291 ASSERT_TRUE(dbms->Exec(query_negative_limit));
292 EXPECT_EQ(0, reps->DaysBeforeExchange(0));
293 EXPECT_EQ(0, reps->DaysBeforeExchange(10));
295 const char* query_negative_last = "UPDATE `module_meta` SET "
296 " `pt_exchanged_x_days_after_epoch` = -10; "
297 " UPDATE `module_config` SET `exchange_after_x_days` = 20";
298 ASSERT_TRUE(dbms->Exec(query_negative_last));
299 EXPECT_EQ(0, reps->DaysBeforeExchange(0));
300 EXPECT_EQ(0, reps->DaysBeforeExchange(10));
302 const char* query_limit = "UPDATE `module_meta` SET "
303 " `pt_exchanged_x_days_after_epoch` = 10; "
304 " UPDATE `module_config` SET `exchange_after_x_days` = 100";
305 ASSERT_TRUE(dbms->Exec(query_limit));
306 EXPECT_EQ(0, reps->DaysBeforeExchange(120));
307 EXPECT_EQ(60, reps->DaysBeforeExchange(50));
308 EXPECT_EQ(0, reps->DaysBeforeExchange(5));
311 TEST_F(SQLPTRepresentationTest, SecondsBetweenRetries) {
312 std::vector<int> seconds;
314 const char* query_delete = "DELETE FROM `seconds_between_retry`; ";
315 ASSERT_TRUE(dbms->Exec(query_delete));
316 ASSERT_TRUE(reps->SecondsBetweenRetries(&seconds));
317 EXPECT_EQ(0, seconds.size());
319 const char* query_insert =
320 "INSERT INTO `seconds_between_retry` (`index`, `value`) "
322 "INSERT INTO `seconds_between_retry` (`index`, `value`) "
324 ASSERT_TRUE(dbms->Exec(query_insert));
325 ASSERT_TRUE(reps->SecondsBetweenRetries(&seconds));
326 ASSERT_EQ(2, seconds.size());
327 EXPECT_EQ(10, seconds[0]);
328 EXPECT_EQ(20, seconds[1]);
331 TEST_F(SQLPTRepresentationTest, TimeoutResponse) {
333 "UPDATE `module_config` SET `timeout_after_x_seconds` = 60";
334 ASSERT_TRUE(dbms->Exec(query));
335 EXPECT_EQ(60, reps->TimeoutResponse());
338 #ifndef EXTENDED_POLICY
339 TEST_F(SQLPTRepresentationTest, SaveGenerateSnapshot) {
340 Json::Value expect(Json::objectValue);
341 expect["policy_table"] = Json::Value(Json::objectValue);
343 Json::Value& policy_table = expect["policy_table"];
344 policy_table["module_meta"] = Json::Value(Json::objectValue);
345 policy_table["module_config"] = Json::Value(Json::objectValue);
346 policy_table["usage_and_error_counts"] = Json::Value(Json::objectValue);
347 policy_table["device_data"] = Json::Value(Json::objectValue);
348 policy_table["functional_groupings"] = Json::Value(Json::objectValue);
349 policy_table["consumer_friendly_messages"] = Json::Value(Json::objectValue);
350 policy_table["app_policies"] = Json::Value(Json::objectValue);
352 Json::Value& module_config = policy_table["module_config"];
353 module_config["preloaded_pt"] = Json::Value(true);
354 module_config["exchange_after_x_ignition_cycles"] = Json::Value(10);
355 module_config["exchange_after_x_kilometers"] = Json::Value(100);
356 module_config["exchange_after_x_days"] = Json::Value(5);
357 module_config["timeout_after_x_seconds"] = Json::Value(500);
358 module_config["seconds_between_retries"] = Json::Value(Json::arrayValue);
359 module_config["seconds_between_retries"][0] = Json::Value(10);
360 module_config["seconds_between_retries"][1] = Json::Value(20);
361 module_config["seconds_between_retries"][2] = Json::Value(30);
362 module_config["endpoints"] = Json::Value(Json::objectValue);
363 module_config["endpoints"]["0x00"] = Json::Value(Json::objectValue);
364 module_config["endpoints"]["0x00"]["default"] = Json::Value(Json::arrayValue);
365 module_config["endpoints"]["0x00"]["default"][0] = Json::Value(
366 "http://ford.com/cloud/default");
367 module_config["notifications_per_minute_by_priority"] = Json::Value(
369 module_config["notifications_per_minute_by_priority"]["emergency"] =
371 module_config["notifications_per_minute_by_priority"]["navigation"] =
373 module_config["notifications_per_minute_by_priority"]["voiceCommunication"] =
375 module_config["notifications_per_minute_by_priority"]["communication"] =
377 module_config["notifications_per_minute_by_priority"]["normal"] = Json::Value(
379 module_config["notifications_per_minute_by_priority"]["none"] = Json::Value(
381 module_config["vehicle_make"] = Json::Value("MakeT");
382 module_config["vehicle_model"] = Json::Value("ModelT");
383 module_config["vehicle_year"] = Json::Value(2014);
385 Json::Value& usage_and_error_counts = policy_table["usage_and_error_counts"];
386 usage_and_error_counts["app_level"] = Json::Value(Json::objectValue);
387 usage_and_error_counts["app_level"]["12345"] = Json::Value(Json::objectValue);
389 Json::Value& device_data = policy_table["device_data"];
390 device_data["user_consent_records"] = Json::Value(Json::objectValue);
392 Json::Value& functional_groupings = policy_table["functional_groupings"];
393 functional_groupings["default"] = Json::Value(Json::objectValue);
394 Json::Value& default_group = functional_groupings["default"];
395 default_group["rpcs"] = Json::Value(Json::objectValue);
396 default_group["rpcs"]["Update"] = Json::Value(Json::objectValue);
397 default_group["rpcs"]["Update"]["hmi_levels"] = Json::Value(Json::arrayValue);
398 default_group["rpcs"]["Update"]["hmi_levels"][0] = Json::Value("FULL");
399 default_group["rpcs"]["Update"]["parameters"] = Json::Value(Json::arrayValue);
400 default_group["rpcs"]["Update"]["parameters"][0] = Json::Value("speed");
402 Json::Value& consumer_friendly_messages =
403 policy_table["consumer_friendly_messages"];
404 consumer_friendly_messages["version"] = Json::Value("1.2");
406 Json::Value& app12345counters = usage_and_error_counts["app_level"]["12345"];
407 app12345counters["app_registration_language_gui"] = "";
408 app12345counters["app_registration_language_vui"] = "";
409 app12345counters["count_of_rejected_rpc_calls"] = 0;
410 app12345counters["count_of_rejections_duplicate_name"] = 0;
411 app12345counters["count_of_rejections_nickname_mismatch"] = 0;
412 app12345counters["count_of_rejections_sync_out_of_memory"] = 0;
413 app12345counters["count_of_removals_for_bad_behavior"] = 0;
414 app12345counters["count_of_rfcom_limit_reached"] = 0;
415 app12345counters["count_of_rpcs_sent_in_hmi_none"] = 0;
416 app12345counters["count_of_run_attempts_while_revoked"] = 0;
417 app12345counters["count_of_user_selections"] = 0;
418 app12345counters["minutes_in_hmi_background"] = 0;
419 app12345counters["minutes_in_hmi_full"] = 0;
420 app12345counters["minutes_in_hmi_limited"] = 0;
421 app12345counters["minutes_in_hmi_none"] = 0;
423 Json::Value& app_policies = policy_table["app_policies"];
424 app_policies["default"] = Json::Value(Json::objectValue);
425 app_policies["default"]["memory_kb"] = Json::Value(50);
426 app_policies["default"]["watchdog_timer_ms"] = Json::Value(100);
427 app_policies["default"]["groups"] = Json::Value(Json::arrayValue);
428 app_policies["default"]["groups"][0] = Json::Value("default");
430 policy_table::Table table(&expect);
432 ASSERT_TRUE(IsValid(table));
433 ASSERT_TRUE(reps->Save(table));
434 utils::SharedPtr<policy_table::Table> snapshot = reps->GenerateSnapshot();
435 EXPECT_TRUE(IsValid(*snapshot));
436 EXPECT_EQ(table.ToJsonValue().toStyledString(),
437 snapshot->ToJsonValue().toStyledString());
439 #endif // EXTENDED_POLICY
441 } // namespace policy
442 } // namespace components
445 int main(int argc, char** argv) {
446 testing::InitGoogleTest(&argc, argv);
447 return RUN_ALL_TESTS();