]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect/http-ua: cleanup tests 5745/head
authorVictor Julien <victor@inliniac.net>
Tue, 19 Jan 2021 06:50:28 +0000 (07:50 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 19 Jan 2021 09:19:40 +0000 (10:19 +0100)
src/tests/detect-http-user-agent.c

index 9d1dcc7e44488c80f7521657b333ce465c862560..2c8cfbe06d129467f46286f2c0e9bdcc1c51494d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2016 Open Information Security Foundation
+/* Copyright (C) 2007-2021 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
 #include "app-layer-htp.h"
 #include "app-layer-protos.h"
 
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest01(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "GET /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"CONNECT\"; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (!(PacketAlertCheck(p, 1))) {
-        printf("sid 1 didn't match but should have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest02(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"CO\"; depth:4; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (!(PacketAlertCheck(p, 1))) {
-        printf("sid 1 didn't match but should have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest03(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http_user_agent test\"; "
-                               "content:!\"ECT\"; depth:4; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (!(PacketAlertCheck(p, 1))) {
-        printf("sid 1 didn't match but should have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest04(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"ECT\"; depth:4; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (PacketAlertCheck(p, 1)) {
-        printf("sid 1 matched but shouldn't have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest05(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:!\"CON\"; depth:4; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (PacketAlertCheck(p, 1)) {
-        printf("sid 1 matched but shouldn't have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest06(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"ECT\"; offset:3; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (!(PacketAlertCheck(p, 1))) {
-        printf("sid 1 didn't match but should have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest07(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:!\"CO\"; offset:3; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (!(PacketAlertCheck(p, 1))) {
-        printf("sid 1 didn't match but should have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest08(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:!\"ECT\"; offset:3; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (PacketAlertCheck(p, 1)) {
-        printf("sid 1 matched but shouldn't have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest09(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"CON\"; offset:3; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (PacketAlertCheck(p, 1)) {
-        printf("sid 1 matched but shouldn't have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest10(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http_user_agent test\"; "
-                               "content:\"CO\"; http_user_agent; "
-                               "content:\"EC\"; within:4; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (!PacketAlertCheck(p, 1)) {
-        printf("sid 1 didn't match but should have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest11(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"CO\"; http_user_agent; "
-                               "content:!\"EC\"; within:3; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (!PacketAlertCheck(p, 1)) {
-        printf("sid 1 didn't match but should have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest12(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http_user_agent test\"; "
-                               "content:\"CO\"; http_user_agent; "
-                               "content:\"EC\"; within:3; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (PacketAlertCheck(p, 1)) {
-        printf("sid 1 matched but shouldn't have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest13(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"CO\"; http_user_agent; "
-                               "content:!\"EC\"; within:4; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (PacketAlertCheck(p, 1)) {
-        printf("sid 1 matched but shouldn't have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest14(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http_user_agent test\"; "
-                               "content:\"CO\"; http_user_agent; "
-                               "content:\"EC\"; distance:2; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (!PacketAlertCheck(p, 1)) {
-        printf("sid 1 didn't match but should have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest15(void)
-{
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"CO\"; http_user_agent; "
-                               "content:!\"EC\"; distance:3; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (!PacketAlertCheck(p, 1)) {
-        printf("sid 1 didn't match but should have: ");
-        goto end;
-    }
-
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest16(void)
+static int DetectEngineHttpUATest(
+        const uint8_t *buf, const uint32_t buf_len, const char *sig, const bool expect)
 {
     TcpSession ssn;
-    Packet *p = NULL;
     ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
     DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
     Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
-    uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
+
     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+    FAIL_IF_NULL(alp_tctx);
 
     memset(&th_v, 0, sizeof(th_v));
     memset(&f, 0, sizeof(f));
     memset(&ssn, 0, sizeof(ssn));
 
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+    FAIL_IF_NULL(p);
 
     FLOW_INITIALIZE(&f);
     f.protoctx = (void *)&ssn;
@@ -1572,194 +72,305 @@ static int DetectEngineHttpUATest16(void)
 
     StreamTcpInitConfig(TRUE);
 
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"CO\"; http_user_agent; "
-                               "content:\"EC\"; distance:3; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx, sig);
+    FAIL_IF_NULL(s);
 
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+    FAIL_IF_NULL(det_ctx);
 
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
+    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, buf, buf_len);
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
 
-    if (PacketAlertCheck(p, 1)) {
-        printf("sid 1 matched but shouldn't have: ");
-        goto end;
-    }
+    bool match = PacketAlertCheck(p, 1);
+    FAIL_IF_NOT(match == expect);
 
-    result = 1;
-
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
+    AppLayerParserThreadCtxFree(alp_tctx);
 
+    DetectEngineCtxFree(de_ctx);
     StreamTcpFreeConfig(TRUE);
     FLOW_DESTROY(&f);
     UTHFreePackets(&p, 1);
-    return result;
+    PASS;
 }
 
-/**
- * \test Test that the http_user_agent content matches against a http request
- *       which holds the content.
- */
-static int DetectEngineHttpUATest17(void)
+static int DetectEngineHttpUATest01(void)
 {
-    TcpSession ssn;
-    Packet *p = NULL;
-    ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    Flow f;
-    uint8_t http_buf[] =
-        "CONNECT /index.html HTTP/1.0\r\n"
-        "User-Agent: CONNECT\r\n"
-        "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint8_t http_buf[] = "GET /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
     uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:\"CONNECT\"; http_user_agent; "
+            "sid:1;)",
+            true);
+}
 
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
+static int DetectEngineHttpUATest02(void)
+{
+    uint8_t http_buf[] = "GET /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:\"CO\"; depth:4; http_user_agent; "
+            "sid:1;)",
+            true);
+}
 
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+static int DetectEngineHttpUATest03(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http_user_agent test\"; "
+            "content:!\"ECT\"; depth:4; http_user_agent; "
+            "sid:1;)",
+            true);
+}
 
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOSERVER;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
+static int DetectEngineHttpUATest04(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:\"ECT\"; depth:4; http_user_agent; "
+            "sid:1;)",
+            false);
+}
 
-    StreamTcpInitConfig(TRUE);
+static int DetectEngineHttpUATest05(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:!\"CON\"; depth:4; http_user_agent; "
+            "sid:1;)",
+            false);
+}
 
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
+static int DetectEngineHttpUATest06(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:\"ECT\"; offset:3; http_user_agent; "
+            "sid:1;)",
+            true);
+}
 
-    de_ctx->flags |= DE_QUIET;
+static int DetectEngineHttpUATest07(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:!\"CO\"; offset:3; http_user_agent; "
+            "sid:1;)",
+            true);
+}
 
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http_user_agent test\"; "
-                               "content:\"CO\"; http_user_agent; "
-                               "content:!\"EC\"; distance:2; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
+static int DetectEngineHttpUATest08(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:!\"ECT\"; offset:3; http_user_agent; "
+            "sid:1;)",
+            false);
+}
 
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+static int DetectEngineHttpUATest09(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:\"CON\"; offset:3; http_user_agent; "
+            "sid:1;)",
+            false);
+}
 
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
+static int DetectEngineHttpUATest10(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http_user_agent test\"; "
+            "content:\"CO\"; http_user_agent; "
+            "content:\"EC\"; within:4; http_user_agent; "
+            "sid:1;)",
+            true);
+}
 
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+static int DetectEngineHttpUATest11(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:\"CO\"; http_user_agent; "
+            "content:!\"EC\"; within:3; http_user_agent; "
+            "sid:1;)",
+            true);
+}
 
