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 = PackageManager::kNone;
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(false, 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(false, 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(false, 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(false, 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 = PackageManager::kNone;
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  result = fakepm.finalizeInstall(target);
91  EXPECT_EQ(result.result_code, data::ResultCode::Numeric::kOk);
92 }
93 
94 #ifdef FIU_ENABLE
95 
96 #include "utilities/fault_injection.h"
97 
98 TEST(PackageManagerFake, DownloadFailureInjection) {
99  TemporaryDirectory temp_dir;
100  Config config;
101  config.pacman.type = PackageManager::kNone;
102  config.storage.path = temp_dir.Path();
103  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
104  auto http = std::make_shared<HttpFake>(temp_dir.Path());
105  Uptane::Fetcher uptane_fetcher(config, http);
106  KeyManager keys(storage, config.keymanagerConfig());
107 
108  PackageManagerFake fakepm(config.pacman, config.bootloader, storage, http);
109 
110  fault_injection_init();
111 
112  // no fault
113  Uptane::EcuMap primary_ecu{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")}};
114  Uptane::Target target("pkg", primary_ecu, {Uptane::Hash(Uptane::Hash::Type::kSha256, "hash")}, 0, "");
115  EXPECT_TRUE(fakepm.fetchTarget(target, uptane_fetcher, keys, nullptr, nullptr));
116 
117  // fault
118  fault_injection_enable("fake_package_download", 1, "", 0);
119  EXPECT_FALSE(fakepm.fetchTarget(target, uptane_fetcher, keys, nullptr, nullptr));
120  fault_injection_disable("fake_package_download");
121 
122  // fault with custom data (through pid file). Unfortunately no easy way to
123  // test the custom emssage.
124  fault_injection_enable("fake_package_download", 1, "RANDOM_DOWNLOAD_CAUSE", 0);
125  EXPECT_FALSE(fakepm.fetchTarget(target, uptane_fetcher, keys, nullptr, nullptr));
126  fault_injection_disable("fake_package_download");
127 }
128 
129 TEST(PackageManagerFake, InstallFailureInjection) {
130  TemporaryDirectory temp_dir;
131  Config config;
132  config.pacman.type = PackageManager::kNone;
133  config.storage.path = temp_dir.Path();
134  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
135 
136  PackageManagerFake fakepm(config.pacman, config.bootloader, storage, nullptr);
137 
138  fault_injection_init();
139 
140  // no fault
141  Uptane::EcuMap primary_ecu{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")}};
142  Uptane::Target target("pkg", primary_ecu, {Uptane::Hash(Uptane::Hash::Type::kSha256, "hash")}, 1, "");
143  auto result = fakepm.install(target);
144  EXPECT_EQ(result.result_code, data::ResultCode::Numeric::kOk);
145 
146  // fault
147  fault_injection_enable("fake_package_install", 1, "", 0);
148  result = fakepm.install(target);
149  EXPECT_EQ(result.result_code, data::ResultCode::Numeric::kInstallFailed);
150  fault_injection_disable("fake_package_install");
151 
152  // fault with custom data (through pid file)
153  fault_injection_enable("fake_package_install", 1, "RANDOM_INSTALL_CAUSE", 0);
154  result = fakepm.install(target);
155  EXPECT_EQ(result.result_code, data::ResultCode(data::ResultCode::Numeric::kInstallFailed, "RANDOM_INSTALL_CAUSE"));
156  fault_injection_disable("fake_package_install");
157 }
158 
159 #endif // FIU_ENABLE
160 
161 #ifndef __NO_MAIN__
162 int main(int argc, char **argv) {
163  ::testing::InitGoogleTest(&argc, argv);
164 
165  return RUN_ALL_TESTS();
166 }
167 #endif
Uptane::Fetcher
Definition: fetcher.h:33
data::ResultCode
Definition: types.h:122
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:73
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.