Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
packagemanagerfake_test.cc
1 #include <gtest/gtest.h>
2 
3 #include <fstream>
4 #include <iostream>
5 #include <memory>
6 #include <string>
7 
8 #include <boost/filesystem.hpp>
9 
10 #include "config/config.h"
11 #include "httpfake.h"
12 #include "package_manager/packagemanagerfake.h"
13 #include "storage/invstorage.h"
14 #include "uptane/tuf.h"
15 #include "utilities/types.h"
16 #include "utilities/utils.h"
17 
18 /*
19  * Verify a stored target.
20  * Verify that a target is unavailable.
21  * Reject a target whose hash does not match the metadata.
22  * Reject an oversized target.
23  * Reject an incomplete target.
24  */
25 TEST(PackageManagerFake, Verify) {
26  TemporaryDirectory temp_dir;
27  Config config;
28  config.pacman.type = PACKAGE_MANAGER_NONE;
29  config.storage.path = temp_dir.Path();
30  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
31 
32  Uptane::EcuMap primary_ecu{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")}};
33  const int length = 4;
34  uint8_t content[length];
35  memcpy(content, "good", length);
36  MultiPartSHA256Hasher hasher;
37  hasher.update(content, length);
38  const std::string hash = hasher.getHexDigest();
39  Uptane::Target target("some-pkg", primary_ecu, {Uptane::Hash(Uptane::Hash::Type::kSha256, hash)}, length, "");
40 
41  PackageManagerFake fakepm(config.pacman, config.bootloader, storage, nullptr);
42  // Target is not yet available.
43  EXPECT_EQ(fakepm.verifyTarget(target), TargetStatus::kNotFound);
44 
45  // Target has a bad hash.
46  auto whandle = storage->allocateTargetFile(target);
47  uint8_t content_bad[length + 1];
48  memset(content_bad, 0, length + 1);
49  EXPECT_EQ(whandle->wfeed(content_bad, length), length);
50  whandle->wcommit();
51  EXPECT_EQ(fakepm.verifyTarget(target), TargetStatus::kHashMismatch);
52 
53  // Target is oversized.
54  whandle = storage->allocateTargetFile(target);
55  EXPECT_EQ(whandle->wfeed(content_bad, length + 1), length + 1);
56  whandle->wcommit();
57  EXPECT_EQ(fakepm.verifyTarget(target), TargetStatus::kOversized);
58 
59  // Target is incomplete.
60  whandle = storage->allocateTargetFile(target);
61  EXPECT_EQ(whandle->wfeed(content, length - 1), length - 1);
62  whandle->wcommit();
63  EXPECT_EQ(fakepm.verifyTarget(target), TargetStatus::kIncomplete);
64 
65  // Target is good.
66  whandle = storage->allocateTargetFile(target);
67  EXPECT_EQ(whandle->wfeed(content, length), length);
68  whandle->wcommit();
69  EXPECT_EQ(fakepm.verifyTarget(target), TargetStatus::kGood);
70 }
71 
72 TEST(PackageManagerFake, FinalizeAfterReboot) {
73  TemporaryDirectory temp_dir;
74  Config config;
75  config.pacman.type = PACKAGE_MANAGER_NONE;
76  config.pacman.fake_need_reboot = true;
77  config.bootloader.reboot_sentinel_dir = temp_dir.Path();
78  config.storage.path = temp_dir.Path();
79  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
80  std::shared_ptr<Bootloader> bootloader = std::make_shared<Bootloader>(config.bootloader, *storage);
81 
82  PackageManagerFake fakepm(config.pacman, config.bootloader, storage, nullptr);
83 
84  Uptane::EcuMap primary_ecu;
85  Uptane::Target target("pkg", primary_ecu, {Uptane::Hash(Uptane::Hash::Type::kSha256, "hash")}, 1, "");
86  auto result = fakepm.install(target);
87  EXPECT_EQ(result.result_code, data::ResultCode::Numeric::kNeedCompletion);
88  storage->savePrimaryInstalledVersion(target, InstalledVersionUpdateMode::kPending);
89 
90  fakepm.completeInstall();
91 
92  result = fakepm.finalizeInstall(target);
93  EXPECT_EQ(result.result_code, data::ResultCode::Numeric::kOk);
94 }
95 
96 #ifdef FIU_ENABLE
97 
98 #include "utilities/fault_injection.h"
99 
100 TEST(PackageManagerFake, DownloadFailureInjection) {
101  TemporaryDirectory temp_dir;
102  Config config;
103  config.pacman.type = PACKAGE_MANAGER_NONE;
104  config.storage.path = temp_dir.Path();
105  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
106  auto http = std::make_shared<HttpFake>(temp_dir.Path());
107  Uptane::Fetcher uptane_fetcher(config, http);
108  KeyManager keys(storage, config.keymanagerConfig());
109 
110  PackageManagerFake fakepm(config.pacman, config.bootloader, storage, http);
111 
112  fault_injection_init();
113 
114  // no fault
115  Uptane::EcuMap primary_ecu{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")}};
116  Uptane::Target target("pkg", primary_ecu, {Uptane::Hash(Uptane::Hash::Type::kSha256, "hash")}, 0, "");
117  EXPECT_TRUE(fakepm.fetchTarget(target, uptane_fetcher, keys, nullptr, nullptr));
118 
119  // fault
120  fault_injection_enable("fake_package_download", 1, "", 0);
121  EXPECT_FALSE(fakepm.fetchTarget(target, uptane_fetcher, keys, nullptr, nullptr));
122  fault_injection_disable("fake_package_download");
123 
124  // fault with custom data (through pid file). Unfortunately no easy way to
125  // test the custom emssage.
126  fault_injection_enable("fake_package_download", 1, "RANDOM_DOWNLOAD_CAUSE", 0);
127  EXPECT_FALSE(fakepm.fetchTarget(target, uptane_fetcher, keys, nullptr, nullptr));
128  fault_injection_disable("fake_package_download");
129 }
130 
131 TEST(PackageManagerFake, InstallFailureInjection) {
132  TemporaryDirectory temp_dir;
133  Config config;
134  config.pacman.type = PACKAGE_MANAGER_NONE;
135  config.storage.path = temp_dir.Path();
136  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
137 
138  PackageManagerFake fakepm(config.pacman, config.bootloader, storage, nullptr);
139 
140  fault_injection_init();
141 
142  // no fault
143  Uptane::EcuMap primary_ecu{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")}};
144  Uptane::Target target("pkg", primary_ecu, {Uptane::Hash(Uptane::Hash::Type::kSha256, "hash")}, 1, "");
145  auto result = fakepm.install(target);
146  EXPECT_EQ(result.result_code, data::ResultCode::Numeric::kOk);
147 
148  // fault
149  fault_injection_enable("fake_package_install", 1, "", 0);
150  result = fakepm.install(target);
151  EXPECT_EQ(result.result_code, data::ResultCode::Numeric::kInstallFailed);
152  fault_injection_disable("fake_package_install");
153 
154  // fault with custom data (through pid file)
155  fault_injection_enable("fake_package_install", 1, "RANDOM_INSTALL_CAUSE", 0);
156  result = fakepm.install(target);
157  EXPECT_EQ(result.result_code, data::ResultCode(data::ResultCode::Numeric::kInstallFailed, "RANDOM_INSTALL_CAUSE"));
158  fault_injection_disable("fake_package_install");
159 }
160 
161 #endif // FIU_ENABLE
162 
163 #ifndef __NO_MAIN__
164 int main(int argc, char **argv) {
165  ::testing::InitGoogleTest(&argc, argv);
166 
167  return RUN_ALL_TESTS();
168 }
169 #endif
Uptane::Fetcher
Definition: fetcher.h:33
data::ResultCode
Definition: types.h:125
KeyManager
Definition: keymanager.h:13
types.h
MultiPartSHA256Hasher
Definition: crypto.h:83
Uptane::HardwareIdentifier
Definition: tuf.h:143
Uptane::Hash
The hash of a file or TUF metadata.
Definition: tuf.h:209
Config
Configuration object for an aktualizr instance running on a primary ECU.
Definition: config.h:74
Uptane::EcuSerial
Definition: tuf.h:174
PackageManagerFake
Definition: packagemanagerfake.h:9
TemporaryDirectory
Definition: utils.h:82
result
Results of libaktualizr API calls.
Definition: results.h:13
Uptane::Target
Definition: tuf.h:238
data::ResultCode::Numeric::kInstallFailed
Package installation failed.