Line data Source code
1 : /*
2 : ___________________________________________
3 : | _ ___ _ |
4 : | | | |__ \ | | |
5 : | | |__ ) |__ _ __ _ ___ _ __ | |_ |
6 : | | '_ \ / // _` |/ _` |/ _ \ '_ \| __| | HTTP/2 AGENT FOR MOCK TESTING
7 : | | | | |/ /| (_| | (_| | __/ | | | |_ | Version 0.0.z
8 : | |_| |_|____\__,_|\__, |\___|_| |_|\__| | https://github.com/testillano/h2agent
9 : | __/ | |
10 : | |___/ |
11 : |___________________________________________|
12 :
13 : Licensed under the MIT License <http://opensource.org/licenses/MIT>.
14 : SPDX-License-Identifier: MIT
15 : Copyright (c) 2021 Eduardo Ramos
16 :
17 : Permission is hereby granted, free of charge, to any person obtaining a copy
18 : of this software and associated documentation files (the "Software"), to deal
19 : in the Software without restriction, including without limitation the rights
20 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21 : copies of the Software, and to permit persons to whom the Software is
22 : furnished to do so, subject to the following conditions:
23 :
24 : The above copyright notice and this permission notice shall be included in all
25 : copies or substantial portions of the Software.
26 :
27 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 : SOFTWARE.
34 : */
35 :
36 : #include <string>
37 : #include <algorithm>
38 :
39 : #include <ert/tracing/Logger.hpp>
40 :
41 : #include <MockServerData.hpp>
42 :
43 :
44 : namespace h2agent
45 : {
46 : namespace model
47 : {
48 :
49 258 : void MockServerData::loadEvent(const DataKey &dataKey, const std::string &previousState, const std::string &state, const std::chrono::microseconds &receptionTimestampUs, unsigned int responseStatusCode, const nghttp2::asio_http2::header_map &requestHeaders, const nghttp2::asio_http2::header_map &responseHeaders, DataPart &requestBodyDataPart, const std::string &responseBody, std::uint64_t serverSequence, unsigned int responseDelayMs, bool historyEnabled, const std::string &virtualOriginComingFromMethod, const std::string &virtualOriginComingFromUri) {
50 :
51 258 : bool maiden{};
52 258 : auto events = std::static_pointer_cast<MockServerEventsHistory>(getEvents(dataKey, maiden));
53 :
54 258 : events->loadEvent(previousState, state, receptionTimestampUs, responseStatusCode, requestHeaders, responseHeaders, requestBodyDataPart, responseBody, serverSequence, responseDelayMs, historyEnabled, virtualOriginComingFromMethod, virtualOriginComingFromUri);
55 :
56 258 : if (maiden) add(dataKey.getKey(), events); // push the key in the map:
57 :
58 258 : last_loaded_event_ = std::static_pointer_cast<MockServerEvent>(events->getEvent(1, true /* reverse: last */));
59 258 : }
60 :
61 0 : bool MockServerData::removeEventByRecvSeq(const DataKey &dataKey, std::uint64_t recvSeq) {
62 :
63 0 : bool exists{};
64 0 : auto events = std::static_pointer_cast<MockServerEventsHistory>(get(dataKey.getKey(), exists));
65 0 : if (!exists) return false;
66 :
67 0 : bool deleted = events->removeEventByRecvSeq(recvSeq);
68 :
69 : // Cleanup empty map entry:
70 0 : if (deleted && events->size() == 0) {
71 0 : bool aux{};
72 0 : remove(dataKey.getKey(), aux);
73 : }
74 :
75 0 : return deleted;
76 0 : }
77 :
78 0 : std::shared_ptr<MockEvent> MockServerData::getEventByRecvSeq(const DataKey &dataKey, std::uint64_t recvSeq) {
79 :
80 0 : bool exists{};
81 0 : auto events = std::static_pointer_cast<MockServerEventsHistory>(get(dataKey.getKey(), exists));
82 0 : if (!exists) return nullptr;
83 :
84 0 : return events->getEventByRecvSeq(recvSeq);
85 0 : }
86 :
87 4 : std::string MockServerData::getSequence(std::uint64_t fromTimestampUs, std::uint64_t toTimestampUs, const std::string &requestMethod, const std::regex *uriRegex) const {
88 :
89 : struct Entry {
90 : std::uint64_t timestampUs;
91 : std::string direction;
92 : std::string method;
93 : std::string uri;
94 : };
95 4 : std::vector<Entry> entries;
96 :
97 4 : forEach([&](const mock_events_key_t&, const std::shared_ptr<MockEventsHistory> &history) {
98 6 : const auto &key = history->getKey();
99 6 : const std::string &method = key.getMethod();
100 6 : const std::string &uri = key.getUri();
101 :
102 7 : if (!requestMethod.empty() && method != requestMethod) return;
103 4 : if (uriRegex && !std::regex_search(uri, *uriRegex)) return;
104 :
105 3 : read_guard_t guard(history->getMutex());
106 9 : for (const auto &ev : history->getEvents()) {
107 6 : auto serverEv = std::static_pointer_cast<MockServerEvent>(ev);
108 12 : std::uint64_t recTs = serverEv->getJson()["receptionTimestampUs"].get<std::uint64_t>();
109 6 : std::uint64_t sendTs = serverEv->getSendingTimestampUs();
110 :
111 : // Recv entry:
112 6 : if ((!fromTimestampUs || recTs >= fromTimestampUs) && (!toTimestampUs || recTs <= toTimestampUs)) {
113 6 : entries.push_back({recTs, "recv", method, uri});
114 : }
115 : // Send entry:
116 6 : if (sendTs && (!fromTimestampUs || sendTs >= fromTimestampUs) && (!toTimestampUs || sendTs <= toTimestampUs)) {
117 0 : entries.push_back({sendTs, "send", method, uri});
118 : }
119 6 : }
120 21 : });
121 :
122 4 : std::sort(entries.begin(), entries.end(), [](const Entry &a, const Entry &b) {
123 8 : return a.timestampUs < b.timestampUs;
124 : });
125 :
126 4 : nlohmann::json result = nlohmann::json::array();
127 10 : for (const auto &e : entries) {
128 6 : nlohmann::json obj;
129 6 : obj["direction"] = e.direction;
130 6 : obj["method"] = e.method;
131 6 : obj["uri"] = e.uri;
132 6 : obj["timestampUs"] = e.timestampUs;
133 6 : result.push_back(std::move(obj));
134 6 : }
135 :
136 8 : return result.dump();
137 4 : }
138 :
139 : }
140 : }
141 :
|