Add termination character to flattened plugin attributes if empty.
Fixes #2450. PiperOrigin-RevId: 730521722 Change-Id: Iec3fa377c65693d782eeb766a144a1c89096d1f3
This commit is contained in:
committed by
Copybara-Service
parent
024616345d
commit
14c8dc62f0
@@ -7157,6 +7157,11 @@ void mjCPlugin::Compile(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if there are no attributes, add a null terminator
|
||||||
|
if (plugin->nattribute == 0) {
|
||||||
|
flattened_attributes.push_back('\0');
|
||||||
|
}
|
||||||
|
|
||||||
// anything left in xml_attributes at this stage is not a valid attribute
|
// anything left in xml_attributes at this stage is not a valid attribute
|
||||||
if (!config_attribs_copy.empty()) {
|
if (!config_attribs_copy.empty()) {
|
||||||
std::string error =
|
std::string error =
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ using ::testing::NotNull;
|
|||||||
|
|
||||||
constexpr int kNumTruePlugins = 10;
|
constexpr int kNumTruePlugins = 10;
|
||||||
constexpr int kNumFakePlugins = 30;
|
constexpr int kNumFakePlugins = 30;
|
||||||
constexpr int kNumTestPlugins = 3;
|
constexpr int kNumTestPlugins = 4;
|
||||||
|
|
||||||
class BaseTestPlugin {
|
class BaseTestPlugin {
|
||||||
public:
|
public:
|
||||||
@@ -340,6 +340,42 @@ int RegisterPassivePlugin() {
|
|||||||
return mjp_registerPlugin(&plugin);
|
return mjp_registerPlugin(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int RegisterNoAttributePlugin() {
|
||||||
|
mjpPlugin plugin;
|
||||||
|
mjp_defaultPlugin(&plugin);
|
||||||
|
|
||||||
|
plugin.name = "mujoco.test.noattribute";
|
||||||
|
|
||||||
|
plugin.nattribute = 0;
|
||||||
|
plugin.attributes = nullptr;
|
||||||
|
|
||||||
|
plugin.capabilityflags |= mjPLUGIN_PASSIVE;
|
||||||
|
|
||||||
|
plugin.nstate = +[](const mjModel* m, int instance) { return 0; };
|
||||||
|
|
||||||
|
plugin.init = +[](const mjModel* m, mjData* d, int instance) {
|
||||||
|
auto* passive = new TestPassive(m, d, instance);
|
||||||
|
d->plugin_data[instance] = reinterpret_cast<uintptr_t>(passive);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
plugin.destroy = +[](mjData* d, int instance) {
|
||||||
|
delete reinterpret_cast<TestPassive*>(d->plugin_data[instance]);
|
||||||
|
d->plugin_data[instance] = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
plugin.reset = +[](const mjModel* m, mjtNum* plugin_state, void* plugin_data,
|
||||||
|
int instance) {
|
||||||
|
auto passive = reinterpret_cast<TestPassive*>(plugin_data);
|
||||||
|
passive->Reset();
|
||||||
|
};
|
||||||
|
plugin.compute = +[](const mjModel* m, mjData* d, int instance, int type) {
|
||||||
|
auto passive = reinterpret_cast<TestPassive*>(d->plugin_data[instance]);
|
||||||
|
passive->Compute();
|
||||||
|
};
|
||||||
|
|
||||||
|
return mjp_registerPlugin(&plugin);
|
||||||
|
}
|
||||||
|
|
||||||
class EnginePluginTest : public PluginTest {
|
class EnginePluginTest : public PluginTest {
|
||||||
public:
|
public:
|
||||||
// register all plugins
|
// register all plugins
|
||||||
@@ -356,6 +392,7 @@ class EnginePluginTest : public PluginTest {
|
|||||||
|
|
||||||
RegisterActuatorPlugin();
|
RegisterActuatorPlugin();
|
||||||
RegisterPassivePlugin();
|
RegisterPassivePlugin();
|
||||||
|
RegisterNoAttributePlugin();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -374,6 +411,9 @@ constexpr char xml[] = R"(
|
|||||||
<config key="multiplier" value="0.125"/>
|
<config key="multiplier" value="0.125"/>
|
||||||
</instance>
|
</instance>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin plugin="mujoco.test.noattribute">
|
||||||
|
<instance name="noattribute"/>
|
||||||
|
</plugin>
|
||||||
<plugin plugin="mujoco.test.passive"/>
|
<plugin plugin="mujoco.test.passive"/>
|
||||||
</extension>
|
</extension>
|
||||||
<worldbody>
|
<worldbody>
|
||||||
@@ -430,6 +470,22 @@ TEST_F(PluginTest, FirstPartyPlugins) {
|
|||||||
EXPECT_THAT(mjp_pluginCount(), kNumTruePlugins);
|
EXPECT_THAT(mjp_pluginCount(), kNumTruePlugins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(EnginePluginTest, NoAttributePlugin) {
|
||||||
|
static constexpr char xml[] = R"(
|
||||||
|
<mujoco>
|
||||||
|
<extension>
|
||||||
|
<plugin plugin="mujoco.test.noattribute">
|
||||||
|
<instance name="noattribute"/>
|
||||||
|
</plugin>
|
||||||
|
</extension>
|
||||||
|
</mujoco>
|
||||||
|
)";
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
|
||||||
|
EXPECT_THAT(m, testing::NotNull()) << error.data();
|
||||||
|
mj_deleteModel(m);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(EnginePluginTest, MultiplePluginTableBlocks) {
|
TEST_F(EnginePluginTest, MultiplePluginTableBlocks) {
|
||||||
EXPECT_EQ(mjp_pluginCount(), kNumTruePlugins + kNumFakePlugins + kNumTestPlugins);
|
EXPECT_EQ(mjp_pluginCount(), kNumTruePlugins + kNumFakePlugins + kNumTestPlugins);
|
||||||
|
|
||||||
@@ -529,7 +585,7 @@ TEST_F(EnginePluginTest, SensorPlugin) {
|
|||||||
EXPECT_EQ(TestSensor::InitCount(), expected_init_count);
|
EXPECT_EQ(TestSensor::InitCount(), expected_init_count);
|
||||||
EXPECT_EQ(TestSensor::DestroyCount(), expected_destroy_count);
|
EXPECT_EQ(TestSensor::DestroyCount(), expected_destroy_count);
|
||||||
|
|
||||||
EXPECT_EQ(m->nplugin, 6);
|
EXPECT_EQ(m->nplugin, 7);
|
||||||
EXPECT_EQ(mj_name2id(m, mjOBJ_PLUGIN, "twosensors"), 0);
|
EXPECT_EQ(mj_name2id(m, mjOBJ_PLUGIN, "twosensors"), 0);
|
||||||
EXPECT_EQ(mj_name2id(m, mjOBJ_PLUGIN, "threesensors"), 1);
|
EXPECT_EQ(mj_name2id(m, mjOBJ_PLUGIN, "threesensors"), 1);
|
||||||
|
|
||||||
@@ -547,7 +603,7 @@ TEST_F(EnginePluginTest, SensorPlugin) {
|
|||||||
m->plugin_stateadr[1]),
|
m->plugin_stateadr[1]),
|
||||||
testing::ElementsAreArray<int>({3*(i+1), 6*j, 3*j}));
|
testing::ElementsAreArray<int>({3*(i+1), 6*j, 3*j}));
|
||||||
EXPECT_THAT(*reinterpret_cast<mjtNum(*)[3]>(d->plugin_state +
|
EXPECT_THAT(*reinterpret_cast<mjtNum(*)[3]>(d->plugin_state +
|
||||||
m->plugin_stateadr[4]),
|
m->plugin_stateadr[5]),
|
||||||
testing::ElementsAreArray<int>({5*(i+1), 10*j, 5*j}));
|
testing::ElementsAreArray<int>({5*(i+1), 10*j, 5*j}));
|
||||||
EXPECT_THAT(*reinterpret_cast<mjtNum(*)[18]>(d->sensordata),
|
EXPECT_THAT(*reinterpret_cast<mjtNum(*)[18]>(d->sensordata),
|
||||||
testing::ElementsAreArray<int>({ i+1, 2*j, j,
|
testing::ElementsAreArray<int>({ i+1, 2*j, j,
|
||||||
@@ -587,7 +643,7 @@ TEST_F(EnginePluginTest, ActuatorPlugin) {
|
|||||||
EXPECT_EQ(TestActuator::InitCount(), expected_init_count);
|
EXPECT_EQ(TestActuator::InitCount(), expected_init_count);
|
||||||
EXPECT_EQ(TestActuator::DestroyCount(), expected_destroy_count);
|
EXPECT_EQ(TestActuator::DestroyCount(), expected_destroy_count);
|
||||||
|
|
||||||
EXPECT_EQ(m->nplugin, 6);
|
EXPECT_EQ(m->nplugin, 7);
|
||||||
EXPECT_EQ(mj_name2id(m, mjOBJ_PLUGIN, "actuator2"), 2);
|
EXPECT_EQ(mj_name2id(m, mjOBJ_PLUGIN, "actuator2"), 2);
|
||||||
|
|
||||||
mjData* d = mj_makeData(m);
|
mjData* d = mj_makeData(m);
|
||||||
|
|||||||
Reference in New Issue
Block a user