-    if (PacketAlertCheck(p, 1)) {
-        printf("sid 1 matched but shouldn't have: ");
-        goto end;
-    }
+static int DetectEngineHttpUATest12(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http_user_agent test\"; "
+            "content:\"CO\"; http_user_agent; "
+            "content:\"EC\"; within:3; http_user_agent; "
+            "sid:1;)",
+            false);
+}
 
-    result = 1;
+static int DetectEngineHttpUATest13(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:\"CO\"; http_user_agent; "
+            "content:!\"EC\"; within:4; http_user_agent; "
+            "sid:1;)",
+            false);
+}
 
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        SigGroupCleanup(de_ctx);
-    if (de_ctx != NULL)
-        SigCleanSignatures(de_ctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
+static int DetectEngineHttpUATest14(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http_user_agent test\"; "
+            "content:\"CO\"; http_user_agent; "
+            "content:\"EC\"; distance:2; http_user_agent; "
+            "sid:1;)",
+            true);
+}
 
-    StreamTcpFreeConfig(TRUE);
-    FLOW_DESTROY(&f);
-    UTHFreePackets(&p, 1);
-    return result;
+static int DetectEngineHttpUATest15(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:\"CO\"; http_user_agent; "
+            "content:!\"EC\"; distance:3; http_user_agent; "
+            "sid:1;)",
+            true);
 }
 
-/**
- * \test Test that a signature containting a http_user_agent is correctly parsed
- *       and the keyword is registered.
- */
-static int DetectHttpUATest01(void)
+static int DetectEngineHttpUATest16(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:\"CO\"; http_user_agent; "
+            "content:\"EC\"; distance:3; http_user_agent; "
+            "sid:1;)",
+            false);
+}
 
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
+static int DetectEngineHttpUATest17(void)
+{
+    uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+                         "User-Agent: CONNECT\r\n"
+                         "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+    uint32_t http_len = sizeof(http_buf) - 1;
+    return DetectEngineHttpUATest(http_buf, http_len,
+            "alert http any any -> any any "
+            "(msg:\"http_user_agent test\"; "
+            "content:\"CO\"; http_user_agent; "
+            "content:!\"EC\"; distance:2; http_user_agent; "
+            "sid:1;)",
+            false);
+}
 
+static int DetectHttpUATestSigParse(const char *sig, const bool expect)
+{
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(msg:\"Testing http_user_agent\"; "
-                               "content:\"one\"; http_user_agent; sid:1;)");
-    if (de_ctx->sig_list != NULL) {
-        result = 1;
-    } else {
-        goto end;
-    }
-
- end:
+
+    Signature *s = DetectEngineAppendSig(de_ctx, sig);
+    bool parsed = (s != NULL);
+    FAIL_IF_NOT(parsed == expect);
     DetectEngineCtxFree(de_ctx);
+    PASS;
+}
 
