VirtualBox

source: vbox/trunk/src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp@ 56301

Last change on this file since 56301 was 55969, checked in by vboxsync, 10 years ago

Removed unnecessary LOG_INSTANCE definitions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.0 KB
Line 
1/* $Id: tstGuestCtrlParseBuffer.cpp 55969 2015-05-20 14:50:23Z vboxsync $ */
2/** @file
3 * Output stream parsing test cases.
4 */
5
6/*
7 * Copyright (C) 2011-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_ENABLED
19#define LOG_GROUP LOG_GROUP_MAIN
20#include <VBox/log.h>
21
22#include "../include/GuestCtrlImplPrivate.h"
23
24using namespace com;
25
26#include <iprt/env.h>
27#include <iprt/test.h>
28#include <iprt/stream.h>
29
30#ifndef BYTE
31# define BYTE uint8_t
32#endif
33
34typedef struct VBOXGUESTCTRL_BUFFER_VALUE
35{
36 char *pszValue;
37} VBOXGUESTCTRL_BUFFER_VALUE, *PVBOXGUESTCTRL_BUFFER_VALUE;
38typedef std::map< RTCString, VBOXGUESTCTRL_BUFFER_VALUE > GuestBufferMap;
39typedef std::map< RTCString, VBOXGUESTCTRL_BUFFER_VALUE >::iterator GuestBufferMapIter;
40typedef std::map< RTCString, VBOXGUESTCTRL_BUFFER_VALUE >::const_iterator GuestBufferMapIterConst;
41
42char szUnterm1[] = { 'a', 's', 'd', 'f' };
43char szUnterm2[] = { 'f', 'o', 'o', '3', '=', 'b', 'a', 'r', '3' };
44
45static struct
46{
47 const char *pbData;
48 size_t cbData;
49 uint32_t uOffsetStart;
50 uint32_t uOffsetAfter;
51 uint32_t uMapElements;
52 int iResult;
53} aTestBlock[] =
54{
55 /*
56 * Single object parsing.
57 * An object is represented by one or multiple key=value pairs which are
58 * separated by a single "\0". If this termination is missing it will be assumed
59 * that we need to collect more data to do a successful parsing.
60 */
61 /* Invalid stuff. */
62 { NULL, 0, 0, 0, 0, VERR_INVALID_POINTER },
63 { NULL, 512, 0, 0, 0, VERR_INVALID_POINTER },
64 { "", 0, 0, 0, 0, VERR_INVALID_PARAMETER },
65 { "", 0, 0, 0, 0, VERR_INVALID_PARAMETER },
66 { "foo=bar1", 0, 0, 0, 0, VERR_INVALID_PARAMETER },
67 { "foo=bar2", 0, 50, 50, 0, VERR_INVALID_PARAMETER },
68 /* Empty buffers. */
69 { "", 1, 0, 1, 0, VINF_SUCCESS },
70 { "\0", 1, 0, 1, 0, VINF_SUCCESS },
71 /* Unterminated values (missing "\0"). */
72 { "test1", sizeof("test1"), 0, 0, 0, VERR_MORE_DATA },
73 { "test2=", sizeof("test2="), 0, 0, 0, VERR_MORE_DATA },
74 { "test3=test3", sizeof("test3=test3"), 0, 0, 0, VERR_MORE_DATA },
75 { "test4=test4\0t41", sizeof("test4=test4\0t41"), 0, sizeof("test4=test4\0") - 1, 1, VERR_MORE_DATA },
76 { "test5=test5\0t51=t51", sizeof("test5=test5\0t51=t51"), 0, sizeof("test5=test5\0") - 1, 1, VERR_MORE_DATA },
77 /* Next block unterminated. */
78 { "t51=t51\0t52=t52\0\0t53=t53", sizeof("t51=t51\0t52=t52\0\0t53=t53"), 0, sizeof("t51=t51\0t52=t52\0") - 1, 2, VINF_SUCCESS },
79 { "test6=test6\0\0t61=t61", sizeof("test6=test6\0\0t61=t61"), 0, sizeof("test6=test6\0") - 1, 1, VINF_SUCCESS },
80 /* Good stuff. */
81 { "test61=\0test611=test611\0", sizeof("test61=\0test611=test611\0"), 0, sizeof("test61=\0test611=test611\0") - 1, 2, VINF_SUCCESS },
82 { "test7=test7\0\0", sizeof("test7=test7\0\0"), 0, sizeof("test7=test7\0") - 1, 1, VINF_SUCCESS },
83 { "test8=test8\0t81=t81\0\0", sizeof("test8=test8\0t81=t81\0\0"), 0, sizeof("test8=test8\0t81=t81\0") - 1, 2, VINF_SUCCESS },
84 /* Good stuff, but with a second block -- should be *not* taken into account since
85 * we're only interested in parsing/handling the first object. */
86 { "t9=t9\0t91=t91\0\0t92=t92\0\0", sizeof("t9=t9\0t91=t91\0\0t92=t92\0\0"), 0, sizeof("t9=t9\0t91=t91\0") - 1, 2, VINF_SUCCESS },
87 /* Nasty stuff. */
88 { "äöü=fäö\0\0", sizeof("äöü=fäö\0\0"), 0, sizeof("äöü=fäö\0") - 1, 1, VINF_SUCCESS },
89 { "äöü=fäö\0ööö=äää", sizeof("äöü=fäö\0ööö=äää"), 0, sizeof("äöü=fäö\0") - 1, 1, VERR_MORE_DATA },
90 /* Some "real world" examples. */
91 { "hdr_id=vbt_stat\0hdr_ver=1\0name=foo.txt\0\0",
92 sizeof("hdr_id=vbt_stat\0hdr_ver=1\0name=foo.txt\0\0"),
93 0, sizeof("hdr_id=vbt_stat\0hdr_ver=1\0name=foo.txt\0") - 1,
94 3, VINF_SUCCESS }
95};
96
97static struct
98{
99 const char *pbData;
100 size_t cbData;
101 /** Number of data blocks retrieved. These are separated by "\0\0". */
102 uint32_t uNumBlocks;
103 /** Overall result when done parsing. */
104 int iResult;
105} aTestStream[] =
106{
107 /* No blocks. */
108 { "\0\0\0\0", sizeof("\0\0\0\0"), 0, VERR_NO_DATA },
109 /* Good stuff. */
110 { "\0b1=b1\0\0", sizeof("\0b1=b1\0\0"), 1, VERR_NO_DATA },
111 { "b1=b1\0\0", sizeof("b1=b1\0\0"), 1, VERR_NO_DATA },
112 { "b1=b1\0b2=b2\0\0", sizeof("b1=b1\0b2=b2\0\0"), 1, VERR_NO_DATA },
113 { "b1=b1\0b2=b2\0\0\0", sizeof("b1=b1\0b2=b2\0\0\0"), 1, VERR_NO_DATA }
114};
115
116int manualTest()
117{
118 int rc;
119 static struct
120 {
121 const char *pbData;
122 size_t cbData;
123 uint32_t uOffsetStart;
124 uint32_t uOffsetAfter;
125 uint32_t uMapElements;
126 int iResult;
127 } aTest[] =
128 {
129 { "test5=test5\0t51=t51", sizeof("test5=test5\0t51=t51"), 0, sizeof("test5=test5\0") - 1, 1, VERR_MORE_DATA },
130 { "\0\0test5=test5\0t51=t51", sizeof("\0\0test5=test5\0t51=t51"), 0, sizeof("\0\0test5=test5\0") - 1, 1, VERR_MORE_DATA },
131 };
132
133 unsigned iTest = 0;
134 for (iTest; iTest < RT_ELEMENTS(aTest); iTest++)
135 {
136 RTTestIPrintf(RTTESTLVL_DEBUG, "Manual test #%d\n", iTest);
137
138 GuestProcessStream stream;
139 rc = stream.AddData((BYTE*)aTest[iTest].pbData, aTest[iTest].cbData);
140
141 for (;;)
142 {
143 GuestProcessStreamBlock block;
144 rc = stream.ParseBlock(block);
145 RTTestIPrintf(RTTESTLVL_DEBUG, "\tReturned with rc=%Rrc, numItems=%ld\n",
146 rc, block.GetCount());
147
148 if (block.GetCount())
149 break;
150 }
151 }
152
153 return rc;
154}
155
156int main()
157{
158 RTTEST hTest;
159 int rc = RTTestInitAndCreate("tstParseBuffer", &hTest);
160 if (rc)
161 return rc;
162 RTTestBanner(hTest);
163
164 RTTestIPrintf(RTTESTLVL_DEBUG, "Initializing COM...\n");
165 HRESULT hrc = com::Initialize();
166 if (FAILED(hrc))
167 {
168 RTTestFailed(hTest, "Failed to initialize COM (%Rhrc)!\n", hrc);
169 return RTEXITCODE_FAILURE;
170 }
171
172#ifdef DEBUG_andy
173 rc = manualTest();
174#endif
175
176 RTTestIPrintf(RTTESTLVL_INFO, "Doing basic tests ...\n");
177
178 if (sizeof("sizecheck") != 10)
179 RTTestFailed(hTest, "Basic size test #1 failed (%u <-> 10)", sizeof("sizecheck"));
180 if (sizeof("off=rab") != 8)
181 RTTestFailed(hTest, "Basic size test #2 failed (%u <-> 7)", sizeof("off=rab"));
182 if (sizeof("off=rab\0\0") != 10)
183 RTTestFailed(hTest, "Basic size test #3 failed (%u <-> 10)", sizeof("off=rab\0\0"));
184
185 RTTestIPrintf(RTTESTLVL_INFO, "Doing line tests ...\n");
186
187 /* Don't let the assertions trigger here
188 * -- we rely on the return values in the test(s) below. */
189 RTAssertSetQuiet(true);
190
191 unsigned iTest = 0;
192 for (iTest; iTest < RT_ELEMENTS(aTestBlock); iTest++)
193 {
194 RTTestIPrintf(RTTESTLVL_DEBUG, "=> Test #%u\n", iTest);
195
196 GuestProcessStream stream;
197 int iResult = stream.AddData((BYTE*)aTestBlock[iTest].pbData, aTestBlock[iTest].cbData);
198 if (RT_SUCCESS(iResult))
199 {
200 GuestProcessStreamBlock curBlock;
201 iResult = stream.ParseBlock(curBlock);
202 if (iResult != aTestBlock[iTest].iResult)
203 {
204 RTTestFailed(hTest, "\tReturned %Rrc, expected %Rrc\n",
205 iResult, aTestBlock[iTest].iResult);
206 }
207 else if (stream.GetOffset() != aTestBlock[iTest].uOffsetAfter)
208 {
209 RTTestFailed(hTest, "\tOffset %u wrong, expected %u\n",
210 stream.GetOffset(), aTestBlock[iTest].uOffsetAfter);
211 }
212 else if (iResult == VERR_MORE_DATA)
213 {
214 RTTestIPrintf(RTTESTLVL_DEBUG, "\tMore data (Offset: %u)\n", stream.GetOffset());
215 }
216
217 if ( ( RT_SUCCESS(iResult)
218 || iResult == VERR_MORE_DATA))
219 {
220 if (curBlock.GetCount() != aTestBlock[iTest].uMapElements)
221 {
222 RTTestFailed(hTest, "\tMap has %u elements, expected %u\n",
223 curBlock.GetCount(), aTestBlock[iTest].uMapElements);
224 }
225 }
226
227 /* There is remaining data left in the buffer (which needs to be merged
228 * with a following buffer) -- print it. */
229 uint32_t uOffset = stream.GetOffset();
230 size_t uToWrite = aTestBlock[iTest].cbData - uOffset;
231 if (uToWrite)
232 {
233 const char *pszRemaining = aTestBlock[iTest].pbData;
234 RTTestIPrintf(RTTESTLVL_DEBUG, "\tRemaining (%u):\n", uToWrite);
235
236 /* How to properly get the current RTTESTLVL (aka IPRT_TEST_MAX_LEVEL) here?
237 * Hack alert: Using RTEnvGet for now. */
238 if (!RTStrICmp(RTEnvGet("IPRT_TEST_MAX_LEVEL"), "debug"))
239 RTStrmWriteEx(g_pStdOut, &aTestBlock[iTest].pbData[uOffset], uToWrite - 1, NULL);
240 }
241 }
242 }
243
244 RTTestIPrintf(RTTESTLVL_INFO, "Doing block tests ...\n");
245
246 iTest = 0;
247 for (iTest; iTest < RT_ELEMENTS(aTestStream); iTest++)
248 {
249 RTTestIPrintf(RTTESTLVL_DEBUG, "=> Block test #%u\n", iTest);
250
251 GuestProcessStream stream;
252 int iResult = stream.AddData((BYTE*)aTestStream[iTest].pbData, aTestStream[iTest].cbData);
253 if (RT_SUCCESS(iResult))
254 {
255 uint32_t uNumBlocks = 0;
256 uint8_t uSafeCouunter = 0;
257 do
258 {
259 GuestProcessStreamBlock curBlock;
260 iResult = stream.ParseBlock(curBlock);
261 RTTestIPrintf(RTTESTLVL_DEBUG, "\tReturned with %Rrc\n", iResult);
262 if (RT_SUCCESS(iResult))
263 {
264 /* Only count block which have at least one pair. */
265 if (curBlock.GetCount())
266 uNumBlocks++;
267 }
268 if (uSafeCouunter++ > 32)
269 break;
270 } while (RT_SUCCESS(iResult));
271
272 if (iResult != aTestStream[iTest].iResult)
273 {
274 RTTestFailed(hTest, "\tReturned %Rrc, expected %Rrc\n",
275 iResult, aTestStream[iTest].iResult);
276 }
277 else if (uNumBlocks != aTestStream[iTest].uNumBlocks)
278 {
279 RTTestFailed(hTest, "\tReturned %u blocks, expected %u\n",
280 uNumBlocks, aTestStream[iTest].uNumBlocks);
281 }
282 }
283 else
284 RTTestFailed(hTest, "\tAdding data failed with %Rrc", iResult);
285 }
286
287 RTTestIPrintf(RTTESTLVL_DEBUG, "Shutting down COM...\n");
288 com::Shutdown();
289
290 /*
291 * Summary.
292 */
293 return RTTestSummaryAndDestroy(hTest);
294}
295
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette