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