Reviewed-by: Michael D Kinney <michael.d.kin...@intel.com>
> -----Original Message----- > From: Michael Kubacki <mikub...@linux.microsoft.com> > Sent: Friday, June 30, 2023 4:00 PM > To: devel@edk2.groups.io; kuqi...@gmail.com > Cc: Sean Brogan <sean.bro...@microsoft.com>; Kinney, Michael D > <michael.d.kin...@intel.com> > Subject: Re: [edk2-devel] [PATCH v3 1/1] UnitTestFrameworkPkg: > UnitTestPersistenceLib: Save Unit Test Cache Option > > Reviewed-by: Michael Kubacki <michael.kuba...@microsoft.com> > > I haven't seen Mike Kinney acknowledge the changes made in response to > his v1 request so we'll need to get that before merging the patch. > > Thanks, > Michael > > On 6/30/2023 2:14 PM, Kun Qin wrote: > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4467 > > > > Current implementation of UnitTestFrameworkPkg for shell-based unit > test > > will save the unit test cache to the same volume as the test > application > > itself. This works as long as the test application is on a writable > > volume, such as USB or EFI partition. > > > > Instead of saving the files to the same file system of unit test > > application, this change will save the cache file to the path where > the > > user ran this test application. > > > > This change then added an input argument to allow user to specify > where > > to save such cache file through `--CachePath` shell argument to allow > > even more flexibility. > > > > This change was tested on proprietary physical hardware platforms and > > QEMU based virtual platform. > > > > Cc: Sean Brogan <sean.bro...@microsoft.com> > > Cc: Michael Kubacki <mikub...@linux.microsoft.com> > > Cc: Michael D Kinney <michael.d.kin...@intel.com> > > > > Signed-off-by: Kun Qin <kuqi...@gmail.com> > > --- > > > > Notes: > > v2: > > - Adding input argument [Mike Kinney] > > v3: > > - No review, no change > > > > > UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/Unit > TestPersistenceLibSimpleFileSystem.c | 232 +++++++++++++------- > > 1 file changed, 157 insertions(+), 75 deletions(-) > > > > diff --git > a/UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/Un > itTestPersistenceLibSimpleFileSystem.c > b/UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/Un > itTestPersistenceLibSimpleFileSystem.c > > index b59991683f48..8f7f03646cd5 100644 > > --- > a/UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/Un > itTestPersistenceLibSimpleFileSystem.c > > +++ > b/UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/Un > itTestPersistenceLibSimpleFileSystem.c > > @@ -16,13 +16,16 @@ > > #include <Library/UefiBootServicesTableLib.h> > > > > #include <Library/DevicePathLib.h> > > > > #include <Library/ShellLib.h> > > > > +#include <Library/UefiLib.h> > > > > #include <Protocol/LoadedImage.h> > > > > #include <UnitTestFrameworkTypes.h> > > > > > > > > #define CACHE_FILE_SUFFIX L"_Cache.dat" > > > > > > > > +CHAR16 *mCachePath = NULL; > > > > + > > > > /** > > > > - Generate the device path to the cache file. > > > > + Generate the file name and path to the cache file. > > > > > > > > @param[in] FrameworkHandle A pointer to the framework that is > being persisted. > > > > > > > > @@ -31,8 +34,8 @@ > > > > > > **/ > > > > STATIC > > > > -EFI_DEVICE_PATH_PROTOCOL * > > > > -GetCacheFileDevicePath ( > > > > +CHAR16 * > > > > +GetCacheFileName ( > > > > IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle > > > > ) > > > > { > > > > @@ -44,13 +47,11 @@ GetCacheFileDevicePath ( > > CHAR16 *TestName; > > > > UINTN DirectorySlashOffset; > > > > UINTN CacheFilePathLength; > > > > - EFI_DEVICE_PATH_PROTOCOL *CacheFileDevicePath; > > > > > > > > - Framework = (UNIT_TEST_FRAMEWORK *)FrameworkHandle; > > > > - AppPath = NULL; > > > > - CacheFilePath = NULL; > > > > - TestName = NULL; > > > > - CacheFileDevicePath = NULL; > > > > + Framework = (UNIT_TEST_FRAMEWORK *)FrameworkHandle; > > > > + AppPath = NULL; > > > > + CacheFilePath = NULL; > > > > + TestName = NULL; > > > > > > > > // > > > > // First, we need to get some information from the loaded image. > > > > @@ -85,35 +86,62 @@ GetCacheFileDevicePath ( > > // PathCleanUpDirectories (FileNameCopy); > > > > // if (PathRemoveLastItem (FileNameCopy)) { > > > > // > > > > - AppPath = ConvertDevicePathToText (LoadedImage- > >FilePath, TRUE, TRUE); // NOTE: This must be freed. > > > > - DirectorySlashOffset = StrLen (AppPath); > > > > - // > > > > - // Make sure we didn't get any weird data. > > > > - // > > > > - if (DirectorySlashOffset == 0) { > > > > - DEBUG ((DEBUG_ERROR, "%a - Weird 0-length string when processing > app path.\n", __func__)); > > > > - goto Exit; > > > > - } > > > > + if (mCachePath == NULL) { > > > > + AppPath = ConvertDevicePathToText (LoadedImage->FilePath, TRUE, > TRUE); // NOTE: This must be freed. > > > > + if (AppPath == NULL) { > > > > + goto Exit; > > > > + } > > > > > > > > - // > > > > - // Now that we know we have a decent string, let's take a deeper > look. > > > > - // > > > > - do { > > > > - if (AppPath[DirectorySlashOffset] == L'\\') { > > > > - break; > > > > + DirectorySlashOffset = StrLen (AppPath); > > > > + // > > > > + // Make sure we didn't get any weird data. > > > > + // > > > > + if (DirectorySlashOffset == 0) { > > > > + DEBUG ((DEBUG_ERROR, "%a - Weird 0-length string when > processing app path.\n", __func__)); > > > > + goto Exit; > > > > } > > > > > > > > - DirectorySlashOffset--; > > > > - } while (DirectorySlashOffset > 0); > > > > + // > > > > + // Now that we know we have a decent string, let's take a deeper > look. > > > > + // > > > > + do { > > > > + if (AppPath[DirectorySlashOffset] == L'\\') { > > > > + break; > > > > + } > > > > + > > > > + DirectorySlashOffset--; > > > > + } while (DirectorySlashOffset > 0); > > > > > > > > - // > > > > - // After that little maneuver, DirectorySlashOffset should be > pointing at the last '\' in AppString. > > > > - // That would be the path to the parent directory that the test app > is executing from. > > > > - // Let's check and make sure that's right. > > > > - // > > > > - if (AppPath[DirectorySlashOffset] != L'\\') { > > > > - DEBUG ((DEBUG_ERROR, "%a - Could not find a single directory > separator in app path.\n", __func__)); > > > > - goto Exit; > > > > + // > > > > + // After that little maneuver, DirectorySlashOffset should be > pointing at the last '\' in AppString. > > > > + // That would be the path to the parent directory that the test > app is executing from. > > > > + // Let's check and make sure that's right. > > > > + // > > > > + if (AppPath[DirectorySlashOffset] != L'\\') { > > > > + DEBUG ((DEBUG_ERROR, "%a - Could not find a single directory > separator in app path.\n", __func__)); > > > > + goto Exit; > > > > + } > > > > + } else { > > > > + AppPath = FullyQualifyPath (mCachePath); // NOTE: This must be > freed. > > > > + if (AppPath == NULL) { > > > > + goto Exit; > > > > + } > > > > + > > > > + DirectorySlashOffset = StrLen (AppPath); > > > > + > > > > + if (AppPath[DirectorySlashOffset - 1] != L'\\') { > > > > + // Set the slash if user did not specify it on the newly > allocated pool > > > > + AppPath = ReallocatePool ( > > > > + (DirectorySlashOffset + 1) * sizeof (CHAR16), > > > > + (DirectorySlashOffset + 2) * sizeof (CHAR16), > > > > + AppPath > > > > + ); > > > > + AppPath[DirectorySlashOffset] = L'\\'; > > > > + AppPath[DirectorySlashOffset + 1] = L'\0'; > > > > + } else { > > > > + // Otherwise the user input is good enough to go, mostly > > > > + DirectorySlashOffset--; > > > > + } > > > > } > > > > > > > > // > > > > @@ -135,11 +163,6 @@ GetCacheFileDevicePath ( > > StrCatS (CacheFilePath, CacheFilePathLength, TestName); > // Copy the base name for the test cache. > > > > StrCatS (CacheFilePath, CacheFilePathLength, CACHE_FILE_SUFFIX); > // Copy the file suffix. > > > > > > > > - // > > > > - // Finally, try to create the device path for the thing thing. > > > > - // > > > > - CacheFileDevicePath = FileDevicePath (LoadedImage->DeviceHandle, > CacheFilePath); > > > > - > > > > Exit: > > > > // > > > > // Free allocated buffers. > > > > @@ -148,15 +171,11 @@ Exit: > > FreePool (AppPath); > > > > } > > > > > > > > - if (CacheFilePath != NULL) { > > > > - FreePool (CacheFilePath); > > > > - } > > > > - > > > > if (TestName != NULL) { > > > > FreePool (TestName); > > > > } > > > > > > > > - return CacheFileDevicePath; > > > > + return CacheFilePath; > > > > } > > > > > > > > /** > > > > @@ -175,21 +194,24 @@ DoesCacheExist ( > > IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle > > > > ) > > > > { > > > > - EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; > > > > - EFI_STATUS Status; > > > > - SHELL_FILE_HANDLE FileHandle; > > > > + CHAR16 *FileName; > > > > + EFI_STATUS Status; > > > > + SHELL_FILE_HANDLE FileHandle; > > > > > > > > // > > > > // NOTE: This devpath is allocated and must be freed. > > > > // > > > > - FileDevicePath = GetCacheFileDevicePath (FrameworkHandle); > > > > + FileName = GetCacheFileName (FrameworkHandle); > > > > + if (FileName == NULL) { > > > > + return FALSE; > > > > + } > > > > > > > > // > > > > // Check to see whether the file exists. If the file can be > opened for > > > > // reading, it exists. Otherwise, probably not. > > > > // > > > > - Status = ShellOpenFileByDevicePath ( > > > > - &FileDevicePath, > > > > + Status = ShellOpenFileByName ( > > > > + FileName, > > > > &FileHandle, > > > > EFI_FILE_MODE_READ, > > > > 0 > > > > @@ -198,8 +220,8 @@ DoesCacheExist ( > > ShellCloseFile (&FileHandle); > > > > } > > > > > > > > - if (FileDevicePath != NULL) { > > > > - FreePool (FileDevicePath); > > > > + if (FileName != NULL) { > > > > + FreePool (FileName); > > > > } > > > > > > > > DEBUG ((DEBUG_VERBOSE, "%a - Returning %d\n", __func__, !EFI_ERROR > (Status))); > > > > @@ -229,10 +251,10 @@ SaveUnitTestCache ( > > IN UINTN SaveStateSize > > > > ) > > > > { > > > > - EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; > > > > - EFI_STATUS Status; > > > > - SHELL_FILE_HANDLE FileHandle; > > > > - UINTN WriteCount; > > > > + CHAR16 *FileName; > > > > + EFI_STATUS Status; > > > > + SHELL_FILE_HANDLE FileHandle; > > > > + UINTN WriteCount; > > > > > > > > // > > > > // Check the inputs for sanity. > > > > @@ -245,13 +267,16 @@ SaveUnitTestCache ( > > // Determine the path for the cache file. > > > > // NOTE: This devpath is allocated and must be freed. > > > > // > > > > - FileDevicePath = GetCacheFileDevicePath (FrameworkHandle); > > > > + FileName = GetCacheFileName (FrameworkHandle); > > > > + if (FileName == NULL) { > > > > + return EFI_INVALID_PARAMETER; > > > > + } > > > > > > > > // > > > > // First lets open the file if it exists so we can delete > it...This is the work around for truncation > > > > // > > > > - Status = ShellOpenFileByDevicePath ( > > > > - &FileDevicePath, > > > > + Status = ShellOpenFileByName ( > > > > + FileName, > > > > &FileHandle, > > > > (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE), > > > > 0 > > > > @@ -270,8 +295,8 @@ SaveUnitTestCache ( > > // > > > > // Now that we know the path to the file... let's open it for > writing. > > > > // > > > > - Status = ShellOpenFileByDevicePath ( > > > > - &FileDevicePath, > > > > + Status = ShellOpenFileByName ( > > > > + FileName, > > > > &FileHandle, > > > > (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | > EFI_FILE_MODE_CREATE), > > > > 0 > > > > @@ -304,8 +329,8 @@ SaveUnitTestCache ( > > ShellCloseFile (&FileHandle); > > > > > > > > Exit: > > > > - if (FileDevicePath != NULL) { > > > > - FreePool (FileDevicePath); > > > > + if (FileName != NULL) { > > > > + FreePool (FileName); > > > > } > > > > > > > > return Status; > > > > @@ -334,13 +359,13 @@ LoadUnitTestCache ( > > OUT UINTN *SaveStateSize > > > > ) > > > > { > > > > - EFI_STATUS Status; > > > > - EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; > > > > - SHELL_FILE_HANDLE FileHandle; > > > > - BOOLEAN IsFileOpened; > > > > - UINT64 LargeFileSize; > > > > - UINTN FileSize; > > > > - VOID *Buffer; > > > > + EFI_STATUS Status; > > > > + CHAR16 *FileName; > > > > + SHELL_FILE_HANDLE FileHandle; > > > > + BOOLEAN IsFileOpened; > > > > + UINT64 LargeFileSize; > > > > + UINTN FileSize; > > > > + VOID *Buffer; > > > > > > > > IsFileOpened = FALSE; > > > > Buffer = NULL; > > > > @@ -356,13 +381,16 @@ LoadUnitTestCache ( > > // Determine the path for the cache file. > > > > // NOTE: This devpath is allocated and must be freed. > > > > // > > > > - FileDevicePath = GetCacheFileDevicePath (FrameworkHandle); > > > > + FileName = GetCacheFileName (FrameworkHandle); > > > > + if (FileName == NULL) { > > > > + return EFI_INVALID_PARAMETER; > > > > + } > > > > > > > > // > > > > // Now that we know the path to the file... let's open it for > writing. > > > > // > > > > - Status = ShellOpenFileByDevicePath ( > > > > - &FileDevicePath, > > > > + Status = ShellOpenFileByName ( > > > > + FileName, > > > > &FileHandle, > > > > EFI_FILE_MODE_READ, > > > > 0 > > > > @@ -407,8 +435,8 @@ Exit: > > // > > > > // Free allocated buffers > > > > // > > > > - if (FileDevicePath != NULL) { > > > > - FreePool (FileDevicePath); > > > > + if (FileName != NULL) { > > > > + FreePool (FileName); > > > > } > > > > > > > > if (IsFileOpened) { > > > > @@ -426,3 +454,57 @@ Exit: > > *SaveData = Buffer; > > > > return Status; > > > > } > > > > + > > > > +/** > > > > + Shell based UnitTestPersistenceLib library constructor. > > > > + > > > > + @param[in] ImageHandle The firmware allocated handle for the EFI > image. > > > > + @param[in] SystemTable A pointer to the EFI System Table. > > > > + > > > > + @retval EFI_SUCCESS The constructor finished successfully. > > > > + @retval Others Error codes returned from gBS- > >HandleProtocol. > > > > + **/ > > > > +EFI_STATUS > > > > +EFIAPI > > > > +UnitTestPersistenceLibConstructor ( > > > > + IN EFI_HANDLE ImageHandle, > > > > + IN EFI_SYSTEM_TABLE *SystemTable > > > > + ) > > > > +{ > > > > + UINTN Index; > > > > + UINTN Argc; > > > > + CHAR16 **Argv; > > > > + EFI_STATUS Status; > > > > + EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters; > > > > + > > > > + Status = gBS->HandleProtocol ( > > > > + gImageHandle, > > > > + &gEfiShellParametersProtocolGuid, > > > > + (VOID **)&ShellParameters > > > > + ); > > > > + if (EFI_ERROR (Status)) { > > > > + ASSERT_EFI_ERROR (Status); > > > > + goto Done; > > > > + } > > > > + > > > > + Argc = ShellParameters->Argc; > > > > + Argv = ShellParameters->Argv; > > > > + > > > > + Status = EFI_SUCCESS; > > > > + if ((Argc > 1) && (Argv != NULL)) { > > > > + // This might be our cue, check for whether we need to do > anything > > > > + for (Index = 1; Index < Argc; Index++) { > > > > + if (StrCmp (Argv[Index], L"--CachePath") == 0) { > > > > + // Need to update the potential cache path to designated path > > > > + if (Index < Argc - 1) { > > > > + mCachePath = Argv[Index + 1]; > > > > + } else { > > > > + Print (L" --CachePath <Path of where to save unit test > cache files, i.e. FS0:TestFolder>\n"); > > > > + } > > > > + } > > > > + } > > > > + } > > > > + > > > > +Done: > > > > + return Status; > > > > +} > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#107077): https://edk2.groups.io/g/devel/message/107077 Mute This Topic: https://groups.io/mt/99878682/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/leave/9847357/21656/1706620634/xyzzy [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-