1 #include <gtest/gtest.h> 6 #include <unordered_map> 9 #include <boost/filesystem.hpp> 10 #include "json/json.h" 13 #include "libaktualizr/config.h" 15 #include "primary/aktualizr.h" 16 #include "primary/aktualizr_helpers.h" 17 #include "primary/sotauptaneclient.h" 18 #include "uptane_test_common.h" 19 #include "utilities/utils.h" 20 #include "virtualsecondary.h" 22 #include "utilities/fault_injection.h" 24 boost::filesystem::path uptane_repos_dir;
25 boost::filesystem::path fake_meta_dir;
27 void verifyNothingInstalled(
const Json::Value& manifest) {
30 manifest[
"ecu_version_manifests"][
"CA:FE:A6:D2:84:9D"][
"signed"][
"custom"][
"operation_result"][
"id"].asString(),
33 manifest[
"ecu_version_manifests"][
"CA:FE:A6:D2:84:9D"][
"signed"][
"custom"][
"operation_result"][
"result_code"]
35 static_cast<int>(data::ResultCode::Numeric::kOk));
37 manifest[
"ecu_version_manifests"][
"CA:FE:A6:D2:84:9D"][
"signed"][
"custom"][
"operation_result"][
"result_text"]
40 EXPECT_EQ(manifest[
"ecu_version_manifests"][
"CA:FE:A6:D2:84:9D"][
"signed"][
"installed_image"][
"filepath"].asString(),
44 manifest[
"ecu_version_manifests"][
"secondary_ecu_serial"][
"signed"][
"installed_image"][
"filepath"].asString(),
53 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"noupdates", fake_meta_dir);
54 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
56 auto storage = INvStorage::newStorage(conf.storage);
61 std::future<void> future;
62 std::promise<void> promise;
64 ev_state.future = ev_state.promise.get_future();
66 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
70 LOG_INFO <<
"Got " <<
event->variant;
71 switch (ev_state.num_events) {
73 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
75 EXPECT_EQ(targets_event->result.ecus_count, 0);
76 EXPECT_EQ(targets_event->result.updates.size(), 0);
77 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
81 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
83 EXPECT_EQ(targets_event->result.ecus_count, 0);
84 EXPECT_EQ(targets_event->result.updates.size(), 0);
85 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
86 ev_state.promise.set_value();
91 FAIL() <<
"Unexpected events!";
93 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
94 ASSERT_EQ(
event->variant,
"");
96 ++ev_state.num_events;
98 boost::signals2::connection conn = aktualizr.SetSignalHandler(f_cb);
100 aktualizr.Initialize();
101 aktualizr.UptaneCycle();
104 aktualizr.UptaneCycle();
105 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
106 if (status != std::future_status::ready) {
107 FAIL() <<
"Timed out waiting for metadata to be fetched.";
110 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
117 TEST(
Aktualizr, DeviceInstallationResult) {
119 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", fake_meta_dir);
120 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
122 auto storage = INvStorage::newStorage(conf.storage);
128 storage->storeEcuSerials(serials);
132 aktualizr.AddSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config));
133 aktualizr.Initialize();
141 aktualizr.uptane_client()->computeDeviceInstallationResult(&result,
nullptr);
142 auto res_json = result.toJson();
143 EXPECT_EQ(res_json[
"code"].asString(),
"primary_hw:INSTALL_FAILED");
144 EXPECT_EQ(res_json[
"success"],
false);
146 storage->saveEcuInstallationResult(
149 aktualizr.uptane_client()->computeDeviceInstallationResult(&result,
nullptr);
150 res_json = result.toJson();
151 EXPECT_EQ(res_json[
"code"].asString(),
"primary_hw:INSTALL_FAILED|hw_id3:SECOND_FAIL");
152 EXPECT_EQ(res_json[
"success"],
false);
161 TEST(
Aktualizr, DeviceInstallationResultMetadata) {
165 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
166 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
167 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"sec_serial1",
"sec_hw1");
168 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"sec_serial2",
"sec_hw2");
169 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"sec_serial3",
"sec_hw3");
171 auto storage = INvStorage::newStorage(conf.storage);
173 aktualizr.Initialize();
174 auto update_result = aktualizr.CheckUpdates().get();
175 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
177 fault_injection_init();
178 fiu_enable(
"secondary_putmetadata", 1,
nullptr, 0);
181 std::vector<Uptane::Target> targets;
182 Json::Value target_json;
183 target_json[
"custom"][
"targetFormat"] =
"BINARY";
184 target_json[
"custom"][
"ecuIdentifiers"][
"sec_serial1"][
"hardwareId"] =
"sec_hw1";
185 target_json[
"custom"][
"ecuIdentifiers"][
"sec_serial3"][
"hardwareId"] =
"sec_hw3";
189 aktualizr.uptane_client()->sendMetadataToEcus(targets, &result,
nullptr);
190 auto res_json = result.toJson();
191 EXPECT_EQ(res_json[
"code"].asString(),
"sec_hw1:VERIFICATION_FAILED|sec_hw3:VERIFICATION_FAILED");
192 EXPECT_EQ(res_json[
"success"],
false);
194 fiu_disable(
"secondary_putmetadata");
197 aktualizr.uptane_client()->sendMetadataToEcus(targets, &result,
nullptr);
198 res_json = result.toJson();
199 EXPECT_EQ(res_json[
"code"].asString(),
"OK");
200 EXPECT_EQ(res_json[
"success"],
true);
207 HttpFakeEventCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
208 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
210 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
212 for (
const Json::Value&
event : data) {
214 std::string event_type =
event[
"eventType"][
"id"].asString();
215 if (event_type.find(
"Ecu") == 0) {
216 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
219 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
220 if (events_seen >= 1 && events_seen <= 4) {
221 EXPECT_TRUE(event_type ==
"EcuDownloadStarted" || event_type ==
"EcuDownloadCompleted");
222 }
else if (events_seen >= 5 && events_seen <= 8) {
223 EXPECT_TRUE(event_type ==
"EcuInstallationStarted" || event_type ==
"EcuInstallationCompleted");
225 std::cout <<
"Unexpected event";
232 unsigned int events_seen{0};
241 auto http = std::make_shared<HttpFakeEventCounter>(temp_dir.Path(), fake_meta_dir);
242 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
244 auto storage = INvStorage::newStorage(conf.storage);
248 size_t num_events{0};
249 std::future<void> future;
250 std::promise<void> promise;
252 ev_state.future = ev_state.promise.get_future();
254 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
258 LOG_INFO <<
"Got " <<
event->variant;
259 switch (ev_state.num_events) {
261 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
263 EXPECT_EQ(targets_event->result.ecus_count, 2);
264 EXPECT_EQ(targets_event->result.updates.size(), 2u);
265 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
266 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
267 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
272 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
274 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
275 download_event->update.filename() ==
"secondary_firmware.txt");
276 EXPECT_TRUE(download_event->success);
280 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
282 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
283 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
284 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
285 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
286 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
287 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
293 ASSERT_EQ(
event->variant,
"InstallStarted");
295 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
301 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
303 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
304 EXPECT_TRUE(install_complete->success);
308 ASSERT_EQ(
event->variant,
"InstallStarted");
310 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
314 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
316 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
317 EXPECT_TRUE(install_complete->success);
321 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
323 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 2);
324 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
325 data::ResultCode::Numeric::kOk);
326 EXPECT_EQ(installs_complete->result.ecu_reports[1].install_res.result_code.num_code,
327 data::ResultCode::Numeric::kOk);
331 ASSERT_EQ(
event->variant,
"PutManifestComplete");
333 EXPECT_TRUE(put_complete->success);
334 ev_state.promise.set_value();
339 FAIL() <<
"Unexpected events!";
341 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
342 ASSERT_EQ(
event->variant,
"");
344 ++ev_state.num_events;
350 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
351 if (status != std::future_status::ready) {
352 FAIL() <<
"Timed out waiting for installation to complete.";
354 EXPECT_EQ(http->events_seen, 8);
359 HttpFakeSplit(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
360 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
362 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
364 for (
const Json::Value&
event : data) {
366 std::string event_type =
event[
"eventType"][
"id"].asString();
367 if (event_type.find(
"Ecu") == 0) {
368 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
371 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
372 switch (events_seen) {
375 EXPECT_TRUE(event_type ==
"EcuDownloadStarted");
379 EXPECT_TRUE(event_type ==
"EcuDownloadCompleted");
383 EXPECT_TRUE(event_type ==
"EcuInstallationStarted");
387 EXPECT_TRUE(event_type ==
"EcuInstallationCompleted");
390 std::cout <<
"Unexpected event";
398 unsigned int events_seen{0};
413 auto http = std::make_shared<HttpFakeSplit>(temp_dir.Path(), fake_meta_dir);
414 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
416 auto storage = INvStorage::newStorage(conf.storage);
420 size_t num_events{0};
421 std::future<void> future;
422 std::promise<void> promise;
424 ev_state.future = ev_state.promise.get_future();
426 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
430 LOG_INFO <<
"Got " <<
event->variant;
431 switch (ev_state.num_events) {
433 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
435 EXPECT_EQ(targets_event->result.ecus_count, 2);
436 EXPECT_EQ(targets_event->result.updates.size(), 2u);
437 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
438 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
439 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
443 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
445 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt");
446 EXPECT_TRUE(download_event->success);
450 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
452 EXPECT_EQ(downloads_complete->result.updates.size(), 1);
453 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt");
454 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
460 ASSERT_EQ(
event->variant,
"InstallStarted");
462 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
468 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
470 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
471 EXPECT_TRUE(install_complete->success);
475 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
477 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 1);
478 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
479 data::ResultCode::Numeric::kOk);
483 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
485 EXPECT_TRUE(download_event->update.filename() ==
"secondary_firmware.txt");
486 EXPECT_TRUE(download_event->success);
490 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
492 EXPECT_EQ(downloads_complete->result.updates.size(), 1);
493 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt");
494 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
498 ASSERT_EQ(
event->variant,
"InstallStarted");
500 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
504 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
506 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
507 EXPECT_TRUE(install_complete->success);
511 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
513 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 1);
514 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
515 data::ResultCode::Numeric::kOk);
519 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
521 EXPECT_EQ(targets_event->result.ecus_count, 0);
522 EXPECT_EQ(targets_event->result.updates.size(), 0);
523 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
524 ev_state.promise.set_value();
529 FAIL() <<
"Unexpected events!";
531 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
532 ASSERT_EQ(
event->variant,
"");
534 ++ev_state.num_events;
540 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
541 ASSERT_EQ(update_result.ecus_count, 2);
545 ASSERT_EQ(download_result.status, result::DownloadStatus::kSuccess);
546 aktualizr.
Install(download_result.updates);
548 download_result = aktualizr.
Download({update_result.updates[1]}).
get();
549 ASSERT_EQ(download_result.status, result::DownloadStatus::kSuccess);
550 aktualizr.
Install(download_result.updates);
553 ASSERT_EQ(update_result.status, result::UpdateStatus::kNoUpdatesAvailable);
555 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
556 if (status != std::future_status::ready) {
557 FAIL() <<
"Timed out waiting for installation to complete.";
559 EXPECT_EQ(http->events_seen, 8);
564 HttpFakePutCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
565 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
567 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
568 if (url.find(
"/manifest") != std::string::npos) {
571 return HttpFake::put(url, data);
574 HttpResponse handle_event(
const std::string& url,
const Json::Value& data)
override {
577 for (
const Json::Value&
event : data) {
578 events.push_back(
event);
583 size_t count_event_with_type(
const std::string& event_type) {
584 auto c = std::count_if(events.cbegin(), events.cend(), [&event_type](
const Json::Value& v) {
585 return v[
"eventType"][
"id"].asString() == event_type;
587 return static_cast<size_t>(c);
590 unsigned int manifest_sends{0};
591 std::vector<Json::Value> events;
614 TEST(
Aktualizr, FullWithUpdatesNeedReboot) {
616 auto http = std::make_shared<HttpFakePutCounter>(temp_dir.Path(), fake_meta_dir);
617 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
618 conf.pacman.fake_need_reboot =
true;
622 auto storage = INvStorage::newStorage(conf.storage);
629 boost::optional<Uptane::Target> pending_target;
630 storage->loadPrimaryInstalledVersions(
nullptr, &pending_target);
631 EXPECT_TRUE(!!pending_target);
635 EXPECT_EQ(http->manifest_sends, 1);
636 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationStarted"), 2);
637 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationApplied"), 1);
638 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationCompleted"), 1);
642 auto storage = INvStorage::newStorage(conf.storage);
647 boost::optional<Uptane::Target> pending_target;
648 storage->loadPrimaryInstalledVersions(
nullptr, &pending_target);
649 EXPECT_TRUE(!!pending_target);
652 EXPECT_EQ(update_res.status, result::UpdateStatus::kError);
655 boost::filesystem::remove(conf.bootloader.reboot_sentinel_dir / conf.bootloader.reboot_sentinel_name);
659 EXPECT_EQ(http->manifest_sends, 1);
660 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationCompleted"), 1);
664 auto storage = INvStorage::newStorage(conf.storage);
669 EXPECT_EQ(update_res.status, result::UpdateStatus::kNoUpdatesAvailable);
672 boost::optional<Uptane::Target> current_target;
673 boost::optional<Uptane::Target> pending_target;
674 storage->loadPrimaryInstalledVersions(¤t_target, &pending_target);
675 EXPECT_TRUE(!!current_target);
676 EXPECT_FALSE(!!pending_target);
679 boost::optional<Uptane::Target> sec_current_target;
680 boost::optional<Uptane::Target> sec_pending_target;
681 storage->loadInstalledVersions(
"secondary_ecu_serial", &sec_current_target, &sec_pending_target);
682 EXPECT_TRUE(!!sec_current_target);
683 EXPECT_FALSE(!!sec_pending_target);
687 EXPECT_EQ(http->manifest_sends, 3);
688 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationCompleted"), 2);
691 for (
const Json::Value&
event : http->events) {
692 std::cout <<
"got event " <<
event[
"eventType"][
"id"].asString() <<
"\n";
693 EXPECT_EQ(event[
"event"][
"correlationId"].asString(),
"id0");
699 class HttpInstallationFailed :
public HttpFake {
701 HttpInstallationFailed(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
702 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
704 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
707 for (
auto& event_data : data) {
708 auto event_id = event_data[
"eventType"][
"id"].asString();
709 auto ecu = event_data[
"event"][
"ecu"].asString();
710 auto correlationID = event_data[
"event"][
"correlationId"].asString();
712 if (event_id ==
"EcuInstallationCompleted") {
713 install_completion_status_[ecu] = event_data[
"event"][
"success"].asBool();
715 report_events_.push_back(event_id);
720 bool checkReceivedReports(
const std::vector<std::string>& expected_event_order) {
722 auto received_event_it = report_events_.begin();
724 for (
auto& expected_event : expected_event_order) {
725 auto received_event = *received_event_it;
726 if (expected_event != received_event) {
735 bool wasInstallSuccessful(
const std::string& ecu_serial)
const {
736 auto find_it = install_completion_status_.find(ecu_serial);
737 if (find_it == install_completion_status_.end()) {
740 return (*find_it).second;
743 void clearReportEvents() { report_events_.clear(); }
746 std::vector<std::string> report_events_;
747 std::unordered_map<std::string, bool> install_completion_status_;
753 functor_ = std::bind(&EventHandler::operator(),
this, std::placeholders::_1);
757 void operator()(
const std::shared_ptr<event::BaseEvent>&
event) {
758 ASSERT_NE(event,
nullptr);
759 received_events_.push_back(event->variant);
762 bool checkReceivedEvents(
const std::vector<std::string>& expected_event_order) {
764 auto received_event_it = received_events_.begin();
766 for (
auto& expected_event : expected_event_order) {
767 auto received_event = *received_event_it;
768 if (expected_event != received_event) {
773 if (received_event ==
"DownloadProgressReport") {
774 while (*(++received_event_it) ==
"DownloadProgressReport") {
784 std::function<void(std::shared_ptr<event::BaseEvent>)> functor_;
785 std::vector<std::string> received_events_{};
800 auto http_server_mock = std::make_shared<HttpInstallationFailed>(temp_dir.Path(), fake_meta_dir);
801 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
802 conf.pacman.fake_need_reboot =
true;
803 conf.uptane.force_install_completion =
true;
804 conf.uptane.polling_sec = 0;
805 auto storage = INvStorage::newStorage(conf.storage);
807 std::vector<std::string> expected_event_order = {
808 "SendDeviceDataComplete",
"UpdateCheckComplete",
"DownloadProgressReport",
"DownloadTargetComplete",
809 "DownloadProgressReport",
"DownloadTargetComplete",
"AllDownloadsComplete",
"InstallStarted",
810 "InstallTargetComplete",
"InstallStarted",
"InstallTargetComplete",
"AllInstallsComplete"};
812 std::vector<std::string> expected_report_order = {
813 "EcuDownloadStarted",
"EcuDownloadCompleted",
"EcuDownloadStarted",
"EcuDownloadCompleted",
814 "EcuInstallationStarted",
"EcuInstallationApplied",
"EcuInstallationStarted",
"EcuInstallationCompleted"};
816 const std::string primary_ecu_id =
"CA:FE:A6:D2:84:9D";
817 const std::string secondary_ecu_id =
"secondary_ecu_serial";
822 EventHandler event_hdlr(aktualizr);
826 boost::optional<Uptane::Target> current_version;
827 boost::optional<Uptane::Target> pending_version;
828 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
832 EXPECT_FALSE(!!pending_version);
833 EXPECT_FALSE(!!current_version);
835 auto aktualizr_cycle_thread = aktualizr.
RunForever();
836 auto aktualizr_cycle_thread_status = aktualizr_cycle_thread.wait_for(std::chrono::seconds(20));
838 ASSERT_EQ(aktualizr_cycle_thread_status, std::future_status::ready);
839 EXPECT_TRUE(aktualizr.uptane_client()->isInstallCompletionRequired());
840 EXPECT_TRUE(event_hdlr.checkReceivedEvents(expected_event_order));
841 EXPECT_TRUE(aktualizr.uptane_client()->hasPendingUpdates());
842 EXPECT_TRUE(http_server_mock->checkReceivedReports(expected_report_order));
845 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
846 EXPECT_TRUE(http_server_mock->wasInstallSuccessful(secondary_ecu_id));
850 std::string correlation_id;
851 ASSERT_TRUE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
852 EXPECT_EQ(dev_installation_res.result_code.num_code, data::ResultCode::Numeric::kNeedCompletion);
854 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
855 ASSERT_TRUE(storage->loadEcuInstallationResults(&ecu_installation_res));
856 EXPECT_EQ(ecu_installation_res.size(), 2);
858 for (
const auto& ecu_install_res : ecu_installation_res) {
859 auto ecu_id = ecu_install_res.first.ToString();
861 if (ecu_id == primary_ecu_id) {
862 EXPECT_EQ(ecu_install_res.second.result_code.num_code, data::ResultCode::Numeric::kNeedCompletion);
863 EXPECT_EQ(ecu_install_res.second.success,
false);
864 EXPECT_EQ(ecu_install_res.second.description,
"Application successful, need reboot");
866 }
else if (ecu_id == secondary_ecu_id) {
867 EXPECT_EQ(ecu_install_res.second.result_code.num_code, data::ResultCode::Numeric::kOk);
868 EXPECT_EQ(ecu_install_res.second.success,
true);
869 EXPECT_EQ(ecu_install_res.second.description,
"");
872 FAIL() <<
"Unexpected ECU serial: " << ecu_install_res.first;
876 pending_version = boost::none;
877 current_version = boost::none;
879 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
880 EXPECT_FALSE(!!current_version);
881 EXPECT_TRUE(!!pending_version);
882 EXPECT_TRUE(pending_version->IsValid());
884 pending_version = boost::none;
885 current_version = boost::none;
887 ASSERT_TRUE(storage->loadInstalledVersions(secondary_ecu_id, ¤t_version, &pending_version));
888 EXPECT_TRUE(!!current_version);
889 EXPECT_TRUE(current_version->IsValid());
890 EXPECT_FALSE(!!pending_version);
895 fault_injection_init();
896 fiu_enable(
"fake_install_finalization_failure", 1,
nullptr, 0);
897 http_server_mock->clearReportEvents();
900 EventHandler event_hdlr(aktualizr);
903 fiu_disable(
"fake_install_finalization_failure");
905 EXPECT_FALSE(aktualizr.uptane_client()->hasPendingUpdates());
906 EXPECT_TRUE(http_server_mock->checkReceivedReports({
"EcuInstallationCompleted"}));
907 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
911 std::string correlation_id;
915 EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
920 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
921 EXPECT_FALSE(storage->loadEcuInstallationResults(&ecu_installation_res));
924 boost::optional<Uptane::Target> current_version;
925 boost::optional<Uptane::Target> pending_version;
927 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
928 EXPECT_FALSE(!!current_version);
929 EXPECT_FALSE(!!pending_version);
931 current_version = boost::none;
932 pending_version = boost::none;
934 ASSERT_TRUE(storage->loadInstalledVersions(secondary_ecu_id, ¤t_version, &pending_version));
935 EXPECT_TRUE(!!current_version);
936 EXPECT_FALSE(!!pending_version);
951 std::vector<std::string> expected_event_order = {
952 "UpdateCheckComplete",
"DownloadProgressReport",
"DownloadTargetComplete",
"DownloadProgressReport",
953 "DownloadTargetComplete",
"AllDownloadsComplete",
"InstallStarted",
"InstallTargetComplete",
954 "InstallStarted",
"InstallTargetComplete",
"AllInstallsComplete",
"PutManifestComplete"};
956 std::vector<std::string> expected_report_order = {
957 "EcuDownloadStarted",
"EcuDownloadCompleted",
"EcuDownloadStarted",
"EcuDownloadCompleted",
958 "EcuInstallationStarted",
"EcuInstallationCompleted",
"EcuInstallationStarted",
"EcuInstallationCompleted"};
960 const std::string primary_ecu_id =
"CA:FE:A6:D2:84:9D";
961 const std::string secondary_ecu_id =
"secondary_ecu_serial";
965 auto http_server_mock = std::make_shared<HttpInstallationFailed>(temp_dir.Path(), fake_meta_dir);
966 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
967 auto storage = INvStorage::newStorage(conf.storage);
969 fault_injection_init();
970 fiu_enable(
"fake_package_install", 1,
nullptr, 0);
973 EventHandler event_hdlr(aktualizr);
977 boost::optional<Uptane::Target> current_version;
978 boost::optional<Uptane::Target> pending_version;
980 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
982 EXPECT_FALSE(!!pending_version);
983 EXPECT_FALSE(!!current_version);
986 aktualizr.uptane_client()->completeInstall();
988 EXPECT_TRUE(event_hdlr.checkReceivedEvents(expected_event_order));
989 EXPECT_FALSE(aktualizr.uptane_client()->hasPendingUpdates());
990 EXPECT_TRUE(http_server_mock->checkReceivedReports(expected_report_order));
991 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
992 EXPECT_TRUE(http_server_mock->wasInstallSuccessful(secondary_ecu_id));
996 std::string correlation_id;
1000 EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
1002 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
1003 EXPECT_FALSE(storage->loadEcuInstallationResults(&ecu_installation_res));
1004 EXPECT_EQ(ecu_installation_res.size(), 0);
1006 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
1010 EXPECT_FALSE(!!current_version);
1011 EXPECT_FALSE(!!pending_version);
1013 fiu_disable(
"fake_package_install");
1017 for (std::string prefix : {
"secondary_install_",
"secondary_sendfirmware_"}) {
1019 auto http_server_mock = std::make_shared<HttpInstallationFailed>(temp_dir.Path(), fake_meta_dir);
1020 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
1021 auto storage = INvStorage::newStorage(conf.storage);
1022 const std::string sec_fault_name = prefix + secondary_ecu_id;
1024 fault_injection_init();
1025 fault_injection_enable(
"fake_package_install", 1,
"PRIMFAIL", 0);
1026 fault_injection_enable(sec_fault_name.c_str(), 1,
"SECFAIL", 0);
1029 EventHandler event_hdlr(aktualizr);
1030 aktualizr.Initialize();
1033 boost::optional<Uptane::Target> current_version;
1034 boost::optional<Uptane::Target> pending_version;
1036 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
1038 EXPECT_FALSE(!!pending_version);
1039 EXPECT_FALSE(!!current_version);
1041 aktualizr.UptaneCycle();
1042 aktualizr.uptane_client()->completeInstall();
1044 EXPECT_TRUE(event_hdlr.checkReceivedEvents(expected_event_order));
1045 EXPECT_FALSE(aktualizr.uptane_client()->hasPendingUpdates());
1046 EXPECT_TRUE(http_server_mock->checkReceivedReports(expected_report_order));
1047 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
1048 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(secondary_ecu_id));
1050 LOG_INFO << http_server_mock->last_manifest;
1051 Json::Value installation_report = http_server_mock->last_manifest[
"signed"][
"installation_report"][
"report"];
1052 EXPECT_EQ(installation_report[
"items"][0][
"result"][
"code"].asString(),
"PRIMFAIL");
1053 EXPECT_EQ(installation_report[
"items"][1][
"result"][
"code"].asString(),
"SECFAIL");
1054 EXPECT_EQ(installation_report[
"result"][
"code"].asString(),
"primary_hw:PRIMFAIL|secondary_hw:SECFAIL");
1058 std::string correlation_id;
1062 EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
1064 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
1065 EXPECT_FALSE(storage->loadEcuInstallationResults(&ecu_installation_res));
1066 EXPECT_EQ(ecu_installation_res.size(), 0);
1068 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
1072 EXPECT_FALSE(!!current_version);
1073 EXPECT_FALSE(!!pending_version);
1075 fault_injection_disable(
"fake_package_install");
1076 fault_injection_disable(sec_fault_name.c_str());
1085 auto http_server_mock = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1086 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
1087 auto storage = INvStorage::newStorage(conf.storage);
1089 fault_injection_init();
1090 fiu_enable(
"secondary_putmetadata", 1,
nullptr, 0);
1096 std::promise<void> promise;
1099 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1100 if (
event->variant !=
"AllInstallsComplete") {
1104 ev_state.result = installs_complete->result;
1106 ev_state.promise.set_value();
1112 auto status = ev_state.promise.get_future().wait_for(std::chrono::seconds(20));
1113 if (status != std::future_status::ready) {
1114 FAIL() <<
"Timed out waiting for installation to complete.";
1117 ASSERT_FALSE(ev_state.result.dev_report.isSuccess());
1119 fiu_disable(
"secondary_putmetadata");
1122 #endif // FIU_ENABLE 1136 TEST(
Aktualizr, AutoRebootAfterUpdate) {
1138 auto http = std::make_shared<HttpFakePutCounter>(temp_dir.Path(), fake_meta_dir);
1139 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1140 conf.pacman.fake_need_reboot =
true;
1141 conf.uptane.force_install_completion =
true;
1142 conf.uptane.polling_sec = 0;
1146 auto storage = INvStorage::newStorage(conf.storage);
1150 auto aktualizr_cycle_thread = aktualizr.
RunForever();
1151 auto aktualizr_cycle_thread_status = aktualizr_cycle_thread.wait_for(std::chrono::seconds(20));
1154 EXPECT_EQ(aktualizr_cycle_thread_status, std::future_status::ready);
1155 EXPECT_TRUE(aktualizr.uptane_client()->isInstallCompletionRequired());
1160 auto storage = INvStorage::newStorage(conf.storage);
1166 EXPECT_EQ(update_res.status, result::UpdateStatus::kNoUpdatesAvailable);
1169 boost::optional<Uptane::Target> current_target;
1170 boost::optional<Uptane::Target> pending_target;
1171 storage->loadPrimaryInstalledVersions(¤t_target, &pending_target);
1172 EXPECT_TRUE(!!current_target);
1173 EXPECT_FALSE(!!pending_target);
1174 EXPECT_EQ(http->manifest_sends, 3);
1184 TEST(
Aktualizr, FullMultipleSecondaries) {
1186 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"multisec", fake_meta_dir);
1187 Config conf(
"tests/config/basic.toml");
1188 conf.provision.primary_ecu_serial =
"testecuserial";
1189 conf.provision.primary_ecu_hardware_id =
"testecuhwid";
1190 conf.storage.path = temp_dir.Path();
1191 conf.pacman.images_path = temp_dir.Path() /
"images";
1192 conf.tls.server = http->tls_server;
1193 conf.uptane.director_server = http->tls_server +
"/director";
1194 conf.uptane.repo_server = http->tls_server +
"/repo";
1197 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"sec_serial1",
"sec_hw1");
1199 auto storage = INvStorage::newStorage(conf.storage);
1201 UptaneTestCommon::addDefaultSecondary(conf, temp_dir2,
"sec_serial2",
"sec_hw2");
1202 ASSERT_NO_THROW(aktualizr.
AddSecondary(std::make_shared<Primary::VirtualSecondary>(
1203 Primary::VirtualSecondaryConfig::create_from_file(conf.uptane.secondary_config_file)[0])));
1208 bool allcomplete{
false};
1209 bool manifest{
false};
1210 std::future<void> future;
1211 std::promise<void> promise;
1213 ev_state.future = ev_state.promise.get_future();
1215 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1216 if (
event->variant ==
"InstallStarted") {
1218 }
else if (
event->variant ==
"InstallTargetComplete") {
1219 ++ev_state.complete;
1220 }
else if (
event->variant ==
"AllInstallsComplete") {
1221 ev_state.allcomplete =
true;
1222 }
else if (
event->variant ==
"PutManifestComplete") {
1223 ev_state.manifest =
true;
1227 if (ev_state.allcomplete && ev_state.complete == 2 && ev_state.manifest) {
1228 ev_state.promise.set_value();
1236 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1237 if (status != std::future_status::ready) {
1238 FAIL() <<
"Timed out waiting for installation to complete.";
1241 EXPECT_EQ(ev_state.started, 2);
1242 EXPECT_EQ(ev_state.complete, 2);
1244 const Json::Value manifest = http->last_manifest[
"signed"];
1245 const Json::Value manifest_versions = manifest[
"ecu_version_manifests"];
1248 EXPECT_EQ(manifest_versions[
"sec_serial1"][
"signed"][
"installed_image"][
"filepath"].asString(),
1249 "secondary_firmware.txt");
1250 EXPECT_EQ(manifest_versions[
"sec_serial1"][
"signed"][
"installed_image"][
"fileinfo"][
"length"].asUInt(), 15);
1251 EXPECT_EQ(manifest_versions[
"sec_serial2"][
"signed"][
"installed_image"][
"filepath"].asString(),
1252 "secondary_firmware2.txt");
1253 EXPECT_EQ(manifest_versions[
"sec_serial2"][
"signed"][
"installed_image"][
"fileinfo"][
"length"].asUInt(), 21);
1256 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"].size(), 2);
1257 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"][0][
"ecu"].asString(),
"sec_serial1");
1258 EXPECT_TRUE(manifest[
"installation_report"][
"report"][
"items"][0][
"result"][
"success"].asBool());
1259 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"][1][
"ecu"].asString(),
"sec_serial2");
1260 EXPECT_TRUE(manifest[
"installation_report"][
"report"][
"items"][1][
"result"][
"success"].asBool());
1268 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"noupdates", fake_meta_dir);
1269 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1271 auto storage = INvStorage::newStorage(conf.storage);
1275 size_t num_events{0};
1276 std::future<void> future;
1277 std::promise<void> promise;
1279 ev_state.future = ev_state.promise.get_future();
1281 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1285 LOG_INFO <<
"Got " <<
event->variant;
1286 switch (ev_state.num_events) {
1288 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1290 EXPECT_EQ(targets_event->result.ecus_count, 0);
1291 EXPECT_EQ(targets_event->result.updates.size(), 0);
1292 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
1296 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1298 EXPECT_EQ(targets_event->result.ecus_count, 0);
1299 EXPECT_EQ(targets_event->result.updates.size(), 0);
1300 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
1301 ev_state.promise.set_value();
1306 FAIL() <<
"Unexpected events!";
1308 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1309 ASSERT_EQ(
event->variant,
"");
1311 ++ev_state.num_events;
1318 EXPECT_EQ(result.ecus_count, 0);
1319 EXPECT_EQ(result.updates.size(), 0);
1320 EXPECT_EQ(result.status, result::UpdateStatus::kNoUpdatesAvailable);
1324 EXPECT_EQ(result.ecus_count, 0);
1325 EXPECT_EQ(result.updates.size(), 0);
1326 EXPECT_EQ(result.status, result::UpdateStatus::kNoUpdatesAvailable);
1328 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1329 if (status != std::future_status::ready) {
1330 FAIL() <<
"Timed out waiting for metadata to be fetched.";
1333 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1344 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1345 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1347 auto storage = INvStorage::newStorage(conf.storage);
1351 size_t num_events{0};
1352 std::future<void> future;
1353 std::promise<void> promise;
1355 ev_state.future = ev_state.promise.get_future();
1357 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1361 LOG_INFO <<
"Got " <<
event->variant;
1362 switch (ev_state.num_events) {
1364 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1366 EXPECT_EQ(downloads_complete->result.updates.size(), 0);
1367 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kError);
1371 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1373 EXPECT_EQ(targets_event->result.ecus_count, 2);
1374 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1375 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1376 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1377 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1382 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
1384 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1385 download_event->update.filename() ==
"secondary_firmware.txt");
1386 EXPECT_TRUE(download_event->success);
1390 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1392 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1393 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1394 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1395 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1396 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1397 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1398 ev_state.promise.set_value();
1403 FAIL() <<
"Unexpected events!";
1405 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1406 ASSERT_EQ(
event->variant,
"");
1408 ++ev_state.num_events;
1415 EXPECT_EQ(result.updates.size(), 0);
1416 EXPECT_EQ(result.status, result::DownloadStatus::kError);
1419 aktualizr.
Download(update_result.updates);
1421 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1422 if (status != std::future_status::ready) {
1423 FAIL() <<
"Timed out waiting for downloads to complete.";
1426 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1431 using Responses = std::vector<std::pair<std::string, HttpResponse>>;
1434 HttpDownloadFailure(
const boost::filesystem::path& test_dir_in,
const Responses& file_to_response, std::string flavor,
1435 const boost::filesystem::path& meta_dir_in)
1436 :
HttpFake(test_dir_in, flavor, meta_dir_in) {
1437 for (
auto resp : file_to_response) {
1438 url_to_response_[tls_server + target_dir_ + resp.first] = resp.second;
1442 HttpResponse download(
const std::string& url, curl_write_callback write_cb, curl_xferinfo_callback progress_cb,
1443 void* userp, curl_off_t from)
override {
1444 const auto found_response_it = url_to_response_.find(url);
1445 if (found_response_it == url_to_response_.end()) {
1446 return HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error");
1449 auto response = url_to_response_.at(url);
1450 if (response.isOk()) {
1451 return HttpFake::download(url, write_cb, progress_cb, userp, from);
1454 return url_to_response_[url];
1458 const std::string target_dir_{
"/repo/targets/"};
1459 std::map<std::string, HttpResponse> url_to_response_;
1471 class DownloadEventHandler {
1473 DownloadEventHandler(
Aktualizr& aktualizr) {
1474 functor_ = std::bind(&DownloadEventHandler::operator(),
this, std::placeholders::_1);
1478 void operator()(
const std::shared_ptr<event::BaseEvent>&
event) {
1479 ASSERT_NE(event,
nullptr);
1483 auto target_filename = download_target_complete_event->update.filename();
1484 download_status[target_filename] = download_target_complete_event->success;
1488 all_download_completed_status = all_download_complete_event->result;
1493 std::map<std::string, bool> download_status;
1497 std::function<void(std::shared_ptr<event::BaseEvent>)> functor_;
1501 HttpDownloadFailure::Responses downloadResponse;
1502 std::vector<std::pair<std::string, bool>> downloadResult;
1506 TestParams test_case_params[]{
1508 {{
"primary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")},
1509 {
"secondary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")}},
1510 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
false}},
1511 result::DownloadStatus::kError},
1513 {{
"primary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")},
1514 {
"secondary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")}},
1515 {{
"primary_firmware.txt",
true}, {
"secondary_firmware.txt",
false}},
1516 result::DownloadStatus::kPartialSuccess},
1518 {{
"primary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")},
1519 {
"secondary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")}},
1520 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
true}},
1521 result::DownloadStatus::kPartialSuccess}};
1523 for (
auto test_params : test_case_params) {
1526 auto http = std::make_shared<HttpDownloadFailure>(temp_dir.Path(), test_params.downloadResponse,
"hasupdates",
1528 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1529 auto storage = INvStorage::newStorage(conf.storage);
1532 DownloadEventHandler event_hdlr{aktualizr};
1536 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1539 for (
auto& expected_result : test_params.downloadResult) {
1541 ASSERT_NE(event_hdlr.download_status.find(expected_result.first), event_hdlr.download_status.end());
1542 EXPECT_EQ(event_hdlr.download_status.at(expected_result.first), expected_result.second);
1544 EXPECT_EQ(event_hdlr.all_download_completed_status.status, test_params.allDownloadsStatus);
1554 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1555 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1557 auto storage = INvStorage::newStorage(conf.storage);
1564 EXPECT_EQ(targets.size(), 0);
1566 aktualizr.
Download(update_result.updates).get();
1569 EXPECT_EQ(targets.size(), 2);
1577 EXPECT_EQ(targets.size(), 0);
1586 const boost::filesystem::path local_metadir = temp_dir /
"metadir";
1587 Utils::createDirectories(local_metadir, S_IRWXU);
1588 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", local_metadir /
"repo");
1590 UptaneRepo repo{local_metadir,
"2021-07-04T16:33:27Z",
"id0"};
1591 repo.generateRepo(KeyType::kED25519);
1592 const std::string hwid =
"primary_hw";
1593 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1594 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1597 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1598 auto storage = INvStorage::newStorage(conf.storage);
1602 boost::signals2::connection ac_conn =
1603 aktualizr.
SetSignalHandler(std::bind(targets_autoclean_cb, std::ref(aktualizr), std::placeholders::_1));
1608 aktualizr.
Download(update_result.updates).get();
1613 EXPECT_TRUE(install_result.dev_report.success);
1616 ASSERT_EQ(targets.size(), 1);
1617 EXPECT_EQ(targets[0].filename(),
"primary_firmware.txt");
1621 repo.emptyTargets();
1622 repo.addImage(fake_meta_dir /
"fake_meta/dummy_firmware.txt",
"dummy_firmware.txt", hwid,
"", {});
1623 repo.addTarget(
"dummy_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1628 aktualizr.
Download(update_result.updates).get();
1633 EXPECT_TRUE(install_result.dev_report.success);
1637 ASSERT_EQ(targets.size(), 2);
1641 repo.emptyTargets();
1642 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1643 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1648 aktualizr.
Download(update_result.updates).get();
1653 EXPECT_TRUE(install_result.dev_report.success);
1657 ASSERT_EQ(targets.size(), 2);
1661 repo.emptyTargets();
1662 repo.addImage(fake_meta_dir /
"fake_meta/secondary_firmware.txt",
"secondary_firmware.txt", hwid,
"", {});
1663 repo.addTarget(
"secondary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1668 aktualizr.
Download(update_result.updates).get();
1673 EXPECT_TRUE(install_result.dev_report.success);
1677 ASSERT_EQ(targets.size(), 2);
1680 Aktualizr::InstallationLog log = aktualizr.GetInstallationLog();
1681 ASSERT_EQ(log.size(), 2);
1683 EXPECT_EQ(log[0].installs.size(), 4);
1684 EXPECT_EQ(log[1].installs.size(), 0);
1686 std::vector<std::string> fws{
"primary_firmware.txt",
"dummy_firmware.txt",
"primary_firmware.txt",
1687 "secondary_firmware.txt"};
1688 for (
auto it = log[0].installs.begin(); it < log[0].installs.end(); it++) {
1689 auto idx =
static_cast<size_t>(it - log[0].installs.begin());
1690 EXPECT_EQ(it->filename(), fws[idx]);
1701 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1702 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1704 auto storage = INvStorage::newStorage(conf.storage);
1708 size_t num_events{0};
1709 std::vector<Uptane::Target> updates;
1710 std::future<void> future;
1711 std::promise<void> promise;
1713 ev_state.future = ev_state.promise.get_future();
1715 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1721 LOG_INFO <<
"Got " <<
event->variant;
1722 switch (ev_state.num_events) {
1724 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
1726 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 0);
1730 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1732 EXPECT_EQ(targets_event->result.ecus_count, 2);
1733 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1734 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1735 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1736 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1737 ev_state.updates = targets_event->result.updates;
1742 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
1744 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1745 download_event->update.filename() ==
"secondary_firmware.txt");
1746 EXPECT_TRUE(download_event->success);
1750 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1752 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1753 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1754 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1755 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1756 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1757 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1763 ASSERT_EQ(
event->variant,
"InstallStarted");
1765 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1771 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
1773 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1774 EXPECT_TRUE(install_complete->success);
1778 ASSERT_EQ(
event->variant,
"InstallStarted");
1780 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
1784 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
1786 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
1787 EXPECT_TRUE(install_complete->success);
1791 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
1793 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 2);
1794 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
1795 data::ResultCode::Numeric::kOk);
1796 EXPECT_EQ(installs_complete->result.ecu_reports[1].install_res.result_code.num_code,
1797 data::ResultCode::Numeric::kOk);
1798 ev_state.promise.set_value();
1803 FAIL() <<
"Unexpected events!";
1805 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1806 ASSERT_EQ(
event->variant,
"");
1808 ++ev_state.num_events;
1814 Json::Value primary_json;
1815 primary_json[
"hashes"][
"sha256"] =
"74e653bbf6c00a88b21f0992159b1002f5af38506e6d2fbc7eb9846711b2d75f";
1816 primary_json[
"hashes"][
"sha512"] =
1817 "91814ad1c13ebe2af8d65044893633c4c3ce964edb8cb58b0f357406c255f7be94f42547e108b300346a42cd57662e4757b9d843b7acbc09" 1819 primary_json[
"length"] = 59;
1820 Uptane::Target primary_target(
"primary_firmware.txt", primary_json);
1822 Json::Value secondary_json;
1823 secondary_json[
"hashes"][
"sha256"] =
"1bbb15aa921ffffd5079567d630f43298dbe5e7cbc1b14e0ccdd6718fde28e47";
1824 secondary_json[
"hashes"][
"sha512"] =
1825 "7dbae4c36a2494b731a9239911d3085d53d3e400886edb4ae2b9b78f40bda446649e83ba2d81653f614cc66f5dd5d4dbd95afba854f148af" 1827 secondary_json[
"length"] = 15;
1828 Uptane::Target secondary_target(
"secondary_firmware.txt", secondary_json);
1832 EXPECT_EQ(result.ecu_reports.size(), 0);
1834 EXPECT_THROW(aktualizr.
OpenStoredTarget(primary_target).get(), std::runtime_error)
1835 <<
"Primary firmware is present in storage before the download";
1836 EXPECT_THROW(aktualizr.
OpenStoredTarget(secondary_target).get(), std::runtime_error)
1837 <<
"Secondary firmware is present in storage before the download";
1840 aktualizr.
Download(update_result.updates).get();
1842 <<
"Primary firmware is not present in storage after the download";
1844 <<
"Secondary firmware is not present in storage after the download";
1847 aktualizr.
Install(update_result.updates);
1849 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1850 if (status != std::future_status::ready) {
1851 FAIL() <<
"Timed out waiting for installation to complete.";
1862 TEST(
Aktualizr, ReportDownloadProgress) {
1866 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1867 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1868 auto storage = INvStorage::newStorage(conf.storage);
1871 unsigned int report_counter = {0};
1872 std::shared_ptr<const event::DownloadProgressReport> lastProgressReport{
nullptr};
1874 std::function<void(std::shared_ptr<event::BaseEvent>
event)> report_event_hdlr =
1875 [&](
const std::shared_ptr<event::BaseEvent>&
event) {
1876 ASSERT_NE(event,
nullptr);
1882 ASSERT_NE(download_progress_event,
nullptr);
1883 ASSERT_NE(download_progress_event.get(),
nullptr);
1884 if (lastProgressReport) {
1885 EXPECT_GE(download_progress_event->progress, lastProgressReport->progress);
1887 lastProgressReport = download_progress_event;
1895 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1898 update_result.updates.pop_back();
1901 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
1903 ASSERT_NE(lastProgressReport,
nullptr);
1904 ASSERT_NE(lastProgressReport.get(),
nullptr);
1905 EXPECT_TRUE(event::DownloadProgressReport::isDownloadCompleted(*lastProgressReport));
1906 EXPECT_GT(report_counter, 1);
1911 HttpFakeCampaign(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
1912 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
1914 HttpResponse get(
const std::string& url, int64_t maxsize)
override {
1915 EXPECT_NE(url.find(
"campaigner/"), std::string::npos);
1916 boost::filesystem::path path = meta_dir / url.substr(tls_server.size() + strlen(
"campaigner/"));
1918 if (url.find(
"campaigner/campaigns") != std::string::npos) {
1919 return HttpResponse(Utils::readFile(path.parent_path() /
"campaigner/campaigns.json"), 200, CURLE_OK,
"");
1921 return HttpFake::get(url, maxsize);
1924 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
1926 for (
auto it = data.begin(); it != data.end(); it++) {
1928 auto id = ev[
"eventType"][
"id"];
1929 if (
id ==
"campaign_accepted" ||
id ==
"campaign_declined" ||
id ==
"campaign_postponed") {
1930 seen_events.push_back(ev);
1936 std::vector<Json::Value> seen_events;
1941 bool campaignaccept_seen{
false};
1942 bool campaigndecline_seen{
false};
1943 bool campaignpostpone_seen{
false};
1945 void handler(
const std::shared_ptr<event::BaseEvent>&
event) {
1946 std::cout <<
event->variant <<
"\n";
1947 if (event->variant ==
"CampaignCheckComplete") {
1949 EXPECT_EQ(concrete_event->result.campaigns.size(), 1);
1950 EXPECT_EQ(concrete_event->result.campaigns[0].name,
"campaign1");
1951 EXPECT_EQ(concrete_event->result.campaigns[0].id,
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
1952 EXPECT_EQ(concrete_event->result.campaigns[0].size, 62470);
1953 EXPECT_EQ(concrete_event->result.campaigns[0].autoAccept,
true);
1954 EXPECT_EQ(concrete_event->result.campaigns[0].description,
"this is my message to show on the device");
1955 }
else if (event->variant ==
"CampaignAcceptComplete") {
1956 campaignaccept_seen =
true;
1957 }
else if (event->variant ==
"CampaignDeclineComplete") {
1958 campaigndecline_seen =
true;
1959 }
else if (event->variant ==
"CampaignPostponeComplete") {
1960 campaignpostpone_seen =
true;
1981 TEST(
Aktualizr, CampaignCheckAndControl) {
1983 auto http = std::make_shared<HttpFakeCampaign>(temp_dir.Path(), fake_meta_dir);
1984 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1989 auto storage = INvStorage::newStorage(conf.storage);
1991 aktualizr.
SetSignalHandler(std::bind(&CampaignEvents::handler, &campaign_events, std::placeholders::_1));
1996 EXPECT_EQ(result.campaigns.size(), 1);
1999 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Accept).get();
2001 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Decline).get();
2003 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Postpone).get();
2006 ASSERT_EQ(http->seen_events.size(), 3);
2007 for (
const auto& ev : http->seen_events) {
2008 EXPECT_EQ(ev[
"event"][
"campaignId"],
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
2010 EXPECT_TRUE(campaign_events.campaignaccept_seen);
2011 EXPECT_TRUE(campaign_events.campaigndecline_seen);
2012 EXPECT_TRUE(campaign_events.campaignpostpone_seen);
2017 HttpFakeNoCorrelationId(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2018 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2020 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
2022 for (
const Json::Value&
event : data) {
2024 EXPECT_EQ(
event[
"event"][
"correlationId"].asString(),
"");
2029 unsigned int events_seen{0};
2036 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/repo", meta_dir.Path() /
"repo");
2037 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/director", meta_dir.Path() /
"director");
2038 auto http = std::make_shared<HttpFakeNoCorrelationId>(temp_dir.Path(), meta_dir.Path());
2043 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2045 auto storage = INvStorage::newStorage(conf.storage);
2050 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
2053 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
2056 for (
const auto& r : install_result.ecu_reports) {
2057 EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
2061 EXPECT_EQ(http->events_seen, 8);
2066 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", fake_meta_dir);
2069 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2071 auto storage = INvStorage::newStorage(conf.storage);
2075 Json::Value custom = Utils::parseJSON(R
"({"test_field":"test_value"})"); 2076 ASSERT_EQ(custom["test_field"].asString(),
"test_value");
2077 ASSERT_EQ(
true, aktualizr.
SendManifest(custom).get()) <<
"Failed to upload manifest with HttpFake server";
2078 EXPECT_EQ(http->last_manifest[
"signed"][
"custom"], custom);
2082 TEST(
Aktualizr, CustomInstallationRawReport) {
2084 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdate", fake_meta_dir);
2086 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2087 auto storage = INvStorage::newStorage(conf.storage);
2095 auto custom_raw_report =
"Installation's custom raw report!";
2098 EXPECT_EQ(http->last_manifest[
"signed"][
"installation_report"][
"report"][
"raw_report"], custom_raw_report);
2112 std::function<void(std::shared_ptr<event::BaseEvent>)> Signal() {
2113 return std::bind(&CountUpdateCheckEvents::count,
this, std::placeholders::_1);
2116 void count(std::shared_ptr<event::BaseEvent>
event) {
2117 std::cout <<
event->variant <<
"\n";
2118 if (event->variant ==
"UpdateCheckComplete") {
2120 if (std::static_pointer_cast<event::UpdateCheckComplete>(event)->result.status == result::UpdateStatus::kError) {
2126 int total_events()
const {
return total_events_; }
2127 int error_events()
const {
return error_events_; }
2130 int total_events_{0};
2131 int error_events_{0};
2136 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
2138 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2140 auto storage = INvStorage::newStorage(conf.storage);
2145 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2147 std::vector<std::future<result::UpdateCheck>> futures;
2148 for (
int i = 0; i < 5; ++i) {
2152 for (
auto& f : futures) {
2157 EXPECT_EQ(counter.total_events(), 5);
2163 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter2.Signal());
2166 std::future<result::UpdateCheck> ft = aktualizr.
CheckUpdates();
2167 for (
int i = 0; i < 99; ++i) {
2172 EXPECT_LT(counter2.total_events(), 100);
2173 EXPECT_GT(counter2.total_events(), 0);
2178 HttpPutManifestFail(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2179 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2180 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
2187 TEST(
Aktualizr, UpdateCheckCompleteError) {
2189 auto http = std::make_shared<HttpPutManifestFail>(temp_dir.Path(), fake_meta_dir);
2191 Config conf = UptaneTestCommon::makeTestConfig(temp_dir,
"http://updatefail");
2193 auto storage = INvStorage::newStorage(conf.storage);
2197 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2200 EXPECT_EQ(result.status, result::UpdateStatus::kError);
2201 EXPECT_EQ(counter.error_events(), 1);
2211 HttpFakePauseCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2212 :
HttpFake(test_dir_in,
"noupdates", meta_dir_in) {}
2214 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
2216 for (
const Json::Value&
event : data) {
2218 std::string event_type =
event[
"eventType"][
"id"].asString();
2220 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
2221 if (events_seen == 1) {
2222 EXPECT_EQ(event_type,
"DevicePaused");
2223 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2224 }
else if (events_seen == 2) {
2225 EXPECT_EQ(event_type,
"DeviceResumed");
2226 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2228 std::cout <<
"Unexpected event";
2235 unsigned int events_seen{0};
2240 auto http = std::make_shared<HttpFakePauseCounter>(temp_dir.Path(), fake_meta_dir);
2241 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2243 auto storage = INvStorage::newStorage(conf.storage);
2248 std::promise<void> end_promise{};
2249 size_t n_events = 0;
2250 std::atomic_bool is_paused{
false};
2251 std::function<void(std::shared_ptr<event::BaseEvent>)> cb = [&end_promise, &n_events, &mutex,
2252 &is_paused](std::shared_ptr<event::BaseEvent>
event) {
2255 ASSERT_EQ(event->variant,
"UpdateCheckComplete");
2258 std::lock_guard<std::mutex> guard(mutex);
2260 ASSERT_EQ(event->variant,
"UpdateCheckComplete");
2262 EXPECT_FALSE(is_paused);
2263 end_promise.set_value();
2267 FAIL() <<
"Unexpected event";
2277 std::lock_guard<std::mutex> guard(mutex);
2278 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kSuccess);
2282 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kAlreadyPaused);
2287 std::this_thread::sleep_for(std::chrono::seconds(1));
2290 std::lock_guard<std::mutex> guard(mutex);
2292 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kSuccess);
2295 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kAlreadyRunning);
2297 auto status = end_promise.get_future().wait_for(std::chrono::seconds(20));
2298 if (status != std::future_status::ready) {
2299 FAIL() <<
"Timed out waiting for UpdateCheck event";
2303 const std::string custom_hwinfo =
2304 R
"([{"description":"ECU1","ECU P/N":"AAA","HW P/N":"BBB","HW Version":"1.234", 2305 "SW P/N":"CCC","SW Version":"4.321","ECU Serial":"AAA-BBB-CCC"}, 2306 {"description":"ECU2","ECU P/N":"ZZZ","HW P/N":"XXX","HW Version":"9.876", 2307 "SW P/N":"YYY","SW Version":"6.789","ECU Serial":"VVV-NNN-MMM"}])"; 2311 HttpSystemInfo(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2312 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2314 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
2315 if (url.find(hwinfo_ep_) == url.length() - hwinfo_ep_.length()) {
2316 if (info_count_ == 0) {
2317 EXPECT_TRUE(data.isObject());
2318 EXPECT_TRUE(data.isMember(
"description"));
2319 }
else if (info_count_ == 1) {
2320 auto hwinfo = Utils::parseJSON(custom_hwinfo);
2321 EXPECT_EQ(hwinfo, data);
2325 }
else if (url.find(
"/manifest") != std::string::npos) {
2328 return HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found");
2334 std::string hwinfo_ep_{
"/system_info"};
2339 auto http = std::make_shared<HttpSystemInfo>(temp_dir.Path(), fake_meta_dir);
2340 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2342 auto storage = INvStorage::newStorage(conf.storage);
2348 auto hwinfo = Utils::parseJSON(custom_hwinfo);
2353 int main(
int argc,
char** argv) {
2354 ::testing::InitGoogleTest(&argc, argv);
2356 std::cerr <<
"Error: " << argv[0] <<
" requires the path to the base directory of Uptane repos.\n";
2357 return EXIT_FAILURE;
2359 uptane_repos_dir = argv[1];
2362 logger_set_threshold(boost::log::trivial::trace);
2365 fake_meta_dir = tmp_dir.Path();
2368 return RUN_ALL_TESTS();
DownloadStatus
Status of an update download.
All ECU installation attempts for an update have completed.
An update is available for download from the server.
void AddSecondary(const std::shared_ptr< SecondaryInterface > &secondary)
Add new Secondary to aktualizr.
Container for information about downloading an update.
A manifest has been sent to the server.
The server has been queried for available campaigns.
A report for a download in progress.
std::vector< Uptane::Target > GetStoredTargets()
Get list of targets currently in storage.
An ECU has begun installation of an update.
bool UptaneCycle()
Synchronously run an Uptane cycle: check for updates, download any new targets, install them...
result::Pause Resume()
Resume the library operations.
Configuration object for an aktualizr instance running on a Primary ECU.
std::future< void > RunForever(const Json::Value &custom_hwinfo=Json::nullValue)
Asynchronously run aktualizr indefinitely until Shutdown is called.
void DeleteStoredTarget(const Uptane::Target &target)
Delete a stored target from storage.
void Shutdown()
Shuts down currently running RunForever() method.
Package installation failed.
std::future< result::Download > Download(const std::vector< Uptane::Target > &updates)
Download targets.
std::future< result::UpdateCheck > CheckUpdates()
Fetch Uptane metadata and check for updates.
bool SetInstallationRawReport(const std::string &custom_raw_report)
SetInstallationRawReport allows setting a custom raw report field in the device installation result...
All targets for an update have been downloaded.
result::Pause Pause()
Pause the library operations.
An installation attempt on an ECU has completed.
std::future< result::Install > Install(const std::vector< Uptane::Target > &updates)
Install targets.
std::future< result::CampaignCheck > CampaignCheck()
Check for campaigns.
std::ifstream OpenStoredTarget(const Uptane::Target &target)
Get target downloaded in Download call.
Container for information about installing an update.
Container for information about available updates.
std::future< void > SendDeviceData(const Json::Value &custom_hwinfo=Json::nullValue)
Send local device data to the server.
boost::signals2::connection SetSignalHandler(const SigHandler &handler)
Provide a function to receive event notifications.
Results of libaktualizr API calls.
std::future< bool > SendManifest(const Json::Value &custom=Json::nullValue)
Send installation report to the backend.
This class provides the main APIs necessary for launching and controlling libaktualizr.
void Initialize()
Initialize aktualizr.
std::future< void > CampaignControl(const std::string &campaign_id, campaign::Cmd cmd)
Act on campaign: accept, decline or postpone.
A target has been downloaded.