diff --git a/Core/Code/CppMicroServices/src/module/usModuleResource.cpp b/Core/Code/CppMicroServices/src/module/usModuleResource.cpp index 6fd0b284d5..dfe1dc251a 100644 --- a/Core/Code/CppMicroServices/src/module/usModuleResource.cpp +++ b/Core/Code/CppMicroServices/src/module/usModuleResource.cpp @@ -1,243 +1,249 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics 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 "usModuleResource.h" #include "usAtomicInt_p.h" #include "usModuleResourceTree_p.h" #include US_BEGIN_NAMESPACE class ModuleResourcePrivate { public: ModuleResourcePrivate() : associatedResourceTree(NULL) , node(-1) , size(0) , data(NULL) , isFile(false) , ref(1) {} std::string fileName; std::string path; std::string filePath; std::vector resourceTrees; const ModuleResourceTree* associatedResourceTree; int node; int32_t size; const unsigned char* data; mutable std::vector children; bool isFile; /** * Reference count for implicitly shared private implementation. */ AtomicInt ref; }; ModuleResource::ModuleResource() : d(new ModuleResourcePrivate) { } ModuleResource::ModuleResource(const ModuleResource &resource) : d(resource.d) { d->ref.Ref(); } ModuleResource::ModuleResource(const std::string& _file, ModuleResourceTree* associatedResourceTree, const std::vector& resourceTrees) : d(new ModuleResourcePrivate) { d->resourceTrees = resourceTrees; d->associatedResourceTree = associatedResourceTree; std::string file = _file; if (file.empty()) file = "/"; if (file[0] != '/') file = std::string("/") + file; std::size_t index = file.find_last_of('/'); if (index < file.size()-1) { d->fileName = file.substr(index+1); } std::string rawPath = file.substr(0,index+1); // remove duplicate / std::string::value_type lastChar = 0; for (std::size_t i = 0; i < rawPath.size(); ++i) { if (rawPath[i] == '/' && lastChar == '/') { continue; } lastChar = rawPath[i]; d->path.push_back(lastChar); } d->filePath = d->path + d->fileName; d->node = d->associatedResourceTree->FindNode(GetResourcePath()); if (d->node != -1) { d->isFile = !associatedResourceTree->IsDir(d->node); if (d->isFile) { d->data = d->associatedResourceTree->GetData(d->node, &d->size); } } } ModuleResource::~ModuleResource() { if (!d->ref.Deref()) delete d; } ModuleResource& ModuleResource::operator =(const ModuleResource& resource) { ModuleResourcePrivate* curr_d = d; d = resource.d; d->ref.Ref(); if (!curr_d->ref.Deref()) delete curr_d; return *this; } bool ModuleResource::operator <(const ModuleResource& resource) const { return this->GetResourcePath() < resource.GetResourcePath(); } bool ModuleResource::operator ==(const ModuleResource& resource) const { return d->associatedResourceTree == resource.d->associatedResourceTree && this->GetResourcePath() == resource.GetResourcePath(); } bool ModuleResource::operator !=(const ModuleResource &resource) const { return !(*this == resource); } bool ModuleResource::IsValid() const { return d->associatedResourceTree && d->associatedResourceTree->IsValid() && d->node > -1; } ModuleResource::operator bool() const { return IsValid(); } std::string ModuleResource::GetName() const { return d->fileName; } std::string ModuleResource::GetPath() const { return d->path; } std::string ModuleResource::GetResourcePath() const { return d->filePath; } std::string ModuleResource::GetBaseName() const { return d->fileName.substr(0, d->fileName.find_first_of('.')); } std::string ModuleResource::GetCompleteBaseName() const { return d->fileName.substr(0, d->fileName.find_last_of('.')); } std::string ModuleResource::GetSuffix() const { std::size_t index = d->fileName.find_last_of('.'); return index < d->fileName.size()-1 ? d->fileName.substr(index+1) : std::string(""); } +std::string ModuleResource::GetCompleteSuffix() const +{ + std::size_t index = d->fileName.find_first_of('.'); + return index < d->fileName.size()-1 ? d->fileName.substr(index+1) : std::string(""); +} + bool ModuleResource::IsDir() const { return !d->isFile; } bool ModuleResource::IsFile() const { return d->isFile; } std::vector ModuleResource::GetChildren() const { if (d->isFile || !IsValid()) return d->children; if (!d->children.empty()) return d->children; for (std::size_t i = 0; i < d->resourceTrees.size(); ++i) { d->resourceTrees[i]->GetChildren(d->node, d->children); } return d->children; } int ModuleResource::GetSize() const { return d->size; } const unsigned char* ModuleResource::GetData() const { if (!IsValid()) return NULL; return d->data; } std::size_t ModuleResource::Hash() const { using namespace US_HASH_FUNCTION_NAMESPACE; return US_HASH_FUNCTION(std::string, this->GetResourcePath()); } US_END_NAMESPACE US_USE_NAMESPACE std::ostream& operator<<(std::ostream& os, const ModuleResource& resource) { return os << resource.GetResourcePath(); } diff --git a/Core/Code/CppMicroServices/src/module/usModuleResource.h b/Core/Code/CppMicroServices/src/module/usModuleResource.h index c022db7bc3..a4efe72076 100644 --- a/Core/Code/CppMicroServices/src/module/usModuleResource.h +++ b/Core/Code/CppMicroServices/src/module/usModuleResource.h @@ -1,100 +1,101 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics 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. =============================================================================*/ #ifndef USMODULERESOURCE_H #define USMODULERESOURCE_H #include #include #include US_MSVC_PUSH_DISABLE_WARNING(4396) US_BEGIN_NAMESPACE class ModuleResourcePrivate; class ModuleResourceTree; class US_EXPORT ModuleResource { public: ModuleResource(); ModuleResource(const ModuleResource& resource); ~ModuleResource(); ModuleResource& operator=(const ModuleResource& resource); bool operator<(const ModuleResource& resource) const; bool operator==(const ModuleResource& resource) const; bool operator!=(const ModuleResource& resource) const; bool IsValid() const; operator bool() const; std::string GetName() const; std::string GetPath() const; std::string GetResourcePath() const; std::string GetBaseName() const; std::string GetCompleteBaseName() const; std::string GetSuffix() const; + std::string GetCompleteSuffix() const; bool IsDir() const; bool IsFile() const; std::vector GetChildren() const; int GetSize() const; const unsigned char* GetData() const; private: ModuleResource(const std::string& file, ModuleResourceTree* resourceTree, const std::vector& resourceTrees); friend class Module; US_HASH_FUNCTION_FRIEND(ModuleResource); std::size_t Hash() const; ModuleResourcePrivate* d; }; US_END_NAMESPACE US_MSVC_POP_WARNING US_EXPORT std::ostream& operator<<(std::ostream& os, const US_PREPEND_NAMESPACE(ModuleResource)& resource); US_HASH_FUNCTION_NAMESPACE_BEGIN US_HASH_FUNCTION_BEGIN(US_PREPEND_NAMESPACE(ModuleResource)) return arg.Hash(); US_HASH_FUNCTION_END US_HASH_FUNCTION_NAMESPACE_END #endif // USMODULERESOURCE_H diff --git a/Core/Code/CppMicroServices/test/usModuleResourceTest.cpp b/Core/Code/CppMicroServices/test/usModuleResourceTest.cpp index 7b3130560b..8befc18601 100644 --- a/Core/Code/CppMicroServices/test/usModuleResourceTest.cpp +++ b/Core/Code/CppMicroServices/test/usModuleResourceTest.cpp @@ -1,475 +1,477 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics 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 #include #include #include #include #include #include #include "usTestUtilSharedLibrary.h" #include "usTestingMacros.h" #include #include US_USE_NAMESPACE namespace { void checkResourceInfo(const ModuleResource& res, const std::string& path, const std::string& baseName, const std::string& completeBaseName, const std::string& suffix, + const std::string& completeSuffix, int size, bool children = false) { US_TEST_CONDITION_REQUIRED(res.IsValid(), "Valid resource") US_TEST_CONDITION(res.GetBaseName() == baseName, "GetBaseName()") US_TEST_CONDITION(res.GetChildren().empty() == !children, "No children") US_TEST_CONDITION(res.GetCompleteBaseName() == completeBaseName, "GetCompleteBaseName()") US_TEST_CONDITION(res.GetName() == completeBaseName + "." + suffix, "GetName()") US_TEST_CONDITION(res.GetResourcePath() == path + completeBaseName + "." + suffix, "GetResourcePath()") US_TEST_CONDITION(res.GetPath() == path, "GetPath()") US_TEST_CONDITION(res.GetSize() == size, "Data size") US_TEST_CONDITION(res.GetSuffix() == suffix, "Suffix") + US_TEST_CONDITION(res.GetCompleteSuffix() == completeSuffix, "Complete suffix") } void testTextResource(Module* module) { ModuleResource res = module->GetResource("foo.txt"); #ifdef US_PLATFORM_WINDOWS - checkResourceInfo(res, "/", "foo", "foo", "txt", 16, false); + checkResourceInfo(res, "/", "foo", "foo", "txt", "txt", 16, false); const std::streampos ssize(13); const std::string fileData = "foo and\nbar\n\n"; #else - checkResourceInfo(res, "/", "foo", "foo", "txt", 13, false); + checkResourceInfo(res, "/", "foo", "foo", "txt", "txt", 13, false); const std::streampos ssize(12); const std::string fileData = "foo and\nbar\n"; #endif ModuleResourceStream rs(res); rs.seekg(0, std::ios::end); US_TEST_CONDITION(rs.tellg() == ssize, "Stream content length"); rs.seekg(0, std::ios::beg); std::string content; content.reserve(res.GetSize()); char buffer[1024]; while (rs.read(buffer, sizeof(buffer))) { content.append(buffer, sizeof(buffer)); } content.append(buffer, rs.gcount()); US_TEST_CONDITION(rs.eof(), "EOF check"); US_TEST_CONDITION(content == fileData, "Resource content"); rs.clear(); rs.seekg(0); US_TEST_CONDITION_REQUIRED(rs.tellg() == std::streampos(0), "Move to start") US_TEST_CONDITION_REQUIRED(rs.good(), "Start re-reading"); std::vector lines; std::string line; while (std::getline(rs, line)) { lines.push_back(line); } US_TEST_CONDITION_REQUIRED(lines.size() > 1, "Number of lines") US_TEST_CONDITION(lines[0] == "foo and", "Check first line") US_TEST_CONDITION(lines[1] == "bar", "Check second line") } void testTextResourceAsBinary(Module* module) { ModuleResource res = module->GetResource("foo.txt"); #ifdef US_PLATFORM_WINDOWS - checkResourceInfo(res, "/", "foo", "foo", "txt", 16, false); + checkResourceInfo(res, "/", "foo", "foo", "txt", "txt", 16, false); const std::streampos ssize(16); const std::string fileData = "foo and\r\nbar\r\n\r\n"; #else - checkResourceInfo(res, "/", "foo", "foo", "txt", 13, false); + checkResourceInfo(res, "/", "foo", "foo", "txt", "txt", 13, false); const std::streampos ssize(13); const std::string fileData = "foo and\nbar\n\n"; #endif ModuleResourceStream rs(res, std::ios_base::binary); rs.seekg(0, std::ios::end); US_TEST_CONDITION(rs.tellg() == ssize, "Stream content length"); rs.seekg(0, std::ios::beg); std::string content; content.reserve(res.GetSize()); char buffer[1024]; while (rs.read(buffer, sizeof(buffer))) { content.append(buffer, sizeof(buffer)); } content.append(buffer, rs.gcount()); US_TEST_CONDITION(rs.eof(), "EOF check"); US_TEST_CONDITION(content == fileData, "Resource content"); } void testInvalidResource(Module* module) { ModuleResource res = module->GetResource("invalid"); US_TEST_CONDITION_REQUIRED(res.IsValid() == false, "Check invalid resource") US_TEST_CONDITION(res.GetName().empty(), "Check empty name") US_TEST_CONDITION(res.GetPath().empty(), "Check empty path") US_TEST_CONDITION(res.GetResourcePath().empty(), "Check empty resource path") US_TEST_CONDITION(res.GetBaseName().empty(), "Check empty base name") US_TEST_CONDITION(res.GetCompleteBaseName().empty(), "Check empty complete base name") US_TEST_CONDITION(res.GetSuffix().empty(), "Check empty suffix") US_TEST_CONDITION(res.GetChildren().empty(), "Check empty children") US_TEST_CONDITION(res.GetSize() == 0, "Check zero size") US_TEST_CONDITION(res.GetData() == NULL, "Check NULL data") ModuleResourceStream rs(res); US_TEST_CONDITION(rs.good() == true, "Check invalid resource stream") rs.ignore(); US_TEST_CONDITION(rs.good() == false, "Check invalid resource stream") US_TEST_CONDITION(rs.eof() == true, "Check invalid resource stream") } void testSpecialCharacters(Module* module) { ModuleResource res = module->GetResource("special_chars.dummy.txt"); #ifdef US_PLATFORM_WINDOWS - checkResourceInfo(res, "/", "special_chars", "special_chars.dummy", "txt", 56, false); + checkResourceInfo(res, "/", "special_chars", "special_chars.dummy", "txt", "dummy.txt", 56, false); const std::streampos ssize(54); const std::string fileData = "German Füße (feet)\nFrench garçon de café (waiter)\n"; #else - checkResourceInfo(res, "/", "special_chars", "special_chars.dummy", "txt", 54, false); + checkResourceInfo(res, "/", "special_chars", "special_chars.dummy", "txt", "dummy.txt", 54, false); const std::streampos ssize(53); const std::string fileData = "German Füße (feet)\nFrench garçon de café (waiter)"; #endif ModuleResourceStream rs(res); rs.seekg(0, std::ios_base::end); US_TEST_CONDITION(rs.tellg() == ssize, "Stream content length"); rs.seekg(0, std::ios_base::beg); std::string content; content.reserve(res.GetSize()); char buffer[1024]; while (rs.read(buffer, sizeof(buffer))) { content.append(buffer, sizeof(buffer)); } content.append(buffer, rs.gcount()); US_TEST_CONDITION(rs.eof(), "EOF check"); US_TEST_CONDITION(content == fileData, "Resource content"); } void testBinaryResource(Module* module) { ModuleResource res = module->GetResource("/icons/cppmicroservices.png"); - checkResourceInfo(res, "/icons/", "cppmicroservices", "cppmicroservices", "png", 2424, false); + checkResourceInfo(res, "/icons/", "cppmicroservices", "cppmicroservices", "png", "png", 2424, false); ModuleResourceStream rs(res, std::ios_base::binary); rs.seekg(0, std::ios_base::end); std::streampos resLength = rs.tellg(); rs.seekg(0); std::ifstream png(CppMicroServices_SOURCE_DIR "/test/modules/libRWithResources/resources/icons/cppmicroservices.png", std::ifstream::in | std::ifstream::binary); US_TEST_CONDITION_REQUIRED(png.is_open(), "Open reference file") png.seekg(0, std::ios_base::end); std::streampos pngLength = png.tellg(); png.seekg(0); US_TEST_CONDITION(resLength = res.GetSize(), "Check resource size") US_TEST_CONDITION_REQUIRED(resLength == pngLength, "Compare sizes") char c1 = 0; char c2 = 0; bool isEqual = true; int count = 0; while (png.get(c1) && rs.get(c2)) { ++count; if (c1 != c2) { isEqual = false; break; } } US_TEST_CONDITION_REQUIRED(count == pngLength, "Check if everything was read"); US_TEST_CONDITION_REQUIRED(isEqual, "Equal binary contents"); US_TEST_CONDITION(png.eof(), "EOF check"); } struct ResourceComparator { bool operator()(const ModuleResource& mr1, const ModuleResource& mr2) const { return mr1 < mr2; } }; void testResourceTree(Module* module) { ModuleResource res = module->GetResource(""); US_TEST_CONDITION(res.GetResourcePath() == "/", "Check root file path") US_TEST_CONDITION(res.IsDir() == true, "Check type") std::vector children = res.GetChildren(); std::sort(children.begin(), children.end()); US_TEST_CONDITION_REQUIRED(children.size() == 4, "Check child count") US_TEST_CONDITION(children[0] == "foo.txt", "Check child name") US_TEST_CONDITION(children[1] == "icons", "Check child name") US_TEST_CONDITION(children[2] == "special_chars.dummy.txt", "Check child name") US_TEST_CONDITION(children[3] == "test.xml", "Check child name") ModuleResource readme = module->GetResource("/icons/readme.txt"); US_TEST_CONDITION(readme.IsFile() && readme.GetChildren().empty(), "Check file resource") ModuleResource icons = module->GetResource("icons"); US_TEST_CONDITION(icons.IsDir() && !icons.IsFile() && !icons.GetChildren().empty(), "Check directory resource") children = icons.GetChildren(); US_TEST_CONDITION_REQUIRED(children.size() == 2, "Check icons child count") std::sort(children.begin(), children.end()); US_TEST_CONDITION(children[0] == "cppmicroservices.png", "Check child name") US_TEST_CONDITION(children[1] == "readme.txt", "Check child name") ResourceComparator resourceComparator; // find all .txt files std::vector nodes = module->FindResources("", "*.txt", false); std::sort(nodes.begin(), nodes.end(), resourceComparator); US_TEST_CONDITION_REQUIRED(nodes.size() == 2, "Found child count") US_TEST_CONDITION(nodes[0].GetResourcePath() == "/foo.txt", "Check child name") US_TEST_CONDITION(nodes[1].GetResourcePath() == "/special_chars.dummy.txt", "Check child name") nodes = module->FindResources("", "*.txt", true); std::sort(nodes.begin(), nodes.end(), resourceComparator); US_TEST_CONDITION_REQUIRED(nodes.size() == 3, "Found child count") US_TEST_CONDITION(nodes[0].GetResourcePath() == "/foo.txt", "Check child name") US_TEST_CONDITION(nodes[1].GetResourcePath() == "/icons/readme.txt", "Check child name") US_TEST_CONDITION(nodes[2].GetResourcePath() == "/special_chars.dummy.txt", "Check child name") // find all resources nodes = module->FindResources("", "", true); US_TEST_CONDITION(nodes.size() == 5, "Total resource number") nodes = module->FindResources("", "**", true); US_TEST_CONDITION(nodes.size() == 5, "Total resource number") // test pattern matching nodes.clear(); nodes = module->FindResources("/icons", "*micro*.png", false); US_TEST_CONDITION(nodes.size() == 1 && nodes[0].GetResourcePath() == "/icons/cppmicroservices.png", "Check file pattern matches") nodes.clear(); nodes = module->FindResources("", "*.txt", true); US_TEST_CONDITION(nodes.size() == 3, "Check recursive pattern matches") } void testStaticResourceTree(Module* module) { ModuleResource res = module->GetResource(""); US_TEST_CONDITION(res.GetResourcePath() == "/", "Check root file path") US_TEST_CONDITION(res.IsDir() == true, "Check type") std::vector children = res.GetChildren(); std::sort(children.begin(), children.end()); US_TEST_CONDITION_REQUIRED(children.size() == 8, "Check child count") US_TEST_CONDITION(children[0] == "dynamic.txt", "Check dynamic.txt child name") US_TEST_CONDITION(children[1] == "foo.txt", "Check foo.txt child name") US_TEST_CONDITION(children[2] == "icons", "Check icons child name") US_TEST_CONDITION(children[3] == "res.txt", "Check res.txt child name") US_TEST_CONDITION(children[4] == "res.txt", "Check res.txt child name") US_TEST_CONDITION(children[5] == "special_chars.dummy.txt", "Check special_chars.dummy.txt child name") US_TEST_CONDITION(children[6] == "static.txt", "Check static.txt child name") US_TEST_CONDITION(children[7] == "test.xml", "Check test.xml child name") ModuleResource readme = module->GetResource("/icons/readme.txt"); US_TEST_CONDITION(readme.IsFile() && readme.GetChildren().empty(), "Check file resource") ModuleResource icons = module->GetResource("icons"); US_TEST_CONDITION(icons.IsDir() && !icons.IsFile() && !icons.GetChildren().empty(), "Check directory resource") children = icons.GetChildren(); US_TEST_CONDITION_REQUIRED(children.size() == 2, "Check icons child count") std::sort(children.begin(), children.end()); US_TEST_CONDITION(children[0] == "cppmicroservices.png", "Check child name") US_TEST_CONDITION(children[1] == "readme.txt", "Check child name") ResourceComparator resourceComparator; // find all .txt files std::vector nodes = module->FindResources("", "*.txt", false); std::sort(nodes.begin(), nodes.end(), resourceComparator); US_TEST_CONDITION_REQUIRED(nodes.size() == 6, "Found child count") US_TEST_CONDITION(nodes[0].GetResourcePath() == "/dynamic.txt", "Check dynamic.txt child name") US_TEST_CONDITION(nodes[1].GetResourcePath() == "/foo.txt", "Check child name") US_TEST_CONDITION(nodes[2].GetResourcePath() == "/res.txt", "Check res.txt child name") US_TEST_CONDITION(nodes[3].GetResourcePath() == "/res.txt", "Check res.txt child name") US_TEST_CONDITION(nodes[4].GetResourcePath() == "/special_chars.dummy.txt", "Check child name") US_TEST_CONDITION(nodes[5].GetResourcePath() == "/static.txt", "Check static.txt child name") nodes = module->FindResources("", "*.txt", true); std::sort(nodes.begin(), nodes.end(), resourceComparator); US_TEST_CONDITION_REQUIRED(nodes.size() == 7, "Found child count") US_TEST_CONDITION(nodes[0].GetResourcePath() == "/dynamic.txt", "Check dynamic.txt child name") US_TEST_CONDITION(nodes[1].GetResourcePath() == "/foo.txt", "Check child name") US_TEST_CONDITION(nodes[2].GetResourcePath() == "/icons/readme.txt", "Check child name") US_TEST_CONDITION(nodes[3].GetResourcePath() == "/res.txt", "Check res.txt child name") US_TEST_CONDITION(nodes[4].GetResourcePath() == "/res.txt", "Check res.txt child name") US_TEST_CONDITION(nodes[5].GetResourcePath() == "/special_chars.dummy.txt", "Check child name") US_TEST_CONDITION(nodes[6].GetResourcePath() == "/static.txt", "Check static.txt child name") // find all resources nodes = module->FindResources("", "", true); US_TEST_CONDITION(nodes.size() == 9, "Total resource number") nodes = module->FindResources("", "**", true); US_TEST_CONDITION(nodes.size() == 9, "Total resource number") // test pattern matching nodes.clear(); nodes = module->FindResources("/icons", "*micro*.png", false); US_TEST_CONDITION(nodes.size() == 1 && nodes[0].GetResourcePath() == "/icons/cppmicroservices.png", "Check file pattern matches") nodes.clear(); nodes = module->FindResources("", "*.txt", true); US_TEST_CONDITION(nodes.size() == 7, "Check recursive pattern matches") } void testResourceOperators(Module* module) { ModuleResource invalid = module->GetResource("invalid"); ModuleResource foo = module->GetResource("foo.txt"); US_TEST_CONDITION_REQUIRED(foo.IsValid() && foo, "Check valid resource") ModuleResource foo2(foo); US_TEST_CONDITION(foo == foo, "Check equality operator") US_TEST_CONDITION(foo == foo2, "Check copy constructor and equality operator") US_TEST_CONDITION(foo != invalid, "Check inequality with invalid resource") ModuleResource xml = module->GetResource("/test.xml"); US_TEST_CONDITION_REQUIRED(xml.IsValid() && xml, "Check valid resource") US_TEST_CONDITION(foo != xml, "Check inequality") US_TEST_CONDITION(foo < xml, "Check operator<") // check operator< by using a set std::set resources; resources.insert(foo); resources.insert(foo); resources.insert(xml); US_TEST_CONDITION(resources.size() == 2, "Check operator< with set") // check hash function specialization US_UNORDERED_SET_TYPE resources2; resources2.insert(foo); resources2.insert(foo); resources2.insert(xml); US_TEST_CONDITION(resources2.size() == 2, "Check operator< with unordered set") // check operator<< std::ostringstream oss; oss << foo; US_TEST_CONDITION(oss.str() == foo.GetResourcePath(), "Check operator<<") } void testResourceFromExecutable(Module* module) { ModuleResource resource = module->GetResource("usTestResource.txt"); US_TEST_CONDITION_REQUIRED(resource.IsValid(), "Check valid executable resource") std::string line; ModuleResourceStream rs(resource); std::getline(rs, line); US_TEST_CONDITION(line == "meant to be compiled into the test driver", "Check executable resource content") } } // end unnamed namespace int usModuleResourceTest(int /*argc*/, char* /*argv*/[]) { US_TEST_BEGIN("ModuleResourceTest"); ModuleContext* mc = GetModuleContext(); assert(mc); #ifdef US_BUILD_SHARED_LIBS SharedLibraryHandle libR("TestModuleR"); try { libR.Load(); } catch (const std::exception& e) { US_TEST_FAILED_MSG(<< "Load module exception: " << e.what()) } Module* moduleR = ModuleRegistry::GetModule("TestModuleR Module"); US_TEST_CONDITION_REQUIRED(moduleR != NULL, "Test for existing module TestModuleR") US_TEST_CONDITION(moduleR->GetName() == "TestModuleR Module", "Test module name") testInvalidResource(moduleR); testResourceTree(moduleR); testResourceFromExecutable(mc->GetModule()); #else Module* moduleR = mc->GetModule(); US_TEST_CONDITION_REQUIRED(moduleR != NULL, "Test for existing module 0") US_TEST_CONDITION(moduleR->GetName() == "CppMicroServices", "Test module name") testStaticResourceTree(moduleR); #endif testResourceOperators(moduleR); testTextResource(moduleR); testTextResourceAsBinary(moduleR); testSpecialCharacters(moduleR); testBinaryResource(moduleR); #ifdef US_BUILD_SHARED_LIBS ModuleResource foo = moduleR->GetResource("foo.txt"); US_TEST_CONDITION(foo.IsValid() == true, "Valid resource") libR.Unload(); US_TEST_CONDITION(foo.IsValid() == false, "Invalidated resource") US_TEST_CONDITION(foo.GetData() == NULL, "NULL data") #endif US_TEST_END() }