| /* |
| * Copyright (C) 2020 CESNET, https://photonics.cesnet.cz/ |
| * |
| * Written by Václav Kubernát <kubervac@fit.cvut.cz> |
| * |
| */ |
| |
| #include <experimental/iterator> |
| #include <iostream> |
| #include "trompeloeil_doctest.hpp" |
| #include "ast_commands.hpp" |
| #include "datastoreaccess_mock.hpp" |
| #include "parser.hpp" |
| #include "static_schema.hpp" |
| |
| namespace std { |
| std::ostream& operator<<(std::ostream& s, const std::set<std::string> set) |
| { |
| s << std::endl << "{"; |
| std::copy(set.begin(), set.end(), std::experimental::make_ostream_joiner(s, ", ")); |
| s << "}" << std::endl; |
| return s; |
| } |
| } |
| |
| TEST_CASE("keyvalue_completion") |
| { |
| auto schema = std::make_shared<StaticSchema>(); |
| schema->addModule("example"); |
| schema->addContainer("/", "example:a"); |
| schema->addContainer("/", "example:b"); |
| schema->addList("/", "example:list", {"number"}); |
| schema->addLeaf("/example:list", "example:number", yang::LeafDataTypes::Int32); |
| schema->addList("/", "example:twoKeyList", {"number", "name"}); |
| schema->addLeaf("/example:twoKeyList", "example:number", yang::LeafDataTypes::Int32); |
| schema->addLeaf("/example:twoKeyList", "example:name", yang::LeafDataTypes::String); |
| auto mockDatastore = std::make_shared<MockDatastoreAccess>(); |
| |
| // DataQuery gets the schema from DatastoreAccess once |
| auto expectation = NAMED_REQUIRE_CALL(*mockDatastore, schema()) |
| .RETURN(schema); |
| auto dataQuery = std::make_shared<DataQuery>(*mockDatastore); |
| expectation.reset(); |
| Parser parser(schema, dataQuery); |
| std::string input; |
| std::ostringstream errorStream; |
| |
| std::set<std::string> expected; |
| std::vector<std::shared_ptr<trompeloeil::expectation>> queryExpectations; |
| std::vector<ListInstance> queryReturn; |
| |
| SECTION("get example:list[number=") |
| { |
| input = "get example:list[number="; |
| queryReturn = { |
| {{"number", 1}}, |
| {{"number", 7}}, |
| {{"number", 9}}, |
| {{"number", 42}} |
| }; |
| expected = { |
| "1", |
| "7", |
| "9", |
| "42" |
| }; |
| queryExpectations.push_back(NAMED_REQUIRE_CALL(*mockDatastore, listInstances("/example:list")) |
| .RETURN(queryReturn)); |
| } |
| |
| SECTION("get example:twoKeyList[number=") |
| { |
| queryReturn = { |
| {{"number", 1}, {"name", std::string{"Petr"}}}, |
| {{"number", 7}, {"name", std::string{"Petr"}}}, |
| {{"number", 10}, {"name", std::string{"Petr"}}}, |
| {{"number", 10}, {"name", std::string{"Honza"}}}, |
| {{"number", 100}, {"name", std::string{"Honza"}}}, |
| }; |
| input = "get example:twoKeyList["; |
| SECTION("no keys set") |
| { |
| SECTION("number") |
| { |
| input += "number="; |
| expected = { "1", "7", "10", "100" }; |
| } |
| SECTION("name") |
| { |
| input += "name="; |
| expected = { "'Petr'", "'Honza'"}; |
| } |
| queryExpectations.push_back(NAMED_REQUIRE_CALL(*mockDatastore, listInstances("/example:twoKeyList")) |
| .RETURN(queryReturn)); |
| } |
| |
| SECTION("name is set") |
| { |
| input += "name="; |
| SECTION("Petr") |
| { |
| input += "'Petr'"; |
| expected = { "1", "7", "10"}; |
| } |
| SECTION("Honza") |
| { |
| input += "'Honza'"; |
| expected = { "10", "100" }; |
| } |
| input += "][number="; |
| queryExpectations.push_back(NAMED_REQUIRE_CALL(*mockDatastore, listInstances("/example:twoKeyList")) |
| .TIMES(2) |
| .RETURN(queryReturn)); |
| } |
| |
| SECTION("number is set") |
| { |
| input += "number="; |
| SECTION("1") |
| { |
| input += "1"; |
| expected = { "'Petr'" }; |
| } |
| SECTION("7") |
| { |
| input += "7"; |
| expected = { "'Petr'" }; |
| } |
| SECTION("10") |
| { |
| input += "10"; |
| expected = { "'Honza'", "'Petr'" }; |
| } |
| SECTION("100") |
| { |
| input += "100"; |
| expected = { "'Honza'" }; |
| } |
| input += "][name="; |
| queryExpectations.push_back(NAMED_REQUIRE_CALL(*mockDatastore, listInstances("/example:twoKeyList")) |
| .TIMES(2) |
| .RETURN(queryReturn)); |
| } |
| |
| SECTION("both keys are set") |
| { |
| SECTION("get example:twoKeyList[number=123][name='Petr'") |
| { |
| input = "get example:twoKeyList[number=123][name='Petr'"; |
| expected = {"]/"}; |
| } |
| SECTION("get example:twoKeyList[number=123][name='Petr']") |
| { |
| input = "get example:twoKeyList[number=123][name='Petr']"; |
| expected = {"]/"}; |
| } |
| SECTION("get example:twoKeyList[number=123][name='Petr'][") |
| { |
| input = "get example:twoKeyList[number=123][name='Petr']["; |
| } |
| // I use ALLOW_CALL here, all this stuff calls it different number of times |
| queryExpectations.push_back(NAMED_ALLOW_CALL(*mockDatastore, listInstances("/example:twoKeyList")) |
| .RETURN(queryReturn)); |
| } |
| |
| } |
| |
| REQUIRE(parser.completeCommand(input, errorStream).m_completions == expected); |
| for (auto& it : queryExpectations) { |
| it.reset(); |
| } |
| } |