@@ -39,7 +39,7 @@ using ::testing::NotNull;
39
39
40
40
constexpr int kNumTruePlugins = 10 ;
41
41
constexpr int kNumFakePlugins = 30 ;
42
- constexpr int kNumTestPlugins = 3 ;
42
+ constexpr int kNumTestPlugins = 4 ;
43
43
44
44
class BaseTestPlugin {
45
45
public:
@@ -340,6 +340,42 @@ int RegisterPassivePlugin() {
340
340
return mjp_registerPlugin (&plugin);
341
341
}
342
342
343
+ int RegisterNoAttributePlugin () {
344
+ mjpPlugin plugin;
345
+ mjp_defaultPlugin (&plugin);
346
+
347
+ plugin.name = " mujoco.test.noattribute" ;
348
+
349
+ plugin.nattribute = 0 ;
350
+ plugin.attributes = nullptr ;
351
+
352
+ plugin.capabilityflags |= mjPLUGIN_PASSIVE;
353
+
354
+ plugin.nstate = +[](const mjModel* m, int instance) { return 0 ; };
355
+
356
+ plugin.init = +[](const mjModel* m, mjData* d, int instance) {
357
+ auto * passive = new TestPassive (m, d, instance);
358
+ d->plugin_data [instance] = reinterpret_cast <uintptr_t >(passive);
359
+ return 0 ;
360
+ };
361
+ plugin.destroy = +[](mjData* d, int instance) {
362
+ delete reinterpret_cast <TestPassive*>(d->plugin_data [instance]);
363
+ d->plugin_data [instance] = 0 ;
364
+ };
365
+
366
+ plugin.reset = +[](const mjModel* m, mjtNum* plugin_state, void * plugin_data,
367
+ int instance) {
368
+ auto passive = reinterpret_cast <TestPassive*>(plugin_data);
369
+ passive->Reset ();
370
+ };
371
+ plugin.compute = +[](const mjModel* m, mjData* d, int instance, int type) {
372
+ auto passive = reinterpret_cast <TestPassive*>(d->plugin_data [instance]);
373
+ passive->Compute ();
374
+ };
375
+
376
+ return mjp_registerPlugin (&plugin);
377
+ }
378
+
343
379
class EnginePluginTest : public PluginTest {
344
380
public:
345
381
// register all plugins
@@ -356,6 +392,7 @@ class EnginePluginTest : public PluginTest {
356
392
357
393
RegisterActuatorPlugin ();
358
394
RegisterPassivePlugin ();
395
+ RegisterNoAttributePlugin ();
359
396
}
360
397
};
361
398
@@ -374,6 +411,9 @@ constexpr char xml[] = R"(
374
411
<config key="multiplier" value="0.125"/>
375
412
</instance>
376
413
</plugin>
414
+ <plugin plugin="mujoco.test.noattribute">
415
+ <instance name="noattribute"/>
416
+ </plugin>
377
417
<plugin plugin="mujoco.test.passive"/>
378
418
</extension>
379
419
<worldbody>
@@ -430,6 +470,22 @@ TEST_F(PluginTest, FirstPartyPlugins) {
430
470
EXPECT_THAT (mjp_pluginCount (), kNumTruePlugins );
431
471
}
432
472
473
+ TEST_F (EnginePluginTest, NoAttributePlugin) {
474
+ static constexpr char xml[] = R"(
475
+ <mujoco>
476
+ <extension>
477
+ <plugin plugin="mujoco.test.noattribute">
478
+ <instance name="noattribute"/>
479
+ </plugin>
480
+ </extension>
481
+ </mujoco>
482
+ )" ;
483
+ std::array<char , 1024 > error;
484
+ mjModel* m = LoadModelFromString (xml, error.data (), error.size ());
485
+ EXPECT_THAT (m, testing::NotNull ()) << error.data ();
486
+ mj_deleteModel (m);
487
+ }
488
+
433
489
TEST_F (EnginePluginTest, MultiplePluginTableBlocks) {
434
490
EXPECT_EQ (mjp_pluginCount (), kNumTruePlugins + kNumFakePlugins + kNumTestPlugins );
435
491
@@ -529,7 +585,7 @@ TEST_F(EnginePluginTest, SensorPlugin) {
529
585
EXPECT_EQ (TestSensor::InitCount (), expected_init_count);
530
586
EXPECT_EQ (TestSensor::DestroyCount (), expected_destroy_count);
531
587
532
- EXPECT_EQ (m->nplugin , 6 );
588
+ EXPECT_EQ (m->nplugin , 7 );
533
589
EXPECT_EQ (mj_name2id (m, mjOBJ_PLUGIN, " twosensors" ), 0 );
534
590
EXPECT_EQ (mj_name2id (m, mjOBJ_PLUGIN, " threesensors" ), 1 );
535
591
@@ -547,7 +603,7 @@ TEST_F(EnginePluginTest, SensorPlugin) {
547
603
m->plugin_stateadr [1 ]),
548
604
testing::ElementsAreArray<int >({3 *(i+1 ), 6 *j, 3 *j}));
549
605
EXPECT_THAT (*reinterpret_cast <mjtNum (*)[3 ]>(d->plugin_state +
550
- m->plugin_stateadr [4 ]),
606
+ m->plugin_stateadr [5 ]),
551
607
testing::ElementsAreArray<int >({5 *(i+1 ), 10 *j, 5 *j}));
552
608
EXPECT_THAT (*reinterpret_cast <mjtNum (*)[18 ]>(d->sensordata ),
553
609
testing::ElementsAreArray<int >({ i+1 , 2 *j, j,
@@ -587,7 +643,7 @@ TEST_F(EnginePluginTest, ActuatorPlugin) {
587
643
EXPECT_EQ (TestActuator::InitCount (), expected_init_count);
588
644
EXPECT_EQ (TestActuator::DestroyCount (), expected_destroy_count);
589
645
590
- EXPECT_EQ (m->nplugin , 6 );
646
+ EXPECT_EQ (m->nplugin , 7 );
591
647
EXPECT_EQ (mj_name2id (m, mjOBJ_PLUGIN, " actuator2" ), 2 );
592
648
593
649
mjData* d = mj_makeData (m);
0 commit comments