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);
1423 aktualizr.
Download(update_result.updates);
1425 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1426 if (status != std::future_status::ready) {
1427 FAIL() <<
"Timed out waiting for downloads to complete.";
1430 verifyNothingInstalled(aktualizr.uptane_client()->AssembleManifest());
1435 using Responses = std::vector<std::pair<std::string, HttpResponse>>;
1438 HttpDownloadFailure(
const boost::filesystem::path& test_dir_in,
const Responses& file_to_response, std::string flavor,
1439 const boost::filesystem::path& meta_dir_in)
1440 :
HttpFake(test_dir_in, flavor, meta_dir_in) {
1441 for (
auto resp : file_to_response) {
1442 url_to_response_[tls_server + target_dir_ + resp.first] = resp.second;
1446 HttpResponse download(
const std::string& url, curl_write_callback write_cb, curl_xferinfo_callback progress_cb,
1447 void* userp, curl_off_t from)
override {
1448 const auto found_response_it = url_to_response_.find(url);
1449 if (found_response_it == url_to_response_.end()) {
1450 return HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error");
1453 auto response = url_to_response_.at(url);
1454 if (response.isOk()) {
1455 return HttpFake::download(url, write_cb, progress_cb, userp, from);
1458 return url_to_response_[url];
1462 const std::string target_dir_{
"/repo/targets/"};
1463 std::map<std::string, HttpResponse> url_to_response_;
1475 class DownloadEventHandler {
1477 DownloadEventHandler(
Aktualizr& aktualizr) {
1478 functor_ = std::bind(&DownloadEventHandler::operator(),
this, std::placeholders::_1);
1482 void operator()(
const std::shared_ptr<event::BaseEvent>&
event) {
1483 ASSERT_NE(
event,
nullptr);
1486 auto download_target_complete_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
1487 auto target_filename = download_target_complete_event->update.filename();
1488 download_status[target_filename] = download_target_complete_event->success;
1491 auto all_download_complete_event = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1492 all_download_completed_status = all_download_complete_event->result;
1497 std::map<std::string, bool> download_status;
1501 std::function<void(std::shared_ptr<event::BaseEvent>)> functor_;
1505 HttpDownloadFailure::Responses downloadResponse;
1506 std::vector<std::pair<std::string, bool>> downloadResult;
1510 TestParams test_case_params[]{
1512 {{
"primary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")},
1513 {
"secondary_firmware.txt",
HttpResponse(
"", 500, CURLE_HTTP_RETURNED_ERROR,
"Internal Server Error")}},
1514 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
false}},
1515 result::DownloadStatus::kError},
1517 {{
"primary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")},
1518 {
"secondary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")}},
1519 {{
"primary_firmware.txt",
true}, {
"secondary_firmware.txt",
false}},
1520 result::DownloadStatus::kPartialSuccess},
1522 {{
"primary_firmware.txt",
HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found")},
1523 {
"secondary_firmware.txt",
HttpResponse(
"", 200, CURLE_OK,
"")}},
1524 {{
"primary_firmware.txt",
false}, {
"secondary_firmware.txt",
true}},
1525 result::DownloadStatus::kPartialSuccess}};
1527 for (
auto test_params : test_case_params) {
1530 auto http = std::make_shared<HttpDownloadFailure>(temp_dir.Path(), test_params.downloadResponse,
"hasupdates",
1532 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1533 auto storage = INvStorage::newStorage(conf.storage);
1536 DownloadEventHandler event_hdlr{aktualizr};
1540 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1543 for (
auto& expected_result : test_params.downloadResult) {
1545 ASSERT_NE(event_hdlr.download_status.find(expected_result.first), event_hdlr.download_status.end());
1546 EXPECT_EQ(event_hdlr.download_status.at(expected_result.first), expected_result.second);
1548 EXPECT_EQ(event_hdlr.all_download_completed_status.status, test_params.allDownloadsStatus);
1558 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1559 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1561 auto storage = INvStorage::newStorage(conf.storage);
1568 EXPECT_EQ(targets.size(), 0);
1570 aktualizr.
Download(update_result.updates).get();
1573 EXPECT_EQ(targets.size(), 2);
1581 EXPECT_EQ(targets.size(), 0);
1590 const boost::filesystem::path local_metadir = temp_dir /
"metadir";
1591 Utils::createDirectories(local_metadir, S_IRWXU);
1592 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", local_metadir /
"repo");
1594 UptaneRepo repo{local_metadir,
"2021-07-04T16:33:27Z",
"id0"};
1595 repo.generateRepo(KeyType::kED25519);
1596 const std::string hwid =
"primary_hw";
1597 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1598 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1601 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1602 auto storage = INvStorage::newStorage(conf.storage);
1606 boost::signals2::connection ac_conn =
1607 aktualizr.
SetSignalHandler(std::bind(targets_autoclean_cb, std::ref(aktualizr), std::placeholders::_1));
1612 aktualizr.
Download(update_result.updates).get();
1617 EXPECT_TRUE(install_result.dev_report.success);
1620 ASSERT_EQ(targets.size(), 1);
1621 EXPECT_EQ(targets[0].filename(),
"primary_firmware.txt");
1625 repo.emptyTargets();
1626 repo.addImage(fake_meta_dir /
"fake_meta/dummy_firmware.txt",
"dummy_firmware.txt", hwid,
"", {});
1627 repo.addTarget(
"dummy_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1632 aktualizr.
Download(update_result.updates).get();
1637 EXPECT_TRUE(install_result.dev_report.success);
1641 ASSERT_EQ(targets.size(), 2);
1645 repo.emptyTargets();
1646 repo.addImage(fake_meta_dir /
"fake_meta/primary_firmware.txt",
"primary_firmware.txt", hwid,
"", {});
1647 repo.addTarget(
"primary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1652 aktualizr.
Download(update_result.updates).get();
1657 EXPECT_TRUE(install_result.dev_report.success);
1661 ASSERT_EQ(targets.size(), 2);
1665 repo.emptyTargets();
1666 repo.addImage(fake_meta_dir /
"fake_meta/secondary_firmware.txt",
"secondary_firmware.txt", hwid,
"", {});
1667 repo.addTarget(
"secondary_firmware.txt", hwid,
"CA:FE:A6:D2:84:9D",
"");
1672 aktualizr.
Download(update_result.updates).get();
1677 EXPECT_TRUE(install_result.dev_report.success);
1681 ASSERT_EQ(targets.size(), 2);
1684 Aktualizr::InstallationLog log = aktualizr.GetInstallationLog();
1685 ASSERT_EQ(log.size(), 2);
1687 EXPECT_EQ(log[0].installs.size(), 4);
1688 EXPECT_EQ(log[1].installs.size(), 0);
1690 std::vector<std::string> fws{
"primary_firmware.txt",
"dummy_firmware.txt",
"primary_firmware.txt",
1691 "secondary_firmware.txt"};
1692 for (
auto it = log[0].installs.begin(); it < log[0].installs.end(); it++) {
1693 auto idx = static_cast<size_t>(it - log[0].installs.begin());
1694 EXPECT_EQ(it->filename(), fws[idx]);
1705 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1706 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1708 auto storage = INvStorage::newStorage(conf.storage);
1712 size_t num_events{0};
1713 std::vector<Uptane::Target> updates;
1714 std::future<void> future;
1715 std::promise<void> promise;
1717 ev_state.future = ev_state.promise.get_future();
1719 auto f_cb = [&ev_state](
const std::shared_ptr<event::BaseEvent>&
event) {
1725 LOG_INFO <<
"Got " <<
event->variant;
1726 switch (ev_state.num_events) {
1728 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
1729 const auto installs_complete = dynamic_cast<event::AllInstallsComplete*>(
event.get());
1730 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 0);
1734 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
1735 const auto targets_event = dynamic_cast<event::UpdateCheckComplete*>(
event.get());
1736 EXPECT_EQ(targets_event->result.ecus_count, 2);
1737 EXPECT_EQ(targets_event->result.updates.size(), 2u);
1738 EXPECT_EQ(targets_event->result.updates[0].filename(),
"primary_firmware.txt");
1739 EXPECT_EQ(targets_event->result.updates[1].filename(),
"secondary_firmware.txt");
1740 EXPECT_EQ(targets_event->result.status, result::UpdateStatus::kUpdatesAvailable);
1741 ev_state.updates = targets_event->result.updates;
1746 ASSERT_EQ(
event->variant,
"DownloadTargetComplete");
1747 const auto download_event = dynamic_cast<event::DownloadTargetComplete*>(
event.get());
1748 EXPECT_TRUE(download_event->update.filename() ==
"primary_firmware.txt" ||
1749 download_event->update.filename() ==
"secondary_firmware.txt");
1750 EXPECT_TRUE(download_event->success);
1754 ASSERT_EQ(
event->variant,
"AllDownloadsComplete");
1755 const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete*>(
event.get());
1756 EXPECT_EQ(downloads_complete->result.updates.size(), 2);
1757 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"primary_firmware.txt" ||
1758 downloads_complete->result.updates[1].filename() ==
"primary_firmware.txt");
1759 EXPECT_TRUE(downloads_complete->result.updates[0].filename() ==
"secondary_firmware.txt" ||
1760 downloads_complete->result.updates[1].filename() ==
"secondary_firmware.txt");
1761 EXPECT_EQ(downloads_complete->result.status, result::DownloadStatus::kSuccess);
1767 ASSERT_EQ(
event->variant,
"InstallStarted");
1768 const auto install_started = dynamic_cast<event::InstallStarted*>(
event.get());
1769 EXPECT_EQ(install_started->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1775 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
1776 const auto install_complete = dynamic_cast<event::InstallTargetComplete*>(
event.get());
1777 EXPECT_EQ(install_complete->serial.ToString(),
"CA:FE:A6:D2:84:9D");
1778 EXPECT_TRUE(install_complete->success);
1782 ASSERT_EQ(
event->variant,
"InstallStarted");
1783 const auto install_started = dynamic_cast<event::InstallStarted*>(
event.get());
1784 EXPECT_EQ(install_started->serial.ToString(),
"secondary_ecu_serial");
1788 ASSERT_EQ(
event->variant,
"InstallTargetComplete");
1789 const auto install_complete = dynamic_cast<event::InstallTargetComplete*>(
event.get());
1790 EXPECT_EQ(install_complete->serial.ToString(),
"secondary_ecu_serial");
1791 EXPECT_TRUE(install_complete->success);
1795 ASSERT_EQ(
event->variant,
"AllInstallsComplete");
1796 const auto installs_complete = dynamic_cast<event::AllInstallsComplete*>(
event.get());
1797 EXPECT_EQ(installs_complete->result.ecu_reports.size(), 2);
1798 EXPECT_EQ(installs_complete->result.ecu_reports[0].install_res.result_code.num_code,
1799 data::ResultCode::Numeric::kOk);
1800 EXPECT_EQ(installs_complete->result.ecu_reports[1].install_res.result_code.num_code,
1801 data::ResultCode::Numeric::kOk);
1802 ev_state.promise.set_value();
1807 FAIL() <<
"Unexpected events!";
1809 std::cout <<
"event #" << ev_state.num_events <<
" is: " <<
event->variant <<
"\n";
1810 ASSERT_EQ(
event->variant,
"");
1812 ++ev_state.num_events;
1818 Json::Value primary_json;
1819 primary_json[
"hashes"][
"sha256"] =
"74e653bbf6c00a88b21f0992159b1002f5af38506e6d2fbc7eb9846711b2d75f";
1820 primary_json[
"hashes"][
"sha512"] =
1821 "91814ad1c13ebe2af8d65044893633c4c3ce964edb8cb58b0f357406c255f7be94f42547e108b300346a42cd57662e4757b9d843b7acbc09"
1823 primary_json[
"length"] = 2;
1824 Uptane::Target primary_target(
"primary_firmware.txt", primary_json);
1826 Json::Value secondary_json;
1827 secondary_json[
"hashes"][
"sha256"] =
"1bbb15aa921ffffd5079567d630f43298dbe5e7cbc1b14e0ccdd6718fde28e47";
1828 secondary_json[
"hashes"][
"sha512"] =
1829 "7dbae4c36a2494b731a9239911d3085d53d3e400886edb4ae2b9b78f40bda446649e83ba2d81653f614cc66f5dd5d4dbd95afba854f148af"
1831 secondary_json[
"length"] = 2;
1832 Uptane::Target secondary_target(
"secondary_firmware.txt", secondary_json);
1836 EXPECT_EQ(
result.ecu_reports.size(), 0);
1838 EXPECT_THROW(aktualizr.
OpenStoredTarget(primary_target).get(), std::runtime_error)
1839 <<
"Primary firmware is present in storage before the download";
1840 EXPECT_THROW(aktualizr.
OpenStoredTarget(secondary_target).get(), std::runtime_error)
1841 <<
"Secondary firmware is present in storage before the download";
1844 aktualizr.
Download(update_result.updates).get();
1846 <<
"Primary firmware is not present in storage after the download";
1848 <<
"Secondary firmware is not present in storage after the download";
1851 aktualizr.
Install(update_result.updates);
1853 auto status = ev_state.future.wait_for(std::chrono::seconds(20));
1854 if (status != std::future_status::ready) {
1855 FAIL() <<
"Timed out waiting for installation to complete.";
1866 TEST(
Aktualizr, ReportDownloadProgress) {
1870 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
1871 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1872 auto storage = INvStorage::newStorage(conf.storage);
1875 unsigned int report_counter = {0};
1876 std::shared_ptr<const event::DownloadProgressReport> lastProgressReport{
nullptr};
1878 std::function<void(std::shared_ptr<event::BaseEvent>
event)> report_event_hdlr =
1879 [&](
const std::shared_ptr<event::BaseEvent>&
event) {
1880 ASSERT_NE(
event,
nullptr);
1885 auto download_progress_event = std::dynamic_pointer_cast<event::DownloadProgressReport>(
event);
1886 ASSERT_NE(download_progress_event,
nullptr);
1887 ASSERT_NE(download_progress_event.get(),
nullptr);
1888 if (lastProgressReport) {
1889 EXPECT_GE(download_progress_event->progress, lastProgressReport->progress);
1891 lastProgressReport = download_progress_event;
1899 ASSERT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
1902 update_result.updates.pop_back();
1905 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
1907 ASSERT_NE(lastProgressReport,
nullptr);
1908 ASSERT_NE(lastProgressReport.get(),
nullptr);
1909 EXPECT_TRUE(event::DownloadProgressReport::isDownloadCompleted(*lastProgressReport));
1910 EXPECT_GT(report_counter, 1);
1915 HttpFakeCampaign(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
1916 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
1918 HttpResponse get(
const std::string& url, int64_t maxsize)
override {
1919 EXPECT_NE(url.find(
"campaigner/"), std::string::npos);
1920 boost::filesystem::path path = meta_dir / url.substr(tls_server.size() + strlen(
"campaigner/"));
1922 if (url.find(
"campaigner/campaigns") != std::string::npos) {
1923 return HttpResponse(Utils::readFile(path.parent_path() /
"campaigner/campaigns.json"), 200, CURLE_OK,
"");
1925 return HttpFake::get(url, maxsize);
1928 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
1930 for (
auto it =
data.begin(); it !=
data.end(); it++) {
1932 auto id = ev[
"eventType"][
"id"];
1933 if (
id ==
"campaign_accepted" ||
id ==
"campaign_declined" ||
id ==
"campaign_postponed") {
1934 seen_events.push_back(ev);
1940 std::vector<Json::Value> seen_events;
1945 bool campaignaccept_seen{
false};
1946 bool campaigndecline_seen{
false};
1947 bool campaignpostpone_seen{
false};
1949 void handler(
const std::shared_ptr<event::BaseEvent>&
event) {
1950 std::cout <<
event->variant <<
"\n";
1951 if (
event->variant ==
"CampaignCheckComplete") {
1952 auto concrete_event = std::static_pointer_cast<event::CampaignCheckComplete>(
event);
1953 EXPECT_EQ(concrete_event->result.campaigns.size(), 1);
1954 EXPECT_EQ(concrete_event->result.campaigns[0].name,
"campaign1");
1955 EXPECT_EQ(concrete_event->result.campaigns[0].id,
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
1956 EXPECT_EQ(concrete_event->result.campaigns[0].size, 62470);
1957 EXPECT_EQ(concrete_event->result.campaigns[0].autoAccept,
true);
1958 EXPECT_EQ(concrete_event->result.campaigns[0].description,
"this is my message to show on the device");
1959 }
else if (
event->variant ==
"CampaignAcceptComplete") {
1960 campaignaccept_seen =
true;
1961 }
else if (
event->variant ==
"CampaignDeclineComplete") {
1962 campaigndecline_seen =
true;
1963 }
else if (
event->variant ==
"CampaignPostponeComplete") {
1964 campaignpostpone_seen =
true;
1985 TEST(
Aktualizr, CampaignCheckAndControl) {
1987 auto http = std::make_shared<HttpFakeCampaign>(temp_dir.Path(), fake_meta_dir);
1988 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
1993 auto storage = INvStorage::newStorage(conf.storage);
1995 aktualizr.
SetSignalHandler(std::bind(&CampaignEvents::handler, &campaign_events, std::placeholders::_1));
2000 EXPECT_EQ(
result.campaigns.size(), 1);
2003 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Accept).get();
2005 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Decline).get();
2007 aktualizr.
CampaignControl(
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493", campaign::Cmd::Postpone).get();
2010 ASSERT_EQ(http->seen_events.size(), 3);
2011 for (
const auto& ev : http->seen_events) {
2012 EXPECT_EQ(ev[
"event"][
"campaignId"],
"c2eb7e8d-8aa0-429d-883f-5ed8fdb2a493");
2014 EXPECT_TRUE(campaign_events.campaignaccept_seen);
2015 EXPECT_TRUE(campaign_events.campaigndecline_seen);
2016 EXPECT_TRUE(campaign_events.campaignpostpone_seen);
2021 HttpFakeNoCorrelationId(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2022 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2024 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
2028 EXPECT_EQ(
event[
"event"][
"correlationId"].asString(),
"");
2033 unsigned int events_seen{0};
2040 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/repo", meta_dir.Path() /
"repo");
2041 Utils::copyDir(uptane_repos_dir /
"full_no_correlation_id/repo/director", meta_dir.Path() /
"director");
2042 auto http = std::make_shared<HttpFakeNoCorrelationId>(temp_dir.Path(), meta_dir.Path());
2047 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2049 auto storage = INvStorage::newStorage(conf.storage);
2054 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
2057 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
2060 for (
const auto& r : install_result.ecu_reports) {
2061 EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
2065 EXPECT_EQ(http->events_seen, 8);
2070 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"", fake_meta_dir);
2073 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2075 auto storage = INvStorage::newStorage(conf.storage);
2079 Json::Value custom = Utils::parseJSON(R
"({"test_field":"test_value"})");
2080 ASSERT_EQ(custom["test_field"].asString(),
"test_value");
2081 ASSERT_EQ(
true, aktualizr.
SendManifest(custom).get()) <<
"Failed to upload manifest with HttpFake server";
2082 EXPECT_EQ(http->last_manifest[
"signed"][
"custom"], custom);
2093 std::function<void(std::shared_ptr<event::BaseEvent>)> Signal() {
2094 return std::bind(&CountUpdateCheckEvents::count,
this, std::placeholders::_1);
2097 void count(std::shared_ptr<event::BaseEvent>
event) {
2098 std::cout <<
event->variant <<
"\n";
2099 if (
event->variant ==
"UpdateCheckComplete") {
2101 if (std::static_pointer_cast<event::UpdateCheckComplete>(
event)->
result.status == result::UpdateStatus::kError) {
2107 int total_events()
const {
return total_events_; }
2108 int error_events()
const {
return error_events_; }
2111 int total_events_{0};
2112 int error_events_{0};
2117 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates", fake_meta_dir);
2119 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2121 auto storage = INvStorage::newStorage(conf.storage);
2126 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2128 std::vector<std::future<result::UpdateCheck>> futures;
2129 for (
int i = 0; i < 5; ++i) {
2133 for (
auto& f : futures) {
2138 EXPECT_EQ(counter.total_events(), 5);
2144 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter2.Signal());
2147 std::future<result::UpdateCheck> ft = aktualizr.
CheckUpdates();
2148 for (
int i = 0; i < 99; ++i) {
2153 EXPECT_LT(counter2.total_events(), 100);
2154 EXPECT_GT(counter2.total_events(), 0);
2159 HttpPutManifestFail(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2160 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2161 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
2168 TEST(
Aktualizr, UpdateCheckCompleteError) {
2170 auto http = std::make_shared<HttpPutManifestFail>(temp_dir.Path(), fake_meta_dir);
2172 Config conf = UptaneTestCommon::makeTestConfig(temp_dir,
"http://updatefail");
2174 auto storage = INvStorage::newStorage(conf.storage);
2178 boost::signals2::connection conn = aktualizr.
SetSignalHandler(counter.Signal());
2181 EXPECT_EQ(
result.status, result::UpdateStatus::kError);
2182 EXPECT_EQ(counter.error_events(), 1);
2192 HttpFakePauseCounter(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2193 :
HttpFake(test_dir_in,
"noupdates", meta_dir_in) {}
2195 HttpResponse handle_event(
const std::string& url,
const Json::Value&
data)
override {
2199 std::string event_type =
event[
"eventType"][
"id"].asString();
2201 std::cout <<
"got event #" << events_seen <<
": " << event_type <<
"\n";
2202 if (events_seen == 1) {
2203 EXPECT_EQ(event_type,
"DevicePaused");
2204 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2205 }
else if (events_seen == 2) {
2206 EXPECT_EQ(event_type,
"DeviceResumed");
2207 EXPECT_EQ(
event[
"event"][
"correlationId"],
"id0");
2209 std::cout <<
"Unexpected event";
2216 unsigned int events_seen{0};
2221 auto http = std::make_shared<HttpFakePauseCounter>(temp_dir.Path(), fake_meta_dir);
2222 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2224 auto storage = INvStorage::newStorage(conf.storage);
2229 std::promise<void> end_promise{};
2230 size_t n_events = 0;
2231 std::atomic_bool is_paused{
false};
2232 std::function<void(std::shared_ptr<event::BaseEvent>)> cb = [&end_promise, &n_events, &mutex,
2233 &is_paused](std::shared_ptr<event::BaseEvent>
event) {
2236 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
2239 std::lock_guard<std::mutex> guard(mutex);
2241 ASSERT_EQ(
event->variant,
"UpdateCheckComplete");
2243 EXPECT_FALSE(is_paused);
2244 end_promise.set_value();
2248 FAIL() <<
"Unexpected event";
2258 std::lock_guard<std::mutex> guard(mutex);
2259 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kSuccess);
2263 EXPECT_EQ(aktualizr.
Pause().status, result::PauseStatus::kAlreadyPaused);
2268 std::this_thread::sleep_for(std::chrono::seconds(1));
2271 std::lock_guard<std::mutex> guard(mutex);
2273 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kSuccess);
2276 EXPECT_EQ(aktualizr.
Resume().status, result::PauseStatus::kAlreadyRunning);
2278 auto status = end_promise.get_future().wait_for(std::chrono::seconds(20));
2279 if (status != std::future_status::ready) {
2280 FAIL() <<
"Timed out waiting for UpdateCheck event";
2284 const std::string custom_hwinfo =
2285 R
"([{"description":"ECU1","ECU P/N":"AAA","HW P/N":"BBB","HW Version":"1.234",
2286 "SW P/N":"CCC","SW Version":"4.321","ECU Serial":"AAA-BBB-CCC"},
2287 {"description":"ECU2","ECU P/N":"ZZZ","HW P/N":"XXX","HW Version":"9.876",
2288 "SW P/N":"YYY","SW Version":"6.789","ECU Serial":"VVV-NNN-MMM"}])";
2292 HttpSystemInfo(
const boost::filesystem::path& test_dir_in,
const boost::filesystem::path& meta_dir_in)
2293 :
HttpFake(test_dir_in,
"", meta_dir_in) {}
2295 HttpResponse put(
const std::string& url,
const Json::Value&
data)
override {
2296 if (url.find(hwinfo_ep_) == url.length() - hwinfo_ep_.length()) {
2297 if (info_count_ == 0) {
2298 EXPECT_TRUE(
data.isObject());
2299 EXPECT_TRUE(
data.isMember(
"description"));
2300 }
else if (info_count_ == 1) {
2301 auto hwinfo = Utils::parseJSON(custom_hwinfo);
2302 EXPECT_EQ(hwinfo,
data);
2306 }
else if (url.find(
"/manifest") != std::string::npos) {
2309 return HttpResponse(
"", 404, CURLE_HTTP_RETURNED_ERROR,
"Not found");
2315 std::string hwinfo_ep_{
"/system_info"};
2320 auto http = std::make_shared<HttpSystemInfo>(temp_dir.Path(), fake_meta_dir);
2321 Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
2323 auto storage = INvStorage::newStorage(conf.storage);
2329 auto hwinfo = Utils::parseJSON(custom_hwinfo);
2334 int main(
int argc,
char** argv) {
2335 ::testing::InitGoogleTest(&argc, argv);
2337 std::cerr <<
"Error: " << argv[0] <<
" requires the path to the base directory of Uptane repos.\n";
2338 return EXIT_FAILURE;
2340 uptane_repos_dir = argv[1];
2343 logger_set_threshold(boost::log::trivial::trace);
2346 fake_meta_dir = tmp_dir.Path();
2349 return RUN_ALL_TESTS();