Mercurial > code
changeset 240:f6d9fdb5eeeb
Xdg: don't use bad directories, add tests
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 14 Aug 2014 09:56:25 +0200 |
parents | 9b69f810d3b9 |
children | d9409b338f2f |
files | C++/Tests/OptionParser/main.cpp C++/Tests/Xdg/CMakeLists.txt C++/Tests/Xdg/main.cpp C++/Xdg.cpp C++/Xdg.h CMakeLists.txt |
diffstat | 6 files changed, 406 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/C++/Tests/OptionParser/main.cpp Tue Aug 12 16:45:33 2014 +0200 +++ b/C++/Tests/OptionParser/main.cpp Thu Aug 14 09:56:25 2014 +0200 @@ -1,3 +1,21 @@ +/* + * main.cpp -- main test file for OptionParser + * + * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + #include <gtest/gtest.h> #include <OptionParser.h>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/C++/Tests/Xdg/CMakeLists.txt Thu Aug 14 09:56:25 2014 +0200 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- tests for XDG +# +# Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +set( + SOURCES + ${code_SOURCE_DIR}/C++/Xdg.cpp + ${code_SOURCE_DIR}/C++/Xdg.h + main.cpp +) + +define_test(xdg "${SOURCES}")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/C++/Tests/Xdg/main.cpp Thu Aug 14 09:56:25 2014 +0200 @@ -0,0 +1,340 @@ +/* + * main.cpp -- main test file for XDG + * + * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <gtest/gtest.h> + +#include <Xdg.h> + +using namespace testing; + +namespace { + +std::string myhome; + +} + +TEST(HomeEmpty, config) +{ + ASSERT_TRUE(unsetenv("XDG_CONFIG_HOME") == 0); + + try { + Xdg xdg; + + ASSERT_EQ(myhome + "/.config", xdg.configHome()); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(HomeEmpty, data) +{ + ASSERT_TRUE(unsetenv("XDG_DATA_HOME") == 0); + + try { + Xdg xdg; + + ASSERT_EQ(myhome + "/.local/share", xdg.dataHome()); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(HomeEmpty, cache) +{ + ASSERT_TRUE(unsetenv("XDG_CACHE_HOME") == 0); + + try { + Xdg xdg; + + ASSERT_EQ(myhome + "/.cache", xdg.cacheHome()); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(HomeEmpty, runtime) +{ + ASSERT_TRUE(unsetenv("XDG_RUNTIME_DIR") == 0); + + try { + Xdg xdg; + + try { + xdg.runtimeDir(); + + ASSERT_TRUE(false); + } catch (const std::exception &) { } + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(HomeValid, config) +{ + ASSERT_TRUE(setenv("XDG_CONFIG_HOME", "/test/config", true) == 0); + + try { + Xdg xdg; + + ASSERT_EQ("/test/config", xdg.configHome()); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(HomeValid, data) +{ + ASSERT_TRUE(setenv("XDG_DATA_HOME", "/test/data", true) == 0); + + try { + Xdg xdg; + + ASSERT_EQ("/test/data", xdg.dataHome()); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(HomeValid, cache) +{ + ASSERT_TRUE(setenv("XDG_CACHE_HOME", "/test/cache", true) == 0); + + try { + Xdg xdg; + + ASSERT_EQ("/test/cache", xdg.cacheHome()); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(HomeValid, runtime) +{ + ASSERT_TRUE(setenv("XDG_RUNTIME_DIR", "/test/runtime", true) == 0); + + try { + Xdg xdg; + + ASSERT_EQ("/test/runtime", xdg.runtimeDir()); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(HomeInvalid, config) +{ + ASSERT_TRUE(setenv("XDG_CONFIG_HOME", "invalid", true) == 0); + + try { + Xdg xdg; + + ASSERT_EQ(myhome + "/.config", xdg.configHome()); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(HomeInvalid, data) +{ + ASSERT_TRUE(setenv("XDG_DATA_HOME", "invalid", true) == 0); + + try { + Xdg xdg; + + ASSERT_EQ(myhome + "/.local/share", xdg.dataHome()); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(HomeInvalid, cache) +{ + ASSERT_TRUE(setenv("XDG_CACHE_HOME", "invalid", true) == 0); + + try { + Xdg xdg; + + ASSERT_EQ(myhome + "/.cache", xdg.cacheHome()); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(HomeInvalid, runtime) +{ + ASSERT_TRUE(setenv("XDG_RUNTIME_DIR", "invalid", true) == 0); + + try { + Xdg xdg; + + try { + xdg.runtimeDir(); + + ASSERT_TRUE(false); + } catch (const std::exception &) { } + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(DirectoriesEmpty, config) +{ + ASSERT_TRUE(unsetenv("XDG_CONFIG_DIRS") == 0); + + try { + Xdg xdg; + + const auto &list = xdg.configDirs(); + + ASSERT_EQ((size_t)1, list.size()); + ASSERT_EQ("/etc/xdg", list[0]); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(DirectoriesEmpty, data) +{ + ASSERT_TRUE(unsetenv("XDG_DATA_DIRS") == 0); + + try { + Xdg xdg; + + const auto &list = xdg.dataDirs(); + + ASSERT_EQ((size_t)2, list.size()); + ASSERT_EQ("/usr/local/share", list[0]); + ASSERT_EQ("/usr/share", list[1]); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(DirectoriesValid, config) +{ + ASSERT_TRUE(setenv("XDG_CONFIG_DIRS", "/config1:/config2", true) == 0); + + try { + Xdg xdg; + + const auto &list = xdg.configDirs(); + + ASSERT_EQ((size_t)2, list.size()); + ASSERT_EQ("/config1", list[0]); + ASSERT_EQ("/config2", list[1]); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(DirectoriesValid, data) +{ + ASSERT_TRUE(setenv("XDG_DATA_DIRS", "/data1:/data2", true) == 0); + + try { + Xdg xdg; + + const auto &list = xdg.dataDirs(); + + ASSERT_EQ((size_t)2, list.size()); + ASSERT_EQ("/data1", list[0]); + ASSERT_EQ("/data2", list[1]); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(DirectoriesInvalid, config) +{ + ASSERT_TRUE(setenv("XDG_CONFIG_DIRS", "bad1:bad2", true) == 0); + + try { + Xdg xdg; + + const auto &list = xdg.configDirs(); + + ASSERT_EQ((size_t)1, list.size()); + ASSERT_EQ("/etc/xdg", list[0]); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(DirectoriesInvalid, data) +{ + ASSERT_TRUE(setenv("XDG_DATA_DIRS", "bad1:bad2", true) == 0); + + try { + Xdg xdg; + + const auto &list = xdg.dataDirs(); + + ASSERT_EQ((size_t)2, list.size()); + ASSERT_EQ("/usr/local/share", list[0]); + ASSERT_EQ("/usr/share", list[1]); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(DirectoriesMixed, config) +{ + ASSERT_TRUE(setenv("XDG_CONFIG_DIRS", "/config1:bad:/config2", true) == 0); + + try { + Xdg xdg; + + const auto &list = xdg.configDirs(); + + ASSERT_EQ((size_t)2, list.size()); + ASSERT_EQ("/config1", list[0]); + ASSERT_EQ("/config2", list[1]); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +TEST(DirectoriesMixed, data) +{ + ASSERT_TRUE(setenv("XDG_DATA_DIRS", "/data1:bad:/data2", true) == 0); + + try { + Xdg xdg; + + const auto &list = xdg.dataDirs(); + + ASSERT_EQ((size_t)2, list.size()); + ASSERT_EQ("/data1", list[0]); + ASSERT_EQ("/data2", list[1]); + } catch (const std::exception &) { + ASSERT_TRUE(false); + } +} + +int main(int argc, char **argv) +{ + auto home = getenv("HOME"); + + if (home == nullptr) + return 0; + + myhome = home; + InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +}
--- a/C++/Xdg.cpp Tue Aug 12 16:45:33 2014 +0200 +++ b/C++/Xdg.cpp Thu Aug 14 09:56:25 2014 +0200 @@ -17,12 +17,18 @@ */ #include <cstdlib> +#include <stdexcept> #include <sstream> -#include "xdg.h" +#include "Xdg.h" namespace { +bool isabsolute(const std::string &path) +{ + return path.length() > 0 && path[0] == '/'; +} + std::vector<std::string> split(const std::string &arg) { std::stringstream iss(arg); @@ -30,7 +36,8 @@ std::vector<std::string> elems; while (std::getline(iss, item, ':')) - elems.push_back(item); + if (isabsolute(item)) + elems.push_back(item); return elems; } @@ -39,7 +46,7 @@ { auto value = getenv(var.c_str()); - if (value == nullptr) { + if (value == nullptr || !isabsolute(value)) { auto home = getenv("HOME"); if (home == nullptr) @@ -58,7 +65,10 @@ if (!value) return list; - return split(value); + // No valid item at all? Use defaults + auto result = split(value); + + return (result.size() == 0) ? list : result; } } // !namespace @@ -77,7 +87,7 @@ * application should manage this by itself. */ auto runtime = getenv("XDG_RUNTIME_DIR"); - if (runtime) + if (runtime && isabsolute(runtime)) m_runtimeDir = runtime; }
--- a/C++/Xdg.h Tue Aug 12 16:45:33 2014 +0200 +++ b/C++/Xdg.h Thu Aug 14 09:56:25 2014 +0200 @@ -36,7 +36,8 @@ * @class Xdg * @brief XDG specifications * - * Read and get XDG directories. + * Read and get XDG directories. This file contains exports thingies so it can + * compiles successfully on Windows but its usage is discouraged. */ class EXPORT Xdg { public:
--- a/CMakeLists.txt Tue Aug 12 16:45:33 2014 +0200 +++ b/CMakeLists.txt Thu Aug 14 09:56:25 2014 +0200 @@ -68,6 +68,7 @@ option(WITH_SOCKET "Enable sockets tests" On) option(WITH_UTF8 "Enable Utf8 functions tests" On) option(WITH_XMLPARSER "Enable XML tests" On) +option(WITH_XDG "Enable XDG standard directories tests" On) if (WITH_DIRECTORY) add_subdirectory(C++/Tests/Directory) @@ -96,3 +97,7 @@ if (WITH_PARSER) add_subdirectory(C++/Tests/Parser) endif () + +if (WITH_XDG) + add_subdirectory(C++/Tests/Xdg) +endif ()