1 #include <gtest/gtest.h> 6 #include <unordered_map> 9 #include <boost/filesystem.hpp> 10 #include "json/json.h" 12 #include "config/config.h" 14 #include "primary/aktualizr.h" 15 #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(),
51 ecu_config.partial_verifying =
false;
52 ecu_config.full_client_dir = client_dir;
53 ecu_config.ecu_serial =
"ecuserial3";
54 ecu_config.ecu_hardware_id =
"hw_id3";
55 ecu_config.ecu_private_key =
"sec.priv";
56 ecu_config.ecu_public_key =
"sec.pub";
57 ecu_config.firmware_path = client_dir /
"firmware.txt";
58 ecu_config.target_name_path = client_dir /
"firmware_name.txt";
59 ecu_config.metadata_path = client_dir /
"secondary_metadata";
69 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"noupdates", fake_meta_dir);
70 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
72 auto storage = INvStorage::newStorage(conf.storage);
77 std::future<void> future;
78 std::promise<void> promise;
80 ev_state.future = ev_state.promise.get_future();
82 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
86 LOG_INFO <<
"Got " <<
event->variant;
87 switch (ev_state.num_events) {
89 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
91 EXPECT_EQ(targets_event->result.ecus_count, 0);
92 EXPECT_EQ(targets_event->result.updates.size(), 0);
93 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
97 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
99 EXPECT_EQ(targets_event->result.ecus_count, 0);
100 EXPECT_EQ(targets_event->result.updates.size(), 0);
101 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
102 ev_state.promise.set_value();
107 FAIL() <<
"Unexpected events!";
109 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
110 ASSERT_EQ(
event->variant,
"");
112 ++ev_state.num_events;
114 boost::signals2::connection conn = aktualizr.SetSignalHandler(f_cb);
116 aktualizr.Initialize();
117 aktualizr.UptaneCycle();
120 aktualizr.UptaneCycle();
121 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
122 if (status != std::future_status::ready) {
123 FAIL() <<
"Timed out waiting for metadata to be fetched.";
126 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
134 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"noupdates", fake_meta_dir);
135 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
137 auto storage = INvStorage::newStorage(conf.storage);
142 aktualizr.AddSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config));
144 aktualizr.Initialize();
147 storage->loadEcuSerials(&serials);
149 std::vector<std::string> expected_ecus = {
"CA:FE:A6:D2:84:9D",
"ecuserial3",
"secondary_ecu_serial"};
150 EXPECT_EQ(serials.size(), 3);
151 for (
const auto& ecu : serials) {
152 auto found = std::find(expected_ecus.begin(), expected_ecus.end(), ecu.first.ToString());
153 if (found != expected_ecus.end()) {
154 expected_ecus.erase(found);
156 FAIL() <<
"Unknown ecu: " << ecu.first.ToString();
159 EXPECT_EQ(expected_ecus.size(), 0);
161 ecu_config.ecu_serial =
"ecuserial4";
162 auto sec4 = std::make_shared<Primary::VirtualSecondary>(ecu_config);
163 EXPECT_THROW(aktualizr.AddSecondary(sec4), std::logic_error);
169 TEST(
Aktualizr, DeviceInstallationResult) {
171 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", fake_meta_dir);
172 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
174 auto storage = INvStorage::newStorage(conf.storage);
181 storage->storeEcuSerials(serials);
187 aktualizr.AddSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config));
189 aktualizr.Initialize();
197 aktualizr.uptane_client()->computeDeviceInstallationResult(&result,
nullptr);
198 auto res_json = result.toJson();
199 EXPECT_EQ(res_json[
"code"].asString(),
"primary_hw:INSTALL_FAILED");
200 EXPECT_EQ(res_json[
"success"],
false);
202 storage->saveEcuInstallationResult(
205 aktualizr.uptane_client()->computeDeviceInstallationResult(&result,
nullptr);
206 res_json = result.toJson();
207 EXPECT_EQ(res_json[
"code"].asString(),
"primary_hw:INSTALL_FAILED|hw_id3:SECOND_FAIL");
208 EXPECT_EQ(res_json[
"success"],
false);
213 HttpFakeEventCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
214 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
216 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
218 for (
const Json::Value&
event : data) {
220 std::string event_type =
event[
"eventType"][
"id"].asString();
221 if (event_type.find(
"Ecu") == 0) {
222 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
225 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
226 if (events_seen >= 1 && events_seen <= 4) {
227 EXPECT_TRUE(event_type ==
"EcuDownloadStarted" || event_type ==
"EcuDownloadCompleted");
228 }
else if (events_seen >= 5 && events_seen <= 8) {
229 EXPECT_TRUE(event_type ==
"EcuInstallationStarted" || event_type ==
"EcuInstallationCompleted");
231 std::cout <<
"Unexpected event";
238 unsigned int events_seen{0};
247 auto http = std::make_shared<HttpFakeEventCounter>(temp_dir.Path(), fake_meta_dir);
248 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
250 auto storage = INvStorage::newStorage(conf.storage);
254 size_t num_events{0};
255 std::future<void> future;
256 std::promise<void> promise;
258 ev_state.future = ev_state.promise.get_future();
260 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
264 LOG_INFO <<
"Got " <<
event->variant;
265 switch (ev_state.num_events) {
267 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
269 EXPECT_EQ(targets_event->result.ecus_count, 2);
270 EXPECT_EQ(targets_event->result.updates.size(), 2u);
271 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
272 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
273 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
278 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
280 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
281 download_event->update.filename() ==
"secondary_firmware.txt");
282 EXPECT_TRUE(download_event->success);
286 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
288 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
289 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
290 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
291 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
292 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
293 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
299 ASSERT_EQ(
event->variant,
"InstallStarted");
301 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
307 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
309 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
310 EXPECT_TRUE(install_complete->success);
314 ASSERT_EQ(
event->variant,
"InstallStarted");
316 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
320 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
322 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
323 EXPECT_TRUE(install_complete->success);
327 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
329 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 2);
330 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
331 data::ResultCode::Numeric::kOk);
332 EXPECT_EQ(installs_complete->result.ecu_reports[1].install_res.result_code.num_code,
333 data::ResultCode::Numeric::kOk);
337 ASSERT_EQ(
event->variant,
"PutManifestComplete");
339 EXPECT_TRUE(put_complete->success);
340 ev_state.promise.set_value();
345 FAIL() <<
"Unexpected events!";
347 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
348 ASSERT_EQ(
event->variant,
"");
350 ++ev_state.num_events;
356 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
357 if (status != std::future_status::ready) {
358 FAIL() <<
"Timed out waiting for installation to complete.";
360 EXPECT_EQ(http->events_seen, 8);
365 HttpFakeSplit(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
366 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
368 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
370 for (
const Json::Value&
event : data) {
372 std::string event_type =
event[
"eventType"][
"id"].asString();
373 if (event_type.find(
"Ecu") == 0) {
374 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
377 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
378 switch (events_seen) {
381 EXPECT_TRUE(event_type ==
"EcuDownloadStarted");
385 EXPECT_TRUE(event_type ==
"EcuDownloadCompleted");
389 EXPECT_TRUE(event_type ==
"EcuInstallationStarted");
393 EXPECT_TRUE(event_type ==
"EcuInstallationCompleted");
396 std::cout <<
"Unexpected event";
404 unsigned int events_seen{0};
419 auto http = std::make_shared<HttpFakeSplit>(temp_dir.Path(), fake_meta_dir);
420 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
422 auto storage = INvStorage::newStorage(conf.storage);
426 size_t num_events{0};
427 std::future<void> future;
428 std::promise<void> promise;
430 ev_state.future = ev_state.promise.get_future();
432 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
436 LOG_INFO <<
"Got " <<
event->variant;
437 switch (ev_state.num_events) {
439 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
441 EXPECT_EQ(targets_event->result.ecus_count, 2);
442 EXPECT_EQ(targets_event->result.updates.size(), 2u);
443 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
444 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
445 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
449 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
451 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt");
452 EXPECT_TRUE(download_event->success);
456 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
458 EXPECT_EQ(downloads_complete->result.updates.size(), 1);
459 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt");
460 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
466 ASSERT_EQ(
event->variant,
"InstallStarted");
468 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
474 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
476 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
477 EXPECT_TRUE(install_complete->success);
481 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
483 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 1);
484 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
485 data::ResultCode::Numeric::kOk);
489 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
491 EXPECT_TRUE(download_event->update.filename() ==
"secondary_firmware.txt");
492 EXPECT_TRUE(download_event->success);
496 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
498 EXPECT_EQ(downloads_complete->result.updates.size(), 1);
499 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt");
500 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
504 ASSERT_EQ(
event->variant,
"InstallStarted");
506 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
510 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
512 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
513 EXPECT_TRUE(install_complete->success);
517 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
519 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 1);
520 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
521 data::ResultCode::Numeric::kOk);
525 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
527 EXPECT_EQ(targets_event->result.ecus_count, 0);
528 EXPECT_EQ(targets_event->result.updates.size(), 0);
529 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
530 ev_state.promise.set_value();
535 FAIL() <<
"Unexpected events!";
537 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
538 ASSERT_EQ(
event->variant,
"");
540 ++ev_state.num_events;
546 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
547 ASSERT_EQ(update_result.ecus_count, 2);
551 ASSERT_EQ(download_result.status, result::DownloadStatus::kSuccess);
552 aktualizr.
Install(download_result.updates);
554 download_result = aktualizr.
Download({update_result.updates[1]}).
get();
555 ASSERT_EQ(download_result.status, result::DownloadStatus::kSuccess);
556 aktualizr.
Install(download_result.updates);
559 ASSERT_EQ(update_result.status, result::UpdateStatus::kNoUpdatesAvailable);
561 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
562 if (status != std::future_status::ready) {
563 FAIL() <<
"Timed out waiting for installation to complete.";
565 EXPECT_EQ(http->events_seen, 8);
570 HttpFakePutCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
571 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
573 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
574 if (url.find(
"/manifest") != std::string::npos) {
577 return HttpFake::put(url, data);
580 HttpResponse handle_event(
const std::string& url,
const Json::Value& data)
override {
583 for (
const Json::Value&
event : data) {
584 events.push_back(
event);
589 size_t count_event_with_type(
const std::string& event_type) {
590 auto c = std::count_if(events.cbegin(), events.cend(), [&event_type](
const Json::Value& v) {
591 return v[
"eventType"][
"id"].asString() == event_type;
593 return static_cast<size_t>(c);
596 unsigned int manifest_sends{0};
597 std::vector<Json::Value> events;
620 TEST(
Aktualizr, FullWithUpdatesNeedReboot) {
622 auto http = std::make_shared<HttpFakePutCounter>(temp_dir.Path(), fake_meta_dir);
623 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
624 conf.pacman.fake_need_reboot =
true;
628 auto storage = INvStorage::newStorage(conf.storage);
635 boost::optional<Uptane::Target> pending_target;
636 storage->loadPrimaryInstalledVersions(
nullptr, &pending_target);
637 EXPECT_TRUE(!!pending_target);
641 EXPECT_EQ(http->manifest_sends, 1);
642 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationStarted"), 2);
643 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationApplied"), 1);
644 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationCompleted"), 1);
648 auto storage = INvStorage::newStorage(conf.storage);
653 boost::optional<Uptane::Target> pending_target;
654 storage->loadPrimaryInstalledVersions(
nullptr, &pending_target);
655 EXPECT_TRUE(!!pending_target);
658 EXPECT_EQ(update_res.status, result::UpdateStatus::kError);
661 boost::filesystem::remove(conf.bootloader.reboot_sentinel_dir / conf.bootloader.reboot_sentinel_name);
665 EXPECT_EQ(http->manifest_sends, 1);
666 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationCompleted"), 1);
670 auto storage = INvStorage::newStorage(conf.storage);
675 EXPECT_EQ(update_res.status, result::UpdateStatus::kNoUpdatesAvailable);
678 boost::optional<Uptane::Target> current_target;
679 boost::optional<Uptane::Target> pending_target;
680 storage->loadPrimaryInstalledVersions(¤t_target, &pending_target);
681 EXPECT_TRUE(!!current_target);
682 EXPECT_FALSE(!!pending_target);
685 boost::optional<Uptane::Target> sec_current_target;
686 boost::optional<Uptane::Target> sec_pending_target;
687 storage->loadInstalledVersions(
"secondary_ecu_serial", &sec_current_target, &sec_pending_target);
688 EXPECT_TRUE(!!sec_current_target);
689 EXPECT_FALSE(!!sec_pending_target);
693 EXPECT_EQ(http->manifest_sends, 3);
694 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationCompleted"), 2);
697 for (
const Json::Value&
event : http->events) {
698 std::cout <<
"got event " <<
event[
"eventType"][
"id"].asString() <<
"\n";
699 EXPECT_EQ(event[
"event"][
"correlationId"].asString(),
"id0");
705 class HttpInstallationFailed :
public HttpFake {
707 HttpInstallationFailed(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
708 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
710 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
713 for (
auto& event_data : data) {
714 auto event_id = event_data[
"eventType"][
"id"].asString();
715 auto ecu = event_data[
"event"][
"ecu"].asString();
716 auto correlationID = event_data[
"event"][
"correlationId"].asString();
718 if (event_id ==
"EcuInstallationCompleted") {
719 install_completion_status_[ecu] = event_data[
"event"][
"success"].asBool();
721 report_events_.push_back(event_id);
726 bool checkReceivedReports(
const std::vector<std::string>& expected_event_order) {
728 auto received_event_it = report_events_.begin();
730 for (
auto& expected_event : expected_event_order) {
731 auto received_event = *received_event_it;
732 if (expected_event != received_event) {
741 bool wasInstallSuccessful(
const std::string& ecu_serial)
const {
742 auto find_it = install_completion_status_.find(ecu_serial);
743 if (find_it == install_completion_status_.end()) {
746 return (*find_it).second;
749 void clearReportEvents() { report_events_.clear(); }
752 std::vector<std::string> report_events_;
753 std::unordered_map<std::string, bool> install_completion_status_;
759 functor_ = std::bind(&EventHandler::operator(),
this, std::placeholders::_1);
763 void operator()(
const std::shared_ptr<event::BaseEvent>&
event) {
764 ASSERT_NE(event,
nullptr);
765 received_events_.push_back(event->variant);
768 bool checkReceivedEvents(
const std::vector<std::string>& expected_event_order) {
770 auto received_event_it = received_events_.begin();
772 for (
auto& expected_event : expected_event_order) {
773 auto received_event = *received_event_it;
774 if (expected_event != received_event) {
779 if (received_event ==
"DownloadProgressReport") {
780 while (*(++received_event_it) ==
"DownloadProgressReport") {
790 std::function<void(std::shared_ptr<event::BaseEvent>)> functor_;
791 std::vector<std::string> received_events_{};
806 auto http_server_mock = std::make_shared<HttpInstallationFailed>(temp_dir.Path(), fake_meta_dir);
807 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
808 conf.pacman.fake_need_reboot =
true;
809 conf.uptane.force_install_completion =
true;
810 conf.uptane.polling_sec = 0;
811 auto storage = INvStorage::newStorage(conf.storage);
813 std::vector<std::string> expected_event_order = {
814 "SendDeviceDataComplete",
"UpdateCheckComplete",
"DownloadProgressReport",
"DownloadTargetComplete",
815 "DownloadProgressReport",
"DownloadTargetComplete",
"AllDownloadsComplete",
"InstallStarted",
816 "InstallTargetComplete",
"InstallStarted",
"InstallTargetComplete",
"AllInstallsComplete"};
818 std::vector<std::string> expected_report_order = {
819 "EcuDownloadStarted",
"EcuDownloadCompleted",
"EcuDownloadStarted",
"EcuDownloadCompleted",
820 "EcuInstallationStarted",
"EcuInstallationApplied",
"EcuInstallationStarted",
"EcuInstallationCompleted"};
822 const std::string primary_ecu_id =
"CA:FE:A6:D2:84:9D";
823 const std::string secondary_ecu_id =
"secondary_ecu_serial";
828 EventHandler event_hdlr(aktualizr);
832 boost::optional<Uptane::Target> current_version;
833 boost::optional<Uptane::Target> pending_version;
834 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
838 EXPECT_FALSE(!!pending_version);
839 EXPECT_FALSE(!!current_version);
841 auto aktualizr_cycle_thread = aktualizr.
RunForever();
842 auto aktualizr_cycle_thread_status = aktualizr_cycle_thread.wait_for(std::chrono::seconds(20));
844 ASSERT_EQ(aktualizr_cycle_thread_status, std::future_status::ready);
845 EXPECT_TRUE(aktualizr.uptane_client()->isInstallCompletionRequired());
846 EXPECT_TRUE(event_hdlr.checkReceivedEvents(expected_event_order));
847 EXPECT_TRUE(aktualizr.uptane_client()->hasPendingUpdates());
848 EXPECT_TRUE(http_server_mock->checkReceivedReports(expected_report_order));
851 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
852 EXPECT_TRUE(http_server_mock->wasInstallSuccessful(secondary_ecu_id));
856 std::string correlation_id;
857 ASSERT_TRUE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
858 EXPECT_EQ(dev_installation_res.result_code.num_code, data::ResultCode::Numeric::kNeedCompletion);
860 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
861 ASSERT_TRUE(storage->loadEcuInstallationResults(&ecu_installation_res));
862 EXPECT_EQ(ecu_installation_res.size(), 2);
864 for (
const auto& ecu_install_res : ecu_installation_res) {
865 auto ecu_id = ecu_install_res.first.ToString();
867 if (ecu_id == primary_ecu_id) {
868 EXPECT_EQ(ecu_install_res.second.result_code.num_code, data::ResultCode::Numeric::kNeedCompletion);
869 EXPECT_EQ(ecu_install_res.second.success,
false);
870 EXPECT_EQ(ecu_install_res.second.description,
"Application successful, need reboot");
872 }
else if (ecu_id == secondary_ecu_id) {
873 EXPECT_EQ(ecu_install_res.second.result_code.num_code, data::ResultCode::Numeric::kOk);
874 EXPECT_EQ(ecu_install_res.second.success,
true);
875 EXPECT_EQ(ecu_install_res.second.description,
"");
878 FAIL() <<
"Unexpected ECU serial: " << ecu_install_res.first;
882 pending_version = boost::none;
883 current_version = boost::none;
885 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
886 EXPECT_FALSE(!!current_version);
887 EXPECT_TRUE(!!pending_version);
888 EXPECT_TRUE(pending_version->IsValid());
890 pending_version = boost::none;
891 current_version = boost::none;
893 ASSERT_TRUE(storage->loadInstalledVersions(secondary_ecu_id, ¤t_version, &pending_version));
894 EXPECT_TRUE(!!current_version);
895 EXPECT_TRUE(current_version->IsValid());
896 EXPECT_FALSE(!!pending_version);
901 fault_injection_init();
902 fiu_enable(
"fake_install_finalization_failure", 1,
nullptr, 0);
903 http_server_mock->clearReportEvents();
906 EventHandler event_hdlr(aktualizr);
909 fiu_disable(
"fake_install_finalization_failure");
911 EXPECT_FALSE(aktualizr.uptane_client()->hasPendingUpdates());
912 EXPECT_TRUE(http_server_mock->checkReceivedReports({
"EcuInstallationCompleted"}));
913 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
917 std::string correlation_id;
921 EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
926 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
927 EXPECT_FALSE(storage->loadEcuInstallationResults(&ecu_installation_res));
930 boost::optional<Uptane::Target> current_version;
931 boost::optional<Uptane::Target> pending_version;
933 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
934 EXPECT_FALSE(!!current_version);
935 EXPECT_FALSE(!!pending_version);
937 current_version = boost::none;
938 pending_version = boost::none;
940 ASSERT_TRUE(storage->loadInstalledVersions(secondary_ecu_id, ¤t_version, &pending_version));
941 EXPECT_TRUE(!!current_version);
942 EXPECT_FALSE(!!pending_version);
957 std::vector<std::string> expected_event_order = {
958 "UpdateCheckComplete",
"DownloadProgressReport",
"DownloadTargetComplete",
"DownloadProgressReport",
959 "DownloadTargetComplete",
"AllDownloadsComplete",
"InstallStarted",
"InstallTargetComplete",
960 "InstallStarted",
"InstallTargetComplete",
"AllInstallsComplete",
"PutManifestComplete"};
962 std::vector<std::string> expected_report_order = {
963 "EcuDownloadStarted",
"EcuDownloadCompleted",
"EcuDownloadStarted",
"EcuDownloadCompleted",
964 "EcuInstallationStarted",
"EcuInstallationCompleted",
"EcuInstallationStarted",
"EcuInstallationCompleted"};
966 const std::string primary_ecu_id =
"CA:FE:A6:D2:84:9D";
967 const std::string secondary_ecu_id =
"secondary_ecu_serial";
971 auto http_server_mock = std::make_shared<HttpInstallationFailed>(temp_dir.Path(), fake_meta_dir);
972 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
973 auto storage = INvStorage::newStorage(conf.storage);
975 fault_injection_init();
976 fiu_enable(
"fake_package_install", 1,
nullptr, 0);
979 EventHandler event_hdlr(aktualizr);
983 boost::optional<Uptane::Target> current_version;
984 boost::optional<Uptane::Target> pending_version;
986 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
988 EXPECT_FALSE(!!pending_version);
989 EXPECT_FALSE(!!current_version);
992 aktualizr.uptane_client()->completeInstall();
994 EXPECT_TRUE(event_hdlr.checkReceivedEvents(expected_event_order));
995 EXPECT_FALSE(aktualizr.uptane_client()->hasPendingUpdates());
996 EXPECT_TRUE(http_server_mock->checkReceivedReports(expected_report_order));
997 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
998 EXPECT_TRUE(http_server_mock->wasInstallSuccessful(secondary_ecu_id));
1002 std::string correlation_id;
1006 EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
1008 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
1009 EXPECT_FALSE(storage->loadEcuInstallationResults(&ecu_installation_res));
1010 EXPECT_EQ(ecu_installation_res.size(), 0);
1012 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
1016 EXPECT_FALSE(!!current_version);
1017 EXPECT_FALSE(!!pending_version);
1019 fiu_disable(
"fake_package_install");
1025 auto http_server_mock = std::make_shared<HttpInstallationFailed>(temp_dir.Path(), fake_meta_dir);
1026 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
1027 auto storage = INvStorage::newStorage(conf.storage);
1028 const std::string sec_fault_name = std::string(
"secondary_install_") + secondary_ecu_id;
1030 fault_injection_init();
1031 fault_injection_enable(
"fake_package_install", 1,
"PRIMFAIL", 0);
1032 fault_injection_enable(sec_fault_name.c_str(), 1,
"SECFAIL", 0);
1035 EventHandler event_hdlr(aktualizr);
1036 aktualizr.Initialize();
1039 boost::optional<Uptane::Target> current_version;
1040 boost::optional<Uptane::Target> pending_version;
1042 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
1044 EXPECT_FALSE(!!pending_version);
1045 EXPECT_FALSE(!!current_version);
1047 aktualizr.UptaneCycle();
1048 aktualizr.uptane_client()->completeInstall();
1050 EXPECT_TRUE(event_hdlr.checkReceivedEvents(expected_event_order));
1051 EXPECT_FALSE(aktualizr.uptane_client()->hasPendingUpdates());
1052 EXPECT_TRUE(http_server_mock->checkReceivedReports(expected_report_order));
1053 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
1054 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(secondary_ecu_id));
1056 LOG_INFO << http_server_mock->last_manifest;
1057 Json::Value installation_report = http_server_mock->last_manifest[
"signed"][
"installation_report"][
"report"];
1058 EXPECT_EQ(installation_report[
"items"][0][
"result"][
"code"].asString(),
"PRIMFAIL");
1059 EXPECT_EQ(installation_report[
"items"][1][
"result"][
"code"].asString(),
"SECFAIL");
1060 EXPECT_EQ(installation_report[
"result"][
"code"].asString(),
"primary_hw:PRIMFAIL|secondary_hw:SECFAIL");
1064 std::string correlation_id;
1068 EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
1070 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
1071 EXPECT_FALSE(storage->loadEcuInstallationResults(&ecu_installation_res));
1072 EXPECT_EQ(ecu_installation_res.size(), 0);
1074 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
1078 EXPECT_FALSE(!!current_version);
1079 EXPECT_FALSE(!!pending_version);
1081 fault_injection_disable(
"fake_package_install");
1082 fault_injection_disable(sec_fault_name.c_str());
1091 auto http_server_mock = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1092 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
1093 auto storage = INvStorage::newStorage(conf.storage);
1095 fault_injection_init();
1096 fiu_enable(
"secondary_putmetadata", 1,
nullptr, 0);
1102 std::promise<void> promise;
1105 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1106 if (
event->variant !=
"AllInstallsComplete") {
1110 ev_state.result = installs_complete->result;
1112 ev_state.promise.set_value();
1118 auto status = ev_state.promise.get_future().wait_for(std::chrono::seconds(20));
1119 if (status != std::future_status::ready) {
1120 FAIL() <<
"Timed out waiting for installation to complete.";
1123 ASSERT_FALSE(ev_state.result.dev_report.isSuccess());
1125 fiu_disable(
"secondary_putmetadata");
1128 #endif // FIU_ENABLE 1142 TEST(
Aktualizr, AutoRebootAfterUpdate) {
1144 auto http = std::make_shared<HttpFakePutCounter>(temp_dir.Path(), fake_meta_dir);
1145 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1146 conf.pacman.fake_need_reboot =
true;
1147 conf.uptane.force_install_completion =
true;
1148 conf.uptane.polling_sec = 0;
1152 auto storage = INvStorage::newStorage(conf.storage);
1156 auto aktualizr_cycle_thread = aktualizr.
RunForever();
1157 auto aktualizr_cycle_thread_status = aktualizr_cycle_thread.wait_for(std::chrono::seconds(20));
1160 EXPECT_EQ(aktualizr_cycle_thread_status, std::future_status::ready);
1161 EXPECT_TRUE(aktualizr.uptane_client()->isInstallCompletionRequired());
1166 auto storage = INvStorage::newStorage(conf.storage);
1172 EXPECT_EQ(update_res.status, result::UpdateStatus::kNoUpdatesAvailable);
1175 boost::optional<Uptane::Target> current_target;
1176 boost::optional<Uptane::Target> pending_target;
1177 storage->loadPrimaryInstalledVersions(¤t_target, &pending_target);
1178 EXPECT_TRUE(!!current_target);
1179 EXPECT_FALSE(!!pending_target);
1180 EXPECT_EQ(http->manifest_sends, 3);
1190 TEST(
Aktualizr, FullMultipleSecondaries) {
1192 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"multisec", fake_meta_dir);
1193 Config conf(
"tests/config/basic.toml");
1194 conf.provision.primary_ecu_serial =
"testecuserial";
1195 conf.provision.primary_ecu_hardware_id =
"testecuhwid";
1196 conf.storage.path = temp_dir.Path();
1197 conf.tls.server = http->tls_server;
1198 conf.uptane.director_server = http->tls_server +
"/director";
1199 conf.uptane.repo_server = http->tls_server +
"/repo";
1202 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"sec_serial1",
"sec_hw1");
1204 auto storage = INvStorage::newStorage(conf.storage);
1206 UptaneTestCommon::addDefaultSecondary(conf, temp_dir2,
"sec_serial2",
"sec_hw2");
1207 ASSERT_NO_THROW(aktualizr.
AddSecondary(std::make_shared<Primary::VirtualSecondary>(
1208 Primary::VirtualSecondaryConfig::create_from_file(conf.uptane.secondary_config_file)[0])));
1213 bool allcomplete{
false};
1214 bool manifest{
false};
1215 std::future<void> future;
1216 std::promise<void> promise;
1218 ev_state.future = ev_state.promise.get_future();
1220 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1221 if (
event->variant ==
"InstallStarted") {
1223 }
else if (
event->variant ==
"InstallTargetComplete") {
1224 ++ev_state.complete;
1225 }
else if (
event->variant ==
"AllInstallsComplete") {
1226 ev_state.allcomplete =
true;
1227 }
else if (
event->variant ==
"PutManifestComplete") {
1228 ev_state.manifest =
true;
1232 if (ev_state.allcomplete && ev_state.complete == 2 && ev_state.manifest) {
1233 ev_state.promise.set_value();
1241 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1242 if (status != std::future_status::ready) {
1243 FAIL() <<
"Timed out waiting for installation to complete.";
1246 EXPECT_EQ(ev_state.started, 2);
1247 EXPECT_EQ(ev_state.complete, 2);
1249 const Json::Value manifest = http->last_manifest[
"signed"];
1250 const Json::Value manifest_versions = manifest[
"ecu_version_manifests"];
1253 EXPECT_EQ(manifest_versions[
"sec_serial1"][
"signed"][
"installed_image"][
"filepath"].asString(),
1254 "secondary_firmware.txt");
1255 EXPECT_EQ(manifest_versions[
"sec_serial1"][
"signed"][
"installed_image"][
"fileinfo"][
"length"].asUInt(), 15);
1256 EXPECT_EQ(manifest_versions[
"sec_serial2"][
"signed"][
"installed_image"][
"filepath"].asString(),
1257 "secondary_firmware2.txt");
1258 EXPECT_EQ(manifest_versions[
"sec_serial2"][
"signed"][
"installed_image"][
"fileinfo"][
"length"].asUInt(), 21);
1261 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"].size(), 2);
1262 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"][0][
"ecu"].asString(),
"sec_serial1");
1263 EXPECT_TRUE(manifest[
"installation_report"][
"report"][
"items"][0][
"result"][
"success"].asBool());
1264 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"][1][
"ecu"].asString(),
"sec_serial2");
1265 EXPECT_TRUE(manifest[
"installation_report"][
"report"][
"items"][1][
"result"][
"success"].asBool());
1273 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"noupdates", fake_meta_dir);
1274 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1276 auto storage = INvStorage::newStorage(conf.storage);
1280 size_t num_events{0};
1281 std::future<void> future;
1282 std::promise<void> promise;
1284 ev_state.future = ev_state.promise.get_future();
1286 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1290 LOG_INFO <<
"Got " <<
event->variant;
1291 switch (ev_state.num_events) {
1293 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1295 EXPECT_EQ(targets_event->result.ecus_count, 0);
1296 EXPECT_EQ(targets_event->result.updates.size(), 0);
1297 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
1301 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1303 EXPECT_EQ(targets_event->result.ecus_count, 0);
1304 EXPECT_EQ(targets_event->result.updates.size(), 0);
1305 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
1306 ev_state.promise.set_value();
1311 FAIL() <<
"Unexpected events!";
1313 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1314 ASSERT_EQ(
event->variant,
"");
1316 ++ev_state.num_events;
1323 EXPECT_EQ(result.ecus_count, 0);
1324 EXPECT_EQ(result.updates.size(), 0);
1325 EXPECT_EQ(result.status, result::UpdateStatus::kNoUpdatesAvailable);
1329 EXPECT_EQ(result.ecus_count, 0);
1330 EXPECT_EQ(result.updates.size(), 0);
1331 EXPECT_EQ(result.status, result::UpdateStatus::kNoUpdatesAvailable);
1333 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1334 if (status != std::future_status::ready) {
1335 FAIL() <<
"Timed out waiting for metadata to be fetched.";
1338 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1349 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1350 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1352 auto storage = INvStorage::newStorage(conf.storage);
1356 size_t num_events{0};
1357 std::future<void> future;
1358 std::promise<void> promise;
1360 ev_state.future = ev_state.promise.get_future();
1362 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1366 LOG_INFO <<
"Got " <<
event->variant;
1367 switch (ev_state.num_events) {
1369 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1371 EXPECT_EQ(downloads_complete->result.updates.size(), 0);
1372 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kError);
1376 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1378 EXPECT_EQ(targets_event->result.ecus_count, 2);
1379 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1380 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1381 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1382 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1387 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
1389 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1390 download_event->update.filename() ==
"secondary_firmware.txt");
1391 EXPECT_TRUE(download_event->success);
1395 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1397 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1398 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1399 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1400 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1401 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1402 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1403 ev_state.promise.set_value();
1408 FAIL() <<
"Unexpected events!";
1410 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1411 ASSERT_EQ(
event->variant,
"");
1413 ++ev_state.num_events;
1420 EXPECT_EQ(result.updates.size(), 0);
1421 EXPECT_EQ(result.status, result::DownloadStatus::kError);
1424 aktualizr.
Download(update_result.updates);
1426 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1427 if (status != std::future_status::ready) {
1428 FAIL() <<
"Timed out waiting for downloads to complete.";
1431 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1436 using Responses = std::vector<std::pair<std::string, HttpResponse>>;
1439 HttpDownloadFailure(
const boost::filesystem::path& test_dir_in,
const Responses& file_to_response, std::string flavor,
1440 const boost::filesystem::path& meta_dir_in)
1441 :
HttpFake(test_dir_in, flavor, meta_dir_in) {
1442 for (
auto resp : file_to_response) {
1443 url_to_response_[tls_server + target_dir_ + resp.first] = resp.second;
1447 HttpResponse download(
const std::string& url, curl_write_callback write_cb, curl_xferinfo_callback progress_cb,
1448 void* userp, curl_off_t from)
override {
1449 const auto found_response_it = url_to_response_.find(url);
1450 if (found_response_it == url_to_response_.end()) {
1451 return HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error");
1454 auto response = url_to_response_.at(url);
1455 if (response.isOk()) {
1456 return HttpFake::download(url, write_cb, progress_cb, userp, from);
1459 return url_to_response_[url];
1463 const std::string target_dir_{
"/repo/targets/"};
1464 std::map<std::string, HttpResponse> url_to_response_;
1476 class DownloadEventHandler {
1478 DownloadEventHandler(
Aktualizr& aktualizr) {
1479 functor_ = std::bind(&DownloadEventHandler::operator(),
this, std::placeholders::_1);
1483 void operator()(
const std::shared_ptr<event::BaseEvent>&
event) {
1484 ASSERT_NE(event,
nullptr);
1488 auto target_filename = download_target_complete_event->update.filename();
1489 download_status[target_filename] = download_target_complete_event->success;
1493 all_download_completed_status = all_download_complete_event->result;
1498 std::map<std::string, bool> download_status;
1502 std::function<void(std::shared_ptr<event::BaseEvent>)> functor_;
1506 HttpDownloadFailure::Responses downloadResponse;
1507 std::vector<std::pair<std::string, bool>> downloadResult;
1511 TestParams test_case_params[]{
1513 {{
"primary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")},
1514 {
"secondary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")}},
1515 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
false}},
1516 result::DownloadStatus::kError},
1518 {{
"primary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")},
1519 {
"secondary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")}},
1520 {{
"primary_firmware.txt",
true}, {
"secondary_firmware.txt",
false}},
1521 result::DownloadStatus::kPartialSuccess},
1523 {{
"primary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")},
1524 {
"secondary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")}},
1525 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
true}},
1526 result::DownloadStatus::kPartialSuccess}};
1528 for (
auto test_params : test_case_params) {
1531 auto http = std::make_shared<HttpDownloadFailure>(temp_dir.Path(), test_params.downloadResponse,
"hasupdates",
1533 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1534 auto storage = INvStorage::newStorage(conf.storage);
1537 DownloadEventHandler event_hdlr{aktualizr};
1541 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1544 for (
auto& expected_result : test_params.downloadResult) {
1546 ASSERT_NE(event_hdlr.download_status.find(expected_result.first), event_hdlr.download_status.end());
1547 EXPECT_EQ(event_hdlr.download_status.at(expected_result.first), expected_result.second);
1549 EXPECT_EQ(event_hdlr.all_download_completed_status.status, test_params.allDownloadsStatus);
1559 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1560 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1562 auto storage = INvStorage::newStorage(conf.storage);
1569 EXPECT_EQ(targets.size(), 0);
1571 aktualizr.
Download(update_result.updates).get();
1574 EXPECT_EQ(targets.size(), 2);
1582 EXPECT_EQ(targets.size(), 0);
1591 const boost::filesystem::path local_metadir = temp_dir /
"metadir";
1592 Utils::createDirectories(local_metadir, S_IRWXU);
1593 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", local_metadir /
"repo");
1595 UptaneRepo repo{local_metadir,
"2021-07-04T16:33:27Z",
"id0"};
1596 repo.generateRepo(KeyType::kED25519);
1597 const std::string hwid =
"primary_hw";
1598 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1599 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1602 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1603 auto storage = INvStorage::newStorage(conf.storage);
1607 boost::signals2::connection ac_conn =
1608 aktualizr.
SetSignalHandler(std::bind(targets_autoclean_cb, std::ref(aktualizr), std::placeholders::_1));
1613 aktualizr.
Download(update_result.updates).get();
1618 EXPECT_TRUE(install_result.dev_report.success);
1621 ASSERT_EQ(targets.size(), 1);
1622 EXPECT_EQ(targets[0].filename(),
"primary_firmware.txt");
1626 repo.emptyTargets();
1627 repo.addImage(fake_meta_dir /
"fake_meta/dummy_firmware.txt",
"dummy_firmware.txt", hwid,
"", {});
1628 repo.addTarget(
"dummy_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1633 aktualizr.
Download(update_result.updates).get();
1638 EXPECT_TRUE(install_result.dev_report.success);
1642 ASSERT_EQ(targets.size(), 2);
1646 repo.emptyTargets();
1647 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1648 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1653 aktualizr.
Download(update_result.updates).get();
1658 EXPECT_TRUE(install_result.dev_report.success);
1662 ASSERT_EQ(targets.size(), 2);
1666 repo.emptyTargets();
1667 repo.addImage(fake_meta_dir /
"fake_meta/secondary_firmware.txt",
"secondary_firmware.txt", hwid,
"", {});
1668 repo.addTarget(
"secondary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1673 aktualizr.
Download(update_result.updates).get();
1678 EXPECT_TRUE(install_result.dev_report.success);
1682 ASSERT_EQ(targets.size(), 2);
1685 Aktualizr::InstallationLog log = aktualizr.GetInstallationLog();
1686 ASSERT_EQ(log.size(), 2);
1688 EXPECT_EQ(log[0].installs.size(), 4);
1689 EXPECT_EQ(log[1].installs.size(), 0);
1691 std::vector<std::string> fws{
"primary_firmware.txt",
"dummy_firmware.txt",
"primary_firmware.txt",
1692 "secondary_firmware.txt"};
1693 for (
auto it = log[0].installs.begin(); it < log[0].installs.end(); it++) {
1694 auto idx =
static_cast<size_t>(it - log[0].installs.begin());
1695 EXPECT_EQ(it->filename(), fws[idx]);
1706 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1707 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1709 auto storage = INvStorage::newStorage(conf.storage);
1713 size_t num_events{0};
1714 std::vector<Uptane::Target> updates;
1715 std::future<void> future;
1716 std::promise<void> promise;
1718 ev_state.future = ev_state.promise.get_future();
1720 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1726 LOG_INFO <<
"Got " <<
event->variant;
1727 switch (ev_state.num_events) {
1729 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
1731 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 0);
1735 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1737 EXPECT_EQ(targets_event->result.ecus_count, 2);
1738 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1739 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1740 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1741 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1742 ev_state.updates = targets_event->result.updates;
1747 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
1749 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1750 download_event->update.filename() ==
"secondary_firmware.txt");
1751 EXPECT_TRUE(download_event->success);
1755 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1757 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1758 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1759 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1760 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1761 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1762 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1768 ASSERT_EQ(
event->variant,
"InstallStarted");
1770 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1776 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
1778 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1779 EXPECT_TRUE(install_complete->success);
1783 ASSERT_EQ(
event->variant,
"InstallStarted");
1785 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
1789 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
1791 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
1792 EXPECT_TRUE(install_complete->success);
1796 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
1798 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 2);
1799 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
1800 data::ResultCode::Numeric::kOk);
1801 EXPECT_EQ(installs_complete->result.ecu_reports[1].install_res.result_code.num_code,
1802 data::ResultCode::Numeric::kOk);
1803 ev_state.promise.set_value();
1808 FAIL() <<
"Unexpected events!";
1810 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1811 ASSERT_EQ(
event->variant,
"");
1813 ++ev_state.num_events;
1819 Json::Value primary_json;
1820 primary_json[
"hashes"][
"sha256"] =
"74e653bbf6c00a88b21f0992159b1002f5af38506e6d2fbc7eb9846711b2d75f";
1821 primary_json[
"hashes"][
"sha512"] =
1822 "91814ad1c13ebe2af8d65044893633c4c3ce964edb8cb58b0f357406c255f7be94f42547e108b300346a42cd57662e4757b9d843b7acbc09" 1824 primary_json[
"length"] = 2;
1825 Uptane::Target primary_target(
"primary_firmware.txt", primary_json);
1827 Json::Value secondary_json;
1828 secondary_json[
"hashes"][
"sha256"] =
"1bbb15aa921ffffd5079567d630f43298dbe5e7cbc1b14e0ccdd6718fde28e47";
1829 secondary_json[
"hashes"][
"sha512"] =
1830 "7dbae4c36a2494b731a9239911d3085d53d3e400886edb4ae2b9b78f40bda446649e83ba2d81653f614cc66f5dd5d4dbd95afba854f148af" 1832 secondary_json[
"length"] = 2;
1833 Uptane::Target secondary_target(
"secondary_firmware.txt", secondary_json);
1837 EXPECT_EQ(result.ecu_reports.size(), 0);
1839 EXPECT_THROW(aktualizr.
OpenStoredTarget(primary_target).get(), std::runtime_error)
1840 <<
"Primary firmware is present in storage before the download";
1841 EXPECT_THROW(aktualizr.
OpenStoredTarget(secondary_target).get(), std::runtime_error)
1842 <<
"Secondary firmware is present in storage before the download";
1845 aktualizr.
Download(update_result.updates).get();
1847 <<
"Primary firmware is not present in storage after the download";
1849 <<
"Secondary firmware is not present in storage after the download";
1852 aktualizr.
Install(update_result.updates);
1854 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1855 if (status != std::future_status::ready) {
1856 FAIL() <<
"Timed out waiting for installation to complete.";
1867 TEST(
Aktualizr, ReportDownloadProgress) {
1871 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1872 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1873 auto storage = INvStorage::newStorage(conf.storage);
1876 unsigned int report_counter = {0};
1877 std::shared_ptr<const event::DownloadProgressReport> lastProgressReport{
nullptr};
1879 std::function<void(std::shared_ptr<event::BaseEvent>
event)> report_event_hdlr =
1880 [&](
const std::shared_ptr<event::BaseEvent>&
event) {
1881 ASSERT_NE(event,
nullptr);
1887 ASSERT_NE(download_progress_event,
nullptr);
1888 ASSERT_NE(download_progress_event.get(),
nullptr);
1889 if (lastProgressReport) {
1890 EXPECT_GE(download_progress_event->progress, lastProgressReport->progress);
1892 lastProgressReport = download_progress_event;
1900 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1903 update_result.updates.pop_back();
1906 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
1908 ASSERT_NE(lastProgressReport,
nullptr);
1909 ASSERT_NE(lastProgressReport.get(),
nullptr);
1910 EXPECT_TRUE(event::DownloadProgressReport::isDownloadCompleted(*lastProgressReport));
1911 EXPECT_GT(report_counter, 1);
1916 HttpFakeCampaign(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
1917 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
1919 HttpResponse get(
const std::string& url, int64_t maxsize)
override {
1920 EXPECT_NE(url.find(
"campaigner/"), std::string::npos);
1921 boost::filesystem::path path = meta_dir / url.substr(tls_server.size() + strlen(
"campaigner/"));
1923 if (url.find(
"campaigner/campaigns") != std::string::npos) {
1924 return HttpResponse(Utils::readFile(path.parent_path() /
"campaigner/campaigns.json"), 200, CURLE_OK,
"");
1926 return HttpFake::get(url, maxsize);
1929 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
1931 for (
auto it = data.begin(); it != data.end(); it++) {
1933 auto id = ev[
"eventType"][
"id"];
1934 if (
id ==
"campaign_accepted" ||
id ==
"campaign_declined" ||
id ==
"campaign_postponed") {
1935 seen_events.push_back(ev);
1941 std::vector<Json::Value> seen_events;
1946 bool campaignaccept_seen{
false};
1947 bool campaigndecline_seen{
false};
1948 bool campaignpostpone_seen{
false};
1950 void handler(
const std::shared_ptr<event::BaseEvent>&
event) {
1951 std::cout <<
event->variant <<
"\n";
1952 if (event->variant ==
"CampaignCheckComplete") {
1954 EXPECT_EQ(concrete_event->result.campaigns.size(), 1);
1955 EXPECT_EQ(concrete_event->result.campaigns[0].name,
"campaign1");
1956 EXPECT_EQ(concrete_event->result.campaigns[0].id,
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
1957 EXPECT_EQ(concrete_event->result.campaigns[0].size, 62470);
1958 EXPECT_EQ(concrete_event->result.campaigns[0].autoAccept,
true);
1959 EXPECT_EQ(concrete_event->result.campaigns[0].description,
"this is my message to show on the device");
1960 }
else if (event->variant ==
"CampaignAcceptComplete") {
1961 campaignaccept_seen =
true;
1962 }
else if (event->variant ==
"CampaignDeclineComplete") {
1963 campaigndecline_seen =
true;
1964 }
else if (event->variant ==
"CampaignPostponeComplete") {
1965 campaignpostpone_seen =
true;
1986 TEST(
Aktualizr, CampaignCheckAndControl) {
1988 auto http = std::make_shared<HttpFakeCampaign>(temp_dir.Path(), fake_meta_dir);
1989 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1994 auto storage = INvStorage::newStorage(conf.storage);
1996 aktualizr.
SetSignalHandler(std::bind(&CampaignEvents::handler, &campaign_events, std::placeholders::_1));
2001 EXPECT_EQ(result.campaigns.size(), 1);
2004 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Accept).get();
2006 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Decline).get();
2008 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Postpone).get();
2011 ASSERT_EQ(http->seen_events.size(), 3);
2012 for (
const auto& ev : http->seen_events) {
2013 EXPECT_EQ(ev[
"event"][
"campaignId"],
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
2015 EXPECT_TRUE(campaign_events.campaignaccept_seen);
2016 EXPECT_TRUE(campaign_events.campaigndecline_seen);
2017 EXPECT_TRUE(campaign_events.campaignpostpone_seen);
2022 HttpFakeNoCorrelationId(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2023 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2025 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
2027 for (
const Json::Value&
event : data) {
2029 EXPECT_EQ(
event[
"event"][
"correlationId"].asString(),
"");
2034 unsigned int events_seen{0};
2041 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/repo", meta_dir.Path() /
"repo");
2042 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/director", meta_dir.Path() /
"director");
2043 auto http = std::make_shared<HttpFakeNoCorrelationId>(temp_dir.Path(), meta_dir.Path());
2048 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2050 auto storage = INvStorage::newStorage(conf.storage);
2055 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
2058 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
2061 for (
const auto& r : install_result.ecu_reports) {
2062 EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
2066 EXPECT_EQ(http->events_seen, 8);
2071 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", fake_meta_dir);
2074 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2076 auto storage = INvStorage::newStorage(conf.storage);
2080 Json::Value custom = Utils::parseJSON(R
"({"test_field":"test_value"})"); 2081 ASSERT_EQ(custom["test_field"].asString(),
"test_value");
2082 ASSERT_EQ(
true, aktualizr.
SendManifest(custom).get()) <<
"Failed to upload manifest with HttpFake server";
2083 EXPECT_EQ(http->last_manifest[
"signed"][
"custom"], custom);
2094 std::function<void(std::shared_ptr<event::BaseEvent>)> Signal() {
2095 return std::bind(&CountUpdateCheckEvents::count,
this, std::placeholders::_1);
2098 void count(std::shared_ptr<event::BaseEvent>
event) {
2099 std::cout <<
event->variant <<
"\n";
2100 if (event->variant ==
"UpdateCheckComplete") {
2102 if (std::static_pointer_cast<event::UpdateCheckComplete>(event)->result.status == result::UpdateStatus::kError) {
2108 int total_events()
const {
return total_events_; }
2109 int error_events()
const {
return error_events_; }
2112 int total_events_{0};
2113 int error_events_{0};
2118 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
2120 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2122 auto storage = INvStorage::newStorage(conf.storage);
2127 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2129 std::vector<std::future<result::UpdateCheck>> futures;
2130 for (
int i = 0; i < 5; ++i) {
2134 for (
auto& f : futures) {
2139 EXPECT_EQ(counter.total_events(), 5);
2145 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter2.Signal());
2148 std::future<result::UpdateCheck> ft = aktualizr.
CheckUpdates();
2149 for (
int i = 0; i < 99; ++i) {
2154 EXPECT_LT(counter2.total_events(), 100);
2155 EXPECT_GT(counter2.total_events(), 0);
2160 HttpPutManifestFail(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2161 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2162 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
2169 TEST(
Aktualizr, UpdateCheckCompleteError) {
2171 auto http = std::make_shared<HttpPutManifestFail>(temp_dir.Path(), fake_meta_dir);
2173 Config conf = UptaneTestCommon::makeTestConfig(temp_dir,
"http://updatefail");
2175 auto storage = INvStorage::newStorage(conf.storage);
2179 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2182 EXPECT_EQ(result.status, result::UpdateStatus::kError);
2183 EXPECT_EQ(counter.error_events(), 1);
2193 HttpFakePauseCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2194 :
HttpFake(test_dir_in,
"noupdates", meta_dir_in) {}
2196 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
2198 for (
const Json::Value&
event : data) {
2200 std::string event_type =
event[
"eventType"][
"id"].asString();
2202 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
2203 if (events_seen == 1) {
2204 EXPECT_EQ(event_type,
"DevicePaused");
2205 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2206 }
else if (events_seen == 2) {
2207 EXPECT_EQ(event_type,
"DeviceResumed");
2208 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2210 std::cout <<
"Unexpected event";
2217 unsigned int events_seen{0};
2222 auto http = std::make_shared<HttpFakePauseCounter>(temp_dir.Path(), fake_meta_dir);
2223 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2225 auto storage = INvStorage::newStorage(conf.storage);
2230 std::promise<void> end_promise{};
2231 size_t n_events = 0;
2232 std::atomic_bool is_paused{
false};
2233 std::function<void(std::shared_ptr<event::BaseEvent>)> cb = [&end_promise, &n_events, &mutex,
2234 &is_paused](std::shared_ptr<event::BaseEvent>
event) {
2237 ASSERT_EQ(event->variant,
"UpdateCheckComplete");
2240 std::lock_guard<std::mutex> guard(mutex);
2242 ASSERT_EQ(event->variant,
"UpdateCheckComplete");
2244 EXPECT_FALSE(is_paused);
2245 end_promise.set_value();
2249 FAIL() <<
"Unexpected event";
2259 std::lock_guard<std::mutex> guard(mutex);
2260 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kSuccess);
2264 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kAlreadyPaused);
2269 std::this_thread::sleep_for(std::chrono::seconds(1));
2272 std::lock_guard<std::mutex> guard(mutex);
2274 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kSuccess);
2277 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kAlreadyRunning);
2279 auto status = end_promise.get_future().wait_for(std::chrono::seconds(20));
2280 if (status != std::future_status::ready) {
2281 FAIL() <<
"Timed out waiting for UpdateCheck event";
2285 const std::string custom_hwinfo =
2286 R
"([{"description":"ECU1","ECU P/N":"AAA","HW P/N":"BBB","HW Version":"1.234", 2287 "SW P/N":"CCC","SW Version":"4.321","ECU Serial":"AAA-BBB-CCC"}, 2288 {"description":"ECU2","ECU P/N":"ZZZ","HW P/N":"XXX","HW Version":"9.876", 2289 "SW P/N":"YYY","SW Version":"6.789","ECU Serial":"VVV-NNN-MMM"}])"; 2293 HttpSystemInfo(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2294 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2296 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
2297 if (url.find(hwinfo_ep_) == url.length() - hwinfo_ep_.length()) {
2298 if (info_count_ == 0) {
2299 EXPECT_TRUE(data.isObject());
2300 EXPECT_TRUE(data.isMember(
"description"));
2301 }
else if (info_count_ == 1) {
2302 auto hwinfo = Utils::parseJSON(custom_hwinfo);
2303 EXPECT_EQ(hwinfo, data);
2307 }
else if (url.find(
"/manifest") != std::string::npos) {
2310 return HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found");
2316 std::string hwinfo_ep_{
"/system_info"};
2321 auto http = std::make_shared<HttpSystemInfo>(temp_dir.Path(), fake_meta_dir);
2322 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2324 auto storage = INvStorage::newStorage(conf.storage);
2330 auto hwinfo = Utils::parseJSON(custom_hwinfo);
2335 int main(
int argc,
char** argv) {
2336 ::testing::InitGoogleTest(&argc, argv);
2338 std::cerr <<
"Error: " << argv[0] <<
" requires the path to the base directory of Uptane repos.\n";
2339 return EXIT_FAILURE;
2341 uptane_repos_dir = argv[1];
2344 logger_set_threshold(boost::log::trivial::trace);
2347 fake_meta_dir = tmp_dir.Path();
2350 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.
Container for information about downloading an update.
A manifest has been sent to the server.
The server has been queried for available campaigns.
void AddSecondary(const std::shared_ptr< Uptane::SecondaryInterface > &secondary)
Add new Secondary to aktualizr.
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.
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.
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::unique_ptr< StorageTargetRHandle > OpenStoredTarget(const Uptane::Target &target)
Get target downloaded in Download call.
std::future< void > CampaignControl(const std::string &campaign_id, campaign::Cmd cmd)
Act on campaign: accept, decline or postpone.
A target has been downloaded.