// Copyright Epic Games, Inc. All Rights Reserved. #include "Misc/AutomationTest.h" #include "Misc/CommandLine.h" #include "Misc/FileHelper.h" #include "Misc/Paths.h" #include "FileUtilities/ZipArchiveWriter.h" #include "FileUtilities/ZipArchiveReader.h" #include "HAL/PlatformFileManager.h" #include "Logging/LogMacros.h" DEFINE_LOG_CATEGORY_STATIC(LogAutomationZipArchive, Log, All); #if WITH_DEV_AUTOMATION_TESTS #if WITH_ENGINE IMPLEMENT_SIMPLE_AUTOMATION_TEST(FZipArchiveTest, "FileUtilities.ZipArchive", EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::EngineFilter); bool FZipArchiveTest::RunTest(const FString& InParameter) { const FString TempDir = FPaths::AutomationTransientDir(); const FString Prefix = TEXT("ZipArchiveTest"); const FString TxtExtension = TEXT(".txt"); const FString TempFileToZip = FPaths::CreateTempFilename(*TempDir, *Prefix, *TxtExtension); // Contents to be zipped const FString FileContents = TEXT("FileUtilities ZipArchive Test"); const FString ZipExtension = TEXT(".zip"); const FString ZipFilePath = FPaths::ConvertRelativePathToFull(FPaths::CreateTempFilename(*TempDir, *Prefix, *ZipExtension)); const FString TestDirectory = FPaths::GetPath(ZipFilePath); // Make sure the directory where OpenWrite is called exists const bool bMakeTree = true; UTEST_TRUE("Making directory tree", IFileManager::Get().MakeDirectory(*TestDirectory, bMakeTree)); ON_SCOPE_EXIT { // Make sure the Tmp folder gets deleted when the tests finishes const bool bRequireExists = true; const bool bRemoveTree = true; IFileManager::Get().DeleteDirectory(*TestDirectory, bRequireExists, bRemoveTree); }; IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); { // Creates a zip file IFileHandle* ZipFile = PlatformFile.OpenWrite(*ZipFilePath); UTEST_NOT_NULL("Zip File is valid", ZipFile); FZipArchiveWriter ZipWriter{ ZipFile }; auto ANSIFileContents = StringCast(*FileContents); TConstArrayView StringView((uint8*) ANSIFileContents.Get(), ANSIFileContents.Length()); ZipWriter.AddFile(FPaths::GetCleanFilename(TempFileToZip), StringView, FDateTime::Now()); } #if WITH_EDITOR // FZipArchiveReader is editor only { // Reads the zip file and see if the contents are correct IFileHandle* ZipFile = PlatformFile.OpenRead(*ZipFilePath); UTEST_NOT_NULL("Zip File is valid", ZipFile); FZipArchiveReader ZipReader{ ZipFile }; const TArray FileNames = ZipReader.GetFileNames(); UTEST_EQUAL("File Count", FileNames.Num(), 1); for (const FString& FileName : FileNames) { TArray FileContentsBuffer; UTEST_TRUE("Try Read File From Zip", ZipReader.TryReadFile(FileName, FileContentsBuffer)); TConstArrayView StringView((ANSICHAR*) FileContentsBuffer.GetData(), FileContentsBuffer.Num()); UTEST_EQUAL("Are Contents the Same", FString{ StringView }, FileContents); } } #endif // WITH_EDITOR return true; } IMPLEMENT_SIMPLE_AUTOMATION_TEST(FZipArchiveCompressTest, "FileUtilities.ZipArchiveCompress", EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::EngineFilter); bool FZipArchiveCompressTest::RunTest(const FString& InParameter) { IFileManager& FileManager = IFileManager::Get(); IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); FString FileExt = TEXT(""); FString FileDir = TEXT(""); bool bCompress = false; FString CmdLine = FCommandLine::Get(); FParse::Value(*CmdLine, TEXT("zipArchiveExt="), FileExt, false); FParse::Value(*CmdLine, TEXT("zipArchiveDir="), FileDir, false); bCompress = FParse::Param(FCommandLine::Get(), TEXT("zipArchiveCompress")); // Didn't find any command line arguments, exit the test. if (FileExt.IsEmpty() || FileDir.IsEmpty()) { return true; } const FString TestDirectory = FPaths::AutomationTransientDir(); PlatformFile.CreateDirectory(*TestDirectory); const FString ZipFilePath = FPaths::ConvertRelativePathToFull(FPaths::CreateTempFilename(*TestDirectory, TEXT("ZipArchiveCompressTest"), TEXT(".zip"))); // Make sure the directory where OpenWrite is called exists const bool bMakeTree = true; UTEST_TRUE("Making directory tree", IFileManager::Get().MakeDirectory(*TestDirectory, bMakeTree)); ON_SCOPE_EXIT { // Make sure the Tmp folder gets deleted when the tests finishes const bool bRequireExists = true; const bool bRemoveTree = true; FileManager.DeleteDirectory(*TestDirectory, bRequireExists, bRemoveTree); }; // create the compress zip file { // Find all the files in the directory TArray FileToCompress; PlatformFile.FindFiles(FileToCompress, *FileDir, *FileExt); // Creates a zip file IFileHandle* ZipFile = PlatformFile.OpenWrite(*ZipFilePath); UTEST_NOT_NULL("Zip File is valid", ZipFile); EZipArchiveOptions ZipOptions = EZipArchiveOptions::RemoveDuplicate; if (bCompress) { ZipOptions |= EZipArchiveOptions::Deflate; } FZipArchiveWriter ZipWriter(ZipFile, ZipOptions); for (int Index = 0; Index < FileToCompress.Num(); Index++) { TUniquePtr Reader = TUniquePtr(FileManager.CreateFileReader(*FileToCompress[Index])); UTEST_TRUE("Fail to create the File archive reader", Reader.IsValid()); int64 Size = Reader->TotalSize(); TArray RawData; RawData.AddUninitialized(Size); Reader->Serialize(RawData.GetData(), Size); Reader->Close(); ZipWriter.AddFile(FileToCompress[Index], RawData, FDateTime::Now()); } } // Reads the zip file and see if the contents are correct { IFileHandle* ZipFile = PlatformFile.OpenRead(*ZipFilePath); UTEST_NOT_NULL("Zip File is valid", ZipFile); FZipArchiveReader ZipReader{ ZipFile }; const TArray FileNames = ZipReader.GetFileNames(); int32 NbProcessFiles = 0; for (const FString& FileName : FileNames) { // open the source uncompress file UTEST_TRUE("File name doesn't match", FileManager.FileExists(*FileName)); TUniquePtr UnCompressReader = TUniquePtr(FileManager.CreateFileReader(*FileName)); UTEST_TRUE("Fail read the uncompress file", UnCompressReader.IsValid()); // extract the file in the zip archive TArray CompressData; UTEST_TRUE("Try Read File From Zip", ZipReader.TryReadFile(FileName, CompressData)); TConstArrayView CompressDataView((ANSICHAR*)CompressData.GetData(), CompressData.Num()); int64 Size = UnCompressReader->TotalSize(); TArray UnCompressData; UnCompressData.AddUninitialized(Size); UnCompressReader->Serialize(UnCompressData.GetData(), Size); UnCompressReader->Close(); TConstArrayView UnCompressView((ANSICHAR*)UnCompressData.GetData(), UnCompressData.Num()); FString StringCompressView(CompressDataView); FString StringUnCompressView(CompressDataView); UTEST_EQUAL("Are Contents the Same", FString{ CompressDataView }, FString{ UnCompressView }); NbProcessFiles++; } if (NbProcessFiles == FileNames.Num()) { UE_LOG(LogAutomationZipArchive, Display, TEXT("Test succeded")); } } return true; } #endif // WITH_ENGINE #endif // WITH_DEV_AUTOMATION_TESTS