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