1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
/*
* Copyright 2020 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <string>
#include <gtest/gtest.h>
#include "sdf/Filesystem.hh"
#include "sdf/Root.hh"
#include "test_config.h"
void PrintErrors(sdf::Errors &_errors)
{
for (sdf::Error e : _errors)
std::cout << e.Message() << std::endl;
}
/////////////////////////////////////////////////
TEST(ParamPassingTest, ExperimentalParamsTag)
{
const std::string modelRootPath =
sdf::testing::TestFile("integration", "model");
sdf::setFindCallback(
[&](const std::string &_file)
{
return sdf::filesystem::append(modelRootPath, _file);
});
// checks normal <include> (w/o <experimental:params>)
std::string testFile =
sdf::testing::TestFile("integration", "include_model.sdf");
sdf::Root root;
sdf::Errors errors = root.Load(testFile);
PrintErrors(errors);
EXPECT_TRUE(errors.empty());
// checks <include> containing <experimental:params> w/ correctly specified
// elements
testFile = sdf::testing::TestFile("integration", "include_custom_model.sdf");
errors = root.Load(testFile);
PrintErrors(errors);
EXPECT_TRUE(errors.empty());
// compare with expected output
testFile = sdf::testing::TestFile("integration",
"include_custom_model_expected_output.sdf");
sdf::Root expectedRoot;
errors = expectedRoot.Load(testFile);
PrintErrors(errors);
EXPECT_TRUE(errors.empty());
EXPECT_EQ(root.Element()->ToString(""), expectedRoot.Element()->ToString(""))
<< "ACTUAL:\n" << root.Element()->ToString("\t")
<< "\nEXPECTED:\n" << expectedRoot.Element()->ToString("\t");
// Expected errors
testFile = sdf::testing::TestFile("integration",
"include_invalid_custom_model.sdf");
errors = root.Load(testFile);
PrintErrors(errors);
EXPECT_FALSE(errors.empty());
ASSERT_EQ(errors.size(), 29u);
int i = -1;
// missing element_id attribute
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_MISSING);
// element does not exist in included model
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_MISSING);
// element already exists in included model
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::DUPLICATE_NAME);
// for add action, parent of specified element does not exist
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_MISSING);
// missing name after double colons
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_INVALID);
// missing action attribute
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_MISSING);
// incorrect schema (missing required attributes; in children of element_id)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_MISSING);
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_INVALID);
// not defined sdf element (in children of where element_id is defined)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_INVALID);
// not defined sdf element (where element_id is defined)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_INVALID);
// missing 'name' attribute where element_id is with action="add"
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_MISSING);
// 'name' attribute is empty (where element_id is with action="add")
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_INVALID);
// incorrect schema (missing required attributes; where element_id defined)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_MISSING);
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_INVALID);
// invalid action
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_INVALID);
// invalid child action
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_INVALID);
// child element does not exist
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_MISSING);
// child <box> (child of <geometry>) does not exist
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_MISSING);
// child element (w/ name attribute) does not exist
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_MISSING);
// child element does not exist (replace action)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_MISSING);
// missing 'name' attribute (replace action)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_MISSING);
// invalid attribute (modify action)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_INVALID);
// element missing (modify action)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_MISSING);
// incorrect schema (missing required attributes; where element_id defined)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_MISSING);
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_INVALID);
// invalid attribute (modify action)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ATTRIBUTE_INVALID);
// element missing (modify action)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_MISSING);
// element missing (modify action)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_MISSING);
// element has invalid value (modify action)
EXPECT_EQ(errors[++i].Code(), sdf::ErrorCode::ELEMENT_INVALID);
}
/////////////////////////////////////////////////
TEST(ParamPassingTest, NestedInclude)
{
const std::string modelRootPath =
sdf::testing::TestFile("integration", "model", "nested_include");
sdf::setFindCallback(
[&](const std::string &_file)
{
return sdf::filesystem::append(modelRootPath, _file);
});
// checks correctly specified elements in <experimental:params>
// at top-level include, which has several nested includes
// e.g., When model A includes B and B includes C. The top-level A
// <experimental:params> specifies elements of C
std::string testFile =
sdf::testing::TestFile("integration", "model",
"nested_include", "test_nested_include.sdf");
sdf::Root root;
sdf::Errors errors = root.Load(testFile);
PrintErrors(errors);
EXPECT_TRUE(errors.empty());
// compare with expected output
testFile = sdf::testing::TestFile("integration",
"include_custom_nested_model_expected_output.sdf");
sdf::Root expectedRoot;
errors = expectedRoot.Load(testFile);
PrintErrors(errors);
EXPECT_TRUE(errors.empty());
EXPECT_EQ(root.Element()->ToString(""), expectedRoot.Element()->ToString(""))
<< "ACTUAL:\n" << root.Element()->ToString("\t")
<< "\nEXPECTED:\n" << expectedRoot.Element()->ToString("\t");
}
|