Aktualizr
C++ SOTA Client
uptane_delegation_test.cc
1 #include <gtest/gtest.h>
2 
3 #include <string>
4 
5 #include <boost/filesystem.hpp>
6 #include "json/json.h"
7 
8 #include "libaktualizr/aktualizr.h"
9 #include "libaktualizr/config.h"
10 #include "libaktualizr/events.h"
11 
12 #include "httpfake.h"
13 #include "uptane_test_common.h"
14 
15 boost::filesystem::path uptane_generator_path;
16 
17 void delegation_basic(const boost::filesystem::path& delegation_path, bool revoke) {
18  std::string output;
19  std::string cmd = "tests/uptane_repo_generation/delegation_basic.sh " + uptane_generator_path.string() + " " +
20  delegation_path.string();
21  if (revoke) {
22  cmd += " revoke";
23  }
24  int retval = Utils::shell(cmd, &output, true);
25  EXPECT_EQ(retval, EXIT_SUCCESS) << output;
26 }
27 
28 void delegation_nested(const boost::filesystem::path& delegation_path, bool revoke) {
29  std::string output;
30  std::string cmd = "tests/uptane_repo_generation/delegation_nested.sh " + uptane_generator_path.string() + " " +
31  delegation_path.string();
32  if (revoke) {
33  cmd += " revoke";
34  }
35  int retval = Utils::shell(cmd, &output, true);
36  EXPECT_EQ(retval, EXIT_SUCCESS) << output;
37 }
38 
39 class HttpFakeDelegation : public HttpFake {
40  public:
41  HttpFakeDelegation(const boost::filesystem::path& test_dir_in)
42  : HttpFake(test_dir_in, "", test_dir_in / "delegation_test/repo") {}
43 
44  HttpResponse handle_event(const std::string& url, const Json::Value& data) override {
45  (void)url;
46  for (const Json::Value& event : data) {
47  ++events_seen;
48  EXPECT_EQ(event["event"]["correlationId"].asString(), "");
49  }
50  return HttpResponse("", 200, CURLE_OK, "");
51  }
52 
53  unsigned int events_seen{0};
54 };
55 
56 /* Validate first-order target delegations.
57  * Search first-order delegations.
58  * Correlation ID is empty if none was provided in Targets metadata. */
59 TEST(Delegation, Basic) {
60  for (auto generate_fun : {delegation_basic, delegation_nested}) {
61  TemporaryDirectory temp_dir;
62  auto delegation_path = temp_dir.Path() / "delegation_test";
63  generate_fun(delegation_path, false);
64  auto http = std::make_shared<HttpFakeDelegation>(temp_dir.Path());
65 
66  // scope `Aktualizr` object, so that the ReportQueue flushes its events before
67  // we count them at the end
68  {
69  Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
70 
71  auto storage = INvStorage::newStorage(conf.storage);
72  UptaneTestCommon::TestAktualizr aktualizr(conf, storage, http);
73 
74  aktualizr.Initialize();
75  result::UpdateCheck update_result = aktualizr.CheckUpdates().get();
76  EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
77 
78  result::Download download_result = aktualizr.Download(update_result.updates).get();
79  EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
80 
81  result::Install install_result = aktualizr.Install(download_result.updates).get();
82  for (const auto& r : install_result.ecu_reports) {
83  EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
84  }
85  }
86 
87  EXPECT_EQ(http->events_seen, 8);
88  }
89 }
90 
91 TEST(Delegation, RevokeAfterCheckUpdates) {
92  for (auto generate_fun : {delegation_basic, delegation_nested}) {
93  TemporaryDirectory temp_dir;
94  auto http = std::make_shared<HttpFakeDelegation>(temp_dir.Path());
95  Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
96  auto storage = INvStorage::newStorage(conf.storage);
97 
98  auto delegation_path = temp_dir.Path() / "delegation_test";
99  {
100  generate_fun(delegation_path, false);
101  UptaneTestCommon::TestAktualizr aktualizr(conf, storage, http);
102  aktualizr.Initialize();
103 
104  result::UpdateCheck update_result = aktualizr.CheckUpdates().get();
105  EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
106  EXPECT_EQ(update_result.updates.size(), 2);
107  }
108  // Revoke delegation after CheckUpdates() and test if we can properly handle it.
109  {
110  generate_fun(delegation_path, true);
111  UptaneTestCommon::TestAktualizr aktualizr(conf, storage, http);
112  aktualizr.Initialize();
113 
114  auto update_result = aktualizr.CheckUpdates().get();
115  EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
116  EXPECT_EQ(update_result.updates.size(), 1);
117 
118  result::Download download_result = aktualizr.Download(update_result.updates).get();
119  EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
120 
121  result::Install install_result = aktualizr.Install(download_result.updates).get();
122  for (const auto& r : install_result.ecu_reports) {
123  EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
124  }
125  }
126  }
127 }
128 
129 TEST(Delegation, RevokeAfterDownload) {
130  for (auto generate_fun : {delegation_basic, delegation_nested}) {
131  TemporaryDirectory temp_dir;
132  auto http = std::make_shared<HttpFakeDelegation>(temp_dir.Path());
133  Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
134  auto storage = INvStorage::newStorage(conf.storage);
135 
136  auto delegation_path = temp_dir.Path() / "delegation_test";
137  {
138  generate_fun(delegation_path, false);
139  UptaneTestCommon::TestAktualizr aktualizr(conf, storage, http);
140  aktualizr.Initialize();
141 
142  result::UpdateCheck update_result = aktualizr.CheckUpdates().get();
143  EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
144 
145  result::Download download_result = aktualizr.Download(update_result.updates).get();
146  EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
147  }
148  // Revoke delegation after Download() and test if we can properly handle it
149  {
150  generate_fun(delegation_path, true);
151  UptaneTestCommon::TestAktualizr aktualizr(conf, storage, http);
152  aktualizr.Initialize();
153 
154  auto update_result = aktualizr.CheckUpdates().get();
155  EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
156  EXPECT_EQ(update_result.updates.size(), 1);
157 
158  result::Download download_result = aktualizr.Download(update_result.updates).get();
159  EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
160 
161  result::Install install_result = aktualizr.Install(download_result.updates).get();
162  for (const auto& r : install_result.ecu_reports) {
163  EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
164  }
165  }
166  }
167 }
168 
169 TEST(Delegation, RevokeAfterInstall) {
170  for (auto generate_fun : {delegation_basic, delegation_nested}) {
171  TemporaryDirectory temp_dir;
172  auto http = std::make_shared<HttpFakeDelegation>(temp_dir.Path());
173  Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
174  auto storage = INvStorage::newStorage(conf.storage);
175 
176  auto delegation_path = temp_dir.Path() / "delegation_test";
177  {
178  generate_fun(delegation_path, false);
179  UptaneTestCommon::TestAktualizr aktualizr(conf, storage, http);
180  aktualizr.Initialize();
181 
182  result::UpdateCheck update_result = aktualizr.CheckUpdates().get();
183  EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
184 
185  result::Download download_result = aktualizr.Download(update_result.updates).get();
186  EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
187 
188  result::Install install_result = aktualizr.Install(download_result.updates).get();
189  for (const auto& r : install_result.ecu_reports) {
190  EXPECT_EQ(r.install_res.result_code.num_code, data::ResultCode::Numeric::kOk);
191  }
192  }
193  // Revoke delegation after Install() and test if can properly CheckUpdates again
194  {
195  generate_fun(delegation_path, true);
196  UptaneTestCommon::TestAktualizr aktualizr(conf, storage, http);
197  aktualizr.Initialize();
198 
199  auto update_result = aktualizr.CheckUpdates().get();
200  EXPECT_EQ(update_result.status, result::UpdateStatus::kNoUpdatesAvailable);
201  }
202  }
203 }
204 
205 /* Iterate over targets in delegation tree */
206 TEST(Delegation, IterateAll) {
207  TemporaryDirectory temp_dir;
208  auto delegation_path = temp_dir.Path() / "delegation_test";
209  delegation_nested(delegation_path, false);
210  auto http = std::make_shared<HttpFakeDelegation>(temp_dir.Path());
211 
212  Config conf = UptaneTestCommon::makeTestConfig(temp_dir, http->tls_server);
213 
214  auto storage = INvStorage::newStorage(conf.storage);
215  UptaneTestCommon::TestAktualizr aktualizr(conf, storage, http);
216 
217  aktualizr.Initialize();
218  result::UpdateCheck update_result = aktualizr.CheckUpdates().get();
219  EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
220 
221  std::vector<std::string> expected_target_names = {"primary.txt", "abracadabra", "abc/secondary.txt", "abc/target0",
222  "abc/target1", "abc/target2", "bcd/target0", "cde/target0",
223  "cde/target1", "def/target0"};
224  for (auto& target : aktualizr.uptane_client()->allTargets()) {
225  EXPECT_EQ(target.filename(), expected_target_names[0]);
226  expected_target_names.erase(expected_target_names.begin());
227  }
228 
229  EXPECT_TRUE(expected_target_names.empty());
230 }
231 
232 #ifndef __NO_MAIN__
233 int main(int argc, char** argv) {
234  ::testing::InitGoogleTest(&argc, argv);
235  if (argc != 2) {
236  std::cerr << "Error: " << argv[0] << " requires the path to the uptane-generator utility\n";
237  return EXIT_FAILURE;
238  }
239  uptane_generator_path = argv[1];
240 
241  logger_init();
242  logger_set_threshold(boost::log::trivial::trace);
243 
244  return RUN_ALL_TESTS();
245 }
246 #endif
247 
248 // vim: set tabstop=2 shiftwidth=2 expandtab:
HttpFake
Definition: httpfake.h:20
UptaneTestCommon::TestAktualizr
Definition: uptane_test_common.h:21
HttpFakeDelegation
Definition: uptane_delegation_test.cc:39
result::UpdateCheck
Container for information about available updates.
Definition: results.h:37
data
General data structures.
Definition: types.h:217
HttpResponse
Definition: httpinterface.h:17
Config
Configuration object for an aktualizr instance running on a Primary ECU.
Definition: config.h:208
events.h
result::Download
Container for information about downloading an update.
Definition: results.h:116
TemporaryDirectory
Definition: utils.h:82
result::Install
Container for information about installing an update.
Definition: results.h:129
Delegation
Definition: repo.h:19
event
Aktualizr status events.
Definition: events.h:15