UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
BuildDataVerifier.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4// HEADER_UNIT_SKIP - Internal
5
6#include "Core/BlockRange.h"
8#include "Common/FileSystem.h"
13#include "BuildPatchUtil.h"
14
15namespace BuildPatchServices
16{
22 {
23 public:
25 : FileSystem(InFileSystem)
26 , ChunkDataSerialization(InChunkDataSerialization)
27 , BuildLocation(InBuildLocation)
28 , OtherBuildLocation(InOtherBuildLocation)
29 , CloudDir(InCloudDir)
30 , Manifest(InManifest)
31 , OtherManifest(InOtherManifest)
32 , BuildFiles(ListHelpers::GetFileList(Manifest))
33 , OtherBuildFiles(ListHelpers::GetFileList(OtherManifest))
34 {
35 }
36
37 FArchive* LoadFile(const FString& BuildFile, bool bUseOther)
38 {
39 const FString FullFilename = bUseOther ? OtherBuildLocation / BuildFile : BuildLocation / BuildFile;
40 TUniquePtr<FArchive>& LoadedFile = LoadedFiles.FindOrAdd(FullFilename);
41 if (LoadedFile.IsValid() == false)
42 {
43 LoadedFile = FileSystem->CreateFileReader(*FullFilename);
44 }
45 check(LoadedFile.IsValid());
46 return LoadedFile.Get();
47 }
48
50 {
51 if (ChunkPart.IsPadding())
52 {
53 OutData.AddUninitialized(ChunkPart.Size);
54 uint8* DataStart = OutData.GetData() + (OutData.Num() - ChunkPart.Size);
55 FMemory::Memset(DataStart, ChunkPart.GetPaddingByte(), ChunkPart.Size);
56 return;
57 }
58 if (LoadedChunks.Contains(ChunkPart.Guid) == false)
59 {
60 EChunkLoadResult ChunkLoadResult;
61 FString DataFilename;
62 if (ChunkWriterSummaries && ChunkWriterSummaries->ChunkOutputHashes.Contains(ChunkPart.Guid))
63 {
64 DataFilename = FBuildPatchUtils::GetChunkNewFilename(ChunkWriterSummaries->FeatureLevel, CloudDir, ChunkPart.Guid, ChunkWriterSummaries->ChunkOutputHashes[ChunkPart.Guid]);
65 }
66 else
67 {
68 const FBuildPatchAppManifest* ManifestRequired = Manifest.GetChunkInfo(ChunkPart.Guid) == nullptr ? &OtherManifest : &Manifest;
70 }
71 LoadedChunks.Emplace(ChunkPart.Guid, ChunkDataSerialization->LoadFromFile(DataFilename, ChunkLoadResult));
72 check(ChunkLoadResult == EChunkLoadResult::Success);
73 }
74 FScopeLockedChunkData ChunkDataAccess(LoadedChunks[ChunkPart.Guid].Get());
75 OutData.Append(ChunkDataAccess.GetData() + ChunkPart.Offset, ChunkPart.Size);
76 }
77
78 void GetFileData(const FString& BuildFilename, const FBlockRange& BlockRange, TArray<uint8>& OutData, bool bUseOther = false)
79 {
81 FArchive* BuildFile = LoadFile(BuildFilename, bUseOther);
82 BuildFile->Seek(BlockRange.GetFirst());
83 BuildFile->Serialize(TestBuffer.GetData(), BlockRange.GetSize());
84 check(BuildFile->IsError() == false);
85 OutData.Append(TestBuffer.GetData(), BlockRange.GetSize());
86 }
87
88 void GetBuildData(const FBlockRange& BlockRange, TArray<uint8>& OutData, bool bUseOther = false)
89 {
92 for (const FString& BuildFilename : (bUseOther ? OtherBuildFiles : BuildFiles))
93 {
94 const FFileManifest* FileManifest = (bUseOther ? OtherManifest : Manifest).GetFileManifest(BuildFilename);
95 check(FileManifest != nullptr);
97 if (FileRange.Overlaps(BlockRange))
98 {
99 ChunkPartFirst = FileRange.GetFirst();
100 for (const FChunkPart& ChunkPart : FileManifest->ChunkParts)
101 {
103 if (ChunkPartRange.Overlaps(BlockRange))
104 {
106 const int64 FileSeek = BuildBytesRange.GetFirst() - FileRange.GetFirst();
107 const int64 DataIndex = BuildBytesRange.GetFirst() - BlockRange.GetFirst();
109 FArchive* BuildFile = LoadFile(BuildFilename, bUseOther);
110 BuildFile->Seek(FileSeek);
111 BuildFile->Serialize(TestBuffer.GetData(), BuildBytesRange.GetSize());
112 check(BuildFile->IsError() == false);
113 OutData.Append(TestBuffer.GetData(), BuildBytesRange.GetSize());
114 }
115 ChunkPartFirst += ChunkPartRange.GetSize();
116 }
118 }
119 BuildFileFirst += FileRange.GetSize();
120 }
121 }
122
123 void GetBuildData(const FBlockStructure& BlockStructure, TArray<uint8>& OutData, bool bUseOther = false)
124 {
125 uint64 ExpectedSize = OutData.Num();
126 const FBlockEntry* BlockEntry = BlockStructure.GetHead();
127 while (BlockEntry)
128 {
129 GetBuildData(BlockEntry->AsRange(), OutData, bUseOther);
130 ExpectedSize += BlockEntry->GetSize();
131 BlockEntry = BlockEntry->GetNext();
132 }
133 check(OutData.Num() == ExpectedSize);
134 }
135
136 void CheckDataAndAssert(const FBlockStructure& BlockStructure, const uint8* Data)
137 {
138 if (BuildLocation.IsEmpty())
139 {
140 return;
141 }
142 TArray<uint8> BuildData;
143 GetBuildData(BlockStructure, BuildData);
144 check(FMemory::Memcmp(BuildData.GetData(), Data, BuildData.Num()) == 0);
145 }
146
147 void CheckDataAndAssert(const FBlockStructure& BlockStructure, const FSHAHash& SHAHash)
148 {
149 if (BuildLocation.IsEmpty())
150 {
151 return;
152 }
153 TArray<uint8> BuildData;
154 GetBuildData(BlockStructure, BuildData);
155 check(SHAHash == DeltaOptimiseHelpers::GetShaForDataSet(BuildData));
156 }
157
158 void CheckDataAndAssert(const IDeltaChunkEnumeration* DeltaChunkEnumeration, const FChunkBuildReference& ChunkBuildReference)
159 {
160 if (BuildLocation.IsEmpty())
161 {
162 return;
163 }
164
165 const FChunkPart& FirstChunkPart = ChunkBuildReference.Get<0>()[0];
166 const FFilenameId& FilenameId = ChunkBuildReference.Get<1>();
167 const uint64& FileOffset = ChunkBuildReference.Get<3>();
168 const FString& Filename = DeltaChunkEnumeration->GetFilename(FilenameId);
169
172
175
176 check(FMemory::Memcmp(ChunkData.GetData(), FileData.GetData(), ChunkData.Num()) == 0);
177 }
178
180 {
181 if (BuildLocation.IsEmpty())
182 {
183 return;
184 }
185 TArray<uint8> BuildData;
187 GetBuildData(BlockStructure, BuildData, false);
189 check(BuildData.Num() == OtherBuildData.Num());
190 check(FMemory::Memcmp(BuildData.GetData(), OtherBuildData.GetData(), BuildData.Num()) == 0);
191 }
192
194 {
195 if (BuildLocation.IsEmpty())
196 {
197 return;
198 }
202 for (const FFileManifest& FileManifest : FileManifestList.FileList)
203 {
204 for (const FChunkPart& ChunkPart : FileManifest.ChunkParts)
205 {
206 check(ChunkWriterSummaries == nullptr || ChunkPart.Guid.IsValid());
207 if (ChunkPart.Guid.IsValid())
208 {
209 BuildBuffer.SetNumUninitialized(0, EAllowShrinking::No);
210 ChunkBuffer.SetNumUninitialized(0, EAllowShrinking::No);
214 check(FMemory::Memcmp(BuildBuffer.GetData(), ChunkBuffer.GetData(), ChunkPart.Size) == 0);
215 }
216 ChunkPartStart += ChunkPart.Size;
217 }
218 }
219 }
220
221 void CheckDataAndAssert(const FBlockStructure& BlockStructure, const FChunkPart& ChunkPart, bool bUseOther = false)
222 {
223 if (BuildLocation.IsEmpty())
224 {
225 return;
226 }
227 TArray<uint8> BuildData;
229 GetBuildData(BlockStructure, BuildData, bUseOther);
230 if (ChunkPart.Guid.IsValid())
231 {
232 GetChunkData(ChunkPart, ChunkData);
233 check(BuildData.Num() == ChunkData.Num());
234 check(FMemory::Memcmp(BuildData.GetData(), ChunkData.GetData(), BuildData.Num()) == 0);
235 }
236 else
237 {
238 check(BuildData.Num() == ChunkPart.Size);
239 }
240 }
241
243 {
244 if (BuildLocation.IsEmpty())
245 {
246 return;
247 }
248 TArray<uint8> BuildData;
251 while (ChunkNode)
252 {
254 ChunkData.SetNumUninitialized(0, EAllowShrinking::No);
255 GetBuildData(ChunkNode->GetValue().BuildRange, BuildData, bUseOther);
256 if (ChunkNode->GetValue().ChunkPart.Guid.IsValid())
257 {
258 GetChunkData(ChunkNode->GetValue().ChunkPart, ChunkData);
259 check(BuildData.Num() == ChunkData.Num());
260 check(FMemory::Memcmp(BuildData.GetData(), ChunkData.GetData(), BuildData.Num()) == 0);
261 }
262 else
263 {
264 check(BuildData.Num() == ChunkNode->GetValue().ChunkPart.Size);
265 }
266 ChunkNode = ChunkNode->GetNextNode();
267 }
268 }
269
271 {
272 if (BuildLocation.IsEmpty())
273 {
274 return;
275 }
276 const FScannerFilesListNode* Node = ChunkDList.GetHead();
277 while (Node)
278 {
279 const FScannerFileElement& Element = Node->GetValue();
280
281 const FBlockRange& ScanDataRange = Element.Get<0>();
282 const FFilenameId& FilenameId = Element.Get<1>();
283 const uint64& FileOffset = Element.Get<3>();
284 const FString& Filename = DeltaChunkEnumeration->GetFilename(FilenameId);
285
287 GetFileData(Filename, FBlockRange::FromFirstAndSize(FileOffset, ScanDataRange.GetSize()), FileData);
288
289 check(FMemory::Memcmp(ScannerData.GetData() + ScanDataRange.GetFirst(), FileData.GetData(), ScanDataRange.GetSize()) == 0);
290
291 Node = Node->GetNextNode();
292 }
293 }
294
296 {
300 for (const FFileManifest& FileManifest : FileManifestList.FileList)
301 {
303 check(FileNode->GetValue().Manifest->Filename == FileManifest.Filename);
304 check(FileNode->GetValue().BuildRange == FileRange);
305 check(FileManifest.ChunkParts.Num() == FileNode->GetValue().ChunkParts.Num());
307 for (const FChunkPart& ChunkPart : FileManifest.ChunkParts)
308 {
310 check(ChunkPart.Guid == ChunkNode->GetValue().ChunkPart.Guid);
311 check(ChunkPart.Offset == ChunkNode->GetValue().ChunkPart.Offset);
312 check(ChunkPart.Size == ChunkNode->GetValue().ChunkPart.Size);
313 check(ChunkPartRange == ChunkNode->GetValue().BuildRange);
314 ChunkPartFirst += ChunkPart.Size;
315 ChunkNode = ChunkNode->GetNextNode();
316 }
317 BuildFileFirst += FileRange.GetSize();
318 FileNode = FileNode->GetNextNode();
319 }
320 }
321
323 {
326 check(FileManifestListA.FileList.Num() == FileManifestListB.FileList.Num());
328 {
333
334 check(FileManifestA.Filename == FileManifestB.Filename);
336 check(FileManifestA.ChunkParts.Num() == FileManifestB.ChunkParts.Num());
337
338 for (int32 ChunkPartIdx = 0; ChunkPartIdx < FileManifestA.ChunkParts.Num(); ++ChunkPartIdx)
339 {
340 const FChunkPart& ChunkPartA = FileManifestA.ChunkParts[ChunkPartIdx];
341 const FChunkPart& ChunkPartB = FileManifestB.ChunkParts[ChunkPartIdx];
344
345 check(ChunkPartA.Guid == ChunkPartB.Guid);
346 check(ChunkPartA.Offset == ChunkPartB.Offset);
347 check(ChunkPartA.Size == ChunkPartB.Size);
349
350 ChunkPartFirst += ChunkPartRangeA.GetSize();
351 }
352 BuildFileFirst += FileRangeA.GetSize();
353 }
354 }
355
356 private:
357 IFileSystem* const FileSystem;
358 IChunkDataSerialization* const ChunkDataSerialization;
359 const FString BuildLocation;
360 const FString OtherBuildLocation;
361 const FString CloudDir;
362 const FBuildPatchAppManifest& Manifest;
363 const FBuildPatchAppManifest& OtherManifest;
364 const TArray<FString> BuildFiles;
365 const TArray<FString> OtherBuildFiles;
368 TArray<uint8> TestBuffer;
369 };
370}
#define check(expr)
Definition AssertionMacros.h:314
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
uint8_t uint8
Definition binka_ue_file_header.h:8
Definition BlockStructure.h:37
const FBlockEntry * GetHead() const
Definition BlockStructure.cpp:181
Definition BuildDataVerifier.h:22
void GetChunkData(const FChunkPart &ChunkPart, TArray< uint8 > &OutData, FParallelChunkWriterSummaries *ChunkWriterSummaries=nullptr)
Definition BuildDataVerifier.h:49
FBuildDataVerifier(IFileSystem *InFileSystem, IChunkDataSerialization *InChunkDataSerialization, const FString &InBuildLocation, const FString &InOtherBuildLocation, const FString &InCloudDir, const FBuildPatchAppManifest &InManifest, const FBuildPatchAppManifest &InOtherManifest)
Definition BuildDataVerifier.h:24
void GetBuildData(const FBlockStructure &BlockStructure, TArray< uint8 > &OutData, bool bUseOther=false)
Definition BuildDataVerifier.h:123
FArchive * LoadFile(const FString &BuildFile, bool bUseOther)
Definition BuildDataVerifier.h:37
void CheckDataAndAssert(const FScannerFilesList &ChunkDList, const IDeltaChunkEnumeration *DeltaChunkEnumeration, const TArray< uint8 > &ScannerData, bool bUseOther=false)
Definition BuildDataVerifier.h:270
void GetBuildData(const FBlockRange &BlockRange, TArray< uint8 > &OutData, bool bUseOther=false)
Definition BuildDataVerifier.h:88
void CheckDataAndAssert(const FBlockStructure &BlockStructure, const FBlockStructure &OtherBlockStructure)
Definition BuildDataVerifier.h:179
void CheckDataAndAssert(const FBlockStructure &BlockStructure, const FSHAHash &SHAHash)
Definition BuildDataVerifier.h:147
void GetFileData(const FString &BuildFilename, const FBlockRange &BlockRange, TArray< uint8 > &OutData, bool bUseOther=false)
Definition BuildDataVerifier.h:78
void CheckDataAndAssert(const FBlockStructure &BlockStructure, const FChunkPart &ChunkPart, bool bUseOther=false)
Definition BuildDataVerifier.h:221
void CheckDataAndAssert(const IDeltaChunkEnumeration *DeltaChunkEnumeration, const FChunkBuildReference &ChunkBuildReference)
Definition BuildDataVerifier.h:158
void CheckDataAndAssert(const FBlockStructure &BlockStructure, const uint8 *Data)
Definition BuildDataVerifier.h:136
void FindDifferences(const FFileManifestList &FileManifestListA, const FFileManifestList &FileManifestListB)
Definition BuildDataVerifier.h:322
void CheckDataAndAssert(const FFileManifestList &FileManifestList, FParallelChunkWriterSummaries *ChunkWriterSummaries=nullptr)
Definition BuildDataVerifier.h:193
void CheckDataAndAssert(FChunkSearcher::FChunkDList &ChunkDList, bool bUseOther=false)
Definition BuildDataVerifier.h:242
void FindDifferences(const FFileManifestList &FileManifestList, FChunkSearcher::FFileDListNode *FileHead)
Definition BuildDataVerifier.h:295
FFileDList::TDoubleLinkedListNode FFileDListNode
Definition ChunkSearch.h:114
virtual IChunkDataAccess * LoadFromFile(const FString &Filename, EChunkLoadResult &OutLoadResult) const =0
Definition DeltaEnumeration.h:25
Definition FileSystem.h:51
virtual TUniquePtr< FArchive > CreateFileReader(const TCHAR *Filename, EReadFlags ReadFlags=EReadFlags::None) const =0
Definition Archive.h:1208
Definition BuildPatchManifest.h:64
virtual const BuildPatchServices::FChunkInfo * GetChunkInfo(const FGuid &ChunkGuid) const
Definition BuildPatchManifest.cpp:1069
Definition SecureHash.h:226
Definition Array.h:670
UE_FORCEINLINE_HINT SizeType AddUninitialized()
Definition Array.h:1664
UE_REWRITE SizeType Num() const
Definition Array.h:1144
UE_NODEBUG UE_FORCEINLINE_HINT ElementType * GetData() UE_LIFETIMEBOUND
Definition Array.h:1027
void Append(const TArray< OtherElementType, OtherAllocatorType > &Source)
Definition Array.h:2412
void SetNumUninitialized(SizeType NewNum, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2369
const ElementType & GetValue() const
Definition List.h:452
Definition UnrealString.h.inl:34
Definition UniquePtr.h:107
bool IsValid() const
Definition UniquePtr.h:280
UE_FORCEINLINE_HINT T * Get() const
Definition UniquePtr.h:324
Definition BuildPatchFileConstructor.h:28
FSHAHash GetShaForDataSet(const uint8 *Data, uint32 Size)
Definition ChunkDeltaOptimiser.cpp:59
Definition BlockStructure.h:10
Definition BlockRange.h:13
static FBlockRange FromIntersection(const FBlockRange &RangeA, const FBlockRange &RangeB)
Definition BlockRange.h:57
static FBlockRange FromFirstAndSize(uint64 InFirst, uint64 InSize)
Definition BlockRange.h:42
Definition ChunkData.h:188
uint32 Offset
Definition ChunkData.h:217
FGuid Guid
Definition ChunkData.h:215
uint32 Size
Definition ChunkData.h:219
bool IsPadding() const
Definition ChunkData.h:202
uint8 GetPaddingByte() const
Definition ChunkData.h:210
Definition ManifestData.h:159
TArray< FFileManifest > FileList
Definition ManifestData.h:173
Definition ManifestData.h:140
uint64 FileSize
Definition ManifestData.h:155
TArray< FChunkPart > ChunkParts
Definition ManifestData.h:153
uint8 * GetData() const
Definition ChunkData.cpp:427
static FString GetDataFilename(const FBuildPatchAppManifestRef &Manifest, const FGuid &DataGUID)
Definition BuildPatchUtil.cpp:96
static FString GetChunkNewFilename(BuildPatchServices::EFeatureLevel FeatureLevel, const FGuid &ChunkGUID, const uint64 &ChunkHash)
Definition BuildPatchUtil.cpp:19
bool IsValid() const
Definition Guid.h:318
static UE_FORCEINLINE_HINT int32 Memcmp(const void *Buf1, const void *Buf2, SIZE_T Count)
Definition UnrealMemory.h:114
static UE_FORCEINLINE_HINT void * Memset(void *Dest, uint8 Char, SIZE_T Count)
Definition UnrealMemory.h:119