A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
DlgTesterHelper.h
Go to the documentation of this file.
1// Copyright Csaba Molnar, Daniel Butum. All Rights Reserved.
2#pragma once
3
4#include <functional>
5#include "CoreMinimal.h"
6#include "UObject/NoExportTypes.h"
7
8#include "DlgHelper.h"
9
10template <typename ArrayType>
12{
13public:
14 static bool IsEqual(const TArray<ArrayType>& ThisArray, const TArray<ArrayType>& OtherArray,
15 const FString& PropertyName, FString& OutError, const bool bIsPrimitive,
16 std::function<FString(const ArrayType&)> GetArrayTypeAsString,
17 std::function<bool(const ArrayType& FirstValue, const ArrayType& SecondValue, FString& ComparisonErrorMessage)> AreValuesEqual)
18 {
19 bool bIsEqual = true;
20 auto AreValuesEqualWithoutMessage = [&AreValuesEqual](const ArrayType& FirstValue, const ArrayType& SecondValue) -> bool
21 {
22 FString DiscardMessage;
23 return AreValuesEqual(FirstValue, SecondValue, DiscardMessage);
24 };
25
26 if (FDlgHelper::IsArrayEqual<ArrayType>(ThisArray, OtherArray, AreValuesEqualWithoutMessage) == false)
27 {
28 bIsEqual = false;
29 if (ThisArray.Num() != OtherArray.Num())
30 {
31 OutError += FString::Printf(
32 TEXT("\tThis.%s.Num (%d) != Other.%s.Num (%d)\n"),
33 *PropertyName, ThisArray.Num(), *PropertyName, OtherArray.Num());
34 }
35
36 // Find which element is different
37 for (int32 Index = 0; Index < ThisArray.Num() && Index < OtherArray.Num(); Index++)
38 {
39 // Values differ
40 FString ComparisonErrorMessage;
41 if (!AreValuesEqual(ThisArray[Index], OtherArray[Index], ComparisonErrorMessage))
42 {
43 if (bIsPrimitive)
44 {
45 OutError += FString::Printf(TEXT("\tThis.%s[%d] (%d) != Other.%s[%d] (%d)\n"),
46 *PropertyName, Index, *GetArrayTypeAsString(ThisArray[Index]), *PropertyName, Index, *GetArrayTypeAsString(OtherArray[Index]));
47 }
48 else
49 {
50 OutError += FString::Printf(TEXT("\tThis.%s[%d] != Other.%s[%d] |message = %s|\n"),
51 *PropertyName, Index, *PropertyName, Index, *ComparisonErrorMessage);
52 }
53 }
54 }
55 }
56
57 return bIsEqual;
58 }
59};
60
61// Variant with default comparison
62template <typename ArrayType>
64{
65public:
66 static bool IsEqual(const TArray<ArrayType>& ThisArray, const TArray<ArrayType>& OtherArray,
67 const FString& PropertyName, FString& OutError,
68 std::function<FString(const ArrayType&)> GetArrayTypeAsString)
69 {
70 return FDlgTestHelper_ArrayEqualImpl<ArrayType>::IsEqual(ThisArray, OtherArray, PropertyName, OutError, true, GetArrayTypeAsString,
71 [](const ArrayType& FirstValue, const ArrayType& SecondValue, FString& ComparisonErrorMessage) -> bool
72 {
73 return FirstValue == SecondValue;
74 });
75 }
76};
77
78// Variant for float
79template <>
81{
82public:
83 static bool IsEqual(const TArray<float>& ThisArray, const TArray<float>& OtherArray,
84 const FString& PropertyName, FString& OutError,
85 std::function<FString(const float&)> GetArrayTypeAsString)
86 {
87 return FDlgTestHelper_ArrayEqualImpl<float>::IsEqual(ThisArray, OtherArray, PropertyName, OutError, true, GetArrayTypeAsString,
88 [](const float& FirstValue, const float& SecondValue, FString& ComparisonErrorMessage) -> bool
89 {
90 return FMath::IsNearlyEqual(FirstValue, SecondValue, KINDA_SMALL_NUMBER);
91 });
92 }
93};
94
95
96// NOTE for SetType = float this won't work, what are you even doing?
97template <typename SetType>
99{
100public:
101 static bool IsEqual(const TSet<SetType>& ThisSet, const TSet<SetType>& OtherSet,
102 const FString& PropertyName, FString& OutError,
103 std::function<FString(const SetType&)> GetSetTypeAsString)
104 {
105 bool bIsEqual = true;
106 if (FDlgHelper::IsSetEqual<SetType>(ThisSet, OtherSet) == false)
107 {
108 bIsEqual = false;
109 if (ThisSet.Num() != OtherSet.Num())
110 {
111 OutError += FString::Printf(
112 TEXT("\tThis.%s.Num (%d) != Other.%s.Num (%d)\n"),
113 *PropertyName, ThisSet.Num(), *PropertyName, OtherSet.Num());
114 }
115
116 // Find The set that is different from the other
117 const TSet<SetType> NotInOther = ThisSet.Difference(OtherSet);
118 OutError += FString::Printf(
119 TEXT("\tNotInOther = This.%s - Other.%s is of length = %d\n"),
120 *PropertyName, *PropertyName, NotInOther.Num());
121
122 FString NotInOtherString;
123 for (const SetType& ValueInOther : NotInOther)
124 {
125 NotInOtherString += FString::Printf(TEXT("%s,"), *GetSetTypeAsString(ValueInOther));
126 }
127 OutError += FString::Printf(TEXT("\tNotInOther = {%s}\n"), *NotInOtherString);
128 }
129
130 return bIsEqual;
131 }
132};
133
134template <typename KeyType, typename ValueType>
136{
137public:
138 static bool IsEqual(const TMap<KeyType, ValueType>& ThisMap, const TMap<KeyType, ValueType>& OtherMap,
139 const FString& PropertyName, FString& OutError, const bool bIsValuePrimitive,
140 std::function<FString(const KeyType&)> GetKeyTypeAsString,
141 std::function<FString(const ValueType&)> GetValueTypeAsString,
142 std::function<bool(const ValueType& FirstValue, const ValueType& SecondValue, FString& ComparisonErrorMessage)> AreValuesEqual)
143 {
144 bool bIsEqual = true;
145 auto AreValuesEqualWithoutMessage = [&AreValuesEqual](const ValueType& FirstValue, const ValueType& SecondValue) -> bool
146 {
147 FString DiscardMessage;
148 return AreValuesEqual(FirstValue, SecondValue, DiscardMessage);
149 };
150
151 if (FDlgHelper::IsMapEqual<KeyType, ValueType>(ThisMap, OtherMap, AreValuesEqualWithoutMessage) == false)
152 {
153 bIsEqual = false;
154 if (ThisMap.Num() != OtherMap.Num())
155 {
156 OutError += FString::Printf(
157 TEXT("\tThis.%s.Num (%d) != Other.%s.Num (%d)\n"),
158 *PropertyName, ThisMap.Num(), *PropertyName, OtherMap.Num());
159 }
160
161 // Find values in ThisMap that do not exist in OtherMap
162 int32 NumKeysNotInOther = 0;
163 FString KeysNotInOtherString;
164 FString ValuesThatDifferString;
165 const bool OtherMapIsEmpty = OtherMap.Num() == 0;
166 for (const auto& ThisElem : ThisMap)
167 {
168 const ValueType* OtherMapValue = OtherMap.Find(ThisElem.Key);
169 if (OtherMapValue != nullptr)
170 {
171 FString ComparisonErrorMessage;
172 if (!AreValuesEqual(ThisElem.Value, *OtherMapValue, ComparisonErrorMessage))
173 {
174 if (bIsValuePrimitive)
175 {
176 ValuesThatDifferString += FString::Printf(
177 TEXT("\tThis.%s[key] (%s) != Other.%s[key] (%s). Key = (%s)\n"),
178 *PropertyName, *GetValueTypeAsString(ThisElem.Value),
179 *PropertyName, *GetValueTypeAsString(*OtherMapValue),
180 *GetKeyTypeAsString(ThisElem.Key));
181 }
182 else
183 {
184 ValuesThatDifferString += FString::Printf(
185 TEXT("\tThis.%s[key] (%s) != Other.%s[key] (%s). Key = (%s). |Message = %s|\n"),
186 *PropertyName, *GetValueTypeAsString(ThisElem.Value),
187 *PropertyName, *GetValueTypeAsString(*OtherMapValue),
188 *GetKeyTypeAsString(ThisElem.Key), *ComparisonErrorMessage);
189 }
190 }
191 }
192 else
193 {
194 KeysNotInOtherString += FString::Printf(TEXT("%s,"), *GetKeyTypeAsString(ThisElem.Key));
195 NumKeysNotInOther++;
196 }
197 }
198
199
200 if (OtherMapIsEmpty)
201 {
202 OutError += FString::Printf(TEXT("\tOther.%s IS EMPTY\n"), *PropertyName);
203 }
204 else
205 {
206 FString OtherStringKeys;
207 for (const auto& OtherElem : OtherMap)
208 {
209 OtherStringKeys += FString::Printf(TEXT("%s,"), *GetKeyTypeAsString(OtherElem.Key));
210 }
211 OutError += FString::Printf(TEXT("\tOther.%s KEYS (Num = %d) = {%s}\n"),
212 *PropertyName, OtherMap.Num(), *OtherStringKeys);
213 }
214
215 OutError += FString::Printf(TEXT("\tKeys that ONLY exist in This.%s (Num = %d) = {%s}\n"),
216 *PropertyName, NumKeysNotInOther, *KeysNotInOtherString);
217 OutError += FString::Printf(TEXT("\tValues that differ:\n%s\n"), *ValuesThatDifferString);
218 }
219
220 return bIsEqual;
221 }
222};
223
224
225// Variant with default comparison
226template <typename KeyType, typename ValueType>
228{
229public:
230 static bool IsEqual(const TMap<KeyType, ValueType>& ThisMap, const TMap<KeyType, ValueType>& OtherMap,
231 const FString& PropertyName, FString& OutError,
232 std::function<FString(const KeyType&)> GetKeyTypeAsString,
233 std::function<FString(const ValueType&)> GetValueTypeAsString)
234 {
235 return FDlgTestHelper_MapEqualImpl<KeyType, ValueType>::IsEqual(ThisMap, OtherMap, PropertyName, OutError, true, GetKeyTypeAsString, GetValueTypeAsString,
236 [](const ValueType& FirstMapValue, const ValueType& SecondMapValue, FString& ComparisonErrorMessage) -> bool
237 {
238 return FirstMapValue == SecondMapValue;
239 });
240 }
241};
242
243// Variant for float
244template <typename KeyType>
246{
247public:
248 static bool IsEqual(const TMap<KeyType, float>& ThisMap, const TMap<KeyType, float>& OtherMap,
249 const FString& PropertyName, FString& OutError,
250 std::function<FString(const KeyType&)> GetKeyTypeAsString,
251 std::function<FString(const float&)> GetValueTypeAsString)
252 {
253 return FDlgTestHelper_MapEqualImpl<KeyType, float>::IsEqual(ThisMap, OtherMap, PropertyName, OutError, true, GetKeyTypeAsString, GetValueTypeAsString,
254 [](const float& FirstMapValue, const float& SecondMapValue, FString& ComparisonErrorMessage) -> bool
255 {
256 return FMath::IsNearlyEqual(FirstMapValue, SecondMapValue, KINDA_SMALL_NUMBER);
257 });
258 }
259};
260
265{
266public:
267
268
269 template <typename ValueType>
270 static void CheckMapStringKeyInvariants(const TMap<FString, ValueType>& ThisMap)
271 {
272 for (const auto& Elem : ThisMap)
273 {
274 // Most likely the map is corrupted
275 check((void*)(*Elem.Key) != nullptr);
276 Elem.Key.CheckInvariants();
277 }
278 }
279
280 template <typename SetType>
281 static bool IsSetEqual(const TSet<SetType>& ThisSet, const TSet<SetType>& OtherSet,
282 const FString& PropertyName, FString& OutError, std::function<FString(const SetType&)> GetSetTypeAsString)
283 {
284 return FDlgTestHelper_SetEqualImpl<SetType>::IsEqual(ThisSet, OtherSet, PropertyName, OutError, GetSetTypeAsString);
285 }
286
287 template <typename KeyType, typename ValueType>
288 static bool IsPrimitiveMapEqual(const TMap<KeyType, ValueType>& ThisMap, const TMap<KeyType, ValueType>& OtherMap,
289 const FString& PropertyName, FString& OutError,
290 std::function<FString(const KeyType&)> GetKeyTypeAsString,
291 std::function<FString(const ValueType&)> GetValueTypeAsString)
292 {
293 return FDlgTestHelper_MapPrimitiveVariantImpl<KeyType, ValueType>::IsEqual(ThisMap, OtherMap, PropertyName, OutError, GetKeyTypeAsString, GetValueTypeAsString);
294 }
295
296 template <typename KeyType, typename ValueType>
297 static bool IsComplexMapValueEqual(const TMap<KeyType, ValueType>& ThisMap, const TMap<KeyType, ValueType>& OtherMap,
298 const FString& PropertyName, FString& OutError,
299 std::function<FString(const KeyType&)> GetKeyTypeAsString,
300 std::function<FString(const ValueType&)> GetValueTypeAsString)
301 {
302 return FDlgTestHelper_MapEqualImpl<KeyType, ValueType>::IsEqual(ThisMap, OtherMap, PropertyName, OutError, false, GetKeyTypeAsString, GetValueTypeAsString,
303 [](const ValueType& FirstMapValue, const ValueType& SecondMapValue, FString& ComparisonErrorMessage) -> bool
304 {
305 return FirstMapValue.IsEqual(SecondMapValue, ComparisonErrorMessage);
306 });
307 }
308
309 template <typename KeyType, typename ValueType>
310 static bool IsComplexPointersMapEqual(const TMap<KeyType, ValueType*>& ThisMap, const TMap<KeyType, ValueType*>& OtherMap,
311 const FString& PropertyName, FString& OutError,
312 std::function<FString(const KeyType&)> GetKeyTypeAsString)
313 {
314 return FDlgTestHelper_MapEqualImpl<KeyType, ValueType*>::IsEqual(ThisMap, OtherMap, PropertyName, OutError, false, GetKeyTypeAsString,
315 [](const auto* Object) -> FString
316 {
318 },
319 [](const auto* FirstMapValue, const auto* SecondMapValue, FString& ComparisonErrorMessage) -> bool
320 {
321 if (FirstMapValue == nullptr)
322 {
323 ComparisonErrorMessage = TEXT("FirstMapValue is nullptr");
324 return SecondMapValue == nullptr;
325 }
326 return FirstMapValue->IsEqual(SecondMapValue, ComparisonErrorMessage);
327 });
328 }
329
330 template <typename ArrayType>
331 static bool IsPrimitiveArrayEqual(const TArray<ArrayType>& ThisArray, const TArray<ArrayType>& OtherArray,
332 const FString& PropertyName, FString& OutError, std::function<FString(const ArrayType&)> GetArrayTypeAsString)
333 {
334 return FDlgTestHelper_ArrayPrimitiveVariantImpl<ArrayType>::IsEqual(ThisArray, OtherArray, PropertyName, OutError, GetArrayTypeAsString);
335 }
336
337 template <typename ArrayType>
338 static bool IsComplexArrayEqual(const TArray<ArrayType>& ThisArray, const TArray<ArrayType>& OtherArray,
339 const FString& PropertyName, FString& OutError)
340 {
341 return FDlgTestHelper_ArrayEqualImpl<ArrayType>::IsEqual(ThisArray, OtherArray, PropertyName, OutError, false,
342 [](const ArrayType& Value) -> FString
343 {
344 return TEXT("IsComplexArrayEqual SHOULD NOT SEE THIS");
345 },
346 [](const ArrayType& FirstValue, const ArrayType& SecondValue, FString& ComparisonErrorMessage) -> bool
347 {
348 return FirstValue.IsEqual(SecondValue, ComparisonErrorMessage);
349 });
350 }
351
352 template <typename ArrayType>
353 static bool IsComplexPointerArrayEqual(const TArray<ArrayType*>& ThisArray, const TArray<ArrayType*>& OtherArray,
354 const FString& PropertyName, FString& OutError)
355 {
356 return FDlgTestHelper_ArrayEqualImpl<ArrayType*>::IsEqual(ThisArray, OtherArray, PropertyName, OutError, false,
357 [](const auto* Value) -> FString
358 {
359 return Value ? Value->ToString() : "";
360 },
361 [](const auto* FirstValue, const auto* SecondValue, FString& ComparisonErrorMessage) -> bool
362 {
363 if (FirstValue == nullptr)
364 {
365 ComparisonErrorMessage = TEXT("FirstValue is nullptr");
366 return SecondValue == nullptr;
367 }
368 return FirstValue->IsEqual(SecondValue, ComparisonErrorMessage);
369 });
370 }
371
372 static std::function<FString(const int32&)> Int32ToString;
373 static std::function<FString(const int64&)> Int64ToString;
374 static std::function<FString(const FName&)> NameToString;
375 static std::function<FString(const FString&)> StringToString;
376 static std::function<FString(const float&)> FloatToString;
377 static std::function<FString(const FVector&)> VectorToString;
378 static std::function<FString(const FColor&)> ColorToString;
379};
static FString GetFullNameFromObject(const UObject *Object)
Definition DlgHelper.h:226
static bool IsEqual(const TArray< ArrayType > &ThisArray, const TArray< ArrayType > &OtherArray, const FString &PropertyName, FString &OutError, const bool bIsPrimitive, std::function< FString(const ArrayType &)> GetArrayTypeAsString, std::function< bool(const ArrayType &FirstValue, const ArrayType &SecondValue, FString &ComparisonErrorMessage)> AreValuesEqual)
static bool IsEqual(const TArray< float > &ThisArray, const TArray< float > &OtherArray, const FString &PropertyName, FString &OutError, std::function< FString(const float &)> GetArrayTypeAsString)
static bool IsEqual(const TArray< ArrayType > &ThisArray, const TArray< ArrayType > &OtherArray, const FString &PropertyName, FString &OutError, std::function< FString(const ArrayType &)> GetArrayTypeAsString)
static bool IsEqual(const TMap< KeyType, float > &ThisMap, const TMap< KeyType, float > &OtherMap, const FString &PropertyName, FString &OutError, std::function< FString(const KeyType &)> GetKeyTypeAsString, std::function< FString(const float &)> GetValueTypeAsString)
static bool IsEqual(const TMap< KeyType, ValueType > &ThisMap, const TMap< KeyType, ValueType > &OtherMap, const FString &PropertyName, FString &OutError, std::function< FString(const KeyType &)> GetKeyTypeAsString, std::function< FString(const ValueType &)> GetValueTypeAsString)
static bool IsEqual(const TMap< KeyType, ValueType > &ThisMap, const TMap< KeyType, ValueType > &OtherMap, const FString &PropertyName, FString &OutError, const bool bIsValuePrimitive, std::function< FString(const KeyType &)> GetKeyTypeAsString, std::function< FString(const ValueType &)> GetValueTypeAsString, std::function< bool(const ValueType &FirstValue, const ValueType &SecondValue, FString &ComparisonErrorMessage)> AreValuesEqual)
static bool IsEqual(const TSet< SetType > &ThisSet, const TSet< SetType > &OtherSet, const FString &PropertyName, FString &OutError, std::function< FString(const SetType &)> GetSetTypeAsString)
static std::function< FString(const FName &) NameToString)
static std::function< FString(const int32 &) Int32ToString)
static bool IsComplexArrayEqual(const TArray< ArrayType > &ThisArray, const TArray< ArrayType > &OtherArray, const FString &PropertyName, FString &OutError)
static std::function< FString(const FVector &) VectorToString)
static bool IsPrimitiveMapEqual(const TMap< KeyType, ValueType > &ThisMap, const TMap< KeyType, ValueType > &OtherMap, const FString &PropertyName, FString &OutError, std::function< FString(const KeyType &)> GetKeyTypeAsString, std::function< FString(const ValueType &)> GetValueTypeAsString)
static bool IsComplexPointersMapEqual(const TMap< KeyType, ValueType * > &ThisMap, const TMap< KeyType, ValueType * > &OtherMap, const FString &PropertyName, FString &OutError, std::function< FString(const KeyType &)> GetKeyTypeAsString)
static std::function< FString(const float &) FloatToString)
static bool IsComplexPointerArrayEqual(const TArray< ArrayType * > &ThisArray, const TArray< ArrayType * > &OtherArray, const FString &PropertyName, FString &OutError)
static std::function< FString(const FString &) StringToString)
static bool IsPrimitiveArrayEqual(const TArray< ArrayType > &ThisArray, const TArray< ArrayType > &OtherArray, const FString &PropertyName, FString &OutError, std::function< FString(const ArrayType &)> GetArrayTypeAsString)
static bool IsComplexMapValueEqual(const TMap< KeyType, ValueType > &ThisMap, const TMap< KeyType, ValueType > &OtherMap, const FString &PropertyName, FString &OutError, std::function< FString(const KeyType &)> GetKeyTypeAsString, std::function< FString(const ValueType &)> GetValueTypeAsString)
static std::function< FString(const FColor &) ColorToString)
static bool IsSetEqual(const TSet< SetType > &ThisSet, const TSet< SetType > &OtherSet, const FString &PropertyName, FString &OutError, std::function< FString(const SetType &)> GetSetTypeAsString)
static void CheckMapStringKeyInvariants(const TMap< FString, ValueType > &ThisMap)
static std::function< FString(const int64 &) Int64ToString)