| /* Copyright 2014 Lieven Govaerts |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef MockHTTP_H |
| #define MockHTTP_H |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif /* __cplusplus */ |
| |
| /* TODO: define defaults, eg HTTP/1.1 in req/resp */ |
| /* TODO: use requests only once, use them in order, use best matching first */ |
| /* TODO: raw requests */ |
| /* TODO: add delay time for accept skt, response */ |
| /* TODO: define all macro's with mh prefix, + create shortcuts with flag to |
| not define this (in case of conflicts with other code ) */ |
| /* TODO: connection level checks: |
| - ssl related: client certificate, handshake successful, |
| - authn: Negotiate, NTLM, Kerberos */ |
| |
| typedef enum mhServerType_t { |
| mhGenericServer, /* Abstract type */ |
| mhGenericProxy, /* Abstract type */ |
| mhHTTPv1, /* Abstract type */ |
| mhHTTPSv1, /* Abstract type */ |
| mhHTTPv11, /* Abstract type */ |
| mhHTTPSv11, /* Abstract type */ |
| mhHTTPv1Server, |
| mhHTTPv11Server, |
| mhHTTPSv1Server, |
| mhHTTPSv11Server, |
| mhHTTPv1Proxy, |
| mhHTTPv11Proxy, |
| mhHTTPSv1Proxy, /* Sets up SSL tunnel on CONNECT request. */ |
| mhHTTPSv11Proxy, /* Sets up SSL tunnel on CONNECT request. */ |
| mhOCSPResponder, |
| } mhServerType_t; |
| |
| typedef enum mhAction_t { |
| mhActionInitiateNone, |
| mhActionInitiateProxyConn, |
| mhActionInitiateSSLTunnel, |
| mhActionSSLRenegotiate, |
| mhActionCloseConnection, |
| } mhAction_t; |
| |
| typedef enum mhClientCertVerification_t { |
| mhCCVerifyNone, |
| mhCCVerifyPeer, |
| mhCCVerifyFailIfNoPeerSet, |
| } mhClientCertVerification_t; |
| |
| typedef enum mhSSLProtocol_t { |
| mhProtoUnspecified = 0x00, |
| mhProtoAllSecure = 0x1E, |
| mhProtoAll = 0xFF, |
| mhProtoSSLv2 = 0x01, |
| mhProtoSSLv3 = 0x02, |
| mhProtoTLSv1 = 0x04, |
| mhProtoTLSv11 = 0x08, |
| mhProtoTLSv12 = 0x10, |
| mhProtoTLSv13 = 0x20, |
| } mhSSLProtocol_t; |
| |
| typedef enum mhThreading_t { |
| mhThreadMain, |
| mhThreadSeparate, |
| } mhThreading_t; |
| |
| typedef struct mhRequest_t mhRequest_t; |
| typedef struct mhRequestMatcher_t mhRequestMatcher_t; |
| typedef struct mhResponse_t mhResponse_t; |
| typedef struct mhServCtx_t mhServCtx_t; |
| typedef struct mhReqMatcherBldr_t mhReqMatcherBldr_t; |
| typedef struct mhConnMatcherBldr_t mhConnMatcherBldr_t; |
| typedef struct mhServerSetupBldr_t mhServerSetupBldr_t; |
| typedef struct mhResponseBldr_t mhResponseBldr_t; |
| |
| #define DEFAULT_SERVER_ID "server" |
| #define DEFAULT_PROXY_ID "proxy" |
| |
| /****************************************************************************** |
| * MockHTTPinC API * |
| * --------------- * |
| * This is the main API of the MockHTTPinC library. Most if the API consists * |
| * of macro's providing a fluent-like API (as much as that's possible in C). * |
| ******************************************************************************/ |
| |
| /* Note: the variadic macro's used here require C99. */ |
| /* TODO: we can provide xxx1(x), xxx2(x,y)... macro's for C89 compilers */ |
| |
| /** |
| * Initialize the MockHTTP library. To be used like this: |
| * |
| * MockHTTP *mh = mhInit(); |
| * InitMockHTTP(mh) |
| * WithHTTPServer(WithPort(30080)) |
| * EndInit |
| */ /* TODO: rename */ |
| #define InitMockServers(mh)\ |
| {\ |
| MockHTTP *__mh = mh;\ |
| mhServCtx_t *__servctx = NULL; |
| |
| /* TODO: Variadic macro's require at least one argument, otherwise compilation |
| will fail. We should be able to initiate a server with all default params. */ |
| |
| #define SetupServer(...)\ |
| __servctx = mhNewServer(__mh);\ |
| mhConfigServer(__servctx, __VA_ARGS__, NULL);\ |
| mhStartServer(__servctx); |
| |
| /* Setup a HTTP server */ |
| |
| /* WithHTTP defaults to HTTP v1.1 */ |
| #define WithHTTP\ |
| mhSetServerType(__servctx, mhHTTPv11) |
| |
| #define WithHTTPv1\ |
| mhSetServerType(__servctx, mhHTTPv1) |
| |
| #define WithHTTPv11\ |
| mhSetServerType(__servctx, mhHTTPv11) |
| |
| /* Setup a HTTPS server */ |
| |
| /* WithHTTPS defaults to HTTPS v1.1 */ |
| #define WithHTTPS\ |
| mhSetServerType(__servctx, mhHTTPSv11) |
| #define WithHTTPSv1\ |
| mhSetServerType(__servctx, mhHTTPSv1) |
| #define WithHTTPSv11\ |
| mhSetServerType(__servctx, mhHTTPSv11) |
| |
| /* Give the server a name, so it can be found (optional, only needed when |
| using multiple servers and requiring post-init configuration) */ |
| #define WithID(serverID)\ |
| mhSetServerID(__servctx, serverID) |
| |
| /* Specify on which TCP port the server should listen. */ |
| #define WithPort(port)\ |
| mhSetServerPort(__servctx, port) |
| |
| /* Specify which protocol the server should choose */ |
| #define WithProtocol(protocol)\ |
| mhSetServerProtocol(__servctx, protocol) |
| |
| /* Set the maximum number of requests per connection. Default is unlimited */ |
| #define WithMaxKeepAliveRequests(maxRequests)\ |
| mhSetServerMaxRequestsPerConn(__servctx, maxRequests) |
| |
| /* Runs the mock server and proxy in separate threads, use this when testing a |
| blocking http client library */ |
| /* EXPERIMENTAL: this feature doesn't work in all cases, can cause crashes! */ |
| #define InSeparateThread\ |
| mhSetServerThreading(__servctx, mhThreadSeparate) |
| |
| /* Runs the mock server and proxy in the main thread, use this when testing a |
| non-blocking http client library. |
| This is the default. */ |
| #define InMainThread\ |
| mhSetServerThreading(__servctx, mhThreadMain) |
| |
| #define SetupProxy(...)\ |
| __servctx = mhNewProxy(__mh);\ |
| mhConfigServer(__servctx, __VA_ARGS__, NULL);\ |
| mhStartServer(__servctx); |
| |
| #define SetupOCSPResponder(...)\ |
| __servctx = mhNewOCSPResponder(__mh);\ |
| mhConfigServer(__servctx, __VA_ARGS__, NULL);\ |
| mhStartServer(__servctx); |
| |
| #define ConfigServerWithID(serverID, ...)\ |
| __servctx = mhFindServerByID(__mh, serverID);\ |
| mhConfigServer(__servctx, __VA_ARGS__, NULL); |
| /** |
| * HTTPS Server configuration options |
| */ |
| #define WithCertificateFilesPrefix(prefix)\ |
| mhSetServerCertPrefix(__servctx, prefix) |
| #define WithCertificateKeyFile(keyFile)\ |
| mhSetServerCertKeyFile(__servctx, keyFile) |
| #define WithCertificateKeyPassPhrase(passphrase)\ |
| mhSetServerCertKeyPassPhrase(__servctx, passphrase) |
| #define WithCertificateFiles(...)\ |
| mhAddServerCertFiles(__servctx, __VA_ARGS__, NULL) |
| #define WithCertificateFileArray(files)\ |
| mhAddServerCertFileArray(__servctx, files) |
| #define WithOptionalClientCertificate\ |
| mhSetServerRequestClientCert(__servctx, mhCCVerifyPeer) |
| #define WithRequiredClientCertificate\ |
| mhSetServerRequestClientCert(__servctx,\ |
| mhCCVerifyFailIfNoPeerSet) |
| #define WithSSLv2 mhAddSSLProtocol(__servctx, mhProtoSSLv2) |
| #define WithSSLv3 mhAddSSLProtocol(__servctx, mhProtoSSLv3) |
| #define WithTLSv1 mhAddSSLProtocol(__servctx, mhProtoTLSv1) |
| #define WithTLSv11 mhAddSSLProtocol(__servctx, mhProtoTLSv11) |
| #define WithTLSv12 mhAddSSLProtocol(__servctx, mhProtoTLSv12) |
| |
| #define WithOCSPEnabled mhSetServerEnableOCSP(__servctx) |
| |
| /* Finalize MockHTTP library initialization */ |
| #define EndInit\ |
| } |
| /** |
| * Stub requests to the proxy or server, return canned responses. Define the |
| * expected results before starting the test, so the server can exit early |
| * when expectations can't be matched. These macro's should be used like this: |
| * |
| * Given(mh) |
| * GETRequest(URLEqualTo("/index.html")) |
| * Respond(WithCode(200), WithBody("body")) |
| * Expect |
| * AllRequestsReceivedOnce |
| * EndGiven |
| */ |
| #define Given(mh)\ |
| {\ |
| MockHTTP *__mh = mh;\ |
| mhResponse_t *__resp;\ |
| mhRequestMatcher_t *__rm;\ |
| mhServCtx_t *__servctx = mhFindServerByID(__mh, DEFAULT_SERVER_ID); |
| |
| |
| #define RequestsReceivedByServer\ |
| __servctx = mhFindServerByID(__mh, DEFAULT_SERVER_ID); |
| |
| #define RequestsReceivedByProxy\ |
| __servctx = mhFindServerByID(__mh, DEFAULT_PROXY_ID); |
| |
| /* Stub a GET request */ |
| #define GETRequest(...)\ |
| __rm = mhGivenRequest(__mh, MethodEqualTo("GET"),\ |
| __VA_ARGS__, NULL);\ |
| mhPushRequest(__mh, __servctx, __rm); |
| |
| /* Stub a POST request */ |
| #define POSTRequest(...)\ |
| __rm = mhGivenRequest(__mh, MethodEqualTo("POST"),\ |
| __VA_ARGS__, NULL);\ |
| mhPushRequest(__mh, __servctx, __rm); |
| |
| /* Stub a PUT request */ |
| #define PUTRequest(...)\ |
| __rm = mhGivenRequest(__mh, MethodEqualTo("PUT"),\ |
| __VA_ARGS__, NULL);\ |
| mhPushRequest(__mh, __servctx, __rm); |
| |
| /* Stub a DELETE request */ |
| #define DELETERequest(...)\ |
| __rm = mhGivenRequest(__mh, MethodEqualTo("DELETE"),\ |
| __VA_ARGS__, NULL);\ |
| mhPushRequest(__mh, __servctx, __rm); |
| |
| /* Stub a HEAD request */ |
| #define HEADRequest(...)\ |
| __rm = mhGivenRequest(__mh, MethodEqualTo("HEAD"),\ |
| __VA_ARGS__, NULL);\ |
| mhPushRequest(__mh, __servctx, __rm); |
| |
| /* Stub an OPTIONS request */ |
| #define OPTIONSRequest(...)\ |
| __rm = mhGivenRequest(__mh, MethodEqualTo("OPTIONS"),\ |
| __VA_ARGS__, NULL);\ |
| mhPushRequest(__mh, __servctx, __rm); |
| |
| /* Stub a HTTP request, first parameter is HTTP method (e.g. PROPFIND) */ |
| #define HTTPRequest(...)\ |
| __rm = mhGivenRequest(__mh, __VA_ARGS__, NULL);\ |
| mhPushRequest(__mh, __servctx, __rm); |
| |
| /* Match the request's METHOD equal to EXP */ |
| #define MethodEqualTo(exp)\ |
| mhMatchMethodEqualTo(__mh, (exp)) |
| |
| /* Match the request's URL equal to EXP */ |
| #define URLEqualTo(exp)\ |
| mhMatchURLEqualTo(__mh, (exp)) |
| |
| /* Match the request's URL not equal to EXP */ |
| #define URLNotEqualTo(exp)\ |
| mhMatchURLNotEqualTo(__mh, (exp)) |
| |
| /* Match the request's body, ignoring transfer encoding (e.g. chunked) */ |
| #define BodyEqualTo(x)\ |
| mhMatchBodyEqualTo(__mh, (x)) |
| |
| /* Match the request's body as raw data (e.g. including the chunk header). */ |
| #define RawBodyEqualTo(x)\ |
| mhMatchRawBodyEqualTo(__mh, (x)) |
| |
| /* Match a request header's value. */ |
| #define HeaderEqualTo(h, v)\ |
| mhMatchHeaderEqualTo(__mh, (h), (v)) |
| |
| /* Match a request with the specified header set */ |
| #define HeaderSet(h)\ |
| mhMatchHeaderNotEqualTo(__mh, (h), NULL) |
| |
| /* Match a request header's value. */ |
| #define HeaderNotEqualTo(h, v)\ |
| mhMatchHeaderNotEqualTo(__mh, (h), (v)) |
| |
| /* Match a request with the specified header not set */ |
| #define HeaderNotSet(h)\ |
| mhMatchHeaderEqualTo(__mh, (h), NULL) |
| |
| /* These are lower level tests, probably only interesting when testing the |
| protocol layer. */ |
| /* Match a request's non-chunked body. IOW, a chunked body won't match. */ |
| #define NotChunkedBodyEqualTo(x)\ |
| mhMatchNotChunkedBodyEqualTo(__mh, (x)) |
| |
| /* Match a request's body which should be chunked encoded, after decoding |
| e.g. ChunkedBodyEqualTo("chunk1chunk2") */ |
| #define ChunkedBodyEqualTo(x)\ |
| mhMatchChunkedBodyEqualTo(__mh, (x)) |
| |
| /* Match a request's body which should be chunked encoded with a list of |
| chunks. |
| e.g. BodyChunksEqualTo("chunk1", "chunk2") */ |
| #define BodyChunksEqualTo(...)\ |
| mhMatchBodyChunksEqualTo(__mh, __VA_ARGS__, NULL) |
| |
| #define IncompleteBodyEqualTo(x)\ |
| mhMatchIncompleteBodyEqualTo(__mh, (x)) |
| |
| #define ClientCertificateIsValid\ |
| mhMatchClientCertValid(__mh) |
| |
| #define ClientCertificateCNEqualTo(x)\ |
| mhMatchClientCertCNEqualTo(__mh, (x)) |
| |
| #define MatchAny\ |
| mhMatchAny(__mh) |
| |
| |
| /* Connection-level aspect matching */ |
| #define ConnectionSetup(...)\ |
| mhGivenConnSetup(__mh, __VA_ARGS__, NULL); |
| |
| /* TODO: http version, conditional, */ |
| /* When a request matches, the server will respond with the response defined |
| here. */ |
| #define DefaultResponse(...)\ |
| __resp = mhNewDefaultResponse(__mh);\ |
| mhConfigResponse(__resp, __VA_ARGS__, NULL); |
| |
| #define Respond(...)\ |
| __resp = mhNewResponseForRequest(__mh, __servctx, __rm);\ |
| mhConfigResponse(__resp, __VA_ARGS__, NULL); |
| |
| #define SetupSSLTunnel\ |
| mhNewActionForRequest(__mh, __servctx, __rm,\ |
| mhActionInitiateSSLTunnel); |
| #define SSLRenegotiate\ |
| mhNewActionForRequest(__mh, __servctx, __rm,\ |
| mhActionSSLRenegotiate); |
| #define CloseConnection\ |
| mhNewActionForRequest(__mh, __servctx, __rm,\ |
| mhActionCloseConnection); |
| /* Set the HTTP response code. Default: 200 OK */ |
| #define WithCode(x)\ |
| mhRespSetCode(__resp, (x)) |
| |
| /* Set a header/value pair */ |
| #define WithHeader(h,v)\ |
| mhRespAddHeader(__resp, (h), (v)) |
| |
| /* Set the body of the response. This will automatically add a Content-Length |
| header */ |
| #define WithBody(x)\ |
| mhRespSetBody(__resp, (x)) |
| |
| /* Set the chunked body of a response. This will automatically add a |
| Transfer-Encoding: chunked header. |
| e.g. WithChunkedBody("chunk1", "chunk2") */ |
| #define WithChunkedBody(...)\ |
| mhRespSetChunkedBody(__resp, __VA_ARGS__, NULL) |
| |
| /* Use the body of the request as the body of the response. */ |
| #define WithRequestBody\ |
| mhRespSetUseRequestBody(__resp) |
| |
| /* If HEADER is set on the request, set it with its value on the response */ |
| #define WithRequestHeader(header)\ |
| mhRespSetUseRequestHeader(__resp, header) |
| |
| /* Adds a "Connection: close" header to the response, makes the mock server |
| close the connection after sending the response. */ |
| #define WithConnectionCloseHeader\ |
| mhRespSetConnCloseHdr(__resp) |
| |
| /* Use the provided string as raw response data. The response need not be |
| valid HTTP.*/ |
| #define WithRawData(data, len)\ |
| mhRespSetRawData(__resp, (data), (len)) |
| |
| #define WithBodyRepeatedPattern(pattern, repeat)\ |
| mhRespSetBodyPattern(__resp, (pattern), (repeat)) |
| |
| #define EndGiven\ |
| /* Assign local variables to NULL to avoid 'variable unused' |
| warnings. */\ |
| (void)__resp; (void)__rm; (void)__mh;\ |
| } |
| |
| |
| #define OnConditionThat(condition, builder)\ |
| mhSetOnConditionThat(condition, builder) |
| |
| |
| /* Set expectations for a series of requests */ |
| #define Expect |
| |
| /* Specify that all stubbed requests should arrive at the server exactly once. |
| The order how they are received is not important for this expectation. */ |
| #define AllRequestsReceivedOnce\ |
| mhExpectAllRequestsReceivedOnce(__mh); |
| |
| /* Specify that all stubbed requests should arrive at the server exactly once |
| and in the order in which they were defined. */ |
| #define AllRequestsReceivedInOrder\ |
| mhExpectAllRequestsReceivedInOrder(__mh); |
| |
| /** |
| * After the test was completed, check the results and match the expectations |
| * defined upfront, and verify other aspects of the mock server(s). |
| * To be used like this: |
| * Verify(mh) |
| * ASSERT(VerifyAllExpectationsOk); |
| * ASSERT(GETRequestReceivedFor(URLEqualTo("/index.html")); |
| * EndVerify |
| * |
| * Note: the ASSERT macro is not included in this library, but should be |
| * provided by an external unit testing library. |
| */ |
| #define Verify(mh)\ |
| {\ |
| MockHTTP *__mh = mh; |
| |
| /* Verify that all stubbed requests where received at least once, order not |
| important */ |
| #define VerifyAllRequestsReceived\ |
| mhVerifyAllRequestsReceived(__mh) |
| |
| /* Verify that all stubbed requests where received once by the serer, in the |
| order in which they were defined. */ |
| #define VerifyAllRequestsReceivedInOrder\ |
| mhVerifyAllRequestsReceivedInOrder(__mh) |
| |
| /* Verify that all expectations in the Except section where matched. |
| This macro will fail (return NO) when no expectations were defined, as this |
| is likely an oversight in creation of the test */ |
| #define VerifyAllExpectationsOk\ |
| mhVerifyAllExpectationsOk(__mh) |
| |
| #define VerifyConnectionSetupOk\ |
| mhVerifyConnectionSetupOk(__mh) |
| |
| #define VerifyStats\ |
| mhVerifyStatistics(__mh) |
| |
| /* Return the last error message, if any. |
| e.g. ASSERT_MSG(ErrorMessage, VerifyAllExpectationsOk); */ |
| #define ErrorMessage\ |
| mhGetLastErrorString(__mh) |
| |
| /* End of test result verification section */ |
| #define EndVerify\ |
| } |
| |
| typedef enum mhOCSPRespnseStatus_t { |
| mhOCSPRespnseStatusSuccessful, |
| mhOCSPRespnseStatusMalformedRequest, |
| mhOCSPRespnseStatusInternalError, |
| mhOCSPRespnseStatusTryLater, |
| mhOCSPRespnseStatusSigRequired, |
| mhOCSPRespnseStatusUnauthorized, |
| } mhOCSPRespnseStatus_t; |
| |
| /* Stub a OCSP request (certificate status request). */ |
| #define OCSPRequest(...)\ |
| __rm = mhGivenOCSPRequest(__mh, __VA_ARGS__, NULL);\ |
| mhPushRequest(__mh, __servctx, __rm); |
| |
| #define WithOCSPResponseStatus(status)\ |
| mhRespOCSPResponseStatus(__resp, (status)) |
| |
| |
| typedef struct mhStats_t { |
| /* Number of requests received and read by the server. This does not include |
| pipelined requests that were received after the server closed the socket. |
| */ |
| unsigned int requestsReceived; |
| |
| /* Number of requests the server responded to. This includes default |
| responses or 500 Internal Server Error responses */ |
| unsigned int requestsResponded; |
| |
| /* Number of requests for which a match was found. */ |
| unsigned int requestsMatched; |
| |
| /* Number of requests for which no match was found. */ |
| unsigned int requestsNotMatched; |
| } mhStats_t; |
| |
| typedef unsigned long mhError_t; |
| |
| /* Everything ok */ |
| #define MOCKHTTP_NO_ERROR 0 |
| /* Responses pending in queueu but can't be sent now */ |
| #define MOCKHTTP_WAITING 1 |
| /* Maximum timeout exceeded when waiting for a complete request */ |
| #define MOCKHTTP_TIMEOUT 2 |
| /* There was a problem while setting up the test environment */ |
| #define MOCKHTTP_SETUP_FAILED 100 |
| /* There was a problem while running a test */ |
| #define MOCKHTTP_TEST_FAILED 101 |
| |
| typedef struct MockHTTP MockHTTP; |
| |
| /** |
| * Initialize a MockHTTP context. |
| * |
| * This context manages the server(s), stubs, expectations of a test. It also |
| * manages one pool of memory which only gets freed when this context is |
| * cleaned up, so a MockHTTP context should be short-lived. |
| */ |
| MockHTTP *mhInit(void); |
| |
| /** |
| * Cleans up a MockHTTP context and all of its associated resources. |
| */ |
| void mhCleanup(MockHTTP *mh); |
| |
| /** |
| * Runs the server loop as long as there are requests to receive or responses |
| * to send. |
| * |
| * Returns: |
| * MOCKHTTP_NO_ERROR if there's nothing more to be done at this time |
| * MOCKHTTP_WAITING if there's nothing more to be done at this time, but there |
| * are still pending responses with a certain delay |
| */ |
| mhError_t mhRunServerLoopCompleteRequests(MockHTTP *mh); |
| |
| /** |
| * Runs the server loop as long as there are requests to receive or responses |
| * to send. This function will wait for requests to arrive completely, with |
| * a maximum delay of 15 seconds. |
| * |
| * Returns: |
| * MOCKHTTP_NO_ERROR if there's nothing more to be done at this time |
| * MOCKHTTP_TIMEOUT maximum timeout exceeded when waiting for a complete |
| * request |
| */ |
| mhError_t mhRunServerLoop(MockHTTP *mh); |
| |
| /** |
| * Get the actual port number on which the server is listening. |
| */ |
| apr_port_t mhServerPortNr(const MockHTTP *mh); |
| |
| /** |
| * Get the actual port number on which the proxy is listening. |
| */ |
| apr_port_t mhProxyPortNr(const MockHTTP *mh); |
| |
| /** |
| * Get the actual port number on which server with id serverID is listening. |
| */ |
| apr_port_t mhServerByIDPortNr(const MockHTTP *mh, const char *serverID); |
| |
| |
| /****************************************************************************** |
| * Semi-public API * |
| * --------------- * |
| * These are the functions that are used by the public API macro's. * |
| * While they're tecnically part of the API (they have to be because we use * |
| * macro's), we've made no effort to make them easy to use. * |
| ******************************************************************************/ |
| |
| /** |
| The following functions should not be used directly, as they can be quite |
| complex to use. Use the macro's instead. |
| **/ |
| mhServCtx_t *mhNewServer(MockHTTP *mh); |
| mhServCtx_t *mhNewProxy(MockHTTP *mh); |
| mhServCtx_t *mhNewOCSPResponder(MockHTTP *mh); |
| mhServCtx_t *mhFindServerByID(const MockHTTP *mh, const char *serverID); |
| void mhConfigServer(mhServCtx_t *ctx, ...); |
| void mhStartServer(mhServCtx_t *ctx); |
| void mhStopServer(mhServCtx_t *ctx); |
| mhServerSetupBldr_t *mhSetServerID(mhServCtx_t *ctx, const char *serverID); |
| mhServerSetupBldr_t *mhSetServerPort(mhServCtx_t *ctx, unsigned int port); |
| mhServerSetupBldr_t *mhSetServerProtocol(mhServCtx_t *ctx, const char *protocols); |
| mhServerSetupBldr_t *mhSetServerType(mhServCtx_t *ctx, mhServerType_t type); |
| mhServerSetupBldr_t *mhSetServerThreading(mhServCtx_t *ctx, |
| mhThreading_t threading); |
| mhServerSetupBldr_t *mhSetServerMaxRequestsPerConn(mhServCtx_t *ctx, |
| unsigned int maxRequests); |
| mhServerSetupBldr_t *mhSetServerCertPrefix(mhServCtx_t *ctx, const char *prefix); |
| mhServerSetupBldr_t *mhSetServerCertKeyFile(mhServCtx_t *ctx, |
| const char *keyFile); |
| mhServerSetupBldr_t *mhSetServerCertKeyPassPhrase(mhServCtx_t *ctx, |
| const char *passphrase); |
| mhServerSetupBldr_t *mhAddServerCertFiles(mhServCtx_t *ctx, ...); |
| mhServerSetupBldr_t *mhAddServerCertFileArray(mhServCtx_t *ctx, |
| const char **certFiles); |
| mhServerSetupBldr_t *mhSetServerRequestClientCert(mhServCtx_t *ctx, |
| mhClientCertVerification_t v); |
| mhServerSetupBldr_t *mhSetServerEnableOCSP(mhServCtx_t *ctx); |
| |
| mhServerSetupBldr_t *mhAddSSLProtocol(mhServCtx_t *ctx, mhSSLProtocol_t proto); |
| |
| /* Define request stubs */ |
| mhRequestMatcher_t *mhGivenRequest(MockHTTP *mh, ...); |
| mhRequestMatcher_t *mhGivenOCSPRequest(MockHTTP *mh, ...); |
| |
| /* Request matching functions */ |
| mhReqMatcherBldr_t *mhMatchURLEqualTo(const MockHTTP *mh, |
| const char *expected); |
| mhReqMatcherBldr_t *mhMatchURLNotEqualTo(const MockHTTP *mh, |
| const char *expected); |
| mhReqMatcherBldr_t *mhMatchMethodEqualTo(const MockHTTP *mh, |
| const char *expected); |
| mhReqMatcherBldr_t *mhMatchBodyEqualTo(const MockHTTP *mh, |
| const char *expected); |
| mhReqMatcherBldr_t *mhMatchRawBodyEqualTo(const MockHTTP *mh, |
| const char *expected); |
| mhReqMatcherBldr_t *mhMatchIncompleteBodyEqualTo(const MockHTTP *mh, |
| const char *expected); |
| /* Network level matching functions, for testing of http libraries */ |
| mhReqMatcherBldr_t *mhMatchBodyNotChunkedEqualTo(const MockHTTP *mh, |
| const char *expected); |
| mhReqMatcherBldr_t *mhMatchChunkedBodyEqualTo(const MockHTTP *mh, |
| const char *expected); |
| mhReqMatcherBldr_t *mhMatchBodyChunksEqualTo(const MockHTTP *mh, ...); |
| mhReqMatcherBldr_t *mhMatchHeaderEqualTo(const MockHTTP *mh, |
| const char *hdr, const char *value); |
| mhReqMatcherBldr_t *mhMatchHeaderNotEqualTo(const MockHTTP *mh, |
| const char *hdr, const char *value); |
| |
| void mhGivenConnSetup(MockHTTP *mh, ...); |
| mhConnMatcherBldr_t *mhMatchClientCertCNEqualTo(const MockHTTP *mh, |
| const char *expected); |
| mhConnMatcherBldr_t *mhMatchClientCertValid(const MockHTTP *mh); |
| /* TODO: make this a generic matcher */ |
| mhReqMatcherBldr_t *mhMatchAny(const MockHTTP *mh); |
| |
| mhResponse_t *mhNewResponseForRequest(MockHTTP *mh, mhServCtx_t *ctx, |
| mhRequestMatcher_t *rm); |
| void mhConfigResponse(mhResponse_t *resp, ...); |
| mhResponse_t *mhNewDefaultResponse(MockHTTP *mh); |
| void mhNewActionForRequest(MockHTTP *mh, mhServCtx_t *ctx, |
| mhRequestMatcher_t *rm, mhAction_t action); |
| |
| mhResponseBldr_t *mhRespSetCode(mhResponse_t *resp, unsigned int status); |
| mhResponseBldr_t *mhRespAddHeader(mhResponse_t *resp, const char *header, |
| const char *value); |
| mhResponseBldr_t *mhRespSetConnCloseHdr(mhResponse_t *resp); |
| mhResponseBldr_t *mhRespSetUseRequestHeader(mhResponse_t *resp, |
| const char *header); |
| mhResponseBldr_t *mhRespSetBody(mhResponse_t *resp, const char *body); |
| mhResponseBldr_t *mhRespSetChunkedBody(mhResponse_t *resp, ...); |
| mhResponseBldr_t *mhRespSetUseRequestBody(mhResponse_t *resp); |
| mhResponseBldr_t *mhRespSetRawData(mhResponse_t *resp, const char *raw_data, |
| size_t length); |
| mhResponseBldr_t *mhRespSetBodyPattern(mhResponse_t *resp, const char *pattern, |
| unsigned int n); |
| mhResponseBldr_t * |
| mhRespOCSPResponseStatus(mhResponse_t *resp, mhOCSPRespnseStatus_t status); |
| |
| const void *mhSetOnConditionThat(int condition, void *builder); |
| |
| /* Define request/response pairs */ |
| void mhPushRequest(MockHTTP *mh, mhServCtx_t *ctx, mhRequestMatcher_t *rm); |
| |
| /* Define expectations */ |
| void mhExpectAllRequestsReceivedOnce(MockHTTP *mh); |
| void mhExpectAllRequestsReceivedInOrder(MockHTTP *mh); |
| |
| /* Verify */ |
| int mhVerifyAllRequestsReceived(const MockHTTP *mh); |
| int mhVerifyAllRequestsReceivedInOrder(const MockHTTP *mh); |
| int mhVerifyAllRequestsReceivedOnce(const MockHTTP *mh); |
| int mhVerifyAllExpectationsOk(const MockHTTP *mh); |
| int mhVerifyConnectionSetupOk(const MockHTTP *mh); |
| mhStats_t *mhVerifyStatistics(const MockHTTP *mh); |
| const char *mhGetLastErrorString(const MockHTTP *mh); |
| |
| |
| mhError_t mhInitHTTPSserver(MockHTTP *mh, ...); |
| |
| #define MOCKHTTP_VERSION 0.2.0 |
| |
| #ifdef __cplusplus |
| } |
| #endif /* __cplusplus */ |
| |
| #endif /* MockHTTP_H */ |