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");
90 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
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");
98 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
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);
180 storage->storeEcuSerials(serials);
186 aktualizr.AddSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config));
188 aktualizr.Initialize();
196 aktualizr.uptane_client()->computeDeviceInstallationResult(&
result,
nullptr);
197 auto res_json =
result.toJson();
198 EXPECT_EQ(res_json[
"code"].asString(),
"primary_hw:INSTALL_FAILED");
199 EXPECT_EQ(res_json[
"success"],
false);
201 storage->saveEcuInstallationResult(
204 aktualizr.uptane_client()->computeDeviceInstallationResult(&
result,
nullptr);
205 res_json =
result.toJson();
206 EXPECT_EQ(res_json[
"code"].asString(),
"primary_hw:INSTALL_FAILED|hw_id3:SECOND_FAIL");
207 EXPECT_EQ(res_json[
"success"],
false);
212 HttpFakeEventCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
213 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
215 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
219 std::string event_type =
event[
"eventType"][
"id"].asString();
220 if (event_type.find(
"Ecu") == 0) {
221 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
224 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
225 if (events_seen >= 1 && events_seen <= 4) {
226 EXPECT_TRUE(event_type ==
"EcuDownloadStarted" || event_type ==
"EcuDownloadCompleted");
227 }
else if (events_seen >= 5 && events_seen <= 8) {
228 EXPECT_TRUE(event_type ==
"EcuInstallationStarted" || event_type ==
"EcuInstallationCompleted");
230 std::cout <<
"Unexpected event";
237 unsigned int events_seen{0};
246 auto http = std::make_shared<HttpFakeEventCounter>(temp_dir.Path(), fake_meta_dir);
247 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
249 auto storage = INvStorage::newStorage(conf.storage);
253 size_t num_events{0};
254 std::future<void> future;
255 std::promise<void> promise;
257 ev_state.future = ev_state.promise.get_future();
259 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
263 LOG_INFO <<
"Got " <<
event->variant;
264 switch (ev_state.num_events) {
266 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
267 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
268 EXPECT_EQ(targets_event->result.ecus_count, 2);
269 EXPECT_EQ(targets_event->result.updates.size(), 2u);
270 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
271 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
272 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
277 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
278 const auto download_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
279 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
280 download_event->update.filename() ==
"secondary_firmware.txt");
281 EXPECT_TRUE(download_event->success);
285 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
286 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
287 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
288 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
289 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
290 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
291 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
292 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
298 ASSERT_EQ(
event->variant,
"InstallStarted");
299 const auto install_started = dynamic_cast<event::InstallStarted*>(
event.get());
300 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
306 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
307 const auto install_complete = dynamic_cast<event::InstallTargetComplete*>(
event.get());
308 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
309 EXPECT_TRUE(install_complete->success);
313 ASSERT_EQ(
event->variant,
"InstallStarted");
314 const auto install_started = dynamic_cast<event::InstallStarted*>(
event.get());
315 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
319 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
320 const auto install_complete = dynamic_cast<event::InstallTargetComplete*>(
event.get());
321 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
322 EXPECT_TRUE(install_complete->success);
326 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
327 const auto installs_complete = dynamic_cast<event::AllInstallsComplete*>(
event.get());
328 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 2);
329 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
330 data::ResultCode::Numeric::kOk);
331 EXPECT_EQ(installs_complete->result.ecu_reports[1].install_res.result_code.num_code,
332 data::ResultCode::Numeric::kOk);
336 ASSERT_EQ(
event->variant,
"PutManifestComplete");
337 const auto put_complete = dynamic_cast<event::PutManifestComplete*>(
event.get());
338 EXPECT_TRUE(put_complete->success);
339 ev_state.promise.set_value();
344 FAIL() <<
"Unexpected events!";
346 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
347 ASSERT_EQ(
event->variant,
"");
349 ++ev_state.num_events;
351 boost::signals2::connection conn = aktualizr.SetSignalHandler(f_cb);
353 aktualizr.Initialize();
354 aktualizr.UptaneCycle();
355 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
356 if (status != std::future_status::ready) {
357 FAIL() <<
"Timed out waiting for installation to complete.";
359 EXPECT_EQ(http->events_seen, 8);
364 HttpFakeSplit(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
365 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
367 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
371 std::string event_type =
event[
"eventType"][
"id"].asString();
372 if (event_type.find(
"Ecu") == 0) {
373 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
376 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
377 switch (events_seen) {
380 EXPECT_TRUE(event_type ==
"EcuDownloadStarted");
384 EXPECT_TRUE(event_type ==
"EcuDownloadCompleted");
388 EXPECT_TRUE(event_type ==
"EcuInstallationStarted");
392 EXPECT_TRUE(event_type ==
"EcuInstallationCompleted");
395 std::cout <<
"Unexpected event";
403 unsigned int events_seen{0};
418 auto http = std::make_shared<HttpFakeSplit>(temp_dir.Path(), fake_meta_dir);
419 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
421 auto storage = INvStorage::newStorage(conf.storage);
425 size_t num_events{0};
426 std::future<void> future;
427 std::promise<void> promise;
429 ev_state.future = ev_state.promise.get_future();
431 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
435 LOG_INFO <<
"Got " <<
event->variant;
436 switch (ev_state.num_events) {
438 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
439 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
440 EXPECT_EQ(targets_event->result.ecus_count, 2);
441 EXPECT_EQ(targets_event->result.updates.size(), 2u);
442 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
443 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
444 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
448 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
449 const auto download_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
450 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt");
451 EXPECT_TRUE(download_event->success);
455 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
456 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
457 EXPECT_EQ(downloads_complete->result.updates.size(), 1);
458 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt");
459 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
465 ASSERT_EQ(
event->variant,
"InstallStarted");
466 const auto install_started = dynamic_cast<event::InstallStarted*>(
event.get());
467 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
473 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
474 const auto install_complete = dynamic_cast<event::InstallTargetComplete*>(
event.get());
475 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
476 EXPECT_TRUE(install_complete->success);
480 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
481 const auto installs_complete = dynamic_cast<event::AllInstallsComplete*>(
event.get());
482 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 1);
483 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
484 data::ResultCode::Numeric::kOk);
488 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
489 const auto download_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
490 EXPECT_TRUE(download_event->update.filename() ==
"secondary_firmware.txt");
491 EXPECT_TRUE(download_event->success);
495 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
496 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
497 EXPECT_EQ(downloads_complete->result.updates.size(), 1);
498 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt");
499 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
503 ASSERT_EQ(
event->variant,
"InstallStarted");
504 const auto install_started = dynamic_cast<event::InstallStarted*>(
event.get());
505 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
509 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
510 const auto install_complete = dynamic_cast<event::InstallTargetComplete*>(
event.get());
511 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
512 EXPECT_TRUE(install_complete->success);
516 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
517 const auto installs_complete = dynamic_cast<event::AllInstallsComplete*>(
event.get());
518 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 1);
519 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
520 data::ResultCode::Numeric::kOk);
524 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
525 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
526 EXPECT_EQ(targets_event->result.ecus_count, 0);
527 EXPECT_EQ(targets_event->result.updates.size(), 0);
528 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
529 ev_state.promise.set_value();
534 FAIL() <<
"Unexpected events!";
536 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
537 ASSERT_EQ(
event->variant,
"");
539 ++ev_state.num_events;
541 boost::signals2::connection conn = aktualizr.SetSignalHandler(f_cb);
543 aktualizr.Initialize();
545 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
546 ASSERT_EQ(update_result.ecus_count, 2);
549 result::Download download_result = aktualizr.Download({update_result.updates[0]}).get();
550 ASSERT_EQ(download_result.status, result::DownloadStatus::kSuccess);
551 aktualizr.Install(download_result.updates);
553 download_result = aktualizr.Download({update_result.updates[1]}).get();
554 ASSERT_EQ(download_result.status, result::DownloadStatus::kSuccess);
555 aktualizr.Install(download_result.updates);
557 update_result = aktualizr.CheckUpdates().get();
558 ASSERT_EQ(update_result.status, result::UpdateStatus::kNoUpdatesAvailable);
560 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
561 if (status != std::future_status::ready) {
562 FAIL() <<
"Timed out waiting for installation to complete.";
564 EXPECT_EQ(http->events_seen, 8);
569 HttpFakePutCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
570 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
572 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
573 if (url.find(
"/manifest") != std::string::npos) {
576 return HttpFake::put(url,
data);
579 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
583 events.push_back(
event);
588 size_t count_event_with_type(
const std::string& event_type) {
589 auto c = std::count_if(events.cbegin(), events.cend(), [&event_type](
const Json::Value& v) {
590 return v[
"eventType"][
"id"].asString() == event_type;
592 return static_cast<size_t>(c);
595 unsigned int manifest_sends{0};
596 std::vector<Json::Value> events;
619 TEST(
Aktualizr, FullWithUpdatesNeedReboot) {
621 auto http = std::make_shared<HttpFakePutCounter>(temp_dir.Path(), fake_meta_dir);
622 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
623 conf.pacman.fake_need_reboot =
true;
627 auto storage = INvStorage::newStorage(conf.storage);
629 aktualizr.Initialize();
630 aktualizr.UptaneCycle();
634 boost::optional<Uptane::Target> pending_target;
635 storage->loadPrimaryInstalledVersions(
nullptr, &pending_target);
636 EXPECT_TRUE(!!pending_target);
640 EXPECT_EQ(http->manifest_sends, 1);
641 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationStarted"), 2);
642 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationApplied"), 1);
643 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationCompleted"), 1);
647 auto storage = INvStorage::newStorage(conf.storage);
649 aktualizr.Initialize();
652 boost::optional<Uptane::Target> pending_target;
653 storage->loadPrimaryInstalledVersions(
nullptr, &pending_target);
654 EXPECT_TRUE(!!pending_target);
657 EXPECT_EQ(update_res.status, result::UpdateStatus::kError);
660 boost::filesystem::remove(conf.bootloader.reboot_sentinel_dir / conf.bootloader.reboot_sentinel_name);
664 EXPECT_EQ(http->manifest_sends, 1);
665 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationCompleted"), 1);
669 auto storage = INvStorage::newStorage(conf.storage);
671 aktualizr.Initialize();
674 EXPECT_EQ(update_res.status, result::UpdateStatus::kNoUpdatesAvailable);
677 boost::optional<Uptane::Target> current_target;
678 boost::optional<Uptane::Target> pending_target;
679 storage->loadPrimaryInstalledVersions(¤t_target, &pending_target);
680 EXPECT_TRUE(!!current_target);
681 EXPECT_FALSE(!!pending_target);
684 boost::optional<Uptane::Target> sec_current_target;
685 boost::optional<Uptane::Target> sec_pending_target;
686 storage->loadInstalledVersions(
"secondary_ecu_serial", &sec_current_target, &sec_pending_target);
687 EXPECT_TRUE(!!sec_current_target);
688 EXPECT_FALSE(!!sec_pending_target);
692 EXPECT_EQ(http->manifest_sends, 3);
693 EXPECT_EQ(http->count_event_with_type(
"EcuInstallationCompleted"), 2);
696 for (
const Json::Value&
event : http->events) {
697 std::cout <<
"got event " <<
event[
"eventType"][
"id"].asString() <<
"\n";
698 EXPECT_EQ(
event[
"event"][
"correlationId"].asString(),
"id0");
704 class HttpInstallationFailed :
public HttpFake {
706 HttpInstallationFailed(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
707 :
HttpFake(test_dir_in,
"hasupdates", meta_dir_in) {}
709 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
712 for (
auto& event_data :
data) {
713 auto event_id = event_data[
"eventType"][
"id"].asString();
714 auto ecu = event_data[
"event"][
"ecu"].asString();
715 auto correlationID = event_data[
"event"][
"correlationId"].asString();
717 if (event_id ==
"EcuInstallationCompleted") {
718 install_completion_status_[ecu] = event_data[
"event"][
"success"].asBool();
720 report_events_.push_back(event_id);
725 bool checkReceivedReports(
const std::vector<std::string>& expected_event_order) {
727 auto received_event_it = report_events_.begin();
729 for (
auto& expected_event : expected_event_order) {
730 auto received_event = *received_event_it;
731 if (expected_event != received_event) {
740 bool wasInstallSuccessful(
const std::string& ecu_serial)
const {
741 auto find_it = install_completion_status_.find(ecu_serial);
742 if (find_it == install_completion_status_.end()) {
745 return (*find_it).second;
748 void clearReportEvents() { report_events_.clear(); }
751 std::vector<std::string> report_events_;
752 std::unordered_map<std::string, bool> install_completion_status_;
758 functor_ = std::bind(&EventHandler::operator(),
this, std::placeholders::_1);
762 void operator()(
const std::shared_ptr<event::BaseEvent>&
event) {
763 ASSERT_NE(
event,
nullptr);
764 received_events_.push_back(
event->variant);
767 bool checkReceivedEvents(
const std::vector<std::string>& expected_event_order) {
769 auto received_event_it = received_events_.begin();
771 for (
auto& expected_event : expected_event_order) {
772 auto received_event = *received_event_it;
773 if (expected_event != received_event) {
778 if (received_event ==
"DownloadProgressReport") {
779 while (*(++received_event_it) ==
"DownloadProgressReport") {
789 std::function<void(std::shared_ptr<event::BaseEvent>)> functor_;
790 std::vector<std::string> received_events_{};
805 auto http_server_mock = std::make_shared<HttpInstallationFailed>(temp_dir.Path(), fake_meta_dir);
806 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
807 conf.pacman.fake_need_reboot =
true;
808 conf.uptane.force_install_completion =
true;
809 conf.uptane.polling_sec = 0;
810 auto storage = INvStorage::newStorage(conf.storage);
812 std::vector<std::string> expected_event_order = {
813 "SendDeviceDataComplete",
"UpdateCheckComplete",
"DownloadProgressReport",
"DownloadTargetComplete",
814 "DownloadProgressReport",
"DownloadTargetComplete",
"AllDownloadsComplete",
"InstallStarted",
815 "InstallTargetComplete",
"InstallStarted",
"InstallTargetComplete",
"AllInstallsComplete"};
817 std::vector<std::string> expected_report_order = {
818 "EcuDownloadStarted",
"EcuDownloadCompleted",
"EcuDownloadStarted",
"EcuDownloadCompleted",
819 "EcuInstallationStarted",
"EcuInstallationApplied",
"EcuInstallationStarted",
"EcuInstallationCompleted"};
821 const std::string primary_ecu_id =
"CA:FE:A6:D2:84:9D";
822 const std::string secondary_ecu_id =
"secondary_ecu_serial";
827 EventHandler event_hdlr(aktualizr);
831 boost::optional<Uptane::Target> current_version;
832 boost::optional<Uptane::Target> pending_version;
833 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
837 EXPECT_FALSE(!!pending_version);
838 EXPECT_FALSE(!!current_version);
840 auto aktualizr_cycle_thread = aktualizr.
RunForever();
841 auto aktualizr_cycle_thread_status = aktualizr_cycle_thread.wait_for(std::chrono::seconds(20));
843 ASSERT_EQ(aktualizr_cycle_thread_status, std::future_status::ready);
844 EXPECT_TRUE(aktualizr.uptane_client()->isInstallCompletionRequired());
845 EXPECT_TRUE(event_hdlr.checkReceivedEvents(expected_event_order));
846 EXPECT_TRUE(aktualizr.uptane_client()->hasPendingUpdates());
847 EXPECT_TRUE(http_server_mock->checkReceivedReports(expected_report_order));
850 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
851 EXPECT_TRUE(http_server_mock->wasInstallSuccessful(secondary_ecu_id));
855 std::string correlation_id;
856 ASSERT_TRUE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
857 EXPECT_EQ(dev_installation_res.result_code.num_code, data::ResultCode::Numeric::kNeedCompletion);
859 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
860 ASSERT_TRUE(storage->loadEcuInstallationResults(&ecu_installation_res));
861 EXPECT_EQ(ecu_installation_res.size(), 2);
863 for (
const auto& ecu_install_res : ecu_installation_res) {
864 auto ecu_id = ecu_install_res.first.ToString();
866 if (ecu_id == primary_ecu_id) {
867 EXPECT_EQ(ecu_install_res.second.result_code.num_code, data::ResultCode::Numeric::kNeedCompletion);
868 EXPECT_EQ(ecu_install_res.second.success,
false);
869 EXPECT_EQ(ecu_install_res.second.description,
"Application successful, need reboot");
871 }
else if (ecu_id == secondary_ecu_id) {
872 EXPECT_EQ(ecu_install_res.second.result_code.num_code, data::ResultCode::Numeric::kOk);
873 EXPECT_EQ(ecu_install_res.second.success,
true);
874 EXPECT_EQ(ecu_install_res.second.description,
"");
877 FAIL() <<
"Unexpected ECU serial: " << ecu_install_res.first;
881 pending_version = boost::none;
882 current_version = boost::none;
884 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
885 EXPECT_FALSE(!!current_version);
886 EXPECT_TRUE(!!pending_version);
887 EXPECT_TRUE(pending_version->IsValid());
889 pending_version = boost::none;
890 current_version = boost::none;
892 ASSERT_TRUE(storage->loadInstalledVersions(secondary_ecu_id, ¤t_version, &pending_version));
893 EXPECT_TRUE(!!current_version);
894 EXPECT_TRUE(current_version->IsValid());
895 EXPECT_FALSE(!!pending_version);
900 fault_injection_init();
901 fiu_enable(
"fake_install_finalization_failure", 1,
nullptr, 0);
902 http_server_mock->clearReportEvents();
905 EventHandler event_hdlr(aktualizr);
908 fiu_disable(
"fake_install_finalization_failure");
910 EXPECT_FALSE(aktualizr.uptane_client()->hasPendingUpdates());
911 EXPECT_TRUE(http_server_mock->checkReceivedReports({
"EcuInstallationCompleted"}));
912 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
916 std::string correlation_id;
920 EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
925 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
926 EXPECT_FALSE(storage->loadEcuInstallationResults(&ecu_installation_res));
929 boost::optional<Uptane::Target> current_version;
930 boost::optional<Uptane::Target> pending_version;
932 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
933 EXPECT_FALSE(!!current_version);
934 EXPECT_FALSE(!!pending_version);
936 current_version = boost::none;
937 pending_version = boost::none;
939 ASSERT_TRUE(storage->loadInstalledVersions(secondary_ecu_id, ¤t_version, &pending_version));
940 EXPECT_TRUE(!!current_version);
941 EXPECT_FALSE(!!pending_version);
956 std::vector<std::string> expected_event_order = {
957 "UpdateCheckComplete",
"DownloadProgressReport",
"DownloadTargetComplete",
"DownloadProgressReport",
958 "DownloadTargetComplete",
"AllDownloadsComplete",
"InstallStarted",
"InstallTargetComplete",
959 "InstallStarted",
"InstallTargetComplete",
"AllInstallsComplete",
"PutManifestComplete"};
961 std::vector<std::string> expected_report_order = {
962 "EcuDownloadStarted",
"EcuDownloadCompleted",
"EcuDownloadStarted",
"EcuDownloadCompleted",
963 "EcuInstallationStarted",
"EcuInstallationCompleted",
"EcuInstallationStarted",
"EcuInstallationCompleted"};
965 const std::string primary_ecu_id =
"CA:FE:A6:D2:84:9D";
966 const std::string secondary_ecu_id =
"secondary_ecu_serial";
970 auto http_server_mock = std::make_shared<HttpInstallationFailed>(temp_dir.Path(), fake_meta_dir);
971 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
972 auto storage = INvStorage::newStorage(conf.storage);
974 fault_injection_init();
975 fiu_enable(
"fake_package_install", 1,
nullptr, 0);
978 EventHandler event_hdlr(aktualizr);
982 boost::optional<Uptane::Target> current_version;
983 boost::optional<Uptane::Target> pending_version;
985 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
987 EXPECT_FALSE(!!pending_version);
988 EXPECT_FALSE(!!current_version);
991 aktualizr.uptane_client()->completeInstall();
993 EXPECT_TRUE(event_hdlr.checkReceivedEvents(expected_event_order));
994 EXPECT_FALSE(aktualizr.uptane_client()->hasPendingUpdates());
995 EXPECT_TRUE(http_server_mock->checkReceivedReports(expected_report_order));
996 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
997 EXPECT_TRUE(http_server_mock->wasInstallSuccessful(secondary_ecu_id));
1001 std::string correlation_id;
1005 EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
1007 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
1008 EXPECT_FALSE(storage->loadEcuInstallationResults(&ecu_installation_res));
1009 EXPECT_EQ(ecu_installation_res.size(), 0);
1011 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
1015 EXPECT_FALSE(!!current_version);
1016 EXPECT_FALSE(!!pending_version);
1018 fiu_disable(
"fake_package_install");
1024 auto http_server_mock = std::make_shared<HttpInstallationFailed>(temp_dir.Path(), fake_meta_dir);
1025 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
1026 auto storage = INvStorage::newStorage(conf.storage);
1027 const std::string sec_fault_name = std::string(
"secondary_install_") + secondary_ecu_id;
1029 fault_injection_init();
1030 fault_injection_enable(
"fake_package_install", 1,
"PRIMFAIL", 0);
1031 fault_injection_enable(sec_fault_name.c_str(), 1,
"SECFAIL", 0);
1034 EventHandler event_hdlr(aktualizr);
1038 boost::optional<Uptane::Target> current_version;
1039 boost::optional<Uptane::Target> pending_version;
1041 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
1043 EXPECT_FALSE(!!pending_version);
1044 EXPECT_FALSE(!!current_version);
1047 aktualizr.uptane_client()->completeInstall();
1049 EXPECT_TRUE(event_hdlr.checkReceivedEvents(expected_event_order));
1050 EXPECT_FALSE(aktualizr.uptane_client()->hasPendingUpdates());
1051 EXPECT_TRUE(http_server_mock->checkReceivedReports(expected_report_order));
1052 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(primary_ecu_id));
1053 EXPECT_FALSE(http_server_mock->wasInstallSuccessful(secondary_ecu_id));
1055 LOG_INFO << http_server_mock->last_manifest;
1056 Json::Value installation_report = http_server_mock->last_manifest[
"signed"][
"installation_report"][
"report"];
1057 EXPECT_EQ(installation_report[
"items"][0][
"result"][
"code"].asString(),
"PRIMFAIL");
1058 EXPECT_EQ(installation_report[
"items"][1][
"result"][
"code"].asString(),
"SECFAIL");
1059 EXPECT_EQ(installation_report[
"result"][
"code"].asString(),
"primary_hw:PRIMFAIL|secondary_hw:SECFAIL");
1063 std::string correlation_id;
1067 EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_installation_res, &report, &correlation_id));
1069 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_installation_res;
1070 EXPECT_FALSE(storage->loadEcuInstallationResults(&ecu_installation_res));
1071 EXPECT_EQ(ecu_installation_res.size(), 0);
1073 ASSERT_TRUE(storage->loadInstalledVersions(primary_ecu_id, ¤t_version, &pending_version));
1077 EXPECT_FALSE(!!current_version);
1078 EXPECT_FALSE(!!pending_version);
1080 fault_injection_disable(
"fake_package_install");
1081 fault_injection_disable(sec_fault_name.c_str());
1085 #endif // FIU_ENABLE
1099 TEST(
Aktualizr, AutoRebootAfterUpdate) {
1101 auto http = std::make_shared<HttpFakePutCounter>(temp_dir.Path(), fake_meta_dir);
1102 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1103 conf.pacman.fake_need_reboot =
true;
1104 conf.uptane.force_install_completion =
true;
1105 conf.uptane.polling_sec = 0;
1109 auto storage = INvStorage::newStorage(conf.storage);
1113 auto aktualizr_cycle_thread = aktualizr.
RunForever();
1114 auto aktualizr_cycle_thread_status = aktualizr_cycle_thread.wait_for(std::chrono::seconds(20));
1117 EXPECT_EQ(aktualizr_cycle_thread_status, std::future_status::ready);
1118 EXPECT_TRUE(aktualizr.uptane_client()->isInstallCompletionRequired());
1123 auto storage = INvStorage::newStorage(conf.storage);
1129 EXPECT_EQ(update_res.status, result::UpdateStatus::kNoUpdatesAvailable);
1132 boost::optional<Uptane::Target> current_target;
1133 boost::optional<Uptane::Target> pending_target;
1134 storage->loadPrimaryInstalledVersions(¤t_target, &pending_target);
1135 EXPECT_TRUE(!!current_target);
1136 EXPECT_FALSE(!!pending_target);
1137 EXPECT_EQ(http->manifest_sends, 4);
1147 TEST(
Aktualizr, FullMultipleSecondaries) {
1149 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"multisec", fake_meta_dir);
1150 Config conf(
"tests/config/basic.toml");
1151 conf.provision.primary_ecu_serial =
"testecuserial";
1152 conf.provision.primary_ecu_hardware_id =
"testecuhwid";
1153 conf.storage.path = temp_dir.Path();
1154 conf.tls.server = http->tls_server;
1155 conf.uptane.director_server = http->tls_server +
"/director";
1156 conf.uptane.repo_server = http->tls_server +
"/repo";
1159 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"sec_serial1",
"sec_hw1");
1161 auto storage = INvStorage::newStorage(conf.storage);
1163 UptaneTestCommon::addDefaultSecondary(conf, temp_dir2,
"sec_serial2",
"sec_hw2");
1164 ASSERT_NO_THROW(aktualizr.
AddSecondary(std::make_shared<Primary::VirtualSecondary>(
1165 Primary::VirtualSecondaryConfig::create_from_file(conf.uptane.secondary_config_file)[0])));
1170 bool allcomplete{
false};
1171 bool manifest{
false};
1172 std::future<void> future;
1173 std::promise<void> promise;
1175 ev_state.future = ev_state.promise.get_future();
1177 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1178 if (
event->variant ==
"InstallStarted") {
1180 }
else if (
event->variant ==
"InstallTargetComplete") {
1181 ++ev_state.complete;
1182 }
else if (
event->variant ==
"AllInstallsComplete") {
1183 ev_state.allcomplete =
true;
1184 }
else if (
event->variant ==
"PutManifestComplete") {
1185 ev_state.manifest =
true;
1189 if (ev_state.allcomplete && ev_state.complete == 2 && ev_state.manifest) {
1190 ev_state.promise.set_value();
1198 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1199 if (status != std::future_status::ready) {
1200 FAIL() <<
"Timed out waiting for installation to complete.";
1203 EXPECT_EQ(ev_state.started, 2);
1204 EXPECT_EQ(ev_state.complete, 2);
1206 const Json::Value manifest = http->last_manifest[
"signed"];
1207 const Json::Value manifest_versions = manifest[
"ecu_version_manifests"];
1210 EXPECT_EQ(manifest_versions[
"sec_serial1"][
"signed"][
"installed_image"][
"filepath"].asString(),
1211 "secondary_firmware.txt");
1212 EXPECT_EQ(manifest_versions[
"sec_serial1"][
"signed"][
"installed_image"][
"fileinfo"][
"length"].asUInt(), 15);
1213 EXPECT_EQ(manifest_versions[
"sec_serial2"][
"signed"][
"installed_image"][
"filepath"].asString(),
1214 "secondary_firmware2.txt");
1215 EXPECT_EQ(manifest_versions[
"sec_serial2"][
"signed"][
"installed_image"][
"fileinfo"][
"length"].asUInt(), 21);
1218 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"].size(), 2);
1219 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"][0][
"ecu"].asString(),
"sec_serial1");
1220 EXPECT_TRUE(manifest[
"installation_report"][
"report"][
"items"][0][
"result"][
"success"].asBool());
1221 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"][1][
"ecu"].asString(),
"sec_serial2");
1222 EXPECT_TRUE(manifest[
"installation_report"][
"report"][
"items"][1][
"result"][
"success"].asBool());
1230 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"noupdates", fake_meta_dir);
1231 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1233 auto storage = INvStorage::newStorage(conf.storage);
1237 size_t num_events{0};
1238 std::future<void> future;
1239 std::promise<void> promise;
1241 ev_state.future = ev_state.promise.get_future();
1243 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1247 LOG_INFO <<
"Got " <<
event->variant;
1248 switch (ev_state.num_events) {
1250 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1251 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1252 EXPECT_EQ(targets_event->result.ecus_count, 0);
1253 EXPECT_EQ(targets_event->result.updates.size(), 0);
1254 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
1258 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1259 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1260 EXPECT_EQ(targets_event->result.ecus_count, 0);
1261 EXPECT_EQ(targets_event->result.updates.size(), 0);
1262 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
1263 ev_state.promise.set_value();
1268 FAIL() <<
"Unexpected events!";
1270 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1271 ASSERT_EQ(
event->variant,
"");
1273 ++ev_state.num_events;
1280 EXPECT_EQ(
result.ecus_count, 0);
1281 EXPECT_EQ(
result.updates.size(), 0);
1282 EXPECT_EQ(
result.status, result::UpdateStatus::kNoUpdatesAvailable);
1286 EXPECT_EQ(
result.ecus_count, 0);
1287 EXPECT_EQ(
result.updates.size(), 0);
1288 EXPECT_EQ(
result.status, result::UpdateStatus::kNoUpdatesAvailable);
1290 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1291 if (status != std::future_status::ready) {
1292 FAIL() <<
"Timed out waiting for metadata to be fetched.";
1295 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1306 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1307 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1309 auto storage = INvStorage::newStorage(conf.storage);
1313 size_t num_events{0};
1314 std::future<void> future;
1315 std::promise<void> promise;
1317 ev_state.future = ev_state.promise.get_future();
1319 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1323 LOG_INFO <<
"Got " <<
event->variant;
1324 switch (ev_state.num_events) {
1326 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1327 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1328 EXPECT_EQ(downloads_complete->result.updates.size(), 0);
1329 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kError);
1333 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1334 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1335 EXPECT_EQ(targets_event->result.ecus_count, 2);
1336 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1337 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1338 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1339 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1344 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
1345 const auto download_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
1346 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1347 download_event->update.filename() ==
"secondary_firmware.txt");
1348 EXPECT_TRUE(download_event->success);
1352 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1353 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1354 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1355 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1356 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1357 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1358 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1359 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1360 ev_state.promise.set_value();
1365 FAIL() <<
"Unexpected events!";
1367 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1368 ASSERT_EQ(
event->variant,
"");
1370 ++ev_state.num_events;
1377 EXPECT_EQ(
result.updates.size(), 0);
1378 EXPECT_EQ(
result.status, result::DownloadStatus::kError);
1380 aktualizr.
Download(update_result.updates);
1382 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1383 if (status != std::future_status::ready) {
1384 FAIL() <<
"Timed out waiting for downloads to complete.";
1387 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1392 using Responses = std::vector<std::pair<std::string, HttpResponse>>;
1395 HttpDownloadFailure(
const boost::filesystem::path& test_dir_in,
const Responses& file_to_response, std::string flavor,
1396 const boost::filesystem::path& meta_dir_in)
1397 :
HttpFake(test_dir_in, flavor, meta_dir_in) {
1398 for (
auto resp : file_to_response) {
1399 url_to_response_[tls_server + target_dir_ + resp.first] = resp.second;
1403 HttpResponse download(
const std::string& url, curl_write_callback write_cb, curl_xferinfo_callback progress_cb,
1404 void* userp, curl_off_t from)
override {
1405 const auto found_response_it = url_to_response_.find(url);
1406 if (found_response_it == url_to_response_.end()) {
1407 return HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error");
1410 auto response = url_to_response_.at(url);
1411 if (response.isOk()) {
1412 return HttpFake::download(url, write_cb, progress_cb, userp, from);
1415 return url_to_response_[url];
1419 const std::string target_dir_{
"/repo/targets/"};
1420 std::map<std::string, HttpResponse> url_to_response_;
1432 class DownloadEventHandler {
1434 DownloadEventHandler(
Aktualizr& aktualizr) {
1435 functor_ = std::bind(&DownloadEventHandler::operator(),
this, std::placeholders::_1);
1439 void operator()(
const std::shared_ptr<event::BaseEvent>&
event) {
1440 ASSERT_NE(
event,
nullptr);
1443 auto download_target_complete_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
1444 auto target_filename = download_target_complete_event->update.filename();
1445 download_status[target_filename] = download_target_complete_event->success;
1448 auto all_download_complete_event = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1449 all_download_completed_status = all_download_complete_event->result;
1454 std::map<std::string, bool> download_status;
1458 std::function<void(std::shared_ptr<event::BaseEvent>)> functor_;
1462 HttpDownloadFailure::Responses downloadResponse;
1463 std::vector<std::pair<std::string, bool>> downloadResult;
1467 TestParams test_case_params[]{
1469 {{
"primary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")},
1470 {
"secondary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")}},
1471 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
false}},
1472 result::DownloadStatus::kError},
1474 {{
"primary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")},
1475 {
"secondary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")}},
1476 {{
"primary_firmware.txt",
true}, {
"secondary_firmware.txt",
false}},
1477 result::DownloadStatus::kPartialSuccess},
1479 {{
"primary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")},
1480 {
"secondary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")}},
1481 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
true}},
1482 result::DownloadStatus::kPartialSuccess}};
1484 for (
auto test_params : test_case_params) {
1487 auto http = std::make_shared<HttpDownloadFailure>(temp_dir.Path(), test_params.downloadResponse,
"hasupdates",
1489 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1490 auto storage = INvStorage::newStorage(conf.storage);
1493 DownloadEventHandler event_hdlr{aktualizr};
1497 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1500 for (
auto& expected_result : test_params.downloadResult) {
1502 ASSERT_NE(event_hdlr.download_status.find(expected_result.first), event_hdlr.download_status.end());
1503 EXPECT_EQ(event_hdlr.download_status.at(expected_result.first), expected_result.second);
1505 EXPECT_EQ(event_hdlr.all_download_completed_status.status, test_params.allDownloadsStatus);
1515 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1516 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1518 auto storage = INvStorage::newStorage(conf.storage);
1525 EXPECT_EQ(targets.size(), 0);
1527 aktualizr.
Download(update_result.updates).get();
1530 EXPECT_EQ(targets.size(), 2);
1538 EXPECT_EQ(targets.size(), 0);
1547 const boost::filesystem::path local_metadir = temp_dir /
"metadir";
1548 Utils::createDirectories(local_metadir, S_IRWXU);
1549 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", local_metadir /
"repo");
1551 UptaneRepo repo{local_metadir,
"2021-07-04T16:33:27Z",
"id0"};
1552 repo.generateRepo(KeyType::kED25519);
1553 const std::string hwid =
"primary_hw";
1554 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1555 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1558 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1559 auto storage = INvStorage::newStorage(conf.storage);
1563 boost::signals2::connection ac_conn =
1564 aktualizr.
SetSignalHandler(std::bind(targets_autoclean_cb, std::ref(aktualizr), std::placeholders::_1));
1569 aktualizr.
Download(update_result.updates).get();
1574 EXPECT_TRUE(install_result.dev_report.success);
1577 ASSERT_EQ(targets.size(), 1);
1578 EXPECT_EQ(targets[0].filename(),
"primary_firmware.txt");
1582 repo.emptyTargets();
1583 repo.addImage(fake_meta_dir /
"fake_meta/dummy_firmware.txt",
"dummy_firmware.txt", hwid,
"", {});
1584 repo.addTarget(
"dummy_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1589 aktualizr.
Download(update_result.updates).get();
1594 EXPECT_TRUE(install_result.dev_report.success);
1598 ASSERT_EQ(targets.size(), 2);
1602 repo.emptyTargets();
1603 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1604 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1609 aktualizr.
Download(update_result.updates).get();
1614 EXPECT_TRUE(install_result.dev_report.success);
1618 ASSERT_EQ(targets.size(), 2);
1622 repo.emptyTargets();
1623 repo.addImage(fake_meta_dir /
"fake_meta/secondary_firmware.txt",
"secondary_firmware.txt", hwid,
"", {});
1624 repo.addTarget(
"secondary_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);
1641 Aktualizr::InstallationLog log = aktualizr.GetInstallationLog();
1642 ASSERT_EQ(log.size(), 2);
1644 EXPECT_EQ(log[0].installs.size(), 4);
1645 EXPECT_EQ(log[1].installs.size(), 0);
1647 std::vector<std::string> fws{
"primary_firmware.txt",
"dummy_firmware.txt",
"primary_firmware.txt",
1648 "secondary_firmware.txt"};
1649 for (
auto it = log[0].installs.begin(); it < log[0].installs.end(); it++) {
1650 auto idx = static_cast<size_t>(it - log[0].installs.begin());
1651 EXPECT_EQ(it->filename(), fws[idx]);
1662 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1663 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1665 auto storage = INvStorage::newStorage(conf.storage);
1669 size_t num_events{0};
1670 std::vector<Uptane::Target> updates;
1671 std::future<void> future;
1672 std::promise<void> promise;
1674 ev_state.future = ev_state.promise.get_future();
1676 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1682 LOG_INFO <<
"Got " <<
event->variant;
1683 switch (ev_state.num_events) {
1685 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
1686 const auto installs_complete = dynamic_cast<event::AllInstallsComplete*>(
event.get());
1687 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 0);
1691 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1692 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1693 EXPECT_EQ(targets_event->result.ecus_count, 2);
1694 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1695 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1696 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1697 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1698 ev_state.updates = targets_event->result.updates;
1703 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
1704 const auto download_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
1705 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1706 download_event->update.filename() ==
"secondary_firmware.txt");
1707 EXPECT_TRUE(download_event->success);
1711 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1712 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1713 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1714 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1715 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1716 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1717 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1718 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1724 ASSERT_EQ(
event->variant,
"InstallStarted");
1725 const auto install_started = dynamic_cast<event::InstallStarted*>(
event.get());
1726 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1732 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
1733 const auto install_complete = dynamic_cast<event::InstallTargetComplete*>(
event.get());
1734 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1735 EXPECT_TRUE(install_complete->success);
1739 ASSERT_EQ(
event->variant,
"InstallStarted");
1740 const auto install_started = dynamic_cast<event::InstallStarted*>(
event.get());
1741 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
1745 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
1746 const auto install_complete = dynamic_cast<event::InstallTargetComplete*>(
event.get());
1747 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
1748 EXPECT_TRUE(install_complete->success);
1752 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
1753 const auto installs_complete = dynamic_cast<event::AllInstallsComplete*>(
event.get());
1754 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 2);
1755 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
1756 data::ResultCode::Numeric::kOk);
1757 EXPECT_EQ(installs_complete->result.ecu_reports[1].install_res.result_code.num_code,
1758 data::ResultCode::Numeric::kOk);
1759 ev_state.promise.set_value();
1764 FAIL() <<
"Unexpected events!";
1766 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1767 ASSERT_EQ(
event->variant,
"");
1769 ++ev_state.num_events;
1775 Json::Value primary_json;
1776 primary_json[
"hashes"][
"sha256"] =
"74e653bbf6c00a88b21f0992159b1002f5af38506e6d2fbc7eb9846711b2d75f";
1777 primary_json[
"hashes"][
"sha512"] =
1778 "91814ad1c13ebe2af8d65044893633c4c3ce964edb8cb58b0f357406c255f7be94f42547e108b300346a42cd57662e4757b9d843b7acbc09"
1780 primary_json[
"length"] = 2;
1781 Uptane::Target primary_target(
"primary_firmware.txt", primary_json);
1783 Json::Value secondary_json;
1784 secondary_json[
"hashes"][
"sha256"] =
"1bbb15aa921ffffd5079567d630f43298dbe5e7cbc1b14e0ccdd6718fde28e47";
1785 secondary_json[
"hashes"][
"sha512"] =
1786 "7dbae4c36a2494b731a9239911d3085d53d3e400886edb4ae2b9b78f40bda446649e83ba2d81653f614cc66f5dd5d4dbd95afba854f148af"
1788 secondary_json[
"length"] = 2;
1789 Uptane::Target secondary_target(
"secondary_firmware.txt", secondary_json);
1793 EXPECT_EQ(
result.ecu_reports.size(), 0);
1795 EXPECT_THROW(aktualizr.
OpenStoredTarget(primary_target).get(), std::runtime_error)
1796 <<
"Primary firmware is present in storage before the download";
1797 EXPECT_THROW(aktualizr.
OpenStoredTarget(secondary_target).get(), std::runtime_error)
1798 <<
"Secondary firmware is present in storage before the download";
1801 aktualizr.
Download(update_result.updates).get();
1803 <<
"Primary firmware is not present in storage after the download";
1805 <<
"Secondary firmware is not present in storage after the download";
1808 aktualizr.
Install(update_result.updates);
1810 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1811 if (status != std::future_status::ready) {
1812 FAIL() <<
"Timed out waiting for installation to complete.";
1823 TEST(
Aktualizr, ReportDownloadProgress) {
1827 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1828 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1829 auto storage = INvStorage::newStorage(conf.storage);
1832 unsigned int report_counter = {0};
1833 std::shared_ptr<const event::DownloadProgressReport> lastProgressReport{
nullptr};
1835 std::function<void(std::shared_ptr<event::BaseEvent>
event)> report_event_hdlr =
1836 [&](
const std::shared_ptr<event::BaseEvent>&
event) {
1837 ASSERT_NE(
event,
nullptr);
1842 auto download_progress_event = std::dynamic_pointer_cast<event::DownloadProgressReport>(
event);
1843 ASSERT_NE(download_progress_event,
nullptr);
1844 ASSERT_NE(download_progress_event.get(),
nullptr);
1845 if (lastProgressReport) {
1846 EXPECT_GE(download_progress_event->progress, lastProgressReport->progress);
1848 lastProgressReport = download_progress_event;
1856 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1859 update_result.updates.pop_back();
1862 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
1864 ASSERT_NE(lastProgressReport,
nullptr);
1865 ASSERT_NE(lastProgressReport.get(),
nullptr);
1866 EXPECT_TRUE(event::DownloadProgressReport::isDownloadCompleted(*lastProgressReport));
1867 EXPECT_GT(report_counter, 1);
1872 HttpFakeCampaign(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
1873 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
1875 HttpResponse get(
const std::string& url, int64_t maxsize)
override {
1876 EXPECT_NE(url.find(
"campaigner/"), std::string::npos);
1877 boost::filesystem::path path = meta_dir / url.substr(tls_server.size() + strlen(
"campaigner/"));
1879 if (url.find(
"campaigner/campaigns") != std::string::npos) {
1880 return HttpResponse(Utils::readFile(path.parent_path() /
"campaigner/campaigns.json"), 200, CURLE_OK,
"");
1882 return HttpFake::get(url, maxsize);
1885 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
1887 for (
auto it =
data.begin(); it !=
data.end(); it++) {
1889 auto id = ev[
"eventType"][
"id"];
1890 if (
id ==
"campaign_accepted" ||
id ==
"campaign_declined" ||
id ==
"campaign_postponed") {
1891 seen_events.push_back(ev);
1897 std::vector<Json::Value> seen_events;
1902 bool campaignaccept_seen{
false};
1903 bool campaigndecline_seen{
false};
1904 bool campaignpostpone_seen{
false};
1906 void handler(
const std::shared_ptr<event::BaseEvent>&
event) {
1907 std::cout <<
event->variant <<
"\n";
1908 if (
event->variant ==
"CampaignCheckComplete") {
1909 auto concrete_event = std::static_pointer_cast<event::CampaignCheckComplete>(
event);
1910 EXPECT_EQ(concrete_event->result.campaigns.size(), 1);
1911 EXPECT_EQ(concrete_event->result.campaigns[0].name,
"campaign1");
1912 EXPECT_EQ(concrete_event->result.campaigns[0].id,
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
1913 EXPECT_EQ(concrete_event->result.campaigns[0].size, 62470);
1914 EXPECT_EQ(concrete_event->result.campaigns[0].autoAccept,
true);
1915 EXPECT_EQ(concrete_event->result.campaigns[0].description,
"this is my message to show on the device");
1916 }
else if (
event->variant ==
"CampaignAcceptComplete") {
1917 campaignaccept_seen =
true;
1918 }
else if (
event->variant ==
"CampaignDeclineComplete") {
1919 campaigndecline_seen =
true;
1920 }
else if (
event->variant ==
"CampaignPostponeComplete") {
1921 campaignpostpone_seen =
true;
1942 TEST(
Aktualizr, CampaignCheckAndControl) {
1944 auto http = std::make_shared<HttpFakeCampaign>(temp_dir.Path(), fake_meta_dir);
1945 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1950 auto storage = INvStorage::newStorage(conf.storage);
1952 aktualizr.
SetSignalHandler(std::bind(&CampaignEvents::handler, &campaign_events, std::placeholders::_1));
1957 EXPECT_EQ(
result.campaigns.size(), 1);
1960 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Accept).get();
1962 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Decline).get();
1964 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Postpone).get();
1967 ASSERT_EQ(http->seen_events.size(), 3);
1968 for (
const auto& ev : http->seen_events) {
1969 EXPECT_EQ(ev[
"event"][
"campaignId"],
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
1971 EXPECT_TRUE(campaign_events.campaignaccept_seen);
1972 EXPECT_TRUE(campaign_events.campaigndecline_seen);
1973 EXPECT_TRUE(campaign_events.campaignpostpone_seen);
1978 HttpFakeNoCorrelationId(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
1979 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
1981 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
1985 EXPECT_EQ(
event[
"event"][
"correlationId"].asString(),
"");
1990 unsigned int events_seen{0};
1997 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/repo", meta_dir.Path() /
"repo");
1998 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/director", meta_dir.Path() /
"director");
1999 auto http = std::make_shared<HttpFakeNoCorrelationId>(temp_dir.Path(), meta_dir.Path());
2004 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2006 auto storage = INvStorage::newStorage(conf.storage);
2011 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
2014 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
2017 for (
const auto& r : install_result.ecu_reports) {
2018 EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
2022 EXPECT_EQ(http->events_seen, 8);
2027 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", fake_meta_dir);
2030 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2032 auto storage = INvStorage::newStorage(conf.storage);
2036 Json::Value custom = Utils::parseJSON(R
"({"test_field":"test_value"})");
2037 ASSERT_EQ(custom["test_field"].asString(),
"test_value");
2038 ASSERT_EQ(
true, aktualizr.
SendManifest(custom).get()) <<
"Failed to upload manifest with HttpFake server";
2039 EXPECT_EQ(http->last_manifest[
"signed"][
"custom"], custom);
2050 std::function<void(std::shared_ptr<event::BaseEvent>)> Signal() {
2051 return std::bind(&CountUpdateCheckEvents::count,
this, std::placeholders::_1);
2054 void count(std::shared_ptr<event::BaseEvent>
event) {
2055 std::cout <<
event->variant <<
"\n";
2056 if (
event->variant ==
"UpdateCheckComplete") {
2058 if (std::static_pointer_cast<event::UpdateCheckComplete>(
event)->
result.status == result::UpdateStatus::kError) {
2064 int total_events()
const {
return total_events_; }
2065 int error_events()
const {
return error_events_; }
2068 int total_events_{0};
2069 int error_events_{0};
2074 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
2076 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2078 auto storage = INvStorage::newStorage(conf.storage);
2083 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2085 std::vector<std::future<result::UpdateCheck>> futures;
2086 for (
int i = 0; i < 5; ++i) {
2090 for (
auto& f : futures) {
2095 EXPECT_EQ(counter.total_events(), 5);
2101 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter2.Signal());
2104 std::future<result::UpdateCheck> ft = aktualizr.
CheckUpdates();
2105 for (
int i = 0; i < 99; ++i) {
2110 EXPECT_LT(counter2.total_events(), 100);
2111 EXPECT_GT(counter2.total_events(), 0);
2116 HttpPutManifestFail(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2117 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2118 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
2125 TEST(
Aktualizr, UpdateCheckCompleteError) {
2127 auto http = std::make_shared<HttpPutManifestFail>(temp_dir.Path(), fake_meta_dir);
2129 Config conf = UptaneTestCommon::makeTestConfig(temp_dir,
"http://updatefail");
2131 auto storage = INvStorage::newStorage(conf.storage);
2135 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2138 EXPECT_EQ(
result.status, result::UpdateStatus::kError);
2139 EXPECT_EQ(counter.error_events(), 1);
2149 HttpFakePauseCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2150 :
HttpFake(test_dir_in,
"noupdates", meta_dir_in) {}
2152 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
2156 std::string event_type =
event[
"eventType"][
"id"].asString();
2158 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
2159 if (events_seen == 1) {
2160 EXPECT_EQ(event_type,
"DevicePaused");
2161 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2162 }
else if (events_seen == 2) {
2163 EXPECT_EQ(event_type,
"DeviceResumed");
2164 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2166 std::cout <<
"Unexpected event";
2173 unsigned int events_seen{0};
2178 auto http = std::make_shared<HttpFakePauseCounter>(temp_dir.Path(), fake_meta_dir);
2179 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2181 auto storage = INvStorage::newStorage(conf.storage);
2186 std::promise<void> end_promise{};
2187 size_t n_events = 0;
2188 std::atomic_bool is_paused{
false};
2189 std::function<void(std::shared_ptr<event::BaseEvent>)> cb = [&end_promise, &n_events, &mutex,
2190 &is_paused](std::shared_ptr<event::BaseEvent>
event) {
2193 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
2196 std::lock_guard<std::mutex> guard(mutex);
2198 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
2200 EXPECT_FALSE(is_paused);
2201 end_promise.set_value();
2205 FAIL() <<
"Unexpected event";
2215 std::lock_guard<std::mutex> guard(mutex);
2216 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kSuccess);
2220 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kAlreadyPaused);
2225 std::this_thread::sleep_for(std::chrono::seconds(1));
2228 std::lock_guard<std::mutex> guard(mutex);
2230 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kSuccess);
2233 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kAlreadyRunning);
2235 auto status = end_promise.get_future().wait_for(std::chrono::seconds(20));
2236 if (status != std::future_status::ready) {
2237 FAIL() <<
"Timed out waiting for UpdateCheck event";
2242 int main(
int argc,
char** argv) {
2243 ::testing::InitGoogleTest(&argc, argv);
2245 std::cerr <<
"Error: " << argv[0] <<
" requires the path to the base directory of uptane repos.\n";
2246 return EXIT_FAILURE;
2248 uptane_repos_dir = argv[1];
2251 logger_set_threshold(boost::log::trivial::trace);
2254 fake_meta_dir = tmp_dir.Path();
2257 return RUN_ALL_TESTS();