356 lines
14 KiB
C++
356 lines
14 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "CoreTypes.h"
|
|
|
|
#include "Misc/PackageName.h"
|
|
#include "TestHarness.h"
|
|
|
|
TEST_CASE("Split full object path with subobjects", "[CoreUObject][FPackageName::SplitFullObjectPath]")
|
|
{
|
|
const FStringView ExpectedClassPath = TEXT("/Script/SomePackage.SomeClass");
|
|
const FStringView ExpectedPackagePath = TEXT("/Path/To/A/Package");
|
|
const FStringView ExpectedObjectName = TEXT("Object");
|
|
const FStringView ExpectedSubobject1Name = TEXT("Subobject1");
|
|
const FStringView ExpectedSubobject2Name = TEXT("Subobject2");
|
|
|
|
// Good cases
|
|
const FStringView TestSingleSubobject = TEXT("/Script/SomePackage.SomeClass /Path/To/A/Package.Object:Subobject1");
|
|
const FStringView TestTwoSubobjects = TEXT("/Script/SomePackage.SomeClass /Path/To/A/Package.Object:Subobject1.Subobject2");
|
|
const FStringView TestNoSubobjects = TEXT("/Script/SomePackage.SomeClass /Path/To/A/Package.Object");
|
|
const FStringView TestTwoSubobjectsAndNoClassPath = TEXT("/Path/To/A/Package.Object:Subobject1.Subobject2");
|
|
const FStringView TestPackage = TEXT("/Script/SomePackage.SomeClass /Path/To/A/Package");
|
|
|
|
// Suspicious cases
|
|
const FStringView TestMissingSubobject = TEXT("/Script/SomePackage.SomeClass /Path/To/A/Package.Object:");
|
|
const FStringView TestMissingSubobjectWithTrailingDot = TEXT("/Script/SomePackage.SomeClass /Path/To/A/Package.Object:.");
|
|
const FStringView TestValidSubobjectWithTrailingDot = TEXT("/Script/SomePackage.SomeClass /Path/To/A/Package.Object:Subobject1.");
|
|
const FStringView TestTwoValidSubobjectsWithTrailingDot = TEXT("/Script/SomePackage.SomeClass /Path/To/A/Package.Object:Subobject1.Subobject2.");
|
|
|
|
FStringView ClassPath;
|
|
FStringView PackagePath;
|
|
FStringView ObjectName;
|
|
TArray<FStringView> SubobjectNames;
|
|
|
|
SECTION("Single subobject verification")
|
|
{
|
|
FPackageName::SplitFullObjectPath(TestSingleSubobject, ClassPath, PackagePath, ObjectName, SubobjectNames);
|
|
|
|
REQUIRE(ClassPath == ExpectedClassPath);
|
|
REQUIRE(PackagePath == ExpectedPackagePath);
|
|
REQUIRE(ObjectName == ExpectedObjectName);
|
|
REQUIRE(SubobjectNames.Num() == 1);
|
|
REQUIRE(SubobjectNames[0] == ExpectedSubobject1Name);
|
|
}
|
|
|
|
SECTION("Two subobjects verification")
|
|
{
|
|
FPackageName::SplitFullObjectPath(TestTwoSubobjects, ClassPath, PackagePath, ObjectName, SubobjectNames);
|
|
|
|
REQUIRE(ClassPath == ExpectedClassPath);
|
|
REQUIRE(PackagePath == ExpectedPackagePath);
|
|
REQUIRE(ObjectName == ExpectedObjectName);
|
|
REQUIRE(SubobjectNames.Num() == 2);
|
|
REQUIRE(SubobjectNames[0] == ExpectedSubobject1Name);
|
|
REQUIRE(SubobjectNames[1] == ExpectedSubobject2Name);
|
|
}
|
|
|
|
SECTION("No subobjects verification")
|
|
{
|
|
FPackageName::SplitFullObjectPath(TestNoSubobjects, ClassPath, PackagePath, ObjectName, SubobjectNames);
|
|
|
|
REQUIRE(ClassPath == ExpectedClassPath);
|
|
REQUIRE(PackagePath == ExpectedPackagePath);
|
|
REQUIRE(ObjectName == ExpectedObjectName);
|
|
REQUIRE(SubobjectNames.Num() == 0);
|
|
}
|
|
|
|
SECTION("No class path verification (bDetectClassName on)")
|
|
{
|
|
FPackageName::SplitFullObjectPath(TestTwoSubobjectsAndNoClassPath, ClassPath, PackagePath, ObjectName, SubobjectNames);
|
|
|
|
REQUIRE(ClassPath.Len() == 0);
|
|
REQUIRE(PackagePath == ExpectedPackagePath);
|
|
REQUIRE(ObjectName == ExpectedObjectName);
|
|
REQUIRE(SubobjectNames.Num() == 2);
|
|
REQUIRE(SubobjectNames[0] == ExpectedSubobject1Name);
|
|
REQUIRE(SubobjectNames[1] == ExpectedSubobject2Name);
|
|
}
|
|
|
|
SECTION("No class path verification (bDetectClassName off)")
|
|
{
|
|
FPackageName::SplitFullObjectPath(TestTwoSubobjectsAndNoClassPath, ClassPath, PackagePath, ObjectName, SubobjectNames, false);
|
|
|
|
REQUIRE(ClassPath.Len() == 0);
|
|
REQUIRE(PackagePath == ExpectedPackagePath);
|
|
REQUIRE(ObjectName == ExpectedObjectName);
|
|
REQUIRE(SubobjectNames.Num() == 2);
|
|
REQUIRE(SubobjectNames[0] == ExpectedSubobject1Name);
|
|
REQUIRE(SubobjectNames[1] == ExpectedSubobject2Name);
|
|
}
|
|
|
|
SECTION("Package verification")
|
|
{
|
|
FPackageName::SplitFullObjectPath(TestPackage, ClassPath, PackagePath, ObjectName, SubobjectNames);
|
|
|
|
REQUIRE(ClassPath == ExpectedClassPath);
|
|
REQUIRE(PackagePath == ExpectedPackagePath);
|
|
REQUIRE(ObjectName == TEXT(""));
|
|
REQUIRE(SubobjectNames.Num() == 0);
|
|
}
|
|
|
|
SECTION("Missing subobject name yields empty subobjects array")
|
|
{
|
|
FPackageName::SplitFullObjectPath(TestMissingSubobject, ClassPath, PackagePath, ObjectName, SubobjectNames);
|
|
|
|
REQUIRE(ClassPath == ExpectedClassPath);
|
|
REQUIRE(PackagePath == ExpectedPackagePath);
|
|
REQUIRE(ObjectName == ExpectedObjectName);
|
|
REQUIRE(SubobjectNames.Num() == 0);
|
|
}
|
|
|
|
SECTION("Missing subobject name with trailing dot yields empty subobjects array")
|
|
{
|
|
FPackageName::SplitFullObjectPath(TestMissingSubobjectWithTrailingDot, ClassPath, PackagePath, ObjectName, SubobjectNames);
|
|
|
|
REQUIRE(ClassPath == ExpectedClassPath);
|
|
REQUIRE(PackagePath == ExpectedPackagePath);
|
|
REQUIRE(ObjectName == ExpectedObjectName);
|
|
REQUIRE(SubobjectNames.Num() == 0);
|
|
}
|
|
|
|
SECTION("Valid subobject with trailing dot still reports correct subobject name")
|
|
{
|
|
FPackageName::SplitFullObjectPath(TestValidSubobjectWithTrailingDot, ClassPath, PackagePath, ObjectName, SubobjectNames);
|
|
|
|
REQUIRE(ClassPath == ExpectedClassPath);
|
|
REQUIRE(PackagePath == ExpectedPackagePath);
|
|
REQUIRE(ObjectName == ExpectedObjectName);
|
|
REQUIRE(SubobjectNames.Num() == 1);
|
|
REQUIRE(SubobjectNames[0] == ExpectedSubobject1Name);
|
|
}
|
|
|
|
SECTION("Two valid subobjects with trailing dot still reports correct subobject names")
|
|
{
|
|
FPackageName::SplitFullObjectPath(TestTwoValidSubobjectsWithTrailingDot, ClassPath, PackagePath, ObjectName, SubobjectNames);
|
|
|
|
REQUIRE(ClassPath == ExpectedClassPath);
|
|
REQUIRE(PackagePath == ExpectedPackagePath);
|
|
REQUIRE(ObjectName == ExpectedObjectName);
|
|
REQUIRE(SubobjectNames.Num() == 2);
|
|
REQUIRE(SubobjectNames[0] == ExpectedSubobject1Name);
|
|
REQUIRE(SubobjectNames[1] == ExpectedSubobject2Name);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Split PackageName", "[CoreUObject][FPackageName::SplitPackageName]")
|
|
{
|
|
FString PackageName(TEXT("/root/path1/path2/leaf.umap"));
|
|
|
|
// Test that not passing outputs does not crash
|
|
FPackageName::SplitPackageName(PackageName, nullptr, nullptr, nullptr);
|
|
|
|
FStringView Root;
|
|
FStringView Path;
|
|
FStringView Leaf;
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf);
|
|
REQUIRE(Root == TEXTVIEW("/root/"));
|
|
REQUIRE(Path == TEXTVIEW("path1/path2/"));
|
|
REQUIRE(Leaf == TEXTVIEW("leaf.umap"));
|
|
|
|
PackageName = TEXTVIEW("/root/path1/path2/");
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf);
|
|
REQUIRE(Root == TEXTVIEW("/root/"));
|
|
REQUIRE(Path == TEXTVIEW("path1/path2/"));
|
|
REQUIRE(Leaf == TEXTVIEW(""));
|
|
|
|
PackageName = TEXTVIEW("/root/path1/leaf");
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf);
|
|
REQUIRE(Root == TEXTVIEW("/root/"));
|
|
REQUIRE(Path == TEXTVIEW("path1/"));
|
|
REQUIRE(Leaf == TEXTVIEW("leaf"));
|
|
|
|
PackageName = TEXTVIEW("/root/path1/");
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf);
|
|
REQUIRE(Root == TEXTVIEW("/root/"));
|
|
REQUIRE(Path == TEXTVIEW("path1/"));
|
|
REQUIRE(Leaf == TEXTVIEW(""));
|
|
|
|
PackageName = TEXTVIEW("/root/leaf");
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf);
|
|
REQUIRE(Root == TEXTVIEW("/root/"));
|
|
REQUIRE(Path == TEXTVIEW(""));
|
|
REQUIRE(Leaf == TEXTVIEW("leaf"));
|
|
|
|
PackageName = TEXTVIEW("/root/");
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf);
|
|
REQUIRE(Root == TEXTVIEW("/root/"));
|
|
REQUIRE(Path == TEXTVIEW(""));
|
|
REQUIRE(Leaf == TEXTVIEW(""));
|
|
|
|
PackageName = TEXTVIEW("/root");
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf);
|
|
REQUIRE(Root == TEXTVIEW(""));
|
|
REQUIRE(Path == TEXTVIEW(""));
|
|
REQUIRE(Leaf == TEXTVIEW(""));
|
|
|
|
PackageName = TEXTVIEW("/");
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf);
|
|
REQUIRE(Root == TEXTVIEW(""));
|
|
REQUIRE(Path == TEXTVIEW(""));
|
|
REQUIRE(Leaf == TEXTVIEW(""));
|
|
|
|
PackageName = TEXTVIEW("");
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf);
|
|
REQUIRE(Root == TEXTVIEW(""));
|
|
REQUIRE(Path == TEXTVIEW(""));
|
|
REQUIRE(Leaf == TEXTVIEW(""));
|
|
|
|
PackageName = TEXTVIEW("path1/path2");
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf);
|
|
REQUIRE(Root == TEXTVIEW(""));
|
|
REQUIRE(Path == TEXTVIEW(""));
|
|
REQUIRE(Leaf == TEXTVIEW(""));
|
|
|
|
// Edge cases with no contract yet; they should not crash
|
|
PackageName = TEXTVIEW("//");
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf);
|
|
|
|
PackageName = TEXTVIEW("///");
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf);
|
|
|
|
// Path formats
|
|
PackageName = TEXTVIEW("/root/path/leaf");
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf, FPackageName::EPathFormatFlags::MountPointNoSlashes);
|
|
REQUIRE(Root == TEXTVIEW("root"));
|
|
REQUIRE(Path == TEXTVIEW("path/"));
|
|
REQUIRE(Leaf == TEXTVIEW("leaf"));
|
|
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf, FPackageName::EPathFormatFlags::MountPointLeadingSlash);
|
|
REQUIRE(Root == TEXTVIEW("/root"));
|
|
REQUIRE(Path == TEXTVIEW("path/"));
|
|
REQUIRE(Leaf == TEXTVIEW("leaf"));
|
|
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf, FPackageName::EPathFormatFlags::MountPointTrailingSlash);
|
|
REQUIRE(Root == TEXTVIEW("root/"));
|
|
REQUIRE(Path == TEXTVIEW("path/"));
|
|
REQUIRE(Leaf == TEXTVIEW("leaf"));
|
|
|
|
FPackageName::SplitPackageName(PackageName, &Root, &Path, &Leaf, FPackageName::EPathFormatFlags::MountPointSlashes);
|
|
REQUIRE(Root == TEXTVIEW("/root/"));
|
|
REQUIRE(Path == TEXTVIEW("path/"));
|
|
REQUIRE(Leaf == TEXTVIEW("leaf"));
|
|
|
|
// Verify Path formats are respected in the FString version
|
|
FString RootStr;
|
|
FString PathStr;
|
|
FString LeafStr;
|
|
PackageName = TEXTVIEW("/root/path/leaf");
|
|
FPackageName::SplitPackageName(PackageName, &RootStr, &PathStr, &LeafStr, FPackageName::EPathFormatFlags::MountPointNoSlashes);
|
|
REQUIRE(RootStr == TEXTVIEW("root"));
|
|
REQUIRE(PathStr == TEXTVIEW("path/"));
|
|
REQUIRE(LeafStr == TEXTVIEW("leaf"));
|
|
|
|
FPackageName::SplitPackageName(PackageName, &RootStr, &PathStr, &LeafStr, FPackageName::EPathFormatFlags::MountPointLeadingSlash);
|
|
REQUIRE(RootStr == TEXTVIEW("/root"));
|
|
REQUIRE(PathStr == TEXTVIEW("path/"));
|
|
REQUIRE(LeafStr == TEXTVIEW("leaf"));
|
|
|
|
FPackageName::SplitPackageName(PackageName, &RootStr, &PathStr, &LeafStr, FPackageName::EPathFormatFlags::MountPointTrailingSlash);
|
|
REQUIRE(RootStr == TEXTVIEW("root/"));
|
|
REQUIRE(PathStr == TEXTVIEW("path/"));
|
|
REQUIRE(LeafStr == TEXTVIEW("leaf"));
|
|
|
|
FPackageName::SplitPackageName(PackageName, &RootStr, &PathStr, &LeafStr, FPackageName::EPathFormatFlags::MountPointSlashes);
|
|
REQUIRE(RootStr == TEXTVIEW("/root/"));
|
|
REQUIRE(PathStr == TEXTVIEW("path/"));
|
|
REQUIRE(LeafStr == TEXTVIEW("leaf"));
|
|
}
|
|
|
|
TEST_CASE("Split PackageNameRoot", "[CoreUObject][FPackageName::SplitPackageNameRoot]")
|
|
{
|
|
FString PackageName(TEXT("/root/path1/path2/leaf.umap"));
|
|
|
|
// Test that not passing outputs does not crash
|
|
(void) FPackageName::SplitPackageNameRoot(PackageName, nullptr);
|
|
|
|
FStringView Root;
|
|
FStringView RelPath;
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath);
|
|
REQUIRE(Root == TEXTVIEW("root"));
|
|
REQUIRE(RelPath == TEXTVIEW("path1/path2/leaf.umap"));
|
|
|
|
PackageName = TEXTVIEW("/root/path1/leaf");
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath);
|
|
REQUIRE(Root == TEXTVIEW("root"));
|
|
REQUIRE(RelPath == TEXTVIEW("path1/leaf"));
|
|
|
|
PackageName = TEXTVIEW("/root/");
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath);
|
|
REQUIRE(Root == TEXTVIEW("root"));
|
|
REQUIRE(RelPath == TEXTVIEW(""));
|
|
|
|
PackageName = TEXTVIEW("/root");
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath);
|
|
REQUIRE(Root == TEXTVIEW("/root"));
|
|
REQUIRE(RelPath == TEXTVIEW(""));
|
|
|
|
PackageName = TEXTVIEW("/");
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath);
|
|
REQUIRE(Root == TEXTVIEW("/"));
|
|
REQUIRE(RelPath == TEXTVIEW(""));
|
|
|
|
PackageName = TEXTVIEW("");
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath);
|
|
REQUIRE(Root == TEXTVIEW(""));
|
|
REQUIRE(RelPath == TEXTVIEW(""));
|
|
|
|
PackageName = TEXTVIEW("path1/path2");
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath);
|
|
REQUIRE(Root == TEXTVIEW(""));
|
|
REQUIRE(RelPath == TEXTVIEW("path1/path2"));
|
|
|
|
// Edge cases with no contract yet; they should not crash
|
|
PackageName = TEXTVIEW("//");
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath);
|
|
|
|
PackageName = TEXTVIEW("///");
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath);
|
|
|
|
// Path formats
|
|
PackageName = TEXTVIEW("/root/path/leaf");
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath, FPackageName::EPathFormatFlags::MountPointNoSlashes);
|
|
REQUIRE(Root == TEXTVIEW("root"));
|
|
REQUIRE(RelPath == TEXTVIEW("path/leaf"));
|
|
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath, FPackageName::EPathFormatFlags::MountPointLeadingSlash);
|
|
REQUIRE(Root == TEXTVIEW("/root"));
|
|
REQUIRE(RelPath == TEXTVIEW("path/leaf"));
|
|
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath, FPackageName::EPathFormatFlags::MountPointTrailingSlash);
|
|
REQUIRE(Root == TEXTVIEW("root/"));
|
|
REQUIRE(RelPath == TEXTVIEW("path/leaf"));
|
|
|
|
Root = FPackageName::SplitPackageNameRoot(PackageName, &RelPath, FPackageName::EPathFormatFlags::MountPointSlashes);
|
|
REQUIRE(Root == TEXTVIEW("/root/"));
|
|
REQUIRE(RelPath == TEXTVIEW("path/leaf"));
|
|
|
|
// Verify Path formats are respected in the FName version
|
|
FString RootStr;
|
|
FString RelPathStr;
|
|
PackageName = TEXTVIEW("/root/path/leaf");
|
|
RootStr = FPackageName::SplitPackageNameRoot(FName(*PackageName), &RelPathStr, FPackageName::EPathFormatFlags::MountPointNoSlashes);
|
|
REQUIRE(RootStr == TEXTVIEW("root"));
|
|
REQUIRE(RelPathStr == TEXTVIEW("path/leaf"));
|
|
|
|
RootStr = FPackageName::SplitPackageNameRoot(FName(*PackageName), &RelPathStr, FPackageName::EPathFormatFlags::MountPointLeadingSlash);
|
|
REQUIRE(RootStr == TEXTVIEW("/root"));
|
|
REQUIRE(RelPathStr == TEXTVIEW("path/leaf"));
|
|
|
|
RootStr = FPackageName::SplitPackageNameRoot(FName(*PackageName), &RelPathStr, FPackageName::EPathFormatFlags::MountPointTrailingSlash);
|
|
REQUIRE(RootStr == TEXTVIEW("root/"));
|
|
REQUIRE(RelPathStr == TEXTVIEW("path/leaf"));
|
|
|
|
RootStr = FPackageName::SplitPackageNameRoot(FName(*PackageName), &RelPathStr, FPackageName::EPathFormatFlags::MountPointSlashes);
|
|
REQUIRE(RootStr == TEXTVIEW("/root/"));
|
|
REQUIRE(RelPathStr == TEXTVIEW("path/leaf"));
|
|
} |