Support directories in VFS via mj_addBufferVFS.
PiperOrigin-RevId: 655286683 Change-Id: I846376a0571d8df28d979beb5981a0cbccd7a04f
This commit is contained in:
committed by
Copybara-Service
parent
2746cb8559
commit
5ac5cfb618
@@ -47,7 +47,7 @@ void CacheText(mjCCache& cache, const std::string& model,
|
||||
mjVFS vfs;
|
||||
mj_defaultVFS(&vfs);
|
||||
mj_addBufferVFS(&vfs, name.c_str(), text.data(), text.size());
|
||||
mjResource* resource = mju_openResource(name.c_str(), &vfs, nullptr, 0);
|
||||
mjResource* resource = mju_openResource("", name.c_str(), &vfs, nullptr, 0);
|
||||
std::shared_ptr<const void> data(&text, +[](const void* data) {});
|
||||
cache.Insert(model, resource, data, text.size());
|
||||
mju_closeResource(resource);
|
||||
@@ -61,7 +61,7 @@ GetCachedText(mjCCache& cache, const std::string& model,
|
||||
mjVFS vfs;
|
||||
mj_defaultVFS(&vfs);
|
||||
mj_addBufferVFS(&vfs, name.c_str(), text.data(), std::strlen(text.c_str()));
|
||||
mjResource* resource = mju_openResource(name.c_str(), &vfs, nullptr, 0);
|
||||
mjResource* resource = mju_openResource("", name.c_str(), &vfs, nullptr, 0);
|
||||
bool inserted = cache.PopulateData(resource,
|
||||
[&cached_text](const void* data) {
|
||||
cached_text = *(static_cast<const std::string*>(data));
|
||||
|
||||
@@ -233,7 +233,7 @@ TEST_F(ResourceTest, GeneralTest) {
|
||||
EXPECT_GT(i, 0);
|
||||
|
||||
// open resource
|
||||
mjResource* resource = mju_openResource("str:file", nullptr, nullptr, 0);
|
||||
mjResource* resource = mju_openResource("", "str:file", nullptr, nullptr, 0);
|
||||
ASSERT_THAT(resource, NotNull());
|
||||
|
||||
const char* buffer = NULL;
|
||||
@@ -256,7 +256,7 @@ TEST_F(ResourceTest, GeneralFailureTest) {
|
||||
static std::array<char, 1024> error;
|
||||
|
||||
// open resource
|
||||
mjResource* resource = mju_openResource("str:notfound", nullptr,
|
||||
mjResource* resource = mju_openResource("", "str:notfound", nullptr,
|
||||
error.data(), error.size());
|
||||
ASSERT_THAT(resource, IsNull());
|
||||
|
||||
@@ -281,7 +281,7 @@ TEST_F(ResourceTest, NameWithValidPrefix) {
|
||||
};
|
||||
|
||||
// open resource
|
||||
mjResource* resource = mju_openResource("nop:found", nullptr, nullptr, 0);
|
||||
mjResource* resource = mju_openResource("", "nop:found", nullptr, nullptr, 0);
|
||||
ASSERT_THAT(resource, NotNull());
|
||||
mju_closeResource(resource);
|
||||
}
|
||||
@@ -304,7 +304,7 @@ TEST_F(ResourceTest, NameWithUpperCasePrefix) {
|
||||
};
|
||||
|
||||
// open resource
|
||||
mjResource* resource = mju_openResource("NOP:found", nullptr, nullptr, 0);
|
||||
mjResource* resource = mju_openResource("", "NOP:found", nullptr, nullptr, 0);
|
||||
ASSERT_THAT(resource, NotNull());
|
||||
mju_closeResource(resource);
|
||||
}
|
||||
@@ -327,7 +327,7 @@ TEST_F(ResourceTest, NameWithInvalidPrefix) {
|
||||
};
|
||||
|
||||
// open resource
|
||||
mjResource* resource = mju_openResource("nopfound", nullptr, nullptr, 0);
|
||||
mjResource* resource = mju_openResource("", "nopfound", nullptr, nullptr, 0);
|
||||
ASSERT_THAT(resource, IsNull());
|
||||
}
|
||||
|
||||
@@ -338,7 +338,7 @@ TEST_F(ResourceTest, OSFilesystemTimestamps) {
|
||||
const char* const file = "engine/testdata/collision_box/boxbox_deep.xml";
|
||||
const std::string xml_path = GetTestDataFilePath(file);
|
||||
|
||||
mjResource* resource = mju_openResource(xml_path.c_str(), nullptr,
|
||||
mjResource* resource = mju_openResource("", xml_path.c_str(), nullptr,
|
||||
nullptr, 0);
|
||||
mju_decodeBase64((uint8_t*) &t, resource->timestamp);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ using ::testing::NotNull;
|
||||
using UserVfsTest = MujocoTest;
|
||||
|
||||
static bool HasFile(const mjVFS* vfs, const std::string& filename) {
|
||||
mjResource* resource = mju_openResource(filename.c_str(), vfs, nullptr, 0);
|
||||
mjResource* resource = mju_openResource("", filename.c_str(), vfs, nullptr, 0);
|
||||
bool result = resource != nullptr;
|
||||
mju_closeResource(resource);
|
||||
return result;
|
||||
@@ -196,14 +196,13 @@ TEST_F(UserVfsTest, AddBufferRepeat) {
|
||||
mj_deleteVFS(&vfs);
|
||||
}
|
||||
|
||||
TEST_F(UserVfsTest, BufferStripPath) {
|
||||
TEST_F(UserVfsTest, BufferPath) {
|
||||
mjVFS vfs;
|
||||
mj_defaultVFS(&vfs);
|
||||
std::string buffer = "<mujoco/>";
|
||||
const void* ptr = static_cast<const void*>(buffer.c_str());
|
||||
mj_addBufferVFS(&vfs, "dir/model", ptr, buffer.size());
|
||||
EXPECT_TRUE(HasFile(&vfs, "MODEL"));
|
||||
EXPECT_TRUE(HasFile(&vfs, "dir\\model"));
|
||||
EXPECT_TRUE(HasFile(&vfs, "files/../dir/model"));
|
||||
mj_deleteVFS(&vfs);
|
||||
}
|
||||
|
||||
@@ -222,7 +221,7 @@ TEST_F(UserVfsTest, Timestamps) {
|
||||
mj_defaultVFS(&vfs);
|
||||
mj_addBufferVFS(&vfs, "cube.obj", cube, sizeof(cube));
|
||||
|
||||
mjResource* resource = mju_openResource("cube.obj", &vfs, nullptr, 0);
|
||||
mjResource* resource = mju_openResource("", "cube.obj", &vfs, nullptr, 0);
|
||||
|
||||
// same timestamps
|
||||
EXPECT_EQ(mju_isModifiedResource(resource, resource->timestamp), 0);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
// Tests for xml/xml_native_reader.cc.
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -613,6 +612,18 @@ static constexpr unsigned char kTinyPng[] = {
|
||||
0x82
|
||||
};
|
||||
|
||||
// mesh OBJ file of a cube
|
||||
static constexpr char kTinyObj[] = R"(
|
||||
v -1 -1 1
|
||||
v 1 -1 1
|
||||
v -1 1 1
|
||||
v 1 1 1
|
||||
v -1 1 -1
|
||||
v 1 1 -1
|
||||
v -1 -1 -1
|
||||
v 1 -1 -1)";
|
||||
|
||||
|
||||
TEST_F(XMLReaderTest, IncludeTest) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
@@ -726,24 +737,22 @@ TEST_F(XMLReaderTest, IncludePathTest) {
|
||||
<geom name="another_box" type="box" size="2 2 2"/>
|
||||
</mujoco>)";
|
||||
|
||||
MockFilesystem fs("IncludePathTest");
|
||||
fs.AddFile("model.xml", (const unsigned char*) xml, sizeof(xml));
|
||||
std::string modelpath = fs.FullPath("model.xml");
|
||||
|
||||
fs.ChangeDirectory("submodels/");
|
||||
fs.AddFile("model1.xml", (const unsigned char*) xml1, sizeof(xml1));
|
||||
fs.AddFile("model2.xml", (const unsigned char*) xml2, sizeof(xml2));
|
||||
fs.AddFile("subsubmodels/model3.xml", (const unsigned char*) xml3,
|
||||
sizeof(xml3));
|
||||
fs.ChangeDirectory("/");
|
||||
mjVFS vfs;
|
||||
mj_defaultVFS(&vfs);
|
||||
mj_addBufferVFS(&vfs, "model.xml", xml, sizeof(xml));
|
||||
mj_addBufferVFS(&vfs, "submodels/model1.xml", xml1, sizeof(xml1));
|
||||
mj_addBufferVFS(&vfs, "submodels/model2.xml", xml2, sizeof(xml2));
|
||||
mj_addBufferVFS(&vfs, "submodels/subsubmodels/model3.xml", xml3,
|
||||
sizeof(xml3));
|
||||
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = mj_loadXML(modelpath.c_str(), nullptr, error.data(),
|
||||
mjModel* model = mj_loadXML("model.xml", &vfs, error.data(),
|
||||
error.size());
|
||||
ASSERT_THAT(model, NotNull()) << error.data();
|
||||
EXPECT_EQ(mj_name2id(model, mjOBJ_GEOM, "ball"), 2);
|
||||
EXPECT_EQ(mj_name2id(model, mjOBJ_GEOM, "another_box"), 3);
|
||||
mj_deleteModel(model);
|
||||
mj_deleteVFS(&vfs);
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, FallbackIncludePathTest) {
|
||||
@@ -772,22 +781,21 @@ TEST_F(XMLReaderTest, FallbackIncludePathTest) {
|
||||
<geom name="another_box" type="box" size="2 2 2"/>
|
||||
</mujoco>)";
|
||||
|
||||
MockFilesystem fs("FallbackIncludePathTest");
|
||||
fs.AddFile("model.xml", (const unsigned char*) xml, sizeof(xml));
|
||||
std::string modelpath = fs.FullPath("model.xml");
|
||||
|
||||
fs.AddFile("model1.xml", (const unsigned char*) xml1, sizeof(xml1));
|
||||
fs.AddFile("submodels/model2.xml", (const unsigned char*) xml2, sizeof(xml2));
|
||||
fs.AddFile("subsubmodels/model3.xml", (const unsigned char*) xml3,
|
||||
sizeof(xml3));
|
||||
mjVFS vfs;
|
||||
mj_defaultVFS(&vfs);
|
||||
mj_addBufferVFS(&vfs, "model.xml", xml, sizeof(xml));
|
||||
mj_addBufferVFS(&vfs, "model1.xml", xml1, sizeof(xml1));
|
||||
mj_addBufferVFS(&vfs, "submodels/model2.xml", xml2, sizeof(xml2));
|
||||
mj_addBufferVFS(&vfs, "subsubmodels/model3.xml", xml3, sizeof(xml3));
|
||||
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = mj_loadXML(modelpath.c_str(), nullptr,
|
||||
mjModel* model = mj_loadXML("model.xml", &vfs,
|
||||
error.data(), error.size());
|
||||
ASSERT_THAT(model, NotNull()) << error.data();
|
||||
EXPECT_EQ(mj_name2id(model, mjOBJ_GEOM, "ball"), 2);
|
||||
EXPECT_EQ(mj_name2id(model, mjOBJ_GEOM, "another_box"), 3);
|
||||
mj_deleteModel(model);
|
||||
mj_deleteVFS(&vfs);
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, MaterialTextureTest) {
|
||||
@@ -809,14 +817,14 @@ TEST_F(XMLReaderTest, MaterialTextureTest) {
|
||||
</mujoco>
|
||||
)";
|
||||
|
||||
MockFilesystem fs("MaterialTextureTest");
|
||||
fs.AddFile("tiny0.png", kTinyPng, sizeof(kTinyPng));
|
||||
fs.AddFile("tiny1.png", kTinyPng, sizeof(kTinyPng));
|
||||
fs.AddFile("model.xml", (const unsigned char*) xml, sizeof(xml));
|
||||
std::string modelpath = fs.FullPath("model.xml");
|
||||
mjVFS vfs;
|
||||
mj_defaultVFS(&vfs);
|
||||
mj_addBufferVFS(&vfs, "tiny0.png", kTinyPng, sizeof(kTinyPng));
|
||||
mj_addBufferVFS(&vfs, "tiny1.png", kTinyPng, sizeof(kTinyPng));
|
||||
mj_addBufferVFS(&vfs, "model.xml", xml, sizeof(xml));
|
||||
|
||||
char error[1024];
|
||||
mjModel* model = mj_loadXML(modelpath.c_str(), nullptr, error, 1024);
|
||||
mjModel* model = mj_loadXML("model.xml", &vfs, error, 1024);
|
||||
|
||||
EXPECT_THAT(model, NotNull()) << error;
|
||||
EXPECT_EQ(model->mat_texid[mjTEXROLE_RGB], 1);
|
||||
@@ -825,6 +833,7 @@ TEST_F(XMLReaderTest, MaterialTextureTest) {
|
||||
EXPECT_EQ(model->mat_texid[mjTEXROLE_OCCLUSION], 0);
|
||||
|
||||
mj_deleteModel(model);
|
||||
mj_deleteVFS(&vfs);
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, LegacyMaterialTextureTest) {
|
||||
@@ -841,19 +850,20 @@ TEST_F(XMLReaderTest, LegacyMaterialTextureTest) {
|
||||
</mujoco>
|
||||
)";
|
||||
|
||||
MockFilesystem fs("LegacyMaterialTextureTest");
|
||||
fs.AddFile("tiny0.png", kTinyPng, sizeof(kTinyPng));
|
||||
fs.AddFile("tiny1.png", kTinyPng, sizeof(kTinyPng));
|
||||
fs.AddFile("model.xml", (const unsigned char*) xml, sizeof(xml));
|
||||
std::string modelpath = fs.FullPath("model.xml");
|
||||
mjVFS vfs;
|
||||
mj_defaultVFS(&vfs);
|
||||
mj_addBufferVFS(&vfs, "tiny0.png", kTinyPng, sizeof(kTinyPng));
|
||||
mj_addBufferVFS(&vfs, "tiny1.png", kTinyPng, sizeof(kTinyPng));
|
||||
mj_addBufferVFS(&vfs, "model.xml", xml, sizeof(xml));
|
||||
|
||||
char error[1024];
|
||||
mjModel* model = mj_loadXML(modelpath.c_str(), nullptr, error, 1024);
|
||||
mjModel* model = mj_loadXML("model.xml", &vfs, error, 1024);
|
||||
|
||||
EXPECT_THAT(model, NotNull()) << error;
|
||||
EXPECT_EQ(model->mat_texid[mjTEXROLE_RGB], 1);
|
||||
|
||||
mj_deleteModel(model);
|
||||
mj_deleteVFS(&vfs);
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, MaterialTextureFailTest) {
|
||||
@@ -873,12 +883,6 @@ TEST_F(XMLReaderTest, MaterialTextureFailTest) {
|
||||
</mujoco>
|
||||
)";
|
||||
|
||||
MockFilesystem fs("MaterialTextureFailTest");
|
||||
fs.AddFile("tiny0.png", kTinyPng, sizeof(kTinyPng));
|
||||
fs.AddFile("tiny1.png", kTinyPng, sizeof(kTinyPng));
|
||||
fs.AddFile("model.xml", (const unsigned char*) xml, sizeof(xml));
|
||||
std::string modelpath = fs.FullPath("model.xml");
|
||||
|
||||
std::array<char, 1024> error;
|
||||
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
|
||||
EXPECT_THAT(m, IsNull());
|
||||
@@ -907,28 +911,32 @@ TEST_F(XMLReaderTest, IncludeAssetsTest) {
|
||||
static constexpr char subassets[] = R"(
|
||||
<mujoco>
|
||||
<texture file="subtiny.png" type="2d"/>
|
||||
<mesh name="cube" file="cube.obj"/>
|
||||
<material name="submaterial" texture="subtiny"/>
|
||||
</mujoco>
|
||||
)";
|
||||
|
||||
MockFilesystem fs("IncludeAssetsTest");
|
||||
fs.AddFile("assets/tiny.png", kTinyPng, sizeof(kTinyPng));
|
||||
fs.AddFile("assets/subassets/subtiny.png", kTinyPng, sizeof(kTinyPng));
|
||||
fs.AddFile("assets/assets.xml", (const unsigned char*) assets,
|
||||
sizeof(assets));
|
||||
fs.AddFile("assets/subassets/assets.xml", (const unsigned char*) subassets,
|
||||
sizeof(subassets));
|
||||
fs.AddFile("model.xml", (const unsigned char*) xml, sizeof(xml));
|
||||
std::string modelpath = fs.FullPath("model.xml");
|
||||
mjVFS vfs;
|
||||
mj_defaultVFS(&vfs);
|
||||
mj_addBufferVFS(&vfs, "assets/tiny.png", kTinyPng, sizeof(kTinyPng));
|
||||
mj_addBufferVFS(&vfs, "assets/subassets/subtiny.png", kTinyPng,
|
||||
sizeof(kTinyPng));
|
||||
mj_addBufferVFS(&vfs, "assets/subassets/cube.obj", kTinyObj,
|
||||
sizeof(kTinyObj));
|
||||
mj_addBufferVFS(&vfs, "assets/assets.xml", assets, sizeof(assets));
|
||||
mj_addBufferVFS(&vfs, "assets/subassets/assets.xml", subassets,
|
||||
sizeof(subassets));
|
||||
mj_addBufferVFS(&vfs, "model.xml", xml, sizeof(xml));
|
||||
|
||||
// loading the file should be successful
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = mj_loadXML(modelpath.c_str(), nullptr, error.data(),
|
||||
mjModel* model = mj_loadXML("model.xml", &vfs, error.data(),
|
||||
error.size());
|
||||
|
||||
ASSERT_THAT(model, NotNull()) << error.data();
|
||||
|
||||
mj_deleteModel(model);
|
||||
mj_deleteVFS(&vfs);
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, FallbackIncludeAssetsTest) {
|
||||
@@ -956,26 +964,26 @@ TEST_F(XMLReaderTest, FallbackIncludeAssetsTest) {
|
||||
</mujoco>
|
||||
)";
|
||||
|
||||
MockFilesystem fs("FallbackIncludeAssetsTest");
|
||||
fs.AddFile("assets/tiny.png", kTinyPng, sizeof(kTinyPng));
|
||||
mjVFS vfs;
|
||||
mj_defaultVFS(&vfs);
|
||||
mj_addBufferVFS(&vfs, "assets/tiny.png", kTinyPng, sizeof(kTinyPng));
|
||||
|
||||
// need to fallback for backwards compatibility
|
||||
fs.AddFile("subtiny.png", kTinyPng, sizeof(kTinyPng));
|
||||
mj_addBufferVFS(&vfs, "subtiny.png", kTinyPng, sizeof(kTinyPng));
|
||||
|
||||
fs.AddFile("assets/assets.xml", (const unsigned char*) assets,
|
||||
sizeof(assets));
|
||||
fs.AddFile("assets/subassets/assets.xml", (const unsigned char*) subassets,
|
||||
sizeof(subassets));
|
||||
fs.AddFile("model.xml", (const unsigned char*) xml, sizeof(xml));
|
||||
std::string modelpath = fs.FullPath("model.xml");
|
||||
mj_addBufferVFS(&vfs, "assets/assets.xml", assets, sizeof(assets));
|
||||
mj_addBufferVFS(&vfs, "assets/subassets/assets.xml", subassets,
|
||||
sizeof(subassets));
|
||||
mj_addBufferVFS(&vfs, "model.xml", xml, sizeof(xml));
|
||||
|
||||
// loading the file should be successful
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = mj_loadXML(modelpath.c_str(), nullptr,
|
||||
mjModel* model = mj_loadXML("model.xml", &vfs,
|
||||
error.data(), error.size());
|
||||
ASSERT_THAT(model, NotNull()) << error.data();
|
||||
|
||||
mj_deleteModel(model);
|
||||
mj_deleteVFS(&vfs);
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, IncludeAbsoluteTest) {
|
||||
|
||||
Reference in New Issue
Block a user