1 #include <gtest/gtest.h>
6 #include <unordered_map>
9 #include <boost/filesystem.hpp>
10 #include "json/json.h"
12 #include "libaktualizr/aktualizr.h"
13 #include "libaktualizr/config.h"
17 #include "primary/aktualizr_helpers.h"
18 #include "primary/sotauptaneclient.h"
19 #include "uptane_test_common.h"
20 #include "utilities/utils.h"
21 #include "virtualsecondary.h"
23 #include "utilities/fault_injection.h"
25 boost::filesystem::path uptane_repos_dir;
26 boost::filesystem::path fake_meta_dir;
28 void verifyNothingInstalled(
const Json::Value& manifest) {
31 manifest[
"ecu_version_manifests"][
"CA:FE:A6:D2:84:9D"][
"signed"][
"custom"][
"operation_result"][
"id"].asString(),
34 manifest[
"ecu_version_manifests"][
"CA:FE:A6:D2:84:9D"][
"signed"][
"custom"][
"operation_result"][
"result_code"]
36 static_cast<int>(data::ResultCode::Numeric::kOk));
38 manifest[
"ecu_version_manifests"][
"CA:FE:A6:D2:84:9D"][
"signed"][
"custom"][
"operation_result"][
"result_text"]
41 EXPECT_EQ(manifest[
"ecu_version_manifests"][
"CA:FE:A6:D2:84:9D"][
"signed"][
"installed_image"][
"filepath"].asString(),
45 manifest[
"ecu_version_manifests"][
"secondary_ecu_serial"][
"signed"][
"installed_image"][
"filepath"].asString(),
54 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"noupdates", fake_meta_dir);
55 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
57 auto storage = INvStorage::newStorage(conf.storage);
62 std::future<void> future;
63 std::promise<void> promise;
65 ev_state.future = ev_state.promise.get_future();
67 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
71 LOG_INFO <<
"Got " <<
event->variant;
72 switch (ev_state.num_events) {
74 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
76 EXPECT_EQ(targets_event->result.ecus_count, 0);
77 EXPECT_EQ(targets_event->result.updates.size(), 0);
78 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
82 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
84 EXPECT_EQ(targets_event->result.ecus_count, 0);
85 EXPECT_EQ(targets_event->result.updates.size(), 0);
86 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
87 ev_state.promise.set_value();
92 FAIL() <<
"Unexpected events!";
94 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
95 ASSERT_EQ(
event->variant,
"");
97 ++ev_state.num_events;
99 boost::signals2::connection conn = aktualizr.SetSignalHandler(f_cb);
101 aktualizr.Initialize();
102 aktualizr.UptaneCycle();
105 aktualizr.UptaneCycle();
106 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
107 if (status != std::future_status::ready) {
108 FAIL() <<
"Timed out waiting for metadata to be fetched.";
111 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
118 TEST(
Aktualizr, DeviceInstallationResult) {
120 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", fake_meta_dir);
121 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
123 auto storage = INvStorage::newStorage(conf.storage);
129 storage->storeEcuSerials(serials);
133 aktualizr.AddSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config));
134 aktualizr.Initialize();
142 aktualizr.uptane_client()->computeDeviceInstallationResult(&
result,
nullptr);
143 auto res_json =
result.toJson();
144 EXPECT_EQ(res_json[
"code"].asString(),
"primary_hw:INSTALL_FAILED");
145 EXPECT_EQ(res_json[
"success"],
false);
147 storage->saveEcuInstallationResult(
150 aktualizr.uptane_client()->computeDeviceInstallationResult(&
result,
nullptr);
151 res_json =
result.toJson();
152 EXPECT_EQ(res_json[
"code"].asString(),
"primary_hw:INSTALL_FAILED|hw_id3:SECOND_FAIL");
153 EXPECT_EQ(res_json[
"success"],
false);
162 TEST(
Aktualizr, DeviceInstallationResultMetadata) {
166 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
167 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
168 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"sec_serial1",
"sec_hw1");
169 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"sec_serial2",
"sec_hw2");
170 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"sec_serial3",
"sec_hw3");
172 auto storage = INvStorage::newStorage(conf.storage);
174 aktualizr.Initialize();
175 auto update_result = aktualizr.CheckUpdates().get();
176 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
178 fault_injection_init();
179 fiu_enable(
"secondary_putmetadata", 1,
nullptr, 0);
182 std::vector<Uptane::Target> targets;
183 Json::Value target_json;
184 target_json[
"custom"][
"targetFormat"] =
"BINARY";
185 target_json[
"custom"][
"ecuIdentifiers"][
"sec_serial1"][
"hardwareId"] =
"sec_hw1";
186 target_json[
"custom"][
"ecuIdentifiers"][
"sec_serial3"][
"hardwareId"] =
"sec_hw3";
190 aktualizr.uptane_client()->sendMetadataToEcus(targets, &
result,
nullptr);
191 auto res_json =
result.toJson();
192 EXPECT_EQ(res_json[
"code"].asString(),
"sec_hw1:VERIFICATION_FAILED|sec_hw3:VERIFICATION_FAILED");
193 EXPECT_EQ(res_json[
"success"],
false);
195 fiu_disable(
"secondary_putmetadata");
198 aktualizr.uptane_client()->sendMetadataToEcus(targets, &
result,
nullptr);
199 res_json =
result.toJson();
200 EXPECT_EQ(res_json[
"code"].asString(),
"OK");
201 EXPECT_EQ(res_json[
"success"],
true);
208 HttpFakeEventCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
209 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
211 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
215 std::string event_type =
event[
"eventType"][
"id"].asString();
216 if (event_type.find(
"Ecu") == 0) {
217 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
220 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
221 if (events_seen >= 1 && events_seen <= 4) {
222 EXPECT_TRUE(event_type ==
"EcuDownloadStarted" || event_type ==
"EcuDownloadCompleted");
223 }
else if (events_seen >= 5 && events_seen <= 8) {
224 EXPECT_TRUE(event_type ==
"EcuInstallationStarted" || event_type ==
"EcuInstallationCompleted");
226 std::cout <<
"Unexpected event";
233 unsigned int events_seen{0};
242 auto http = std::make_shared<HttpFakeEventCounter>(temp_dir.Path(), fake_meta_dir);
243 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
245 auto storage = INvStorage::newStorage(conf.storage);
249 size_t num_events{0};
250 std::future<void> future;
251 std::promise<void> promise;
253 ev_state.future = ev_state.promise.get_future();
255 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
259 LOG_INFO <<
"Got " <<
event->variant;
260 switch (ev_state.num_events) {
262 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
264 EXPECT_EQ(targets_event->result.ecus_count, 2);
265 EXPECT_EQ(targets_event->result.updates.size(), 2u);
266 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
267 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
268 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
273 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
275 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
276 download_event->update.filename() ==
"secondary_firmware.txt");
277 EXPECT_TRUE(download_event->success);
281 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
283 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
284 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
285 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
286 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
287 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
288 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
294 ASSERT_EQ(
event->variant,
"InstallStarted");
296 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
302 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
304 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
305 EXPECT_TRUE(install_complete->success);
309 ASSERT_EQ(
event->variant,
"InstallStarted");
311 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
315 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
317 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
318 EXPECT_TRUE(install_complete->success);
322 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
324 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 2);
325 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
326 data::ResultCode::Numeric::kOk);
327 EXPECT_EQ(installs_complete->result.ecu_reports[1].install_res.result_code.num_code,
328 data::ResultCode::Numeric::kOk);
332 ASSERT_EQ(
event->variant,
"PutManifestComplete");
334 EXPECT_TRUE(put_complete->success);
335 ev_state.promise.set_value();
340 FAIL() <<
"Unexpected events!";
342 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
343 ASSERT_EQ(
event->variant,
"");
345 ++ev_state.num_events;
347 boost::signals2::connection conn = aktualizr.SetSignalHandler(f_cb);
349 aktualizr.Initialize();
350 aktualizr.UptaneCycle();
351 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
352 if (status != std::future_status::ready) {
353 FAIL() <<
"Timed out waiting for installation to complete.";
355 EXPECT_EQ(http->events_seen, 8);
360 HttpFakeSplit(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
361 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
363 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
367 std::string event_type =
event[
"eventType"][
"id"].asString();
368 if (event_type.find(
"Ecu") == 0) {
369 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
372 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
373 switch (events_seen) {
376 EXPECT_TRUE(event_type ==
"EcuDownloadStarted");
380 EXPECT_TRUE(event_type ==
"EcuDownloadCompleted");
384 EXPECT_TRUE(event_type ==
"EcuInstallationStarted");
388 EXPECT_TRUE(event_type ==
"EcuInstallationCompleted");
391 std::cout <<
"Unexpected event";
399 unsigned int events_seen{0};
414 auto http = std::make_shared<HttpFakeSplit>(temp_dir.Path(), fake_meta_dir);
415 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
417 auto storage = INvStorage::newStorage(conf.storage);
421 size_t num_events{0};
422 std::future<void> future;
423 std::promise<void> promise;
425 ev_state.future = ev_state.promise.get_future();
427 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
431 LOG_INFO <<
"Got " <<
event->variant;
432 switch (ev_state.num_events) {
434 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
436 EXPECT_EQ(targets_event->result.ecus_count, 2);
437 EXPECT_EQ(targets_event->result.updates.size(), 2u);
438 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
439 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
440 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
444 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
446 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt");
447 EXPECT_TRUE(download_event->success);
451 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
453 EXPECT_EQ(downloads_complete->result.updates.size(), 1);
454 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt");
455 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
461 ASSERT_EQ(
event->variant,
"InstallStarted");
463 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
469 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
471 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
472 EXPECT_TRUE(install_complete->success);
476 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
478 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 1);
479 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
480 data::ResultCode::Numeric::kOk);
484 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
486 EXPECT_TRUE(download_event->update.filename() ==
"secondary_firmware.txt");
487 EXPECT_TRUE(download_event->success);
491 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
493 EXPECT_EQ(downloads_complete->result.updates.size(), 1);
494 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt");
495 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
499 ASSERT_EQ(
event->variant,
"InstallStarted");
501 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
505 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
507 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
508 EXPECT_TRUE(install_complete->success);
512 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
514 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 1);
515 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
516 data::ResultCode::Numeric::kOk);
520 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
522 EXPECT_EQ(targets_event->result.ecus_count, 0);
523 EXPECT_EQ(targets_event->result.updates.size(), 0);
524 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
525 ev_state.promise.set_value();
530 FAIL() <<
"Unexpected events!";
532 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
533 ASSERT_EQ(
event->variant,
"");
535 ++ev_state.num_events;
537 boost::signals2::connection conn = aktualizr.SetSignalHandler(f_cb);
539 aktualizr.Initialize();
541 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
542 ASSERT_EQ(update_result.ecus_count, 2);
545 result::Download download_result = aktualizr.Download({update_result.updates[0]}).get();
546 ASSERT_EQ(download_result.status, result::DownloadStatus::kSuccess);
547 aktualizr.Install(download_result.updates);
549 download_result = aktualizr.Download({update_result.updates[1]}).get();
550 ASSERT_EQ(download_result.status, result::DownloadStatus::kSuccess);
551 aktualizr.Install(download_result.updates);
553 update_result = aktualizr.CheckUpdates().get();
554 ASSERT_EQ(update_result.status, result::UpdateStatus::kNoUpdatesAvailable);
556 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
557 if (status != std::future_status::ready) {
558 FAIL() <<
"Timed out waiting for installation to complete.";
560 EXPECT_EQ(http->events_seen, 8);
565 HttpFakePutCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
566 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
568 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
569 if (url.find(
"/manifest") != std::string::npos) {
572 return HttpFake::put(url,
data);
575 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
579 events.push_back(
event);
584 size_t count_event_with_type(
const std::string& event_type) {
585 auto c = std::count_if(events.cbegin(), events.cend(), [&event_type](
const Json::Value& v) {
586 return v[
"eventType"][
"id"].asString() == event_type;
588 return static_cast<size_t>(c);
591 unsigned int manifest_sends{0};
592 std::vector<Json::Value> events;
615 TEST(
Aktualizr, FullWithUpdatesNeedReboot) {
617 auto http = std::make_shared<HttpFakePutCounter>(temp_dir.Path(), fake_meta_dir);
618 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
619 conf.pacman.fake_need_reboot =
true;
623 auto storage = INvStorage::newStorage(conf.storage);
625 aktualizr.Initialize();
626 aktualizr.UptaneCycle();
630 boost::optional<Uptane::Target> pending_target;
631 storage->loadPrimaryInstalledVersions(
nullptr, &pending_target);
632 EXPECT_TRUE(!!pending_target);
636 EXPECT_EQ(http->manifest_sends, 1);
637 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationStarted"), 2);
638 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationApplied"), 1);
639 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationCompleted"), 1);
643 auto storage = INvStorage::newStorage(conf.storage);
645 aktualizr.Initialize();
648 boost::optional<Uptane::Target> pending_target;
649 storage->loadPrimaryInstalledVersions(
nullptr, &pending_target);
650 EXPECT_TRUE(!!pending_target);
653 EXPECT_EQ(update_res.status, result::UpdateStatus::kError);
656 boost::filesystem::remove(conf.bootloader.reboot_sentinel_dir / conf.bootloader.reboot_sentinel_name);
660 EXPECT_EQ(http->manifest_sends, 1);
661 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationCompleted"), 1);
665 auto storage = INvStorage::newStorage(conf.storage);
667 aktualizr.Initialize();
670 EXPECT_EQ(update_res.status, result::UpdateStatus::kNoUpdatesAvailable);
673 boost::optional<Uptane::Target> current_target;
674 boost::optional<Uptane::Target> pending_target;
675 storage->loadPrimaryInstalledVersions(¤t_target, &pending_target);
676 EXPECT_TRUE(!!current_target);
677 EXPECT_FALSE(!!pending_target);
680 boost::optional<Uptane::Target> sec_current_target;
681 boost::optional<Uptane::Target> sec_pending_target;
682 storage->loadInstalledVersions(
"secondary_ecu_serial", &sec_current_target, &sec_pending_target);
683 EXPECT_TRUE(!!sec_current_target);
684 EXPECT_FALSE(!!sec_pending_target);
688 EXPECT_EQ(http->manifest_sends, 3);
689 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationCompleted"), 2);
692 for (
const Json::Value&
event : http->events) {
693 std::cout <<
"got event " <<
event[
"eventType"][
"id"].asString() <<
"\n";
694 EXPECT_EQ(
event[
"event"][
"correlationId"].asString(),
"id0");
700 class HttpInstallationFailed :
public HttpFake {
702 HttpInstallationFailed(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
703 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
705 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
708 for (
auto& event_data :
data) {
709 auto event_id = event_data[
"eventType"][
"id"].asString();
710 auto ecu = event_data[
"event"][
"ecu"].asString();
711 auto correlationID = event_data[
"event"][
"correlationId"].asString();
713 if (event_id ==
"EcuInstallationCompleted") {
714 install_completion_status_[ecu] = event_data[
"event"][
"success"].asBool();
716 report_events_.push_back(event_id);
721 bool checkReceivedReports(
const std::vector<std::string>& expected_event_order) {
723 auto received_event_it = report_events_.begin();
725 for (
auto& expected_event : expected_event_order) {
726 auto received_event = *received_event_it;
727 if (expected_event != received_event) {
736 bool wasInstallSuccessful(
const std::string& ecu_serial)
const {
737 auto find_it = install_completion_status_.find(ecu_serial);
738 if (find_it == install_completion_status_.end()) {
741 return (*find_it).second;
744 void clearReportEvents() { report_events_.clear(); }
747 std::vector<std::string> report_events_;
748 std::unordered_map<std::string, bool> install_completion_status_;
754 functor_ = std::bind(&EventHandler::operator(),
this, std::placeholders::_1);
758 void operator()(
const std::shared_ptr<event::BaseEvent>&
event) {
759 ASSERT_NE(
event,
nullptr);
760 received_events_.push_back(
event->variant);
763 bool checkReceivedEvents(
const std::vector<std::string>& expected_event_order) {
765 auto received_event_it = received_events_.begin();
767 for (
auto& expected_event : expected_event_order) {
768 auto received_event = *received_event_it;
769 if (expected_event != received_event) {
774 if (received_event ==
"DownloadProgressReport") {
775 while (*(++received_event_it) ==
"DownloadProgressReport") {
785 std::function<void(std::shared_ptr<event::BaseEvent>)> functor_;
786 std::vector<std::string> received_events_{};
801 auto http_server_mock = std::make_shared<HttpInstallationFailed>(temp_dir.Path(), fake_meta_dir);
802 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
803 conf.pacman.fake_need_reboot =
true;
804 conf.uptane.force_install_completion =
true;
805 conf.uptane.polling_sec = 0;
806 auto storage = INvStorage::newStorage(conf.storage);
808 std::vector<std::string> expected_event_order = {
809 "SendDeviceDataComplete",
"UpdateCheckComplete",
"DownloadProgressReport",
"DownloadTargetComplete",
810 "DownloadProgressReport",
"DownloadTargetComplete",
"AllDownloadsComplete",
"InstallStarted",
811 "InstallTargetComplete",
"InstallStarted",
"InstallTargetComplete",
"AllInstallsComplete"};
813 std::vector<std::string> expected_report_order = {
814 "EcuDownloadStarted",
"EcuDownloadCompleted",
"EcuDownloadStarted",
"EcuDownloadCompleted",
815 "EcuInstallationStarted",
"EcuInstallationApplied",
"EcuInstallationStarted",
"EcuInstallationCompleted"};
817 const std::string primary_ecu_id =
"CA:FE:A6:D2:84:9D";
818 const std::string secondary_ecu_id =
"secondary_ecu_serial";
823 EventHandler event_hdlr(aktualizr);
827 boost::optional<Uptane::Target> current_version;
828 boost::optional<Uptane::Target> pending_version;
829 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
833 EXPECT_FALSE(!!pending_version);
834 EXPECT_FALSE(!!current_version);
836 auto aktualizr_cycle_thread = aktualizr.
RunForever();
837 auto aktualizr_cycle_thread_status = aktualizr_cycle_thread.wait_for(std::chrono::seconds(20));
839 ASSERT_EQ(aktualizr_cycle_thread_status, std::future_status::ready);
840 EXPECT_TRUE(aktualizr.uptane_client()->isInstallCompletionRequired());
841 EXPECT_TRUE(event_hdlr.checkReceivedEvents(expected_event_order));
842 EXPECT_TRUE(aktualizr.uptane_client()->hasPendingUpdates());
843 EXPECT_TRUE(http_server_mock->checkReceivedReports(expected_report_order));
846 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
847 EXPECT_TRUE(http_server_mock->wasInstallSuccessful(secondary_ecu_id));
851 std::string correlation_id;
852 ASSERT_TRUE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
853 EXPECT_EQ(dev_installation_res.result_code.num_code, data::ResultCode::Numeric::kNeedCompletion);
855 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
856 ASSERT_TRUE(storage->loadEcuInstallationResults(&ecu_installation_res));
857 EXPECT_EQ(ecu_installation_res.size(), 2);
859 for (
const auto& ecu_install_res : ecu_installation_res) {
860 auto ecu_id = ecu_install_res.first.ToString();
862 if (ecu_id == primary_ecu_id) {
863 EXPECT_EQ(ecu_install_res.second.result_code.num_code, data::ResultCode::Numeric::kNeedCompletion);
864 EXPECT_EQ(ecu_install_res.second.success,
false);
865 EXPECT_EQ(ecu_install_res.second.description,
"Application successful, need reboot");
867 }
else if (ecu_id == secondary_ecu_id) {
868 EXPECT_EQ(ecu_install_res.second.result_code.num_code, data::ResultCode::Numeric::kOk);
869 EXPECT_EQ(ecu_install_res.second.success,
true);
870 EXPECT_EQ(ecu_install_res.second.description,
"");
873 FAIL() <<
"Unexpected ECU serial: " << ecu_install_res.first;
877 pending_version = boost::none;
878 current_version = boost::none;
880 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
881 EXPECT_FALSE(!!current_version);
882 EXPECT_TRUE(!!pending_version);
883 EXPECT_TRUE(pending_version->IsValid());
885 pending_version = boost::none;
886 current_version = boost::none;
888 ASSERT_TRUE(storage->loadInstalledVersions(secondary_ecu_id, ¤t_version, &pending_version));
889 EXPECT_TRUE(!!current_version);
890 EXPECT_TRUE(current_version->IsValid());
891 EXPECT_FALSE(!!pending_version);
896 fault_injection_init();
897 fiu_enable(
"fake_install_finalization_failure", 1,
nullptr, 0);
898 http_server_mock->clearReportEvents();
901 EventHandler event_hdlr(aktualizr);
904 fiu_disable(
"fake_install_finalization_failure");
906 EXPECT_FALSE(aktualizr.uptane_client()->hasPendingUpdates());
907 EXPECT_TRUE(http_server_mock->checkReceivedReports({
"EcuInstallationCompleted"}));
908 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
912 std::string correlation_id;
916 EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
921 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
922 EXPECT_FALSE(storage->loadEcuInstallationResults(&ecu_installation_res));
925 boost::optional<Uptane::Target> current_version;
926 boost::optional<Uptane::Target> pending_version;
928 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
929 EXPECT_FALSE(!!current_version);
930 EXPECT_FALSE(!!pending_version);
932 current_version = boost::none;
933 pending_version = boost::none;
935 ASSERT_TRUE(storage->loadInstalledVersions(secondary_ecu_id, ¤t_version, &pending_version));
936 EXPECT_TRUE(!!current_version);
937 EXPECT_FALSE(!!pending_version);
952 std::vector<std::string> expected_event_order = {
953 "UpdateCheckComplete",
"DownloadProgressReport",
"DownloadTargetComplete",
"DownloadProgressReport",
954 "DownloadTargetComplete",
"AllDownloadsComplete",
"InstallStarted",
"InstallTargetComplete",
955 "InstallStarted",
"InstallTargetComplete",
"AllInstallsComplete",
"PutManifestComplete"};
957 std::vector<std::string> expected_report_order = {
958 "EcuDownloadStarted",
"EcuDownloadCompleted",
"EcuDownloadStarted",
"EcuDownloadCompleted",
959 "EcuInstallationStarted",
"EcuInstallationCompleted",
"EcuInstallationStarted",
"EcuInstallationCompleted"};
961 const std::string primary_ecu_id =
"CA:FE:A6:D2:84:9D";
962 const std::string secondary_ecu_id =
"secondary_ecu_serial";
966 auto http_server_mock = std::make_shared<HttpInstallationFailed>(temp_dir.Path(), fake_meta_dir);
967 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
968 auto storage = INvStorage::newStorage(conf.storage);
970 fault_injection_init();
971 fiu_enable(
"fake_package_install", 1,
nullptr, 0);
974 EventHandler event_hdlr(aktualizr);
978 boost::optional<Uptane::Target> current_version;
979 boost::optional<Uptane::Target> pending_version;
981 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
983 EXPECT_FALSE(!!pending_version);
984 EXPECT_FALSE(!!current_version);
987 aktualizr.uptane_client()->completeInstall();
989 EXPECT_TRUE(event_hdlr.checkReceivedEvents(expected_event_order));
990 EXPECT_FALSE(aktualizr.uptane_client()->hasPendingUpdates());
991 EXPECT_TRUE(http_server_mock->checkReceivedReports(expected_report_order));
992 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
993 EXPECT_TRUE(http_server_mock->wasInstallSuccessful(secondary_ecu_id));
997 std::string correlation_id;
1001 EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
1003 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
1004 EXPECT_FALSE(storage->loadEcuInstallationResults(&ecu_installation_res));
1005 EXPECT_EQ(ecu_installation_res.size(), 0);
1007 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
1011 EXPECT_FALSE(!!current_version);
1012 EXPECT_FALSE(!!pending_version);
1014 fiu_disable(
"fake_package_install");
1018 for (std::string prefix : {
"secondary_install_",
"secondary_sendfirmware_"}) {
1020 auto http_server_mock = std::make_shared<HttpInstallationFailed>(temp_dir.Path(), fake_meta_dir);
1021 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
1022 auto storage = INvStorage::newStorage(conf.storage);
1023 const std::string sec_fault_name = prefix + secondary_ecu_id;
1025 fault_injection_init();
1026 fault_injection_enable(
"fake_package_install", 1,
"PRIMFAIL", 0);
1027 fault_injection_enable(sec_fault_name.c_str(), 1,
"SECFAIL", 0);
1030 EventHandler event_hdlr(aktualizr);
1034 boost::optional<Uptane::Target> current_version;
1035 boost::optional<Uptane::Target> pending_version;
1037 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
1039 EXPECT_FALSE(!!pending_version);
1040 EXPECT_FALSE(!!current_version);
1043 aktualizr.uptane_client()->completeInstall();
1045 EXPECT_TRUE(event_hdlr.checkReceivedEvents(expected_event_order));
1046 EXPECT_FALSE(aktualizr.uptane_client()->hasPendingUpdates());
1047 EXPECT_TRUE(http_server_mock->checkReceivedReports(expected_report_order));
1048 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
1049 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(secondary_ecu_id));
1051 LOG_INFO << http_server_mock->last_manifest;
1052 Json::Value installation_report = http_server_mock->last_manifest[
"signed"][
"installation_report"][
"report"];
1053 EXPECT_EQ(installation_report[
"items"][0][
"result"][
"code"].asString(),
"PRIMFAIL");
1054 EXPECT_EQ(installation_report[
"items"][1][
"result"][
"code"].asString(),
"SECFAIL");
1055 EXPECT_EQ(installation_report[
"result"][
"code"].asString(),
"primary_hw:PRIMFAIL|secondary_hw:SECFAIL");
1059 std::string correlation_id;
1063 EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
1065 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
1066 EXPECT_FALSE(storage->loadEcuInstallationResults(&ecu_installation_res));
1067 EXPECT_EQ(ecu_installation_res.size(), 0);
1069 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
1073 EXPECT_FALSE(!!current_version);
1074 EXPECT_FALSE(!!pending_version);
1076 fault_injection_disable(
"fake_package_install");
1077 fault_injection_disable(sec_fault_name.c_str());
1086 auto http_server_mock = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1087 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
1088 auto storage = INvStorage::newStorage(conf.storage);
1090 fault_injection_init();
1091 fiu_enable(
"secondary_putmetadata", 1,
nullptr, 0);
1097 std::promise<void> promise;
1100 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1101 if (
event->variant !=
"AllInstallsComplete") {
1105 ev_state.result = installs_complete->result;
1107 ev_state.promise.set_value();
1113 auto status = ev_state.promise.get_future().wait_for(std::chrono::seconds(20));
1114 if (status != std::future_status::ready) {
1115 FAIL() <<
"Timed out waiting for installation to complete.";
1118 ASSERT_FALSE(ev_state.result.dev_report.isSuccess());
1120 fiu_disable(
"secondary_putmetadata");
1123 #endif // FIU_ENABLE
1137 TEST(
Aktualizr, AutoRebootAfterUpdate) {
1139 auto http = std::make_shared<HttpFakePutCounter>(temp_dir.Path(), fake_meta_dir);
1140 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1141 conf.pacman.fake_need_reboot =
true;
1142 conf.uptane.force_install_completion =
true;
1143 conf.uptane.polling_sec = 0;
1147 auto storage = INvStorage::newStorage(conf.storage);
1151 auto aktualizr_cycle_thread = aktualizr.
RunForever();
1152 auto aktualizr_cycle_thread_status = aktualizr_cycle_thread.wait_for(std::chrono::seconds(20));
1155 EXPECT_EQ(aktualizr_cycle_thread_status, std::future_status::ready);
1156 EXPECT_TRUE(aktualizr.uptane_client()->isInstallCompletionRequired());
1161 auto storage = INvStorage::newStorage(conf.storage);
1167 EXPECT_EQ(update_res.status, result::UpdateStatus::kNoUpdatesAvailable);
1170 boost::optional<Uptane::Target> current_target;
1171 boost::optional<Uptane::Target> pending_target;
1172 storage->loadPrimaryInstalledVersions(¤t_target, &pending_target);
1173 EXPECT_TRUE(!!current_target);
1174 EXPECT_FALSE(!!pending_target);
1175 EXPECT_EQ(http->manifest_sends, 3);
1185 TEST(
Aktualizr, FullMultipleSecondaries) {
1187 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"multisec", fake_meta_dir);
1188 Config conf(
"tests/config/basic.toml");
1189 conf.provision.primary_ecu_serial =
"testecuserial";
1190 conf.provision.primary_ecu_hardware_id =
"testecuhwid";
1191 conf.storage.path = temp_dir.Path();
1192 conf.pacman.images_path = temp_dir.Path() /
"images";
1193 conf.tls.server = http->tls_server;
1194 conf.uptane.director_server = http->tls_server +
"/director";
1195 conf.uptane.repo_server = http->tls_server +
"/repo";
1198 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"sec_serial1",
"sec_hw1");
1200 auto storage = INvStorage::newStorage(conf.storage);
1202 UptaneTestCommon::addDefaultSecondary(conf, temp_dir2,
"sec_serial2",
"sec_hw2");
1203 ASSERT_NO_THROW(aktualizr.
AddSecondary(std::make_shared<Primary::VirtualSecondary>(
1204 Primary::VirtualSecondaryConfig::create_from_file(conf.uptane.secondary_config_file)[0])));
1209 bool allcomplete{
false};
1210 bool manifest{
false};
1211 std::future<void> future;
1212 std::promise<void> promise;
1214 ev_state.future = ev_state.promise.get_future();
1216 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1217 if (
event->variant ==
"InstallStarted") {
1219 }
else if (
event->variant ==
"InstallTargetComplete") {
1220 ++ev_state.complete;
1221 }
else if (
event->variant ==
"AllInstallsComplete") {
1222 ev_state.allcomplete =
true;
1223 }
else if (
event->variant ==
"PutManifestComplete") {
1224 ev_state.manifest =
true;
1228 if (ev_state.allcomplete && ev_state.complete == 2 && ev_state.manifest) {
1229 ev_state.promise.set_value();
1237 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1238 if (status != std::future_status::ready) {
1239 FAIL() <<
"Timed out waiting for installation to complete.";
1242 EXPECT_EQ(ev_state.started, 2);
1243 EXPECT_EQ(ev_state.complete, 2);
1245 const Json::Value manifest = http->last_manifest[
"signed"];
1246 const Json::Value manifest_versions = manifest[
"ecu_version_manifests"];
1249 EXPECT_EQ(manifest_versions[
"sec_serial1"][
"signed"][
"installed_image"][
"filepath"].asString(),
1250 "secondary_firmware.txt");
1251 EXPECT_EQ(manifest_versions[
"sec_serial1"][
"signed"][
"installed_image"][
"fileinfo"][
"length"].asUInt(), 15);
1252 EXPECT_EQ(manifest_versions[
"sec_serial2"][
"signed"][
"installed_image"][
"filepath"].asString(),
1253 "secondary_firmware2.txt");
1254 EXPECT_EQ(manifest_versions[
"sec_serial2"][
"signed"][
"installed_image"][
"fileinfo"][
"length"].asUInt(), 21);
1257 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"].size(), 2);
1258 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"][0][
"ecu"].asString(),
"sec_serial1");
1259 EXPECT_TRUE(manifest[
"installation_report"][
"report"][
"items"][0][
"result"][
"success"].asBool());
1260 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"][1][
"ecu"].asString(),
"sec_serial2");
1261 EXPECT_TRUE(manifest[
"installation_report"][
"report"][
"items"][1][
"result"][
"success"].asBool());
1269 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"noupdates", fake_meta_dir);
1270 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1272 auto storage = INvStorage::newStorage(conf.storage);
1276 size_t num_events{0};
1277 std::future<void> future;
1278 std::promise<void> promise;
1280 ev_state.future = ev_state.promise.get_future();
1282 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1286 LOG_INFO <<
"Got " <<
event->variant;
1287 switch (ev_state.num_events) {
1289 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1291 EXPECT_EQ(targets_event->result.ecus_count, 0);
1292 EXPECT_EQ(targets_event->result.updates.size(), 0);
1293 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
1297 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1299 EXPECT_EQ(targets_event->result.ecus_count, 0);
1300 EXPECT_EQ(targets_event->result.updates.size(), 0);
1301 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
1302 ev_state.promise.set_value();
1307 FAIL() <<
"Unexpected events!";
1309 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1310 ASSERT_EQ(
event->variant,
"");
1312 ++ev_state.num_events;
1319 EXPECT_EQ(
result.ecus_count, 0);
1320 EXPECT_EQ(
result.updates.size(), 0);
1321 EXPECT_EQ(
result.status, result::UpdateStatus::kNoUpdatesAvailable);
1325 EXPECT_EQ(
result.ecus_count, 0);
1326 EXPECT_EQ(
result.updates.size(), 0);
1327 EXPECT_EQ(
result.status, result::UpdateStatus::kNoUpdatesAvailable);
1329 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1330 if (status != std::future_status::ready) {
1331 FAIL() <<
"Timed out waiting for metadata to be fetched.";
1334 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1345 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1346 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1348 auto storage = INvStorage::newStorage(conf.storage);
1352 size_t num_events{0};
1353 std::future<void> future;
1354 std::promise<void> promise;
1356 ev_state.future = ev_state.promise.get_future();
1358 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1362 LOG_INFO <<
"Got " <<
event->variant;
1363 switch (ev_state.num_events) {
1365 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1367 EXPECT_EQ(downloads_complete->result.updates.size(), 0);
1368 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kError);
1372 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1374 EXPECT_EQ(targets_event->result.ecus_count, 2);
1375 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1376 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1377 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1378 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1383 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
1385 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1386 download_event->update.filename() ==
"secondary_firmware.txt");
1387 EXPECT_TRUE(download_event->success);
1391 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1393 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1394 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1395 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1396 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1397 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1398 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1399 ev_state.promise.set_value();
1404 FAIL() <<
"Unexpected events!";
1406 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1407 ASSERT_EQ(
event->variant,
"");
1409 ++ev_state.num_events;
1416 EXPECT_EQ(
result.updates.size(), 0);
1417 EXPECT_EQ(
result.status, result::DownloadStatus::kError);
1420 aktualizr.
Download(update_result.updates);
1422 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1423 if (status != std::future_status::ready) {
1424 FAIL() <<
"Timed out waiting for downloads to complete.";
1427 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1432 using Responses = std::vector<std::pair<std::string, HttpResponse>>;
1435 HttpDownloadFailure(
const boost::filesystem::path& test_dir_in,
const Responses& file_to_response, std::string flavor,
1436 const boost::filesystem::path& meta_dir_in)
1437 :
HttpFake(test_dir_in, flavor, meta_dir_in) {
1438 for (
auto resp : file_to_response) {
1439 url_to_response_[tls_server + target_dir_ + resp.first] = resp.second;
1443 HttpResponse download(
const std::string& url, curl_write_callback write_cb, curl_xferinfo_callback progress_cb,
1444 void* userp, curl_off_t from)
override {
1445 const auto found_response_it = url_to_response_.find(url);
1446 if (found_response_it == url_to_response_.end()) {
1447 return HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error");
1450 auto response = url_to_response_.at(url);
1451 if (response.isOk()) {
1452 return HttpFake::download(url, write_cb, progress_cb, userp, from);
1455 return url_to_response_[url];
1459 const std::string target_dir_{
"/repo/targets/"};
1460 std::map<std::string, HttpResponse> url_to_response_;
1472 class DownloadEventHandler {
1474 DownloadEventHandler(
Aktualizr& aktualizr) {
1475 functor_ = std::bind(&DownloadEventHandler::operator(),
this, std::placeholders::_1);
1479 void operator()(
const std::shared_ptr<event::BaseEvent>&
event) {
1480 ASSERT_NE(
event,
nullptr);
1484 auto target_filename = download_target_complete_event->update.filename();
1485 download_status[target_filename] = download_target_complete_event->success;
1489 all_download_completed_status = all_download_complete_event->result;
1494 std::map<std::string, bool> download_status;
1498 std::function<void(std::shared_ptr<event::BaseEvent>)> functor_;
1502 HttpDownloadFailure::Responses downloadResponse;
1503 std::vector<std::pair<std::string, bool>> downloadResult;
1507 TestParams test_case_params[]{
1509 {{
"primary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")},
1510 {
"secondary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")}},
1511 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
false}},
1512 result::DownloadStatus::kError},
1514 {{
"primary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")},
1515 {
"secondary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")}},
1516 {{
"primary_firmware.txt",
true}, {
"secondary_firmware.txt",
false}},
1517 result::DownloadStatus::kPartialSuccess},
1519 {{
"primary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")},
1520 {
"secondary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")}},
1521 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
true}},
1522 result::DownloadStatus::kPartialSuccess}};
1524 for (
auto test_params : test_case_params) {
1527 auto http = std::make_shared<HttpDownloadFailure>(temp_dir.Path(), test_params.downloadResponse,
"hasupdates",
1529 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1530 auto storage = INvStorage::newStorage(conf.storage);
1533 DownloadEventHandler event_hdlr{aktualizr};
1537 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1540 for (
auto& expected_result : test_params.downloadResult) {
1542 ASSERT_NE(event_hdlr.download_status.find(expected_result.first), event_hdlr.download_status.end());
1543 EXPECT_EQ(event_hdlr.download_status.at(expected_result.first), expected_result.second);
1545 EXPECT_EQ(event_hdlr.all_download_completed_status.status, test_params.allDownloadsStatus);
1555 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1556 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1558 auto storage = INvStorage::newStorage(conf.storage);
1565 EXPECT_EQ(targets.size(), 0);
1567 aktualizr.
Download(update_result.updates).get();
1570 EXPECT_EQ(targets.size(), 2);
1578 EXPECT_EQ(targets.size(), 0);
1587 const boost::filesystem::path local_metadir = temp_dir /
"metadir";
1588 Utils::createDirectories(local_metadir, S_IRWXU);
1589 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", local_metadir /
"repo");
1591 UptaneRepo repo{local_metadir,
"2021-07-04T16:33:27Z",
"id0"};
1592 repo.generateRepo(KeyType::kED25519);
1593 const std::string hwid =
"primary_hw";
1594 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1595 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1598 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1599 auto storage = INvStorage::newStorage(conf.storage);
1603 boost::signals2::connection ac_conn =
1604 aktualizr.
SetSignalHandler(std::bind(targets_autoclean_cb, std::ref(aktualizr), std::placeholders::_1));
1609 aktualizr.
Download(update_result.updates).get();
1614 EXPECT_TRUE(install_result.dev_report.success);
1617 ASSERT_EQ(targets.size(), 1);
1618 EXPECT_EQ(targets[0].filename(),
"primary_firmware.txt");
1622 repo.emptyTargets();
1623 repo.addImage(fake_meta_dir /
"fake_meta/dummy_firmware.txt",
"dummy_firmware.txt", hwid,
"", {});
1624 repo.addTarget(
"dummy_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1629 aktualizr.
Download(update_result.updates).get();
1634 EXPECT_TRUE(install_result.dev_report.success);
1638 ASSERT_EQ(targets.size(), 2);
1642 repo.emptyTargets();
1643 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1644 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1649 aktualizr.
Download(update_result.updates).get();
1654 EXPECT_TRUE(install_result.dev_report.success);
1658 ASSERT_EQ(targets.size(), 2);
1662 repo.emptyTargets();
1663 repo.addImage(fake_meta_dir /
"fake_meta/secondary_firmware.txt",
"secondary_firmware.txt", hwid,
"", {});
1664 repo.addTarget(
"secondary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1669 aktualizr.
Download(update_result.updates).get();
1674 EXPECT_TRUE(install_result.dev_report.success);
1678 ASSERT_EQ(targets.size(), 2);
1682 ASSERT_EQ(log.size(), 2);
1684 EXPECT_EQ(log[0].installs.size(), 4);
1685 EXPECT_EQ(log[1].installs.size(), 0);
1687 std::vector<std::string> fws{
"primary_firmware.txt",
"dummy_firmware.txt",
"primary_firmware.txt",
1688 "secondary_firmware.txt"};
1689 for (
auto it = log[0].installs.begin(); it < log[0].installs.end(); it++) {
1690 auto idx =
static_cast<size_t>(it - log[0].installs.begin());
1691 EXPECT_EQ(it->filename(), fws[idx]);
1702 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1703 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1705 auto storage = INvStorage::newStorage(conf.storage);
1709 size_t num_events{0};
1710 std::vector<Uptane::Target> updates;
1711 std::future<void> future;
1712 std::promise<void> promise;
1714 ev_state.future = ev_state.promise.get_future();
1716 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1722 LOG_INFO <<
"Got " <<
event->variant;
1723 switch (ev_state.num_events) {
1725 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
1727 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 0);
1731 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1733 EXPECT_EQ(targets_event->result.ecus_count, 2);
1734 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1735 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1736 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1737 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1738 ev_state.updates = targets_event->result.updates;
1743 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
1745 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1746 download_event->update.filename() ==
"secondary_firmware.txt");
1747 EXPECT_TRUE(download_event->success);
1751 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1753 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1754 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1755 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1756 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1757 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1758 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1764 ASSERT_EQ(
event->variant,
"InstallStarted");
1766 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1772 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
1774 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1775 EXPECT_TRUE(install_complete->success);
1779 ASSERT_EQ(
event->variant,
"InstallStarted");
1781 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
1785 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
1787 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
1788 EXPECT_TRUE(install_complete->success);
1792 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
1794 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 2);
1795 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
1796 data::ResultCode::Numeric::kOk);
1797 EXPECT_EQ(installs_complete->result.ecu_reports[1].install_res.result_code.num_code,
1798 data::ResultCode::Numeric::kOk);
1799 ev_state.promise.set_value();
1804 FAIL() <<
"Unexpected events!";
1806 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1807 ASSERT_EQ(
event->variant,
"");
1809 ++ev_state.num_events;
1815 Json::Value primary_json;
1816 primary_json[
"hashes"][
"sha256"] =
"74e653bbf6c00a88b21f0992159b1002f5af38506e6d2fbc7eb9846711b2d75f";
1817 primary_json[
"hashes"][
"sha512"] =
1818 "91814ad1c13ebe2af8d65044893633c4c3ce964edb8cb58b0f357406c255f7be94f42547e108b300346a42cd57662e4757b9d843b7acbc09"
1820 primary_json[
"length"] = 59;
1821 Uptane::Target primary_target(
"primary_firmware.txt", primary_json);
1823 Json::Value secondary_json;
1824 secondary_json[
"hashes"][
"sha256"] =
"1bbb15aa921ffffd5079567d630f43298dbe5e7cbc1b14e0ccdd6718fde28e47";
1825 secondary_json[
"hashes"][
"sha512"] =
1826 "7dbae4c36a2494b731a9239911d3085d53d3e400886edb4ae2b9b78f40bda446649e83ba2d81653f614cc66f5dd5d4dbd95afba854f148af"
1828 secondary_json[
"length"] = 15;
1829 Uptane::Target secondary_target(
"secondary_firmware.txt", secondary_json);
1833 EXPECT_EQ(
result.ecu_reports.size(), 0);
1835 EXPECT_THROW(aktualizr.
OpenStoredTarget(primary_target).get(), std::runtime_error)
1836 <<
"Primary firmware is present in storage before the download";
1837 EXPECT_THROW(aktualizr.
OpenStoredTarget(secondary_target).get(), std::runtime_error)
1838 <<
"Secondary firmware is present in storage before the download";
1841 aktualizr.
Download(update_result.updates).get();
1843 <<
"Primary firmware is not present in storage after the download";
1845 <<
"Secondary firmware is not present in storage after the download";
1848 aktualizr.
Install(update_result.updates);
1850 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1851 if (status != std::future_status::ready) {
1852 FAIL() <<
"Timed out waiting for installation to complete.";
1863 TEST(
Aktualizr, ReportDownloadProgress) {
1867 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1868 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1869 auto storage = INvStorage::newStorage(conf.storage);
1872 unsigned int report_counter = {0};
1873 std::shared_ptr<const event::DownloadProgressReport> lastProgressReport{
nullptr};
1875 std::function<void(std::shared_ptr<event::BaseEvent>
event)> report_event_hdlr =
1876 [&](
const std::shared_ptr<event::BaseEvent>&
event) {
1877 ASSERT_NE(
event,
nullptr);
1882 auto download_progress_event = std::dynamic_pointer_cast<event::DownloadProgressReport>(
event);
1883 ASSERT_NE(download_progress_event,
nullptr);
1884 ASSERT_NE(download_progress_event.get(),
nullptr);
1885 if (lastProgressReport) {
1886 EXPECT_GE(download_progress_event->progress, lastProgressReport->progress);
1888 lastProgressReport = download_progress_event;
1896 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1899 update_result.updates.pop_back();
1902 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
1904 ASSERT_NE(lastProgressReport,
nullptr);
1905 ASSERT_NE(lastProgressReport.get(),
nullptr);
1906 EXPECT_TRUE(event::DownloadProgressReport::isDownloadCompleted(*lastProgressReport));
1907 EXPECT_GT(report_counter, 1);
1912 HttpFakeCampaign(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
1913 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
1915 HttpResponse get(
const std::string& url, int64_t maxsize)
override {
1916 EXPECT_NE(url.find(
"campaigner/"), std::string::npos);
1917 boost::filesystem::path path = meta_dir / url.substr(tls_server.size() + strlen(
"campaigner/"));
1919 if (url.find(
"campaigner/campaigns") != std::string::npos) {
1920 return HttpResponse(Utils::readFile(path.parent_path() /
"campaigner/campaigns.json"), 200, CURLE_OK,
"");
1922 return HttpFake::get(url, maxsize);
1925 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
1927 for (
auto it =
data.begin(); it !=
data.end(); it++) {
1929 auto id = ev[
"eventType"][
"id"];
1930 if (
id ==
"campaign_accepted" ||
id ==
"campaign_declined" ||
id ==
"campaign_postponed") {
1931 seen_events.push_back(ev);
1937 std::vector<Json::Value> seen_events;
1942 bool campaignaccept_seen{
false};
1943 bool campaigndecline_seen{
false};
1944 bool campaignpostpone_seen{
false};
1946 void handler(
const std::shared_ptr<event::BaseEvent>&
event) {
1947 std::cout <<
event->variant <<
"\n";
1948 if (
event->variant ==
"CampaignCheckComplete") {
1949 auto concrete_event = std::static_pointer_cast<event::CampaignCheckComplete>(
event);
1950 EXPECT_EQ(concrete_event->result.campaigns.size(), 1);
1951 EXPECT_EQ(concrete_event->result.campaigns[0].name,
"campaign1");
1952 EXPECT_EQ(concrete_event->result.campaigns[0].id,
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
1953 EXPECT_EQ(concrete_event->result.campaigns[0].size, 62470);
1954 EXPECT_EQ(concrete_event->result.campaigns[0].autoAccept,
true);
1955 EXPECT_EQ(concrete_event->result.campaigns[0].description,
"this is my message to show on the device");
1956 }
else if (
event->variant ==
"CampaignAcceptComplete") {
1957 campaignaccept_seen =
true;
1958 }
else if (
event->variant ==
"CampaignDeclineComplete") {
1959 campaigndecline_seen =
true;
1960 }
else if (
event->variant ==
"CampaignPostponeComplete") {
1961 campaignpostpone_seen =
true;
1982 TEST(
Aktualizr, CampaignCheckAndControl) {
1984 auto http = std::make_shared<HttpFakeCampaign>(temp_dir.Path(), fake_meta_dir);
1985 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1990 auto storage = INvStorage::newStorage(conf.storage);
1992 aktualizr.
SetSignalHandler(std::bind(&CampaignEvents::handler, &campaign_events, std::placeholders::_1));
1997 EXPECT_EQ(
result.campaigns.size(), 1);
2000 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Accept).get();
2002 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Decline).get();
2004 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Postpone).get();
2007 ASSERT_EQ(http->seen_events.size(), 3);
2008 for (
const auto& ev : http->seen_events) {
2009 EXPECT_EQ(ev[
"event"][
"campaignId"],
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
2011 EXPECT_TRUE(campaign_events.campaignaccept_seen);
2012 EXPECT_TRUE(campaign_events.campaigndecline_seen);
2013 EXPECT_TRUE(campaign_events.campaignpostpone_seen);
2018 HttpFakeNoCorrelationId(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2019 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2021 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
2025 EXPECT_EQ(
event[
"event"][
"correlationId"].asString(),
"");
2030 unsigned int events_seen{0};
2037 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/repo", meta_dir.Path() /
"repo");
2038 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/director", meta_dir.Path() /
"director");
2039 auto http = std::make_shared<HttpFakeNoCorrelationId>(temp_dir.Path(), meta_dir.Path());
2044 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2046 auto storage = INvStorage::newStorage(conf.storage);
2051 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
2054 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
2057 for (
const auto& r : install_result.ecu_reports) {
2058 EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
2062 EXPECT_EQ(http->events_seen, 8);
2067 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", fake_meta_dir);
2070 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2072 auto storage = INvStorage::newStorage(conf.storage);
2076 Json::Value custom = Utils::parseJSON(R
"({"test_field":"test_value"})");
2077 ASSERT_EQ(custom["test_field"].asString(),
"test_value");
2078 ASSERT_EQ(
true, aktualizr.
SendManifest(custom).get()) <<
"Failed to upload manifest with HttpFake server";
2079 EXPECT_EQ(http->last_manifest[
"signed"][
"custom"], custom);
2083 TEST(
Aktualizr, CustomInstallationRawReport) {
2085 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdate", fake_meta_dir);
2087 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2088 auto storage = INvStorage::newStorage(conf.storage);
2096 auto custom_raw_report =
"Installation's custom raw report!";
2099 EXPECT_EQ(http->last_manifest[
"signed"][
"installation_report"][
"report"][
"raw_report"], custom_raw_report);
2113 std::function<void(std::shared_ptr<event::BaseEvent>)> Signal() {
2114 return std::bind(&CountUpdateCheckEvents::count,
this, std::placeholders::_1);
2117 void count(std::shared_ptr<event::BaseEvent>
event) {
2118 std::cout <<
event->variant <<
"\n";
2119 if (
event->variant ==
"UpdateCheckComplete") {
2121 if (std::static_pointer_cast<event::UpdateCheckComplete>(
event)->
result.status == result::UpdateStatus::kError) {
2127 int total_events()
const {
return total_events_; }
2128 int error_events()
const {
return error_events_; }
2131 int total_events_{0};
2132 int error_events_{0};
2137 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
2139 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2141 auto storage = INvStorage::newStorage(conf.storage);
2146 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2148 std::vector<std::future<result::UpdateCheck>> futures;
2149 for (
int i = 0; i < 5; ++i) {
2153 for (
auto& f : futures) {
2158 EXPECT_EQ(counter.total_events(), 5);
2164 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter2.Signal());
2167 std::future<result::UpdateCheck> ft = aktualizr.
CheckUpdates();
2168 for (
int i = 0; i < 99; ++i) {
2173 EXPECT_LT(counter2.total_events(), 100);
2174 EXPECT_GT(counter2.total_events(), 0);
2179 HttpPutManifestFail(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2180 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2181 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
2188 TEST(
Aktualizr, UpdateCheckCompleteError) {
2190 auto http = std::make_shared<HttpPutManifestFail>(temp_dir.Path(), fake_meta_dir);
2192 Config conf = UptaneTestCommon::makeTestConfig(temp_dir,
"http://updatefail");
2194 auto storage = INvStorage::newStorage(conf.storage);
2198 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2201 EXPECT_EQ(
result.status, result::UpdateStatus::kError);
2202 EXPECT_EQ(counter.error_events(), 1);
2212 HttpFakePauseCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2213 :
HttpFake(test_dir_in,
"noupdates", meta_dir_in) {}
2215 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
2219 std::string event_type =
event[
"eventType"][
"id"].asString();
2221 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
2222 if (events_seen == 1) {
2223 EXPECT_EQ(event_type,
"DevicePaused");
2224 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2225 }
else if (events_seen == 2) {
2226 EXPECT_EQ(event_type,
"DeviceResumed");
2227 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2229 std::cout <<
"Unexpected event";
2236 unsigned int events_seen{0};
2241 auto http = std::make_shared<HttpFakePauseCounter>(temp_dir.Path(), fake_meta_dir);
2242 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2244 auto storage = INvStorage::newStorage(conf.storage);
2249 std::promise<void> end_promise{};
2250 size_t n_events = 0;
2251 std::atomic_bool is_paused{
false};
2252 std::function<void(std::shared_ptr<event::BaseEvent>)> cb = [&end_promise, &n_events, &mutex,
2253 &is_paused](std::shared_ptr<event::BaseEvent>
event) {
2256 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
2259 std::lock_guard<std::mutex> guard(mutex);
2261 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
2263 EXPECT_FALSE(is_paused);
2264 end_promise.set_value();
2268 FAIL() <<
"Unexpected event";
2278 std::lock_guard<std::mutex> guard(mutex);
2279 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kSuccess);
2283 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kAlreadyPaused);
2288 std::this_thread::sleep_for(std::chrono::seconds(1));
2291 std::lock_guard<std::mutex> guard(mutex);
2293 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kSuccess);
2296 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kAlreadyRunning);
2298 auto status = end_promise.get_future().wait_for(std::chrono::seconds(20));
2299 if (status != std::future_status::ready) {
2300 FAIL() <<
"Timed out waiting for UpdateCheck event";
2304 const std::string custom_hwinfo =
2305 R
"([{"description":"ECU1","ECU P/N":"AAA","HW P/N":"BBB","HW Version":"1.234",
2306 "SW P/N":"CCC","SW Version":"4.321","ECU Serial":"AAA-BBB-CCC"},
2307 {"description":"ECU2","ECU P/N":"ZZZ","HW P/N":"XXX","HW Version":"9.876",
2308 "SW P/N":"YYY","SW Version":"6.789","ECU Serial":"VVV-NNN-MMM"}])";
2312 HttpSystemInfo(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2313 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2315 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
2316 if (url.find(hwinfo_ep_) == url.length() - hwinfo_ep_.length()) {
2317 if (info_count_ == 0) {
2318 EXPECT_TRUE(
data.isObject());
2319 EXPECT_TRUE(
data.isMember(
"description"));
2320 }
else if (info_count_ == 1) {
2321 auto hwinfo = Utils::parseJSON(custom_hwinfo);
2322 EXPECT_EQ(hwinfo,
data);
2326 }
else if (url.find(
"/manifest") != std::string::npos) {
2329 return HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found");
2335 std::string hwinfo_ep_{
"/system_info"};
2340 auto http = std::make_shared<HttpSystemInfo>(temp_dir.Path(), fake_meta_dir);
2341 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2343 auto storage = INvStorage::newStorage(conf.storage);
2349 auto hwinfo = Utils::parseJSON(custom_hwinfo);
2354 int main(
int argc,
char** argv) {
2355 ::testing::InitGoogleTest(&argc, argv);
2357 std::cerr <<
"Error: " << argv[0] <<
" requires the path to the base directory of Uptane repos.\n";
2358 return EXIT_FAILURE;
2360 uptane_repos_dir = argv[1];
2363 logger_set_threshold(boost::log::trivial::trace);
2366 fake_meta_dir = tmp_dir.Path();
2369 return RUN_ALL_TESTS();