-    return result;
+/**
+ * \test Test that a signature containting a http_user_agent is correctly parsed
+ *       and the keyword is registered.
+ */
+static int DetectHttpUATest01(void)
+{
+    return DetectHttpUATestSigParse("alert tcp any any -> any any "
+                                    "(msg:\"Testing http_user_agent\"; "
+                                    "content:\"one\"; http_user_agent; sid:1;)",
+            true);
 }
 
 /**
@@ -1768,24 +379,10 @@ static int DetectHttpUATest01(void)
  */
 static int DetectHttpUATest02(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(msg:\"Testing http_user_agent\"; "
-                               "content:\"one\"; http_user_agent:; sid:1;)");
-    if (de_ctx->sig_list != NULL)
-        result = 1;
-
- end:
-    DetectEngineCtxFree(de_ctx);
-
-    return result;
+    return DetectHttpUATestSigParse("alert tcp any any -> any any "
+                                    "(msg:\"Testing http_user_agent\"; "
+                                    "content:\"one\"; http_user_agent:; sid:1;)",
+            true);
 }
 
 /**
@@ -1794,24 +391,10 @@ static int DetectHttpUATest02(void)
  */
 static int DetectHttpUATest03(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(msg:\"Testing http_user_agent\"; "
-                               "http_user_agent; sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        result = 1;
-
- end:
-    DetectEngineCtxFree(de_ctx);
-
-    return result;
+    return DetectHttpUATestSigParse("alert tcp any any -> any any "
+                                    "(msg:\"Testing http_user_agent\"; "
+                                    "http_user_agent; sid:1;)",
+            false);
 }
 
 /**
@@ -1820,24 +403,10 @@ static int DetectHttpUATest03(void)
  */
 static int DetectHttpUATest04(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(msg:\"Testing http_user_agent\"; "
-                               "content:\"one\"; rawbytes; http_user_agent; sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        result = 1;
-
- end:
-    DetectEngineCtxFree(de_ctx);
-
-    return result;
+    return DetectHttpUATestSigParse("alert tcp any any -> any any "
+                                    "(msg:\"Testing http_user_agent\"; "
+                                    "content:\"one\"; rawbytes; http_user_agent; sid:1;)",
+            false);
 }
 
 /**
@@ -1845,24 +414,10 @@ static int DetectHttpUATest04(void)
  */
 static int DetectHttpUATest05(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
-
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(msg:\"Testing http_user_agent\"; "
-                               "content:\"one\"; http_user_agent; nocase; sid:1;)");
-    if (de_ctx->sig_list != NULL)
-        result = 1;
-
- end:
-    DetectEngineCtxFree(de_ctx);
-
-    return result;
+    return DetectHttpUATestSigParse("alert tcp any any -> any any "
+                                    "(msg:\"Testing http_user_agent\"; "
+                                    "content:\"one\"; http_user_agent; nocase; sid:1;)",
+            true);
 }
 
 /**
@@ -1872,11 +427,8 @@ static int DetectHttpUATest05(void)
 static int DetectHttpUATest06(void)
 {
     TcpSession ssn;
-    Packet *p = NULL;
     ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
     DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
     Flow f;
     uint8_t http_buf[] =
         "GET /index.html HTTP/1.0\r\n"
@@ -1885,14 +437,14 @@ static int DetectHttpUATest06(void)
         "Content-Type: text/html\r\n"
         "\r\n";
     uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
 
     memset(&th_v, 0, sizeof(th_v));
     memset(&f, 0, sizeof(f));
     memset(&ssn, 0, sizeof(ssn));
 
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+    FAIL_IF_NULL(p);
 
     FLOW_INITIALIZE(&f);
     f.protoctx = (void *)&ssn;
@@ -1907,59 +459,36 @@ static int DetectHttpUATest06(void)
 
     StreamTcpInitConfig(TRUE);
 
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"message\"; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+                                                 "(msg:\"http user agent test\"; "
+                                                 "content:\"message\"; http_user_agent; "
+                                                 "sid:1;)");
+    FAIL_IF_NULL(s);
 
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 
-    FLOWLOCK_WRLOCK(&f);
     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                 STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: \n");
-        result = 0;
-        goto end;
-    }
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
 
-    if (!(PacketAlertCheck(p, 1))) {
-        printf("sid 1 didn't match but should have\n");
-        goto end;
-    }
+    FAIL_IF_NOT(PacketAlertCheck(p, 1));
 
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
+    AppLayerParserThreadCtxFree(alp_tctx);
+    DetectEngineCtxFree(de_ctx);
 
     StreamTcpFreeConfig(TRUE);
     FLOW_DESTROY(&f);
     UTHFreePackets(&p, 1);
-    return result;
+    PASS;
 }
 
 /**
@@ -1972,9 +501,7 @@ static int DetectHttpUATest07(void)
     Packet *p1 = NULL;
     Packet *p2 = NULL;
     ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
     DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
     Flow f;
     uint8_t http1_buf[] =
         "GET /index.html HTTP/1.0\r\n"
@@ -1984,7 +511,6 @@ static int DetectHttpUATest07(void)
         "body1\r\n\r\n";
     uint32_t http1_len = sizeof(http1_buf) - 1;
     uint32_t http2_len = sizeof(http2_buf) - 1;
-    int result = 0;
     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
 
     memset(&th_v, 0, sizeof(th_v));
@@ -2011,76 +537,46 @@ static int DetectHttpUATest07(void)
 
     StreamTcpInitConfig(TRUE);
 
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"message\"; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+                                                 "(msg:\"http user agent test\"; "
+                                                 "content:\"message\"; http_user_agent; "
+                                                 "sid:1;)");
+    FAIL_IF_NULL(s);
 
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 
-    FLOWLOCK_WRLOCK(&f);
     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                 STREAM_TOSERVER, http1_buf, http1_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        goto end;
-    }
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
 
-    if (PacketAlertCheck(p1, 1)) {
-        printf("sid 1 matched on p1 but shouldn't have: ");
-        goto end;
-    }
+    FAIL_IF(PacketAlertCheck(p1, 1));
 
-    FLOWLOCK_WRLOCK(&f);
     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                             STREAM_TOSERVER, http2_buf, http2_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
-    if (!(PacketAlertCheck(p2, 1))) {
-        printf("sid 1 didn't match on p2 but should have: ");
-        goto end;
-    }
-
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
+    FAIL_IF_NOT(PacketAlertCheck(p2, 1));
+
+    AppLayerParserThreadCtxFree(alp_tctx);
+    DetectEngineCtxFree(de_ctx);
 
     StreamTcpFreeConfig(TRUE);
     FLOW_DESTROY(&f);
     UTHFreePackets(&p1, 1);
     UTHFreePackets(&p2, 1);
-    return result;
+    PASS;
 }
 
 /**
@@ -2093,9 +589,7 @@ static int DetectHttpUATest08(void)
     Packet *p1 = NULL;
     Packet *p2 = NULL;
     ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
     DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
     Flow f;
     uint8_t http1_buf[] =
         "GET /index.html HTTP/1.0\r\n"
@@ -2105,7 +599,6 @@ static int DetectHttpUATest08(void)
         "age body\r\n\r\n";
     uint32_t http1_len = sizeof(http1_buf) - 1;
     uint32_t http2_len = sizeof(http2_buf) - 1;
-    int result = 0;
     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
 
     memset(&th_v, 0, sizeof(th_v));
@@ -2132,79 +625,46 @@ static int DetectHttpUATest08(void)
 
     StreamTcpInitConfig(TRUE);
 
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"message\"; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+                                                 "(msg:\"http user agent test\"; "
+                                                 "content:\"message\"; http_user_agent; "
+                                                 "sid:1;)");
+    FAIL_IF_NULL(s);
 
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 
-    FLOWLOCK_WRLOCK(&f);
     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                 STREAM_TOSERVER, http1_buf, http1_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+    FAIL_IF(PacketAlertCheck(p1, 1));
 
-    if ((PacketAlertCheck(p1, 1))) {
-        printf("sid 1 didn't match but should have");
-        goto end;
-    }
-
-    FLOWLOCK_WRLOCK(&f);
     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                             STREAM_TOSERVER, http2_buf, http2_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
 
-    if (!(PacketAlertCheck(p2, 1))) {
-        printf("sid 1 didn't match but should have");
-        goto end;
-    }
+    FAIL_IF_NOT(PacketAlertCheck(p2, 1));
 
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
+    AppLayerParserThreadCtxFree(alp_tctx);
+    DetectEngineCtxFree(de_ctx);
 
     StreamTcpFreeConfig(TRUE);
     FLOW_DESTROY(&f);
     UTHFreePackets(&p1, 1);
     UTHFreePackets(&p2, 1);
-    return result;
+    PASS;
 }
 
 /**
@@ -2217,9 +677,7 @@ static int DetectHttpUATest09(void)
     Packet *p1 = NULL;
     Packet *p2 = NULL;
     ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
     DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
     Flow f;
     uint8_t http1_buf[] =
         "GET /index.html HTTP/1.0\r\n"
@@ -2233,7 +691,6 @@ static int DetectHttpUATest09(void)
         "This is dummy body1";
     uint32_t http1_len = sizeof(http1_buf) - 1;
     uint32_t http2_len = sizeof(http2_buf) - 1;
-    int result = 0;
     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
 
     memset(&th_v, 0, sizeof(th_v));
@@ -2260,79 +717,45 @@ static int DetectHttpUATest09(void)
 
     StreamTcpInitConfig(TRUE);
 
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"body1This\"; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+                                                 "(msg:\"http user agent test\"; "
+                                                 "content:\"body1This\"; http_user_agent; "
+                                                 "sid:1;)");
+    FAIL_IF_NULL(s);
 
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 
-    FLOWLOCK_WRLOCK(&f);
     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                 STREAM_TOSERVER, http1_buf, http1_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+    FAIL_IF(PacketAlertCheck(p1, 1));
 
-    if ((PacketAlertCheck(p1, 1))) {
-        printf("sid 1 didn't match but should have");
-        goto end;
-    }
-
-    FLOWLOCK_WRLOCK(&f);
     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                             STREAM_TOSERVER, http2_buf, http2_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
 
-    if (!(PacketAlertCheck(p2, 1))) {
-        printf("sid 1 didn't match but should have");
-        goto end;
-    }
-
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
+    FAIL_IF_NOT(PacketAlertCheck(p2, 1));
 
+    AppLayerParserThreadCtxFree(alp_tctx);
+    DetectEngineCtxFree(de_ctx);
     StreamTcpFreeConfig(TRUE);
     FLOW_DESTROY(&f);
     UTHFreePackets(&p1, 1);
     UTHFreePackets(&p2, 1);
-    return result;
+    PASS;
 }
 
 /**
@@ -2345,9 +768,7 @@ static int DetectHttpUATest10(void)
     Packet *p1 = NULL;
     Packet *p2 = NULL;
     ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
     DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
     Flow f;
     uint8_t http1_buf[] =
         "GET /index.html HTTP/1.0\r\n"
@@ -2361,7 +782,6 @@ static int DetectHttpUATest10(void)
         "This is dummy bodY1";
     uint32_t http1_len = sizeof(http1_buf) - 1;
     uint32_t http2_len = sizeof(http2_buf) - 1;
-    int result = 0;
     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
 
     memset(&th_v, 0, sizeof(th_v));
@@ -2388,79 +808,44 @@ static int DetectHttpUATest10(void)
 
     StreamTcpInitConfig(TRUE);
 
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"body1this\"; http_user_agent; nocase;"
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+                                                 "(msg:\"http user agent test\"; "
+                                                 "content:\"body1this\"; http_user_agent; nocase;"
+                                                 "sid:1;)");
+    FAIL_IF_NULL(s);
 
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 
-    FLOWLOCK_WRLOCK(&f);
     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                 STREAM_TOSERVER, http1_buf, http1_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: \n");
-        result = 0;
-        goto end;
-    }
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+    FAIL_IF(PacketAlertCheck(p1, 1));
 
-    if ((PacketAlertCheck(p1, 1))) {
-        printf("sid 1 didn't match but should have\n");
-        goto end;
-    }
-
-    FLOWLOCK_WRLOCK(&f);
     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                             STREAM_TOSERVER, http2_buf, http2_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+    FAIL_IF_NOT(PacketAlertCheck(p2, 1));
 
-    if (!(PacketAlertCheck(p2, 1))) {
-        printf("sid 1 didn't match but should have");
-        goto end;
-    }
-
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-
+    AppLayerParserThreadCtxFree(alp_tctx);
+    DetectEngineCtxFree(de_ctx);
     StreamTcpFreeConfig(TRUE);
     FLOW_DESTROY(&f);
     UTHFreePackets(&p1, 1);
     UTHFreePackets(&p2, 1);
-    return result;
+    PASS;
 }
 
 /**
@@ -2472,9 +857,7 @@ static int DetectHttpUATest11(void)
     TcpSession ssn;
     Packet *p = NULL;
     ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
     DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
     Flow f;
     uint8_t http_buf[] =
         "GET /index.html HTTP/1.0\r\n"
@@ -2483,7 +866,6 @@ static int DetectHttpUATest11(void)
         "Content-Type: text/html\r\n"
         "\r\n";
     uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
 
     memset(&th_v, 0, sizeof(th_v));
@@ -2505,59 +887,35 @@ static int DetectHttpUATest11(void)
 
     StreamTcpInitConfig(TRUE);
 
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:!\"message\"; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+                                                 "(msg:\"http user agent test\"; "
+                                                 "content:!\"message\"; http_user_agent; "
+                                                 "sid:1;)");
+    FAIL_IF_NULL(s);
 
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 
-    FLOWLOCK_WRLOCK(&f);
     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                 STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
 
-    if (PacketAlertCheck(p, 1)) {
-        printf("sid 1 matched but shouldn't have");
-        goto end;
-    }
-
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
+    FAIL_IF(PacketAlertCheck(p, 1));
 
+    AppLayerParserThreadCtxFree(alp_tctx);
+    DetectEngineCtxFree(de_ctx);
     StreamTcpFreeConfig(TRUE);
     FLOW_DESTROY(&f);
     UTHFreePackets(&p, 1);
-    return result;
+    PASS;
 }
 
 /**
@@ -2569,9 +927,7 @@ static int DetectHttpUATest12(void)
     TcpSession ssn;
     Packet *p = NULL;
     ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
     DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
     Flow f;
     uint8_t http_buf[] =
         "GET /index.html HTTP/1.0\r\n"
@@ -2579,7 +935,6 @@ static int DetectHttpUATest12(void)
         "User-Agent: This is dummy body\r\n"
         "\r\n";
     uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
 
     memset(&th_v, 0, sizeof(th_v));
@@ -2601,59 +956,35 @@ static int DetectHttpUATest12(void)
 
     StreamTcpInitConfig(TRUE);
 
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:!\"message\"; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+                                                 "(msg:\"http user agent test\"; "
+                                                 "content:!\"message\"; http_user_agent; "
+                                                 "sid:1;)");
+    FAIL_IF_NULL(s);
 
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 
-    FLOWLOCK_WRLOCK(&f);
     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                 STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    FAIL_IF_NOT(PacketAlertCheck(p, 1));
 
-    if (!(PacketAlertCheck(p, 1))) {
-        printf("sid 1 didn't match but should have");
-        goto end;
-    }
-
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
+    AppLayerParserThreadCtxFree(alp_tctx);
+    DetectEngineCtxFree(de_ctx);
 
     StreamTcpFreeConfig(TRUE);
     FLOW_DESTROY(&f);
     UTHFreePackets(&p, 1);
-    return result;
+    PASS;
 }
 
 /**
@@ -2665,9 +996,7 @@ static int DetectHttpUATest13(void)
     TcpSession ssn;
     Packet *p = NULL;
     ThreadVars th_v;
-    DetectEngineCtx *de_ctx = NULL;
     DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
     Flow f;
     uint8_t http_buf[] =
         "GET /index.html HTTP/1.0\r\n"
@@ -2676,7 +1005,6 @@ static int DetectHttpUATest13(void)
         "Content-Type: text/html\r\n"
         "\r\n";
     uint32_t http_len = sizeof(http_buf) - 1;
-    int result = 0;
     AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
 
     memset(&th_v, 0, sizeof(th_v));
@@ -2698,59 +1026,36 @@ static int DetectHttpUATest13(void)
 
     StreamTcpInitConfig(TRUE);
 
-    de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL)
-        goto end;
-
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
-    de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
-                               "(msg:\"http user agent test\"; "
-                               "content:\"abcdefghijklmnopqrstuvwxyz0123456789\"; http_user_agent; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx,
+            "alert http any any -> any any "
+            "(msg:\"http user agent test\"; "
+            "content:\"abcdefghijklmnopqrstuvwxyz0123456789\"; http_user_agent; "
+            "sid:1;)");
+    FAIL_IF_NULL(s);
 
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 
-    FLOWLOCK_WRLOCK(&f);
     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                 STREAM_TOSERVER, http_buf, http_len);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
+    FAIL_IF_NOT(r == 0);
+    FAIL_IF_NULL(f.alstate);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
 
-    if (!(PacketAlertCheck(p, 1))) {
-        printf("sid 1 didn't match but should have");
-        goto end;
-    }
-
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
+    FAIL_IF_NOT(PacketAlertCheck(p, 1));
 
+    AppLayerParserThreadCtxFree(alp_tctx);
+    DetectEngineCtxFree(de_ctx);
     StreamTcpFreeConfig(TRUE);
     FLOW_DESTROY(&f);
     UTHFreePackets(&p, 1);
-    return result;
+    PASS;
 }
 
 /**
@@ -2758,7 +1063,6 @@ end:
  */
 static int DetectHttpUATest14(void)
 {
-    int result = 0;
     Signature *s = NULL;
     DetectEngineThreadCtx *det_ctx = NULL;
     ThreadVars th_v;
@@ -2799,819 +1103,477 @@ static int DetectHttpUATest14(void)
     StreamTcpInitConfig(TRUE);
 
     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL) {
-        goto end;
-    }
-
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"dummy1\"; http_cookie; content:\"Body one\"; http_user_agent; sid:1; rev:1;)");
-    if (s == NULL) {
-        printf("sig parse failed: ");
-        goto end;
-    }
+    FAIL_IF_NULL(s);
     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"dummy2\"; http_cookie; content:\"Body two\"; http_user_agent; sid:2; rev:1;)");
