tstRTR0Common.h revision 533240a0b68828716de5ebea7afaf56720aa6ae7
d5d12f5d4455786efdce0a22f09ec396bcb60718vboxsync/* $Id$ */
18589e4730562fe0d41783eb53496bea5a47af97vboxsync/** @file
d5d12f5d4455786efdce0a22f09ec396bcb60718vboxsync * IPRT R0 Testcase - Common header.
18589e4730562fe0d41783eb53496bea5a47af97vboxsync */
18589e4730562fe0d41783eb53496bea5a47af97vboxsync
d5d12f5d4455786efdce0a22f09ec396bcb60718vboxsync/*
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2010 Oracle Corporation
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * available from http://www.virtualbox.org. This file is free software;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * The contents of this file may alternatively be used under the terms
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * of the Common Development and Distribution License Version 1.0
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution, in which case the provisions of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * CDDL are applicable instead of those of the GPL.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * You may elect to license modified versions of this file under the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * terms and conditions of either the GPL or the CDDL or both.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync */
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync#ifndef ___testcase_tstRTR0Common_h
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync#define ___testcase_tstRTR0Common_h
95b10998d08fa1fb5b30d3c2ee25f2fdc2cfa9b2vboxsync
130a462bf46409a9352467033f92e02e4b249879vboxsync#include <iprt/stdarg.h>
130a462bf46409a9352467033f92e02e4b249879vboxsync#include <iprt/string.h>
130a462bf46409a9352467033f92e02e4b249879vboxsync#include "tstRTR0CommonReq.h"
130a462bf46409a9352467033f92e02e4b249879vboxsync
130a462bf46409a9352467033f92e02e4b249879vboxsync
130a462bf46409a9352467033f92e02e4b249879vboxsync/*******************************************************************************
18589e4730562fe0d41783eb53496bea5a47af97vboxsync* Global Variables *
d5d12f5d4455786efdce0a22f09ec396bcb60718vboxsync*******************************************************************************/
18589e4730562fe0d41783eb53496bea5a47af97vboxsync/** Global error buffer used by macros and inline functions in this file. */
18589e4730562fe0d41783eb53496bea5a47af97vboxsyncstatic char g_szErr[2048];
18589e4730562fe0d41783eb53496bea5a47af97vboxsync/** The number of errors reported in this g_szErr. */
d5d12f5d4455786efdce0a22f09ec396bcb60718vboxsyncstatic uint32_t volatile g_cErrors;
d5d12f5d4455786efdce0a22f09ec396bcb60718vboxsync
d5d12f5d4455786efdce0a22f09ec396bcb60718vboxsync
d5d12f5d4455786efdce0a22f09ec396bcb60718vboxsync/**
3145bb572fc92a2c79eed3da96cff1ce2ea7da59vboxsync * Service request handler prolog.
3145bb572fc92a2c79eed3da96cff1ce2ea7da59vboxsync *
3145bb572fc92a2c79eed3da96cff1ce2ea7da59vboxsync * Returns if the input is invalid. Initializes the return packet as well as
3145bb572fc92a2c79eed3da96cff1ce2ea7da59vboxsync * the globals (g_szErr, g_cErrors).
3145bb572fc92a2c79eed3da96cff1ce2ea7da59vboxsync *
d5d12f5d4455786efdce0a22f09ec396bcb60718vboxsync * @param pReqHdr The request packet header.
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync */
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync#define RTR0TESTR0_SRV_REQ_PROLOG_RET(pReqHdr) \
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync do \
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync { \
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync if (!VALID_PTR(pReqHdr)) \
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync return VERR_INVALID_PARAMETER; \
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync \
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync PRTTSTR0REQ pReq = (PRTTSTR0REQ)(pReqHdr); \
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync size_t cchErr = pReqHdr->cbReq - sizeof(pReq->Hdr); \
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync if (cchErr < 32 || cchErr >= 0x10000) \
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync return VERR_INVALID_PARAMETER; \
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync pReq->szMsg[0] = '\0'; \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync \
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync /* Initialize the global buffer. */ \
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync memset(&g_szErr[0], 0, sizeof(g_szErr)); \
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync ASMAtomicWriteU32(&g_cErrors, 0); \
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync } while (0)
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync/**
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync * Service request handler epilog.
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync *
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync * Copies any errors or messages into the request packet.
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync *
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync * @param pReqHdr The request packet header.
c93cb830958ff97bdfff54d92776c1c364a41999vboxsync */
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync#define RTR0TESTR0_SRV_REQ_EPILOG(pReqHdr) \
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync do \
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync { \
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync PRTTSTR0REQ pReq = (PRTTSTR0REQ)(pReqHdr); \
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync size_t cbErr = pReqHdr->cbReq - sizeof(pReq->Hdr); \
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync if (g_szErr[0] && pReq->szMsg[0] != '!') \
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync RTStrCopyEx(pReq->szMsg, (cbErr), g_szErr, sizeof(g_szErr) - 1); \
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync } while (0)
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync/**
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync * Implement the sanity check switch-cases of a service request handler.
0d1b878aabfc7e4fe035c10466387dcfb42cd3aavboxsync */
18589e4730562fe0d41783eb53496bea5a47af97vboxsync#define RTR0TESTR0_IMPLEMENT_SANITY_CASES() \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync case RTTSTR0REQ_SANITY_OK: \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync break; \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync case RTTSTR0REQ_SANITY_FAILURE: \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync RTR0TestR0Error("42failure42%4096s", ""); \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync break
18589e4730562fe0d41783eb53496bea5a47af97vboxsync
18589e4730562fe0d41783eb53496bea5a47af97vboxsync/**
18589e4730562fe0d41783eb53496bea5a47af97vboxsync * Implements the default switch-case of a service request handler.
18589e4730562fe0d41783eb53496bea5a47af97vboxsync * @param uOperation The operation.
18589e4730562fe0d41783eb53496bea5a47af97vboxsync */
18589e4730562fe0d41783eb53496bea5a47af97vboxsync#define RTR0TESTR0_IMPLEMENT_DEFAULT_CASE(uOperation) \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync default: \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync RTR0TestR0Error("Unknown test #%d", (uOperation)); \
3ffde73ed2ec311d260d72a61beede079ccf8cf8vboxsync break
3ffde73ed2ec311d260d72a61beede079ccf8cf8vboxsync
3ffde73ed2ec311d260d72a61beede079ccf8cf8vboxsync
3ffde73ed2ec311d260d72a61beede079ccf8cf8vboxsync/**
3ffde73ed2ec311d260d72a61beede079ccf8cf8vboxsync * Macro for checking the return code of an API in the ring-0 testcase.
3ffde73ed2ec311d260d72a61beede079ccf8cf8vboxsync *
3ffde73ed2ec311d260d72a61beede079ccf8cf8vboxsync * Similar to RTTESTI_CHECK_RC.
3ffde73ed2ec311d260d72a61beede079ccf8cf8vboxsync *
3ffde73ed2ec311d260d72a61beede079ccf8cf8vboxsync * @param rcExpr The expression producing the return code. Only
3ffde73ed2ec311d260d72a61beede079ccf8cf8vboxsync * evaluated once.
3ffde73ed2ec311d260d72a61beede079ccf8cf8vboxsync * @param rcExpect The expected result. Evaluated multiple times.
9d39fac7876e40b270f64af45852a8f792c6aba1vboxsync */
a0f799005156cec8551520c155b2cba9ed1a21abvboxsync#define RTR0TESTR0_CHECK_RC(rcExpr, rcExpect) \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync do { \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync int rcCheck = (rcExpr); \
eb858f71a093a700161e8304d38265672c7c2cccvboxsync if (rcCheck != (rcExpect)) \
eb858f71a093a700161e8304d38265672c7c2cccvboxsync RTR0TestR0Error("line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \
eb858f71a093a700161e8304d38265672c7c2cccvboxsync } while (0)
eb858f71a093a700161e8304d38265672c7c2cccvboxsync
eb858f71a093a700161e8304d38265672c7c2cccvboxsync/**
18589e4730562fe0d41783eb53496bea5a47af97vboxsync * Same as RTR0TESTR0_CHECK_RC + break.
18589e4730562fe0d41783eb53496bea5a47af97vboxsync */
18589e4730562fe0d41783eb53496bea5a47af97vboxsync#define RTR0TESTR0_CHECK_RC_BREAK(rcExpr, rcExpect) \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync if (1) \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync { \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync int rcCheck = (rcExpr); \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync if (rcCheck != (rcExpect)) \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync { \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync RTR0TestR0Error("line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync break; \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync } \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync } else do { } while (0)
3d0f3fda97a66ab12305c585530e045329a185d6vboxsync
18589e4730562fe0d41783eb53496bea5a47af97vboxsync/**
18589e4730562fe0d41783eb53496bea5a47af97vboxsync * Macro for checking the return code of an API in the ring-0 testcase.
18589e4730562fe0d41783eb53496bea5a47af97vboxsync *
18589e4730562fe0d41783eb53496bea5a47af97vboxsync * Similar to RTTESTI_CHECK_MSG
18589e4730562fe0d41783eb53496bea5a47af97vboxsync *
d5d12f5d4455786efdce0a22f09ec396bcb60718vboxsync * @param expr The expression to evaluate.
3145bb572fc92a2c79eed3da96cff1ce2ea7da59vboxsync * @param DetailsArgs Format string + arguments - in paranthesis.
18589e4730562fe0d41783eb53496bea5a47af97vboxsync */
727c92cfe8cb44ec7a1fd977b633db6cdc192000vboxsync#define RTR0TESTR0_CHECK_MSG(expr, DetailsArgs) \
727c92cfe8cb44ec7a1fd977b633db6cdc192000vboxsync do { \
07dfc0801e1df43b76629d72bd2c779ea3195deavboxsync if (!(expr)) \
727c92cfe8cb44ec7a1fd977b633db6cdc192000vboxsync { \
727c92cfe8cb44ec7a1fd977b633db6cdc192000vboxsync RTR0TestR0Error("line %u: expression failed: %s - ", __LINE__, #expr); \
727c92cfe8cb44ec7a1fd977b633db6cdc192000vboxsync RTR0TestR0AppendDetails DetailsArgs; \
727c92cfe8cb44ec7a1fd977b633db6cdc192000vboxsync } \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync } while (0)
d5d12f5d4455786efdce0a22f09ec396bcb60718vboxsync
18589e4730562fe0d41783eb53496bea5a47af97vboxsync/**
18589e4730562fe0d41783eb53496bea5a47af97vboxsync * Same as RTR0TESTR0_CHECK_MSG + break.
a0f799005156cec8551520c155b2cba9ed1a21abvboxsync */
a0f799005156cec8551520c155b2cba9ed1a21abvboxsync#define RTR0TESTR0_CHECK_MSG_BREAK(expr, DetailsArgs) \
a0f799005156cec8551520c155b2cba9ed1a21abvboxsync if (!(expr)) \
a0f799005156cec8551520c155b2cba9ed1a21abvboxsync { \
18589e4730562fe0d41783eb53496bea5a47af97vboxsync RTR0TestR0Error("line %u: expression failed: %s - ", __LINE__, #expr); \
RTR0TestR0AppendDetails DetailsArgs; \
break; \
} else do { } while (0)
/**
* Same as RTR0TESTR0_CHECK_MSG + return @a rcRete.
*/
#define RTR0TESTR0_CHECK_MSG_RET(expr, DetailsArgs, rcRet) \
do { \
if (!(expr)) \
{ \
RTR0TestR0Error("line %u: expression failed: %s - ", __LINE__, #expr); \
RTR0TestR0AppendDetails DetailsArgs; \
return (rcRet); \
} \
} while (0)
/**
* Report an error.
*/
void RTR0TestR0Error(const char *pszFormat, ...)
{
size_t off = RTStrNLen(g_szErr, sizeof(g_szErr) - 1);
size_t cbLeft = sizeof(g_szErr) - off;
if (cbLeft > 10)
{
char *psz = &g_szErr[off];
if (off)
{
*psz++ = '\n';
*psz++ = '\n';
cbLeft -= 2;
}
*psz++ = '!';
cbLeft--;
va_list va;
va_start(va, pszFormat);
RTStrPrintfV(psz, cbLeft, pszFormat, va);
va_end(va);
}
ASMAtomicIncU32(&g_cErrors);
}
/**
* Append error details.
*/
void RTR0TestR0AppendDetails(const char *pszFormat, ...)
{
size_t off = RTStrNLen(g_szErr, sizeof(g_szErr) - 1);
va_list va;
va_start(va, pszFormat);
RTStrPrintfV(&g_szErr[off], sizeof(g_szErr) - off, pszFormat, va);
va_end(va);
}
/**
* Informational message.
*/
void RTR0TestR0Info(const char *pszFormat, ...)
{
size_t off = RTStrNLen(g_szErr, sizeof(g_szErr) - 1);
size_t cbLeft = sizeof(g_szErr) - off;
if (cbLeft > 10)
{
char *psz = &g_szErr[off];
if (off)
{
*psz++ = '\n';
*psz++ = '\n';
cbLeft -= 2;
}
*psz++ = '?';
cbLeft--;
va_list va;
va_start(va, pszFormat);
RTStrPrintfV(psz, cbLeft, pszFormat, va);
va_end(va);
}
}
/**
* Checks if we have any error reports.
*
* @returns true if there are errors, false if none.
*/
bool RTR0TestR0HaveErrors(void)
{
return ASMAtomicUoReadU32(&g_cErrors) > 0;
}
#endif