VirtualBox

source: vbox/trunk/src/VBox/GuestHost/installation/testcase/tstVBoxWinDrvInstInf.cpp@ 107092

Last change on this file since 107092 was 107076, checked in by vboxsync, 3 months ago

Windows driver installation: Added INF installation testcases (dry-run mode). bugref:10762

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.4 KB
Line 
1/* $Id: tstVBoxWinDrvInstInf.cpp 107076 2024-11-21 09:59:02Z vboxsync $ */
2/** @file
3 * VirtualBox Windows driver installation tests.
4 */
5
6/*
7 * Copyright (C) 2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include <iprt/assert.h>
29#include <iprt/dir.h>
30#include <iprt/err.h>
31#include <iprt/path.h>
32#include <iprt/process.h>
33#include <iprt/test.h>
34
35#include <VBox/err.h>
36#include <VBox/log.h>
37
38#include <VBox/GuestHost/VBoxWinDrvInst.h>
39#include <VBox/GuestHost/VBoxWinDrvStore.h>
40
41#include "VBoxWinDrvInstInternal.h"
42
43
44/**
45 * Test context to use.
46 */
47typedef struct VBOXWINDRVINSTTESTCTX
48{
49 /** Test handle. */
50 RTTEST hTest;
51 /** Installer handle. */
52 VBOXWINDRVINST hInst;
53 /** Index of current test running.
54 * Set to UINT32_MAX if no test running (yet). */
55 size_t idxTest;
56} VBOXWINDRVINSTTESTCTX;
57typedef VBOXWINDRVINSTTESTCTX *PVBOXWINDRVINSTTESTCTX;
58
59/**
60 * Expected results for a single test.
61 */
62typedef struct VBOXWINDRVINSTTESTRES
63{
64 /** Number of errors occurred for this test. */
65 unsigned cErrors;
66} VBOXWINDRVINSTTESTRES;
67
68/**
69 * Parameters for a single test.
70 */
71typedef struct VBOXWINDRVINSTTESTPARMS
72{
73 /** Expected section to (un)install.
74 * NULL if not being used. */
75 const char *pszSection;
76 /** Expected model name.
77 * NULL if not being used. */
78 const char *pszModel;
79 /** Expected PnP ID.
80 * NULL if not being used. */
81 const char *pszPnpId;
82} VBOXWINDRVINSTTESTPARMS;
83
84/**
85 * A single test.
86 */
87typedef struct VBOXWINDRVINSTTEST
88{
89 /** INF file to use for testing. */
90 const char *pszFile;
91 /** (Un)installation flags. */
92 uint32_t fFlags;
93 /** Expected overall result of the test. */
94 int rc;
95 /** Test parameters. */
96 VBOXWINDRVINSTTESTPARMS Parms;
97 /** Test result(s). Must come last due to array initialization. */
98 VBOXWINDRVINSTTESTRES Result;
99} VBOXWINDRVINSTTEST;
100typedef VBOXWINDRVINSTTEST *PVBOXWINDRVINSTTEST;
101
102/**
103 * Test definitions.
104 */
105VBOXWINDRVINSTTEST g_aTests[] =
106{
107 /**
108 * Failing tests.
109 */
110 /** File does not exist. */
111 { "testInstallFileDoesNotExist.inf", VBOX_WIN_DRIVERINSTALL_F_NONE, VERR_FILE_NOT_FOUND },
112 /** File exists but empty. */
113 { "testInstallEmpty.inf", VBOX_WIN_DRIVERINSTALL_F_NONE, VERR_INSTALLATION_FAILED /* ERROR_GENERAL_SYNTAX */ },
114 /** Does not have an Version section and/or signature. */
115 { "testInstallWrongInfStyle.inf", VBOX_WIN_DRIVERINSTALL_F_NONE, VERR_INSTALLATION_FAILED /* ERROR_WRONG_INF_STYLE */ },
116 /** Does neither have a DefaultInstall nor a Manufacturer section. */
117 { "testInstallNoManufacturerOrDefaultInstall.inf", VBOX_WIN_DRIVERINSTALL_F_NONE, VERR_INVALID_PARAMETER /* ERROR_WRONG_INF_STYLE */ },
118 /** Both, a Manufacturer section *and* a DefaultInstall section are present, which is invalid. */
119 { "testInstallManufacturerAndDefaultInstall.inf", VBOX_WIN_DRIVERINSTALL_F_NONE, VERR_INVALID_PARAMETER /* ERROR_WRONG_INF_STYLE */ },
120 /** Manufacturer section is present, but no model section. */
121 { "testInstallManufacturerButNoModelSection.inf", VBOX_WIN_DRIVERINSTALL_F_NONE, VERR_NOT_FOUND },
122 /** Manufacturer section + model present, but bogus / invalid architecture. */
123 { "testInstallManufacturerInvalidArch.inf", VBOX_WIN_DRIVERINSTALL_F_NONE, VERR_PLATFORM_ARCH_NOT_SUPPORTED },
124 /**
125 * Succeeding tests.
126 */
127 /** Default section is present, but no model section.
128 * This actually is valid and has to succeed. */
129 { "testInstallDefaultInstallButNoModelSection.inf", VBOX_WIN_DRIVERINSTALL_F_NONE, VINF_SUCCESS },
130 /** Manufacturer, model and section given. */
131 { "testInstallManufacturerWithModelSection.inf", VBOX_WIN_DRIVERINSTALL_F_NONE,
132 VINF_SUCCESS, { "VBoxTest" /* Section */, "VBoxTest.NTAMD64" /* Model */, "PCI\\VEN_80ee&DEV_cafe" /* PnP ID */, } }
133};
134typedef VBOXWINDRVINSTTEST *PVBOXWINDRVINSTTEST;
135
136/**
137 * Logging callback for the Windows driver (un)installation code.
138 */
139static DECLCALLBACK(void) tstVBoxDrvInstLogCallback(VBOXWINDRIVERLOGTYPE enmType, const char *pszMsg, void *pvUser)
140{
141 PVBOXWINDRVINSTTESTCTX pCtx = (PVBOXWINDRVINSTTESTCTX)pvUser;
142
143 RTTestPrintf(pCtx->hTest, RTTESTLVL_ALWAYS, "%s\n", pszMsg);
144
145 switch (enmType)
146 {
147 case VBOXWINDRIVERLOGTYPE_ERROR:
148 {
149 if (pCtx->idxTest == UINT32_MAX) /* No test defined? Must be an error in the actual framework. */
150 RTTestFailed(pCtx->hTest, "%s", pszMsg);
151 else /* Just count the error here. If that actually is a not expected error is up to the test later then. */
152 g_aTests[pCtx->idxTest].Result.cErrors++;
153 break;
154 }
155
156 default:
157 break;
158 }
159}
160
161static int tstVBoxDrvInstTestOne(PVBOXWINDRVINSTTESTCTX pCtx, const char *pszInfFile, PVBOXWINDRVINSTTEST pTest)
162{
163 pTest->fFlags |= /* Only run in dry-mode. */
164 VBOX_WIN_DRIVERINSTALL_F_DRYRUN
165 /* Don't destroy the (un)installation parameters for later inspection (see below). */
166 | VBOX_WIN_DRIVERINSTALL_F_NO_DESTROY;
167
168 int rc = VBoxWinDrvInstInstall(pCtx->hInst, pszInfFile, pTest->fFlags);
169 RTTEST_CHECK_MSG_RET(pCtx->hTest, rc == pTest->rc, (pCtx->hTest, "Error: Got %Rrc, expected %Rrc\n", rc, pTest->rc), rc);
170 if (RT_FAILURE(rc)) /* Nothing to do here anymore. */
171 return VINF_SUCCESS;
172
173 PVBOXWINDRVINSTPARMS const pParms = VBoxWinDrvInstTestGetParms(pCtx->hInst);
174
175 /* Check section. */
176 char *psz;
177 if (pTest->Parms.pszSection)
178 {
179 RTUtf16ToUtf8(pParms->u.UnInstall.pwszSection, &psz);
180 if (RTStrCmp(pTest->Parms.pszSection, psz))
181 RTTestFailed(pCtx->hTest, "Error: Got section %s, expected %s\n", psz, pTest->Parms.pszSection);
182 RTStrFree(psz);
183 }
184
185 /* Check model. */
186 if (pTest->Parms.pszModel)
187 {
188 RTUtf16ToUtf8(pParms->u.UnInstall.pwszModel, &psz);
189 if (RTStrCmp(pTest->Parms.pszModel, psz))
190 RTTestFailed(pCtx->hTest, "Error: Got model %s, expected %s\n", psz, pTest->Parms.pszModel);
191 RTStrFree(psz);
192 }
193
194 /* Check PnP ID. */
195 if (pTest->Parms.pszPnpId)
196 {
197 RTUtf16ToUtf8(pParms->u.UnInstall.pwszPnpId, &psz);
198 if (RTStrCmp(pTest->Parms.pszPnpId, psz))
199 RTTestFailed(pCtx->hTest, "Error: Got PnP ID %s, expected %s\n", psz, pTest->Parms.pszPnpId);
200 RTStrFree(psz);
201 }
202
203 VBoxWinDrvInstTestParmsDestroy(pParms); /* For VBOX_WIN_DRIVERINSTALL_F_NO_DESTROY. */
204
205 return VINF_SUCCESS;
206}
207
208static int tstVBoxDrvInstTestPath(PVBOXWINDRVINSTTESTCTX pCtx, const char *pszPath)
209{
210 for (size_t i = 0; i < RT_ELEMENTS(g_aTests); i++)
211 {
212 pCtx->idxTest = i; /* Set current test index for callback. */
213
214 char szInfPath[RTPATH_MAX];
215 RTTEST_CHECK(pCtx->hTest, RTStrPrintf(szInfPath, sizeof(szInfPath), "%s", pszPath) > 0);
216 RTTEST_CHECK_RC_OK(pCtx->hTest, RTPathAppend(szInfPath, sizeof(szInfPath), g_aTests[i].pszFile));
217 RTTEST_CHECK_RC_OK(pCtx->hTest, tstVBoxDrvInstTestOne(pCtx, szInfPath, &g_aTests[i]));
218 }
219
220 return VINF_SUCCESS;
221}
222
223int main(int argc, char **argv)
224{
225 /*
226 * Init the runtime, test and say hello.
227 */
228 RTTEST hTest;
229 int rc = RTTestInitAndCreate("tstVBoxWinDrvInstInf", &hTest);
230 if (rc)
231 return rc;
232 RTTestBanner(hTest);
233
234 /* Simply create + destroy. */
235 VBOXWINDRVINST hWinDrvInst;
236 RTTEST_CHECK_RC_OK_BREAK(hTest, VBoxWinDrvInstCreateEx(&hWinDrvInst, 4 /* Verbosity */,
237 NULL, NULL /* pvUser */));
238 VBoxWinDrvInstDestroy(hWinDrvInst);
239
240 /* Run all tests. */
241 do
242 {
243 char szTestPath[RTPATH_MAX];
244
245 if (argc < 2)
246 {
247 RTTEST_CHECK_BREAK(hTest, RTProcGetExecutablePath(szTestPath, sizeof(szTestPath)) != NULL);
248 RTPathStripFilename(szTestPath);
249 RTTEST_CHECK_RC_OK_BREAK(hTest, RTPathAppend(szTestPath, sizeof(szTestPath), "inf"));
250 }
251 else
252 {
253 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Warning: Custom directory specified\n");
254 RTTEST_CHECK_BREAK(hTest, RTStrPrintf(szTestPath, sizeof(szTestPath), "%s", argv[1]) > 0);
255 }
256
257 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Test directory: %s\n", szTestPath);
258
259 VBOXWINDRVINSTTESTCTX Ctx = { 0 };
260 Ctx.idxTest = UINT32_MAX;
261
262 RTTEST_CHECK_RC_OK_BREAK(hTest, VBoxWinDrvInstCreateEx(&hWinDrvInst, 4 /* Verbosity */,
263 &tstVBoxDrvInstLogCallback, &Ctx /* pvUser */));
264 Ctx.hInst = hWinDrvInst;
265
266 rc = tstVBoxDrvInstTestPath(&Ctx, szTestPath);
267
268 VBoxWinDrvInstDestroy(hWinDrvInst);
269
270 } while (0);
271
272 /*
273 * Run the test.
274 */
275 return RTTestSummaryAndDestroy(hTest);
276}
277
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