-    if (s == NULL) {
-        printf("sig2 parse failed: ");
-        goto end;
-    }
+    FAIL_IF_NULL(s);
 
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 
-    FLOWLOCK_WRLOCK(&f);
     int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                 STREAM_TOSERVER, httpbuf1, httplen1);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF_NOT(r == 0);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-    if (PacketAlertCheck(p, 1)) {
-        printf("sig 1 alerted: ");
-        goto end;
-    }
-    p->alerts.cnt = 0;
+    FAIL_IF(PacketAlertCheck(p, 1));
 
-    FLOWLOCK_WRLOCK(&f);
     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                             STREAM_TOSERVER, httpbuf2, httplen2);
-    if (r != 0) {
-        printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF_NOT(r == 0);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-    if (PacketAlertCheck(p, 1)) {
-        printf("sig 1 alerted (2): ");
-        goto end;
-    }
-    p->alerts.cnt = 0;
+    FAIL_IF(PacketAlertCheck(p, 1));
 
-    FLOWLOCK_WRLOCK(&f);
     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                             STREAM_TOSERVER, httpbuf3, httplen3);
-    if (r != 0) {
-        printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF_NOT(r == 0);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-    if (!(PacketAlertCheck(p, 1))) {
-        printf("sig 1 didn't alert: ");
-        goto end;
-    }
+    FAIL_IF_NOT(PacketAlertCheck(p, 1));
     p->alerts.cnt = 0;
 
-    FLOWLOCK_WRLOCK(&f);
     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                             STREAM_TOSERVER, httpbuf4, httplen4);
