Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
reportqueue_test.cc
1 #include <gtest/gtest.h>
2 
3 #include <unistd.h>
4 #include <future>
5 #include <memory>
6 #include <string>
7 
8 #include <json/json.h>
9 
10 #include "config/config.h"
11 #include "httpfake.h"
12 #include "reportqueue.h"
13 #include "utilities/types.h" // TimeStamp
14 #include "utilities/utils.h"
15 
16 class HttpFakeRq : public HttpFake {
17  public:
18  HttpFakeRq(const boost::filesystem::path &test_dir_in, size_t expected_events)
19  : HttpFake(test_dir_in, ""), expected_events_(expected_events) {}
20 
21  HttpResponse handle_event(const std::string &url, const Json::Value &data) override {
22  (void)data;
23  if (url == "reportqueue/SingleEvent/events") {
24  EXPECT_EQ(data[0]["eventType"]["id"], "EcuDownloadCompleted");
25  EXPECT_EQ(data[0]["event"]["ecu"], "SingleEvent");
26  ++events_seen;
27  if (events_seen == expected_events_) {
28  expected_events_received.set_value(true);
29  }
30  return HttpResponse("", 200, CURLE_OK, "");
31  } else if (url.find("reportqueue/MultipleEvents") == 0) {
32  for (int i = 0; i < static_cast<int>(data.size()); ++i) {
33  EXPECT_EQ(data[i]["eventType"]["id"], "EcuDownloadCompleted");
34  EXPECT_EQ(data[i]["event"]["ecu"], "MultipleEvents" + std::to_string(events_seen++));
35  }
36  if (events_seen == expected_events_) {
37  expected_events_received.set_value(true);
38  }
39  return HttpResponse("", 200, CURLE_OK, "");
40  } else if (url.find("reportqueue/FailureRecovery") == 0) {
41  if (data.size() < 10) {
42  return HttpResponse("", 400, CURLE_OK, "");
43  } else {
44  for (int i = 0; i < static_cast<int>(data.size()); ++i) {
45  EXPECT_EQ(data[i]["eventType"]["id"], "EcuDownloadCompleted");
46  EXPECT_EQ(data[i]["event"]["ecu"], "FailureRecovery" + std::to_string(i));
47  }
48  events_seen = data.size();
49  if (events_seen == expected_events_) {
50  expected_events_received.set_value(true);
51  }
52  return HttpResponse("", 200, CURLE_OK, "");
53  }
54  }
55  LOG_ERROR << "Unexpected event: " << data;
56  return HttpResponse("", 400, CURLE_OK, "");
57  }
58 
59  size_t events_seen{0};
60  size_t expected_events_;
61  std::promise<bool> expected_events_received{};
62 };
63 
64 /* Test one event. */
65 TEST(ReportQueue, SingleEvent) {
66  TemporaryDirectory temp_dir;
67  Config config;
68  config.storage.path = temp_dir.Path();
69  config.tls.server = "reportqueue/SingleEvent";
70 
71  size_t num_events = 1;
72  auto http = std::make_shared<HttpFakeRq>(temp_dir.Path(), num_events);
73  ReportQueue report_queue(config, http);
74 
75  report_queue.enqueue(std_::make_unique<EcuDownloadCompletedReport>(Uptane::EcuSerial("SingleEvent"), "", true));
76 
77  // Wait at most 30 seconds for the message to get processed.
78  http->expected_events_received.get_future().wait_for(std::chrono::seconds(20));
79  EXPECT_EQ(http->events_seen, num_events);
80 }
81 
82 /* Test ten events. */
83 TEST(ReportQueue, MultipleEvents) {
84  TemporaryDirectory temp_dir;
85  Config config;
86  config.storage.path = temp_dir.Path();
87  config.tls.server = "reportqueue/MultipleEvents";
88 
89  size_t num_events = 10;
90  auto http = std::make_shared<HttpFakeRq>(temp_dir.Path(), num_events);
91  ReportQueue report_queue(config, http);
92 
93  for (int i = 0; i < 10; ++i) {
94  report_queue.enqueue(std_::make_unique<EcuDownloadCompletedReport>(
95  Uptane::EcuSerial("MultipleEvents" + std::to_string(i)), "", true));
96  }
97 
98  // Wait at most 30 seconds for the messages to get processed.
99  http->expected_events_received.get_future().wait_for(std::chrono::seconds(20));
100  EXPECT_EQ(http->events_seen, num_events);
101 }
102 
103 /* Test ten events, but the "server" returns an error the first nine times. The
104  * tenth time should succeed with an array of all ten events. */
105 TEST(ReportQueue, FailureRecovery) {
106  TemporaryDirectory temp_dir;
107  Config config;
108  config.storage.path = temp_dir.Path();
109  config.tls.server = "reportqueue/FailureRecovery";
110 
111  size_t num_events = 10;
112  auto http = std::make_shared<HttpFakeRq>(temp_dir.Path(), num_events);
113  ReportQueue report_queue(config, http);
114 
115  for (int i = 0; i < 10; ++i) {
116  report_queue.enqueue(std_::make_unique<EcuDownloadCompletedReport>(
117  Uptane::EcuSerial("FailureRecovery" + std::to_string(i)), "", true));
118  }
119 
120  // Wait at most 30 seconds for the messages to get processed.
121  http->expected_events_received.get_future().wait_for(std::chrono::seconds(20));
122  EXPECT_EQ(http->events_seen, num_events);
123 }
124 
125 #ifndef __NO_MAIN__
126 int main(int argc, char **argv) {
127  ::testing::InitGoogleTest(&argc, argv);
128  logger_set_threshold(boost::log::trivial::trace);
129  return RUN_ALL_TESTS();
130 }
131 #endif
HttpFakeRq
Definition: reportqueue_test.cc:16
HttpFake
Definition: httpfake.h:22
types.h
data
General data structures.
Definition: types.cc:54
HttpResponse
Definition: httpinterface.h:17
Config
Configuration object for an aktualizr instance running on a primary ECU.
Definition: config.h:74
Uptane::EcuSerial
Definition: tuf.h:174
TemporaryDirectory
Definition: utils.h:82
ReportQueue
Definition: reportqueue.h:85