From 5374e7ece90472424e75ccfc18655b9c581b3602 Mon Sep 17 00:00:00 2001 From: TheAssassin Date: Sat, 22 Dec 2018 23:09:04 +0100 Subject: [PATCH] Switch to extracted desktop file library --- .gitmodules | 21 +- include/linuxdeploy/core/appdir.h | 2 +- .../core/desktopfile/desktopfile.h | 126 ----- .../core/desktopfile/desktopfileentry.h | 71 --- .../linuxdeploy/core/desktopfile/exceptions.h | 40 -- lib/CMakeLists.txt | 34 +- lib/boost-array | 1 - lib/boost-concept_check | 1 - lib/boost-lexical_cast | 1 - lib/boost-math | 1 - lib/boost-move | 1 - lib/boost-numeric_conversion | 1 - lib/linuxdeploy-desktopfile | 1 + src/CMakeLists.txt | 2 +- src/core.cpp | 1 + src/core/CMakeLists.txt | 3 +- src/core/appdir.cpp | 6 +- src/core/desktopfile/CMakeLists.txt | 17 - src/core/desktopfile/desktopfile.cpp | 214 -------- src/core/desktopfile/desktopfileentry.cpp | 125 ----- src/core/desktopfile/desktopfilereader.cpp | 216 -------- src/core/desktopfile/desktopfilereader.h | 66 --- src/core/desktopfile/desktopfilewriter.cpp | 102 ---- src/core/desktopfile/desktopfilewriter.h | 58 --- src/main.cpp | 5 +- tests/core/CMakeLists.txt | 4 - tests/core/desktopfile/CMakeLists.txt | 17 - tests/core/desktopfile/main.cpp | 15 - tests/core/desktopfile/test_desktopfile.cpp | 279 ----------- .../test_desktopfile_conformance.cpp | 90 ---- .../desktopfile/test_desktopfileentry.cpp | 146 ------ .../desktopfile/test_desktopfilereader.cpp | 468 ------------------ .../desktopfile/test_desktopfilewriter.cpp | 108 ---- tests/core/test_appdir.cpp | 2 +- 34 files changed, 18 insertions(+), 2227 deletions(-) delete mode 100644 include/linuxdeploy/core/desktopfile/desktopfile.h delete mode 100644 include/linuxdeploy/core/desktopfile/desktopfileentry.h delete mode 100644 include/linuxdeploy/core/desktopfile/exceptions.h delete mode 160000 lib/boost-array delete mode 160000 lib/boost-concept_check delete mode 160000 lib/boost-lexical_cast delete mode 160000 lib/boost-math delete mode 160000 lib/boost-move delete mode 160000 lib/boost-numeric_conversion create mode 160000 lib/linuxdeploy-desktopfile delete mode 100644 src/core/desktopfile/CMakeLists.txt delete mode 100644 src/core/desktopfile/desktopfile.cpp delete mode 100644 src/core/desktopfile/desktopfileentry.cpp delete mode 100644 src/core/desktopfile/desktopfilereader.cpp delete mode 100644 src/core/desktopfile/desktopfilereader.h delete mode 100644 src/core/desktopfile/desktopfilewriter.cpp delete mode 100644 src/core/desktopfile/desktopfilewriter.h delete mode 100644 tests/core/desktopfile/CMakeLists.txt delete mode 100644 tests/core/desktopfile/main.cpp delete mode 100644 tests/core/desktopfile/test_desktopfile.cpp delete mode 100644 tests/core/desktopfile/test_desktopfile_conformance.cpp delete mode 100644 tests/core/desktopfile/test_desktopfileentry.cpp delete mode 100644 tests/core/desktopfile/test_desktopfilereader.cpp delete mode 100644 tests/core/desktopfile/test_desktopfilewriter.cpp diff --git a/.gitmodules b/.gitmodules index eaaa619..6bd501f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -76,24 +76,9 @@ [submodule "lib/googletest"] path = lib/googletest url = https://github.com/google/googletest -[submodule "lib/boost-lexical_cast"] - path = lib/boost-lexical_cast - url = https://github.com/boostorg/lexical_cast -[submodule "lib/boost-concept_check"] - path = lib/boost-concept_check - url = https://github.com/boostorg/concept_check -[submodule "lib/boost-numeric_conversion"] - path = lib/boost-numeric_conversion - url = https://github.com/boostorg/numeric_conversion -[submodule "lib/boost-array"] - path = lib/boost-array - url = https://github.com/boostorg/array [submodule "lib/boost-container"] path = lib/boost-container url = https://github.com/boostorg/container -[submodule "lib/boost-move"] - path = lib/boost-move - url = https://github.com/boostorg/move -[submodule "lib/boost-math"] - path = lib/boost-math - url = https://github.com/boostorg/math +[submodule "lib/linuxdeploy-desktopfile"] + path = lib/linuxdeploy-desktopfile + url = https://github.com/linuxdeploy/linuxdeploy-desktopfile diff --git a/include/linuxdeploy/core/appdir.h b/include/linuxdeploy/core/appdir.h index b9eb3e5..b0d17f6 100644 --- a/include/linuxdeploy/core/appdir.h +++ b/include/linuxdeploy/core/appdir.h @@ -5,7 +5,7 @@ #include // local includes -#include "linuxdeploy/core/desktopfile/desktopfile.h" +#include "linuxdeploy/desktopfile/desktopfile.h" #pragma once diff --git a/include/linuxdeploy/core/desktopfile/desktopfile.h b/include/linuxdeploy/core/desktopfile/desktopfile.h deleted file mode 100644 index 92a79ef..0000000 --- a/include/linuxdeploy/core/desktopfile/desktopfile.h +++ /dev/null @@ -1,126 +0,0 @@ -// system includes -#include - -// library includes -#include - -// local includes -#include "desktopfileentry.h" - -#pragma once - -namespace linuxdeploy { - namespace core { - namespace desktopfile { - /* - * Parse and read desktop files. - */ - class DesktopFile { - public: - // describes a single section - typedef std::unordered_map section_t; - - // describes all sections in the desktop file - typedef std::unordered_map sections_t; - - private: - // private data class pattern - class PrivateData; - std::shared_ptr d; - - // (in)equality operators are implemented outside this class - friend bool operator==(const DesktopFile& first, const DesktopFile& second); - friend bool operator!=(const DesktopFile& first, const DesktopFile& second); - - public: - // default constructor - DesktopFile(); - - // construct from existing desktop file - // if the file exists, it will be read using DesktopFileReader - // if reading fails, exceptions will be thrown (see DesktopFileReader for more information) - explicit DesktopFile(const boost::filesystem::path& path); - - // construct by reading an existing stream - // file must exist, otherwise std::runtime_error is thrown - explicit DesktopFile(std::istream& is); - - // copy constructor - DesktopFile(const DesktopFile& other); - - // copy assignment constructor - DesktopFile& operator=(const DesktopFile& other); - - // move assignment operator - DesktopFile& operator=(DesktopFile&& other) noexcept; - - public: - // returns true if a file has been loaded, false otherwise - bool isEmpty() const; - - // read desktop file - // sets path associated with this file - // throws exceptions in case of issues, see DesktopFileReader for more information - void read(const boost::filesystem::path& path); - - // read desktop file from existing stream - // throws exceptions in case of issues, see DesktopFileReader for more information - void read(std::istream& is); - - // get path associated with this file - boost::filesystem::path path() const; - - // sets the path associated with this desktop file - // used to e.g., save the desktop file - void setPath(const boost::filesystem::path& path); - - // clear contents of desktop file - void clear(); - - // save desktop file - bool save() const; - - // save desktop file to path - // does not change path associated with desktop file - // throws exceptions in case of errors, see DesktopFileWriter::save(...) for more information - bool save(const boost::filesystem::path& path) const; - - // save desktop file to ostream - // does not change path associated with desktop file - // throws exceptions in case of errors, see DesktopFileWriter::save(...) for more information - bool save(std::ostream& os) const; - - // check if entry exists in given section and key - bool entryExists(const std::string& section, const std::string& key) const; - - // get key from desktop file - // an std::string passed as value parameter will be populated with the contents - // returns true (and populates value) if the key exists, false otherwise - bool getEntry(const std::string& section, const std::string& key, DesktopFileEntry& value) const; - - // add key to section in desktop file - // the section will be created if it doesn't exist already - // returns true if an existing key was overwritten, false otherwise - bool setEntry(const std::string& section, const DesktopFileEntry& entry); - - // add key to section in desktop file - // the section will be created if it doesn't exist already - // returns true if an existing key was overwritten, false otherwise - bool setEntry(const std::string& section, DesktopFileEntry&& entry); - - // create common application entries in desktop file - // returns false if one of the keys exists and was left unmodified - bool addDefaultKeys(const std::string& executableFileName); - - // validate desktop file - bool validate() const; - }; - - // DesktopFile equality operator - bool operator==(const DesktopFile& first, const DesktopFile& second); - - // DesktopFile inequality operator - bool operator!=(const DesktopFile& first, const DesktopFile& second); - } - } -} diff --git a/include/linuxdeploy/core/desktopfile/desktopfileentry.h b/include/linuxdeploy/core/desktopfile/desktopfileentry.h deleted file mode 100644 index 97bc6ce..0000000 --- a/include/linuxdeploy/core/desktopfile/desktopfileentry.h +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once - -// system headers -#include -#include - -// library headers -#include - -namespace linuxdeploy { - namespace core { - namespace desktopfile { - class DesktopFileEntry { - private: - // opaque data class pattern - class PrivateData; - - std::shared_ptr d; - - public: - // default constructor - DesktopFileEntry(); - - // construct from key and value - explicit DesktopFileEntry(std::string key, std::string value); - - // copy constructor - DesktopFileEntry(const DesktopFileEntry& other); - - // copy assignment constructor - DesktopFileEntry& operator=(const DesktopFileEntry& other); - - // move assignment operator - DesktopFileEntry& operator=(DesktopFileEntry&& other) noexcept; - - // equality operator - bool operator==(const DesktopFileEntry& other) const; - - // inequality operator - bool operator!=(const DesktopFileEntry& other) const; - - public: - // checks whether a key and value have been set - bool isEmpty() const; - - // return entry's key - const std::string& key() const; - - // return entry's value - const std::string& value() const; - - public: - // convert value to integer - // throws boost::bad_lexical_cast in case of type errors - int32_t asInt() const; - - // convert value to long - // throws boost::bad_lexical_cast in case of type errors - int64_t asLong() const; - - // convert value to double - // throws boost::bad_lexical_cast in case of type errors - double asDouble() const; - - // split CSV list value into vector - // the separator used to split the string is a semicolon as per desktop file spec - std::vector parseStringList() const; - }; - } - } -} diff --git a/include/linuxdeploy/core/desktopfile/exceptions.h b/include/linuxdeploy/core/desktopfile/exceptions.h deleted file mode 100644 index 8e1ea1f..0000000 --- a/include/linuxdeploy/core/desktopfile/exceptions.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -// system includes -#include -#include - -namespace linuxdeploy { - namespace core { - namespace desktopfile { - /** - * Desktop file library's base exception. - */ - class DesktopFileError : public std::runtime_error { - public: - explicit DesktopFileError(const std::string& message = "unknown desktop file error") : runtime_error(message) {}; - }; - - /** - * Exception thrown by DesktopFileReader on parsing errors. - */ - class ParseError : public DesktopFileError { - public: - explicit ParseError(const std::string& message = "unknown parse error") : DesktopFileError(message) {}; - }; - - /** - * I/O exception, thrown if files cannot be opened, reading or writing fails etc. - */ - class IOError : public DesktopFileError { - public: - explicit IOError(const std::string& message = "unknown I/O error") : DesktopFileError(message) {}; - }; - - class UnknownSectionError : public DesktopFileError { - public: - explicit UnknownSectionError(const std::string& section) : DesktopFileError("unknown section: " + section) {}; - }; - } - } -} diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index a6ed21e..a16eec6 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -9,6 +9,8 @@ add_library(args INTERFACE) target_sources(args INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/args/args.hxx) target_include_directories(args INTERFACE args) +add_subdirectory(linuxdeploy-desktopfile) + if(NOT USE_SYSTEM_BOOST) add_library(boost_config INTERFACE) set_property(TARGET boost_config PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$") @@ -101,38 +103,8 @@ if(NOT USE_SYSTEM_BOOST) boost_config boost_predef boost_assert boost_throw_exception boost_smart_ptr boost_core boost_mpl boost_type_traits boost_static_assert boost_integer boost_preprocessor boost_functional boost_detail ) - - add_library(boost_numeric_conversion INTERFACE) - set_property(TARGET boost_numeric_conversion PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$") - set_property(TARGET boost_numeric_conversion PROPERTY INTERFACE_LINK_LIBRARIES "boost_config") - - add_library(boost_concept_check INTERFACE) - set_property(TARGET boost_concept_check PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$") - set_property(TARGET boost_concept_check PROPERTY INTERFACE_LINK_LIBRARIES "boost_config") - target_link_libraries(boost_concept_check INTERFACE boost_numeric_conversion) - - add_library(boost_array INTERFACE) - set_property(TARGET boost_array PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$") - set_property(TARGET boost_array PROPERTY INTERFACE_LINK_LIBRARIES "boost_config") - - add_library(boost_move INTERFACE) - set_property(TARGET boost_move PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$") - set_property(TARGET boost_move PROPERTY INTERFACE_LINK_LIBRARIES "boost_config") - - add_library(boost_container INTERFACE) - set_property(TARGET boost_container PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$") - set_property(TARGET boost_container PROPERTY INTERFACE_LINK_LIBRARIES boost_config boost_move) - - add_library(boost_math INTERFACE) - set_property(TARGET boost_math PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$") - set_property(TARGET boost_math PROPERTY INTERFACE_LINK_LIBRARIES boost_config boost_move) - - add_library(boost_lexical_cast INTERFACE) - set_property(TARGET boost_lexical_cast PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$") - set_property(TARGET boost_lexical_cast PROPERTY INTERFACE_LINK_LIBRARIES "boost_config") - target_link_libraries(boost_lexical_cast INTERFACE boost_concept_check boost_numeric_conversion boost_array boost_container boost_math) endif() -if(BUILD_TESTING) +if(BUILD_TESTING AND NOT TARGET gtest) add_subdirectory(googletest) endif() diff --git a/lib/boost-array b/lib/boost-array deleted file mode 160000 index cef221d..0000000 --- a/lib/boost-array +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cef221d8b4fe89325c4d0678519b0d59d2a82075 diff --git a/lib/boost-concept_check b/lib/boost-concept_check deleted file mode 160000 index 7dbaa85..0000000 --- a/lib/boost-concept_check +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7dbaa8541362bb2011f766cf16e6d1f0169af375 diff --git a/lib/boost-lexical_cast b/lib/boost-lexical_cast deleted file mode 160000 index 5cd9771..0000000 --- a/lib/boost-lexical_cast +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5cd977133786b58acab162344024e3a12f795034 diff --git a/lib/boost-math b/lib/boost-math deleted file mode 160000 index 6bbba17..0000000 --- a/lib/boost-math +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6bbba17f9e5deded2427342ba34454227836b8ce diff --git a/lib/boost-move b/lib/boost-move deleted file mode 160000 index 3ce9452..0000000 --- a/lib/boost-move +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3ce9452f93c8675dcac98f2ab5b1a1fd2aaeb22a diff --git a/lib/boost-numeric_conversion b/lib/boost-numeric_conversion deleted file mode 160000 index b900379..0000000 --- a/lib/boost-numeric_conversion +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b900379a744b3452f6d7a568bbe702a71a2d0f4e diff --git a/lib/linuxdeploy-desktopfile b/lib/linuxdeploy-desktopfile new file mode 160000 index 0000000..31718ac --- /dev/null +++ b/lib/linuxdeploy-desktopfile @@ -0,0 +1 @@ +Subproject commit 31718acde5251855ff3931aa7ba266f5092cf45d diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e049b05..d7bba6d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,7 @@ if(USE_SYSTEM_BOOST) set(BOOST_LIBS Boost::filesystem Boost::regex) else() # use custom built libs - set(BOOST_LIBS boost_system boost_filesystem boost_regex boost_lexical_cast) + set(BOOST_LIBS boost_system boost_filesystem boost_regex) endif() diff --git a/src/core.cpp b/src/core.cpp index f5884a4..9a516b2 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -8,6 +8,7 @@ using namespace linuxdeploy::core; using namespace linuxdeploy::core::log; +using namespace linuxdeploy::desktopfile; namespace bf = boost::filesystem; namespace linuxdeploy { diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2817aa3..136abb1 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -18,11 +18,10 @@ target_include_directories(linuxdeploy_core_log PUBLIC ${PROJECT_SOURCE_DIR}/inc target_link_libraries(linuxdeploy_core_log PUBLIC ${BOOST_LIBS}) add_subdirectory(copyright) -add_subdirectory(desktopfile) add_library(linuxdeploy_core STATIC elf.cpp appdir.cpp ${HEADERS}) target_link_libraries(linuxdeploy_core PUBLIC - linuxdeploy_plugin linuxdeploy_core_log linuxdeploy_util linuxdeploy_core_desktopfile + linuxdeploy_plugin linuxdeploy_core_log linuxdeploy_util linuxdeploy_desktopfile ${BOOST_LIBS} CImg ${CMAKE_THREAD_LIBS_INIT} ) target_link_libraries(linuxdeploy_core PRIVATE linuxdeploy_core_copyright) diff --git a/src/core/appdir.cpp b/src/core/appdir.cpp index 60eeaa5..2f3e5a7 100644 --- a/src/core/appdir.cpp +++ b/src/core/appdir.cpp @@ -12,9 +12,9 @@ // local headers #include "linuxdeploy/core/appdir.h" -#include "linuxdeploy/core/desktopfile/desktopfileentry.h" #include "linuxdeploy/core/elf.h" #include "linuxdeploy/core/log.h" +#include "linuxdeploy/desktopfile/desktopfileentry.h" #include "linuxdeploy/util/util.h" #include "copyright.h" @@ -22,7 +22,7 @@ #include "excludelist.h" using namespace linuxdeploy::core; -using namespace linuxdeploy::core::desktopfile; +using namespace linuxdeploy::desktopfile; using namespace linuxdeploy::core::log; using namespace cimg_library; @@ -651,7 +651,7 @@ namespace linuxdeploy { }), paths.end()); for (const auto& path : paths) { - desktopFiles.emplace_back(path); + desktopFiles.emplace_back(path.string()); } return desktopFiles; diff --git a/src/core/desktopfile/CMakeLists.txt b/src/core/desktopfile/CMakeLists.txt deleted file mode 100644 index 14919a7..0000000 --- a/src/core/desktopfile/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -cmake_minimum_required(VERSION 3.0) - -file(GLOB HEADERS ${PROJECT_SOURCE_DIR}/include/linuxdeploy/core/desktopfile/*.h) - -add_library(linuxdeploy_core_desktopfile STATIC - desktopfile.cpp - desktopfileentry.cpp - desktopfilereader.cpp - desktopfilewriter.cpp - desktopfilereader.h - desktopfilewriter.h - ${HEADERS} -) - -target_include_directories(linuxdeploy_core_desktopfile PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -target_link_libraries(linuxdeploy_core_desktopfile PUBLIC linuxdeploy_util linuxdeploy_core_log ${BOOST_LIBS}) diff --git a/src/core/desktopfile/desktopfile.cpp b/src/core/desktopfile/desktopfile.cpp deleted file mode 100644 index 5e93fb5..0000000 --- a/src/core/desktopfile/desktopfile.cpp +++ /dev/null @@ -1,214 +0,0 @@ -// local headers -#include "linuxdeploy/core/desktopfile/exceptions.h" -#include "linuxdeploy/core/desktopfile/desktopfile.h" -#include "linuxdeploy/core/log.h" -#include "desktopfilereader.h" -#include "desktopfilewriter.h" - -using namespace linuxdeploy::core; -using namespace linuxdeploy::core::log; - -namespace bf = boost::filesystem; - -namespace linuxdeploy { - namespace core { - namespace desktopfile { - class DesktopFile::PrivateData { - public: - bf::path path; - sections_t data; - - public: - PrivateData() = default; - - void copyData(const std::shared_ptr& other) { - path = other->path; - data = other->data; - } - - public: - bool isEmpty() const { - return data.empty(); - } - }; - - DesktopFile::DesktopFile() : d(std::make_shared()) {} - - DesktopFile::DesktopFile(const bf::path& path) : DesktopFile() { - // if the file doesn't exist, an exception shall be thrown - // otherwise, a user cannot know for sure whether a file was actually read (would need to check this - // manually beforehand - if (!bf::exists(path)) { - throw IOError("Could not find file " + path.string()); - } - - // will throw exceptions in case of issues - read(path); - }; - - DesktopFile::DesktopFile(std::istream& is) : DesktopFile() { - // will throw exceptions in case of issues - read(is); - }; - - // copy constructor - DesktopFile::DesktopFile(const DesktopFile& other) : DesktopFile() { - d->copyData(other.d); - } - - // copy assignment constructor - DesktopFile& DesktopFile::operator=(const DesktopFile& other) { - if (this != &other) { - d->copyData(other.d); - } - - return *this; - } - - // move assignment operator - DesktopFile& DesktopFile::operator=(DesktopFile&& other) noexcept { - if (this != &other) { - d = other.d; - other.d = nullptr; - } - return *this; - } - - void DesktopFile::read(const boost::filesystem::path& path) { - setPath(path); - - // clear data before reading a new file - clear(); - - DesktopFileReader reader(path); - d->data = std::move(reader.data()); - } - - void DesktopFile::read(std::istream& is) { - // clear data before reading a new file - clear(); - - DesktopFileReader reader(is); - d->data = reader.data(); - } - - boost::filesystem::path DesktopFile::path() const { - return d->path; - } - - void DesktopFile::setPath(const boost::filesystem::path& path) { - d->path = path; - } - - bool DesktopFile::isEmpty() const { - return d->isEmpty(); - } - - void DesktopFile::clear() { - d->data.clear(); - } - - bool DesktopFile::save() const { - return save(d->path); - } - - bool DesktopFile::save(const boost::filesystem::path& path) const { - DesktopFileWriter writer(d->data); - writer.save(path); - - return true; - } - - bool DesktopFile::save(std::ostream& os) const { - DesktopFileWriter writer(d->data); - writer.save(os); - - return true; - } - - bool DesktopFile::entryExists(const std::string& section, const std::string& key) const { - auto it = d->data.find(section); - if (it == d->data.end()) - return false; - - return (it->second.find(key) != it->second.end()); - } - - bool DesktopFile::setEntry(const std::string& section, const DesktopFileEntry& entry) { - // check if value exists -- used for return value - auto rv = entryExists(section, entry.key()); - - d->data[section][entry.key()] = entry; - - return rv; - } - - bool DesktopFile::setEntry(const std::string& section, DesktopFileEntry&& entry) { - // check if value exists -- used for return value - auto rv = entryExists(section, entry.key()); - - d->data[section][entry.key()] = entry; - - return rv; - } - - bool DesktopFile::getEntry(const std::string& section, const std::string& key, DesktopFileEntry& entry) const { - if (!entryExists(section, key)) - return false; - - entry = d->data[section][key]; - - // make sure keys are equal - assert(key == entry.key()); - - return true; - } - - bool DesktopFile::addDefaultKeys(const std::string& executableFileName) { - ldLog() << "Adding default values to desktop file:" << path() << std::endl; - - auto rv = true; - - auto setDefault = [&rv, this](const std::string& section, const std::string& key, const std::string& value) { - if (entryExists(section, key)) { - DesktopFileEntry entry; - - // this should never return false - auto entryExists = getEntry(section, key, entry); - assert(entryExists); - - ldLog() << LD_WARNING << "Key exists, not modified:" << key << "(current value:" << entry.value() << LD_NO_SPACE << ")" << std::endl; - rv = false; - } else { - auto entryOverwritten = setEntry(section, DesktopFileEntry(key, value)); - assert(!entryOverwritten); - } - }; - - setDefault("Desktop Entry", "Name", executableFileName); - setDefault("Desktop Entry", "Exec", executableFileName); - setDefault("Desktop Entry", "Icon", executableFileName); - setDefault("Desktop Entry", "Type", "Application"); - setDefault("Desktop Entry", "Categories", "Utility;"); - - return rv; - } - - bool DesktopFile::validate() const { - // FIXME: call desktop-file-validate - return true; - } - - bool operator==(const DesktopFile& first, const DesktopFile& second) { - return first.d->path == second.d->path && first.d->data == second.d->data; - } - - bool operator !=(const DesktopFile& first, const DesktopFile& second) { - return !operator==(first, second); - } - } - } -} - - - diff --git a/src/core/desktopfile/desktopfileentry.cpp b/src/core/desktopfile/desktopfileentry.cpp deleted file mode 100644 index 9e5fa00..0000000 --- a/src/core/desktopfile/desktopfileentry.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// library headers -#include - -// local headers -#include "linuxdeploy/core/log.h" -#include "linuxdeploy/core/desktopfile/desktopfileentry.h" - -using boost::lexical_cast; - -namespace linuxdeploy { - namespace core { - using namespace log; - - namespace desktopfile { - class DesktopFileEntry::PrivateData { - public: - std::string key; - std::string value; - - public: - void copyData(const std::shared_ptr& other) { - key = other->key; - value = other->value; - } - - void assertValueNotEmpty() { - if (value.empty()) - throw std::invalid_argument("value is empty"); - } - }; - - DesktopFileEntry::DesktopFileEntry() : d(new PrivateData) {} - - DesktopFileEntry::DesktopFileEntry(std::string key, std::string value) : DesktopFileEntry() { - d->key = std::move(key); - d->value = std::move(value); - } - - DesktopFileEntry::DesktopFileEntry(const DesktopFileEntry& other) : DesktopFileEntry() { - d->copyData(other.d); - } - - DesktopFileEntry& DesktopFileEntry::operator=(const DesktopFileEntry& other) { - if (this != &other) { - d.reset(new PrivateData); - d->copyData(other.d); - } - - return *this; - } - - DesktopFileEntry& DesktopFileEntry::operator=(DesktopFileEntry&& other) noexcept { - if (this != &other) { - d = other.d; - other.d = nullptr; - } - - return *this; - } - - bool DesktopFileEntry::operator==(const DesktopFileEntry& other) const { - return d->key == other.d->key && d->value == other.d->value; - } - - bool DesktopFileEntry::operator!=(const DesktopFileEntry& other) const { - return !operator==(other); - } - - bool DesktopFileEntry::isEmpty() const { - return d->key.empty(); - } - - const std::string& DesktopFileEntry::key() const { - return d->key; - } - - const std::string& DesktopFileEntry::value() const { - return d->value; - } - - int32_t DesktopFileEntry::asInt() const { - d->assertValueNotEmpty(); - - return lexical_cast(value()); - } - - int64_t DesktopFileEntry::asLong() const { - d->assertValueNotEmpty(); - - return lexical_cast(value()); - } - - double DesktopFileEntry::asDouble() const { - d->assertValueNotEmpty(); - - return lexical_cast(value()); - } - - std::vector DesktopFileEntry::parseStringList() const { - const auto& value = this->value(); - - if (value.empty()) - return {}; - - if (value.back() != ';') - ldLog() << LD_DEBUG << "desktop file string list does not end with semicolon:" << value - << std::endl; - - std::vector list; - - std::stringstream ss(value); - - std::string currentVal; - while (std::getline(ss, currentVal, ';')) { - // the last value will be empty, as in desktop files, lists shall end with a semicolon - // therefore we skip all empty values (assuming that empty values in lists in desktop files don't make sense anyway) - if (!currentVal.empty()) - list.emplace_back(currentVal); - } - - return list; - } - } - } -}; diff --git a/src/core/desktopfile/desktopfilereader.cpp b/src/core/desktopfile/desktopfilereader.cpp deleted file mode 100644 index c8bbc22..0000000 --- a/src/core/desktopfile/desktopfilereader.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// system includes -#include -#include -#include -#include - -// local headers -#include "linuxdeploy/util/util.h" -#include "linuxdeploy/core/desktopfile/desktopfileentry.h" -#include "linuxdeploy/core/desktopfile/exceptions.h" -#include "desktopfilereader.h" - -namespace bf = boost::filesystem; - -namespace linuxdeploy { - namespace core { - namespace desktopfile { - class DesktopFileReader::PrivateData { - public: - bf::path path; - DesktopFile::sections_t sections; - - public: - bool isEmpty() { - return sections.empty(); - } - - void assertPathIsNotEmptyAndFileExists() { - if (path.empty()) - throw IOError("empty path is not permitted"); - } - - void copyData(const std::shared_ptr& other) { - path = other->path; - sections = other->sections; - } - - void parse(std::istream& file) { - std::string line; - bool first = true; - - std::string currentSectionName; - - while (std::getline(file, line)) { - if (first) { - first = false; - // said to allow handling of UTF-16/32 documents, not entirely sure why - if (line[0] == static_cast(0xEF)) { - line.erase(0, 3); - return; - } - } - - if (!line.empty()) { - auto len = line.length(); - if (len > 0 && - !((len >= 2 && (line[0] == '/' && line[1] == '/')) || (len >= 1 && line[0] == '#'))) { - if (line[0] == '[') { - if (line.find_last_of('[') != 0) - throw ParseError("Multiple opening [ brackets"); - - // this line apparently introduces a new section - auto closingBracketPos = line.find(']'); - auto lastClosingBracketPos = line.find_last_of(']'); - - if (closingBracketPos == std::string::npos) - throw ParseError("No closing ] bracket in section header"); - else if (closingBracketPos != lastClosingBracketPos) - throw ParseError("Two or more closing ] brackets in section header"); - - size_t length = len - 2; - auto title = line.substr(1, closingBracketPos - 1); - - // set up the new section - sections.insert(std::make_pair(title, DesktopFile::section_t())); - currentSectionName = std::move(title); - } else { - // we require at least one section to be present in the desktop file - if (currentSectionName.empty()) - throw ParseError("No section in desktop file"); - - auto delimiterPos = line.find('='); - if (delimiterPos == std::string::npos) - throw ParseError("No = key/value delimiter found"); - - // this line should be a normal key-value pair - std::string key = line.substr(0, delimiterPos); - std::string value = line.substr(delimiterPos + 1, line.size()); - - // we can strip away any sort of leading or trailing whitespace safely - linuxdeploy::util::trim(key); - linuxdeploy::util::trim(value); - - // empty keys are not allowed for obvious reasons - if (key.empty()) - throw ParseError("Empty keys are not allowed"); - - // keys may only contain A-Za-z- characters according to specification - for (const char c : key) { - if (!( - (c >= 'A' && c <= 'Z') || - (c >= 'a' && c <= 'z') || - (c >= '0' && c <= '9') || - (c == '-') || - // FIXME: remove this hack after introducing localization support to - // conform to desktop file spec again - (c == '[') || (c == ']') - ) - ) { - throw ParseError( - "Key " + key + " contains invalid character " + std::string{c} - ); - } - } - - if (std::count(key.begin(), key.end(), '[') > 1 || - std::count(key.begin(), key.end(), ']') > 1 || - // make sure that both [ and ] are present - (key.find('[') != std::string::npos && key.find(']') == std::string::npos) || - (key.find('[') == std::string::npos && key.find(']') != std::string::npos) || - // disallow empty locale names - (key.find('[') != std::string::npos && key.find(']') != std::string::npos && (key.find(']') - key.find('[')) < 2) || - // ensure order of [ and ] - (key.find('[') != std::string::npos && key.find('[' ) > key.find(']')) - ) { - throw ParseError("Invalid localization syntax used in key " + key); - } - - auto& section = sections[currentSectionName]; - - // keys must be unique in the same section - if (section.find(key) != section.end()) - throw ParseError("Key " + key + " found more than once"); - - section[key] = DesktopFileEntry(key, value); - } - } - } - } - } - }; - - DesktopFileReader::DesktopFileReader() : d(new PrivateData) {} - - DesktopFileReader::DesktopFileReader(boost::filesystem::path path) : DesktopFileReader() { - d->path = std::move(path); - d->assertPathIsNotEmptyAndFileExists(); - - std::ifstream ifs(d->path.string()); - if (!ifs) - throw IOError("could not open file: " + d->path.string()); - - d->parse(ifs); - } - - DesktopFileReader::DesktopFileReader(std::istream& is) : DesktopFileReader() { - d->parse(is); - } - - DesktopFileReader::DesktopFileReader(const DesktopFileReader& other) : DesktopFileReader() { - d->copyData(other.d); - } - - DesktopFileReader& DesktopFileReader::operator=(const DesktopFileReader& other) { - if (this != &other) { - // set up a new instance of PrivateData, and copy data over from other object - d.reset(new PrivateData); - d->copyData(other.d); - } - - return *this; - } - - DesktopFileReader& DesktopFileReader::operator=(DesktopFileReader&& other) noexcept { - if (this != &other) { - // move other object's data into this one, and remove reference there - d = other.d; - other.d = nullptr; - } - - return *this; - } - - bool DesktopFileReader::isEmpty() const { - return d->isEmpty(); - } - - bool DesktopFileReader::operator==(const DesktopFileReader& other) const { - return d->path == other.d->path && d->sections == other.d->sections; - } - - bool DesktopFileReader::operator!=(const DesktopFileReader& other) const { - return !operator==(other); - } - - boost::filesystem::path DesktopFileReader::path() const { - return d->path; - } - - DesktopFile::sections_t DesktopFileReader::data() const { - return d->sections; - } - - DesktopFile::section_t DesktopFileReader::operator[](const std::string& name) const { - auto it = d->sections.find(name); - - // the map would lazy-initialize a new entry in case the section doesn't exist - // therefore explicitly checking whether the section exists, throwing an exception in case it does not - if (it == d->sections.end()) - throw UnknownSectionError(name); - - return it->second; - } - } - } -} diff --git a/src/core/desktopfile/desktopfilereader.h b/src/core/desktopfile/desktopfilereader.h deleted file mode 100644 index a8dff3f..0000000 --- a/src/core/desktopfile/desktopfilereader.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -// system includes -#include -#include - -// library includes -#include - -// local includes -#include "linuxdeploy/core/desktopfile/desktopfile.h" -#include "linuxdeploy/core/desktopfile/desktopfileentry.h" - -namespace linuxdeploy { - namespace core { - namespace desktopfile { - class DesktopFileReader { - private: - // opaque data class pattern - class PrivateData; - - std::shared_ptr d; - - public: - // default constructor - DesktopFileReader(); - - // construct from path - explicit DesktopFileReader(boost::filesystem::path path); - - // construct from existing istream - explicit DesktopFileReader(std::istream& is); - - // copy constructor - DesktopFileReader(const DesktopFileReader& other); - - // copy assignment constructor - DesktopFileReader& operator=(const DesktopFileReader& other); - - // move assignment operator - DesktopFileReader& operator=(DesktopFileReader&& other) noexcept; - - // equality operator - bool operator==(const DesktopFileReader& other) const; - - // inequality operator - bool operator!=(const DesktopFileReader& other) const; - - public: - // checks whether parsed data is available - bool isEmpty() const; - - // returns desktop file path - boost::filesystem::path path() const; - - // get a specific section from the parsed data - // throws std::range_error if section does not exist - DesktopFile::section_t operator[](const std::string& name) const; - - // get copy of internal data storage - // can be handed to a DesktopFileWriter instance, or to manually hack on the data - DesktopFile::sections_t data() const; - }; - } - } -} diff --git a/src/core/desktopfile/desktopfilewriter.cpp b/src/core/desktopfile/desktopfilewriter.cpp deleted file mode 100644 index ee061f7..0000000 --- a/src/core/desktopfile/desktopfilewriter.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// system includes -#include -#include - -// local headers -#include "linuxdeploy/util/util.h" -#include "linuxdeploy/core/desktopfile/exceptions.h" -#include "desktopfilewriter.h" - -namespace bf = boost::filesystem; - -namespace linuxdeploy { - namespace core { - namespace desktopfile { - class DesktopFileWriter::PrivateData { - public: - DesktopFile::sections_t data; - - public: - void copyData(const std::shared_ptr& other) { - data = other->data; - } - - std::string dumpString() { - std::stringstream ss; - - for (const auto& section : data) { - ss << "[" << section.first << "]" << std::endl; - - for (const auto& pair : section.second) { - auto key = pair.first; - util::trim(key); - auto value = pair.second.value(); - util::trim(value); - ss << key << "=" << value << std::endl; - } - - // insert an empty line between sections - ss << std::endl; - } - - return ss.str(); - } - }; - - DesktopFileWriter::DesktopFileWriter() : d(std::make_shared()) {} - - DesktopFileWriter::DesktopFileWriter(DesktopFile::sections_t data) : DesktopFileWriter() { - d->data = std::move(data); - } - - DesktopFileWriter::DesktopFileWriter(const DesktopFileWriter& other) : DesktopFileWriter() { - d->copyData(other.d); - } - - DesktopFileWriter& DesktopFileWriter::operator=(const DesktopFileWriter& other) { - if (this != &other) { - // set up a new instance of PrivateData, and copy data over from other object - d.reset(new PrivateData); - d->copyData(other.d); - } - - return *this; - } - - DesktopFileWriter& DesktopFileWriter::operator=(DesktopFileWriter&& other) noexcept { - if (this != &other) { - // move other object's data into this one, and remove reference there - d = other.d; - other.d = nullptr; - } - - return *this; - } - - bool DesktopFileWriter::operator==(const DesktopFileWriter& other) const { - return d->data == other.d->data; - } - - bool DesktopFileWriter::operator!=(const DesktopFileWriter& other) const { - return !operator==(other); - } - - DesktopFile::sections_t DesktopFileWriter::data() const { - return d->data; - } - - void DesktopFileWriter::save(const boost::filesystem::path& path) { - std::ofstream ofs(path.string()); - - if (!ofs) - throw IOError("could not open file for writing: " + path.string()); - - save(ofs); - } - - void DesktopFileWriter::save(std::ostream& os) { - os << d->dumpString(); - } - } - } -} diff --git a/src/core/desktopfile/desktopfilewriter.h b/src/core/desktopfile/desktopfilewriter.h deleted file mode 100644 index 6a84f84..0000000 --- a/src/core/desktopfile/desktopfilewriter.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -// system includes -#include -#include - -// library includes -#include - -// local includes -#include "linuxdeploy/core/desktopfile/desktopfile.h" -#include "linuxdeploy/core/desktopfile/desktopfileentry.h" - -namespace linuxdeploy { - namespace core { - namespace desktopfile { - class DesktopFileWriter { - private: - // opaque data class pattern - class PrivateData; - std::shared_ptr d; - - public: - // default constructor - DesktopFileWriter(); - - // construct from data - explicit DesktopFileWriter(DesktopFile::sections_t data); - - // copy constructor - DesktopFileWriter(const DesktopFileWriter& other); - - // copy assignment constructor - DesktopFileWriter& operator=(const DesktopFileWriter& other); - - // move assignment operator - DesktopFileWriter& operator=(DesktopFileWriter&& other) noexcept; - - // equality operator - bool operator==(const DesktopFileWriter& other) const; - - // inequality operator - bool operator!=(const DesktopFileWriter& other) const; - - public: - // returns desktop file path - DesktopFile::sections_t data() const; - - public: - // save to given path - void save(const boost::filesystem::path& path); - - // save to given ostream - void save(std::ostream& os); - }; - } - } -} diff --git a/src/main.cpp b/src/main.cpp index 5437065..aae8de4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,13 +7,14 @@ // local headers #include "linuxdeploy/core/appdir.h" -#include "linuxdeploy/core/desktopfile/desktopfile.h" +#include "linuxdeploy/desktopfile/desktopfile.h" #include "linuxdeploy/core/elf.h" #include "linuxdeploy/core/log.h" #include "linuxdeploy/plugin/plugin.h" #include "linuxdeploy/util/util.h" #include "core.h" +using namespace linuxdeploy; using namespace linuxdeploy::core; using namespace linuxdeploy::core::log; using namespace linuxdeploy::util; @@ -249,7 +250,7 @@ int main(int argc, char** argv) { ldLog() << LD_WARNING << "Tried to overwrite existing entries in desktop file:" << desktopFilePath << std::endl; } - if (!desktopFile.save(desktopFilePath)) { + if (!desktopFile.save(desktopFilePath.string())) { ldLog() << LD_ERROR << "Failed to save desktop file:" << desktopFilePath << std::endl; return 1; } diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index 0946844..dcef6fc 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -37,7 +37,3 @@ add_test(test_linuxdeploy test_linuxdeploy) # make sure library and executable are built before test_appdir add_dependencies(test_linuxdeploy simple_library simple_executable) - - -# include desktop file tests -add_subdirectory(desktopfile) diff --git a/tests/core/desktopfile/CMakeLists.txt b/tests/core/desktopfile/CMakeLists.txt deleted file mode 100644 index 1585ddc..0000000 --- a/tests/core/desktopfile/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -# build a single test binary -add_executable(test_desktopfile - test_desktopfile.cpp - test_desktopfileentry.cpp - test_desktopfilereader.cpp - test_desktopfilewriter.cpp - test_desktopfile_conformance.cpp - main.cpp -) - -target_link_libraries(test_desktopfile PRIVATE linuxdeploy_core_desktopfile gtest) - -set_property(TARGET test_desktopfile - PROPERTY COMPILE_FLAGS "-DDESKTOP_FILE_PATH=\\\"${TEST_DATA_DIR}/simple_app.desktop\\\"" -) - -add_test(test_desktopfile test_desktopfile) diff --git a/tests/core/desktopfile/main.cpp b/tests/core/desktopfile/main.cpp deleted file mode 100644 index bfd59c0..0000000 --- a/tests/core/desktopfile/main.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// library headers -#include - -// local headers -#include - -using namespace linuxdeploy::core::log; - -int main(int argc, char** argv) { - // set loglevel to prevent unnecessary log messages - ldLog::setVerbosity(LD_ERROR); - - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/tests/core/desktopfile/test_desktopfile.cpp b/tests/core/desktopfile/test_desktopfile.cpp deleted file mode 100644 index 7a77357..0000000 --- a/tests/core/desktopfile/test_desktopfile.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// library headers -#include -#include - -// local headers -#include "linuxdeploy/core/desktopfile/desktopfile.h" -#include "linuxdeploy/core/desktopfile/exceptions.h" -#include "../../src/core/desktopfile/desktopfilereader.h" - -using boost::bad_lexical_cast; -using namespace linuxdeploy::core::desktopfile; - -namespace bf = boost::filesystem; - -class DesktopFileTest : public ::testing::Test { -public: - std::string testType; - std::string testName; - std::string testExec; - std::string testIcon; - std::string testDesktopFile; - -private: - void SetUp() override { - testType = "Application"; - testName = "Simple Application"; - testExec = "simple_app"; - testIcon = "simple_app"; - - std::stringstream ss; - ss << "[Desktop Entry]" << std::endl - << "Type=Application" << std::endl - << "Name=Simple Application" << std::endl - << "Exec=" << testExec << std::endl - << "Icon=" << testIcon << std::endl; - - testDesktopFile = ss.str(); - } - - void TearDown() override {} - -public: - void assertIsTestDesktopFile(const DesktopFile& file, ssize_t expectedKeys = -1) { - std::stringstream ss; - file.save(ss); - - assertHasTestDesktopFileKeys(ss, expectedKeys); - } - - void assertHasTestDesktopFileKeys(std::stringstream& ss, ssize_t expectedKeys = -1) const { - DesktopFileReader reader(ss); - - if (expectedKeys < 0) - expectedKeys = 4; - - EXPECT_EQ(reader["Desktop Entry"]["Name"].value(), testName); - EXPECT_EQ(reader["Desktop Entry"]["Exec"].value(), testExec); - EXPECT_EQ(reader["Desktop Entry"]["Icon"].value(), testIcon); - EXPECT_EQ(reader["Desktop Entry"]["Type"].value(), testType); - EXPECT_EQ(reader["Desktop Entry"].size(), expectedKeys); - } -}; - -TEST_F(DesktopFileTest, testDefaultConstructor) { - DesktopFile file; - EXPECT_TRUE(file.isEmpty()); -} - -TEST_F(DesktopFileTest, testPathConstructor) { - ASSERT_THROW(DesktopFile nonExistingPath("/a/b/c/d/e/f/g/h/1/2/3/4/5/6/7/8"), IOError); - - DesktopFile emptyFile("/dev/null"); - EXPECT_TRUE(emptyFile.isEmpty()); - - DesktopFile file(DESKTOP_FILE_PATH); - EXPECT_FALSE(file.isEmpty()); -} - -TEST_F(DesktopFileTest, testStreamConstructor) { - std::stringstream emptyString; - DesktopFile emptyFile(emptyString); - EXPECT_TRUE(emptyFile.isEmpty()); - - std::stringstream ss; - ss << testDesktopFile; - DesktopFile file(ss); - EXPECT_FALSE(file.isEmpty()); - - assertIsTestDesktopFile(file); -} - -TEST_F(DesktopFileTest, testCopyConstructor) { - DesktopFile empty; - EXPECT_TRUE(empty == empty); - EXPECT_FALSE(empty != empty); - - DesktopFile copyOfEmpty(empty); - EXPECT_TRUE(empty == copyOfEmpty); - EXPECT_FALSE(empty != copyOfEmpty); - - std::stringstream ss; - ss << testDesktopFile; - DesktopFile file(ss); - - DesktopFile copy(file); - - EXPECT_TRUE(file == copy); - EXPECT_FALSE(file != copy); - - assertIsTestDesktopFile(file); - assertIsTestDesktopFile(copy); -} - -TEST_F(DesktopFileTest, testCopyAssignmentConstructor) { - std::stringstream ss; - ss << testDesktopFile; - DesktopFile file(ss); - - DesktopFile copy; - copy = file; - - EXPECT_TRUE(file == copy); - EXPECT_FALSE(file != copy); - - assertIsTestDesktopFile(file); - assertIsTestDesktopFile(copy); -} - -TEST_F(DesktopFileTest, testMoveAssignmentConstructor) { - std::stringstream ss; - ss << testDesktopFile; - DesktopFile file(ss); - - DesktopFile copy; - copy = std::move(file); - EXPECT_FALSE(copy.isEmpty()); - - assertIsTestDesktopFile(copy); -} - -void assertDefaultKeysExistInDesktopFile(const DesktopFile& file) { - DesktopFileEntry entry; - - for (const auto& key : {"Name", "Exec", "Icon", "Type"}) - EXPECT_TRUE(file.getEntry("Desktop Entry", key, entry)) << "Could not find key in desktop file: " << key; -} - -TEST_F(DesktopFileTest, testAddDefaultValues) { - const auto& value = "testExecutable"; - - DesktopFile file; - file.addDefaultKeys(value); - - // make sure keys exist in desktop files - assertDefaultKeysExistInDesktopFile(file); - - std::stringstream ss; - - file.save(ss); - - DesktopFileReader reader(ss); - - EXPECT_EQ(reader["Desktop Entry"]["Name"].value(), value); - EXPECT_EQ(reader["Desktop Entry"]["Exec"].value(), value); - EXPECT_EQ(reader["Desktop Entry"]["Icon"].value(), value); - EXPECT_EQ(reader["Desktop Entry"]["Type"].value(), "Application"); - EXPECT_EQ(reader["Desktop Entry"]["Categories"].value(), "Utility;"); -} - -TEST_F(DesktopFileTest, testAddDefaultValuesExistingKeys) { - const auto& value = "testExecutable"; - - std::stringstream iss; - iss << "[Desktop Entry]" << std::endl - << "Name=A Different Name" << std::endl - << "Exec=a_different_exec" << std::endl; - - DesktopFile file(iss); - file.addDefaultKeys(value); - - // make sure keys exist in desktop files - assertDefaultKeysExistInDesktopFile(file); - - file.save(std::cout); - - std::stringstream ss; - - file.save(ss); - - DesktopFileReader reader(ss); - - EXPECT_EQ(reader["Desktop Entry"]["Name"].value(), "A Different Name"); - EXPECT_EQ(reader["Desktop Entry"]["Exec"].value(), "a_different_exec"); - EXPECT_EQ(reader["Desktop Entry"]["Icon"].value(), value); - EXPECT_EQ(reader["Desktop Entry"]["Categories"].value(), "Utility;"); -} - -TEST_F(DesktopFileTest, testAddDefaultValuesNoOverwrite) { - const auto& value = "testExecutable"; - - std::stringstream iss; - iss << testDesktopFile; - DesktopFile file(iss); - - file.addDefaultKeys(value); - - // make sure keys exist in desktop files - assertDefaultKeysExistInDesktopFile(file); - - { - std::stringstream oss; - file.save(oss); - - // keys should not have been overwritten, and should still have the original values - // however, there should be 5 keys, as the Categories one is coming from the testDesktopFile string - assertHasTestDesktopFileKeys(oss, 5); - } - - { - std::stringstream oss; - file.save(oss); - - DesktopFileReader reader(oss); - EXPECT_EQ(reader["Desktop Entry"]["Categories"].parseStringList(), std::vector({"Utility"})); - } -} - -TEST_F(DesktopFileTest, testSaveToPath) { - std::stringstream ins; - ins << testDesktopFile; - - DesktopFile file(ins); - - EXPECT_NO_THROW(file.save("/dev/null")); -} - -TEST_F(DesktopFileTest, testSave) { - DesktopFile file("/dev/null"); - EXPECT_NO_THROW(file.save()); -} - -TEST_F(DesktopFileTest, testSaveToStream) { - std::stringstream ins; - ins << testDesktopFile; - - DesktopFile file(ins); - - std::stringstream outs; - file.save(outs); - - assertHasTestDesktopFileKeys(outs); -} - -TEST_F(DesktopFileTest, testEquality) { - std::stringstream ins0(testDesktopFile); - std::stringstream ins1(testDesktopFile); - - DesktopFile file0(ins0); - DesktopFile file1(ins1); - - EXPECT_TRUE(file0 == file1); - EXPECT_FALSE(file0 != file1); - - EXPECT_EQ(file0, file1); -} - -TEST_F(DesktopFileTest, testInequality) { - std::stringstream ins; - ins << testDesktopFile; - - DesktopFile file(ins); - - DesktopFile emptyFile; - - EXPECT_TRUE(file != emptyFile); - EXPECT_FALSE(file == emptyFile); - - EXPECT_NE(file, emptyFile); -} diff --git a/tests/core/desktopfile/test_desktopfile_conformance.cpp b/tests/core/desktopfile/test_desktopfile_conformance.cpp deleted file mode 100644 index fbd9ffa..0000000 --- a/tests/core/desktopfile/test_desktopfile_conformance.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// library headers -#include -#include - -// local headers -#include "linuxdeploy/core/desktopfile/desktopfile.h" -#include "linuxdeploy/core/desktopfile/exceptions.h" - -using boost::bad_lexical_cast; -using namespace linuxdeploy::core::desktopfile; - -namespace bf = boost::filesystem; - -class DesktopFileConformanceTest : public ::testing::Test { -private: - void SetUp() override {} - void TearDown() override {} -}; - -TEST_F(DesktopFileConformanceTest, testBasicFormatInvalidKeyCharacters) { - // test conformance with a couple of invalid values - { - std::stringstream ss; - ss << "[Desktop Entry]" << std::endl - << "no spaces in key=foo" << std::endl; - - EXPECT_THROW(DesktopFile file(ss), ParseError); - } - - { - std::stringstream ss; - ss << "[Desktop Entry]" << std::endl - << "UmlautTestÄöÜ=foo" << std::endl; - - EXPECT_THROW(DesktopFile file(ss), ParseError); - } - - { - std::stringstream ss; - ss << "[Desktop Entry]" << std::endl - << "NoUnderscores_=foo" << std::endl; - - EXPECT_THROW(DesktopFile file(ss), ParseError); - } -} - -TEST_F(DesktopFileConformanceTest, testBasicFormatValidKeyCharacters) { - { - std::stringstream ss; - ss << "[Desktop Entry]" << std::endl - << "TestKey=foo" << std::endl; - - EXPECT_NO_THROW(DesktopFile file(ss)); - } - - { - std::stringstream ss; - ss << "[Desktop Entry]" << std::endl - << "4242trolol0=foo" << std::endl; - - EXPECT_NO_THROW(DesktopFile file(ss)); - } - - { - std::stringstream ss; - ss << "[Desktop Entry]" << std::endl - << "----=foo" << std::endl; - - EXPECT_NO_THROW(DesktopFile file(ss)); - } - - { - std::stringstream ss; - ss << "[Desktop Entry]" << std::endl - << "allLowerCase=foo" << std::endl; - - EXPECT_NO_THROW(DesktopFile file(ss)); - } -} - -TEST_F(DesktopFileConformanceTest, testBasicFormatCheckKeysUnique) { - { - std::stringstream ss; - ss << "[Desktop Entry]" << std::endl - << "foo=bar" << std::endl - << "foo=baz" << std::endl; - - EXPECT_THROW(DesktopFile file(ss), ParseError); - } -} diff --git a/tests/core/desktopfile/test_desktopfileentry.cpp b/tests/core/desktopfile/test_desktopfileentry.cpp deleted file mode 100644 index b603f51..0000000 --- a/tests/core/desktopfile/test_desktopfileentry.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// library headers -#include -#include -#include - -// local headers -#include "linuxdeploy/core/desktopfile/desktopfileentry.h" - -using boost::bad_lexical_cast; -using namespace linuxdeploy::core::desktopfile; - -namespace bf = boost::filesystem; - -class DesktopFileEntryTest : public ::testing::Test { -public: - const std::string key; - const std::string value; - -protected: - DesktopFileEntryTest() : key("testKey"), value("testValue") {} - -private: - void SetUp() override {} - - void TearDown() override {} -}; - -TEST_F(DesktopFileEntryTest, testDefaultConstructor) { - DesktopFileEntry entry; - EXPECT_TRUE(entry.isEmpty()); -} - -TEST_F(DesktopFileEntryTest, testKeyValueConstructor) { - DesktopFileEntry entry(key, value); - EXPECT_FALSE(entry.isEmpty()); - EXPECT_EQ(entry.key(), key); - EXPECT_EQ(entry.value(), value); -} - -TEST_F(DesktopFileEntryTest, testGetters) { - DesktopFileEntry entry(key, value); - EXPECT_EQ(entry.key(), key); - EXPECT_EQ(entry.value(), value); -} - -TEST_F(DesktopFileEntryTest, testEqualityAndInequalityOperators) { - DesktopFileEntry emptyEntry; - EXPECT_TRUE(emptyEntry == emptyEntry); - EXPECT_FALSE(emptyEntry != emptyEntry); - - DesktopFileEntry nonEmptyEntry(key, value); - EXPECT_NE(emptyEntry, nonEmptyEntry); - - DesktopFileEntry nonEmptyEntryWithDifferentValue(key, value + "abc"); - EXPECT_NE(nonEmptyEntry, nonEmptyEntryWithDifferentValue); -} - -TEST_F(DesktopFileEntryTest, testCopyConstructor) { - DesktopFileEntry entry(key, value); - EXPECT_FALSE(entry.isEmpty()); - - DesktopFileEntry copy = entry; - EXPECT_FALSE(copy.isEmpty()); - - EXPECT_EQ(entry, copy); -} - -TEST_F(DesktopFileEntryTest, testCopyAssignmentConstructor) { - DesktopFileEntry entry; - EXPECT_TRUE(entry.isEmpty()); - - DesktopFileEntry otherEntry(key, value); - EXPECT_FALSE(otherEntry.isEmpty()); - - entry = otherEntry; - EXPECT_EQ(entry.key(), key); - EXPECT_EQ(entry.value(), value); - - // test self-assignment - entry = entry; -} - -TEST_F(DesktopFileEntryTest, testMoveAssignmentConstructor) { - DesktopFileEntry entry; - EXPECT_TRUE(entry.isEmpty()); - - DesktopFileEntry otherEntry(key, value); - EXPECT_FALSE(otherEntry.isEmpty()); - - entry = std::move(otherEntry); - EXPECT_EQ(entry.key(), key); - EXPECT_EQ(entry.value(), value); - - // test self-assignment - entry = std::move(entry); -} - -TEST_F(DesktopFileEntryTest, testConversionToInt) { - DesktopFileEntry intEntry(key, "1234"); - EXPECT_EQ(intEntry.asInt(), 1234); - - DesktopFileEntry brokenValueEntry(key, "abcd"); - ASSERT_THROW(brokenValueEntry.asInt(), bad_lexical_cast); - - DesktopFileEntry emptyEntry(key, ""); - ASSERT_THROW(emptyEntry.asInt(), std::invalid_argument); -} - -TEST_F(DesktopFileEntryTest, testConversionToLong) { - DesktopFileEntry intEntry(key, "123456789123456789"); - EXPECT_EQ(intEntry.asLong(), 123456789123456789L); - - DesktopFileEntry brokenValueEntry(key, "abcd"); - ASSERT_THROW(brokenValueEntry.asLong(), bad_lexical_cast); - - DesktopFileEntry emptyEntry(key, ""); - ASSERT_THROW(emptyEntry.asLong(), std::invalid_argument); -} - -TEST_F(DesktopFileEntryTest, testConversionToDouble) { - DesktopFileEntry doubleEntry(key, "1.234567"); - EXPECT_NEAR(doubleEntry.asDouble(), 1.234567, 0.00000001); - - DesktopFileEntry brokenValueEntry(key, "abcd"); - ASSERT_THROW(brokenValueEntry.asDouble(), bad_lexical_cast); - - DesktopFileEntry emptyEntry(key, ""); - ASSERT_THROW(emptyEntry.asDouble(), std::invalid_argument); -} - -TEST_F(DesktopFileEntryTest, testParsingStringList) { - DesktopFileEntry emptyEntry(key, ""); - EXPECT_EQ(emptyEntry.parseStringList(), std::vector({})); - - DesktopFileEntry nonListEntry(key, value); - EXPECT_EQ(nonListEntry.parseStringList(), std::vector({value})); - - DesktopFileEntry listEntry(key, "val1;val2;"); - EXPECT_EQ(listEntry.parseStringList(), std::vector({"val1", "val2"})); - - DesktopFileEntry listEntryWithoutTrailingSemicolon(key, "val1;val2"); - EXPECT_EQ(listEntry.parseStringList(), std::vector({"val1", "val2"})); - - DesktopFileEntry listEntryWithEmptyItems(key, "val1;;;val2;;"); - EXPECT_EQ(listEntry.parseStringList(), std::vector({"val1", "val2"})); -} diff --git a/tests/core/desktopfile/test_desktopfilereader.cpp b/tests/core/desktopfile/test_desktopfilereader.cpp deleted file mode 100644 index e892e66..0000000 --- a/tests/core/desktopfile/test_desktopfilereader.cpp +++ /dev/null @@ -1,468 +0,0 @@ -// library headers -#include -#include - -// local headers -#include "../../src/core/desktopfile/desktopfilereader.h" -#include "linuxdeploy/core/desktopfile/exceptions.h" - -using namespace linuxdeploy::core::desktopfile; -namespace bf = boost::filesystem; - -class DesktopFileReaderTest : public ::testing::Test { - void SetUp() override {} - void TearDown() override {} -}; - -TEST_F(DesktopFileReaderTest, testDefaultConstructor) { - DesktopFileReader reader; - EXPECT_TRUE(reader.isEmpty()); -} - -TEST_F(DesktopFileReaderTest, testPathConstructor) { - bf::path path = "/dev/null"; - - DesktopFileReader reader(path); - EXPECT_TRUE(reader.isEmpty()); - - ASSERT_THROW(DesktopFileReader("/no/such/file/or/directory"), IOError); -} - -TEST_F(DesktopFileReaderTest, testStreamConstructor) { - std::stringstream ss; - DesktopFileReader reader(ss); - - EXPECT_TRUE(reader.isEmpty()); -} - -TEST_F(DesktopFileReaderTest, testPathConstructorWithEmptyPath) { - ASSERT_THROW(DesktopFileReader(""), IOError); -} - -TEST_F(DesktopFileReaderTest, testPathConstructorWithNonExistingPath) { - ASSERT_THROW(DesktopFileReader("/no/such/path/42"), IOError); -} - -TEST_F(DesktopFileReaderTest, testEqualityAndInequalityOperators) { - { - DesktopFileReader emptyReader; - EXPECT_TRUE(emptyReader == emptyReader); - EXPECT_FALSE(emptyReader != emptyReader); - } - - { - // make sure that files with different paths are recognized as different - DesktopFile nullFile("/dev/null"); - DesktopFile fileWithoutPath; - - EXPECT_TRUE(nullFile != fileWithoutPath); - EXPECT_FALSE(nullFile == fileWithoutPath); - } - - { - // make sure that files with different contents are recognized as different - DesktopFile fileWithContents; - fileWithContents.setEntry("Desktop Entry", DesktopFileEntry("test", "test")); - - DesktopFile emptyFile; - - EXPECT_TRUE(emptyFile != fileWithContents); - EXPECT_FALSE(emptyFile == fileWithContents); - } -} - -TEST_F(DesktopFileReaderTest, testCopyConstructor) { - { - bf::path path = "/dev/null"; - - DesktopFileReader reader(path); - EXPECT_TRUE(reader.isEmpty()); - - DesktopFileReader copy = reader; - EXPECT_TRUE(copy.isEmpty()); - - EXPECT_EQ(reader, copy); - } - - { - // make sure that contents are copied, too - DesktopFile file; - file.setEntry("Desktop Entry", DesktopFileEntry("test", "test")); - - std::stringstream ss; - file.save(ss); - - DesktopFileReader reader(ss); - DesktopFileReader copy(reader); - - EXPECT_TRUE(reader.data() == copy.data()); - EXPECT_TRUE(reader == copy); - } -} - -TEST_F(DesktopFileReaderTest, testCopyAssignmentConstructor) { - bf::path path = "/dev/null"; - - DesktopFileReader reader; - EXPECT_TRUE(reader.isEmpty()); - - DesktopFileReader otherReader(path); - EXPECT_TRUE(otherReader.isEmpty()); - - reader = otherReader; - EXPECT_EQ(reader.path(), path); - - // test self-assignment - reader = reader; -} - -TEST_F(DesktopFileReaderTest, testMoveAssignmentConstructor) { - bf::path path = "/dev/null"; - - DesktopFileReader reader; - EXPECT_TRUE(reader.isEmpty()); - - DesktopFileReader otherReader(path); - EXPECT_TRUE(otherReader.isEmpty()); - - reader = std::move(otherReader); - EXPECT_EQ(reader.path(), path); - - // test self-assignment - reader = std::move(reader); -} - -TEST_F(DesktopFileReaderTest, testParseSimpleDesktopFile) { - std::stringstream ss; - ss << "[Desktop File]" << std::endl - << "Version=1.0" << std::endl - << "Name=name" << std::endl - << "Exec=exec" << std::endl - << "Icon=icon" << std::endl - << "Type=Application" << std::endl - << "Categories=Utility;Multimedia;" << std::endl; - - DesktopFileReader reader; - reader = DesktopFileReader(ss); - - auto section = reader["Desktop File"]; - EXPECT_FALSE(section.empty()); - EXPECT_EQ(section.size(), 6); - - EXPECT_NEAR(section["Version"].asDouble(), 1.0, 0.000001); - EXPECT_EQ(section["Name"].value(), "name"); - EXPECT_EQ(section["Exec"].value(), "exec"); - EXPECT_EQ(section["Icon"].value(), "icon"); - EXPECT_EQ(section["Type"].value(), "Application"); - EXPECT_EQ(section["Name"].value(), "name"); - EXPECT_EQ(section["Categories"].parseStringList(), std::vector({"Utility", "Multimedia"})); -} - -TEST_F(DesktopFileReaderTest, testParseSimpleDesktopFileWithComments) { - std::stringstream ss; - ss << "[Desktop File]" << std::endl - << "Version=1.0" << std::endl - << "Name=name" << std::endl - << "# a comment" << std::endl - << "Exec=exec" << std::endl - << "Icon=icon" << std::endl - << "Type=Application" << std::endl - << "# another comment" << std::endl - << "Categories=Utility;Multimedia;" << std::endl; - - DesktopFileReader reader; - reader = DesktopFileReader(ss); - - auto section = reader["Desktop File"]; - EXPECT_FALSE(section.empty()); - EXPECT_EQ(section.size(), 6); - - // TODO: check for comments in data - // right now, they're just discarded, but they shall be preserved in the right positions in the future - - EXPECT_NEAR(section["Version"].asDouble(), 1.0f, 0.000001); - EXPECT_EQ(section["Name"].value(), "name"); - EXPECT_EQ(section["Exec"].value(), "exec"); - EXPECT_EQ(section["Icon"].value(), "icon"); - EXPECT_EQ(section["Type"].value(), "Application"); - EXPECT_EQ(section["Name"].value(), "name"); - EXPECT_EQ(section["Categories"].parseStringList(), std::vector({"Utility", "Multimedia"})); -} - -TEST_F(DesktopFileReaderTest, testParseFileGetNonExistingSection) { - std::stringstream ss; - ss << "[Desktop File]" << std::endl; - - DesktopFileReader reader; - reader = DesktopFileReader(ss); - - ASSERT_THROW(reader["Non-existing Section"], UnknownSectionError); -} - -TEST_F(DesktopFileReaderTest, testParseFileMissingSectionHeader) { - std::stringstream ss; - ss << "Name=name" << std::endl - << "Exec=exec" << std::endl - << "Icon=icon" << std::endl - << "Type=Application" << std::endl - << "Categories=Utility;Multimedia;" << std::endl; - - DesktopFileReader reader; - ASSERT_THROW(reader = DesktopFileReader(ss), ParseError); -} - -TEST_F(DesktopFileReaderTest, testParseFileEmptyKey) { - std::stringstream ss; - ss << "[Desktop File]" << std::endl - << "=name" << std::endl - << "Exec=exec" << std::endl - << "Icon=icon" << std::endl - << "Type=Application" << std::endl - << "Categories=Utility;Multimedia;" << std::endl; - - DesktopFileReader reader; - ASSERT_THROW(reader = DesktopFileReader(ss), ParseError); -} - -TEST_F(DesktopFileReaderTest, testParseFileMissingDelimiterInLine) { - { - std::stringstream ss; - ss << "[Desktop File]" << std::endl - << "Exec" << std::endl; - - DesktopFileReader reader; - ASSERT_THROW(reader = DesktopFileReader(ss), ParseError); - } - - { - std::stringstream ss; - ss << "[Desktop File]" << std::endl - << "Name name" << std::endl; - - DesktopFileReader reader; - ASSERT_THROW(reader = DesktopFileReader(ss), ParseError); - } -} - -TEST_F(DesktopFileReaderTest, testParseFile) { - std::stringstream ss; - ss << "[Desktop File]" << std::endl - << "Name name" << std::endl - << "Exec" << std::endl; - - DesktopFileReader reader; - ASSERT_THROW(reader = DesktopFileReader(ss), ParseError); -} - -TEST_F(DesktopFileReaderTest, testParseFileMultipleDelimitersInLine) { - // TODO: verify that ==Name would be a legal value according to desktop file specification - std::stringstream ss; - ss << "[Desktop File]" << std::endl - << "Name===name" << std::endl; - - DesktopFileReader reader; - ASSERT_NO_THROW(reader = DesktopFileReader(ss)); -} - -TEST_F(DesktopFileReaderTest, testParseFileWithLeadingAndTrailingWhitespaceInLines) { - std::stringstream ss; - ss << "[Desktop File]" << std::endl - << "Name= name" << std::endl - << "Exec =exec" << std::endl; - - DesktopFileReader reader(ss); - - auto section = reader["Desktop File"]; - EXPECT_FALSE(section.empty()); - - EXPECT_EQ(section["Name"].value(), "name"); - EXPECT_EQ(section["Exec"].value(), "exec"); -} - -TEST_F(DesktopFileReaderTest, testDataGetter) { - std::stringstream ss; - ss << "[Desktop File]" << std::endl - << "Name= name" << std::endl - << "Exec =exec" << std::endl; - - DesktopFileReader reader(ss); - - auto section = reader["Desktop File"]; - EXPECT_FALSE(section.empty()); - - auto data = reader.data(); - - auto expected = DesktopFile::section_t({ - {"Name", DesktopFileEntry("Name", "name")}, - {"Exec", DesktopFileEntry("Exec", "exec")}, - }); - - EXPECT_EQ(data["Desktop File"], expected); -} - -TEST_F(DesktopFileReaderTest, testParseLinesWithMultipleSpaces) { - std::stringstream ss; - ss << "[Desktop File]" << std::endl - << "Name= What a great name " << std::endl; - - DesktopFileReader reader(ss); - - auto section = reader["Desktop File"]; - EXPECT_FALSE(section.empty()); - - EXPECT_EQ(section["Name"].value(), "What a great name"); -} - -TEST_F(DesktopFileReaderTest, testReadBrokenSectionHeaderMissingClosingBracket) { - { - std::stringstream ins; - ins << "[Desktop Entry" << std::endl - << "test=test" << std::endl; - - ASSERT_THROW(DesktopFileReader reader(ins), ParseError); - } - - // also test for brokenness in a later section, as the first section is normally treated specially - { - std::stringstream ins; - ins << "[Desktop Entry]" << std::endl - << "test=test" << std::endl - << "[Another Section" << std::endl; - - ASSERT_THROW(DesktopFileReader reader(ins), ParseError); - } -} - -TEST_F(DesktopFileReaderTest, testReadBrokenSectionHeaderTooManyClosingBrackets) { - { - std::stringstream ins; - ins << "[Desktop Entry]]" << std::endl - << "test=test" << std::endl; - - ASSERT_THROW(DesktopFileReader reader(ins), ParseError); - } - - // also test for brokenness in a later section, as the first section is normally treated specially - { - std::stringstream ins; - ins << "[Desktop Entry]" << std::endl - << "test=test" << std::endl - << "[Another Section]]" << std::endl; - - ASSERT_THROW(DesktopFileReader reader(ins), ParseError); - } -} - -TEST_F(DesktopFileReaderTest, testReadBrokenSectionHeaderTooManyOpeningBrackets) { - { - std::stringstream ins; - ins << "[[Desktop Entry]" << std::endl - << "test=test" << std::endl; - - ASSERT_THROW(DesktopFileReader reader(ins), ParseError); - } - - // also test for brokenness in a later section, as the first section is normally treated specially - { - std::stringstream ins; - ins << "[Desktop Entry]" << std::endl - << "test=test" << std::endl - << "[[Another Section]"; - - ASSERT_THROW(DesktopFileReader reader(ins), ParseError); - } -} - -TEST_F(DesktopFileReaderTest, testReadBrokenSectionMissingOpeningBracket) { - { - std::stringstream ins; - ins << "Desktop Entry]" << std::endl - << "test=test" << std::endl; - ASSERT_THROW(DesktopFileReader reader(ins), ParseError); - } - - // also test for brokenness in a later section, as the first section is normally treated specially - { - std::stringstream ins; - ins << "[Desktop Entry]" << std::endl - << "test=test" << std::endl - << "Another Section]" << std::endl; - - ASSERT_THROW(DesktopFileReader reader(ins), ParseError); - } -} - -// FIXME: introduce proper localization support -TEST_F(DesktopFileReaderTest, testReadLocalizedEntriesWithoutProperLocalizationSupport) { - std::stringstream ss; - ss << "[Desktop File]" << std::endl - << "Name=name" << std::endl - << "Name[de]=name" << std::endl - << "Exec=exec" << std::endl; - - DesktopFileReader reader(ss); - - auto section = reader["Desktop File"]; - EXPECT_FALSE(section.empty()); - - auto data = reader.data(); - - auto expected = DesktopFile::section_t({ - {"Name", DesktopFileEntry("Name", "name")}, - // FIXME: revise after introduction of localization support - {"Name[de]", DesktopFileEntry("Name[de]", "name")}, - {"Exec", DesktopFileEntry("Exec", "exec")}, - }); - - EXPECT_EQ(data["Desktop File"], expected); -} - -TEST_F(DesktopFileReaderTest, testBrokenLocalizedKeys) { - { - std::stringstream ins; - ins << "[Desktop Entry]" << std::endl - << "test]de[=test" << std::endl; - - EXPECT_THROW(DesktopFileReader reader(ins), ParseError); - } - - { - std::stringstream ins; - ins << "[Desktop Entry]" << std::endl - << "test[de]]=test" << std::endl; - - EXPECT_THROW(DesktopFileReader reader(ins), ParseError); - } - - { - std::stringstream ins; - ins << "[Desktop Entry]" << std::endl - << "test[[de]=test" << std::endl; - - EXPECT_THROW(DesktopFileReader reader(ins), ParseError); - } - - { - std::stringstream ins; - ins << "[Desktop Entry]" << std::endl - << "test[]de=test" << std::endl; - - EXPECT_THROW(DesktopFileReader reader(ins), ParseError); - } - - { - std::stringstream ins; - ins << "[Desktop Entry]" << std::endl - << "test[de=test" << std::endl; - - EXPECT_THROW(DesktopFileReader reader(ins), ParseError); - } - - { - std::stringstream ins; - ins << "[Desktop Entry]" << std::endl - << "testde]=test" << std::endl; - - EXPECT_THROW(DesktopFileReader reader(ins), ParseError); - } -} diff --git a/tests/core/desktopfile/test_desktopfilewriter.cpp b/tests/core/desktopfile/test_desktopfilewriter.cpp deleted file mode 100644 index 1e3db82..0000000 --- a/tests/core/desktopfile/test_desktopfilewriter.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// library headers -#include -#include - -// local headers -#include "../../src/core/desktopfile/desktopfilewriter.h" -#include "../../src/core/desktopfile/desktopfilereader.h" -#include "linuxdeploy/core/desktopfile/exceptions.h" - -using namespace linuxdeploy::core::desktopfile; -namespace bf = boost::filesystem; - -class DesktopFileWriterTest : public ::testing::Test { - void SetUp() override {} - void TearDown() override {} -}; - -TEST_F(DesktopFileWriterTest, testDefaultConstructor) { - DesktopFileWriter writer; -} - -TEST_F(DesktopFileWriterTest, testDataConstructor) { - DesktopFile::sections_t data; - DesktopFileWriter writer(data); -} - -TEST_F(DesktopFileWriterTest, testCopyConstructor) { - DesktopFile::sections_t data; - DesktopFileWriter writer(data); - - DesktopFileWriter copy(writer); - EXPECT_EQ(copy, writer); -} - -TEST_F(DesktopFileWriterTest, testCopyAssignmentConstructor) { - DesktopFile::sections_t data; - DesktopFileWriter writer(data); - - DesktopFileWriter otherWriter; - otherWriter = writer; - EXPECT_EQ(writer, otherWriter); -} - - -TEST_F(DesktopFileWriterTest, testEqualityAndInequalityOperators) { - DesktopFile::sections_t data; - DesktopFileWriter writer(data); - - DesktopFileWriter otherWriter(data); - - EXPECT_TRUE(writer == otherWriter); - EXPECT_FALSE(writer != otherWriter); -} - -TEST_F(DesktopFileWriterTest, testMoveAssignmentConstructor) { - DesktopFile::sections_t data; - DesktopFileWriter writer(data); - - DesktopFileWriter otherWriter; - otherWriter = std::move(writer); -} - -TEST_F(DesktopFileWriterTest, testSaveToPath) { - DesktopFile::sections_t data; - DesktopFileWriter writer(data); - - writer.save("/dev/null"); -} - -TEST_F(DesktopFileWriterTest, testSaveToInvalidPath) { - DesktopFileWriter writer; - ASSERT_THROW(writer.save("/a/b/c/d/e/f/g/h/1/2/3/4/5/6/7/8"), IOError); -} - -TEST_F(DesktopFileWriterTest, testSaveToStream) { - DesktopFile::sections_t data; - DesktopFileWriter writer(data); - - std::stringstream ss; - writer.save(ss); -} - -TEST_F(DesktopFileWriterTest, testDataGetter) { - DesktopFile::sections_t data; - DesktopFileWriter writer(data); - - EXPECT_EQ(data, writer.data()); -} - -TEST_F(DesktopFileWriterTest, testSerialization) { - DesktopFile::section_t section = { - {"Exec", DesktopFileEntry("Exec", "exec")}, - {"Name", DesktopFileEntry("Name", "name")}, - }; - - DesktopFile::sections_t data = { - {"Desktop File", section}, - }; - - DesktopFileWriter writer(data); - EXPECT_EQ(data, writer.data()); - - std::stringstream ss; - writer.save(ss); - - DesktopFileReader reader(ss); - EXPECT_EQ(reader["Desktop File"], section); -} diff --git a/tests/core/test_appdir.cpp b/tests/core/test_appdir.cpp index df67258..27e4438 100644 --- a/tests/core/test_appdir.cpp +++ b/tests/core/test_appdir.cpp @@ -2,7 +2,7 @@ #include "linuxdeploy/core/appdir.h" using namespace linuxdeploy::core::appdir; -using namespace linuxdeploy::core::desktopfile; +using namespace linuxdeploy::desktopfile; using namespace boost::filesystem; namespace AppDirTest {