-    if (r != 0) {
-        printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r);
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF_NOT(r == 0);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-    if (PacketAlertCheck(p, 1) || PacketAlertCheck(p, 2)) {
-        printf("sig 1 alerted (4): ");
-        goto end;
-    }
-    p->alerts.cnt = 0;
+    FAIL_IF(PacketAlertCheck(p, 1));
+    FAIL_IF(PacketAlertCheck(p, 2));
 
-    FLOWLOCK_WRLOCK(&f);
     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                             STREAM_TOSERVER, httpbuf5, httplen5);
-    if (r != 0) {
-        printf("toserver chunk 6 returned %" PRId32 ", expected 0: ", r);
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF_NOT(r == 0);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-    if ((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2))) {
-        printf("sig 1 alerted (request 2, chunk 6): ");
-        goto end;
-    }
-    p->alerts.cnt = 0;
+    FAIL_IF(PacketAlertCheck(p, 1));
+    FAIL_IF(PacketAlertCheck(p, 2));
 
     SCLogDebug("sending data chunk 7");
 
-    FLOWLOCK_WRLOCK(&f);
     r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                             STREAM_TOSERVER, httpbuf6, httplen6);
-    if (r != 0) {
-        printf("toserver chunk 7 returned %" PRId32 ", expected 0: ", r);
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF_NOT(r == 0);
 
     /* do detect */
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-    if (PacketAlertCheck(p, 1) || !(PacketAlertCheck(p, 2))) {
-        printf("signature 2 didn't match or sig 1 matched, but shouldn't have: ");
-        goto end;
-    }
+    FAIL_IF(PacketAlertCheck(p, 1));
+    FAIL_IF_NOT(PacketAlertCheck(p, 2));
     p->alerts.cnt = 0;
 
     HtpState *htp_state = f.alstate;
-    if (htp_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    if (AppLayerParserGetTxCnt(&f, htp_state) != 2) {
-        printf("The http app layer doesn't have 2 transactions, but it should: ");
-        goto end;
-    }
-
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (det_ctx != NULL) {
-        DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
-    }
-    if (de_ctx != NULL) {
-        DetectEngineCtxFree(de_ctx);
-    }
+    FAIL_IF_NULL(htp_state);
+    FAIL_IF_NOT(AppLayerParserGetTxCnt(&f, htp_state) == 2);
+
+    AppLayerParserThreadCtxFree(alp_tctx);
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
 
     StreamTcpFreeConfig(TRUE);
     FLOW_DESTROY(&f);
     UTHFreePacket(p);
-    return result;
+    PASS;
 }
 
 static int DetectHttpUATest22(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
 
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx,
+            "alert tcp any any -> any any "
+            "(content:\"one\"; content:\"two\"; http_user_agent; "
+            "content:\"three\"; distance:10; http_user_agent; content:\"four\"; sid:1;)");
+    FAIL_IF_NULL(s);
+    FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_PMATCH]);
+    FAIL_IF_NULL(s->sm_lists[g_http_ua_buffer_id]);
+
+    DetectContentData *cd1 =
+            (DetectContentData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
+    DetectContentData *cd2 = (DetectContentData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
+    DetectContentData *huad1 =
+            (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
+    DetectContentData *huad2 = (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->ctx;
+
+    FAIL_IF_NULL(cd1);
+    FAIL_IF_NULL(cd2);
+    FAIL_IF_NULL(huad1);
+    FAIL_IF_NULL(huad2);
+
+    FAIL_IF_NOT(cd1->flags == 0);
+    FAIL_IF_NOT(memcmp(cd1->content, "one", cd1->content_len) == 0);
+    FAIL_IF_NOT(cd2->flags == 0);
+    FAIL_IF_NOT(memcmp(cd2->content, "four", cd2->content_len) == 0);
+    FAIL_IF_NOT(huad1->flags == DETECT_CONTENT_RELATIVE_NEXT);
+    FAIL_IF_NOT(memcmp(huad1->content, "two", huad1->content_len) == 0);
+    FAIL_IF_NOT(huad2->flags == DETECT_CONTENT_DISTANCE);
+    FAIL_IF_NOT(memcmp(huad2->content, "three", huad1->content_len) == 0);
+
+    FAIL_IF(!DETECT_CONTENT_IS_SINGLE(cd1));
+    FAIL_IF(!DETECT_CONTENT_IS_SINGLE(cd2));
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(huad1));
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(huad2));
 
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"one\"; content:\"two\"; http_user_agent; "
-                               "content:\"three\"; distance:10; http_user_agent; content:\"four\"; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL\n");
-        goto end;
-    }
-
-    DetectContentData *cd1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
-    DetectContentData *cd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
-    DetectContentData *huad1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
-    DetectContentData *huad2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->ctx;
-    if (cd1->flags != 0 || memcmp(cd1->content, "one", cd1->content_len) != 0 ||
-        cd2->flags != 0 || memcmp(cd2->content, "four", cd2->content_len) != 0 ||
-        huad1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
-        memcmp(huad1->content, "two", huad1->content_len) != 0 ||
-        huad2->flags != DETECT_CONTENT_DISTANCE ||
-        memcmp(huad2->content, "three", huad1->content_len) != 0) {
-        goto end;
-    }
-
-    if (!DETECT_CONTENT_IS_SINGLE(cd1) ||
-        !DETECT_CONTENT_IS_SINGLE(cd2) ||
-        DETECT_CONTENT_IS_SINGLE(huad1) ||
-        DETECT_CONTENT_IS_SINGLE(huad2)) {
-        goto end;
-    }
-
-    result = 1;
-
- end:
     DetectEngineCtxFree(de_ctx);
-    return result;
+    PASS;
 }
 
 static int DetectHttpUATest23(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
 
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx,
+            "alert tcp any any -> any any "
+            "(content:\"one\"; http_user_agent; pcre:/two/; "
+            "content:\"three\"; distance:10; http_user_agent; content:\"four\"; sid:1;)");
+    FAIL_IF_NULL(s);
+    FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_PMATCH]);
+    FAIL_IF_NULL(s->sm_lists[g_http_ua_buffer_id]);
+
+    DetectPcreData *pd1 = (DetectPcreData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
+    DetectContentData *cd2 = (DetectContentData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
+    DetectContentData *huad1 =
+            (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
+    DetectContentData *huad2 = (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->ctx;
+    FAIL_IF_NOT(pd1->flags == 0);
+    FAIL_IF_NOT(cd2->flags == 0);
+    FAIL_IF_NOT(memcmp(cd2->content, "four", cd2->content_len) == 0);
+    FAIL_IF_NOT(huad1->flags == DETECT_CONTENT_RELATIVE_NEXT);
+    FAIL_IF_NOT(memcmp(huad1->content, "one", huad1->content_len) == 0);
+    FAIL_IF_NOT(huad2->flags == DETECT_CONTENT_DISTANCE);
+    FAIL_IF_NOT(memcmp(huad2->content, "three", huad1->content_len) == 0);
+
+    FAIL_IF(!DETECT_CONTENT_IS_SINGLE(cd2));
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(huad1));
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(huad2));
 
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"one\"; http_user_agent; pcre:/two/; "
-                               "content:\"three\"; distance:10; http_user_agent; content:\"four\"; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL\n");
-        goto end;
-    }
-
-    DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
-    DetectContentData *cd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
-    DetectContentData *huad1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
-    DetectContentData *huad2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->ctx;
-    if (pd1->flags != 0 ||
-        cd2->flags != 0 || memcmp(cd2->content, "four", cd2->content_len) != 0 ||
-        huad1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
-        memcmp(huad1->content, "one", huad1->content_len) != 0 ||
-        huad2->flags != DETECT_CONTENT_DISTANCE ||
-        memcmp(huad2->content, "three", huad1->content_len) != 0) {
-        goto end;
-    }
-
-    if (!DETECT_CONTENT_IS_SINGLE(cd2) ||
-        DETECT_CONTENT_IS_SINGLE(huad1) ||
-        DETECT_CONTENT_IS_SINGLE(huad2)) {
-        goto end;
-    }
-
-    result = 1;
-
- end:
     DetectEngineCtxFree(de_ctx);
