Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
storage_common_test.cc
1 #include <gtest/gtest.h>
2 
3 #include <memory>
4 #include <string>
5 
6 #include <boost/filesystem.hpp>
7 
8 #include "logging/logging.h"
9 #include "storage/sqlstorage.h"
10 #include "utilities/types.h"
11 #include "utilities/utils.h"
12 
13 StorageType current_storage_type{StorageType::kSqlite};
14 
15 std::unique_ptr<INvStorage> Storage(const boost::filesystem::path &dir) {
16  StorageConfig storage_config;
17  storage_config.type = current_storage_type;
18  storage_config.path = dir;
19 
20  if (storage_config.type == StorageType::kSqlite) {
21  return std::unique_ptr<INvStorage>(new SQLStorage(storage_config, false));
22  } else {
23  throw std::runtime_error("Invalid config type");
24  }
25 }
26 
27 StorageConfig MakeConfig(StorageType type, const boost::filesystem::path &storage_dir) {
28  StorageConfig config;
29 
30  config.type = type;
31  if (config.type == StorageType::kSqlite) {
32  config.sqldb_path = storage_dir / "test.db";
33  } else {
34  throw std::runtime_error("Invalid config type");
35  }
36  return config;
37 }
38 
39 /* Load and store primary keys. */
40 TEST(storage, load_store_primary_keys) {
41  TemporaryDirectory temp_dir;
42  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
43 
44  storage->storePrimaryKeys("", "");
45  storage->storePrimaryKeys("pr_public", "pr_private");
46 
47  std::string pubkey;
48  std::string privkey;
49 
50  EXPECT_TRUE(storage->loadPrimaryKeys(&pubkey, &privkey));
51  EXPECT_EQ(pubkey, "pr_public");
52  EXPECT_EQ(privkey, "pr_private");
53  storage->clearPrimaryKeys();
54  EXPECT_FALSE(storage->loadPrimaryKeys(nullptr, nullptr));
55 }
56 
57 /* Load and store TLS credentials. */
58 TEST(storage, load_store_tls) {
59  TemporaryDirectory temp_dir;
60  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
61 
62  storage->storeTlsCreds("", "", "");
63  storage->storeTlsCreds("ca", "cert", "priv");
64  std::string ca;
65  std::string cert;
66  std::string priv;
67 
68  EXPECT_TRUE(storage->loadTlsCreds(&ca, &cert, &priv));
69 
70  EXPECT_EQ(ca, "ca");
71  EXPECT_EQ(cert, "cert");
72  EXPECT_EQ(priv, "priv");
73  storage->clearTlsCreds();
74  EXPECT_FALSE(storage->loadTlsCreds(nullptr, nullptr, nullptr));
75 }
76 
77 /* Load and store Uptane metadata. */
78 TEST(storage, load_store_metadata) {
79  TemporaryDirectory temp_dir;
80  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
81 
82  Json::Value root_json;
83  root_json["_type"] = "Root";
84  root_json["consistent_snapshot"] = false;
85  root_json["expires"] = "2038-01-19T03:14:06Z";
86  root_json["keys"]["firstid"]["keytype"] = "ed25519";
87  root_json["keys"]["firstid"]["keyval"]["public"] = "firstval";
88  root_json["keys"]["secondid"]["keytype"] = "ed25519";
89  root_json["keys"]["secondid"]["keyval"]["public"] = "secondval";
90 
91  root_json["roles"]["root"]["threshold"] = 1;
92  root_json["roles"]["root"]["keyids"][0] = "firstid";
93  root_json["roles"]["snapshot"]["threshold"] = 1;
94  root_json["roles"]["snapshot"]["keyids"][0] = "firstid";
95  root_json["roles"]["targets"]["threshold"] = 1;
96  root_json["roles"]["targets"]["keyids"][0] = "firstid";
97  root_json["roles"]["timestamp"]["threshold"] = 1;
98  root_json["roles"]["timestamp"]["keyids"][0] = "firstid";
99 
100  Json::Value meta_root;
101  meta_root["signed"] = root_json;
102  std::string director_root = Utils::jsonToStr(meta_root);
103  std::string images_root = Utils::jsonToStr(meta_root);
104 
105  Json::Value targets_json;
106  targets_json["_type"] = "Targets";
107  targets_json["expires"] = "2038-01-19T03:14:06Z";
108  targets_json["targets"]["file1"]["custom"]["ecu_identifier"] = "ecu1";
109  targets_json["targets"]["file1"]["custom"]["hardware_identifier"] = "hw1";
110  targets_json["targets"]["file1"]["hashes"]["sha256"] = "12ab";
111  targets_json["targets"]["file1"]["length"] = 1;
112  targets_json["targets"]["file2"]["custom"]["ecu_identifier"] = "ecu2";
113  targets_json["targets"]["file2"]["custom"]["hardware_identifier"] = "hw2";
114  targets_json["targets"]["file2"]["hashes"]["sha512"] = "12ab";
115  targets_json["targets"]["file2"]["length"] = 11;
116 
117  Json::Value meta_targets;
118  meta_targets["signed"] = targets_json;
119  std::string director_targets = Utils::jsonToStr(meta_targets);
120  std::string images_targets = Utils::jsonToStr(meta_targets);
121 
122  Json::Value timestamp_json;
123  timestamp_json["signed"]["_type"] = "Timestamp";
124  timestamp_json["signed"]["expires"] = "2038-01-19T03:14:06Z";
125  std::string images_timestamp = Utils::jsonToStr(timestamp_json);
126 
127  Json::Value snapshot_json;
128  snapshot_json["_type"] = "Snapshot";
129  snapshot_json["expires"] = "2038-01-19T03:14:06Z";
130  snapshot_json["meta"]["root.json"]["version"] = 1;
131  snapshot_json["meta"]["targets.json"]["version"] = 2;
132  snapshot_json["meta"]["timestamp.json"]["version"] = 3;
133  snapshot_json["meta"]["snapshot.json"]["version"] = 4;
134 
135  Json::Value meta_snapshot;
136  meta_snapshot["signed"] = snapshot_json;
137  std::string images_snapshot = Utils::jsonToStr(meta_snapshot);
138 
139  storage->storeRoot(director_root, Uptane::RepositoryType::Director(), Uptane::Version(1));
140  storage->storeNonRoot(director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
141  storage->storeRoot(images_root, Uptane::RepositoryType::Image(), Uptane::Version(1));
142  storage->storeNonRoot(images_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets());
143  storage->storeNonRoot(images_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp());
144  storage->storeNonRoot(images_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot());
145 
146  std::string loaded_director_root;
147  std::string loaded_director_targets;
148  std::string loaded_images_root;
149  std::string loaded_images_targets;
150  std::string loaded_images_timestamp;
151  std::string loaded_images_snapshot;
152 
153  EXPECT_TRUE(storage->loadLatestRoot(&loaded_director_root, Uptane::RepositoryType::Director()));
154  EXPECT_TRUE(
155  storage->loadNonRoot(&loaded_director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
156  EXPECT_TRUE(storage->loadLatestRoot(&loaded_images_root, Uptane::RepositoryType::Image()));
157  EXPECT_TRUE(storage->loadNonRoot(&loaded_images_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
158  EXPECT_TRUE(
159  storage->loadNonRoot(&loaded_images_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
160  EXPECT_TRUE(storage->loadNonRoot(&loaded_images_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
161  EXPECT_EQ(director_root, loaded_director_root);
162  EXPECT_EQ(director_targets, loaded_director_targets);
163  EXPECT_EQ(images_root, loaded_images_root);
164  EXPECT_EQ(images_targets, loaded_images_targets);
165  EXPECT_EQ(images_timestamp, loaded_images_timestamp);
166  EXPECT_EQ(images_snapshot, loaded_images_snapshot);
167 
168  storage->clearNonRootMeta(Uptane::RepositoryType::Director());
169  storage->clearNonRootMeta(Uptane::RepositoryType::Image());
170  EXPECT_FALSE(
171  storage->loadNonRoot(&loaded_director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
172  EXPECT_FALSE(
173  storage->loadNonRoot(&loaded_images_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
174 }
175 
176 /* Load and store Uptane roots. */
177 TEST(storage, load_store_root) {
178  TemporaryDirectory temp_dir;
179  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
180 
181  Json::Value root_json;
182  root_json["_type"] = "Root";
183  root_json["consistent_snapshot"] = false;
184  root_json["expires"] = "2038-01-19T03:14:06Z";
185  root_json["keys"]["firstid"]["keytype"] = "ed25519";
186  root_json["keys"]["firstid"]["keyval"]["public"] = "firstval";
187  root_json["keys"]["secondid"]["keytype"] = "ed25519";
188  root_json["keys"]["secondid"]["keyval"]["public"] = "secondval";
189 
190  root_json["roles"]["root"]["threshold"] = 1;
191  root_json["roles"]["root"]["keyids"][0] = "firstid";
192  root_json["roles"]["snapshot"]["threshold"] = 1;
193  root_json["roles"]["snapshot"]["keyids"][0] = "firstid";
194  root_json["roles"]["targets"]["threshold"] = 1;
195  root_json["roles"]["targets"]["keyids"][0] = "firstid";
196  root_json["roles"]["timestamp"]["threshold"] = 1;
197  root_json["roles"]["timestamp"]["keyids"][0] = "firstid";
198 
199  Json::Value meta_root;
200  meta_root["signed"] = root_json;
201 
202  std::string loaded_root;
203 
204  storage->storeRoot(Utils::jsonToStr(meta_root), Uptane::RepositoryType::Director(), Uptane::Version(2));
205  EXPECT_TRUE(storage->loadRoot(&loaded_root, Uptane::RepositoryType::Director(), Uptane::Version(2)));
206  EXPECT_EQ(Utils::jsonToStr(meta_root), loaded_root);
207 
208  EXPECT_TRUE(storage->loadLatestRoot(&loaded_root, Uptane::RepositoryType::Director()));
209  EXPECT_EQ(Utils::jsonToStr(meta_root), loaded_root);
210 }
211 
212 /* Load and store the device ID. */
213 TEST(storage, load_store_deviceid) {
214  TemporaryDirectory temp_dir;
215  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
216 
217  storage->storeDeviceId("");
218  storage->storeDeviceId("device_id");
219 
220  std::string device_id;
221 
222  EXPECT_TRUE(storage->loadDeviceId(&device_id));
223 
224  EXPECT_EQ(device_id, "device_id");
225  storage->clearDeviceId();
226  EXPECT_FALSE(storage->loadDeviceId(nullptr));
227 }
228 
229 /* Load and store ECU serials.
230  * Preserve ECU ordering between store and load calls.
231  */
232 TEST(storage, load_store_ecu_serials) {
233  TemporaryDirectory temp_dir;
234  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
235 
236  storage->storeEcuSerials({{Uptane::EcuSerial("a"), Uptane::HardwareIdentifier("")}});
237  EcuSerials serials{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")},
238  {Uptane::EcuSerial("secondary_1"), Uptane::HardwareIdentifier("secondary_hw")},
239  {Uptane::EcuSerial("secondary_2"), Uptane::HardwareIdentifier("secondary_hw")}};
240  storage->storeEcuSerials(serials);
241 
242  EcuSerials serials_out;
243 
244  EXPECT_TRUE(storage->loadEcuSerials(&serials_out));
245 
246  EXPECT_EQ(serials, serials_out);
247  storage->clearEcuSerials();
248  EXPECT_FALSE(storage->loadEcuSerials(nullptr));
249 }
250 
251 /* Load and store a list of misconfigured ECUs. */
252 TEST(storage, load_store_misconfigured_ecus) {
253  TemporaryDirectory temp_dir;
254  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
255 
256  std::vector<MisconfiguredEcu> ecus;
257  ecus.push_back(MisconfiguredEcu(Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw"),
258  EcuState::kNotRegistered));
259 
260  storage->storeMisconfiguredEcus(ecus);
261 
262  std::vector<MisconfiguredEcu> ecus_out;
263 
264  EXPECT_TRUE(storage->loadMisconfiguredEcus(&ecus_out));
265 
266  EXPECT_EQ(ecus_out.size(), ecus.size());
267  EXPECT_EQ(ecus_out[0].serial, Uptane::EcuSerial("primary"));
268  EXPECT_EQ(ecus_out[0].hardware_id, Uptane::HardwareIdentifier("primary_hw"));
269  EXPECT_EQ(ecus_out[0].state, EcuState::kNotRegistered);
270 
271  storage->clearMisconfiguredEcus();
272  ecus_out.clear();
273  EXPECT_FALSE(storage->loadMisconfiguredEcus(&ecus_out));
274 }
275 
276 /* Load and store a flag indicating successful registration. */
277 TEST(storage, load_store_ecu_registered) {
278  TemporaryDirectory temp_dir;
279  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
280 
281  EXPECT_THROW(storage->storeEcuRegistered(), std::runtime_error);
282  storage->storeDeviceId("test");
283  storage->storeEcuRegistered();
284  storage->storeEcuRegistered();
285 
286  EXPECT_TRUE(storage->loadEcuRegistered());
287 
288  storage->clearEcuRegistered();
289  EXPECT_FALSE(storage->loadEcuRegistered());
290 }
291 
292 /* Load and store installed versions. */
293 TEST(storage, load_store_installed_versions) {
294  TemporaryDirectory temp_dir;
295  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
296 
297  // Test lazy primary installed version: primary ecu serial is not defined yet
298  const std::vector<Uptane::Hash> hashes = {
299  Uptane::Hash{Uptane::Hash::Type::kSha256, "2561"},
300  Uptane::Hash{Uptane::Hash::Type::kSha512, "5121"},
301  };
302  Uptane::EcuMap primary_ecu{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")}};
303  Uptane::Target t1{"update.bin", primary_ecu, hashes, 1, "corrid"};
304  Json::Value custom;
305  custom["version"] = 42;
306  custom["foo"] = "bar";
307  t1.updateCustom(custom);
308  storage->savePrimaryInstalledVersion(t1, InstalledVersionUpdateMode::kCurrent);
309  {
310  std::vector<Uptane::Target> log;
311  storage->loadPrimaryInstallationLog(&log, true);
312  EXPECT_EQ(log.size(), 1);
313  EXPECT_EQ(log[0].filename(), "update.bin");
314  }
315 
316  EcuSerials serials{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")},
317  {Uptane::EcuSerial("secondary_1"), Uptane::HardwareIdentifier("secondary_hw")},
318  {Uptane::EcuSerial("secondary_2"), Uptane::HardwareIdentifier("secondary_hw")}};
319  storage->storeEcuSerials(serials);
320 
321  {
322  boost::optional<Uptane::Target> current;
323  EXPECT_TRUE(storage->loadInstalledVersions("primary", &current, nullptr));
324  EXPECT_TRUE(!!current);
325  EXPECT_EQ(current->filename(), "update.bin");
326  EXPECT_EQ(current->sha256Hash(), "2561");
327  EXPECT_EQ(current->hashes(), hashes);
328  EXPECT_EQ(current->ecus(), primary_ecu);
329  EXPECT_EQ(current->correlation_id(), "corrid");
330  EXPECT_EQ(current->length(), 1);
331  EXPECT_EQ(current->custom_data()["foo"], "bar");
332  EXPECT_EQ(current->custom_data()["version"], 42);
333  }
334 
335  // Set t2 as a pending version
336  Uptane::Target t2{"update2.bin", primary_ecu, {Uptane::Hash{Uptane::Hash::Type::kSha256, "2562"}}, 2};
337  storage->savePrimaryInstalledVersion(t2, InstalledVersionUpdateMode::kPending);
338 
339  {
340  boost::optional<Uptane::Target> pending;
341  EXPECT_TRUE(storage->loadInstalledVersions("primary", nullptr, &pending));
342  EXPECT_TRUE(!!pending);
343  EXPECT_EQ(pending->filename(), "update2.bin");
344  }
345 
346  // Set t3 as the new pending
347  Uptane::Target t3{"update3.bin", primary_ecu, {Uptane::Hash{Uptane::Hash::Type::kSha256, "2563"}}, 3};
348  storage->savePrimaryInstalledVersion(t3, InstalledVersionUpdateMode::kPending);
349 
350  {
351  boost::optional<Uptane::Target> pending;
352  EXPECT_TRUE(storage->loadInstalledVersions("primary", nullptr, &pending));
353  EXPECT_TRUE(!!pending);
354  EXPECT_EQ(pending->filename(), "update3.bin");
355  }
356 
357  // Set t3 as current: should replace the pending flag but not create a new
358  // version
359  storage->savePrimaryInstalledVersion(t3, InstalledVersionUpdateMode::kCurrent);
360  {
361  boost::optional<Uptane::Target> current;
362  boost::optional<Uptane::Target> pending;
363  EXPECT_TRUE(storage->loadInstalledVersions("primary", &current, &pending));
364  EXPECT_TRUE(!!current);
365  EXPECT_EQ(current->filename(), "update3.bin");
366  EXPECT_FALSE(!!pending);
367 
368  std::vector<Uptane::Target> log;
369  storage->loadInstallationLog("primary", &log, true);
370  EXPECT_EQ(log.size(), 2);
371  EXPECT_EQ(log.back().filename(), "update3.bin");
372  }
373 
374  // Set t1 as current: the log should have grown even though we rolled back
375  {
376  storage->savePrimaryInstalledVersion(t1, InstalledVersionUpdateMode::kCurrent);
377  std::vector<Uptane::Target> log;
378  storage->loadInstallationLog("primary", &log, true);
379  EXPECT_EQ(log.size(), 3);
380  EXPECT_EQ(log.back().filename(), "update.bin");
381  }
382 
383  // Set t2 as the new pending and t3 as current afterwards: the pending flag
384  // should disappear
385  storage->savePrimaryInstalledVersion(t2, InstalledVersionUpdateMode::kPending);
386  storage->savePrimaryInstalledVersion(t3, InstalledVersionUpdateMode::kCurrent);
387 
388  {
389  boost::optional<Uptane::Target> current;
390  boost::optional<Uptane::Target> pending;
391  EXPECT_TRUE(storage->loadInstalledVersions("primary", &current, &pending));
392  EXPECT_TRUE(!!current);
393  EXPECT_EQ(current->filename(), "update3.bin");
394  EXPECT_FALSE(!!pending);
395 
396  std::vector<Uptane::Target> log;
397  storage->loadInstallationLog("primary", &log, true);
398  EXPECT_EQ(log.size(), 4);
399  EXPECT_EQ(log.back().filename(), "update3.bin");
400  EXPECT_EQ(log[0].custom_data()["foo"], "bar");
401  }
402 
403  // Add a secondary installed version
404  Uptane::EcuMap secondary_ecu{{Uptane::EcuSerial("secondary1"), Uptane::HardwareIdentifier("secondary_hw")}};
405  Uptane::Target tsec{"secondary.bin", secondary_ecu, {Uptane::Hash{Uptane::Hash::Type::kSha256, "256s"}}, 4};
406  storage->saveInstalledVersion("secondary_1", tsec, InstalledVersionUpdateMode::kCurrent);
407 
408  {
409  EXPECT_TRUE(storage->loadInstalledVersions("primary", nullptr, nullptr));
410  EXPECT_TRUE(storage->loadInstalledVersions("secondary_1", nullptr, nullptr));
411 
412  std::vector<Uptane::Target> log;
413  storage->loadInstallationLog("secondary_1", &log, true);
414  EXPECT_EQ(log.size(), 1);
415  EXPECT_EQ(log.back().filename(), "secondary.bin");
416  }
417 }
418 
419 /*
420  * Load and store an ecu installation result in an SQL database.
421  * Load and store a device installation result in an SQL database.
422  */
423 TEST(storage, load_store_installation_results) {
424  TemporaryDirectory temp_dir;
425  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
426 
427  EcuSerials serials{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")},
428  {Uptane::EcuSerial("secondary_1"), Uptane::HardwareIdentifier("secondary_hw")},
429  {Uptane::EcuSerial("secondary_2"), Uptane::HardwareIdentifier("secondary_hw")}};
430  storage->storeEcuSerials(serials);
431 
432  storage->saveEcuInstallationResult(Uptane::EcuSerial("secondary_2"), data::InstallationResult());
433  storage->saveEcuInstallationResult(Uptane::EcuSerial("primary"), data::InstallationResult());
434  storage->saveEcuInstallationResult(Uptane::EcuSerial("primary"),
436 
437  std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> res;
438  EXPECT_TRUE(storage->loadEcuInstallationResults(&res));
439  EXPECT_EQ(res.size(), 2);
440  EXPECT_EQ(res.at(0).first.ToString(), "primary");
441  EXPECT_EQ(res.at(0).second.result_code.num_code, data::ResultCode::Numeric::kGeneralError);
442  EXPECT_EQ(res.at(1).first.ToString(), "secondary_2");
443  EXPECT_EQ(res.at(1).second.result_code.num_code, data::ResultCode::Numeric::kOk);
444 
445  storage->storeDeviceInstallationResult(data::InstallationResult(data::ResultCode::Numeric::kGeneralError, ""), "raw",
446  "corrid");
447 
448  data::InstallationResult dev_res;
449  std::string report;
450  std::string correlation_id;
451  EXPECT_TRUE(storage->loadDeviceInstallationResult(&dev_res, &report, &correlation_id));
452  EXPECT_EQ(dev_res.result_code.num_code, data::ResultCode::Numeric::kGeneralError);
453  EXPECT_EQ(report, "raw");
454  EXPECT_EQ(correlation_id, "corrid");
455 
456  storage->clearInstallationResults();
457  res.clear();
458  EXPECT_FALSE(storage->loadEcuInstallationResults(&res));
459  EXPECT_EQ(res.size(), 0);
460  EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_res, &report, &correlation_id));
461 }
462 
463 /* Load and store targets. */
464 TEST(storage, store_target) {
465  TemporaryDirectory temp_dir;
466  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
467 
468  Json::Value target_json;
469  target_json["hashes"]["sha256"] = "hash";
470  target_json["length"] = 2;
471  Uptane::Target target("some.deb", target_json);
472 
473  // write
474  {
475  std::unique_ptr<StorageTargetWHandle> fhandle = storage->allocateTargetFile(false, target);
476  const uint8_t wb[] = "ab";
477  fhandle->wfeed(wb, 1);
478  fhandle->wfeed(wb + 1, 1);
479  fhandle->wcommit();
480  }
481 
482  // read
483  {
484  std::unique_ptr<StorageTargetRHandle> rhandle = storage->openTargetFile(target);
485  uint8_t rb[3] = {0};
486  EXPECT_EQ(rhandle->rsize(), 2);
487  rhandle->rread(rb, 1);
488  rhandle->rread(rb + 1, 1);
489  rhandle->rclose();
490  EXPECT_STREQ(reinterpret_cast<char *>(rb), "ab");
491  }
492 
493  // write again
494  {
495  std::unique_ptr<StorageTargetWHandle> fhandle = storage->allocateTargetFile(false, target);
496  const uint8_t wb[] = "ab";
497  fhandle->wfeed(wb, 1);
498  fhandle->wfeed(wb + 1, 1);
499  fhandle->wcommit();
500  }
501 
502  // delete
503  {
504  storage->removeTargetFile(target.filename());
505  EXPECT_THROW(storage->openTargetFile(target), StorageTargetRHandle::ReadError);
506  EXPECT_THROW(storage->removeTargetFile(target.filename()), std::runtime_error);
507  }
508 
509  // write stream
510  {
511  std::unique_ptr<StorageTargetWHandle> fhandle = storage->allocateTargetFile(false, target);
512  std::stringstream("ab") >> *fhandle;
513  }
514 
515  // read stream
516  {
517  std::stringstream sstr;
518  std::unique_ptr<StorageTargetRHandle> rhandle = storage->openTargetFile(target);
519  sstr << *rhandle;
520  EXPECT_STREQ(sstr.str().c_str(), "ab");
521  }
522 }
523 
524 /*
525  * List targets currently in storage.
526  * Remove a target binary from storage.
527  */
528 TEST(storage, list_remove_targets) {
529  TemporaryDirectory temp_dir;
530  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
531 
532  Json::Value target_json;
533  target_json["hashes"]["sha256"] = "HASH";
534  target_json["length"] = 2;
535  Uptane::Target target("some.deb", target_json);
536 
537  auto tfs = storage->getTargetFiles();
538  EXPECT_EQ(tfs.size(), 0);
539 
540  // write
541  {
542  std::unique_ptr<StorageTargetWHandle> fhandle = storage->allocateTargetFile(false, target);
543  const uint8_t wb[] = "ab";
544  fhandle->wfeed(wb, 1);
545  fhandle->wfeed(wb + 1, 1);
546  fhandle->wcommit();
547  }
548 
549  tfs = storage->getTargetFiles();
550  ASSERT_EQ(tfs.size(), 1);
551 
552  auto tf = tfs.at(0);
553 
554  EXPECT_EQ(tf.filename(), "some.deb");
555  EXPECT_EQ(tf.length(), 2);
556  EXPECT_EQ(tf.hashes().size(), 1);
557  EXPECT_EQ(tf.hashes().at(0), Uptane::Hash(Uptane::Hash::Type::kSha256, "HASH"));
558 
559  // note: implementation specific
560  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "images" / "HASH"));
561 
562  storage->removeTargetFile(tf.filename());
563 
564  tfs = storage->getTargetFiles();
565  EXPECT_EQ(tfs.size(), 0);
566  EXPECT_FALSE(boost::filesystem::exists(temp_dir.Path() / "images" / "HASH"));
567 }
568 
569 TEST(storage, checksum) {
570  TemporaryDirectory temp_dir;
571  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
572 
573  Json::Value target_json1;
574  target_json1["hashes"]["sha256"] = "hash1";
575  target_json1["length"] = 2;
576  Uptane::Target target1("some.deb", target_json1);
577  Json::Value target_json2;
578  target_json2["length"] = 2;
579  target_json2["hashes"]["sha256"] = "hash2";
580  Uptane::Target target2("some.deb", target_json2);
581 
582  // write target1
583  {
584  std::unique_ptr<StorageTargetWHandle> fhandle = storage->allocateTargetFile(false, target1);
585  const uint8_t wb[] = "ab";
586  fhandle->wfeed(wb, 2);
587  fhandle->wcommit();
588  }
589 
590  // read target 1
591  {
592  std::unique_ptr<StorageTargetRHandle> rhandle = storage->openTargetFile(target1);
593  uint8_t rb[3] = {0};
594  EXPECT_EQ(rhandle->rsize(), 2);
595  rhandle->rread(rb, 2);
596  rhandle->rclose();
597  EXPECT_STREQ(reinterpret_cast<char *>(rb), "ab");
598  }
599 
600  // read target 2
601  { EXPECT_THROW(storage->openTargetFile(target2), StorageTargetRHandle::ReadError); }
602 }
603 
604 TEST(storage, partial) {
605  TemporaryDirectory temp_dir;
606  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
607 
608  Json::Value target_json;
609  target_json["hashes"]["sha256"] = "hash1";
610  target_json["length"] = 3;
611  Uptane::Target target("some.deb", target_json);
612 
613  // write partial target
614  {
615  std::unique_ptr<StorageTargetWHandle> fhandle = storage->allocateTargetFile(false, target);
616  const uint8_t wb[] = "a";
617  fhandle->wfeed(wb, 1);
618  fhandle->wcommit();
619  }
620 
621  // read and check partial target
622  {
623  std::unique_ptr<StorageTargetRHandle> rhandle = storage->openTargetFile(target);
624  uint8_t rb[2] = {0};
625  EXPECT_EQ(rhandle->rsize(), 1);
626  EXPECT_TRUE(rhandle->isPartial());
627  rhandle->rread(rb, 1);
628  rhandle->rclose();
629  EXPECT_STREQ(reinterpret_cast<char *>(rb), "a");
630  }
631 
632  // Append without committing, should commit in whandle destructor
633  {
634  std::unique_ptr<StorageTargetWHandle> whandle = storage->openTargetFile(target)->toWriteHandle();
635  const uint8_t wb[] = "b";
636  whandle->wfeed(wb, 1);
637  }
638 
639  // read and check partial target
640  {
641  std::unique_ptr<StorageTargetRHandle> rhandle = storage->openTargetFile(target);
642  uint8_t rb[3] = {0};
643  EXPECT_EQ(rhandle->rsize(), 2);
644  EXPECT_TRUE(rhandle->isPartial());
645  rhandle->rread(rb, 2);
646  rhandle->rclose();
647  EXPECT_STREQ(reinterpret_cast<char *>(rb), "ab");
648  }
649 
650  // Append partial
651  {
652  std::unique_ptr<StorageTargetWHandle> whandle = storage->openTargetFile(target)->toWriteHandle();
653  const uint8_t wb[] = "c";
654  whandle->wfeed(wb, 1);
655  whandle->wcommit();
656  }
657 
658  // Check full target
659  {
660  std::unique_ptr<StorageTargetRHandle> rhandle = storage->openTargetFile(target);
661  EXPECT_EQ(rhandle->rsize(), 3);
662  EXPECT_FALSE(rhandle->isPartial());
663  }
664 }
665 
666 /* Import keys and credentials from file into storage. */
667 TEST(storage, import_data) {
668  TemporaryDirectory temp_dir;
669  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
670  boost::filesystem::create_directories(temp_dir / "import");
671 
672  ImportConfig import_config;
673  import_config.base_path = temp_dir.Path() / "import";
674  import_config.uptane_private_key_path = BasedPath("private");
675  import_config.uptane_public_key_path = BasedPath("public");
676  import_config.tls_cacert_path = BasedPath("ca");
677  import_config.tls_clientcert_path = BasedPath("cert");
678  import_config.tls_pkey_path = BasedPath("pkey");
679 
680  Utils::writeFile(import_config.uptane_private_key_path.get(import_config.base_path).string(),
681  std::string("uptane_private_1"));
682  Utils::writeFile(import_config.uptane_public_key_path.get(import_config.base_path).string(),
683  std::string("uptane_public_1"));
684  Utils::writeFile(import_config.tls_cacert_path.get(import_config.base_path).string(), std::string("tls_cacert_1"));
685  Utils::writeFile(import_config.tls_clientcert_path.get(import_config.base_path).string(), std::string("tls_cert_1"));
686  Utils::writeFile(import_config.tls_pkey_path.get(import_config.base_path).string(), std::string("tls_pkey_1"));
687 
688  // Initially the storage is empty
689  EXPECT_FALSE(storage->loadPrimaryPublic(nullptr));
690  EXPECT_FALSE(storage->loadPrimaryPrivate(nullptr));
691  EXPECT_FALSE(storage->loadTlsCa(nullptr));
692  EXPECT_FALSE(storage->loadTlsCert(nullptr));
693  EXPECT_FALSE(storage->loadTlsPkey(nullptr));
694 
695  storage->importData(import_config);
696 
697  std::string primary_public;
698  std::string primary_private;
699  std::string tls_ca;
700  std::string tls_cert;
701  std::string tls_pkey;
702 
703  // the data has been imported
704  EXPECT_TRUE(storage->loadPrimaryPublic(&primary_public));
705  EXPECT_TRUE(storage->loadPrimaryPrivate(&primary_private));
706  EXPECT_TRUE(storage->loadTlsCa(&tls_ca));
707  EXPECT_TRUE(storage->loadTlsCert(&tls_cert));
708  EXPECT_TRUE(storage->loadTlsPkey(&tls_pkey));
709 
710  EXPECT_EQ(primary_private, "uptane_private_1");
711  EXPECT_EQ(primary_public, "uptane_public_1");
712  EXPECT_EQ(tls_ca, "tls_cacert_1");
713  EXPECT_EQ(tls_cert, "tls_cert_1");
714  EXPECT_EQ(tls_pkey, "tls_pkey_1");
715 
716  Utils::writeFile(import_config.uptane_private_key_path.get(import_config.base_path).string(),
717  std::string("uptane_private_2"));
718  Utils::writeFile(import_config.uptane_public_key_path.get(import_config.base_path).string(),
719  std::string("uptane_public_2"));
720  Utils::writeFile(import_config.tls_cacert_path.get(import_config.base_path).string(), std::string("tls_cacert_2"));
721  Utils::writeFile(import_config.tls_clientcert_path.get(import_config.base_path).string(), std::string("tls_cert_2"));
722  Utils::writeFile(import_config.tls_pkey_path.get(import_config.base_path).string(), std::string("tls_pkey_2"));
723 
724  storage->importData(import_config);
725 
726  EXPECT_TRUE(storage->loadPrimaryPublic(&primary_public));
727  EXPECT_TRUE(storage->loadPrimaryPrivate(&primary_private));
728  EXPECT_TRUE(storage->loadTlsCa(&tls_ca));
729  EXPECT_TRUE(storage->loadTlsCert(&tls_cert));
730  EXPECT_TRUE(storage->loadTlsPkey(&tls_pkey));
731 
732  // only root cert is being updated
733  EXPECT_EQ(primary_private, "uptane_private_1");
734  EXPECT_EQ(primary_public, "uptane_public_1");
735  EXPECT_EQ(tls_ca, "tls_cacert_2");
736  EXPECT_EQ(tls_cert, "tls_cert_1");
737  EXPECT_EQ(tls_pkey, "tls_pkey_1");
738 }
739 
740 #ifndef __NO_MAIN__
741 int main(int argc, char **argv) {
742  ::testing::InitGoogleTest(&argc, argv);
743  logger_init();
744  logger_set_threshold(boost::log::trivial::trace);
745 
746  std::cout << "Running tests for SQLStorage" << std::endl;
747  current_storage_type = StorageType::kSqlite;
748  int res_sql = RUN_ALL_TESTS();
749 
750  return res_sql; // 0 indicates success
751 }
752 #endif
data::ResultCode::Numeric::kGeneralError
Other error.
types.h
data::InstallationResult
Definition: types.h:179
Uptane::Version
Metadata version numbers.
Definition: tuf.h:116
BasedPath
Definition: utils.h:101
StorageConfig
Definition: storage_config.h:15
MisconfiguredEcu
Definition: invstorage.h:28
Uptane::HardwareIdentifier
Definition: tuf.h:143
Uptane::Hash
The hash of a file or TUF metadata.
Definition: tuf.h:209
Uptane::EcuSerial
Definition: tuf.h:174
TemporaryDirectory
Definition: utils.h:82
Uptane::Target
Definition: tuf.h:238
SQLStorage
Definition: sqlstorage.h:18
ImportConfig
Definition: storage_config.h:34
StorageTargetRHandle::ReadError
Definition: invstorage.h:63