1 //--------------------------------------------------------------------------
2 // Copyright (C) 2016-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation. You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 //--------------------------------------------------------------------------
18
19 // http_transaction_test.cc author Tom Peters <thopeter@cisco.com>
20 // unit test main
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "service_inspectors/http_inspect/http_common.h"
27 #include "service_inspectors/http_inspect/http_enum.h"
28 #include "service_inspectors/http_inspect/http_flow_data.h"
29 #include "service_inspectors/http_inspect/http_module.h"
30 #include "service_inspectors/http_inspect/http_transaction.h"
31 #include "service_inspectors/http2_inspect/http2_flow_data.h"
32
33 #include <CppUTest/CommandLineTestRunner.h>
34 #include <CppUTest/TestHarness.h>
35 #include <CppUTestExt/MockSupport.h>
36
37 using namespace snort;
38 using namespace HttpCommon;
39 using namespace HttpEnums;
40
41 namespace snort
42 {
43 // Stubs whose sole purpose is to make the test code link
44 unsigned FlowData::flow_data_id = 0;
FlowData(unsigned,Inspector *)45 FlowData::FlowData(unsigned, Inspector*) {}
46 FlowData::~FlowData() = default;
queue_event(unsigned int,unsigned int)47 int DetectionEngine::queue_event(unsigned int, unsigned int) { return 0; }
File_Decomp_StopFree(fd_session_t *)48 fd_status_t File_Decomp_StopFree(fd_session_t*) { return File_Decomp_OK; }
str_to_hash(const uint8_t *,size_t)49 uint32_t str_to_hash(const uint8_t *, size_t) { return 0; }
get_flow_data(uint32_t) const50 FlowData* Flow::get_flow_data(uint32_t) const { return nullptr; }
51 }
52
53 unsigned Http2FlowData::inspector_id = 0;
get_processing_stream_id() const54 uint32_t Http2FlowData::get_processing_stream_id() const { return 0; }
55
56 THREAD_LOCAL PegCount HttpModule::peg_counts[PEG_COUNT_MAX] = { };
57
58 class HttpUnitTestSetup
59 {
60 public:
get_section_type(HttpFlowData * flow_data)61 static SectionType* get_section_type(HttpFlowData* flow_data)
62 { assert(flow_data!=nullptr); return flow_data->section_type; }
get_type_expected(HttpFlowData * flow_data)63 static SectionType* get_type_expected(HttpFlowData* flow_data)
64 { assert(flow_data!=nullptr); return flow_data->type_expected; }
65 };
66
TEST_GROUP(http_transaction_test)67 TEST_GROUP(http_transaction_test)
68 {
69 HttpFlowData* const flow_data = new HttpFlowData(nullptr);
70 SectionType* const section_type = HttpUnitTestSetup::get_section_type(flow_data);
71 SectionType* const type_expected = HttpUnitTestSetup::get_type_expected(flow_data);
72
73 void teardown() override
74 {
75 delete flow_data;
76 }
77 };
78
TEST(http_transaction_test,simple_transaction)79 TEST(http_transaction_test, simple_transaction)
80 {
81 // This test is a request message with a chunked body and trailers followed by a similar
82 // response message. No overlap in time.
83 // Request
84 type_expected[SRC_CLIENT] = SEC_REQUEST;
85 section_type[SRC_CLIENT] = SEC_REQUEST;
86 HttpTransaction* trans = HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT);
87 CHECK(trans != nullptr);
88 type_expected[SRC_CLIENT] = SEC_HEADER;
89 section_type[SRC_CLIENT] = SEC_HEADER;
90 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
91 type_expected[SRC_CLIENT] = SEC_BODY_CHUNK;
92 section_type[SRC_CLIENT] = SEC_BODY_CHUNK;
93 for (unsigned k=0; k<100; k++)
94 {
95 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
96 }
97 type_expected[SRC_CLIENT] = SEC_TRAILER;
98 section_type[SRC_CLIENT] = SEC_TRAILER;
99 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
100 type_expected[SRC_CLIENT] = SEC_REQUEST;
101
102 // Response
103 section_type[SRC_SERVER] = SEC_STATUS;
104 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
105 section_type[SRC_SERVER] = SEC_HEADER;
106 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
107 section_type[SRC_SERVER] = SEC_BODY_CHUNK;
108 for (unsigned k=0; k<100; k++)
109 {
110 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
111 }
112 section_type[SRC_SERVER] = SEC_TRAILER;
113 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
114 }
115
TEST(http_transaction_test,orphan_response)116 TEST(http_transaction_test, orphan_response)
117 {
118 // Response message without a request
119 type_expected[SRC_CLIENT] = SEC_REQUEST;
120 section_type[SRC_SERVER] = SEC_STATUS;
121 HttpTransaction* trans = HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER);
122 CHECK(trans != nullptr);
123 section_type[SRC_SERVER] = SEC_HEADER;
124 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
125 section_type[SRC_SERVER] = SEC_BODY_CHUNK;
126 for (unsigned k=0; k<10; k++)
127 {
128 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
129 }
130 section_type[SRC_SERVER] = SEC_TRAILER;
131 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
132 }
133
TEST(http_transaction_test,simple_pipeline)134 TEST(http_transaction_test, simple_pipeline)
135 {
136 // Pipeline with four requests followed by four responses
137 HttpTransaction* trans[4];
138 for (unsigned k=0; k < 4; k++)
139 {
140 type_expected[SRC_CLIENT] = SEC_REQUEST;
141 section_type[SRC_CLIENT] = SEC_REQUEST;
142 trans[k] = HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT);
143 CHECK(trans[k] != nullptr);
144 type_expected[SRC_CLIENT] = SEC_HEADER;
145 section_type[SRC_CLIENT] = SEC_HEADER;
146 CHECK(trans[k] == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
147 for (unsigned j=0; j < k; j++)
148 {
149 CHECK(trans[k] != trans[j]);
150 }
151 }
152 type_expected[SRC_CLIENT] = SEC_REQUEST;
153
154 for (unsigned k=0; k < 4; k++)
155 {
156 section_type[SRC_SERVER] = SEC_STATUS;
157 CHECK(trans[k] == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
158 section_type[SRC_SERVER] = SEC_HEADER;
159 CHECK(trans[k] == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
160 section_type[SRC_SERVER] = SEC_BODY_CL;
161 CHECK(trans[k] == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
162 }
163 }
164
TEST(http_transaction_test,concurrent_request_response)165 TEST(http_transaction_test, concurrent_request_response)
166 {
167 // Response starts before request completes, request completes first
168 type_expected[SRC_CLIENT] = SEC_REQUEST;
169 section_type[SRC_CLIENT] = SEC_REQUEST;
170 HttpTransaction* trans = HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT);
171 CHECK(trans != nullptr);
172 type_expected[SRC_CLIENT] = SEC_HEADER;
173 section_type[SRC_CLIENT] = SEC_HEADER;
174 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
175 type_expected[SRC_CLIENT] = SEC_BODY_CHUNK;
176
177 section_type[SRC_SERVER] = SEC_STATUS;
178 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
179 section_type[SRC_SERVER] = SEC_HEADER;
180 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
181
182 section_type[SRC_CLIENT] = SEC_BODY_CHUNK;
183 for (unsigned k=0; k<4; k++)
184 {
185 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
186 }
187 type_expected[SRC_CLIENT] = SEC_TRAILER;
188 section_type[SRC_CLIENT] = SEC_TRAILER;
189 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
190 type_expected[SRC_CLIENT] = SEC_REQUEST;
191
192 section_type[SRC_SERVER] = SEC_BODY_CHUNK;
193 for (unsigned k=0; k<6; k++)
194 {
195 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
196 }
197 section_type[SRC_SERVER] = SEC_TRAILER;
198 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
199 }
200
TEST(http_transaction_test,pipeline_underflow)201 TEST(http_transaction_test, pipeline_underflow)
202 {
203 // Underflow scenario with request, two responses, request, response
204 type_expected[SRC_CLIENT] = SEC_REQUEST;
205 section_type[SRC_CLIENT] = SEC_REQUEST;
206 HttpTransaction* trans = HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT);
207 CHECK(trans != nullptr);
208 type_expected[SRC_CLIENT] = SEC_HEADER;
209 section_type[SRC_CLIENT] = SEC_HEADER;
210 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
211 type_expected[SRC_CLIENT] = SEC_REQUEST;
212
213 section_type[SRC_SERVER] = SEC_STATUS;
214 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
215 section_type[SRC_SERVER] = SEC_HEADER;
216 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
217
218 section_type[SRC_SERVER] = SEC_STATUS;
219 trans = HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER);
220 CHECK(trans != nullptr);
221 section_type[SRC_SERVER] = SEC_HEADER;
222 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
223
224 section_type[SRC_CLIENT] = SEC_REQUEST;
225 HttpTransaction* trans2 = HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT);
226 CHECK((trans2 != nullptr) && (trans2 != trans));
227 type_expected[SRC_CLIENT] = SEC_HEADER;
228 section_type[SRC_CLIENT] = SEC_HEADER;
229 CHECK(trans2 == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
230 type_expected[SRC_CLIENT] = SEC_REQUEST;
231
232 section_type[SRC_SERVER] = SEC_STATUS;
233 trans = HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER);
234 CHECK((trans != nullptr) && (trans != trans2));
235 section_type[SRC_SERVER] = SEC_HEADER;
236 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
237 }
238
TEST(http_transaction_test,concurrent_request_response_underflow)239 TEST(http_transaction_test, concurrent_request_response_underflow)
240 {
241 // Response starts before request completes, response completes first, second response
242 type_expected[SRC_CLIENT] = SEC_REQUEST;
243 section_type[SRC_CLIENT] = SEC_REQUEST;
244 HttpTransaction* trans = HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT);
245 CHECK(trans != nullptr);
246 type_expected[SRC_CLIENT] = SEC_HEADER;
247 section_type[SRC_CLIENT] = SEC_HEADER;
248 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
249 type_expected[SRC_CLIENT] = SEC_BODY_CHUNK;
250
251 section_type[SRC_SERVER] = SEC_STATUS;
252 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
253 section_type[SRC_SERVER] = SEC_HEADER;
254 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
255 section_type[SRC_SERVER] = SEC_BODY_CHUNK;
256 for (unsigned k=0; k<6; k++)
257 {
258 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
259 }
260 section_type[SRC_SERVER] = SEC_TRAILER;
261 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
262
263 section_type[SRC_CLIENT] = SEC_BODY_CHUNK;
264 for (unsigned k=0; k<4; k++)
265 {
266 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
267 }
268 type_expected[SRC_CLIENT] = SEC_TRAILER;
269 section_type[SRC_CLIENT] = SEC_TRAILER;
270 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
271 type_expected[SRC_CLIENT] = SEC_REQUEST;
272
273 section_type[SRC_SERVER] = SEC_STATUS;
274 HttpTransaction* trans2 = HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER);
275 CHECK((trans2 != nullptr) && (trans2 != trans));
276 section_type[SRC_SERVER] = SEC_HEADER;
277 CHECK(trans2 == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
278 section_type[SRC_SERVER] = SEC_BODY_CHUNK;
279 for (unsigned k=0; k<6; k++)
280 {
281 CHECK(trans2 == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
282 }
283 section_type[SRC_SERVER] = SEC_TRAILER;
284 CHECK(trans2 == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
285 }
286
TEST(http_transaction_test,basic_continue)287 TEST(http_transaction_test, basic_continue)
288 {
289 // Request with interim response and final response
290 // Request headers
291 type_expected[SRC_CLIENT] = SEC_REQUEST;
292 section_type[SRC_CLIENT] = SEC_REQUEST;
293 HttpTransaction* trans = HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT);
294 CHECK(trans != nullptr);
295 type_expected[SRC_CLIENT] = SEC_HEADER;
296 section_type[SRC_CLIENT] = SEC_HEADER;
297 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
298 type_expected[SRC_CLIENT] = SEC_BODY_CHUNK;
299
300 // Interim response
301 section_type[SRC_SERVER] = SEC_STATUS;
302 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
303 trans->set_one_hundred_response();
304 section_type[SRC_SERVER] = SEC_HEADER;
305 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
306
307 // Request body
308 section_type[SRC_CLIENT] = SEC_BODY_CHUNK;
309 for (unsigned k=0; k<4; k++)
310 {
311 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
312 }
313 type_expected[SRC_CLIENT] = SEC_TRAILER;
314 section_type[SRC_CLIENT] = SEC_TRAILER;
315 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
316 type_expected[SRC_CLIENT] = SEC_REQUEST;
317
318 // Second response
319 section_type[SRC_SERVER] = SEC_STATUS;
320 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
321 section_type[SRC_SERVER] = SEC_HEADER;
322 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
323 section_type[SRC_SERVER] = SEC_BODY_CHUNK;
324 for (unsigned k=0; k<6; k++)
325 {
326 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
327 }
328 section_type[SRC_SERVER] = SEC_TRAILER;
329 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
330 }
331
TEST(http_transaction_test,multiple_continue)332 TEST(http_transaction_test, multiple_continue)
333 {
334 // Request with interim response and final response
335 // Request headers
336 type_expected[SRC_CLIENT] = SEC_REQUEST;
337 section_type[SRC_CLIENT] = SEC_REQUEST;
338 HttpTransaction* trans = HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT);
339 CHECK(trans != nullptr);
340 type_expected[SRC_CLIENT] = SEC_HEADER;
341 section_type[SRC_CLIENT] = SEC_HEADER;
342 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
343 type_expected[SRC_CLIENT] = SEC_BODY_CHUNK;
344
345 // Interim responses
346 for (unsigned k=0; k < 10; k++)
347 {
348 section_type[SRC_SERVER] = SEC_STATUS;
349 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
350 trans->set_one_hundred_response();
351 section_type[SRC_SERVER] = SEC_HEADER;
352 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
353 }
354
355 // Request body
356 section_type[SRC_CLIENT] = SEC_BODY_CHUNK;
357 for (unsigned k=0; k<4; k++)
358 {
359 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
360 }
361 type_expected[SRC_CLIENT] = SEC_TRAILER;
362 section_type[SRC_CLIENT] = SEC_TRAILER;
363 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
364 type_expected[SRC_CLIENT] = SEC_REQUEST;
365
366 // Final response
367 section_type[SRC_SERVER] = SEC_STATUS;
368 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
369 section_type[SRC_SERVER] = SEC_HEADER;
370 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
371 section_type[SRC_SERVER] = SEC_BODY_CHUNK;
372 for (unsigned k=0; k<6; k++)
373 {
374 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
375 }
376 section_type[SRC_SERVER] = SEC_TRAILER;
377 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
378 }
379
TEST(http_transaction_test,multiple_orphan_continue)380 TEST(http_transaction_test, multiple_orphan_continue)
381 {
382 type_expected[SRC_CLIENT] = SEC_REQUEST;
383 // Repeated interim and final response messages without a request
384 for (unsigned k=0; k < 10; k++)
385 {
386 // Interim response
387 section_type[SRC_SERVER] = SEC_STATUS;
388 HttpTransaction* trans = HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER);
389 CHECK(trans != nullptr);
390 trans->set_one_hundred_response();
391 section_type[SRC_SERVER] = SEC_HEADER;
392 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
393 section_type[SRC_SERVER] = SEC_BODY_CHUNK;
394 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
395 section_type[SRC_SERVER] = SEC_TRAILER;
396 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
397
398 // Final response
399 section_type[SRC_SERVER] = SEC_STATUS;
400 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
401 section_type[SRC_SERVER] = SEC_HEADER;
402 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
403 section_type[SRC_SERVER] = SEC_BODY_CHUNK;
404 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
405 section_type[SRC_SERVER] = SEC_TRAILER;
406 CHECK(trans == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
407 }
408 }
409
TEST(http_transaction_test,pipeline_continue_pipeline)410 TEST(http_transaction_test, pipeline_continue_pipeline)
411 {
412 // 3.5 requests in pipeline, 3 responses + continue response, body + 3 requests in pipeline,
413 // final response + 3 responses
414 HttpTransaction* trans[7];
415 // Four requests in pipeline, the final one will be continued later
416 for (unsigned k=0; k < 4; k++)
417 {
418 type_expected[SRC_CLIENT] = SEC_REQUEST;
419 section_type[SRC_CLIENT] = SEC_REQUEST;
420 trans[k] = HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT);
421 CHECK(trans[k] != nullptr);
422 type_expected[SRC_CLIENT] = SEC_HEADER;
423 section_type[SRC_CLIENT] = SEC_HEADER;
424 CHECK(trans[k] == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
425 for (unsigned j=0; j < k; j++)
426 {
427 CHECK(trans[k] != trans[j]);
428 }
429 }
430 type_expected[SRC_CLIENT] = SEC_BODY_CL;
431
432 // Three responses to the pipeline
433 for (unsigned k=0; k < 3; k++)
434 {
435 section_type[SRC_SERVER] = SEC_STATUS;
436 CHECK(trans[k] == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
437 section_type[SRC_SERVER] = SEC_HEADER;
438 CHECK(trans[k] == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
439 section_type[SRC_SERVER] = SEC_BODY_CL;
440 CHECK(trans[k] == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
441 }
442
443 // Interim response to fourth request
444 section_type[SRC_SERVER] = SEC_STATUS;
445 CHECK(trans[3] == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
446 trans[3]->set_one_hundred_response();
447 section_type[SRC_SERVER] = SEC_HEADER;
448 CHECK(trans[3] == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
449
450 // Finish the fourth request
451 section_type[SRC_CLIENT] = SEC_BODY_CL;
452 CHECK(trans[3] == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
453
454 // Requests 5-7 in pipeline
455 for (unsigned k=4; k < 7; k++)
456 {
457 type_expected[SRC_CLIENT] = SEC_REQUEST;
458 section_type[SRC_CLIENT] = SEC_REQUEST;
459 trans[k] = HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT);
460 CHECK(trans[k] != nullptr);
461 type_expected[SRC_CLIENT] = SEC_HEADER;
462 section_type[SRC_CLIENT] = SEC_HEADER;
463 CHECK(trans[k] == HttpTransaction::attach_my_transaction(flow_data, SRC_CLIENT));
464 for (unsigned j=5; j < k; j++)
465 {
466 CHECK(trans[k] != trans[j]);
467 }
468 }
469 type_expected[SRC_CLIENT] = SEC_REQUEST;
470
471 // Final response to 4 and responses to 5-7
472 for (unsigned k=3; k < 7; k++)
473 {
474 section_type[SRC_SERVER] = SEC_STATUS;
475 CHECK(trans[k] == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
476 section_type[SRC_SERVER] = SEC_HEADER;
477 CHECK(trans[k] == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
478 section_type[SRC_SERVER] = SEC_BODY_CL;
479 CHECK(trans[k] == HttpTransaction::attach_my_transaction(flow_data, SRC_SERVER));
480 }
481 }
482
main(int argc,char ** argv)483 int main(int argc, char** argv)
484 {
485 return CommandLineTestRunner::RunAllTests(argc, argv);
486 }
487
488