-    return result;
+    PASS;
 }
 
 static int DetectHttpUATest24(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
 
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
+                                                 "(content:\"one\"; http_user_agent; pcre:/two/; "
+                                                 "content:\"three\"; distance:10; within:15; "
+                                                 "http_user_agent; content:\"four\"; sid:1;)");
+    FAIL_IF_NULL(s);
+    FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_PMATCH]);
+    FAIL_IF_NULL(s->sm_lists[g_http_ua_buffer_id]);
+
+    DetectPcreData *pd1 = (DetectPcreData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
+    DetectContentData *cd2 = (DetectContentData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
+    DetectContentData *huad1 =
+            (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
+    DetectContentData *huad2 = (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->ctx;
+    FAIL_IF_NOT(pd1->flags == 0);
+    FAIL_IF_NOT(cd2->flags == 0);
+    FAIL_IF_NOT(memcmp(cd2->content, "four", cd2->content_len) == 0);
+    FAIL_IF_NOT(huad1->flags == DETECT_CONTENT_RELATIVE_NEXT);
+    FAIL_IF_NOT(memcmp(huad1->content, "one", huad1->content_len) == 0);
+    FAIL_IF_NOT(huad2->flags == (DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN));
+    FAIL_IF_NOT(memcmp(huad2->content, "three", huad1->content_len) == 0);
+
+    FAIL_IF(!DETECT_CONTENT_IS_SINGLE(cd2));
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(huad1));
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(huad2));
 
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"one\"; http_user_agent; pcre:/two/; "
-                               "content:\"three\"; distance:10; within:15; http_user_agent; content:\"four\"; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL\n");
-        goto end;
-    }
-
-    DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
-    DetectContentData *cd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
-    DetectContentData *huad1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
-    DetectContentData *huad2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->ctx;
-    if (pd1->flags != 0 ||
-        cd2->flags != 0 || memcmp(cd2->content, "four", cd2->content_len) != 0 ||
-        huad1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
-        memcmp(huad1->content, "one", huad1->content_len) != 0 ||
-        huad2->flags != (DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN) ||
-        memcmp(huad2->content, "three", huad1->content_len) != 0) {
-        goto end;
-    }
-
-    if (!DETECT_CONTENT_IS_SINGLE(cd2) ||
-        DETECT_CONTENT_IS_SINGLE(huad1) ||
-        DETECT_CONTENT_IS_SINGLE(huad2)) {
-        goto end;
-    }
-
-    result = 1;
-
- end:
     DetectEngineCtxFree(de_ctx);
-    return result;
+    PASS;
 }
 
 static int DetectHttpUATest25(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
 
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
+                                                 "(content:\"one\"; http_user_agent; pcre:/two/; "
+                                                 "content:\"three\"; distance:10; http_user_agent; "
+                                                 "content:\"four\"; distance:10; sid:1;)");
+    FAIL_IF_NULL(s);
+    FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_PMATCH]);
+    FAIL_IF_NULL(s->sm_lists[g_http_ua_buffer_id]);
+
+    DetectPcreData *pd1 = (DetectPcreData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
+    DetectContentData *cd2 = (DetectContentData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
+    DetectContentData *huad1 =
+            (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
+    DetectContentData *huad2 = (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->ctx;
+
+    FAIL_IF_NOT(pd1->flags == DETECT_PCRE_RELATIVE_NEXT);
+    FAIL_IF_NOT(cd2->flags == DETECT_CONTENT_DISTANCE);
+    FAIL_IF_NOT(memcmp(cd2->content, "four", cd2->content_len) == 0);
+    FAIL_IF_NOT(huad1->flags == DETECT_CONTENT_RELATIVE_NEXT);
+    FAIL_IF_NOT(memcmp(huad1->content, "one", huad1->content_len) == 0);
+    FAIL_IF_NOT(huad2->flags == DETECT_CONTENT_DISTANCE);
+    FAIL_IF_NOT(memcmp(huad2->content, "three", huad1->content_len) == 0);
+
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(cd2));
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(huad1));
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(huad2));
 
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"one\"; http_user_agent; pcre:/two/; "
-                               "content:\"three\"; distance:10; http_user_agent; "
-                               "content:\"four\"; distance:10; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL\n");
-        goto end;
-    }
-
-    DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
-    DetectContentData *cd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
-    DetectContentData *huad1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
-    DetectContentData *huad2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->ctx;
-    if (pd1->flags != DETECT_PCRE_RELATIVE_NEXT ||
-        cd2->flags != DETECT_CONTENT_DISTANCE ||
-        memcmp(cd2->content, "four", cd2->content_len) != 0 ||
-        huad1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
-        memcmp(huad1->content, "one", huad1->content_len) != 0 ||
-        huad2->flags != DETECT_CONTENT_DISTANCE ||
-        memcmp(huad2->content, "three", huad1->content_len) != 0) {
-        goto end;
-    }
-
-    if (DETECT_CONTENT_IS_SINGLE(cd2) ||
-        DETECT_CONTENT_IS_SINGLE(huad1) ||
-        DETECT_CONTENT_IS_SINGLE(huad2)) {
-        goto end;
-    }
-
-    result = 1;
-
- end:
     DetectEngineCtxFree(de_ctx);
-    return result;
+    PASS;
 }
 
 static int DetectHttpUATest26(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
 
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx,
+            "alert tcp any any -> any any "
+            "(content:\"one\"; offset:10; http_user_agent; pcre:/two/; "
+            "content:\"three\"; distance:10; http_user_agent; within:10; "
+            "content:\"four\"; distance:10; sid:1;)");
+    FAIL_IF_NULL(s);
+    FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_PMATCH]);
+    FAIL_IF_NULL(s->sm_lists[g_http_ua_buffer_id]);
+
+    DetectPcreData *pd1 = (DetectPcreData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
+    DetectContentData *cd2 = (DetectContentData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
+    DetectContentData *huad1 =
+            (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
+    DetectContentData *huad2 = (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->ctx;
+
+    FAIL_IF_NOT(pd1->flags == DETECT_PCRE_RELATIVE_NEXT);
+    FAIL_IF_NOT(cd2->flags == DETECT_CONTENT_DISTANCE);
+    FAIL_IF_NOT(memcmp(cd2->content, "four", cd2->content_len) == 0);
+    FAIL_IF_NOT(huad1->flags == (DETECT_CONTENT_RELATIVE_NEXT | DETECT_CONTENT_OFFSET));
+    FAIL_IF_NOT(memcmp(huad1->content, "one", huad1->content_len) == 0);
+    FAIL_IF_NOT(huad2->flags == (DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN));
+    FAIL_IF_NOT(memcmp(huad2->content, "three", huad1->content_len) == 0);
+
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(cd2));
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(huad1));
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(huad2));
 
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"one\"; offset:10; http_user_agent; pcre:/two/; "
-                               "content:\"three\"; distance:10; http_user_agent; within:10; "
-                               "content:\"four\"; distance:10; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL\n");
-        goto end;
-    }
-
-    DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
-    DetectContentData *cd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
-    DetectContentData *huad1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
-    DetectContentData *huad2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->ctx;
-    if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) ||
-        cd2->flags != DETECT_CONTENT_DISTANCE ||
-        memcmp(cd2->content, "four", cd2->content_len) != 0 ||
-        huad1->flags != (DETECT_CONTENT_RELATIVE_NEXT | DETECT_CONTENT_OFFSET) ||
-        memcmp(huad1->content, "one", huad1->content_len) != 0 ||
-        huad2->flags != (DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN) ||
-        memcmp(huad2->content, "three", huad1->content_len) != 0) {
-        printf ("failed: http_user_agent incorrect flags");
-        goto end;
-    }
-
-    if (DETECT_CONTENT_IS_SINGLE(cd2) ||
-        DETECT_CONTENT_IS_SINGLE(huad1) ||
-        DETECT_CONTENT_IS_SINGLE(huad2)) {
-        goto end;
-    }
-
-    result = 1;
-
- end:
     DetectEngineCtxFree(de_ctx);
