// Copyright 2021 DeepMind Technologies Limited // // 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. // Tests for xml/xml_native_reader.cc. #include #include #include #include #include #include #include #include "test/fixture.h" namespace mujoco { namespace { using ::testing::HasSubstr; using ::testing::IsNull; using UserDataTest = MujocoTest; TEST_F(UserDataTest, InvalidNUserBody) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("nuser_body")); } TEST_F(UserDataTest, InvalidNUserJoint) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("nuser_jnt")); } TEST_F(UserDataTest, InvalidNUserGeom) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("nuser_geom")); } TEST_F(UserDataTest, InvalidNUserSite) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("nuser_site")); } TEST_F(UserDataTest, InvalidNUserCamera) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("nuser_cam")); } TEST_F(UserDataTest, InvalidNUserTendon) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("nuser_tendon")); } TEST_F(UserDataTest, InvalidNUserActuator) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("nuser_actuator")); } TEST_F(UserDataTest, InvalidNUserSensor) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("nuser_sensor")); } TEST_F(UserDataTest, InvalidArrayElement) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("problem reading attribute 'axisangle'")); } TEST_F(UserDataTest, InvalidArrayLength) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("has too much data")); } TEST_F(UserDataTest, InvalidNumber) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("problem reading attribute")); } TEST_F(UserDataTest, AllowsSpaces) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, Not(IsNull())); mj_deleteModel(model); } // ------------- test relative frame sensor parsing ---------------------------- using RelativeFrameSensorParsingTest = MujocoTest; TEST_F(RelativeFrameSensorParsingTest, RefNameButNoType) { static constexpr char xml[] = R"( )"; std::array error; LoadModelFromString(xml, error.data(), error.size()); EXPECT_THAT(error.data(), HasSubstr("but reftype is missing")); } TEST_F(RelativeFrameSensorParsingTest, RefTypeButNoName) { static constexpr char xml[] = R"( )"; std::array error; LoadModelFromString(xml, error.data(), error.size()); EXPECT_THAT(error.data(), HasSubstr("attribute missing: 'refname'")); } // ------------- test actlimited parsing --------------------------------------- using ActuatorTest = MujocoTest; TEST_F(ActuatorTest, InvalidActlimited) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("unrecognized attribute")); } TEST_F(ActuatorTest, IncompleteActlimited) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, IsNull()); EXPECT_THAT(error.data(), HasSubstr("attribute 'actrange' does not have enough data")); } TEST_F(ActuatorTest, ReadsByte) { static constexpr char xml[] = R"( )"; std::array error; mjModel* model = LoadModelFromString(xml, error.data(), error.size()); ASSERT_THAT(model, Not(IsNull())); EXPECT_EQ(*(model->actuator_actlimited), (mjtByte)(1 & 0xFF)); mj_deleteModel(model); } } // namespace } // namespace mujoco