Aktualizr
C++ SOTA Client
uptane_vector_tests.cc
1 #include <gtest/gtest.h>
2 
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <cstdlib>
6 #include <iostream>
7 #include <memory>
8 #include <string>
9 #include <utility>
10 
11 #include "config/config.h"
12 #include "http/httpclient.h"
13 #include "logging/logging.h"
14 #include "primary/sotauptaneclient.h"
15 #include "storage/invstorage.h"
16 #include "utilities/utils.h"
17 
18 /**
19  * \verify{\tst{49}} Check that aktualizr fails on expired metadata
20  */
21 
22 /**
23  * \verify{\tst{52}} Check that aktualizr fails on bad threshold
24  */
25 
26 // This is a class solely for the purpose of being a FRIEND_TEST to
27 // SotaUptaneClient. The name is carefully constructed for this purpose.
29  private:
30  static bool match_error(const Json::Value& error, const Uptane::Exception& e) {
31  std::cout << "name: " << e.getName() << std::endl;
32  std::cout << "e.what: " << e.what() << std::endl;
33  std::cout << "1: " << error["director"]["update"]["err_msg"].asString() << std::endl;
34  std::cout << "2: " << error["director"]["targets"][e.getName()]["err_msg"].asString() << std::endl;
35  std::cout << "3: " << error["image_repo"]["update"]["err_msg"].asString() << std::endl;
36  std::cout << "4: " << error["image_repo"]["targets"][e.getName()]["err_msg"].asString() << std::endl;
37  if (error["director"]["update"]["err_msg"].asString() == e.what() ||
38  error["director"]["targets"][e.getName()]["err_msg"].asString() == e.what() ||
39  error["image_repo"]["update"]["err_msg"].asString() == e.what() ||
40  error["image_repo"]["targets"][e.getName()]["err_msg"].asString() == e.what()) {
41  return true;
42  }
43  std::cout << "aktualizr failed with unmatched exception " << typeid(e).name() << ": " << e.what() << "\n";
44  return false;
45  }
46 
47  public:
48  static bool run_test(const std::string& test_name, const Json::Value& vector, const std::string& port) {
49  std::cout << "VECTOR: " << vector;
50  TemporaryDirectory temp_dir;
51  Config config;
52  config.provision.primary_ecu_serial = "test_primary_ecu_serial";
53  config.provision.primary_ecu_hardware_id = "test_primary_hardware_id";
54  config.uptane.director_server = "http://127.0.0.1:" + port + "/" + test_name + "/director";
55  config.uptane.repo_server = "http://127.0.0.1:" + port + "/" + test_name + "/image_repo";
56  config.storage.path = temp_dir.Path();
57  config.storage.uptane_metadata_path = BasedPath(port + "/aktualizr_repos");
58  config.pacman.type = PackageManager::kNone;
59  logger_set_threshold(boost::log::trivial::trace);
60 
61  try {
62  auto storage = INvStorage::newStorage(config.storage);
63  Uptane::Manifest uptane_manifest{config, storage};
64  auto uptane_client = SotaUptaneClient::newDefaultClient(config, storage);
65  Uptane::EcuSerial ecu_serial(config.provision.primary_ecu_serial);
66  Uptane::HardwareIdentifier hw_id(config.provision.primary_ecu_hardware_id);
67  uptane_client->hw_ids.insert(std::make_pair(ecu_serial, hw_id));
68  uptane_client->installed_images[ecu_serial] = "test_filename";
69  if (!uptane_client->uptaneIteration()) {
70  throw uptane_client->getLastException();
71  }
72 
73  } catch (const Uptane::Exception& e) {
74  return match_error(vector, e);
75  } catch (const std::exception& e) {
76  std::cout << "aktualizr failed with unrecognized exception " << typeid(e).name() << ": " << e.what() << "\n";
77  return false;
78  }
79 
80  if (vector["director"]["update"]["is_success"].asBool() && vector["image_repo"]["update"]["is_success"].asBool()) {
81  for (Json::ValueConstIterator it = vector["director"]["targets"].begin();
82  it != vector["director"]["targets"].end(); ++it) {
83  if (!(*it)["is_success"].asBool()) {
84  std::cout << "aktualizr did not fail as expected.\n";
85  return false;
86  }
87  }
88  for (Json::ValueConstIterator it = vector["image_repo"]["targets"].begin();
89  it != vector["image_repo"]["targets"].end(); ++it) {
90  if (!(*it)["is_success"].asBool()) {
91  std::cout << "aktualizr did not fail as expected.\n";
92  return false;
93  }
94  }
95 
96  return true;
97  } else {
98  std::cout << "No exceptions happen, but expects ";
99  if (!vector["director"]["update"]["is_success"].asBool()) {
100  std::cout << "exception from director: '" << vector["director"]["update"]["err"]
101  << " with message: " << vector["director"]["update"]["err_msg"] << "\n";
102  } else if (!vector["image_repo"]["update"]["is_success"].asBool()) {
103  std::cout << "exception from image_repo: '" << vector["image_repo"]["update"]["err"]
104  << " with message: " << vector["image_repo"]["update"]["err_msg"] << "\n";
105  }
106 
107  return false;
108  }
109  }
110 };
111 
112 int main(int argc, char* argv[]) {
113  ::testing::InitGoogleTest(&argc, argv);
114  logger_init();
115  logger_set_threshold(boost::log::trivial::trace);
116 
117  if (argc != 2) {
118  std::cerr << "This program is intended to be run from run_vector_tests.sh!\n";
119  return 1;
120  }
121 
122  HttpClient http_client;
123  /* Use ports to distinguish both the server connection and local storage so
124  * that parallel runs of this code don't cause problems that are difficult to
125  * debug. */
126  const std::string port = argv[1];
127  const std::string address = "http://127.0.0.1:" + port + "/";
128  const Json::Value json_vectors = http_client.get(address, HttpInterface::kNoLimit).getJson();
129  int passed = 0;
130  int failed = 0;
131  for (Json::ValueConstIterator it = json_vectors.begin(); it != json_vectors.end(); it++) {
132  std::cout << "Running test vector " << (*it).asString() << "\n";
133  while (true) {
134  HttpResponse response = http_client.post(address + (*it).asString() + "/step", Json::Value());
135  if (response.http_status_code == 204) {
136  break;
137  }
138 
139  bool pass = Uptane_Vector_Test::run_test((*it).asString(), response.getJson(), port);
140  std::cout << "Finished test vector " << (*it).asString() << "\n";
141  if (pass) {
142  passed++;
143  std::cout << "TEST: PASS\n";
144  } else {
145  failed++;
146  std::cout << "TEST: FAIL\n";
147  }
148  }
149  }
150  std::cout << "\n\n\nPASSED TESTS: " << passed << "\n";
151  std::cout << "FAILED TESTS: " << failed << "\n";
152  return failed;
153 }
Configuration object for an aktualizr instance running on a primary ECU.
Definition: config.h:100