-    return result;
+    PASS;
 }
 
 static int DetectHttpUATest27(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
-
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"one\"; offset:10; http_user_agent; pcre:/two/; "
-                               "content:\"three\"; distance:10; http_user_agent; within:10; "
-                               "content:\"four\"; distance:10; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    result = 1;
-
- end:
-    DetectEngineCtxFree(de_ctx);
-    return result;
+    return DetectHttpUATestSigParse("alert tcp any any -> any any "
+                                    "(content:\"one\"; offset:10; http_user_agent; pcre:/two/; "
+                                    "content:\"three\"; distance:10; http_user_agent; within:10; "
+                                    "content:\"four\"; distance:10; sid:1;)",
+            true);
 }
 
 static int DetectHttpUATest28(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
 
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
+                                                 "(content:\"one\"; http_user_agent; pcre:/two/; "
+                                                 "content:\"three\"; http_user_agent; depth:10; "
+                                                 "content:\"four\"; distance:10; sid:1;)");
+    FAIL_IF_NULL(s);
+    FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_PMATCH]);
+    FAIL_IF_NULL(s->sm_lists[g_http_ua_buffer_id]);
+
+    DetectPcreData *pd1 = (DetectPcreData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
+    DetectContentData *cd2 = (DetectContentData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
+    DetectContentData *huad1 =
+            (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
+    DetectContentData *huad2 = (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->ctx;
+
+    FAIL_IF_NOT(pd1->flags == DETECT_PCRE_RELATIVE_NEXT);
+    FAIL_IF_NOT(cd2->flags == DETECT_CONTENT_DISTANCE);
+    FAIL_IF_NOT(memcmp(cd2->content, "four", cd2->content_len) == 0);
+    FAIL_IF_NOT(huad1->flags == 0);
+    FAIL_IF_NOT(memcmp(huad1->content, "one", huad1->content_len) == 0);
+    FAIL_IF_NOT(huad2->flags == (DETECT_CONTENT_DEPTH));
+    FAIL_IF_NOT(memcmp(huad2->content, "three", huad1->content_len) == 0);
+
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(cd2));
+    FAIL_IF_NOT(DETECT_CONTENT_IS_SINGLE(huad1));
+    FAIL_IF(DETECT_CONTENT_IS_SINGLE(huad2));
 
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"one\"; http_user_agent; pcre:/two/; "
-                               "content:\"three\"; http_user_agent; depth:10; "
-                               "content:\"four\"; distance:10; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL\n");
-        goto end;
-    }
-
-    DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
-    DetectContentData *cd2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
-    DetectContentData *huad1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
-    DetectContentData *huad2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->ctx;
-    if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) ||
-        cd2->flags != DETECT_CONTENT_DISTANCE ||
-        memcmp(cd2->content, "four", cd2->content_len) != 0 ||
-        huad1->flags != 0 ||
-        memcmp(huad1->content, "one", huad1->content_len) != 0 ||
-        huad2->flags != DETECT_CONTENT_DEPTH ||
-        memcmp(huad2->content, "three", huad1->content_len) != 0) {
-        goto end;
-    }
-
-    if (DETECT_CONTENT_IS_SINGLE(cd2) ||
-        !DETECT_CONTENT_IS_SINGLE(huad1) ||
-        DETECT_CONTENT_IS_SINGLE(huad2)) {
-        goto end;
-    }
-
-    result = 1;
-
- end:
     DetectEngineCtxFree(de_ctx);
-    return result;
+    PASS;
 }
 
 static int DetectHttpUATest29(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
 
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
+    Signature *s =
+            DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
+                                          "(content:\"one\"; http_user_agent; "
+                                          "content:\"two\"; distance:0; http_user_agent; sid:1;)");
+    FAIL_IF_NULL(s);
+    FAIL_IF_NOT_NULL(s->sm_lists[DETECT_SM_LIST_PMATCH]);
+    FAIL_IF_NULL(s->sm_lists[g_http_ua_buffer_id]);
+
+    DetectContentData *huad1 =
+            (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
+    DetectContentData *huad2 = (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->ctx;
+    FAIL_IF_NOT(huad1->flags == DETECT_CONTENT_RELATIVE_NEXT);
+    FAIL_IF_NOT(memcmp(huad1->content, "one", huad1->content_len) == 0);
+    FAIL_IF_NOT(huad2->flags == DETECT_CONTENT_DISTANCE);
+    FAIL_IF_NOT(memcmp(huad2->content, "two", huad1->content_len) == 0);
 
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"one\"; http_user_agent; "
-                               "content:\"two\"; distance:0; http_user_agent; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
-        printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL\n");
-        goto end;
-    }
-
-    DetectContentData *huad1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
-    DetectContentData *huad2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->ctx;
-    if (huad1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
-        memcmp(huad1->content, "one", huad1->content_len) != 0 ||
-        huad2->flags != DETECT_CONTENT_DISTANCE ||
-        memcmp(huad2->content, "two", huad1->content_len) != 0) {
-        goto end;
-    }
-
-    result = 1;
-
- end:
     DetectEngineCtxFree(de_ctx);
-    return result;
+    PASS;
 }
 
 static int DetectHttpUATest30(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
 
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
+    Signature *s =
+            DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
+                                          "(content:\"one\"; http_user_agent; "
+                                          "content:\"two\"; within:5; http_user_agent; sid:1;)");
+    FAIL_IF_NULL(s);
+    FAIL_IF_NOT_NULL(s->sm_lists[DETECT_SM_LIST_PMATCH]);
+    FAIL_IF_NULL(s->sm_lists[g_http_ua_buffer_id]);
+
+    DetectContentData *huad1 =
+            (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
+    DetectContentData *huad2 = (DetectContentData *)s->sm_lists_tail[g_http_ua_buffer_id]->ctx;
+    FAIL_IF_NOT(huad1->flags == DETECT_CONTENT_RELATIVE_NEXT);
+    FAIL_IF_NOT(memcmp(huad1->content, "one", huad1->content_len) == 0);
+    FAIL_IF_NOT(huad2->flags == DETECT_CONTENT_WITHIN);
+    FAIL_IF_NOT(memcmp(huad2->content, "two", huad1->content_len) == 0);
 
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"one\"; http_user_agent; "
-                               "content:\"two\"; within:5; http_user_agent; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
-        printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL\n");
-        goto end;
-    }
-
-    DetectContentData *huad1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
-    DetectContentData *huad2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->ctx;
-    if (huad1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
-        memcmp(huad1->content, "one", huad1->content_len) != 0 ||
-        huad2->flags != DETECT_CONTENT_WITHIN ||
-        memcmp(huad2->content, "two", huad1->content_len) != 0) {
-        goto end;
-    }
-
-    result = 1;
-
- end:
     DetectEngineCtxFree(de_ctx);
