return new NHttpInspect(nhttp_mod->get_once_params());
}
-const char* NHttpApi::classic_buffers[] =
+const char* NHttpApi::classic_buffer_names[] =
{
"http_client_body",
"http_cookie",
},
IT_SERVICE,
(uint16_t)PktType::PDU,
- classic_buffers,
+ classic_buffer_names,
"http",
NHttpApi::nhttp_init,
NHttpApi::nhttp_term,
{
public:
static const InspectApi nhttp_api;
- static const char* classic_buffers[];
+ static const char* classic_buffer_names[];
private:
NHttpApi() = delete;
SEC_BODY_OLD };
// Message buffers available to clients
-// This enum must remain synchronized with classic_buffers[]
+// This enum must remain synchronized with NHttpApi::classic_buffer_names[]
enum NHTTP_BUFFER { NHTTP_BUFFER_CLIENT_BODY = 1, NHTTP_BUFFER_COOKIE, NHTTP_BUFFER_HEADER,
NHTTP_BUFFER_METHOD, NHTTP_BUFFER_RAW_COOKIE, NHTTP_BUFFER_RAW_HEADER, NHTTP_BUFFER_RAW_URI,
NHTTP_BUFFER_STAT_CODE, NHTTP_BUFFER_STAT_MSG, NHTTP_BUFFER_URI, NHTTP_BUFFER_VERSION,
NHTTP_BUFFER_TRAILER, NHTTP_BUFFER_RAW_TRAILER, NHTTP_BUFFER_RAW_REQUEST,
NHTTP_BUFFER_RAW_STATUS, NHTTP_BUFFER_MAX };
+// Peg counts
+// This enum must remain synchronized with NHttpModule::peg_names[] in nhttp_tables.cc
+enum PEG_COUNT { PEG_FLOW = 0, PEG_SCAN, PEG_REASSEMBLE, PEG_INSPECT, PEG_REQUEST, PEG_RESPONSE,
+ PEG_GET, PEG_HEAD, PEG_POST, PEG_PUT, PEG_DELETE, PEG_CONNECT, PEG_OPTIONS, PEG_TRACE,
+ PEG_OTHER_METHOD, PEG_REQUEST_BODY, PEG_CHUNKED, PEG_URI_NORM, PEG_URI_PATH, PEG_URI_CODING,
+ PEG_COUNT_MAX };
+
// Result of scanning by splitter
enum ScanResult { SCAN_NOTFOUND, SCAN_FOUND, SCAN_FOUND_PIECE, SCAN_DISCARD, SCAN_DISCARD_PIECE,
SCAN_ABORT, SCAN_END };
INF_URI_PERCENT_UTF8_3B,
INF_URI_PERCENT_UNRESERVED,
INF_URI_PERCENT_UTF8_2B,
- INF_URI_PERCENT_UCODE,
+ INF_NOT_USED_1,
INF_URI_PERCENT_OTHER,
INF_URI_BAD_CHAR,
INF_URI_8BIT_CHAR,
INF_URI_NEED_NORM_HOST,
INF_URI_NEED_NORM_QUERY,
INF_URI_NEED_NORM_FRAGMENT,
- INF_U_ENCODE,
- INF_UNKNOWN_PERCENT,
- INF_DOUBLE_DECODE,
+ INF_URI_U_ENCODE,
+ INF_URI_UNKNOWN_PERCENT,
+ INF_URI_DOUBLE_DECODE,
INF_MULTIPLE_CONTLEN,
INF_BOTH_CL_AND_TE,
INF_BAD_CODE_BODY_HEADER,
}
NHttpTestManager::set_print_amount(params->print_amount);
NHttpTestManager::set_print_hex(params->print_hex);
+ NHttpTestManager::set_show_pegs(params->show_pegs);
#endif
}
NHttpFlowData::nhttp_flow_id);
assert(session_data != nullptr);
+ NHttpModule::increment_peg_counts(PEG_INSPECT);
+
switch (session_data->section_type[source_id])
{
case SEC_REQUEST:
"number of characters to print from a Field" },
{ "print_hex", Parameter::PT_BOOL, nullptr, "false",
"nonprinting characters printed in [HH] format instead of using an asterisk" },
+ { "show_pegs", Parameter::PT_BOOL, nullptr, "true", "display peg counts with test output" },
#endif
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
+THREAD_LOCAL PegCount NHttpModule::peg_counts[PEG_COUNT_MAX] = { 0 };
+
bool NHttpModule::begin(const char*, int, SnortConfig*)
{
delete params;
{
params->print_hex = val.get_bool();
}
+ else if (val.is("show_pegs"))
+ {
+ params->show_pegs = val.get_bool();
+ }
#endif
else
{
bool test_output;
long print_amount;
bool print_hex;
+ bool show_pegs;
#endif
};
return ret_val;
}
+ const PegInfo* get_pegs() const override { return peg_names; }
+ PegCount* get_counts() const override { return peg_counts; }
+ static void increment_peg_counts(NHttpEnums::PEG_COUNT counter)
+ { peg_counts[counter]++; return; }
+
+#ifdef REG_TEST
+ static const PegInfo* get_peg_names() { return peg_names; }
+ static const PegCount* get_peg_counts() { return peg_counts; }
+ static void reset_peg_counts()
+ {
+ for (unsigned k=0; k < NHttpEnums::PEG_COUNT_MAX; peg_counts[k++] = 0);
+ }
+#endif
+
private:
static const Parameter nhttp_params[];
static const RuleMap nhttp_events[];
NHttpParaList* params = nullptr;
+ static const PegInfo peg_names[];
+ static THREAD_LOCAL PegCount peg_counts[];
};
#endif
{
detect_data.print(output, "Detect data");
get_classic_buffer(NHTTP_BUFFER_CLIENT_BODY, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_CLIENT_BODY-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_CLIENT_BODY-1]);
if (g_file_data.len > 0)
{
Field(g_file_data.len, g_file_data.data).print(output, "file_data");
#include "file_api/file_service.h"
#include "file_api/file_flows.h"
+#include "nhttp_module.h"
#include "nhttp_api.h"
#include "nhttp_normalizers.h"
#include "nhttp_msg_request.h"
{
// Chunked body
session_data->type_expected[source_id] = SEC_BODY_CHUNK;
+ NHttpModule::increment_peg_counts(PEG_CHUNKED);
prepare_body();
return;
}
update_depth();
session_data->infractions[source_id].reset();
session_data->events[source_id].reset();
+ if (source_id == SRC_CLIENT)
+ {
+ NHttpModule::increment_peg_counts(PEG_REQUEST_BODY);
+ }
}
void NHttpMsgHeader::setup_file_processing()
NHttpMsgSection::print_section_title(output, "header");
NHttpMsgHeadShared::print_headers(output);
get_classic_buffer(NHTTP_BUFFER_COOKIE, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_COOKIE-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_COOKIE-1]);
get_classic_buffer(NHTTP_BUFFER_HEADER, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_HEADER-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_HEADER-1]);
get_classic_buffer(NHTTP_BUFFER_RAW_COOKIE, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_RAW_COOKIE-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_RAW_COOKIE-1]);
get_classic_buffer(NHTTP_BUFFER_RAW_HEADER, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_RAW_HEADER-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_RAW_HEADER-1]);
NHttpMsgSection::print_section_wrapup(output);
}
#endif
void NHttpMsgRequest::parse_start_line()
{
- // Status line: "HTTP/X.Y KLM <text>" where X, Y, K, L, and M are decimal digits
// Check the version field
- // FIXIT-L An idea would be to move this test into the cutter and abort the scan() instead of
- // allowing it to come here.
if ((start_line.length < 10) || !is_sp_tab[start_line.start[start_line.length-9]] ||
memcmp(start_line.start + start_line.length - 8, "HTTP/", 5))
{
return;
}
+ NHttpModule::increment_peg_counts(PEG_REQUEST);
+
// The splitter guarantees there will be a non-whitespace at octet 1 and a whitespace within
// octets 2-81. The following algorithm uses those assumptions.
method.length = first_space;
method_id = (MethodId)str_to_code(method.start, method.length, method_list);
+ switch (method_id)
+ {
+ case METH_GET: NHttpModule::increment_peg_counts(PEG_GET); break;
+ case METH_HEAD: NHttpModule::increment_peg_counts(PEG_HEAD); break;
+ case METH_POST: NHttpModule::increment_peg_counts(PEG_POST); break;
+ case METH_PUT: NHttpModule::increment_peg_counts(PEG_PUT); break;
+ case METH_DELETE: NHttpModule::increment_peg_counts(PEG_DELETE); break;
+ case METH_CONNECT: NHttpModule::increment_peg_counts(PEG_CONNECT); break;
+ case METH_OPTIONS: NHttpModule::increment_peg_counts(PEG_OPTIONS); break;
+ case METH_TRACE: NHttpModule::increment_peg_counts(PEG_TRACE); break;
+ default: NHttpModule::increment_peg_counts(PEG_OTHER_METHOD); break;
+ }
+
version.start = start_line.start + (start_line.length - 8);
version.length = 8;
derive_version_id();
uri->get_norm_fragment().print(output, "Normalized Fragment");
}
get_classic_buffer(NHTTP_BUFFER_METHOD, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_METHOD-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_METHOD-1]);
get_classic_buffer(NHTTP_BUFFER_RAW_URI, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_RAW_URI-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_RAW_URI-1]);
get_classic_buffer(NHTTP_BUFFER_URI, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_URI-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_URI-1]);
get_classic_buffer(NHTTP_BUFFER_VERSION, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_VERSION-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_VERSION-1]);
get_classic_buffer(NHTTP_BUFFER_RAW_REQUEST, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_RAW_REQUEST-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_RAW_REQUEST-1]);
NHttpMsgSection::print_section_wrapup(output);
}
#include "nhttp_enum.h"
#include "nhttp_transaction.h"
+#include "nhttp_test_manager.h"
#include "nhttp_msg_section.h"
#include "nhttp_msg_request.h"
#include "nhttp_msg_status.h"
fprintf(output, "Infractions: %016" PRIx64 " %016" PRIx64 ", Events: %016" PRIx64 " %016"
PRIx64 ", TCP Close: %s\n\n", infractions.get_raw2(), infractions.get_raw(),
events.get_raw2(), events.get_raw(), tcp_close ? "True" : "False");
+ if (NHttpTestManager::get_show_pegs())
+ {
+ print_peg_counts(output);
+ }
session_data->show(output);
fprintf(output, "\n");
}
+void NHttpMsgSection::print_peg_counts(FILE* output) const
+{
+ const PegInfo* const peg_names = NHttpModule::get_peg_names();
+ const PegCount* const peg_counts = NHttpModule::get_peg_counts();
+
+ fprintf(output, "Peg Counts\n");
+ for (unsigned k = 0; k < PEG_COUNT_MAX; k++)
+ {
+ if (peg_counts[k] > 0)
+ {
+ fprintf(output, "%s: %" PRIu64 "\n", peg_names[k].name, peg_counts[k]);
+ }
+ }
+ fprintf(output, "\n");
+}
+
#endif
#ifdef REG_TEST
void print_section_title(FILE* output, const char* title) const;
void print_section_wrapup(FILE* output) const;
+ void print_peg_counts(FILE* output) const;
#endif
private:
return;
}
+ NHttpModule::increment_peg_counts(PEG_RESPONSE);
+
version.start = start_line.start;
version.length = 8;
derive_version_id();
fprintf(output, "Status Code Num: %d\n", status_code_num);
reason_phrase.print(output, "Reason Phrase");
get_classic_buffer(NHTTP_BUFFER_STAT_CODE, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_STAT_CODE-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_STAT_CODE-1]);
get_classic_buffer(NHTTP_BUFFER_STAT_MSG, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_STAT_MSG-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_STAT_MSG-1]);
get_classic_buffer(NHTTP_BUFFER_VERSION, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_VERSION-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_VERSION-1]);
get_classic_buffer(NHTTP_BUFFER_RAW_STATUS, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_RAW_STATUS-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_RAW_STATUS-1]);
NHttpMsgSection::print_section_wrapup(output);
}
#endif
NHttpMsgSection::print_section_title(output, "trailer");
NHttpMsgHeadShared::print_headers(output);
get_classic_buffer(NHTTP_BUFFER_TRAILER, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_TRAILER-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_TRAILER-1]);
get_classic_buffer(NHTTP_BUFFER_RAW_TRAILER, 0, 0).print(output,
- NHttpApi::classic_buffers[NHTTP_BUFFER_RAW_TRAILER-1]);
+ NHttpApi::classic_buffer_names[NHTTP_BUFFER_RAW_TRAILER-1]);
NHttpMsgSection::print_section_wrapup(output);
}
#endif
return nullptr;
}
+ NHttpModule::increment_peg_counts(PEG_REASSEMBLE);
+
uint8_t*& buffer = session_data->section_buffer[source_id];
const bool is_body = (session_data->section_type[source_id] == SEC_BODY_CHUNK) ||
if (session_data == nullptr)
{
flow->set_application_data(session_data = new NHttpFlowData);
+ NHttpModule::increment_peg_counts(PEG_FLOW);
}
SectionType type = session_data->type_expected[source_id];
assert(!session_data->tcp_close[source_id]);
+ NHttpModule::increment_peg_counts(PEG_SCAN);
+
// Check for 0.9 response message
if ((type == SEC_STATUS) &&
(session_data->expected_msg_num[SRC_SERVER] == session_data->zero_nine_expected))
#include <sys/types.h>
#include "framework/module.h"
+#include "framework/counts.h"
#include "nhttp_enum.h"
#include "nhttp_str_to_code.h"
{ 0, nullptr }
};
+const PegInfo NHttpModule::peg_names[PEG_COUNT_MAX+1] =
+{
+ { "flows", "HTTP connections inspected" },
+ { "scans", "TCP segments scanned looking for HTTP messages" },
+ { "reassembles", "TCP segments combined into HTTP messages" },
+ { "inspections", "total message sections inspected" },
+ { "requests", "HTTP request messages inspected" },
+ { "responses", "HTTP response messages inspected" },
+ { "GET requests", "GET requests inspected" },
+ { "HEAD requests", "HEAD requests inspected" },
+ { "POST requests", "POST requests inspected" },
+ { "PUT requests", "PUT requests inspected" },
+ { "DELETE requests", "DELETE requests inspected" },
+ { "CONNECT requests", "CONNECT requests inspected" },
+ { "OPTIONS requests", "OPTIONS requests inspected" },
+ { "TRACE requests", "TRACE requests inspected" },
+ { "other requests", "other request methods inspected" },
+ { "request bodies", "POST, PUT, and other requests with message bodies" },
+ { "chunked", "chunked message bodies" },
+ { "URI normalizations", "URIs needing to be normalization" },
+ { "URI path", "URIs with path problems" },
+ { "URI coding", "URIs with character coding problems" },
+ { nullptr, nullptr }
+};
+
const int8_t NHttpEnums::as_hex[256] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
#include <assert.h>
#include <stdexcept>
+#include "nhttp_module.h"
#include "nhttp_test_manager.h"
#include "nhttp_test_input.h"
fclose(include_file);
include_file = nullptr;
}
+
+ // Each test needs separate peg counts
+ NHttpModule::reset_peg_counts();
}
// Read from the test data file and present to StreamSplitter. In the process we may need to skip
FILE* NHttpTestManager::test_out = nullptr;
long NHttpTestManager::print_amount = 1200;
bool NHttpTestManager::print_hex = false;
+bool NHttpTestManager::show_pegs = true;
void NHttpTestManager::update_test_number(int64_t new_test_number)
{
static long get_print_amount() { return print_amount; }
static void set_print_hex(bool print_hex_) { print_hex = print_hex_; }
static bool get_print_hex() { return print_hex; }
+ static void set_show_pegs(bool show_pegs_) { show_pegs = show_pegs_; }
+ static bool get_show_pegs() { return show_pegs; }
private:
NHttpTestManager() = delete;
static int64_t test_number;
static long print_amount;
static bool print_hex;
+ static bool show_pegs;
};
#endif
#include <stdio.h>
#include "nhttp_enum.h"
+#include "nhttp_module.h"
#include "nhttp_uri.h"
using namespace NHttpEnums;
if (!((infractions & INF_URI_NEED_NORM_PATH) || (infractions & INF_URI_NEED_NORM_HOST) ||
(infractions & INF_URI_NEED_NORM_QUERY) || (infractions & INF_URI_NEED_NORM_FRAGMENT)))
{
+ // This URI is OK, normalization not required
host_norm = host;
path_norm = path;
query_norm = query;
return;
}
+ NHttpModule::increment_peg_counts(PEG_URI_NORM);
+
// Create a new buffer containing the normalized URI by normalizing each individual piece.
const uint32_t total_length = uri.length + UriNormalizer::URI_NORM_EXPANSION;
uint8_t* const new_buf = new uint8_t[total_length];
current += fragment_norm.length;
}
assert(current - new_buf <= total_length);
+
+ if ((infractions & INF_URI_MULTISLASH) || (infractions & INF_URI_SLASH_DOT) ||
+ (infractions & INF_URI_SLASH_DOT_DOT))
+ {
+ NHttpModule::increment_peg_counts(PEG_URI_PATH);
+ }
+
+ if ((infractions & INF_URI_U_ENCODE) || (infractions & INF_URI_UNKNOWN_PERCENT) ||
+ (infractions & INF_URI_PERCENT_UNRESERVED) || (infractions & INF_URI_PERCENT_UTF8_2B) ||
+ (infractions & INF_URI_PERCENT_UTF8_3B) || (infractions & INF_URI_DOUBLE_DECODE))
+ {
+ NHttpModule::increment_peg_counts(PEG_URI_CODING);
+ }
+
classic_norm.set(current - new_buf, new_buf);
classic_norm_allocated = true;
}
else if (uri_param.percent_u && is_u_encoding(input, k))
{
// %u encoding, this is nonstandard and likely to be malicious
- infractions += INF_U_ENCODE;
+ infractions += INF_URI_U_ENCODE;
events.create_event(EVENT_U_ENCODE);
percent_encoded[length] = true;
const uint8_t byte_val = reduce_to_eight_bits(extract_u_encoding(input, k),
else
{
// don't recognize, pass it through
- infractions += INF_UNKNOWN_PERCENT;
+ infractions += INF_URI_UNKNOWN_PERCENT;
events.create_event(EVENT_UNKNOWN_PERCENT);
double_decoding_needed = true;
out_buf[length++] = '%';
{
if (is_percent_encoding(input, k))
{
- infractions += INF_DOUBLE_DECODE;
+ infractions += INF_URI_DOUBLE_DECODE;
events.create_event(EVENT_DOUBLE_DECODE);
out_buf[length++] = extract_percent_encoding(input, k);
k += 2;
}
else if (uri_param.percent_u && is_u_encoding(input, k))
{
- infractions += INF_DOUBLE_DECODE;
+ infractions += INF_URI_DOUBLE_DECODE;
events.create_event(EVENT_DOUBLE_DECODE);
- infractions += INF_U_ENCODE;
+ infractions += INF_URI_U_ENCODE;
events.create_event(EVENT_U_ENCODE);
out_buf[length++] = reduce_to_eight_bits(extract_u_encoding(input, k), uri_param,
infractions, events);
add_cpputest(nhttp_uri_norm_test nhttp_inspect framework)
add_cpputest(nhttp_normalizers_test nhttp_inspect framework)
+add_cpputest(nhttp_module_test nhttp_inspect framework)
check_PROGRAMS = \
nhttp_uri_norm_test \
-nhttp_normalizers_test
+nhttp_normalizers_test \
+nhttp_module_test
TESTS = $(check_PROGRAMS)
../nhttp_field.o \
@CPPUTEST_LDFLAGS@
+nhttp_module_test_CPPFLAGS = $(AM_CPPFLAGS) @CPPUTEST_CPPFLAGS@
+nhttp_module_test_LDADD = \
+../nhttp_module.o \
+../nhttp_tables.o \
+../nhttp_normalizers.o \
+../nhttp_uri_norm.o \
+../nhttp_field.o \
+../../../framework/module.o \
+@CPPUTEST_LDFLAGS@
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2016 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// nhttp_module_test.cc author Tom Peters <thopeter@cisco.com>
+// unit test main
+
+#include "log/messages.h"
+#include "events/event_queue.h"
+
+#include "service_inspectors/nhttp_inspect/nhttp_module.h"
+#include "service_inspectors/nhttp_inspect/nhttp_test_manager.h"
+#include "service_inspectors/nhttp_inspect/nhttp_str_to_code.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+using namespace NHttpEnums;
+
+// Stubs whose sole purpose is to make the test code link
+void ParseWarning(WarningGroup, const char*, ...) {}
+void ParseError(const char*, ...) {}
+
+void show_stats(PegCount*, const PegInfo*, unsigned, const char*) { }
+void show_stats(PegCount*, const PegInfo*, IndexVec&, const char*, FILE*) { }
+void show_stats(SimpleStats*, const char*) { }
+
+void Value::get_bits(std::bitset<256ul>&) const {}
+int SnortEventqAdd(unsigned int, unsigned int, RuleType) { return 0; }
+
+int32_t str_to_code(const uint8_t*, const int32_t, const StrCode []) { return 0; }
+long NHttpTestManager::print_amount {};
+bool NHttpTestManager::print_hex {};
+
+TEST_GROUP(nhttp_peg_count_test)
+{
+ NHttpModule mod;
+
+ void setup()
+ {
+ PegCount* counts = mod.get_counts();
+ for (unsigned k=0; k < PEG_COUNT_MAX; k++)
+ {
+ CHECK(counts[k] == 0);
+ }
+ }
+
+ void teardown()
+ {
+ PegCount* counts = mod.get_counts();
+ for (unsigned k=0; k < PEG_COUNT_MAX; k++)
+ {
+ counts[k] = 0;
+ }
+ }
+};
+
+TEST(nhttp_peg_count_test, increment)
+{
+ for (unsigned k=0; k < 13; k++)
+ {
+ NHttpModule::increment_peg_counts(PEG_SCAN);
+ }
+ for (unsigned k=0; k < 27816; k++)
+ {
+ NHttpModule::increment_peg_counts(PEG_INSPECT);
+ }
+ PegCount* counts = mod.get_counts();
+ CHECK(counts[PEG_SCAN] == 13);
+ CHECK(counts[PEG_INSPECT] == 27816);
+}
+
+TEST(nhttp_peg_count_test, zero_out)
+{
+ for (unsigned k=0; k < 12; k++)
+ {
+ NHttpModule::increment_peg_counts(PEG_INSPECT);
+ }
+ PegCount* counts = mod.get_counts();
+ CHECK(counts[PEG_INSPECT] == 12);
+ counts[PEG_INSPECT] = 0;
+ NHttpModule::increment_peg_counts(PEG_INSPECT);
+ counts = mod.get_counts();
+ CHECK(counts[PEG_INSPECT] == 1);
+}
+
+int main(int argc, char** argv)
+{
+ return CommandLineTestRunner::RunAllTests(argc, argv);
+}
+