| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file LICENSE.rst or https://cmake.org/licensing for details. */ | |
| #include <cstdint> | |
| #include <memory> | |
| #include <string> | |
| #include <unordered_set> | |
| #include <vector> | |
| #include <cm3p/cppdap/optional.h> | |
| #include <cm3p/cppdap/protocol.h> | |
| #include <cm3p/cppdap/types.h> | |
| #include "cmDebuggerVariables.h" | |
| #include "cmDebuggerVariablesManager.h" | |
| #include "testCommon.h" | |
| #include "testDebugger.h" | |
| static dap::VariablesRequest CreateVariablesRequest(int64_t reference) | |
| { | |
| dap::VariablesRequest variableRequest; | |
| variableRequest.variablesReference = reference; | |
| return variableRequest; | |
| } | |
| static bool testUniqueIds() | |
| { | |
| auto variablesManager = | |
| std::make_shared<cmDebugger::cmDebuggerVariablesManager>(); | |
| std::unordered_set<int64_t> variableIds; | |
| bool noDuplicateIds = true; | |
| for (int i = 0; i < 10000 && noDuplicateIds; ++i) { | |
| auto variable = | |
| cmDebugger::cmDebuggerVariables(variablesManager, "Locals", true, []() { | |
| return std::vector<cmDebugger::cmDebuggerVariableEntry>(); | |
| }); | |
| if (variableIds.find(variable.GetId()) != variableIds.end()) { | |
| noDuplicateIds = false; | |
| } | |
| variableIds.insert(variable.GetId()); | |
| } | |
| ASSERT_TRUE(noDuplicateIds); | |
| return true; | |
| } | |
| static bool testConstructors() | |
| { | |
| auto variablesManager = | |
| std::make_shared<cmDebugger::cmDebuggerVariablesManager>(); | |
| auto parent = std::make_shared<cmDebugger::cmDebuggerVariables>( | |
| variablesManager, "Parent", true, [=]() { | |
| return std::vector<cmDebugger::cmDebuggerVariableEntry>{ | |
| { "ParentKey", "ParentValue", "ParentType" } | |
| }; | |
| }); | |
| auto children1 = std::make_shared<cmDebugger::cmDebuggerVariables>( | |
| variablesManager, "Children1", true, [=]() { | |
| return std::vector<cmDebugger::cmDebuggerVariableEntry>{ | |
| { "ChildKey1", "ChildValue1", "ChildType1" }, | |
| { "ChildKey2", "ChildValue2", "ChildType2" } | |
| }; | |
| }); | |
| parent->AddSubVariables(children1); | |
| auto children2 = std::make_shared<cmDebugger::cmDebuggerVariables>( | |
| variablesManager, "Children2", true); | |
| auto grandChildren21 = std::make_shared<cmDebugger::cmDebuggerVariables>( | |
| variablesManager, "GrandChildren21", true); | |
| grandChildren21->SetValue("GrandChildren21 Value"); | |
| children2->AddSubVariables(grandChildren21); | |
| parent->AddSubVariables(children2); | |
| dap::array<dap::Variable> variables = | |
| variablesManager->HandleVariablesRequest( | |
| CreateVariablesRequest(parent->GetId())); | |
| ASSERT_TRUE(variables.size() == 3); | |
| ASSERT_VARIABLE_REFERENCE(variables[0], "Children1", "", "collection", | |
| children1->GetId()); | |
| ASSERT_VARIABLE_REFERENCE(variables[1], "Children2", "", "collection", | |
| children2->GetId()); | |
| ASSERT_VARIABLE(variables[2], "ParentKey", "ParentValue", "ParentType"); | |
| variables = variablesManager->HandleVariablesRequest( | |
| CreateVariablesRequest(children1->GetId())); | |
| ASSERT_TRUE(variables.size() == 2); | |
| ASSERT_VARIABLE(variables[0], "ChildKey1", "ChildValue1", "ChildType1"); | |
| ASSERT_VARIABLE(variables[1], "ChildKey2", "ChildValue2", "ChildType2"); | |
| variables = variablesManager->HandleVariablesRequest( | |
| CreateVariablesRequest(children2->GetId())); | |
| ASSERT_TRUE(variables.size() == 1); | |
| ASSERT_VARIABLE_REFERENCE(variables[0], "GrandChildren21", | |
| "GrandChildren21 Value", "collection", | |
| grandChildren21->GetId()); | |
| return true; | |
| } | |
| static bool testIgnoreEmptyStringEntries() | |
| { | |
| auto variablesManager = | |
| std::make_shared<cmDebugger::cmDebuggerVariablesManager>(); | |
| auto vars = std::make_shared<cmDebugger::cmDebuggerVariables>( | |
| variablesManager, "Variables", true, []() { | |
| return std::vector<cmDebugger::cmDebuggerVariableEntry>{ | |
| { "IntValue1", 5 }, { "StringValue1", "" }, | |
| { "StringValue2", "foo" }, { "StringValue3", "" }, | |
| { "StringValue4", "bar" }, { "StringValue5", "" }, | |
| { "IntValue2", int64_t(99) }, { "BooleanTrue", true }, | |
| { "BooleanFalse", false }, | |
| }; | |
| }); | |
| vars->SetIgnoreEmptyStringEntries(true); | |
| vars->SetEnableSorting(false); | |
| dap::array<dap::Variable> variables = | |
| variablesManager->HandleVariablesRequest( | |
| CreateVariablesRequest(vars->GetId())); | |
| ASSERT_TRUE(variables.size() == 6); | |
| ASSERT_VARIABLE(variables[0], "IntValue1", "5", "int"); | |
| ASSERT_VARIABLE(variables[1], "StringValue2", "foo", "string"); | |
| ASSERT_VARIABLE(variables[2], "StringValue4", "bar", "string"); | |
| ASSERT_VARIABLE(variables[3], "IntValue2", "99", "int"); | |
| ASSERT_VARIABLE(variables[4], "BooleanTrue", "TRUE", "bool"); | |
| ASSERT_VARIABLE(variables[5], "BooleanFalse", "FALSE", "bool"); | |
| return true; | |
| } | |
| static bool testSortTheResult() | |
| { | |
| auto variablesManager = | |
| std::make_shared<cmDebugger::cmDebuggerVariablesManager>(); | |
| auto vars = std::make_shared<cmDebugger::cmDebuggerVariables>( | |
| variablesManager, "Variables", true, []() { | |
| return std::vector<cmDebugger::cmDebuggerVariableEntry>{ | |
| { "4", "4" }, { "2", "2" }, { "1", "1" }, { "3", "3" }, { "5", "5" }, | |
| }; | |
| }); | |
| dap::array<dap::Variable> variables = | |
| variablesManager->HandleVariablesRequest( | |
| CreateVariablesRequest(vars->GetId())); | |
| ASSERT_TRUE(variables.size() == 5); | |
| ASSERT_VARIABLE(variables[0], "1", "1", "string"); | |
| ASSERT_VARIABLE(variables[1], "2", "2", "string"); | |
| ASSERT_VARIABLE(variables[2], "3", "3", "string"); | |
| ASSERT_VARIABLE(variables[3], "4", "4", "string"); | |
| ASSERT_VARIABLE(variables[4], "5", "5", "string"); | |
| vars->SetEnableSorting(false); | |
| variables = variablesManager->HandleVariablesRequest( | |
| CreateVariablesRequest(vars->GetId())); | |
| ASSERT_TRUE(variables.size() == 5); | |
| ASSERT_VARIABLE(variables[0], "4", "4", "string"); | |
| ASSERT_VARIABLE(variables[1], "2", "2", "string"); | |
| ASSERT_VARIABLE(variables[2], "1", "1", "string"); | |
| ASSERT_VARIABLE(variables[3], "3", "3", "string"); | |
| ASSERT_VARIABLE(variables[4], "5", "5", "string"); | |
| return true; | |
| } | |
| static bool testNoSupportsVariableType() | |
| { | |
| auto variablesManager = | |
| std::make_shared<cmDebugger::cmDebuggerVariablesManager>(); | |
| auto vars = std::make_shared<cmDebugger::cmDebuggerVariables>( | |
| variablesManager, "Variables", false, []() { | |
| return std::vector<cmDebugger::cmDebuggerVariableEntry>{ { "test", | |
| "value" } }; | |
| }); | |
| auto subvars = std::make_shared<cmDebugger::cmDebuggerVariables>( | |
| variablesManager, "Children", false); | |
| vars->AddSubVariables(subvars); | |
| dap::array<dap::Variable> variables = | |
| variablesManager->HandleVariablesRequest( | |
| CreateVariablesRequest(vars->GetId())); | |
| ASSERT_TRUE(variables.size() == 2); | |
| ASSERT_VARIABLE(variables[0], "Children", "", ""); | |
| ASSERT_VARIABLE(variables[1], "test", "value", ""); | |
| return true; | |
| } | |
| int testDebuggerVariables(int, char*[]) | |
| { | |
| return runTests({ testUniqueIds, testConstructors, | |
| testIgnoreEmptyStringEntries, testSortTheResult, | |
| testNoSupportsVariableType }); | |
| } |