-    return result;
+    PASS;
 }
 
 static int DetectHttpUATest31(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
-
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"one\"; within:5; http_user_agent; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    result = 1;
-
- end:
-    DetectEngineCtxFree(de_ctx);
-    return result;
+    return DetectHttpUATestSigParse("alert tcp any any -> any any "
+                                    "(content:\"one\"; within:5; http_user_agent; sid:1;)",
+            true);
 }
 
 static int DetectHttpUATest32(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
-
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"one\"; http_user_agent; within:5; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list != NULL\n");
-        goto end;
-    }
-
-    result = 1;
-
- end:
-    DetectEngineCtxFree(de_ctx);
-    return result;
+    return DetectHttpUATestSigParse("alert tcp any any -> any any "
+                                    "(content:\"one\"; http_user_agent; within:5; sid:1;)",
+            true);
 }
 
 static int DetectHttpUATest33(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
-
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"one\"; within:5; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    result = 1;
-
- end:
-    DetectEngineCtxFree(de_ctx);
-    return result;
+    return DetectHttpUATestSigParse("alert tcp any any -> any any "
+                                    "(content:\"one\"; within:5; sid:1;)",
+            true);
 }
 
 static int DetectHttpUATest34(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
 
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
+    Signature *s =
+            DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
+                                          "(pcre:/one/V; "
+                                          "content:\"two\"; within:5; http_user_agent; sid:1;)");
+    FAIL_IF_NULL(s);
+    FAIL_IF_NOT_NULL(s->sm_lists[DETECT_SM_LIST_PMATCH]);
+    FAIL_IF_NULL(s->sm_lists[g_http_ua_buffer_id]);
+
+    SigMatch *sm = de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id];
+    FAIL_IF_NULL(sm);
+    FAIL_IF_NOT(sm->type == DETECT_CONTENT);
+    FAIL_IF_NULL(sm->prev);
+    FAIL_IF_NOT(sm->prev->type == DETECT_PCRE);
+
+    DetectPcreData *pd1 = (DetectPcreData *)sm->prev->ctx;
+    DetectContentData *huad2 = (DetectContentData *)sm->ctx;
+    FAIL_IF_NOT(pd1->flags == (DETECT_PCRE_RELATIVE_NEXT));
+    FAIL_IF_NOT(huad2->flags == DETECT_CONTENT_WITHIN);
+    FAIL_IF_NOT(memcmp(huad2->content, "two", huad2->content_len) == 0);
 
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(pcre:/one/V; "
-                               "content:\"two\"; within:5; http_user_agent; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
-        printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id] == NULL ||
-        de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->type != DETECT_CONTENT ||
-        de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev == NULL ||
-        de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->type != DETECT_PCRE) {
-
-        goto end;
-    }
-
-    DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
-    DetectContentData *huad2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->ctx;
-    if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) ||
-        huad2->flags != DETECT_CONTENT_WITHIN ||
-        memcmp(huad2->content, "two", huad2->content_len) != 0) {
-        goto end;
-    }
-
-    result = 1;
-
- end:
     DetectEngineCtxFree(de_ctx);
-    return result;
+    PASS;
 }
 
 static int DetectHttpUATest35(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
 
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
+    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
+                                                 "(content:\"two\"; http_user_agent; "
+                                                 "pcre:/one/VR; sid:1;)");
+    FAIL_IF_NULL(s);
+
+    FAIL_IF_NOT_NULL(s->sm_lists[DETECT_SM_LIST_PMATCH]);
+    SigMatch *sm = s->sm_lists_tail[g_http_ua_buffer_id];
+    FAIL_IF_NULL(sm);
+
+    FAIL_IF_NOT(sm->type == DETECT_PCRE);
+    FAIL_IF_NULL(sm->prev);
+    FAIL_IF_NOT(sm->prev->type == DETECT_CONTENT);
+
+    DetectContentData *huad1 = (DetectContentData *)sm->prev->ctx;
+    DetectPcreData *pd2 = (DetectPcreData *)sm->ctx;
+    FAIL_IF_NOT(pd2->flags == (DETECT_PCRE_RELATIVE));
+    FAIL_IF_NOT(huad1->flags == DETECT_CONTENT_RELATIVE_NEXT);
+    FAIL_IF_NOT(memcmp(huad1->content, "two", huad1->content_len) == 0);
 
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(content:\"two\"; http_user_agent; "
-                               "pcre:/one/VR; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
-        printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id] == NULL ||
-        de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->type != DETECT_PCRE ||
-        de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev == NULL ||
-        de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->type != DETECT_CONTENT) {
-
-        goto end;
-    }
-
-    DetectContentData *huad1 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
-    DetectPcreData *pd2 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->ctx;
-    if (pd2->flags != (DETECT_PCRE_RELATIVE) ||
-        huad1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
-        memcmp(huad1->content, "two", huad1->content_len) != 0) {
-        goto end;
-    }
-
-    result = 1;
-
- end:
     DetectEngineCtxFree(de_ctx);
-    return result;
+    PASS;
 }
 
 static int DetectHttpUATest36(void)
 {
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
 
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
+    Signature *s =
+            DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
+                                          "(pcre:/one/V; "
+                                          "content:\"two\"; distance:5; http_user_agent; sid:1;)");
+    FAIL_IF_NULL(s);
+    FAIL_IF_NOT_NULL(s->sm_lists[DETECT_SM_LIST_PMATCH]);
+    SigMatch *sm = s->sm_lists_tail[g_http_ua_buffer_id];
+    FAIL_IF_NULL(sm);
+
+    FAIL_IF(sm->type != DETECT_CONTENT);
+    FAIL_IF_NULL(sm->prev);
+    FAIL_IF_NOT(sm->prev->type == DETECT_PCRE);
+
+    DetectPcreData *pd1 = (DetectPcreData *)sm->prev->ctx;
+    DetectContentData *huad2 = (DetectContentData *)sm->ctx;
+    FAIL_IF_NOT(pd1->flags == (DETECT_PCRE_RELATIVE_NEXT));
+    FAIL_IF_NOT(huad2->flags == DETECT_CONTENT_DISTANCE);
+    FAIL_IF_NOT(memcmp(huad2->content, "two", huad2->content_len) == 0);
 
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(pcre:/one/V; "
-                               "content:\"two\"; distance:5; http_user_agent; sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("de_ctx->sig_list == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
-        printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL) {
-        printf("de_ctx->sig_list->sm_lists[g_http_ua_buffer_id] == NULL\n");
-        goto end;
-    }
-
-    if (de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id] == NULL ||
-        de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->type != DETECT_CONTENT ||
-        de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev == NULL ||
-        de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->type != DETECT_PCRE) {
-
-        goto end;
-    }
-
-    DetectPcreData *pd1 = (DetectPcreData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->prev->ctx;
-    DetectContentData *huad2 = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[g_http_ua_buffer_id]->ctx;
-    if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) ||
-        huad2->flags != DETECT_CONTENT_DISTANCE ||
-        memcmp(huad2->content, "two", huad2->content_len) != 0) {
-        goto end;
-    }
-
-    result = 1;
-
- end:
     DetectEngineCtxFree(de_ctx);
-    return result;
+    PASS;
 }
 
 static void DetectHttpUARegisterTests(void)