Changeset 101291 in vbox for trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg
- Timestamp:
- Sep 27, 2023 1:34:02 PM (17 months ago)
- svn:sync-xref-src-repo-rev:
- 159276
- Location:
- trunk/src/VBox/Devices/EFI/FirmwareNew
- Files:
-
- 18 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/EFI/FirmwareNew
-
Property svn:mergeinfo
changed from (toggle deleted branches)
to (toggle deleted branches)/vendor/edk2/current 103735-103757,103769-103776,129194-156846 /vendor/edk2/current 103735-103757,103769-103776,129194-159268
-
Property svn:mergeinfo
changed from (toggle deleted branches)
-
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
r99404 r101291 11 11 12 12 #include <gtest/gtest.h> 13 #include <gmock/gmock.h> 14 #include <cstring> 15 16 extern "C" { 17 #include <Uefi.h> 18 } 19 20 ////////////////////////////////////////////////////////////////////////////// 21 // Below are the action extensions to GoogleTest and gmock for EDK2 types. 22 // These actions are intended to be used in EXPECT_CALL (and related gmock 23 // macros) to support assignments to output arguments in the expected call. 24 // 25 26 // Action to support pointer types to a buffer (such as UINT8* or VOID*) 27 ACTION_TEMPLATE ( 28 SetArgBuffer, 29 HAS_1_TEMPLATE_PARAMS (size_t, ArgNum), 30 AND_2_VALUE_PARAMS (Buffer, ByteSize) 31 ) { 32 auto ArgBuffer = std::get<ArgNum>(args); 33 34 std::memcpy (ArgBuffer, Buffer, ByteSize); 35 } 36 37 ////////////////////////////////////////////////////////////////////////////// 38 // Below are the matcher extensions to GoogleTest and gmock for EDK2 types. 39 // These matchers are intended to be used in EXPECT_CALL (and related gmock 40 // macros) to support comparisons to input arguments in the expected call. 41 // 42 // Note that these matchers can also be used in the EXPECT_THAT or ASSERT_THAT 43 // macros to compare whether two values are equal. 44 // 45 46 // Matcher to support pointer types to a buffer (such as UINT8* or VOID* or 47 // any structure pointer) 48 MATCHER_P2 ( 49 BufferEq, 50 Buffer, 51 ByteSize, 52 std::string ("buffer data to ") + (negation ? "not " : "") + "be the same" 53 ) { 54 UINT8 *Actual = (UINT8 *)arg; 55 UINT8 *Expected = (UINT8 *)Buffer; 56 57 for (size_t i = 0; i < ByteSize; i++) { 58 if (Actual[i] != Expected[i]) { 59 *result_listener << "byte at offset " << i 60 << " does not match expected. [" << std::hex 61 << "Actual: 0x" << std::setw (2) << std::setfill ('0') 62 << (unsigned int)Actual[i] << ", " 63 << "Expected: 0x" << std::setw (2) << std::setfill ('0') 64 << (unsigned int)Expected[i] << "]"; 65 return false; 66 } 67 } 68 69 *result_listener << "all bytes match"; 70 return true; 71 } 72 73 // Matcher to support CHAR16* type 74 MATCHER_P ( 75 Char16StrEq, 76 String, 77 std::string ("strings to ") + (negation ? "not " : "") + "be the same" 78 ) { 79 CHAR16 *Actual = (CHAR16 *)arg; 80 CHAR16 *Expected = (CHAR16 *)String; 81 82 for (size_t i = 0; Actual[i] != 0; i++) { 83 if (Actual[i] != Expected[i]) { 84 *result_listener << "character at offset " << i 85 << " does not match expected. [" << std::hex 86 << "Actual: 0x" << std::setw (4) << std::setfill ('0') 87 << Actual[i]; 88 89 if (std::isprint (Actual[i])) { 90 *result_listener << " ('" << (char)Actual[i] << "')"; 91 } 92 93 *result_listener << ", Expected: 0x" << std::setw (4) << std::setfill ('0') 94 << Expected[i]; 95 96 if (std::isprint (Expected[i])) { 97 *result_listener << " ('" << (char)Expected[i] << "')"; 98 } 99 100 *result_listener << "]"; 101 102 return false; 103 } 104 } 105 106 *result_listener << "strings match"; 107 return true; 108 } 13 109 14 110 #endif -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
r99404 r101291 17 17 18 18 # 19 # VALID_ARCHITECTURES = IA32 X64 ARM AARCH6419 # VALID_ARCHITECTURES = IA32 X64 20 20 # 21 21 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
r99404 r101291 8 8 9 9 [Defines] 10 INF_VERSION = 0x000100 0510 INF_VERSION = 0x00010018 11 11 BASE_NAME = GoogleTestLib 12 12 MODULE_UNI_FILE = GoogleTestLib.uni 13 13 FILE_GUID = A90E4751-AD30-43CC-980B-01E356B49ADF 14 MODULE_TYPE = BASE14 MODULE_TYPE = HOST_APPLICATION 15 15 VERSION_STRING = 0.1 16 LIBRARY_CLASS = GoogleTestLib |HOST_APPLICATION16 LIBRARY_CLASS = GoogleTestLib 17 17 18 18 # 19 # VALID_ARCHITECTURES = IA32 X64 ARM AARCH6419 # VALID_ARCHITECTURES = IA32 X64 20 20 # 21 21 22 22 [Sources] 23 23 googletest/googletest/src/gtest-all.cc 24 googletest/googlemock/src/gmock-all.cc 24 25 25 26 [Packages] 27 MdePkg/MdePkg.dec 26 28 UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec 27 29 28 30 [BuildOptions] 29 MSFT:*_*_*_CC_FLAGS == /c /EHsc /Zi 30 MSFT:NOOPT_*_*_CC_FLAGS = /Od 31 32 GCC:*_*_*_CC_FLAGS == -g -c 33 34 GCC:NOOPT_*_*_CC_FLAGS = -O0 35 GCC:*_*_IA32_CC_FLAGS = -m32 36 GCC:*_*_X64_CC_FLAGS = -m64 31 MSFT:*_*_*_CC_FLAGS == /c /EHsc /Zi /Od 32 GCC:*_*_IA32_CC_FLAGS == -g -c -fshort-wchar -O0 -m32 33 GCC:*_*_X64_CC_FLAGS == -g -c -fshort-wchar -O0 -m64 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
r99404 r101291 2 2 // This module provides GoogleTest Library implementation. 3 3 // 4 // This module provides GoogleTest Library implementation.5 //6 4 // Copyright (c) 2022, Intel Corporation. All rights reserved.<BR> 7 //8 5 // SPDX-License-Identifier: BSD-2-Clause-Patent 9 6 // -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/Library/UnitTestBootLibUsbClass/UnitTestBootLibUsbClass.c
r99404 r101291 62 62 DpEnd = AppendDevicePathNode (NULL, NULL); 63 63 if (DpEnd == NULL) { 64 DEBUG ((DEBUG_ERROR, "%a: Unable to create device path. DpEnd is NULL.\n", __ FUNCTION__));64 DEBUG ((DEBUG_ERROR, "%a: Unable to create device path. DpEnd is NULL.\n", __func__)); 65 65 Status = EFI_OUT_OF_RESOURCES; 66 66 goto CLEANUP; … … 73 73 ); 74 74 if (Dp == NULL) { 75 DEBUG ((DEBUG_ERROR, "%a: Unable to create device path. Dp is NULL.\n", __ FUNCTION__));75 DEBUG ((DEBUG_ERROR, "%a: Unable to create device path. Dp is NULL.\n", __func__)); 76 76 Status = EFI_OUT_OF_RESOURCES; 77 77 goto CLEANUP; … … 89 89 ); 90 90 if (EFI_ERROR (Status)) { 91 DEBUG ((DEBUG_ERROR, "%a: Error creating load option. Status = %r\n", __ FUNCTION__, Status));91 DEBUG ((DEBUG_ERROR, "%a: Error creating load option. Status = %r\n", __func__, Status)); 92 92 goto CLEANUP; 93 93 } 94 94 95 95 NewOptionValid = TRUE; 96 DEBUG ((DEBUG_VERBOSE, "%a: Generic USB Class Device boot option created.\n", __ FUNCTION__));96 DEBUG ((DEBUG_VERBOSE, "%a: Generic USB Class Device boot option created.\n", __func__)); 97 97 Status = EfiBootManagerLoadOptionToVariable (&NewOption); 98 98 if (EFI_ERROR (Status)) { 99 DEBUG ((DEBUG_ERROR, "%a: Error Saving boot option NV variable. Status = %r\n", __ FUNCTION__, Status));99 DEBUG ((DEBUG_ERROR, "%a: Error Saving boot option NV variable. Status = %r\n", __func__, Status)); 100 100 goto CLEANUP; 101 101 } … … 112 112 ); 113 113 114 DEBUG ((DEBUG_VERBOSE, "%a - Set BootNext Status (%r)\n", __ FUNCTION__, Status));114 DEBUG ((DEBUG_VERBOSE, "%a - Set BootNext Status (%r)\n", __func__, Status)); 115 115 116 116 CLEANUP: -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/Library/UnitTestLib/Log.c
r99404 r101291 119 119 // 120 120 if (Test == NULL) { 121 DEBUG ((DEBUG_ERROR, "%a called with invalid Test parameter\n", __ FUNCTION__));121 DEBUG ((DEBUG_ERROR, "%a called with invalid Test parameter\n", __func__)); 122 122 return; 123 123 } -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.c
r99404 r101291 275 275 // Don't actually report it as an error, but emit a warning. 276 276 // 277 DEBUG ((DEBUG_ERROR, "%a - Cache was detected, but failed to load.\n", __ FUNCTION__));277 DEBUG ((DEBUG_ERROR, "%a - Cache was detected, but failed to load.\n", __func__)); 278 278 Status = EFI_SUCCESS; 279 279 } … … 857 857 Status = SaveUnitTestCache (FrameworkHandle, Header, Header->SaveStateSize); 858 858 if (EFI_ERROR (Status)) { 859 DEBUG ((DEBUG_ERROR, "%a - Could not save state! %r\n", __ FUNCTION__, Status));859 DEBUG ((DEBUG_ERROR, "%a - Could not save state! %r\n", __func__, Status)); 860 860 Status = EFI_DEVICE_ERROR; 861 861 } -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/UnitTestPersistenceLibSimpleFileSystem.c
r99404 r101291 17 17 #include <Library/DevicePathLib.h> 18 18 #include <Library/ShellLib.h> 19 #include <Library/UefiLib.h> 19 20 #include <Protocol/LoadedImage.h> 20 21 #include <UnitTestFrameworkTypes.h> … … 22 23 #define CACHE_FILE_SUFFIX L"_Cache.dat" 23 24 25 CHAR16 *mCachePath = NULL; 26 24 27 /** 25 Generate the devicepath to the cache file.28 Generate the file name and path to the cache file. 26 29 27 30 @param[in] FrameworkHandle A pointer to the framework that is being persisted. … … 32 35 **/ 33 36 STATIC 34 EFI_DEVICE_PATH_PROTOCOL*35 GetCacheFile DevicePath(37 CHAR16 * 38 GetCacheFileName ( 36 39 IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle 37 40 ) … … 45 48 UINTN DirectorySlashOffset; 46 49 UINTN CacheFilePathLength; 47 EFI_DEVICE_PATH_PROTOCOL *CacheFileDevicePath; 48 49 Framework = (UNIT_TEST_FRAMEWORK *)FrameworkHandle; 50 AppPath = NULL; 51 CacheFilePath = NULL; 52 TestName = NULL; 53 CacheFileDevicePath = NULL; 50 51 Framework = (UNIT_TEST_FRAMEWORK *)FrameworkHandle; 52 AppPath = NULL; 53 CacheFilePath = NULL; 54 TestName = NULL; 54 55 55 56 // … … 62 63 ); 63 64 if (EFI_ERROR (Status)) { 64 DEBUG ((DEBUG_WARN, "%a - Failed to locate DevicePath for loaded image. %r\n", __ FUNCTION__, Status));65 DEBUG ((DEBUG_WARN, "%a - Failed to locate DevicePath for loaded image. %r\n", __func__, Status)); 65 66 return NULL; 66 67 } … … 86 87 // if (PathRemoveLastItem (FileNameCopy)) { 87 88 // 88 AppPath = ConvertDevicePathToText (LoadedImage->FilePath, TRUE, TRUE); // NOTE: This must be freed. 89 DirectorySlashOffset = StrLen (AppPath); 90 // 91 // Make sure we didn't get any weird data. 92 // 93 if (DirectorySlashOffset == 0) { 94 DEBUG ((DEBUG_ERROR, "%a - Weird 0-length string when processing app path.\n", __FUNCTION__)); 95 goto Exit; 96 } 97 98 // 99 // Now that we know we have a decent string, let's take a deeper look. 100 // 101 do { 102 if (AppPath[DirectorySlashOffset] == L'\\') { 103 break; 104 } 105 106 DirectorySlashOffset--; 107 } while (DirectorySlashOffset > 0); 108 109 // 110 // After that little maneuver, DirectorySlashOffset should be pointing at the last '\' in AppString. 111 // That would be the path to the parent directory that the test app is executing from. 112 // Let's check and make sure that's right. 113 // 114 if (AppPath[DirectorySlashOffset] != L'\\') { 115 DEBUG ((DEBUG_ERROR, "%a - Could not find a single directory separator in app path.\n", __FUNCTION__)); 116 goto Exit; 89 if (mCachePath == NULL) { 90 AppPath = ConvertDevicePathToText (LoadedImage->FilePath, TRUE, TRUE); // NOTE: This must be freed. 91 if (AppPath == NULL) { 92 goto Exit; 93 } 94 95 DirectorySlashOffset = StrLen (AppPath); 96 // 97 // Make sure we didn't get any weird data. 98 // 99 if (DirectorySlashOffset == 0) { 100 DEBUG ((DEBUG_ERROR, "%a - Weird 0-length string when processing app path.\n", __func__)); 101 goto Exit; 102 } 103 104 // 105 // Now that we know we have a decent string, let's take a deeper look. 106 // 107 do { 108 if (AppPath[DirectorySlashOffset] == L'\\') { 109 break; 110 } 111 112 DirectorySlashOffset--; 113 } while (DirectorySlashOffset > 0); 114 115 // 116 // After that little maneuver, DirectorySlashOffset should be pointing at the last '\' in AppString. 117 // That would be the path to the parent directory that the test app is executing from. 118 // Let's check and make sure that's right. 119 // 120 if (AppPath[DirectorySlashOffset] != L'\\') { 121 DEBUG ((DEBUG_ERROR, "%a - Could not find a single directory separator in app path.\n", __func__)); 122 goto Exit; 123 } 124 } else { 125 AppPath = FullyQualifyPath (mCachePath); // NOTE: This must be freed. 126 if (AppPath == NULL) { 127 goto Exit; 128 } 129 130 DirectorySlashOffset = StrLen (AppPath); 131 132 if (AppPath[DirectorySlashOffset - 1] != L'\\') { 133 // Set the slash if user did not specify it on the newly allocated pool 134 AppPath = ReallocatePool ( 135 (DirectorySlashOffset + 1) * sizeof (CHAR16), 136 (DirectorySlashOffset + 2) * sizeof (CHAR16), 137 AppPath 138 ); 139 AppPath[DirectorySlashOffset] = L'\\'; 140 AppPath[DirectorySlashOffset + 1] = L'\0'; 141 } else { 142 // Otherwise the user input is good enough to go, mostly 143 DirectorySlashOffset--; 144 } 117 145 } 118 146 … … 136 164 StrCatS (CacheFilePath, CacheFilePathLength, CACHE_FILE_SUFFIX); // Copy the file suffix. 137 165 138 //139 // Finally, try to create the device path for the thing thing.140 //141 CacheFileDevicePath = FileDevicePath (LoadedImage->DeviceHandle, CacheFilePath);142 143 166 Exit: 144 167 // … … 149 172 } 150 173 151 if (CacheFilePath != NULL) {152 FreePool (CacheFilePath);153 }154 155 174 if (TestName != NULL) { 156 175 FreePool (TestName); 157 176 } 158 177 159 return CacheFile DevicePath;178 return CacheFilePath; 160 179 } 161 180 … … 176 195 ) 177 196 { 178 EFI_DEVICE_PATH_PROTOCOL *FileDevicePath;179 EFI_STATUS 180 SHELL_FILE_HANDLE 197 CHAR16 *FileName; 198 EFI_STATUS Status; 199 SHELL_FILE_HANDLE FileHandle; 181 200 182 201 // 183 202 // NOTE: This devpath is allocated and must be freed. 184 203 // 185 FileDevicePath = GetCacheFileDevicePath (FrameworkHandle); 204 FileName = GetCacheFileName (FrameworkHandle); 205 if (FileName == NULL) { 206 return FALSE; 207 } 186 208 187 209 // … … 189 211 // reading, it exists. Otherwise, probably not. 190 212 // 191 Status = ShellOpenFileBy DevicePath(192 &FileDevicePath,213 Status = ShellOpenFileByName ( 214 FileName, 193 215 &FileHandle, 194 216 EFI_FILE_MODE_READ, … … 199 221 } 200 222 201 if (File DevicePath!= NULL) {202 FreePool (File DevicePath);203 } 204 205 DEBUG ((DEBUG_VERBOSE, "%a - Returning %d\n", __ FUNCTION__, !EFI_ERROR (Status)));223 if (FileName != NULL) { 224 FreePool (FileName); 225 } 226 227 DEBUG ((DEBUG_VERBOSE, "%a - Returning %d\n", __func__, !EFI_ERROR (Status))); 206 228 207 229 return (!EFI_ERROR (Status)); … … 230 252 ) 231 253 { 232 EFI_DEVICE_PATH_PROTOCOL *FileDevicePath;233 EFI_STATUS 234 SHELL_FILE_HANDLE 235 UINTN 254 CHAR16 *FileName; 255 EFI_STATUS Status; 256 SHELL_FILE_HANDLE FileHandle; 257 UINTN WriteCount; 236 258 237 259 // … … 246 268 // NOTE: This devpath is allocated and must be freed. 247 269 // 248 FileDevicePath = GetCacheFileDevicePath (FrameworkHandle); 270 FileName = GetCacheFileName (FrameworkHandle); 271 if (FileName == NULL) { 272 return EFI_INVALID_PARAMETER; 273 } 249 274 250 275 // 251 276 // First lets open the file if it exists so we can delete it...This is the work around for truncation 252 277 // 253 Status = ShellOpenFileBy DevicePath(254 &FileDevicePath,278 Status = ShellOpenFileByName ( 279 FileName, 255 280 &FileHandle, 256 281 (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE), … … 264 289 Status = ShellDeleteFile (&FileHandle); 265 290 if (EFI_ERROR (Status)) { 266 DEBUG ((DEBUG_ERROR, "%a failed to delete file %r\n", __ FUNCTION__, Status));291 DEBUG ((DEBUG_ERROR, "%a failed to delete file %r\n", __func__, Status)); 267 292 } 268 293 } … … 271 296 // Now that we know the path to the file... let's open it for writing. 272 297 // 273 Status = ShellOpenFileBy DevicePath(274 &FileDevicePath,298 Status = ShellOpenFileByName ( 299 FileName, 275 300 &FileHandle, 276 301 (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE), … … 278 303 ); 279 304 if (EFI_ERROR (Status)) { 280 DEBUG ((DEBUG_ERROR, "%a - Opening file for writing failed! %r\n", __ FUNCTION__, Status));305 DEBUG ((DEBUG_ERROR, "%a - Opening file for writing failed! %r\n", __func__, Status)); 281 306 goto Exit; 282 307 } … … 286 311 // 287 312 WriteCount = SaveStateSize; 288 DEBUG ((DEBUG_INFO, "%a - Writing %d bytes to file...\n", __ FUNCTION__, WriteCount));313 DEBUG ((DEBUG_INFO, "%a - Writing %d bytes to file...\n", __func__, WriteCount)); 289 314 Status = ShellWriteFile ( 290 315 FileHandle, … … 294 319 295 320 if (EFI_ERROR (Status) || (WriteCount != SaveStateSize)) { 296 DEBUG ((DEBUG_ERROR, "%a - Writing to file failed! %r\n", __ FUNCTION__, Status));321 DEBUG ((DEBUG_ERROR, "%a - Writing to file failed! %r\n", __func__, Status)); 297 322 } else { 298 DEBUG ((DEBUG_INFO, "%a - SUCCESS!\n", __ FUNCTION__));323 DEBUG ((DEBUG_INFO, "%a - SUCCESS!\n", __func__)); 299 324 } 300 325 … … 305 330 306 331 Exit: 307 if (File DevicePath!= NULL) {308 FreePool (File DevicePath);332 if (FileName != NULL) { 333 FreePool (FileName); 309 334 } 310 335 … … 335 360 ) 336 361 { 337 EFI_STATUS 338 EFI_DEVICE_PATH_PROTOCOL *FileDevicePath;339 SHELL_FILE_HANDLE 340 BOOLEAN 341 UINT64 342 UINTN 343 VOID 362 EFI_STATUS Status; 363 CHAR16 *FileName; 364 SHELL_FILE_HANDLE FileHandle; 365 BOOLEAN IsFileOpened; 366 UINT64 LargeFileSize; 367 UINTN FileSize; 368 VOID *Buffer; 344 369 345 370 IsFileOpened = FALSE; … … 357 382 // NOTE: This devpath is allocated and must be freed. 358 383 // 359 FileDevicePath = GetCacheFileDevicePath (FrameworkHandle); 384 FileName = GetCacheFileName (FrameworkHandle); 385 if (FileName == NULL) { 386 return EFI_INVALID_PARAMETER; 387 } 360 388 361 389 // 362 390 // Now that we know the path to the file... let's open it for writing. 363 391 // 364 Status = ShellOpenFileBy DevicePath(365 &FileDevicePath,392 Status = ShellOpenFileByName ( 393 FileName, 366 394 &FileHandle, 367 395 EFI_FILE_MODE_READ, … … 369 397 ); 370 398 if (EFI_ERROR (Status)) { 371 DEBUG ((DEBUG_ERROR, "%a - Opening file for writing failed! %r\n", __ FUNCTION__, Status));399 DEBUG ((DEBUG_ERROR, "%a - Opening file for writing failed! %r\n", __func__, Status)); 372 400 goto Exit; 373 401 } else { … … 380 408 Status = ShellGetFileSize (FileHandle, &LargeFileSize); 381 409 if (EFI_ERROR (Status)) { 382 DEBUG ((DEBUG_ERROR, "%a - Failed to determine file size! %r\n", __ FUNCTION__, Status));410 DEBUG ((DEBUG_ERROR, "%a - Failed to determine file size! %r\n", __func__, Status)); 383 411 goto Exit; 384 412 } … … 391 419 Buffer = AllocatePool (FileSize); 392 420 if (Buffer == NULL) { 393 DEBUG ((DEBUG_ERROR, "%a - Failed to allocate a pool to hold the file contents! %r\n", __ FUNCTION__, Status));421 DEBUG ((DEBUG_ERROR, "%a - Failed to allocate a pool to hold the file contents! %r\n", __func__, Status)); 394 422 Status = EFI_OUT_OF_RESOURCES; 395 423 goto Exit; … … 401 429 Status = ShellReadFile (FileHandle, &FileSize, Buffer); 402 430 if (EFI_ERROR (Status)) { 403 DEBUG ((DEBUG_ERROR, "%a - Failed to read the file contents! %r\n", __ FUNCTION__, Status));431 DEBUG ((DEBUG_ERROR, "%a - Failed to read the file contents! %r\n", __func__, Status)); 404 432 } 405 433 … … 408 436 // Free allocated buffers 409 437 // 410 if (File DevicePath!= NULL) {411 FreePool (File DevicePath);438 if (FileName != NULL) { 439 FreePool (FileName); 412 440 } 413 441 … … 427 455 return Status; 428 456 } 457 458 /** 459 Shell based UnitTestPersistenceLib library constructor. 460 461 @param[in] ImageHandle The firmware allocated handle for the EFI image. 462 @param[in] SystemTable A pointer to the EFI System Table. 463 464 @retval EFI_SUCCESS The constructor finished successfully. 465 @retval Others Error codes returned from gBS->HandleProtocol. 466 **/ 467 EFI_STATUS 468 EFIAPI 469 UnitTestPersistenceLibConstructor ( 470 IN EFI_HANDLE ImageHandle, 471 IN EFI_SYSTEM_TABLE *SystemTable 472 ) 473 { 474 UINTN Index; 475 UINTN Argc; 476 CHAR16 **Argv; 477 EFI_STATUS Status; 478 EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters; 479 480 Status = gBS->HandleProtocol ( 481 gImageHandle, 482 &gEfiShellParametersProtocolGuid, 483 (VOID **)&ShellParameters 484 ); 485 if (EFI_ERROR (Status)) { 486 ASSERT_EFI_ERROR (Status); 487 goto Done; 488 } 489 490 Argc = ShellParameters->Argc; 491 Argv = ShellParameters->Argv; 492 493 Status = EFI_SUCCESS; 494 if ((Argc > 1) && (Argv != NULL)) { 495 // This might be our cue, check for whether we need to do anything 496 for (Index = 1; Index < Argc; Index++) { 497 if (StrCmp (Argv[Index], L"--CachePath") == 0) { 498 // Need to update the potential cache path to designated path 499 if (Index < Argc - 1) { 500 mCachePath = Argv[Index + 1]; 501 } else { 502 Print (L" --CachePath <Path of where to save unit test cache files, i.e. FS0:TestFolder>\n"); 503 } 504 } 505 } 506 } 507 508 Done: 509 return Status; 510 } -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLib.c
r99404 r101291 103 103 // Return last entry if no match found. 104 104 // 105 DEBUG ((DEBUG_INFO, "%a Failure Type does not have string defined 0x%X\n", __ FUNCTION__, (UINT32)Failure));105 DEBUG ((DEBUG_INFO, "%a Failure Type does not have string defined 0x%X\n", __func__, (UINT32)Failure)); 106 106 return mFailureTypeStrings[Index].String; 107 107 } -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibConOut.c
r99404 r101291 26 26 Length = UnicodeVSPrintAsciiFormat (String, sizeof (String), Format, Marker); 27 27 if (Length == 0) { 28 DEBUG ((DEBUG_ERROR, "%a formatted string is too long\n", __ FUNCTION__));28 DEBUG ((DEBUG_ERROR, "%a formatted string is too long\n", __func__)); 29 29 } else { 30 30 gST->ConOut->OutputString (gST->ConOut, String); -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibDebugLib.c
r99404 r101291 25 25 Length = AsciiVSPrint (String, sizeof (String), Format, Marker); 26 26 if (Length == 0) { 27 DEBUG ((DEBUG_ERROR, "%a formatted string is too long\n", __ FUNCTION__));27 DEBUG ((DEBUG_ERROR, "%a formatted string is too long\n", __func__)); 28 28 } else { 29 29 DEBUG ((DEBUG_INFO, String)); -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/ReadMe.md
r99404 r101291 21 21 22 22 The second unit test framework supported by the UnitTestFrameworkPkg is 23 [GoogleTest](http://google.github.io/googletest/) that can be used to implement host-based unit tests. 24 Use of GoogleTest for target-based unit tests of EDK II components is not supported. If a 25 host-based unit test requires mocked interfaces, then the Framework with cmocka support should be 26 used instead. Enabling support for mocked interfaces with GoogleTest is being actively investigated. 23 [GoogleTest](http://google.github.io/googletest/) and can be used to implement host-based unit tests. 27 24 [GoogleTest on GitHub](https://github.com/google/googletest) is included in the UnitTestFrameworkPkg 28 as a submodule. 25 as a submodule. Use of GoogleTest for target-based unit tests of EDK II components is not supported. 26 Host-based unit tests that require mocked interfaces can use the mocking infrastructure included with 27 GoogleTest called [gMock](https://github.com/google/googletest/tree/main/googlemock). Note that the 28 gMock framework does not directly support mocking of free (C style) functions, so the FunctionMockLib 29 (containing a set of macros that wrap gMock's MOCK_METHOD macro) was created within the 30 UnitTestFrameworkPkg to enable this support. The details and usage of these macros in the 31 FunctionMockLib are described later. 29 32 30 33 GoogleTest requires less overhead to register test suites and test cases compared to the Framework. … … 34 37 that may be used to implement, run, and debug unit tests implemented using GoogleTest. 35 38 36 If a component can be tested with host-based unit tests without support for mocked interfaces, 37 then GoogleTest is recommended. The MdePkg contains a port of the BaseSafeIntLib unit tests in 38 the GoogleTest style so the differences between GoogleTest and Framework unit tests can be reviewed. 39 The paths to the BaseSafeIntLib unit tests are: 40 41 * MdePkg\Test\UnitTest\Library\BaseSafeIntLib 42 * MdePkg\Test\GoogleTest\Library\BaseSafeIntLib 39 If a component can be tested with host-based unit tests, then GoogleTest is recommended. The MdePkg 40 contains a port of the BaseSafeIntLib unit tests in the GoogleTest style so the differences between 41 GoogleTest and Framework unit tests can be reviewed. The paths to the BaseSafeIntLib unit tests are: 42 43 * `MdePkg/Test/UnitTest/Library/BaseSafeIntLib` 44 * `MdePkg/Test/GoogleTest/Library/BaseSafeIntLib` 45 46 Furthermore, the SecurityPkg contains unit tests for the SecureBootVariableLib using mocks in both 47 the Framework/cmocka and GoogleTest/gMock style so the differences between cmocka and gMock can be 48 reviewed. The paths to the SecureBootVariableLib unit tests are: 49 50 * `SecurityPkg/Library/SecureBootVariableLib/UnitTest` 51 * `SecurityPkg/Library/SecureBootVariableLib/GoogleTest` 43 52 44 53 ## Framework and GoogleTest Feature Comparison … … 57 66 | Type-Parameterized Tests | NO | YES | 58 67 | Timeout Support | NO | YES | 59 | Mocking Support | Cmocka | NO|68 | Mocking Support | Cmocka | gMock | 60 69 | JUNIT XML Reports | YES | YES | 61 70 | Execute subset of tests | NO | YES | … … 105 114 how to check for expected conditions in test cases and a bit of the logging characteristics. 106 115 107 Most of these examples will refer to the SampleUnitTestUefiShellapp found in this package.116 Most of these examples will refer to the `SampleUnitTestUefiShell` app found in this package. 108 117 109 118 ### Framework Requirements - INF … … 114 123 you should be good to go. 115 124 116 See this example in 'SampleUnitTestUefiShell.inf'...125 See this example in `SampleUnitTestUefiShell.inf`... 117 126 118 127 ``` … … 128 137 ``` 129 138 130 Also, if you want you test to automatically be picked up by the Test Runner plugin, you will need139 Also, if you want your test to automatically be picked up by the Test Runner plugin, you will need 131 140 to make sure that the module `BASE_NAME` contains the word `Test`... 132 141 … … 136 145 ``` 137 146 147 ### Framework Requirements - DSC 148 149 In our DSC file, we'll need to bring in the INF file that was just created into the `[Components]` 150 section so that the unit tests will be built. 151 152 See this example in `UnitTestFrameworkPkg.dsc`... 153 154 ``` 155 [Components] 156 UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestUefiShell.inf 157 ``` 158 159 Also, based on the type of tests that are being created, the associated DSC include file from the 160 UnitTestFrameworkPkg for Host or Target based tests should also be included at the top of the DSC 161 file. 162 163 ``` 164 !include UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc 165 ``` 166 167 Lastly, in the case that the test build has specific dependent libraries associated with it, 168 they should be added in the \<LibraryClasses\> sub-section for the INF file in the 169 `[Components]` section of the DSC file. 170 171 See this example in `SecurityPkgHostTest.dsc`... 172 173 ``` 174 [Components] 175 SecurityPkg/Library/SecureBootVariableLib/UnitTest/SecureBootVariableLibUnitTest.inf { 176 <LibraryClasses> 177 SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf 178 UefiRuntimeServicesTableLib|SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiRuntimeServicesTableLib.inf 179 PlatformPKProtectionLib|SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockPlatformPKProtectionLib.inf 180 UefiLib|SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiLib.inf 181 } 182 ``` 183 138 184 ### Framework Requirements - Code 139 185 … … 144 190 ``` 145 191 146 Now that we've got that squared away, let's look at our 'Main()' 'routine (or DriverEntryPoint() or whatever).192 Now that we've got that squared away, let's look at our 'Main()' routine (or DriverEntryPoint() or whatever). 147 193 148 194 ### Framework Configuration … … 158 204 These strings are copied internally to the Framework, so using stack-allocated or literal strings is fine. 159 205 160 In the 'SampleUnitTestUefiShell'app, the module name is used as the short name, so the initialization looks like this.206 In the `SampleUnitTestUefiShell` app, the module name is used as the short name, so the initialization looks like this. 161 207 162 208 ```c … … 185 231 `UNIT_TEST_SUITE_SETUP` and `UNIT_TEST_SUITE_TEARDOWN`. 186 232 187 Looking at 'SampleUnitTestUefiShell'app, you can see that the first test suite is created as below...233 Looking at `SampleUnitTestUefiShell` app, you can see that the first test suite is created as below... 188 234 189 235 ```c … … 219 265 pointer, so it could be a simple value, or it could be a complex structure. If unneeded, pass `NULL`. 220 266 221 In 'SampleUnitTestUefiShell'app, the first test case is added using the code below...267 In `SampleUnitTestUefiShell` app, the first test case is added using the code below... 222 268 223 269 ```c … … 283 329 https://api.cmocka.org/ 284 330 331 ## GoogleTest Libraries 332 333 ### GoogleTestLib 334 335 GoogleTestLib is the core library used for GoogleTest in EDK II. This library is mainly a wrapper 336 around the GoogleTest and gMock header and source files. So all the standard 337 [GoogleTest](http://google.github.io/googletest/) and 338 [gMock](https://github.com/google/googletest/tree/main/googlemock) documentation for writing tests 339 and using mocks applies. 340 341 Additionally, to support the use of some primitive types that are not directly supported by 342 GoogleTest and gMock (but are needed to allow gMock to be used in EDK II), some custom gMock 343 actions and matchers were added to GoogleTestLib. These customizations are briefly described in 344 the following tables. 345 346 #### Custom Actions 347 348 | Action Name | Similar gMock Generic Action | Usage | 349 |:--- |:--- |:--- | 350 | `SetArgBuffer()` | `SetArgPointee()` | Used to set a buffer output argument (such as UINT8*, VOID*, a structure pointer, etc.) with data in an expect call. Can be used in an `EXPECT_CALL()` | 351 352 #### Custom Matchers 353 354 | Matcher Name | Similar gMock Generic Matcher | Usage | 355 |:--- |:--- |:--- | 356 | `BufferEq()` | `Pointee(Eq())` | Used to compare two buffer pointer types (such as UINT8*, VOID*, a structure pointer, etc.). Can be used in an `EXPECT_CALL()`, `EXPECT_THAT()`, or anywhere else a matcher to compare two buffers is needed. | 357 | `Char16StrEq()` | `Pointee(Eq())` | Used to compare two CHAR16* strings. Can be used in an `EXPECT_CALL()`, `EXPECT_THAT()`, or anywhere else a matcher to compare two CHAR16* strings is needed. | 358 359 ### FunctionMockLib 360 361 FunctionMockLib is the library that allows gMock to be used with free (C style) functions. This 362 library contains a set of macros that wrap gMock's MOCK_METHOD macro to enable the standard gMock 363 capabilities to be used with free functions. The details of how this is implemented is outside the 364 scope of this document, but a brief description of each of the public macros in FunctionMockLib is 365 described below. A full example of how to use these macros to create a mock is described in a 366 later section. 367 368 In total there are six public macros in FunctionMockLib. Four of the macros are related to creating 369 the mock functions, and the other two macros are related to creating an interface that is necessary 370 to contain the mock functions and connect them into the gMock framework. 371 372 The macros used to create the interface are... 373 1. `MOCK_INTERFACE_DECLARATION(MOCK)` 374 2. `MOCK_INTERFACE_DEFINITION(MOCK)` 375 376 These macros both take one argument which is the name of the interface for the mock. The 377 `MOCK_INTERFACE_DECLARATION` macro is used to declare the interface in the `.h` file and the 378 `MOCK_INTERFACE_DEFINITION` macro is used to define the interface in the `.cpp` file. For 379 example, to create a mock for the `UefiLib`, a `MockUefiLib.h` file would be created and the 380 below code would be added to it. 381 382 ```cpp 383 struct MockUefiLib { 384 MOCK_INTERFACE_DECLARATION(MockUefiLib); 385 }; 386 ``` 387 388 Additionally, the below code would be written into a `MockUefiLib.cpp` file. 389 390 ```cpp 391 MOCK_INTERFACE_DEFINITION(MockUefiLib); 392 ``` 393 394 The macros used to create the mock functions are... 395 1. `MOCK_FUNCTION_DECLARATION(RET_TYPE, FUNC, ARGS)` 396 2. `MOCK_FUNCTION_DEFINITION(MOCK, FUNC, NUM_ARGS, CALL_TYPE)` 397 3. `MOCK_FUNCTION_INTERNAL_DECLARATION(RET_TYPE, FUNC, ARGS)` 398 4. `MOCK_FUNCTION_INTERNAL_DEFINITION(MOCK, FUNC, NUM_ARGS, CALL_TYPE)` 399 400 You will notice that there are two sets of macros: one to mock external functions and 401 another to mock internal functions. Each set of macros has the exact same arguments, but 402 they are used for slightly different use cases. The details of these different use cases 403 is described in detail in a later section. For now, we will focus on the usage of the macro 404 arguments since that is common between them. 405 406 The `MOCK_FUNCTION_DECLARATION` macro is used to declare the mock function in the `.h` file, 407 and it takes three arguments: return type, function name, and argument list. The 408 `MOCK_FUNCTION_DEFINITION` macro is used to define the mock function in the `.cpp` file, 409 and it takes four arguments: name of the interface for the mock, function name, number of 410 arguments the function takes, and calling convention type of the function. For example, to 411 continue with the `UefiLib` mock example above, the `GetVariable2` and `GetEfiGlobalVariable2` 412 functions are declared in `UefiLib.h` as shown below. 413 414 ```cpp 415 EFI_STATUS 416 EFIAPI 417 GetVariable2 ( 418 IN CONST CHAR16 *Name, 419 IN CONST EFI_GUID *Guid, 420 OUT VOID **Value, 421 OUT UINTN *Size OPTIONAL 422 ); 423 424 EFI_STATUS 425 EFIAPI 426 GetEfiGlobalVariable2 ( 427 IN CONST CHAR16 *Name, 428 OUT VOID **Value, 429 OUT UINTN *Size OPTIONAL 430 ); 431 ``` 432 433 To declare mocks for these functions within the previously created `MockUefiLib` interface, 434 the below code would be added to the `MockUefiLib.h` file. Note that the previously added 435 interface declaration is also included in the code below for context. 436 437 ```cpp 438 struct MockUefiLib { 439 MOCK_INTERFACE_DECLARATION (MockUefiLib); 440 441 MOCK_FUNCTION_DECLARATION ( 442 EFI_STATUS, 443 GetVariable2, 444 (IN CONST CHAR16 *Name, 445 IN CONST EFI_GUID *Guid, 446 OUT VOID **Value, 447 OUT UINTN *Size OPTIONAL) 448 ); 449 450 MOCK_FUNCTION_DECLARATION ( 451 EFI_STATUS, 452 GetEfiGlobalVariable2, 453 (IN CONST CHAR16 *Name, 454 OUT VOID **Value, 455 OUT UINTN *Size OPTIONAL) 456 ); 457 }; 458 ``` 459 460 Additionally, the below code would be added into the `MockUefiLib.cpp` file to provide 461 the definitions for these mock functions. Again, the previously added interface 462 definition is also included in the code below for context. 463 464 ```cpp 465 MOCK_INTERFACE_DEFINITION(MockUefiLib); 466 467 MOCK_FUNCTION_DEFINITION(MockUefiLib, GetVariable2, 4, EFIAPI); 468 MOCK_FUNCTION_DEFINITION(MockUefiLib, GetEfiGlobalVariable2, 3, EFIAPI); 469 ``` 470 471 That concludes the basic overview on how to use the macros, but a more detailed 472 description on how to name the mocks, where to put the files, how to build the 473 mocks, and how to use the mocks is described in detail later. 474 475 ### SubhookLib 476 477 SubhookLib is the library used by FunctionMockLib to implement the macros to 478 mock internal functions: `MOCK_FUNCTION_INTERNAL_DECLARATION` and 479 `MOCK_FUNCTION_INTERNAL_DEFINITION`. These macros require the additional 480 functionality provided by SubhookLib because they create mock functions 481 for functions that are already defined and compiled within the module being 482 tested. More detail on this is provided in a later section, but for now it is 483 sufficient to know that the SubhookLib allows a second definition of the 484 function to be compiled into the test application and then hooked to during a 485 test. 486 487 This library is mainly a wrapper around the 488 [subhook](https://github.com/Zeex/subhook) header and source files. It is 489 important to note that the use of the mock function macros and the creation 490 of mock functions requires no knowledge about the SubhookLib. The SubhookLib 491 library is entirely hidden and encapsulated within FunctionMockLib, and it 492 is only mentioned here to provide a complete explanation on all the libraries 493 used in the implementation. 494 495 ## FunctionMockLib Mocks 496 497 This section describes the details on how to use the mock function macros in 498 FunctionMockLib to create mock functions, name them, organize their files, 499 and build them so that they can be used within GoogleTest tests. The usage 500 of the mock functions is detailed in a later section while this section 501 simply details how to create them, build them, and where to put them. 502 503 ### FunctionMockLib Mocks - External vs. Internal 504 505 The first question to ask when creating a mock function is if the function being 506 mocked is external or internal to the module being tested. This is very important 507 because the macros in FunctionMockLib used to create the mock function are named 508 differently for these two use cases. Fortunately, the arguments to these macros 509 and the usage of the mock functions within the tests are exactly the same. 510 However, because of the different underlying implementations, two different sets 511 of macros are used. 512 513 A more detailed description of when to use the external vs. internal mock function 514 macros is in the following sections, but the quick summary is as follows. 515 516 * External mock function macros are used to mock functions that are outside the 517 module being tested and use link-time replacement. 518 * Internal mock function macros are used to mock functions that are inside the 519 module being tested and use run-time replacement. 520 521 The below table shows which macros to use in these two use cases. However, note that 522 for the creation of the interface, the same macros are used in both cases. 523 524 | Mock Function Use Case | Mock Interface Macros | Mock Function Macros | 525 |:--- |:--- |:--- | 526 | External mock functions | `MOCK_INTERFACE_DECLARATION`</br>`MOCK_INTERFACE_DEFINITION` | `MOCK_FUNCTION_DECLARATION`</br>`MOCK_FUNCTION_DEFINITION` | 527 | Internal mock functions | `MOCK_INTERFACE_DECLARATION`</br>`MOCK_INTERFACE_DEFINITION` | `MOCK_FUNCTION_INTERNAL_DECLARATION`</br>`MOCK_FUNCTION_INTERNAL_DEFINITION` | 528 529 #### FunctionMockLib Mocks - External mock function 530 531 The external mock function macros are used to create mock function definitions 532 for a library, global service, or protocol that is defined outside of the module 533 being tested. These mock function definitions are linked into the test application 534 instead of linking in the design function definitions. In other words, the 535 external mock function macros use link-time replacement of the design functions. 536 537 The `.h/.cpp` files for these mock functions are created within the package 538 directory where the library, global table, or protocol that is being mocked is 539 declared. These files are compiled into their own separate library (using 540 an INF file) that can be shared and linked into many test applications, but more 541 on that later. 542 543 #### FunctionMockLib Mocks - Internal mock function 544 545 The internal mock function macros are used to create mock function definitions 546 for functions that are defined within the module being tested. These mock 547 function definitions are compiled into the test application along with the design 548 function definitions. This is possible because the mock functions are given a 549 slightly different name during compilation. Then during test execution, the 550 design function is hooked and replaced with the mock function. In other words, 551 the internal mock function macros use run-time replacement of the design 552 functions. 553 554 The `.h/.cpp` files for these mock functions are created within the GoogleTest 555 directory containing the specific tests that are using them. These files are 556 compiled directly in the GoogleTest INF file that builds the test application, 557 and they are not shared outside of that GoogleTest directory, but more on that 558 later. 559 560 ### FunctionMockLib Mocks - Declaration 561 562 The declaration of mock functions using the FunctionMockLib macros are done 563 in header files. The name of the header file is determined by the interface 564 (such as a library or a protocol) that is being created for the mock functions. 565 The rules for naming the file are shown in the table below. 566 567 | Interface Type | Header File Name | 568 | :--- | :--- | 569 | Library | Mock\<LibraryName\>Lib.h | 570 | Global Table (e.g. gRT, gBS, etc.) | Mock\<GlobalTableLibraryName\>Lib.h | 571 | Protocol | Mock\<ProtocolName\>Protocol.h | 572 573 The below table shows examples for file names with each of the above cases. 574 575 | Interface Type | Interface Name | Header File Name | 576 | :--- | :--- | :--- | 577 | Library | UefiLib | MockUefiLib.h | 578 | Global Table (e.g. gRT, gBS, etc.) | UefiRuntimeServicesTableLib | MockUefiRuntimeServicesTableLib.h | 579 | Protocol | EFI_USB_IO_PROTOCOL | MockEfiUsbIoProtocol.h | 580 581 Once the header file name is known, the file needs to be created in the proper 582 location. For internal mock functions, the location is simply the same 583 GoogleTest directory that contains the INF file that builds the test application. 584 For external mock functions, the location is within the `Test` directory under the 585 package where the library, global table, or protocol that is being mocked is 586 declared. The exact location depends on the interface type and is shown in the 587 below table. 588 589 | Interface Type | Header File Location | 590 | :--- | :--- | 591 | Library | \<PackageName\>/Test/Mock/Include/GoogleTest/Library | 592 | Global Table (e.g. gRT, gBS, etc.) | \<PackageName\>/Test/Mock/Include/GoogleTest/Library | 593 | Protocol | \<PackageName\>/Test/Mock/Include/GoogleTest/Protocol | 594 595 The below table shows examples for file locations with each of the above cases. 596 597 | Interface Type | Interface Name | Header File Location | 598 | :--- | :--- | :--- | 599 | Library | UefiLib | MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiLib.h | 600 | Global Table (e.g. gRT, gBS, etc.) | UefiRuntimeServicesTableLib | MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiRuntimeServicesTableLib.h | 601 | Protocol | EFI_USB_IO_PROTOCOL | MdePkg/Test/Mock/Include/GoogleTest/Protocol/MockEfiUsbIoProtocol.h | 602 603 Now that the file location is known, the contents can be added to it. After the 604 standard `#ifndef` for a header file is added at the top of the file, the 605 `GoogleTestLib.h` and `FunctionMockLib.h` files are always added. Following these 606 includes other EDK II related include files are added and must be wrapped in 607 `extern "C" {}` because they are C include files. Failure to do this will cause 608 link errors to occur. Note that a `#include` of the interface being mocked must 609 also be added. This causes the declarations of the functions being mocked to be 610 included in the compilation and allows the compilation to verify that the function 611 signatures of the mock and design functions are identical. 612 613 After all the needed includes have been added in the file , a `struct` is declared 614 using the same name as the header file (which was determined using the rules 615 above). Within this structure declaration a `MOCK_INTERFACE_DECLARATION` is 616 added along with a `MOCK_FUNCTION_DECLARATION` (or a 617 `MOCK_FUNCTION_INTERNAL_DECLARATION` if this interface is for internal mock 618 functions) for each function in the interface. To build on the examples above, 619 the complete `MockUefiLib.h` file would be as shown below. Note that for brevity 620 only the `GetVariable2` and `GetEfiGlobalVariable2` declarations are included in 621 the example. 622 623 ```cpp 624 #ifndef MOCK_UEFI_LIB_H_ 625 #define MOCK_UEFI_LIB_H_ 626 627 #include <Library/GoogleTestLib.h> 628 #include <Library/FunctionMockLib.h> 629 extern "C" { 630 #include <Uefi.h> 631 #include <Library/UefiLib.h> 632 } 633 634 struct MockUefiLib { 635 MOCK_INTERFACE_DECLARATION (MockUefiLib); 636 637 MOCK_FUNCTION_DECLARATION ( 638 EFI_STATUS, 639 GetVariable2, 640 (IN CONST CHAR16 *Name, 641 IN CONST EFI_GUID *Guid, 642 OUT VOID **Value, 643 OUT UINTN *Size OPTIONAL) 644 ); 645 646 MOCK_FUNCTION_DECLARATION ( 647 EFI_STATUS, 648 GetEfiGlobalVariable2, 649 (IN CONST CHAR16 *Name, 650 OUT VOID **Value, 651 OUT UINTN *Size OPTIONAL) 652 ); 653 }; 654 655 #endif 656 ``` 657 658 In the case of libraries, the function names in the mock declarations 659 align exactly with the function names in the design. However, in the 660 case of global tables and protocols, to eliminate possible function 661 name collisions, the names are adjusted slightly in the mock 662 declarations as shown in the below table. 663 664 | Mock Function Use Case | Design Function Name | Mock Function Name | 665 | :--- | :--- | :--- | 666 | Library | GetVariable2 | GetVariable2 | 667 | Global Table (e.g. gRT, gBS, etc.) | gRT->GetVariable | gRT_GetVariable | 668 | Protocol | UsbIoProtocol->UsbPortReset | UsbIoProtocol_UsbPortReset | 669 670 Lastly, when creating mock functions, there are two limitations to be 671 aware of in gMock that extend into FunctionMockLib. 672 673 1. gMock does not support mocking functions that have more than 15 arguments. 674 2. gMock does not support mocking variadic functions. 675 676 With those limitations in mind, that completes the mock function 677 declarations, and now the mock function definitions for those declarations 678 can be created. 679 680 ### FunctionMockLib Mocks - Definition 681 682 The definition of mock functions using the FunctionMockLib macros are done 683 in source files. The name of the source file is determined by the interface 684 (such as a library or a protocol) that is being created for the mock functions. 685 The rules for naming the file align with the naming of the file for declarations 686 and are shown in the table below. 687 688 | Interface Type | Source File Name | 689 | :--- | :--- | 690 | Library | Mock\<LibraryName\>Lib.cpp | 691 | Global Table (e.g. gRT, gBS, etc.) | Mock\<GlobalTableLibraryName\>Lib.cpp | 692 | Protocol | Mock\<ProtocolName\>Protocol.cpp | 693 694 The below table shows examples for file names with each of the above cases. 695 696 | Interface Type | Interface Name | Source File Name | 697 | :--- | :--- | :--- | 698 | Library | UefiLib | MockUefiLib.cpp | 699 | Global Table (e.g. gRT, gBS, etc.) | UefiRuntimeServicesTableLib | MockUefiRuntimeServicesTableLib.cpp | 700 | Protocol | EFI_USB_IO_PROTOCOL | MockEfiUsbIoProtocol.cpp | 701 702 Once the source file name is known, the file needs to be created in the proper 703 location. The location of the source file is aligned with the location for the 704 header file. For internal mock functions, the location is simply the same 705 GoogleTest directory that contains the INF file that builds the test application. 706 For external mock functions, the location is within the `Test` directory under the 707 package where the library, global table, or protocol that is being mocked is 708 declared. The exact location depends on the interface type and is shown in the 709 below table. 710 711 | Interface Type | Source File Location | 712 | :--- | :--- | 713 | Library | \<PackageName\>/Test/Mock/Library/GoogleTest/Mock\<LibraryName\>Lib | 714 | Global Table (e.g. gRT, gBS, etc.) | \<PackageName\>/Test/Mock/Library/GoogleTest/Mock\<GlobalTableLibraryName\>Lib | 715 | Protocol | \<PackageName\>/Test/Mock/Library/GoogleTest/Mock\<ProtocolName\>Protocol | 716 717 The below table shows examples for file locations with each of the above cases. 718 719 | Interface Type | Interface Name | Source File Location | 720 | :--- | :--- | :--- | 721 | Library | UefiLib | MdePkg/Test/Mock/Library/GoogleTest/MockUefiLib/MockUefiLib.cpp | 722 | Global Table (e.g. gRT, gBS, etc.) | UefiRuntimeServicesTableLib | MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.cpp | 723 | Protocol | EFI_USB_IO_PROTOCOL | MdePkg/Test/Mock/Library/GoogleTest/MockEfiUsbIoProtocol/MockEfiUsbIoProtocol.cpp | 724 725 Now that the file location is known, the contents can be added to it. At the top 726 of the file, the header file containing the mock function declarations is always 727 added. After this `#include`, the interface definition is created using 728 `MOCK_INTERFACE_DEFINITION` with the interface name that was used in the mock 729 function declaration header file. A `MOCK_FUNCTION_DEFINITION` is then added (or 730 a `MOCK_FUNCTION_INTERNAL_DEFINITION` if this interface is for internal mock 731 functions) for each function that was declared in the interface. To build on the 732 prior declaration examples, the complete `MockUefiLib.cpp` file would be as shown 733 below. Note that for brevity only the `GetVariable2` and `GetEfiGlobalVariable2` 734 definitions are included in the example. 735 736 ```cpp 737 #include <GoogleTest/Library/MockUefiLib.h> 738 739 MOCK_INTERFACE_DEFINITION(MockUefiLib); 740 741 MOCK_FUNCTION_DEFINITION(MockUefiLib, GetVariable2, 4, EFIAPI); 742 MOCK_FUNCTION_DEFINITION(MockUefiLib, GetEfiGlobalVariable2, 3, EFIAPI); 743 ``` 744 745 When creating the defintions, there are a few things to keep in mind. 746 747 First, when using `MOCK_FUNCTION_DEFINITION`, some functions being mocked do 748 not specify a calling convention. In this case, it is fine to leave the last 749 argument of `MOCK_FUNCTION_DEFINITION` empty. For example, if `GetVariable2` 750 did not specify the `EFIAPI` calling convention in its declaration, then the 751 below code would be used for the mock function definition. 752 753 ```cpp 754 MOCK_FUNCTION_DEFINITION(MockUefiLib, GetVariable2, 4, ); 755 ``` 756 757 Second, the function name used in `MOCK_FUNCTION_DEFINITION` must align with 758 the function name used in the associated `MOCK_FUNCTION_DECLARATION` in the 759 header file. 760 761 Last, if the interface is mocking a global table or protocol, then the structure 762 of function pointers for that interface must also be defined within the source 763 file as a `static` structure with the mock function definitions being assigned 764 to the associated entries in the structure. The address of this `static` 765 structure is then assigned to the global table or protocol pointer. Note that 766 this pointer must be wrapped in `extern "C" {}` because it needs C style 767 linkage. Failure to do this will cause link errors to occur. For example, when 768 creating the definition of the mock for the global runtime services table, the 769 complete `MockUefiRuntimeServicesTableLib.cpp` file would be as shown below. 770 Note that for brevity only the `GetVariable` and `SetVariable` definitions are 771 included in the example. 772 773 ```cpp 774 #include <GoogleTest/Library/MockUefiRuntimeServicesTableLib.h> 775 776 MOCK_INTERFACE_DEFINITION(MockUefiRuntimeServicesTableLib); 777 778 MOCK_FUNCTION_DEFINITION(MockUefiRuntimeServicesTableLib, gRT_GetVariable, 5, EFIAPI); 779 MOCK_FUNCTION_DEFINITION(MockUefiRuntimeServicesTableLib, gRT_SetVariable, 5, EFIAPI); 780 781 static EFI_RUNTIME_SERVICES localRt = { 782 {0}, // EFI_TABLE_HEADER 783 784 NULL, // EFI_GET_TIME 785 NULL, // EFI_SET_TIME 786 NULL, // EFI_GET_WAKEUP_TIME 787 NULL, // EFI_SET_WAKEUP_TIME 788 789 NULL, // EFI_SET_VIRTUAL_ADDRESS_MAP 790 NULL, // EFI_CONVERT_POINTER 791 792 gRT_GetVariable, // EFI_GET_VARIABLE 793 NULL, // EFI_GET_NEXT_VARIABLE_NAME 794 gRT_SetVariable, // EFI_SET_VARIABLE 795 796 NULL, // EFI_GET_NEXT_HIGH_MONO_COUNT 797 NULL, // EFI_RESET_SYSTEM 798 799 NULL, // EFI_UPDATE_CAPSULE 800 NULL, // EFI_QUERY_CAPSULE_CAPABILITIES 801 802 NULL, // EFI_QUERY_VARIABLE_INFO 803 }; 804 805 extern "C" { 806 EFI_RUNTIME_SERVICES* gRT = &localRt; 807 } 808 ``` 809 810 That completes the mock function definitions. So now these mock function 811 definitions can be compiled. 812 813 ### FunctionMockLib Mocks - Build 814 815 The building of mock functions using FunctionMockLib is done slightly 816 differently for external and internal function mocks. External mock 817 functions are built using their own separate INF file and internal mock 818 functions are built as source files directly referenced in the GoogleTest 819 INF file that builds the test application. 820 821 #### FunctionMockLib Mocks - Build External Mock Functions 822 823 The building of external mock functions is done using their own separate INF 824 file which is placed in the same location as the associated source file 825 containing the mock function definitions. The name of the INF file is exactly 826 the same as the mock function definitions file, but uses the `.inf` extension 827 rather than `.cpp`. 828 829 Within the `.inf` file the `BASE_NAME` should be set to the same name as the 830 file (minus the extension), the `MODULE_TYPE` should be set to 831 `HOST_APPLICATION`, and the `LIBRARY_CLASS` should be the same as the 832 `BASE_NAME` but without the `Mock` prefix. 833 834 The `[Sources]` section will contain the single mock function definition 835 source file, the `[Packages]` section will contain all the necessary DEC 836 files to compile the mock functions (which at a minimum will include the 837 `UnitTestFrameworkPkg.dec` file), the `[LibraryClasses]` section will contain 838 the `GoogleTestLib`, and the `[BuildOptions]` will need to append the `/EHsc` 839 compilation flag to all MSFT builds to enable proper use of the C++ exception 840 handler. Below is the complete `MockUefiLib.inf` as an example. 841 842 ``` 843 [Defines] 844 INF_VERSION = 0x00010005 845 BASE_NAME = MockUefiLib 846 FILE_GUID = 47211F7A-6D90-4DFB-BDF9-610B69197C2E 847 MODULE_TYPE = HOST_APPLICATION 848 VERSION_STRING = 1.0 849 LIBRARY_CLASS = UefiLib 850 851 # 852 # The following information is for reference only and not required by the build tools. 853 # 854 # VALID_ARCHITECTURES = IA32 X64 855 # 856 857 [Sources] 858 MockUefiLib.cpp 859 860 [Packages] 861 MdePkg/MdePkg.dec 862 UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec 863 864 [LibraryClasses] 865 GoogleTestLib 866 867 [BuildOptions] 868 MSFT:*_*_*_CC_FLAGS = /EHsc 869 ``` 870 871 To ensure that this specific set of mock functions are always buildable even 872 if no test uses it yet, this created INF file needs to be added into the 873 `[Components]` section of the associated `Test` DSC file for the package in 874 which this INF file resides. For example, the above `MockUefiLib.inf` would 875 need to be added to the `MdePkg/Test/MdePkgHostTest.dsc` file as shown below. 876 877 ``` 878 [Components] 879 MdePkg/Test/Mock/Library/GoogleTest/MockUefiLib/MockUefiLib.inf 880 ``` 881 882 This created INF file will also be referenced within the necessary `Test` DSC 883 files in order to include the mock function definitions in the test 884 applications which use this set of mock functions, but more on that later. 885 886 One small additional requirement is that if this INF file is added into a 887 package that does not yet have any other external mock functions in it, then 888 that package's DEC file will need to have the mock include directory (more 889 specifically the `Test/Mock/Include` directory) added to its `[Includes]` 890 section so that test files who want to use the mock functions will be able to 891 locate the mock function header file. For example, if `MockUefiLib.inf` were 892 the first mock added to the `MdePkg`, then the below snippet would need to be 893 added to the `MdePkg.dec` file. 894 895 ``` 896 [Includes] 897 Test/Mock/Include 898 ``` 899 900 #### FunctionMockLib Mocks - Build Internal Mock Functions 901 902 The building of internal mock functions is done using the GoogleTest INF file 903 that already needs to exist to build the test application. This is easy to 904 manage since the source and header files for the internal mock functions are 905 also located in the same GoogleTest directory as the GoogleTest INF file that 906 will reference them. 907 908 The only additions that are required to the GoogleTest INF file are that the 909 mock function definitions file be added to the `[Sources]` section, the 910 `UnitTestFrameworkPkg.dec` file be added to the `[Packages]` section, and the 911 `GoogleTestLib` and `SubhookLib` be added to the `[LibraryClasses]` section. 912 Below is a minimal contrived example for a `MyModuleGoogleTest.inf` that uses a 913 `MockMyModuleInternalFunctions.cpp` source file for its internal mock functions. 914 915 ``` 916 [Defines] 917 INF_VERSION = 0x00010017 918 BASE_NAME = MyModuleGoogleTest 919 FILE_GUID = 814B09B9-2D51-4786-8A77-2E10CD1C55F3 920 VERSION_STRING = 1.0 921 MODULE_TYPE = HOST_APPLICATION 922 923 # 924 # The following information is for reference only and not required by the build tools. 925 # 926 # VALID_ARCHITECTURES = IA32 X64 927 # 928 929 [Sources] 930 MyModuleGoogleTest.cpp 931 MockMyModuleInternalFunctions.cpp 932 933 [Packages] 934 MdePkg/MdePkg.dec 935 UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec 936 937 [LibraryClasses] 938 GoogleTestLib 939 SubhookLib 940 ``` 941 285 942 ## GoogleTest Samples 286 943 … … 292 949 needing a target. 293 950 951 There is also a sample unit test provided as both an example of how to write a unit test with 952 mock functions and leverage some of the gMock features. This sample can be found in the 953 `SecurityPkg/Library/SecureBootVariableLib/GoogleTest` directory. 954 955 It too is provided for the HOST_APPLICATION build type, which can be run on a host system without 956 needing a target. 957 294 958 ## GoogleTest Usage 295 959 … … 298 962 how to check for expected conditions in test cases and a bit of the logging characteristics. 299 963 300 Most of these examples will refer to the SampleGoogleTestHost app found in this package. 964 Most of these examples will refer to the `SampleGoogleTestHost` app found in this package, but 965 the examples related to mock functions will refer to the `SecureBootVariableLibGoogleTest` app 966 found in the `SecurityPkg`. 301 967 302 968 ### GoogleTest Requirements - INF 303 969 304 In our INF file, we'll need to bring in the `GoogleTest ` library. Conveniently, the interface305 header for the `GoogleTest ` is in `UnitTestFrameworkPkg`, so you shouldn't need to depend on any other970 In our INF file, we'll need to bring in the `GoogleTestLib` library. Conveniently, the interface 971 header for the `GoogleTestLib` is in `UnitTestFrameworkPkg`, so you shouldn't need to depend on any other 306 972 packages. As long as your DSC file knows where to find the lib implementation that you want to use, 307 973 you should be good to go. 308 974 309 See this example in 'SampleGoogleTestHost.inf'...975 See this example in `SampleGoogleTestHost.inf`... 310 976 311 977 ``` … … 320 986 ``` 321 987 322 Also, if you want you test to automatically be picked up by the Test Runner plugin, you will need988 Also, if you want your test to automatically be picked up by the Test Runner plugin, you will need 323 989 to make sure that the module `BASE_NAME` contains the word `Test`... 324 990 … … 328 994 ``` 329 995 996 ### GoogleTest Requirements - DSC 997 998 In our DSC file, we'll need to bring in the INF file that was just created into the `[Components]` 999 section so that the unit tests will be built. 1000 1001 See this example in `UnitTestFrameworkPkgHostTest.dsc`... 1002 1003 ``` 1004 [Components] 1005 UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTestHost.inf 1006 ``` 1007 1008 Also, based on the type of tests that are being created, the associated DSC include file from the 1009 UnitTestFrameworkPkg for Host or Target based tests should also be included at the top of the DSC 1010 file. 1011 1012 ``` 1013 !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc 1014 ``` 1015 1016 Lastly, in the case that the test build has specific dependent libraries associated with it, 1017 they should be added in the \<LibraryClasses\> sub-section for the INF file in the 1018 `[Components]` section of the DSC file. Note that it is within this sub-section where you can 1019 control whether the design or mock version of a component is linked into the test exectuable. 1020 1021 See this example in `SecurityPkgHostTest.dsc` where the `SecureBootVariableLib` design is 1022 being tested using mock versions of `UefiRuntimeServicesTableLib`, `PlatformPKProtectionLib`, 1023 and `UefiLib`... 1024 1025 ``` 1026 [Components] 1027 SecurityPkg/Library/SecureBootVariableLib/GoogleTest/SecureBootVariableLibGoogleTest.inf { 1028 <LibraryClasses> 1029 SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf 1030 UefiRuntimeServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.inf 1031 PlatformPKProtectionLib|SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf 1032 UefiLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiLib/MockUefiLib.inf 1033 } 1034 ``` 1035 330 1036 ### GoogleTest Requirements - Code 331 1037 332 Not to state the obvious, but let's make sure we have the following include before getting too far along... 333 334 ``` 335 #include <gtest/gtest.h> 1038 GoogleTest applications are implemented in C++, so make sure that your test file has 1039 a `.cpp` extension. With that behind us, not to state the obvious, but let's make sure 1040 we have the following includes before getting too far along in the file... 1041 1042 ```cpp 1043 #include <Library/GoogleTestLib.h> 336 1044 extern "C" { 337 1045 #include <Uefi.h> … … 341 1049 ``` 342 1050 343 GoogleTest applications are implemented in C++. The first include brings in the 344 GoogleTest definitions. Other EDK II related include files must be wrapped in 345 `extern "C" {}` because they are C include files. Link failures will occur if 346 this is not done. 347 348 Now that we've got that squared away, let's look at our 'Main()'' routine (or DriverEntryPoint() or whatever). 1051 The first include brings in the GoogleTest definitions. Other EDK II related include 1052 files must be wrapped in `extern "C" {}` because they are C include files. Link 1053 failures will occur if this is not done. 1054 1055 Also, when using GoogleTest it is helpful to add a `using` declaration for its 1056 `testing` namespace. This `using` statement greatly reduces the amount of code you 1057 need to write in the tests when referencing the utilities within the `testing` 1058 namespace. For example, instead of writing `::testing::Return` or `::testing::Test`, 1059 you can just write `Return` or `Test` respectively, and these types of references 1060 occur numerous times within the tests. 1061 1062 Lastly, in the case that tests within a GoogleTest application require the usage of 1063 mock functions, it is also necessary to include the header files for those interfaces 1064 as well. As an example, the `SecureBootVariableLibGoogleTest` uses the mock versions 1065 of `UefiLib` and `UefiRuntimeServicesTableLib`. So its test file contains the below 1066 includes. Note that the `using` declaration mentioned above is also shown in the code 1067 below for completeness of the example. 1068 1069 ```cpp 1070 #include <Library/GoogleTestLib.h> 1071 #include <GoogleTest/Library/MockUefiLib.h> 1072 #include <GoogleTest/Library/MockUefiRuntimeServicesTableLib.h> 1073 1074 extern "C" { 1075 #include <Uefi.h> 1076 ... 1077 } 1078 1079 using namespace testing; 1080 ``` 1081 1082 Now that we've got that squared away, let's look at our 'Main()' routine (or DriverEntryPoint() or whatever). 349 1083 350 1084 ### GoogleTest Configuration … … 353 1087 be registered. Instead, the test cases declare the test suite name and test 354 1088 case name as part of their implementation. The only requirement for GoogleTest 355 is to have a `main()` function that initialize the GoogleTest infrastructure and356 callthe service `RUN_ALL_TESTS()` to run all the unit tests.357 358 ```c 1089 is to have a `main()` function that initializes the GoogleTest infrastructure 1090 and calls the service `RUN_ALL_TESTS()` to run all the unit tests. 1091 1092 ```cpp 359 1093 int main(int argc, char* argv[]) { 360 1094 testing::InitGoogleTest(&argc, argv); … … 363 1097 ``` 364 1098 1099 However, while GoogleTest does not require test suites or test cases to be 1100 registered, there is still one rule within EDK II that currently needs to be 1101 followed. This rule is that all tests for a given GoogleTest application must 1102 be contained within the same source file that contains the `main()` function 1103 shown above. These tests can be written directly in the file or a `#include` 1104 can be used to add them into the file indirectly. 1105 1106 The reason for this is due to EDK II taking the host application INF file and 1107 first compiling all of its source files into a static library. This static 1108 library is then linked into the final host application. The problem with this 1109 method is that only the tests in the object file containing the `main()` 1110 function are linked into the final host application. This is because the other 1111 tests are contained in their own object files within the static library and 1112 they have no symbols in them that the final host application depends on, so 1113 those object files are not linked into the final host application. 1114 365 1115 ### GoogleTest - A Simple Test Case 366 1116 367 We'll look at the below test case from 'SampleGoogleTestHost'...368 369 ```c 1117 Below is a sample test case from `SampleGoogleTestHost`. 1118 1119 ```cpp 370 1120 TEST(SimpleMathTests, OnePlusOneShouldEqualTwo) { 371 1121 UINTN A; … … 394 1144 _Note_ that this early return can have implications for memory leakage. 395 1145 396 There is no return status from a GooglTest unit test. If no assertions are 1146 For most `ASSERT` macros in GoogleTest there is also an equivalent `EXPECT` macro. Both macro versions 1147 will ultimately cause the `TEST` to fail if the check fails. However, the difference between the two 1148 macro versions is that when the check fails, the `ASSERT` version immediately returns from the `TEST` 1149 while the `EXPECT` version continues running the `TEST`. 1150 1151 There is no return status from a GooglTest unit test. If no assertions (or expectations) are 397 1152 triggered then the unit test has a passing status. 1153 1154 ### GoogleTest - A gMock Test Case 1155 1156 Below is a sample test case from `SecureBootVariableLibGoogleTest`. Although 1157 actually, the test case is not written exactly like this in the test file, but 1158 more on that in a bit. 1159 1160 ```cpp 1161 TEST(SetSecureBootModeTest, SetVarError) { 1162 MockUefiRuntimeServicesTableLib RtServicesMock; 1163 UINT8 SecureBootMode; 1164 EFI_STATUS Status; 1165 1166 // Any random magic number can be used for these tests 1167 SecureBootMode = 0xAB; 1168 1169 EXPECT_CALL(RtServicesMock, gRT_SetVariable) 1170 .WillOnce(Return(EFI_INVALID_PARAMETER)); 1171 1172 Status = SetSecureBootMode(SecureBootMode); 1173 EXPECT_EQ(Status, EFI_INVALID_PARAMETER); 1174 } 1175 ``` 1176 1177 Keep in mind that this test is written to verify that `SetSecureBootMode()` will 1178 return `EFI_INVALID_PARAMETER` when the call to `gRT->SetVariable()` within the 1179 implementation of `SetSecureBootMode()` returns `EFI_INVALID_PARAMETER`. With that 1180 in mind, let's discuss how a mock function is used to accomplish this in the test. 1181 1182 In this test case, the `MockUefiRuntimeServicesTableLib` interface is instantiated as 1183 `RtServicesMock` which enables its associated mock functions. These interface 1184 instantiations that contain the mock functions are very important for mock function 1185 based unit tests because without these instantiations, the mock functions within that 1186 interface will not exist and can not be used. 1187 1188 The next line of interest is the `EXPECT_CALL`, which is a standard part of the gMock 1189 framework. This macro is telling the test that a call is expected to occur to a 1190 specific function on a specific interface. The first argument is the name of the 1191 interface object that was instantiated in this test, and the second argument is the 1192 name of the mock function within that interface that is expected to be called. The 1193 `WillOnce(Return(EFI_INVALID_PARAMETER))` associated with this `EXPECT_CALL` states 1194 that the `gRT_SetVariable()` function (remember from earlier in this documentation 1195 that this refers to the `gRT->SetVariable()` function) will be called once during 1196 this test, and when it does get called, we want it to return `EFI_INVALID_PARAMETER`. 1197 1198 Once this `EXPECT_CALL` has been setup, the call to `SetSecureBootMode()` occurs in 1199 the test, and its return value is saved in `Status` so that it can be tested. Based 1200 on the `EXPECT_CALL` that was setup earlier, when `SetSecureBootMode()` internally 1201 calls `gRT->SetVariable()`, it returns `EFI_INVALID_PARAMETER`. This value should 1202 then be returned by `SetSecureBootMode()`, and the 1203 `EXPECT_EQ(Status, EFI_INVALID_PARAMETER)` verifies this is the case. 1204 1205 There is much more that can be done with `EXPECT_CALL` and mock functions, but we 1206 will leave those details to be explained in the gMock documentation. 1207 1208 Now it was mentioned earlier that this test case is not written exactly like this 1209 in the test file, and the next section describes how this test is slightly 1210 refactored to reduce the total amount of code in the entire test suite. 1211 1212 ### GoogleTest - A gMock Test Case (refactored) 1213 1214 The sample test case from `SecureBootVariableLibGoogleTest` in the prior section is 1215 actually written as shown below. 1216 1217 ```cpp 1218 class SetSecureBootModeTest : public Test { 1219 protected: 1220 MockUefiRuntimeServicesTableLib RtServicesMock; 1221 UINT8 SecureBootMode; 1222 EFI_STATUS Status; 1223 1224 void SetUp() override { 1225 // Any random magic number can be used for these tests 1226 SecureBootMode = 0xAB; 1227 } 1228 }; 1229 1230 TEST_F(SetSecureBootModeTest, SetVarError) { 1231 EXPECT_CALL(RtServicesMock, gRT_SetVariable) 1232 .WillOnce(Return(EFI_INVALID_PARAMETER)); 1233 1234 Status = SetSecureBootMode(SecureBootMode); 1235 EXPECT_EQ(Status, EFI_INVALID_PARAMETER); 1236 } 1237 ``` 1238 1239 This code may at first seem more complicated, but you will notice that the code 1240 with in it is still the same. There is still a `MockUefiRuntimeServicesTableLib` 1241 instantiation, there is still a `SecureBootMode` and `Status` variable defined, 1242 there is still an `EXPECT_CALL`, and etc. However, the benefit of constructing 1243 the test this way is that the new `TEST_F()` requires less code than the prior 1244 `TEST()`. 1245 1246 This is made possible by the usage of what GoogleTest calls a _test fixture_. 1247 This concept of a test fixture allows multiple tests to use (or more specifically 1248 inherit from a base class) a common set of variables and initial conditions. 1249 Notice that using `TEST_F()` requires the first argument to be a name that aligns 1250 with a test fixture (in this case `SetSecureBootModeTest`), and the second 1251 argument is the name of the test (just like in the `TEST()` macro). 1252 1253 All `TEST_F()` tests that use a specific test fixture can be thought of as having 1254 all of that test fixture's variables automatically defined in the test as well as 1255 having that text fixture's `SetUp()` function called before entering the test. 1256 1257 This means that another `TEST_F()` can be written without needing to worry about 1258 defining a bunch of variables or instantiating a bunch of interfaces for mock 1259 functions. For example, the below test (also in `SecureBootVariableLibGoogleTest`) 1260 uses the same test fixture and makes use of its `RtServicesMock`, `Status`, and 1261 `SecureBootMode` variables. 1262 1263 ```cpp 1264 TEST_F(SetSecureBootModeTest, PropogateModeToSetVar) { 1265 EXPECT_CALL(RtServicesMock, 1266 gRT_SetVariable( 1267 Char16StrEq(EFI_CUSTOM_MODE_NAME), 1268 BufferEq(&gEfiCustomModeEnableGuid, sizeof(EFI_GUID)), 1269 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, 1270 sizeof(SecureBootMode), 1271 BufferEq(&SecureBootMode, sizeof(SecureBootMode)))) 1272 .WillOnce(Return(EFI_SUCCESS)); 1273 1274 Status = SetSecureBootMode(SecureBootMode); 1275 EXPECT_EQ(Status, EFI_SUCCESS); 1276 } 1277 ``` 1278 1279 The biggest benefit is that the `TEST_F()` code can now focus on what is being 1280 tested and not worry about any repetitive setup. There is more that can be done 1281 with test fixtures, but we will leave those details to be explained in the 1282 gMock documentation. 1283 1284 Now, as for what is in the above test, it is slightly more complicated than the 1285 first test. So let's explain this added complexity and what it is actually 1286 testing. In this test, there is still an `EXPECT_CALL` for the 1287 `gRT_SetVariable()` function. However, in this test we are stating that we 1288 expect the input arguments passed to `gRT_SetVariable()` be specific values. 1289 The order they are provided in the `EXPECT_CALL` align with the order of the 1290 arguments in the `gRT_SetVariable()` function. In this case the order of the 1291 `gRT_SetVariable()` arguments is as shown below. 1292 1293 ```cpp 1294 IN CHAR16 *VariableName, 1295 IN EFI_GUID *VendorGuid, 1296 IN UINT32 Attributes, 1297 IN UINTN DataSize, 1298 IN VOID *Data 1299 ``` 1300 1301 So in the `EXPECT_CALL` we are stating that the call to `gRT_SetVariable()` 1302 will be made with the below input argument values. 1303 1304 1. `VariableName` is equal to the `EFI_CUSTOM_MODE_NAME` string 1305 2. `VendorGuid` is equal to the `gEfiCustomModeEnableGuid` GUID (which has a byte length of `sizeof(EFI_GUID)`) 1306 3. `Attributes` is equal to `EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS` 1307 4. `DataSize` is equal to `sizeof(SecureBootMode)` 1308 5. `Data` is equal to `SecureBootMode` (which has a byte length of `sizeof(SecureBootMode)`) 1309 1310 If any one of these input arguments does not match in the actual call to 1311 `gRT_SetVariable()` in the design, then the test will fail. There is much more 1312 that can be done with `EXPECT_CALL` and mock functions, but again we will 1313 leave those details to be explained in the gMock documentation. 398 1314 399 1315 ### GoogleTest - More Complex Cases … … 588 1504 Host based Unit Tests will automatically enable coverage data. 589 1505 590 For Windows, This is primarily leveragefor pipeline builds, but this can be leveraged locally using the1506 For Windows, this is primarily leveraged for pipeline builds, but this can be leveraged locally using the 591 1507 OpenCppCoverage windows tool to parse coverage data to cobertura xml format. 592 1508 … … 608 1524 609 1525 610 For Linux, This is primarily leveraged for pipeline builds, but this can be leveraged locally using the1526 For Linux, this is primarily leveraged for pipeline builds, but this can be leveraged locally using the 611 1527 lcov linux tool, and parsed using the lcov_cobertura python tool to parse it to cobertura xml format. 612 1528 … … 655 1571 Code/Test | Location 656 1572 --------- | -------- 657 Host-Based Unit Tests for a Library/Protocol/PPI/GUID Interface | If what's being tested is an interface (e.g. a library with a public header file, like DebugLib) ,the test should be scoped to the parent package.<br/>Example: `MdePkg/Test/UnitTest/[Library/Protocol/Ppi/Guid]/`<br/><br/>A real-world example of this is the BaseSafeIntLib test in MdePkg.<br/>`MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLibHost.inf`658 Host-Based Unit Tests for a Library/Driver (PEI/DXE/SMM) implementation | If what's being tested is a specific implementation (e.g. BaseDebugLibSerialPort for DebugLib), the test should be scoped to the implementation directory itself, in a UnitTest subdirectory.<br/><br/>Module Example: `MdeModulePkg/Universal/EsrtFmpDxe/UnitTest/`<br/>Library Example: `MdePkg/Library/BaseMemoryLib/UnitTest/`1573 Host-Based Unit Tests for a Library/Protocol/PPI/GUID Interface | If what's being tested is an interface (e.g. a library with a public header file, like DebugLib) and the test is agnostic to a specific implementation, then the test should be scoped to the parent package.<br/>Example: `MdePkg/Test/UnitTest/[Library/Protocol/Ppi/Guid]/`<br/><br/>A real-world example of this is the BaseSafeIntLib test in MdePkg.<br/>`MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLibHost.inf` 1574 Host-Based Unit Tests for a Library/Driver (PEI/DXE/SMM) implementation | If what's being tested is a specific implementation (e.g. BaseDebugLibSerialPort for DebugLib), then the test should be scoped to the implementation directory itself, in a UnitTest (or GoogleTest) subdirectory.<br/><br/>Module Example: `MdeModulePkg/Universal/EsrtFmpDxe/UnitTest/`<br/>Library Example: `MdePkg/Library/BaseMemoryLib/UnitTest/`<br/>Library Example (GoogleTest): `SecurityPkg/Library/SecureBootVariableLib/GoogleTest/` 659 1575 Host-Based Tests for a Functionality or Feature | If you're writing a functional test that operates at the module level (i.e. if it's more than a single file or library), the test should be located in the package-level Tests directory under the HostFuncTest subdirectory.<br/>For example, if you were writing a test for the entire FMP Device Framework, you might put your test in:<br/>`FmpDevicePkg/Test/HostFuncTest/FmpDeviceFramework`<br/><br/>If the feature spans multiple packages, it's location should be determined by the package owners related to the feature. 660 1576 Non-Host-Based (PEI/DXE/SMM/Shell) Tests for a Functionality or Feature | Similar to Host-Based, if the feature is in one package, should be located in the `*Pkg/Test/[Shell/Dxe/Smm/Pei]Test` directory.<br/><br/>If the feature spans multiple packages, it's location should be determined by the package owners related to the feature.<br/><br/>USAGE EXAMPLES<br/>PEI Example: MP_SERVICE_PPI. Or check MTRR configuration in a notification function.<br/> SMM Example: a test in a protocol callback function. (It is different with the solution that SmmAgent+ShellApp)<br/>DXE Example: a test in a UEFI event call back to check SPI/SMRAM status. <br/> Shell Example: the SMM handler audit test has a shell-based app that interacts with an SMM handler to get information. The SMM paging audit test gathers information about both DXE and SMM. And the SMM paging functional test actually forces errors into SMM via a DXE driver. … … 714 1630 GeneralPurposeLibHostUnitTest.inf 715 1631 1632 Mock/ 1633 Include/ 1634 GoogleTest/ 1635 Library/ 1636 MockGeneralPurposeLib.h 1637 1638 Library/ 1639 GoogleTest/ 1640 MockGeneralPurposeLib/ 1641 MockGeneralPurposeLib.cpp 1642 MockGeneralPurposeLib.inf 1643 716 1644 <Package>Pkg.dsc # Standard Modules and any Target-Based Test Apps (including in Test/) 717 718 1645 ``` 719 1646 -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
r99404 r101291 33 33 # 34 34 UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf 35 UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.inf 35 36 UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf 36 37 UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosix.inf 37 38 UnitTestFrameworkPkg/Library/Posix/MemoryAllocationLibPosix/MemoryAllocationLibPosix.inf 39 UnitTestFrameworkPkg/Library/SubhookLib/SubhookLib.inf 38 40 UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLibCmocka.inf -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
r99404 r101291 80 80 "IgnoreFiles": [ # use gitignore syntax to ignore errors in matching files 81 81 "Library/CmockaLib/cmocka/**/*.*", # not going to spell check a submodule 82 "Library/GoogleTestLib/googletest/**/*.*" # not going to spell check a submodule 82 "Library/GoogleTestLib/googletest/**/*.*", # not going to spell check a submodule 83 "Library/SubhookLib/subhook/**/*.*" # not going to spell check a submodule 83 84 ], 84 85 "ExtendWords": [ # words to extend to the dictionary for this package 86 "Pointee", 87 "gmock", 88 "GMOCK", 89 "DSUBHOOK", 85 90 "testcase", 86 91 "testsuites", -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
r99404 r101291 21 21 Library/GoogleTestLib/googletest/googletest/include 22 22 Library/GoogleTestLib/googletest/googlemock/include 23 Library/SubhookLib/subhook 23 24 24 25 [Includes.Common.Private] … … 26 27 Library/CmockaLib/cmocka/include/cmockery 27 28 Library/GoogleTestLib/googletest/googletest 29 Library/GoogleTestLib/googletest/googlemock 28 30 29 31 [LibraryClasses] … … 35 37 # 36 38 GoogleTestLib|Include/Library/GoogleTestLib.h 39 SubhookLib|Include/Library/SubhookLib.h 40 FunctionMockLib|Include/Library/FunctionMockLib.h 37 41 38 42 [LibraryClasses.Common.Private] -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc
r99404 r101291 36 36 UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf 37 37 UnitTestFrameworkPkg/Library/UnitTestUefiBootServicesTableLib/UnitTestUefiBootServicesTableLib.inf 38 UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.inf 38 39 39 40 UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestDxe.inf -
trunk/src/VBox/Devices/EFI/FirmwareNew/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
r99404 r101291 16 16 CmockaLib|UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf 17 17 GoogleTestLib|UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf 18 SubhookLib|UnitTestFrameworkPkg/Library/SubhookLib/SubhookLib.inf 19 FunctionMockLib|UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.inf 18 20 UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLibCmocka.inf 19 21 DebugLib|UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosix.inf 20 22 MemoryAllocationLib|UnitTestFrameworkPkg/Library/Posix/MemoryAllocationLibPosix/MemoryAllocationLibPosix.inf 21 23 UefiBootServicesTableLib|UnitTestFrameworkPkg/Library/UnitTestUefiBootServicesTableLib/UnitTestUefiBootServicesTableLib.inf 24 PeiServicesTablePointerLib|UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.inf 22 25 23 26 [BuildOptions]
Note:
See TracChangeset
for help on using the changeset viewer.