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());
1090 auto http_server_mock = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1091 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http_server_mock->tls_server);
1092 auto storage = INvStorage::newStorage(conf.storage);
1094 fault_injection_init();
1095 fiu_enable(
"secondary_putmetadata", 1,
nullptr, 0);
1101 std::promise<void> promise;
1104 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1105 if (
event->variant !=
"AllInstallsComplete") {
1108 const auto installs_complete = dynamic_cast<event::AllInstallsComplete*>(
event.get());
1109 ev_state.result = installs_complete->result;
1111 ev_state.promise.set_value();
1117 auto status = ev_state.promise.get_future().wait_for(std::chrono::seconds(20));
1118 if (status != std::future_status::ready) {
1119 FAIL() <<
"Timed out waiting for installation to complete.";
1122 ASSERT_FALSE(ev_state.result.dev_report.isSuccess());
1124 fiu_disable(
"secondary_putmetadata");
1127 #endif // FIU_ENABLE
1141 TEST(
Aktualizr, AutoRebootAfterUpdate) {
1143 auto http = std::make_shared<HttpFakePutCounter>(temp_dir.Path(), fake_meta_dir);
1144 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1145 conf.pacman.fake_need_reboot =
true;
1146 conf.uptane.force_install_completion =
true;
1147 conf.uptane.polling_sec = 0;
1151 auto storage = INvStorage::newStorage(conf.storage);
1155 auto aktualizr_cycle_thread = aktualizr.
RunForever();
1156 auto aktualizr_cycle_thread_status = aktualizr_cycle_thread.wait_for(std::chrono::seconds(20));
1159 EXPECT_EQ(aktualizr_cycle_thread_status, std::future_status::ready);
1160 EXPECT_TRUE(aktualizr.uptane_client()->isInstallCompletionRequired());
1165 auto storage = INvStorage::newStorage(conf.storage);
1171 EXPECT_EQ(update_res.status, result::UpdateStatus::kNoUpdatesAvailable);
1174 boost::optional<Uptane::Target> current_target;
1175 boost::optional<Uptane::Target> pending_target;
1176 storage->loadPrimaryInstalledVersions(¤t_target, &pending_target);
1177 EXPECT_TRUE(!!current_target);
1178 EXPECT_FALSE(!!pending_target);
1179 EXPECT_EQ(http->manifest_sends, 4);
1189 TEST(
Aktualizr, FullMultipleSecondaries) {
1191 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"multisec", fake_meta_dir);
1192 Config conf(
"tests/config/basic.toml");
1193 conf.provision.primary_ecu_serial =
"testecuserial";
1194 conf.provision.primary_ecu_hardware_id =
"testecuhwid";
1195 conf.storage.path = temp_dir.Path();
1196 conf.tls.server = http->tls_server;
1197 conf.uptane.director_server = http->tls_server +
"/director";
1198 conf.uptane.repo_server = http->tls_server +
"/repo";
1201 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"sec_serial1",
"sec_hw1");
1203 auto storage = INvStorage::newStorage(conf.storage);
1205 UptaneTestCommon::addDefaultSecondary(conf, temp_dir2,
"sec_serial2",
"sec_hw2");
1206 ASSERT_NO_THROW(aktualizr.
AddSecondary(std::make_shared<Primary::VirtualSecondary>(
1207 Primary::VirtualSecondaryConfig::create_from_file(conf.uptane.secondary_config_file)[0])));
1212 bool allcomplete{
false};
1213 bool manifest{
false};
1214 std::future<void> future;
1215 std::promise<void> promise;
1217 ev_state.future = ev_state.promise.get_future();
1219 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1220 if (
event->variant ==
"InstallStarted") {
1222 }
else if (
event->variant ==
"InstallTargetComplete") {
1223 ++ev_state.complete;
1224 }
else if (
event->variant ==
"AllInstallsComplete") {
1225 ev_state.allcomplete =
true;
1226 }
else if (
event->variant ==
"PutManifestComplete") {
1227 ev_state.manifest =
true;
1231 if (ev_state.allcomplete && ev_state.complete == 2 && ev_state.manifest) {
1232 ev_state.promise.set_value();
1240 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1241 if (status != std::future_status::ready) {
1242 FAIL() <<
"Timed out waiting for installation to complete.";
1245 EXPECT_EQ(ev_state.started, 2);
1246 EXPECT_EQ(ev_state.complete, 2);
1248 const Json::Value manifest = http->last_manifest[
"signed"];
1249 const Json::Value manifest_versions = manifest[
"ecu_version_manifests"];
1252 EXPECT_EQ(manifest_versions[
"sec_serial1"][
"signed"][
"installed_image"][
"filepath"].asString(),
1253 "secondary_firmware.txt");
1254 EXPECT_EQ(manifest_versions[
"sec_serial1"][
"signed"][
"installed_image"][
"fileinfo"][
"length"].asUInt(), 15);
1255 EXPECT_EQ(manifest_versions[
"sec_serial2"][
"signed"][
"installed_image"][
"filepath"].asString(),
1256 "secondary_firmware2.txt");
1257 EXPECT_EQ(manifest_versions[
"sec_serial2"][
"signed"][
"installed_image"][
"fileinfo"][
"length"].asUInt(), 21);
1260 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"].size(), 2);
1261 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"][0][
"ecu"].asString(),
"sec_serial1");
1262 EXPECT_TRUE(manifest[
"installation_report"][
"report"][
"items"][0][
"result"][
"success"].asBool());
1263 EXPECT_EQ(manifest[
"installation_report"][
"report"][
"items"][1][
"ecu"].asString(),
"sec_serial2");
1264 EXPECT_TRUE(manifest[
"installation_report"][
"report"][
"items"][1][
"result"][
"success"].asBool());
1272 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"noupdates", fake_meta_dir);
1273 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1275 auto storage = INvStorage::newStorage(conf.storage);
1279 size_t num_events{0};
1280 std::future<void> future;
1281 std::promise<void> promise;
1283 ev_state.future = ev_state.promise.get_future();
1285 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1289 LOG_INFO <<
"Got " <<
event->variant;
1290 switch (ev_state.num_events) {
1292 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1293 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1294 EXPECT_EQ(targets_event->result.ecus_count, 0);
1295 EXPECT_EQ(targets_event->result.updates.size(), 0);
1296 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
1300 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1301 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1302 EXPECT_EQ(targets_event->result.ecus_count, 0);
1303 EXPECT_EQ(targets_event->result.updates.size(), 0);
1304 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kNoUpdatesAvailable);
1305 ev_state.promise.set_value();
1310 FAIL() <<
"Unexpected events!";
1312 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1313 ASSERT_EQ(
event->variant,
"");
1315 ++ev_state.num_events;
1322 EXPECT_EQ(
result.ecus_count, 0);
1323 EXPECT_EQ(
result.updates.size(), 0);
1324 EXPECT_EQ(
result.status, result::UpdateStatus::kNoUpdatesAvailable);
1328 EXPECT_EQ(
result.ecus_count, 0);
1329 EXPECT_EQ(
result.updates.size(), 0);
1330 EXPECT_EQ(
result.status, result::UpdateStatus::kNoUpdatesAvailable);
1332 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1333 if (status != std::future_status::ready) {
1334 FAIL() <<
"Timed out waiting for metadata to be fetched.";
1337 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1348 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1349 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1351 auto storage = INvStorage::newStorage(conf.storage);
1355 size_t num_events{0};
1356 std::future<void> future;
1357 std::promise<void> promise;
1359 ev_state.future = ev_state.promise.get_future();
1361 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1365 LOG_INFO <<
"Got " <<
event->variant;
1366 switch (ev_state.num_events) {
1368 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1369 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1370 EXPECT_EQ(downloads_complete->result.updates.size(), 0);
1371 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kError);
1375 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1376 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1377 EXPECT_EQ(targets_event->result.ecus_count, 2);
1378 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1379 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1380 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1381 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1386 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
1387 const auto download_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
1388 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1389 download_event->update.filename() ==
"secondary_firmware.txt");
1390 EXPECT_TRUE(download_event->success);
1394 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1395 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1396 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1397 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1398 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1399 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1400 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1401 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1402 ev_state.promise.set_value();
1407 FAIL() <<
"Unexpected events!";
1409 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1410 ASSERT_EQ(
event->variant,
"");
1412 ++ev_state.num_events;
1419 EXPECT_EQ(
result.updates.size(), 0);
1420 EXPECT_EQ(
result.status, result::DownloadStatus::kError);
1422 aktualizr.
Download(update_result.updates);
1424 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1425 if (status != std::future_status::ready) {
1426 FAIL() <<
"Timed out waiting for downloads to complete.";
1429 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1434 using Responses = std::vector<std::pair<std::string, HttpResponse>>;
1437 HttpDownloadFailure(
const boost::filesystem::path& test_dir_in,
const Responses& file_to_response, std::string flavor,
1438 const boost::filesystem::path& meta_dir_in)
1439 :
HttpFake(test_dir_in, flavor, meta_dir_in) {
1440 for (
auto resp : file_to_response) {
1441 url_to_response_[tls_server + target_dir_ + resp.first] = resp.second;
1445 HttpResponse download(
const std::string& url, curl_write_callback write_cb, curl_xferinfo_callback progress_cb,
1446 void* userp, curl_off_t from)
override {
1447 const auto found_response_it = url_to_response_.find(url);
1448 if (found_response_it == url_to_response_.end()) {
1449 return HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error");
1452 auto response = url_to_response_.at(url);
1453 if (response.isOk()) {
1454 return HttpFake::download(url, write_cb, progress_cb, userp, from);
1457 return url_to_response_[url];
1461 const std::string target_dir_{
"/repo/targets/"};
1462 std::map<std::string, HttpResponse> url_to_response_;
1474 class DownloadEventHandler {
1476 DownloadEventHandler(
Aktualizr& aktualizr) {
1477 functor_ = std::bind(&DownloadEventHandler::operator(),
this, std::placeholders::_1);
1481 void operator()(
const std::shared_ptr<event::BaseEvent>&
event) {
1482 ASSERT_NE(
event,
nullptr);
1485 auto download_target_complete_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
1486 auto target_filename = download_target_complete_event->update.filename();
1487 download_status[target_filename] = download_target_complete_event->success;
1490 auto all_download_complete_event = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1491 all_download_completed_status = all_download_complete_event->result;
1496 std::map<std::string, bool> download_status;
1500 std::function<void(std::shared_ptr<event::BaseEvent>)> functor_;
1504 HttpDownloadFailure::Responses downloadResponse;
1505 std::vector<std::pair<std::string, bool>> downloadResult;
1509 TestParams test_case_params[]{
1511 {{
"primary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")},
1512 {
"secondary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")}},
1513 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
false}},
1514 result::DownloadStatus::kError},
1516 {{
"primary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")},
1517 {
"secondary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")}},
1518 {{
"primary_firmware.txt",
true}, {
"secondary_firmware.txt",
false}},
1519 result::DownloadStatus::kPartialSuccess},
1521 {{
"primary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")},
1522 {
"secondary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")}},
1523 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
true}},
1524 result::DownloadStatus::kPartialSuccess}};
1526 for (
auto test_params : test_case_params) {
1529 auto http = std::make_shared<HttpDownloadFailure>(temp_dir.Path(), test_params.downloadResponse,
"hasupdates",
1531 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1532 auto storage = INvStorage::newStorage(conf.storage);
1535 DownloadEventHandler event_hdlr{aktualizr};
1539 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1542 for (
auto& expected_result : test_params.downloadResult) {
1544 ASSERT_NE(event_hdlr.download_status.find(expected_result.first), event_hdlr.download_status.end());
1545 EXPECT_EQ(event_hdlr.download_status.at(expected_result.first), expected_result.second);
1547 EXPECT_EQ(event_hdlr.all_download_completed_status.status, test_params.allDownloadsStatus);
1557 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1558 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1560 auto storage = INvStorage::newStorage(conf.storage);
1567 EXPECT_EQ(targets.size(), 0);
1569 aktualizr.
Download(update_result.updates).get();
1572 EXPECT_EQ(targets.size(), 2);
1580 EXPECT_EQ(targets.size(), 0);
1589 const boost::filesystem::path local_metadir = temp_dir /
"metadir";
1590 Utils::createDirectories(local_metadir, S_IRWXU);
1591 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", local_metadir /
"repo");
1593 UptaneRepo repo{local_metadir,
"2021-07-04T16:33:27Z",
"id0"};
1594 repo.generateRepo(KeyType::kED25519);
1595 const std::string hwid =
"primary_hw";
1596 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1597 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1600 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1601 auto storage = INvStorage::newStorage(conf.storage);
1605 boost::signals2::connection ac_conn =
1606 aktualizr.
SetSignalHandler(std::bind(targets_autoclean_cb, std::ref(aktualizr), std::placeholders::_1));
1611 aktualizr.
Download(update_result.updates).get();
1616 EXPECT_TRUE(install_result.dev_report.success);
1619 ASSERT_EQ(targets.size(), 1);
1620 EXPECT_EQ(targets[0].filename(),
"primary_firmware.txt");
1624 repo.emptyTargets();
1625 repo.addImage(fake_meta_dir /
"fake_meta/dummy_firmware.txt",
"dummy_firmware.txt", hwid,
"", {});
1626 repo.addTarget(
"dummy_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1631 aktualizr.
Download(update_result.updates).get();
1636 EXPECT_TRUE(install_result.dev_report.success);
1640 ASSERT_EQ(targets.size(), 2);
1644 repo.emptyTargets();
1645 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1646 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1651 aktualizr.
Download(update_result.updates).get();
1656 EXPECT_TRUE(install_result.dev_report.success);
1660 ASSERT_EQ(targets.size(), 2);
1664 repo.emptyTargets();
1665 repo.addImage(fake_meta_dir /
"fake_meta/secondary_firmware.txt",
"secondary_firmware.txt", hwid,
"", {});
1666 repo.addTarget(
"secondary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1671 aktualizr.
Download(update_result.updates).get();
1676 EXPECT_TRUE(install_result.dev_report.success);
1680 ASSERT_EQ(targets.size(), 2);
1683 Aktualizr::InstallationLog log = aktualizr.GetInstallationLog();
1684 ASSERT_EQ(log.size(), 2);
1686 EXPECT_EQ(log[0].installs.size(), 4);
1687 EXPECT_EQ(log[1].installs.size(), 0);
1689 std::vector<std::string> fws{
"primary_firmware.txt",
"dummy_firmware.txt",
"primary_firmware.txt",
1690 "secondary_firmware.txt"};
1691 for (
auto it = log[0].installs.begin(); it < log[0].installs.end(); it++) {
1692 auto idx = static_cast<size_t>(it - log[0].installs.begin());
1693 EXPECT_EQ(it->filename(), fws[idx]);
1704 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1705 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1707 auto storage = INvStorage::newStorage(conf.storage);
1711 size_t num_events{0};
1712 std::vector<Uptane::Target> updates;
1713 std::future<void> future;
1714 std::promise<void> promise;
1716 ev_state.future = ev_state.promise.get_future();
1718 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1724 LOG_INFO <<
"Got " <<
event->variant;
1725 switch (ev_state.num_events) {
1727 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
1728 const auto installs_complete = dynamic_cast<event::AllInstallsComplete*>(
event.get());
1729 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 0);
1733 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1734 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1735 EXPECT_EQ(targets_event->result.ecus_count, 2);
1736 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1737 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1738 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1739 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1740 ev_state.updates = targets_event->result.updates;
1745 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
1746 const auto download_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
1747 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1748 download_event->update.filename() ==
"secondary_firmware.txt");
1749 EXPECT_TRUE(download_event->success);
1753 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1754 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1755 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1756 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1757 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1758 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1759 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1760 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1766 ASSERT_EQ(
event->variant,
"InstallStarted");
1767 const auto install_started = dynamic_cast<event::InstallStarted*>(
event.get());
1768 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1774 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
1775 const auto install_complete = dynamic_cast<event::InstallTargetComplete*>(
event.get());
1776 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1777 EXPECT_TRUE(install_complete->success);
1781 ASSERT_EQ(
event->variant,
"InstallStarted");
1782 const auto install_started = dynamic_cast<event::InstallStarted*>(
event.get());
1783 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
1787 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
1788 const auto install_complete = dynamic_cast<event::InstallTargetComplete*>(
event.get());
1789 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
1790 EXPECT_TRUE(install_complete->success);
1794 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
1795 const auto installs_complete = dynamic_cast<event::AllInstallsComplete*>(
event.get());
1796 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 2);
1797 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
1798 data::ResultCode::Numeric::kOk);
1799 EXPECT_EQ(installs_complete->result.ecu_reports[1].install_res.result_code.num_code,
1800 data::ResultCode::Numeric::kOk);
1801 ev_state.promise.set_value();
1806 FAIL() <<
"Unexpected events!";
1808 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1809 ASSERT_EQ(
event->variant,
"");
1811 ++ev_state.num_events;
1817 Json::Value primary_json;
1818 primary_json[
"hashes"][
"sha256"] =
"74e653bbf6c00a88b21f0992159b1002f5af38506e6d2fbc7eb9846711b2d75f";
1819 primary_json[
"hashes"][
"sha512"] =
1820 "91814ad1c13ebe2af8d65044893633c4c3ce964edb8cb58b0f357406c255f7be94f42547e108b300346a42cd57662e4757b9d843b7acbc09"
1822 primary_json[
"length"] = 2;
1823 Uptane::Target primary_target(
"primary_firmware.txt", primary_json);
1825 Json::Value secondary_json;
1826 secondary_json[
"hashes"][
"sha256"] =
"1bbb15aa921ffffd5079567d630f43298dbe5e7cbc1b14e0ccdd6718fde28e47";
1827 secondary_json[
"hashes"][
"sha512"] =
1828 "7dbae4c36a2494b731a9239911d3085d53d3e400886edb4ae2b9b78f40bda446649e83ba2d81653f614cc66f5dd5d4dbd95afba854f148af"
1830 secondary_json[
"length"] = 2;
1831 Uptane::Target secondary_target(
"secondary_firmware.txt", secondary_json);
1835 EXPECT_EQ(
result.ecu_reports.size(), 0);
1837 EXPECT_THROW(aktualizr.
OpenStoredTarget(primary_target).get(), std::runtime_error)
1838 <<
"Primary firmware is present in storage before the download";
1839 EXPECT_THROW(aktualizr.
OpenStoredTarget(secondary_target).get(), std::runtime_error)
1840 <<
"Secondary firmware is present in storage before the download";
1843 aktualizr.
Download(update_result.updates).get();
1845 <<
"Primary firmware is not present in storage after the download";
1847 <<
"Secondary firmware is not present in storage after the download";
1850 aktualizr.
Install(update_result.updates);
1852 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1853 if (status != std::future_status::ready) {
1854 FAIL() <<
"Timed out waiting for installation to complete.";
1865 TEST(
Aktualizr, ReportDownloadProgress) {
1869 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1870 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1871 auto storage = INvStorage::newStorage(conf.storage);
1874 unsigned int report_counter = {0};
1875 std::shared_ptr<const event::DownloadProgressReport> lastProgressReport{
nullptr};
1877 std::function<void(std::shared_ptr<event::BaseEvent>
event)> report_event_hdlr =
1878 [&](
const std::shared_ptr<event::BaseEvent>&
event) {
1879 ASSERT_NE(
event,
nullptr);
1884 auto download_progress_event = std::dynamic_pointer_cast<event::DownloadProgressReport>(
event);
1885 ASSERT_NE(download_progress_event,
nullptr);
1886 ASSERT_NE(download_progress_event.get(),
nullptr);
1887 if (lastProgressReport) {
1888 EXPECT_GE(download_progress_event->progress, lastProgressReport->progress);
1890 lastProgressReport = download_progress_event;
1898 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1901 update_result.updates.pop_back();
1904 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
1906 ASSERT_NE(lastProgressReport,
nullptr);
1907 ASSERT_NE(lastProgressReport.get(),
nullptr);
1908 EXPECT_TRUE(event::DownloadProgressReport::isDownloadCompleted(*lastProgressReport));
1909 EXPECT_GT(report_counter, 1);
1914 HttpFakeCampaign(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
1915 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
1917 HttpResponse get(
const std::string& url, int64_t maxsize)
override {
1918 EXPECT_NE(url.find(
"campaigner/"), std::string::npos);
1919 boost::filesystem::path path = meta_dir / url.substr(tls_server.size() + strlen(
"campaigner/"));
1921 if (url.find(
"campaigner/campaigns") != std::string::npos) {
1922 return HttpResponse(Utils::readFile(path.parent_path() /
"campaigner/campaigns.json"), 200, CURLE_OK,
"");
1924 return HttpFake::get(url, maxsize);
1927 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
1929 for (
auto it =
data.begin(); it !=
data.end(); it++) {
1931 auto id = ev[
"eventType"][
"id"];
1932 if (
id ==
"campaign_accepted" ||
id ==
"campaign_declined" ||
id ==
"campaign_postponed") {
1933 seen_events.push_back(ev);
1939 std::vector<Json::Value> seen_events;
1944 bool campaignaccept_seen{
false};
1945 bool campaigndecline_seen{
false};
1946 bool campaignpostpone_seen{
false};
1948 void handler(
const std::shared_ptr<event::BaseEvent>&
event) {
1949 std::cout <<
event->variant <<
"\n";
1950 if (
event->variant ==
"CampaignCheckComplete") {
1951 auto concrete_event = std::static_pointer_cast<event::CampaignCheckComplete>(
event);
1952 EXPECT_EQ(concrete_event->result.campaigns.size(), 1);
1953 EXPECT_EQ(concrete_event->result.campaigns[0].name,
"campaign1");
1954 EXPECT_EQ(concrete_event->result.campaigns[0].id,
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
1955 EXPECT_EQ(concrete_event->result.campaigns[0].size, 62470);
1956 EXPECT_EQ(concrete_event->result.campaigns[0].autoAccept,
true);
1957 EXPECT_EQ(concrete_event->result.campaigns[0].description,
"this is my message to show on the device");
1958 }
else if (
event->variant ==
"CampaignAcceptComplete") {
1959 campaignaccept_seen =
true;
1960 }
else if (
event->variant ==
"CampaignDeclineComplete") {
1961 campaigndecline_seen =
true;
1962 }
else if (
event->variant ==
"CampaignPostponeComplete") {
1963 campaignpostpone_seen =
true;
1984 TEST(
Aktualizr, CampaignCheckAndControl) {
1986 auto http = std::make_shared<HttpFakeCampaign>(temp_dir.Path(), fake_meta_dir);
1987 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1992 auto storage = INvStorage::newStorage(conf.storage);
1994 aktualizr.
SetSignalHandler(std::bind(&CampaignEvents::handler, &campaign_events, std::placeholders::_1));
1999 EXPECT_EQ(
result.campaigns.size(), 1);
2002 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Accept).get();
2004 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Decline).get();
2006 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Postpone).get();
2009 ASSERT_EQ(http->seen_events.size(), 3);
2010 for (
const auto& ev : http->seen_events) {
2011 EXPECT_EQ(ev[
"event"][
"campaignId"],
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
2013 EXPECT_TRUE(campaign_events.campaignaccept_seen);
2014 EXPECT_TRUE(campaign_events.campaigndecline_seen);
2015 EXPECT_TRUE(campaign_events.campaignpostpone_seen);
2020 HttpFakeNoCorrelationId(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2021 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2023 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
2027 EXPECT_EQ(
event[
"event"][
"correlationId"].asString(),
"");
2032 unsigned int events_seen{0};
2039 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/repo", meta_dir.Path() /
"repo");
2040 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/director", meta_dir.Path() /
"director");
2041 auto http = std::make_shared<HttpFakeNoCorrelationId>(temp_dir.Path(), meta_dir.Path());
2046 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2048 auto storage = INvStorage::newStorage(conf.storage);
2053 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
2056 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
2059 for (
const auto& r : install_result.ecu_reports) {
2060 EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
2064 EXPECT_EQ(http->events_seen, 8);
2069 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", fake_meta_dir);
2072 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2074 auto storage = INvStorage::newStorage(conf.storage);
2078 Json::Value custom = Utils::parseJSON(R
"({"test_field":"test_value"})");
2079 ASSERT_EQ(custom["test_field"].asString(),
"test_value");
2080 ASSERT_EQ(
true, aktualizr.
SendManifest(custom).get()) <<
"Failed to upload manifest with HttpFake server";
2081 EXPECT_EQ(http->last_manifest[
"signed"][
"custom"], custom);
2092 std::function<void(std::shared_ptr<event::BaseEvent>)> Signal() {
2093 return std::bind(&CountUpdateCheckEvents::count,
this, std::placeholders::_1);
2096 void count(std::shared_ptr<event::BaseEvent>
event) {
2097 std::cout <<
event->variant <<
"\n";
2098 if (
event->variant ==
"UpdateCheckComplete") {
2100 if (std::static_pointer_cast<event::UpdateCheckComplete>(
event)->
result.status == result::UpdateStatus::kError) {
2106 int total_events()
const {
return total_events_; }
2107 int error_events()
const {
return error_events_; }
2110 int total_events_{0};
2111 int error_events_{0};
2116 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
2118 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2120 auto storage = INvStorage::newStorage(conf.storage);
2125 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2127 std::vector<std::future<result::UpdateCheck>> futures;
2128 for (
int i = 0; i < 5; ++i) {
2132 for (
auto& f : futures) {
2137 EXPECT_EQ(counter.total_events(), 5);
2143 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter2.Signal());
2146 std::future<result::UpdateCheck> ft = aktualizr.
CheckUpdates();
2147 for (
int i = 0; i < 99; ++i) {
2152 EXPECT_LT(counter2.total_events(), 100);
2153 EXPECT_GT(counter2.total_events(), 0);
2158 HttpPutManifestFail(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2159 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2160 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
2167 TEST(
Aktualizr, UpdateCheckCompleteError) {
2169 auto http = std::make_shared<HttpPutManifestFail>(temp_dir.Path(), fake_meta_dir);
2171 Config conf = UptaneTestCommon::makeTestConfig(temp_dir,
"http://updatefail");
2173 auto storage = INvStorage::newStorage(conf.storage);
2177 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2180 EXPECT_EQ(
result.status, result::UpdateStatus::kError);
2181 EXPECT_EQ(counter.error_events(), 1);
2191 HttpFakePauseCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2192 :
HttpFake(test_dir_in,
"noupdates", meta_dir_in) {}
2194 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
2198 std::string event_type =
event[
"eventType"][
"id"].asString();
2200 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
2201 if (events_seen == 1) {
2202 EXPECT_EQ(event_type,
"DevicePaused");
2203 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2204 }
else if (events_seen == 2) {
2205 EXPECT_EQ(event_type,
"DeviceResumed");
2206 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2208 std::cout <<
"Unexpected event";
2215 unsigned int events_seen{0};
2220 auto http = std::make_shared<HttpFakePauseCounter>(temp_dir.Path(), fake_meta_dir);
2221 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2223 auto storage = INvStorage::newStorage(conf.storage);
2228 std::promise<void> end_promise{};
2229 size_t n_events = 0;
2230 std::atomic_bool is_paused{
false};
2231 std::function<void(std::shared_ptr<event::BaseEvent>)> cb = [&end_promise, &n_events, &mutex,
2232 &is_paused](std::shared_ptr<event::BaseEvent>
event) {
2235 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
2238 std::lock_guard<std::mutex> guard(mutex);
2240 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
2242 EXPECT_FALSE(is_paused);
2243 end_promise.set_value();
2247 FAIL() <<
"Unexpected event";
2257 std::lock_guard<std::mutex> guard(mutex);
2258 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kSuccess);
2262 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kAlreadyPaused);
2267 std::this_thread::sleep_for(std::chrono::seconds(1));
2270 std::lock_guard<std::mutex> guard(mutex);
2272 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kSuccess);
2275 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kAlreadyRunning);
2277 auto status = end_promise.get_future().wait_for(std::chrono::seconds(20));
2278 if (status != std::future_status::ready) {
2279 FAIL() <<
"Timed out waiting for UpdateCheck event";
2284 int main(
int argc,
char** argv) {
2285 ::testing::InitGoogleTest(&argc, argv);
2287 std::cerr <<
"Error: " << argv[0] <<
" requires the path to the base directory of Uptane repos.\n";
2288 return EXIT_FAILURE;
2290 uptane_repos_dir = argv[1];
2293 logger_set_threshold(boost::log::trivial::trace);
2296 fake_meta_dir = tmp_dir.Path();
2299 return RUN_ALL_TESTS();