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 EXPECT_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 EXPECT_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 EXPECT_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,
"correlation_id");
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,
"correlation_id");
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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_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()->package_manager_->rebootDetected());
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));
1116 EXPECT_EQ(aktualizr_cycle_thread_status, std::future_status::ready);
1117 EXPECT_TRUE(aktualizr.uptane_client()->package_manager_->rebootDetected());
1122 auto storage = INvStorage::newStorage(conf.storage);
1128 EXPECT_EQ(update_res.status, result::UpdateStatus::kNoUpdatesAvailable);
1131 boost::optional<Uptane::Target> current_target;
1132 boost::optional<Uptane::Target> pending_target;
1133 storage->loadPrimaryInstalledVersions(¤t_target, &pending_target);
1134 EXPECT_TRUE(!!current_target);
1135 EXPECT_FALSE(!!pending_target);
1136 EXPECT_EQ(http->manifest_sends, 4);
1146 TEST(
Aktualizr, FullMultipleSecondaries) {
1148 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"multisec", fake_meta_dir);
1149 Config conf(
"tests/config/basic.toml");
1150 conf.provision.primary_ecu_serial =
"testecuserial";
1151 conf.provision.primary_ecu_hardware_id =
"testecuhwid";
1152 conf.storage.path = temp_dir.Path();
1153 conf.tls.server = http->tls_server;
1154 conf.uptane.director_server = http->tls_server +
"/director";
1155 conf.uptane.repo_server = http->tls_server +
"/repo";
1158 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"sec_serial1",
"sec_hw1");
1160 auto storage = INvStorage::newStorage(conf.storage);
1162 UptaneTestCommon::addDefaultSecondary(conf, temp_dir2,
"sec_serial2",
"sec_hw2");
1163 ASSERT_NO_THROW(aktualizr.
AddSecondary(std::make_shared<Primary::VirtualSecondary>(
1164 Primary::VirtualSecondaryConfig::create_from_file(conf.uptane.secondary_config_file)[0])));
1169 bool allcomplete{
false};
1170 bool manifest{
false};
1171 std::future<void> future;
1172 std::promise<void> promise;
1174 ev_state.future = ev_state.promise.get_future();
1176 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1177 if (
event->variant ==
"InstallStarted") {
1179 }
else if (
event->variant ==
"InstallTargetComplete") {
1180 ++ev_state.complete;
1181 }
else if (
event->variant ==
"AllInstallsComplete") {
1182 ev_state.allcomplete =
true;
1183 }
else if (
event->variant ==
"PutManifestComplete") {
1184 ev_state.manifest =
true;
1188 if (ev_state.allcomplete && ev_state.complete == 2 && ev_state.manifest) {
1189 ev_state.promise.set_value();
1197 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1198 if (status != std::future_status::ready) {
1199 FAIL() <<
"Timed out waiting for installation to complete.";
1202 EXPECT_EQ(ev_state.started, 2);
1203 EXPECT_EQ(ev_state.complete, 2);
1205 const Json::Value manifest = http->last_manifest[
"signed"];
1206 const Json::Value manifest_versions = manifest[
"ecu_version_manifests"];
1209 EXPECT_EQ(manifest_versions[
"sec_serial1"][
"signed"][
"installed_image"][
"filepath"].asString(),
1210 "secondary_firmware.txt");
1211 EXPECT_EQ(manifest_versions[
"sec_serial1"][
"signed"][
"installed_image"][
"fileinfo"][
"length"].asUInt(), 15);
1212 EXPECT_EQ(manifest_versions[
"sec_serial2"][
"signed"][
"installed_image"][
"filepath"].asString(),
1213 "secondary_firmware2.txt");
1214 EXPECT_EQ(manifest_versions[
"sec_serial2"][
"signed"][
"installed_image"][
"fileinfo"][
"length"].asUInt(), 21);
1217 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"].size(), 2);
1218 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"][0][
"ecu"].asString(),
"sec_serial1");
1219 EXPECT_TRUE(manifest[
"installation_report"][
"report"][
"items"][0][
"result"][
"success"].asBool());
1220 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"][1][
"ecu"].asString(),
"sec_serial2");
1221 EXPECT_TRUE(manifest[
"installation_report"][
"report"][
"items"][1][
"result"][
"success"].asBool());
1229 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"noupdates", fake_meta_dir);
1230 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1232 auto storage = INvStorage::newStorage(conf.storage);
1236 size_t num_events{0};
1237 std::future<void> future;
1238 std::promise<void> promise;
1240 ev_state.future = ev_state.promise.get_future();
1242 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1246 LOG_INFO <<
"Got " <<
event->variant;
1247 switch (ev_state.num_events) {
1249 EXPECT_EQ(
event->variant,
"UpdateCheckComplete");
1250 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1251 EXPECT_EQ(targets_event->result.ecus_count, 0);
1252 EXPECT_EQ(targets_event->result.updates.size(), 0);
1253 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
1257 EXPECT_EQ(
event->variant,
"UpdateCheckComplete");
1258 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1259 EXPECT_EQ(targets_event->result.ecus_count, 0);
1260 EXPECT_EQ(targets_event->result.updates.size(), 0);
1261 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
1262 ev_state.promise.set_value();
1267 FAIL() <<
"Unexpected events!";
1269 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1270 EXPECT_EQ(
event->variant,
"");
1272 ++ev_state.num_events;
1279 EXPECT_EQ(
result.ecus_count, 0);
1280 EXPECT_EQ(
result.updates.size(), 0);
1281 EXPECT_EQ(
result.status, result::UpdateStatus::kNoUpdatesAvailable);
1285 EXPECT_EQ(
result.ecus_count, 0);
1286 EXPECT_EQ(
result.updates.size(), 0);
1287 EXPECT_EQ(
result.status, result::UpdateStatus::kNoUpdatesAvailable);
1289 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1290 if (status != std::future_status::ready) {
1291 FAIL() <<
"Timed out waiting for metadata to be fetched.";
1294 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1305 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1306 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1308 auto storage = INvStorage::newStorage(conf.storage);
1312 size_t num_events{0};
1313 std::future<void> future;
1314 std::promise<void> promise;
1316 ev_state.future = ev_state.promise.get_future();
1318 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1322 LOG_INFO <<
"Got " <<
event->variant;
1323 switch (ev_state.num_events) {
1325 EXPECT_EQ(
event->variant,
"AllDownloadsComplete");
1326 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1327 EXPECT_EQ(downloads_complete->result.updates.size(), 0);
1328 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kError);
1332 EXPECT_EQ(
event->variant,
"UpdateCheckComplete");
1333 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1334 EXPECT_EQ(targets_event->result.ecus_count, 2);
1335 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1336 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1337 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1338 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1343 EXPECT_EQ(
event->variant,
"DownloadTargetComplete");
1344 const auto download_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
1345 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1346 download_event->update.filename() ==
"secondary_firmware.txt");
1347 EXPECT_TRUE(download_event->success);
1351 EXPECT_EQ(
event->variant,
"AllDownloadsComplete");
1352 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1353 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1354 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1355 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1356 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1357 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1358 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1359 ev_state.promise.set_value();
1364 FAIL() <<
"Unexpected events!";
1366 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1367 EXPECT_EQ(
event->variant,
"");
1369 ++ev_state.num_events;
1376 EXPECT_EQ(
result.updates.size(), 0);
1377 EXPECT_EQ(
result.status, result::DownloadStatus::kError);
1379 aktualizr.
Download(update_result.updates);
1381 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1382 if (status != std::future_status::ready) {
1383 FAIL() <<
"Timed out waiting for downloads to complete.";
1386 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1391 using Responses = std::vector<std::pair<std::string, HttpResponse>>;
1394 HttpDownloadFailure(
const boost::filesystem::path& test_dir_in,
const Responses& file_to_response, std::string flavor,
1395 const boost::filesystem::path& meta_dir_in)
1396 :
HttpFake(test_dir_in, flavor, meta_dir_in) {
1397 for (
auto resp : file_to_response) {
1398 url_to_response_[tls_server + target_dir_ + resp.first] = resp.second;
1402 HttpResponse download(
const std::string& url, curl_write_callback write_cb, curl_xferinfo_callback progress_cb,
1403 void* userp, curl_off_t from)
override {
1404 const auto found_response_it = url_to_response_.find(url);
1405 if (found_response_it == url_to_response_.end()) {
1406 return HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error");
1409 auto response = url_to_response_.at(url);
1410 if (response.isOk()) {
1411 return HttpFake::download(url, write_cb, progress_cb, userp, from);
1414 return url_to_response_[url];
1418 const std::string target_dir_{
"/repo/targets/"};
1419 std::map<std::string, HttpResponse> url_to_response_;
1431 class DownloadEventHandler {
1433 DownloadEventHandler(
Aktualizr& aktualizr) {
1434 functor_ = std::bind(&DownloadEventHandler::operator(),
this, std::placeholders::_1);
1438 void operator()(
const std::shared_ptr<event::BaseEvent>&
event) {
1439 ASSERT_NE(
event,
nullptr);
1442 auto download_target_complete_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
1443 auto target_filename = download_target_complete_event->update.filename();
1444 download_status[target_filename] = download_target_complete_event->success;
1447 auto all_download_complete_event = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1448 all_download_completed_status = all_download_complete_event->result;
1453 std::map<std::string, bool> download_status;
1457 std::function<void(std::shared_ptr<event::BaseEvent>)> functor_;
1461 HttpDownloadFailure::Responses downloadResponse;
1462 std::vector<std::pair<std::string, bool>> downloadResult;
1466 TestParams test_case_params[]{
1468 {{
"primary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")},
1469 {
"secondary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")}},
1470 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
false}},
1471 result::DownloadStatus::kError},
1473 {{
"primary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")},
1474 {
"secondary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")}},
1475 {{
"primary_firmware.txt",
true}, {
"secondary_firmware.txt",
false}},
1476 result::DownloadStatus::kPartialSuccess},
1478 {{
"primary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")},
1479 {
"secondary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")}},
1480 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
true}},
1481 result::DownloadStatus::kPartialSuccess}};
1483 for (
auto test_params : test_case_params) {
1486 auto http = std::make_shared<HttpDownloadFailure>(temp_dir.Path(), test_params.downloadResponse,
"hasupdates",
1488 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1489 auto storage = INvStorage::newStorage(conf.storage);
1492 DownloadEventHandler event_hdlr{aktualizr};
1496 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1499 for (
auto& expected_result : test_params.downloadResult) {
1501 ASSERT_NE(event_hdlr.download_status.find(expected_result.first), event_hdlr.download_status.end());
1502 EXPECT_EQ(event_hdlr.download_status.at(expected_result.first), expected_result.second);
1504 EXPECT_EQ(event_hdlr.all_download_completed_status.status, test_params.allDownloadsStatus);
1514 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1515 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1517 auto storage = INvStorage::newStorage(conf.storage);
1524 EXPECT_EQ(targets.size(), 0);
1526 aktualizr.
Download(update_result.updates).get();
1529 EXPECT_EQ(targets.size(), 2);
1537 EXPECT_EQ(targets.size(), 0);
1546 const boost::filesystem::path local_metadir = temp_dir /
"metadir";
1547 Utils::createDirectories(local_metadir, S_IRWXU);
1548 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", local_metadir /
"repo");
1550 UptaneRepo repo{local_metadir,
"2021-07-04T16:33:27Z",
"id0"};
1551 repo.generateRepo(KeyType::kED25519);
1552 const std::string hwid =
"primary_hw";
1553 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1554 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1557 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1558 auto storage = INvStorage::newStorage(conf.storage);
1562 boost::signals2::connection ac_conn =
1563 aktualizr.
SetSignalHandler(std::bind(targets_autoclean_cb, std::ref(aktualizr), std::placeholders::_1));
1568 aktualizr.
Download(update_result.updates).get();
1573 EXPECT_TRUE(install_result.dev_report.success);
1576 ASSERT_EQ(targets.size(), 1);
1577 EXPECT_EQ(targets[0].filename(),
"primary_firmware.txt");
1581 repo.emptyTargets();
1582 repo.addImage(fake_meta_dir /
"fake_meta/dummy_firmware.txt",
"dummy_firmware.txt", hwid,
"", {});
1583 repo.addTarget(
"dummy_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1588 aktualizr.
Download(update_result.updates).get();
1593 EXPECT_TRUE(install_result.dev_report.success);
1597 ASSERT_EQ(targets.size(), 2);
1601 repo.emptyTargets();
1602 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1603 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1608 aktualizr.
Download(update_result.updates).get();
1613 EXPECT_TRUE(install_result.dev_report.success);
1617 ASSERT_EQ(targets.size(), 2);
1621 repo.emptyTargets();
1622 repo.addImage(fake_meta_dir /
"fake_meta/secondary_firmware.txt",
"secondary_firmware.txt", hwid,
"", {});
1623 repo.addTarget(
"secondary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1628 aktualizr.
Download(update_result.updates).get();
1633 EXPECT_TRUE(install_result.dev_report.success);
1637 ASSERT_EQ(targets.size(), 2);
1640 Aktualizr::InstallationLog log = aktualizr.GetInstallationLog();
1641 ASSERT_EQ(log.size(), 2);
1643 EXPECT_EQ(log[0].installs.size(), 4);
1644 EXPECT_EQ(log[1].installs.size(), 0);
1646 std::vector<std::string> fws{
"primary_firmware.txt",
"dummy_firmware.txt",
"primary_firmware.txt",
1647 "secondary_firmware.txt"};
1648 for (
auto it = log[0].installs.begin(); it < log[0].installs.end(); it++) {
1649 auto idx = static_cast<size_t>(it - log[0].installs.begin());
1650 EXPECT_EQ(it->filename(), fws[idx]);
1661 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1662 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1664 auto storage = INvStorage::newStorage(conf.storage);
1668 size_t num_events{0};
1669 std::vector<Uptane::Target> updates;
1670 std::future<void> future;
1671 std::promise<void> promise;
1673 ev_state.future = ev_state.promise.get_future();
1675 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1681 LOG_INFO <<
"Got " <<
event->variant;
1682 switch (ev_state.num_events) {
1684 EXPECT_EQ(
event->variant,
"AllInstallsComplete");
1685 const auto installs_complete = dynamic_cast<event::AllInstallsComplete*>(
event.get());
1686 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 0);
1690 EXPECT_EQ(
event->variant,
"UpdateCheckComplete");
1691 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1692 EXPECT_EQ(targets_event->result.ecus_count, 2);
1693 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1694 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1695 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1696 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1697 ev_state.updates = targets_event->result.updates;
1702 EXPECT_EQ(
event->variant,
"DownloadTargetComplete");
1703 const auto download_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
1704 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1705 download_event->update.filename() ==
"secondary_firmware.txt");
1706 EXPECT_TRUE(download_event->success);
1710 EXPECT_EQ(
event->variant,
"AllDownloadsComplete");
1711 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1712 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1713 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1714 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1715 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1716 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1717 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1723 EXPECT_EQ(
event->variant,
"InstallStarted");
1724 const auto install_started = dynamic_cast<event::InstallStarted*>(
event.get());
1725 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1731 EXPECT_EQ(
event->variant,
"InstallTargetComplete");
1732 const auto install_complete = dynamic_cast<event::InstallTargetComplete*>(
event.get());
1733 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1734 EXPECT_TRUE(install_complete->success);
1738 EXPECT_EQ(
event->variant,
"InstallStarted");
1739 const auto install_started = dynamic_cast<event::InstallStarted*>(
event.get());
1740 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
1744 EXPECT_EQ(
event->variant,
"InstallTargetComplete");
1745 const auto install_complete = dynamic_cast<event::InstallTargetComplete*>(
event.get());
1746 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
1747 EXPECT_TRUE(install_complete->success);
1751 EXPECT_EQ(
event->variant,
"AllInstallsComplete");
1752 const auto installs_complete = dynamic_cast<event::AllInstallsComplete*>(
event.get());
1753 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 2);
1754 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
1755 data::ResultCode::Numeric::kOk);
1756 EXPECT_EQ(installs_complete->result.ecu_reports[1].install_res.result_code.num_code,
1757 data::ResultCode::Numeric::kOk);
1758 ev_state.promise.set_value();
1763 FAIL() <<
"Unexpected events!";
1765 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1766 EXPECT_EQ(
event->variant,
"");
1768 ++ev_state.num_events;
1774 Json::Value primary_json;
1775 primary_json[
"hashes"][
"sha256"] =
"74e653bbf6c00a88b21f0992159b1002f5af38506e6d2fbc7eb9846711b2d75f";
1776 primary_json[
"hashes"][
"sha512"] =
1777 "91814ad1c13ebe2af8d65044893633c4c3ce964edb8cb58b0f357406c255f7be94f42547e108b300346a42cd57662e4757b9d843b7acbc09"
1779 primary_json[
"length"] = 2;
1780 Uptane::Target primary_target(
"primary_firmware.txt", primary_json);
1782 Json::Value secondary_json;
1783 secondary_json[
"hashes"][
"sha256"] =
"1bbb15aa921ffffd5079567d630f43298dbe5e7cbc1b14e0ccdd6718fde28e47";
1784 secondary_json[
"hashes"][
"sha512"] =
1785 "7dbae4c36a2494b731a9239911d3085d53d3e400886edb4ae2b9b78f40bda446649e83ba2d81653f614cc66f5dd5d4dbd95afba854f148af"
1787 secondary_json[
"length"] = 2;
1788 Uptane::Target secondary_target(
"secondary_firmware.txt", secondary_json);
1792 EXPECT_EQ(
result.ecu_reports.size(), 0);
1794 EXPECT_THROW(aktualizr.
OpenStoredTarget(primary_target).get(), std::runtime_error)
1795 <<
"Primary firmware is present in storage before the download";
1796 EXPECT_THROW(aktualizr.
OpenStoredTarget(secondary_target).get(), std::runtime_error)
1797 <<
"Secondary firmware is present in storage before the download";
1800 aktualizr.
Download(update_result.updates).get();
1802 <<
"Primary firmware is not present in storage after the download";
1804 <<
"Secondary firmware is not present in storage after the download";
1807 aktualizr.
Install(update_result.updates);
1809 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1810 if (status != std::future_status::ready) {
1811 FAIL() <<
"Timed out waiting for installation to complete.";
1822 TEST(
Aktualizr, ReportDownloadProgress) {
1826 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1827 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1828 auto storage = INvStorage::newStorage(conf.storage);
1831 unsigned int report_counter = {0};
1832 std::shared_ptr<const event::DownloadProgressReport> lastProgressReport{
nullptr};
1834 std::function<void(std::shared_ptr<event::BaseEvent>
event)> report_event_hdlr =
1835 [&](
const std::shared_ptr<event::BaseEvent>&
event) {
1836 ASSERT_NE(
event,
nullptr);
1841 auto download_progress_event = std::dynamic_pointer_cast<event::DownloadProgressReport>(
event);
1842 ASSERT_NE(download_progress_event,
nullptr);
1843 ASSERT_NE(download_progress_event.get(),
nullptr);
1844 if (lastProgressReport) {
1845 EXPECT_GE(download_progress_event->progress, lastProgressReport->progress);
1847 lastProgressReport = download_progress_event;
1855 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1858 update_result.updates.pop_back();
1861 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
1863 ASSERT_NE(lastProgressReport,
nullptr);
1864 ASSERT_NE(lastProgressReport.get(),
nullptr);
1865 EXPECT_TRUE(event::DownloadProgressReport::isDownloadCompleted(*lastProgressReport));
1866 EXPECT_GT(report_counter, 1);
1871 HttpFakeCampaign(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
1872 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
1874 HttpResponse get(
const std::string& url, int64_t maxsize)
override {
1875 EXPECT_NE(url.find(
"campaigner/"), std::string::npos);
1876 boost::filesystem::path path = meta_dir / url.substr(tls_server.size() + strlen(
"campaigner/"));
1878 if (url.find(
"campaigner/campaigns") != std::string::npos) {
1879 return HttpResponse(Utils::readFile(path.parent_path() /
"campaigner/campaigns.json"), 200, CURLE_OK,
"");
1881 return HttpFake::get(url, maxsize);
1884 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
1886 for (
auto it =
data.begin(); it !=
data.end(); it++) {
1888 auto id = ev[
"eventType"][
"id"];
1889 if (
id ==
"campaign_accepted" ||
id ==
"campaign_declined" ||
id ==
"campaign_postponed") {
1890 seen_events.push_back(ev);
1896 std::vector<Json::Value> seen_events;
1901 bool campaignaccept_seen{
false};
1902 bool campaigndecline_seen{
false};
1903 bool campaignpostpone_seen{
false};
1905 void handler(
const std::shared_ptr<event::BaseEvent>&
event) {
1906 std::cout <<
event->variant <<
"\n";
1907 if (
event->variant ==
"CampaignCheckComplete") {
1908 auto concrete_event = std::static_pointer_cast<event::CampaignCheckComplete>(
event);
1909 EXPECT_EQ(concrete_event->result.campaigns.size(), 1);
1910 EXPECT_EQ(concrete_event->result.campaigns[0].name,
"campaign1");
1911 EXPECT_EQ(concrete_event->result.campaigns[0].id,
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
1912 EXPECT_EQ(concrete_event->result.campaigns[0].size, 62470);
1913 EXPECT_EQ(concrete_event->result.campaigns[0].autoAccept,
true);
1914 EXPECT_EQ(concrete_event->result.campaigns[0].description,
"this is my message to show on the device");
1915 }
else if (
event->variant ==
"CampaignAcceptComplete") {
1916 campaignaccept_seen =
true;
1917 }
else if (
event->variant ==
"CampaignDeclineComplete") {
1918 campaigndecline_seen =
true;
1919 }
else if (
event->variant ==
"CampaignPostponeComplete") {
1920 campaignpostpone_seen =
true;
1941 TEST(
Aktualizr, CampaignCheckAndControl) {
1943 auto http = std::make_shared<HttpFakeCampaign>(temp_dir.Path(), fake_meta_dir);
1944 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1949 auto storage = INvStorage::newStorage(conf.storage);
1951 aktualizr.
SetSignalHandler(std::bind(&CampaignEvents::handler, &campaign_events, std::placeholders::_1));
1956 EXPECT_EQ(
result.campaigns.size(), 1);
1959 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Accept).get();
1961 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Decline).get();
1963 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Postpone).get();
1966 ASSERT_EQ(http->seen_events.size(), 3);
1967 for (
const auto& ev : http->seen_events) {
1968 EXPECT_EQ(ev[
"event"][
"campaignId"],
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
1970 EXPECT_TRUE(campaign_events.campaignaccept_seen);
1971 EXPECT_TRUE(campaign_events.campaigndecline_seen);
1972 EXPECT_TRUE(campaign_events.campaignpostpone_seen);
1977 HttpFakeNoCorrelationId(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
1978 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
1980 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
1984 EXPECT_EQ(
event[
"event"][
"correlationId"].asString(),
"");
1989 unsigned int events_seen{0};
1996 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/repo", meta_dir.Path() /
"repo");
1997 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/director", meta_dir.Path() /
"director");
1998 auto http = std::make_shared<HttpFakeNoCorrelationId>(temp_dir.Path(), meta_dir.Path());
2003 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2005 auto storage = INvStorage::newStorage(conf.storage);
2010 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
2013 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
2016 for (
const auto& r : install_result.ecu_reports) {
2017 EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
2021 EXPECT_EQ(http->events_seen, 8);
2026 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", fake_meta_dir);
2029 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2031 auto storage = INvStorage::newStorage(conf.storage);
2035 Json::Value custom = Utils::parseJSON(R
"({"test_field":"test_value"})");
2036 ASSERT_EQ(custom["test_field"].asString(),
"test_value");
2037 ASSERT_EQ(
true, aktualizr.
SendManifest(custom).get()) <<
"Failed to upload manifest with HttpFake server";
2038 EXPECT_EQ(http->last_manifest[
"signed"][
"custom"], custom);
2049 std::function<void(std::shared_ptr<event::BaseEvent>)> Signal() {
2050 return std::bind(&CountUpdateCheckEvents::count,
this, std::placeholders::_1);
2053 void count(std::shared_ptr<event::BaseEvent>
event) {
2054 std::cout <<
event->variant <<
"\n";
2055 if (
event->variant ==
"UpdateCheckComplete") {
2057 if (std::static_pointer_cast<event::UpdateCheckComplete>(
event)->
result.status == result::UpdateStatus::kError) {
2063 int total_events()
const {
return total_events_; }
2064 int error_events()
const {
return error_events_; }
2067 int total_events_{0};
2068 int error_events_{0};
2073 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
2075 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2077 auto storage = INvStorage::newStorage(conf.storage);
2082 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2084 std::vector<std::future<result::UpdateCheck>> futures;
2085 for (
int i = 0; i < 5; ++i) {
2089 for (
auto& f : futures) {
2094 EXPECT_EQ(counter.total_events(), 5);
2100 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter2.Signal());
2103 std::future<result::UpdateCheck> ft = aktualizr.
CheckUpdates();
2104 for (
int i = 0; i < 99; ++i) {
2109 EXPECT_LT(counter2.total_events(), 100);
2110 EXPECT_GT(counter2.total_events(), 0);
2115 HttpPutManifestFail(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2116 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2117 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
2124 TEST(
Aktualizr, UpdateCheckCompleteError) {
2126 auto http = std::make_shared<HttpPutManifestFail>(temp_dir.Path(), fake_meta_dir);
2128 Config conf = UptaneTestCommon::makeTestConfig(temp_dir,
"http://updatefail");
2130 auto storage = INvStorage::newStorage(conf.storage);
2134 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2137 EXPECT_EQ(
result.status, result::UpdateStatus::kError);
2138 EXPECT_EQ(counter.error_events(), 1);
2148 HttpFakePauseCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2149 :
HttpFake(test_dir_in,
"noupdates", meta_dir_in) {}
2151 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
2155 std::string event_type =
event[
"eventType"][
"id"].asString();
2157 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
2158 if (events_seen == 1) {
2159 EXPECT_EQ(event_type,
"DevicePaused");
2160 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2161 }
else if (events_seen == 2) {
2162 EXPECT_EQ(event_type,
"DeviceResumed");
2163 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2165 std::cout <<
"Unexpected event";
2172 unsigned int events_seen{0};
2177 auto http = std::make_shared<HttpFakePauseCounter>(temp_dir.Path(), fake_meta_dir);
2178 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2180 auto storage = INvStorage::newStorage(conf.storage);
2185 std::promise<void> end_promise{};
2186 size_t n_events = 0;
2187 std::atomic_bool is_paused{
false};
2188 std::function<void(std::shared_ptr<event::BaseEvent>)> cb = [&end_promise, &n_events, &mutex,
2189 &is_paused](std::shared_ptr<event::BaseEvent>
event) {
2192 EXPECT_EQ(
event->variant,
"UpdateCheckComplete");
2195 std::lock_guard<std::mutex> guard(mutex);
2197 EXPECT_EQ(
event->variant,
"UpdateCheckComplete");
2199 EXPECT_FALSE(is_paused);
2200 end_promise.set_value();
2204 FAIL() <<
"Unexpected event";
2214 std::lock_guard<std::mutex> guard(mutex);
2215 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kSuccess);
2219 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kAlreadyPaused);
2224 std::this_thread::sleep_for(std::chrono::seconds(1));
2227 std::lock_guard<std::mutex> guard(mutex);
2229 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kSuccess);
2232 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kAlreadyRunning);
2234 auto status = end_promise.get_future().wait_for(std::chrono::seconds(20));
2235 if (status != std::future_status::ready) {
2236 FAIL() <<
"Timed out waiting for UpdateCheck event";
2241 int main(
int argc,
char** argv) {
2242 ::testing::InitGoogleTest(&argc, argv);
2244 std::cerr <<
"Error: " << argv[0] <<
" requires the path to the base directory of uptane repos.\n";
2245 return EXIT_FAILURE;
2247 uptane_repos_dir = argv[1];
2250 logger_set_threshold(boost::log::trivial::trace);
2253 fake_meta_dir = tmp_dir.Path();
2256 return RUN_ALL_TESTS();