diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/.clang-tidy | 16 | ||||
-rw-r--r-- | tests/TestClient.hpp | 18 | ||||
-rw-r--r-- | tests/connect_disconnect_node_patch.ttl | 6 | ||||
-rw-r--r-- | tests/ingen_bench.cpp | 55 | ||||
-rw-r--r-- | tests/ingen_test.cpp | 122 | ||||
-rw-r--r-- | tests/lint/meson.build | 24 | ||||
-rw-r--r-- | tests/meson.build | 100 | ||||
-rw-r--r-- | tests/test_utils.hpp | 4 | ||||
-rw-r--r-- | tests/tst_FilePath.cpp | 108 |
9 files changed, 241 insertions, 212 deletions
diff --git a/tests/.clang-tidy b/tests/.clang-tidy new file mode 100644 index 00000000..6c26f23c --- /dev/null +++ b/tests/.clang-tidy @@ -0,0 +1,16 @@ +Checks: > + -*-no-malloc, + -*-vararg, + -android-cloexec-fopen, + -cert-err33-c, + -concurrency-mt-unsafe, + -cppcoreguidelines-avoid-non-const-global-variables, + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-type-reinterpret-cast, + -cppcoreguidelines-pro-type-union-access, + -fuchsia-statically-constructed-objects, + -google-readability-todo, + -llvm-header-guard, + -readability-function-cognitive-complexity, +InheritParentConfig: true diff --git a/tests/TestClient.hpp b/tests/TestClient.hpp index da749660..72265b14 100644 --- a/tests/TestClient.hpp +++ b/tests/TestClient.hpp @@ -17,13 +17,13 @@ #ifndef INGEN_TESTCLIENT_HPP #define INGEN_TESTCLIENT_HPP -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/Message.hpp" -#include "ingen/Status.hpp" -#include "ingen/URI.hpp" +#include <ingen/Interface.hpp> +#include <ingen/Log.hpp> +#include <ingen/Message.hpp> +#include <ingen/Status.hpp> +#include <ingen/URI.hpp> -#include <boost/variant/get.hpp> +#include <variant> #include <cstdlib> @@ -32,14 +32,14 @@ namespace ingen { class TestClient : public Interface { public: - explicit TestClient(Log& log) : _log(log) {} + explicit TestClient(Log& log) noexcept : _log(log) {} ~TestClient() override = default; URI uri() const override { return URI("ingen:testClient"); } void message(const Message& msg) override { - if (const Response* const response = boost::get<Response>(&msg)) { + if (const Response* const response = std::get_if<Response>(&msg)) { if (response->status != Status::SUCCESS) { _log.error("error on message %1%: %2% (%3%)\n", response->id, @@ -47,7 +47,7 @@ public: response->subject); exit(EXIT_FAILURE); } - } else if (const Error* const error = boost::get<Error>(&msg)) { + } else if (const Error* const error = std::get_if<Error>(&msg)) { _log.error("error: %1%\n", error->message); exit(EXIT_FAILURE); } diff --git a/tests/connect_disconnect_node_patch.ttl b/tests/connect_disconnect_node_patch.ttl index 77ada2ad..373b5cbf 100644 --- a/tests/connect_disconnect_node_patch.ttl +++ b/tests/connect_disconnect_node_patch.ttl @@ -13,10 +13,10 @@ <msg1> a patch:Put ; - patch:subject <ingen:/main/sampler> ; + patch:subject <ingen:/main/metro> ; patch:body [ a ingen:Block ; - lv2:prototype <http://lv2plug.in/plugins/eg-sampler> + lv2:prototype <http://lv2plug.in/plugins/eg-metro> ] . <msg2> @@ -85,7 +85,7 @@ patch:body [ a ingen:Arc ; ingen:tail <ingen:/main/control> ; - ingen:head <ingen:/main/sampler/control> + ingen:head <ingen:/main/metro/control> ] . <msg10> diff --git a/tests/ingen_bench.cpp b/tests/ingen_bench.cpp index 2af53f89..ee890401 100644 --- a/tests/ingen_bench.cpp +++ b/tests/ingen_bench.cpp @@ -14,14 +14,14 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Atom.hpp" -#include "ingen/Clock.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/EngineBase.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Parser.hpp" -#include "ingen/World.hpp" -#include "ingen/runtime_paths.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Clock.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/EngineBase.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Parser.hpp> +#include <ingen/World.hpp> +#include <ingen/runtime_paths.hpp> #include <chrono> #include <cstdint> @@ -32,8 +32,7 @@ #include <memory> #include <string> -namespace ingen { -namespace bench { +namespace ingen::bench { namespace { std::unique_ptr<ingen::World> world; @@ -42,7 +41,7 @@ void ingen_try(bool cond, const char* msg) { if (!cond) { - std::cerr << "ingen: Error: " << msg << std::endl; + std::cerr << "ingen: Error: " << msg << "\n"; world.reset(); exit(EXIT_FAILURE); } @@ -62,15 +61,14 @@ run(int argc, char** argv) { // Create world try { - world = std::unique_ptr<ingen::World>{ - new ingen::World(nullptr, nullptr, nullptr)}; + world = std::make_unique<ingen::World>(nullptr, nullptr, nullptr); world->conf().add( "output", "output", 'O', "File to write benchmark output", ingen::Configuration::SESSION, world->forge().String, Atom()); world->load_configuration(argc, argv); } catch (std::exception& e) { - std::cout << "ingen: " << e.what() << std::endl; + std::cout << "ingen: " << e.what() << "\n"; return EXIT_FAILURE; } @@ -78,9 +76,7 @@ run(int argc, char** argv) const Atom& load = world->conf().option("load"); const Atom& out = world->conf().option("output"); if (!load.is_valid() || !out.is_valid()) { - std::cerr << "Usage: ingen_bench --load START_GRAPH --output OUT_FILE" - << std::endl; - + std::cerr << "Usage: ingen_bench --load START_GRAPH --output OUT_FILE\n"; return EXIT_FAILURE; } @@ -92,7 +88,7 @@ run(int argc, char** argv) if (start_graph.empty()) { std::cerr << "error: initial graph '" << static_cast<const char*>(load.get_body()) - << "' does not exist" << std::endl; + << "' does not exist\n"; return EXIT_FAILURE; } @@ -101,7 +97,7 @@ run(int argc, char** argv) "Unable to load server module"); // Initialise engine - ingen_try(bool(world->engine()), + ingen_try(!!world->engine(), "Unable to create engine"); world->engine()->init(48000.0, 4096, 4096); world->engine()->activate(); @@ -109,7 +105,7 @@ run(int argc, char** argv) // Load graph if (!world->parser()->parse_file(*world, *world->interface(), start_graph)) { std::cerr << "error: failed to load initial graph " << start_graph - << std::endl; + << "\n"; return EXIT_FAILURE; } @@ -117,10 +113,10 @@ run(int argc, char** argv) // Run benchmark // TODO: Set up real-time scheduling for this and worker threads - ingen::Clock clock; - const uint32_t n_test_frames = 1 << 20; - const uint32_t block_length = 4096; - const uint64_t t_start = clock.now_microseconds(); + const ingen::Clock clock; + const uint32_t n_test_frames = 1 << 20; + const uint32_t block_length = 4096; + const uint64_t t_start = clock.now_microseconds(); for (uint32_t i = 0; i < n_test_frames; i += block_length) { world->engine()->advance(block_length); world->engine()->run(block_length); @@ -129,14 +125,14 @@ run(int argc, char** argv) const uint64_t t_end = clock.now_microseconds(); // Write log output - std::unique_ptr<FILE, decltype(&fclose)> log{fopen(out_file.c_str(), "a"), - &fclose}; + const std::unique_ptr<FILE, int (*)(FILE*)> log{fopen(out_file.c_str(), "a"), + &fclose}; if (ftell(log.get()) == 0) { fprintf(log.get(), "# n_threads\trun_time\treal_time\n"); } - fprintf(log.get(), "%u\t%f\t%f\n", + fprintf(log.get(), "%d\t%f\t%f\n", world->conf().option("threads").get<int32_t>(), - (t_end - t_start) / 1000000.0, + static_cast<double>(t_end - t_start) / 1000000.0, (n_test_frames / 48000.0)); // Shut down @@ -146,8 +142,7 @@ run(int argc, char** argv) } } // namespace -} // namespace bench -} // namespace ingen +} // namespace ingen::bench int main(int argc, char** argv) diff --git a/tests/ingen_test.cpp b/tests/ingen_test.cpp index 87e02e9f..215d20a1 100644 --- a/tests/ingen_test.cpp +++ b/tests/ingen_test.cpp @@ -16,40 +16,41 @@ #include "TestClient.hpp" -#include "ingen/Atom.hpp" -#include "ingen/AtomForge.hpp" -#include "ingen/AtomReader.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/EngineBase.hpp" -#include "ingen/FilePath.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Parser.hpp" -#include "ingen/Serialiser.hpp" -#include "ingen/Store.hpp" -#include "ingen/URI.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/World.hpp" -#include "ingen/filesystem.hpp" -#include "ingen/fmt.hpp" -#include "ingen/memory.hpp" -#include "ingen/runtime_paths.hpp" -#include "raul/Path.hpp" -#include "serd/serd.h" -#include "sord/sordmm.hpp" -#include "sratom/sratom.h" +#include <ingen/Atom.hpp> +#include <ingen/AtomForge.hpp> +#include <ingen/AtomReader.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/EngineBase.hpp> +#include <ingen/FilePath.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Parser.hpp> +#include <ingen/Serialiser.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/World.hpp> +#include <ingen/fmt.hpp> +#include <ingen/memory.hpp> +#include <ingen/runtime_paths.hpp> +#include <raul/Path.hpp> +#include <serd/serd.h> +#include <sord/sordmm.hpp> +#include <sratom/sratom.h> #include <chrono> #include <cstdint> #include <cstdlib> #include <exception> +#include <filesystem> #include <iostream> #include <map> #include <memory> #include <string> #include <utility> -namespace ingen { -namespace test { +// #define DUMP_EVENTS 1 + +namespace ingen::test { namespace { std::unique_ptr<World> world; @@ -58,7 +59,7 @@ void ingen_try(bool cond, const char* msg) { if (!cond) { - std::cerr << "ingen: Error: " << msg << std::endl; + std::cerr << "ingen: Error: " << msg << "\n"; world.reset(); exit(EXIT_FAILURE); } @@ -67,8 +68,8 @@ ingen_try(bool cond, const char* msg) FilePath real_file_path(const char* path) { - std::unique_ptr<char, FreeDeleter<char>> real_path{realpath(path, nullptr), - FreeDeleter<char>{}}; + const std::unique_ptr<char, FreeDeleter<char>> real_path{realpath(path, nullptr), + FreeDeleter<char>{}}; return FilePath{real_path.get()}; } @@ -78,10 +79,10 @@ run(int argc, char** argv) { // Create world try { - world = std::unique_ptr<World>{new World(nullptr, nullptr, nullptr)}; + world = std::make_unique<World>(nullptr, nullptr, nullptr); world->load_configuration(argc, argv); - } catch (std::exception& e) { - std::cout << "ingen: " << e.what() << std::endl; + } catch (const std::exception& e) { + std::cerr << "ingen: " << e.what() << "\n"; return EXIT_FAILURE; } @@ -90,8 +91,7 @@ run(int argc, char** argv) const Atom& execute = world->conf().option("execute"); if (!load.is_valid() || !execute.is_valid()) { std::cerr - << "Usage: ingen_test --load START_GRAPH --execute COMMANDS_FILE" - << std::endl; + << "Usage: ingen_test --load START_GRAPH --execute COMMANDS_FILE\n"; return EXIT_FAILURE; } @@ -101,14 +101,12 @@ run(int argc, char** argv) const FilePath run_path = real_file_path(static_cast<const char*>(execute.get_body())); if (load_path.empty()) { - std::cerr << "error: initial graph '" << load_path << "' does not exist" - << std::endl; - + std::cerr << "error: initial graph '" << load_path << "' does not exist\n"; return EXIT_FAILURE; - } else if (run_path.empty()) { - std::cerr << "error: command file '" << run_path << "' does not exist" - << std::endl; + } + if (run_path.empty()) { + std::cerr << "error: command file '" << run_path << "' does not exist\n"; return EXIT_FAILURE; } @@ -117,16 +115,14 @@ run(int argc, char** argv) "Unable to load server module"); // Initialise engine - ingen_try(bool(world->engine()), + ingen_try(!!world->engine(), "Unable to create engine"); world->engine()->init(48000.0, 4096, 4096); world->engine()->activate(); // Load graph if (!world->parser()->parse_file(*world, *world->interface(), load_path)) { - std::cerr << "error: failed to load initial graph " << load_path - << std::endl; - + std::cerr << "error: failed to load initial graph " << load_path << "\n"; return EXIT_FAILURE; } world->engine()->flush_events(std::chrono::milliseconds(20)); @@ -144,7 +140,7 @@ run(int argc, char** argv) *world->interface()); // AtomWriter to serialise responses from the engine - std::shared_ptr<Interface> client(new TestClient(world->log())); + const std::shared_ptr<Interface> client{new TestClient(world->log())}; world->interface()->set_respondee(client); world->engine()->register_client(client); @@ -160,13 +156,16 @@ run(int argc, char** argv) SerdEnv* env = serd_env_new(&cmds_file_uri); cmds->load_file(env, SERD_TURTLE, run_path); - Sord::Node nil; - int n_events = 0; + const Sord::Node nil; + int n_events = 0; for (;; ++n_events) { - std::string subject_str = fmt("msg%1%", n_events); - Sord::URI subject(*world->rdf_world(), subject_str, + const std::string subject_str = fmt("msg%1%", n_events); + + Sord::URI subject(*world->rdf_world(), + subject_str, reinterpret_cast<const char*>(cmds_file_uri.buf)); - Sord::Iter iter = cmds->find(subject, nil, nil); + + auto iter = cmds->find(subject, nil, nil); if (iter.end()) { break; } @@ -174,9 +173,9 @@ run(int argc, char** argv) forge.clear(); forge.read(*world->rdf_world(), cmds->c_obj(), subject.c_obj()); -#if 0 +#ifdef DUMP_EVENTS const LV2_Atom* atom = forge.atom(); - cerr << "READ " << atom->size << " BYTES" << endl; + cerr << "READ " << atom->size << " BYTES\n"; cerr << sratom_to_turtle( sratom, &world->uri_map().urid_unmap_feature()->urid_unmap, @@ -185,6 +184,7 @@ run(int argc, char** argv) #endif if (!atom_reader.write(forge.atom(), n_events + 1)) { + delete cmds; return EXIT_FAILURE; } @@ -197,10 +197,10 @@ run(int argc, char** argv) auto r = world->store()->find(raul::Path("/")); const std::string base = run_path.stem(); const std::string out_name = base.substr(0, base.find('.')) + ".out.ingen"; - const FilePath out_path = filesystem::current_path() / out_name; + const FilePath out_path = std::filesystem::current_path() / out_name; world->serialiser()->write_bundle(r->second, URI(out_path)); - // Undo every event (should result in a graph identical to the original) + // Undo every event (makes the graph identical to the original) for (int i = 0; i < n_events; ++i) { world->interface()->undo(); world->engine()->flush_events(std::chrono::milliseconds(20)); @@ -209,10 +209,10 @@ run(int argc, char** argv) // Save completely undone graph r = world->store()->find(raul::Path("/")); const std::string undo_name = base.substr(0, base.find('.')) + ".undo.ingen"; - const FilePath undo_path = filesystem::current_path() / undo_name; + const FilePath undo_path = std::filesystem::current_path() / undo_name; world->serialiser()->write_bundle(r->second, URI(undo_path)); - // Redo every event (should result in a graph identical to the pre-undo output) + // Redo every event (makes the graph identical to the pre-undo output) for (int i = 0; i < n_events; ++i) { world->interface()->redo(); world->engine()->flush_events(std::chrono::milliseconds(20)); @@ -221,7 +221,7 @@ run(int argc, char** argv) // Save completely redone graph r = world->store()->find(raul::Path("/")); const std::string redo_name = base.substr(0, base.find('.')) + ".redo.ingen"; - const FilePath redo_path = filesystem::current_path() / redo_name; + const FilePath redo_path = std::filesystem::current_path() / redo_name; world->serialiser()->write_bundle(r->second, URI(redo_path)); serd_env_free(env); @@ -234,14 +234,18 @@ run(int argc, char** argv) } } // namespace -} // namespace test -} // namespace ingen +} // namespace ingen::test int main(int argc, char** argv) { - ingen::set_bundle_path_from_code( - reinterpret_cast<void (*)()>(&ingen::test::ingen_try)); + try { + ingen::set_bundle_path_from_code( + reinterpret_cast<void (*)()>(&ingen::test::ingen_try)); - return ingen::test::run(argc, argv); + return ingen::test::run(argc, argv); + } catch (const std::exception& e) { + std::cerr << "ingen: " << e.what() << "\n"; + return EXIT_FAILURE; + } } diff --git a/tests/lint/meson.build b/tests/lint/meson.build new file mode 100644 index 00000000..c641cbaa --- /dev/null +++ b/tests/lint/meson.build @@ -0,0 +1,24 @@ +# Copyright 2019-2024 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR GPL-3.0-or-later + +if not meson.is_subproject() + # Check code with cppcheck + cppcheck = find_program('cppcheck', required: false) + if cppcheck.found() + compdb_path = join_paths(ingen_build_root, 'compile_commands.json') + suppress_path = join_paths(ingen_src_root, '.suppress.cppcheck') + test( + 'cppcheck', + cppcheck, + args: [ + '--cppcheck-build-dir=' + meson.current_build_dir(), + '--enable=warning,style,performance,portability', + '--error-exitcode=1', + '--project=' + compdb_path, + '--suppressions-list=' + suppress_path, + '-q', + ], + suite: 'code', + ) + endif +endif diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 00000000..1637230b --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,100 @@ +# Copyright 2019-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR GPL-3.0-or-later + +##################### +# Integration Tests # +##################### + +ingen_test = executable( + 'ingen_test', + files('ingen_test.cpp'), + cpp_args: cpp_suppressions + platform_defines, + dependencies: [ingen_dep], +) + +ingen_bench = executable( + 'ingen_bench', + files('ingen_bench.cpp'), + cpp_args: cpp_suppressions + platform_defines, + dependencies: [ingen_dep], +) + +empty_manifest = files('empty.ingen/manifest.ttl') +empty_main = files('empty.ingen/main.ttl') + +integration_tests = [ + 'connect_disconnect_node_node', + 'connect_disconnect_node_patch', + 'connect_disconnect_patch_patch', + 'copy_node', + 'create_delete_node', + 'create_delete_patch', + 'create_delete_poly_patch', + 'create_delete_port', + 'disconnect_all_node', + 'disconnect_all_port', + 'duplicate_node', + 'enable_graph', + 'get_engine', + 'get_node', + 'get_patch', + 'get_plugin', + 'get_plugins', + 'get_port', + 'load_graph', + 'move_node', + 'move_port', + 'move_root_port', + 'poly', + 'put_audio_in', + 'save_graph', + 'set_graph_poly', + 'set_patch_port_value', +] + +test_env = environment( + { + 'INGEN_MODULE_PATH': ':'.join( + [ + ingen_build_root / 'src', + ingen_build_root / 'src' / 'client', + ingen_build_root / 'src' / 'gui', + ingen_build_root / 'src' / 'server', + ], + ), + 'LV2_PATH': ':'.join( + [ + lv2_dep.get_variable( + default_value: lv2dir, + internal: 'lv2dir', + pkgconfig: 'lv2dir', + ), + lv2_dep.get_variable( + default_value: lv2dir, + internal: 'plugindir', + pkgconfig: 'plugindir', + ), + ], + ), + }, +) + +foreach test : integration_tests + test( + test, + ingen_test, + env: test_env, + args: [ + ['--load', empty_manifest], + ['--execute', files(test + '.ttl')], + ], + ) +endforeach + +######## +# Lint # +######## + +if get_option('lint') + subdir('lint') +endif diff --git a/tests/test_utils.hpp b/tests/test_utils.hpp index 57446ac5..4c358739 100644 --- a/tests/test_utils.hpp +++ b/tests/test_utils.hpp @@ -14,9 +14,7 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -// IWYU pragma: no_include "ingen/FilePath.hpp" - -#include "ingen/fmt.hpp" +#include <ingen/fmt.hpp> #include <iostream> #include <string> diff --git a/tests/tst_FilePath.cpp b/tests/tst_FilePath.cpp deleted file mode 100644 index 75744f46..00000000 --- a/tests/tst_FilePath.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2018 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "test_utils.hpp" - -#include "ingen/FilePath.hpp" -#include "ingen/fmt.hpp" - -#include <boost/utility/string_view_fwd.hpp> - -#include <string> - -using ingen::FilePath; -using ingen::fmt; - -int -main(int, char**) -{ - EXPECT_EQ(FilePath("/").parent_path(), FilePath("/")); - - EXPECT_TRUE(FilePath("/abs").is_absolute()); - EXPECT_FALSE(FilePath("/abs").is_relative()); - EXPECT_EQ(FilePath("/abs").root_name(), FilePath()); - EXPECT_EQ(FilePath("/abs").root_directory(), FilePath("/")); - EXPECT_EQ(FilePath("/abs").root_path(), FilePath("/")); - EXPECT_EQ(FilePath("/abs").relative_path(), FilePath("abs")); - EXPECT_EQ(FilePath("/abs").parent_path(), FilePath("/")); - EXPECT_EQ(FilePath("/abs").filename(), FilePath("abs")); - EXPECT_EQ(FilePath("/abs").stem(), FilePath("abs")); - EXPECT_EQ(FilePath("/abs").extension(), FilePath()); - - EXPECT_FALSE(FilePath("rel").is_absolute()); - EXPECT_TRUE(FilePath("rel").is_relative()); - EXPECT_EQ(FilePath("rel").root_name(), FilePath()); - EXPECT_EQ(FilePath("rel").root_directory(), FilePath()); - EXPECT_EQ(FilePath("rel").root_path(), FilePath()); - EXPECT_EQ(FilePath("rel").relative_path(), FilePath()); - EXPECT_EQ(FilePath("rel").parent_path(), FilePath()); - EXPECT_EQ(FilePath("rel").filename(), "rel"); - EXPECT_EQ(FilePath("rel").stem(), "rel"); - EXPECT_EQ(FilePath("rel").extension(), FilePath()); - - EXPECT_FALSE(FilePath("file.txt").is_absolute()); - EXPECT_TRUE(FilePath("file.txt").is_relative()); - EXPECT_EQ(FilePath("file.txt").filename(), "file.txt"); - EXPECT_EQ(FilePath("file.txt").stem(), "file"); - EXPECT_EQ(FilePath("file.txt").extension(), ".txt"); - - EXPECT_TRUE(FilePath("/abs/file.txt").is_absolute()); - EXPECT_FALSE(FilePath("/abs/file.txt").is_relative()); - EXPECT_EQ(FilePath("/abs/file.txt").filename(), "file.txt"); - EXPECT_EQ(FilePath("/abs/file.txt").stem(), "file"); - EXPECT_EQ(FilePath("/abs/file.txt").extension(), ".txt"); - - EXPECT_FALSE(FilePath("rel/file.txt").is_absolute()); - EXPECT_TRUE(FilePath("rel/file.txt").is_relative()); - EXPECT_EQ(FilePath("rel/file.txt").filename(), "file.txt"); - EXPECT_EQ(FilePath("rel/file.txt").stem(), "file"); - EXPECT_EQ(FilePath("rel/file.txt").extension(), ".txt"); - - FilePath path("/x"); - EXPECT_EQ(path, "/x"); - path = std::string("/a"); - EXPECT_EQ(path, "/a"); - - path /= FilePath("b"); - EXPECT_EQ(path, "/a/b"); - - path += FilePath("ar"); - EXPECT_EQ(path, "/a/bar"); - - path += std::string("/c"); - EXPECT_EQ(path, "/a/bar/c"); - - path += "a"; - EXPECT_EQ(path, "/a/bar/ca"); - - path += 'r'; - EXPECT_EQ(path, "/a/bar/car"); - - path += boost::string_view("/d"); - EXPECT_EQ(path, "/a/bar/car/d"); - - const FilePath apple("apple"); - const FilePath zebra("zebra"); - EXPECT_TRUE(apple == apple); - EXPECT_TRUE(apple != zebra); - EXPECT_TRUE(apple < zebra); - EXPECT_TRUE(apple <= zebra); - EXPECT_TRUE(apple <= apple); - EXPECT_TRUE(zebra > apple); - EXPECT_TRUE(zebra >= apple); - EXPECT_TRUE(zebra >= zebra); - return 0; -} |