#pragma once #include "SUDSDialogue.h" #include "SUDSScriptNode.h" #include "SUDSScriptNodeText.h" #include "Internationalization/StringTable.h" #include "Internationalization/StringTableRegistry.h" #include "Misc/AutomationTest.h" #include "UObject/Package.h" FORCEINLINE void TestDialogueText(FAutomationTestBase* T, const FString& NameForTest, USUDSDialogue* D, const FString& SpeakerID, const FString& Text) { T->TestEqual(NameForTest, D->GetSpeakerID(), SpeakerID); T->TestEqual(NameForTest, D->GetText().ToString(), Text); } FORCEINLINE bool TestParsedText(FAutomationTestBase* T, const FString& NameForTest, const FSUDSParsedNode* Node, const FString& Speaker, const FString& Text) { if (T->TestNotNull(NameForTest, Node)) { T->TestEqual(NameForTest, Node->NodeType, ESUDSParsedNodeType::Text); T->TestEqual(NameForTest, Node->Identifier, Speaker); T->TestEqual(NameForTest, Node->Text, Text); return true; } return false; } FORCEINLINE bool TestArgValue(FAutomationTestBase* T, const FString& NameForTest, const FSUDSValue& Actual, int Expected) { if (T->TestEqual(NameForTest, Actual.GetType(), ESUDSValueType::Int)) { return T->TestEqual(NameForTest, Actual.GetIntValue(), Expected); } return false; } FORCEINLINE bool TestArgValue(FAutomationTestBase* T, const FString& NameForTest, const FSUDSValue& Actual, float Expected) { if (T->TestEqual(NameForTest, Actual.GetType(), ESUDSValueType::Float)) { return T->TestEqual(NameForTest, Actual.GetFloatValue(), Expected); } return false; } FORCEINLINE bool TestArgValue(FAutomationTestBase* T, const FString& NameForTest, const FSUDSValue& Actual, ETextGender Expected) { if (T->TestEqual(NameForTest, Actual.GetType(), ESUDSValueType::Gender)) { return T->TestEqual(NameForTest, Actual.GetGenderValue(), Expected); } return false; } FORCEINLINE bool TestArgValue(FAutomationTestBase* T, const FString& NameForTest, const FSUDSValue& Actual, const FString& Expected) { if (T->TestEqual(NameForTest, Actual.GetType(), ESUDSValueType::Text)) { return T->TestEqual(NameForTest, Actual.GetTextValue().ToString(), Expected); } return false; } template FORCEINLINE bool TestParsedSetLiteral(FAutomationTestBase* T, const FString& NameForTest, const FSUDSParsedNode* Node, const FString& VarName, V Literal) { if (T->TestNotNull(NameForTest, Node)) { T->TestEqual(NameForTest, Node->NodeType, ESUDSParsedNodeType::SetVariable); T->TestEqual(NameForTest, Node->Identifier, VarName); if (T->TestTrue(NameForTest, Node->Expression.IsLiteral())) { TestArgValue(T, NameForTest,Node->Expression.GetLiteralValue(), Literal); } return true; } return false; } // Explicit bool version of the above since otherwise it gets converted to int & fails FORCEINLINE bool TestParsedSetLiteral(FAutomationTestBase* T, const FString& NameForTest, const FSUDSParsedNode* Node, const FString& VarName, bool Literal) { if (T->TestNotNull(NameForTest, Node)) { T->TestEqual(NameForTest, Node->NodeType, ESUDSParsedNodeType::SetVariable); T->TestEqual(NameForTest, Node->Identifier, VarName); if (T->TestTrue(NameForTest, Node->Expression.IsLiteral())) { T->TestEqual(NameForTest,Node->Expression.GetBooleanLiteralValue(), Literal); } return true; } return false; } FORCEINLINE bool TestParsedSetLiteral(FAutomationTestBase* T, const FString& NameForTest, const FSUDSParsedNode* Node, const FString& VarName, const FName& Name) { if (T->TestNotNull(NameForTest, Node)) { T->TestEqual(NameForTest, Node->NodeType, ESUDSParsedNodeType::SetVariable); T->TestEqual(NameForTest, Node->Identifier, VarName); if (T->TestTrue(NameForTest, Node->Expression.IsLiteral())) { T->TestEqual(NameForTest,Node->Expression.GetNameLiteralValue(), Name); } return true; } return false; } FORCEINLINE bool TestGetParsedNextNode(FAutomationTestBase* T, const FString& NameForTest, const FSUDSParsedNode* Node, FSUDSScriptImporter& Importer, bool bIsHeader, const FSUDSParsedNode** OutNextNode) { if (T->TestNotNull(NameForTest, Node)) { if (T->TestEqual(NameForTest, Node->Edges.Num(), 1)) { const int NextNodeIdx = Node->Edges[0].TargetNodeIdx; *OutNextNode = bIsHeader ? Importer.GetHeaderNode(NextNodeIdx) : Importer.GetNode(NextNodeIdx); return true; } } *OutNextNode = nullptr; return false; } FORCEINLINE bool TestParsedChoice(FAutomationTestBase* T, const FString& NameForTest, const FSUDSParsedNode* Node, int ExpectedNumChoices) { if (T->TestNotNull(NameForTest, Node)) { T->TestEqual(NameForTest, Node->NodeType, ESUDSParsedNodeType::Choice); T->TestEqual(NameForTest, Node->Edges.Num(), ExpectedNumChoices); return true; } return false; } FORCEINLINE bool TestParsedSelect(FAutomationTestBase* T, const FString& NameForTest, const FSUDSParsedNode* Node, int ExpectedNumEdges) { if (T->TestNotNull(NameForTest, Node)) { T->TestEqual(NameForTest, Node->NodeType, ESUDSParsedNodeType::Select); T->TestEqual(NameForTest, Node->Edges.Num(), ExpectedNumEdges); return true; } return false; } FORCEINLINE bool TestParsedChoiceEdge(FAutomationTestBase* T, const FString& NameForTest, const FSUDSParsedNode* Node, int EdgeIndex, const FString& Text, FSUDSScriptImporter& Importer, const FSUDSParsedNode** OutNode) { *OutNode = nullptr; if (Node && Node->Edges.Num() > EdgeIndex) { auto& Edge = Node->Edges[EdgeIndex]; T->TestEqual(NameForTest, Edge.Text, Text); const int Idx = Edge.TargetNodeIdx; *OutNode = Importer.GetNode(Idx); return true; } return false; } FORCEINLINE bool TestParsedSelectEdge(FAutomationTestBase* T, const FString& NameForTest, const FSUDSParsedNode* Node, int EdgeIndex, const FString& ConditionStr, FSUDSScriptImporter& Importer, const FSUDSParsedNode** OutNode) { *OutNode = nullptr; if (Node && Node->Edges.Num() > EdgeIndex) { auto& Edge = Node->Edges[EdgeIndex]; T->TestEqual(NameForTest, Edge.ConditionExpression.GetSourceString(), ConditionStr); const int Idx = Edge.TargetNodeIdx; *OutNode = Importer.GetNode(Idx); return true; } return false; } FORCEINLINE bool TestParsedGoto(FAutomationTestBase* T, const FString& NameForTest, const FSUDSParsedNode* Node, FSUDSScriptImporter& Importer, const FSUDSParsedNode** OutNode) { if (T->TestNotNull(NameForTest, Node)) { T->TestEqual(NameForTest, Node->NodeType, ESUDSParsedNodeType::Goto); const int Target = Importer.GetGotoTargetNodeIndex(Node->Identifier); *OutNode = Importer.GetNode(Target); return true; } return false; } FORCEINLINE bool TestTextNode(FAutomationTestBase* T, const FString& NameForTest, const USUDSScriptNode* Node, const FString& Speaker, const FString& Text) { if (T->TestNotNull(NameForTest, Node)) { T->TestEqual(NameForTest, Node->GetNodeType(), ESUDSScriptNodeType::Text); if (auto TextNode = Cast(Node)) { T->TestEqual(NameForTest, TextNode->GetSpeakerID(), Speaker); T->TestEqual(NameForTest, TextNode->GetText().ToString(), Text); } return true; } return false; } FORCEINLINE bool TestEdge(FAutomationTestBase* T, const FString& NameForTest, USUDSScriptNode* Node, int EdgeIndex, USUDSScriptNode** OutNode) { *OutNode = nullptr; if (Node && Node->GetEdgeCount() > EdgeIndex) { if (auto Edge = Node->GetEdge(EdgeIndex)) { *OutNode = Edge->GetTargetNode().Get(); return T->TestNotNull(NameForTest, *OutNode); } } return false; } FORCEINLINE bool TestChoiceNode(FAutomationTestBase* T, const FString& NameForTest, const USUDSScriptNode* Node, int NumChoices) { if (T->TestNotNull(NameForTest, Node)) { T->TestEqual(NameForTest, Node->GetNodeType(), ESUDSScriptNodeType::Choice); return T->TestEqual(NameForTest, Node->GetEdgeCount(), NumChoices); } return false; } FORCEINLINE bool TestSelectNode(FAutomationTestBase* T, const FString& NameForTest, const USUDSScriptNode* Node, int NumEdges) { if (T->TestNotNull(NameForTest, Node)) { T->TestEqual(NameForTest, Node->GetNodeType(), ESUDSScriptNodeType::Select); return T->TestEqual(NameForTest, Node->GetEdgeCount(), NumEdges); } return false; } FORCEINLINE bool TestChoiceEdge(FAutomationTestBase* T, const FString& NameForTest, USUDSScriptNode* Node, int EdgeIndex, const FString& Text, USUDSScriptNode** OutNode) { *OutNode = nullptr; if (Node && Node->GetEdgeCount() > EdgeIndex) { if (auto Edge = Node->GetEdge(EdgeIndex)) { T->TestEqual(NameForTest, Edge->GetText().ToString(), Text); *OutNode = Edge->GetTargetNode().Get(); return T->TestNotNull(NameForTest, *OutNode); } } return false; } FORCEINLINE bool TestSelectEdge(FAutomationTestBase* T, const FString& NameForTest, USUDSScriptNode* Node, int EdgeIndex, const FString& ConditionStr, USUDSScriptNode** OutNode) { *OutNode = nullptr; if (Node && Node->GetEdgeCount() > EdgeIndex) { if (auto Edge = Node->GetEdge(EdgeIndex)) { T->TestEqual(NameForTest, Edge->GetCondition().GetSourceString(), ConditionStr); *OutNode = Edge->GetTargetNode().Get(); return T->TestNotNull(NameForTest, *OutNode); } } return false; } // Helper to provide a string table just in scope struct ScopedStringTableHolder { public: UStringTable* StringTable; ScopedStringTableHolder() { StringTable = NewObject(GetTransientPackage(), "TestStrings"); } ~ScopedStringTableHolder() { // Tidy up string table // UStringTable constructor registered this table FStringTableRegistry::Get().UnregisterStringTable(StringTable->GetStringTableId()); } };