#include #include #include #include #include #include #include "settings.hpp" namespace { class ScopedFileCleanup { public: explicit ScopedFileCleanup(std::filesystem::path path) : path_(std::move(path)) {} ScopedFileCleanup(const ScopedFileCleanup &) = delete; ScopedFileCleanup &operator=(const ScopedFileCleanup &) = delete; ScopedFileCleanup(ScopedFileCleanup &&) = delete; ScopedFileCleanup &operator=(ScopedFileCleanup &&) = delete; ~ScopedFileCleanup() { if (!path_.empty()) { std::error_code error; std::filesystem::remove(path_, error); } } private: std::filesystem::path path_; }; std::string random_token(std::size_t length) { static const char charset[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; std::string result; result.reserve(length); std::mt19937 engine{std::random_device{}()}; std::uniform_int_distribution dist(0, sizeof(charset) - 2); for (std::size_t i = 0; i < length; ++i) { result.push_back(charset[dist(engine)]); } return result; } TEST(SettingsBuilder, DefaultsToStdStreamsAndFlagsOff) { wavefront::SettingsBuilder builder; EXPECT_EQ(&builder.input(), &std::cin); EXPECT_EQ(&builder.output(), &std::cout); EXPECT_FALSE(builder.with_normals()); EXPECT_FALSE(builder.with_texcoords()); EXPECT_FALSE(builder.use_float64()); wavefront::Settings settings = builder.build(); EXPECT_EQ(&settings.input(), &std::cin); EXPECT_EQ(&settings.output(), &std::cout); EXPECT_FALSE(settings.extract_normals()); EXPECT_FALSE(settings.extract_texcoords()); EXPECT_FALSE(settings.use_float64()); EXPECT_TRUE(settings.selected_objects().empty()); EXPECT_TRUE(settings.selected_groups().empty()); } TEST(SettingsBuilder, AppliesConfigurationAndSelection) { std::istringstream input("dummy"); std::ostringstream output; wavefront::SettingsBuilder builder; builder.input(input) .output(output) .with_normals(true) .with_texcoords(true) .use_float64(true); builder.selected_objects().push_back("object_a"); builder.selected_groups().push_back("group_a"); EXPECT_EQ(&builder.input(), &input); EXPECT_EQ(&builder.output(), &output); EXPECT_TRUE(builder.with_normals()); EXPECT_TRUE(builder.with_texcoords()); EXPECT_TRUE(builder.use_float64()); wavefront::Settings settings = builder.build(); EXPECT_EQ(&settings.input(), &input); EXPECT_EQ(&settings.output(), &output); EXPECT_TRUE(settings.extract_normals()); EXPECT_TRUE(settings.extract_texcoords()); EXPECT_TRUE(settings.use_float64()); ASSERT_EQ(settings.selected_objects().size(), 1u); EXPECT_EQ(settings.selected_objects()[0], "object_a"); ASSERT_EQ(settings.selected_groups().size(), 1u); EXPECT_EQ(settings.selected_groups()[0], "group_a"); } TEST(SettingsBuilder, CanOpenFileFromString) { const auto temp_dir = std::filesystem::temp_directory_path(); const auto token = random_token(12); const auto input_path = temp_dir / std::filesystem::path("dragiyski-wavefront-parser-test-settings-input-" + token + ".txt"); const auto output_path = temp_dir / std::filesystem::path("dragiyski-wavefront-parser-test-settings-output-" + token + ".txt"); const ScopedFileCleanup input_cleanup(input_path); const ScopedFileCleanup output_cleanup(output_path); { std::ofstream seed(input_path); seed << token; } wavefront::SettingsBuilder builder; builder.input(input_path.string()) .output(output_path.string()); wavefront::Settings settings = builder.build(); EXPECT_NE(&settings.input(), &std::cin); EXPECT_NE(&settings.output(), &std::cout); auto *input_stream = dynamic_cast(&settings.input()); ASSERT_NE(input_stream, nullptr); EXPECT_TRUE(input_stream->is_open()); std::string input_contents; *input_stream >> input_contents; EXPECT_EQ(input_contents, token); auto *output_stream = dynamic_cast(&settings.output()); ASSERT_NE(output_stream, nullptr); EXPECT_TRUE(output_stream->is_open()); *output_stream << token; output_stream->flush(); std::ifstream verify(output_path); std::string output_contents; verify >> output_contents; EXPECT_EQ(output_contents, token); } TEST(SettingsBuilder, CanOpenFileFromMovedStreams) { const auto temp_dir = std::filesystem::temp_directory_path(); const auto token = random_token(12); const auto input_path = temp_dir / std::filesystem::path("dragiyski-wavefront-parser-test-settings-input-move-" + token + ".txt"); const auto output_path = temp_dir / std::filesystem::path("dragiyski-wavefront-parser-test-settings-output-move-" + token + ".txt"); const ScopedFileCleanup input_cleanup(input_path); const ScopedFileCleanup output_cleanup(output_path); { std::ofstream seed(input_path); seed << token; } std::ifstream input_stream(input_path); std::ofstream output_stream(output_path); wavefront::SettingsBuilder builder; builder.input(std::move(input_stream)) .output(std::move(output_stream)); wavefront::Settings settings = builder.build(); EXPECT_NE(&settings.input(), &std::cin); EXPECT_NE(&settings.output(), &std::cout); auto *input_file = dynamic_cast(&settings.input()); ASSERT_NE(input_file, nullptr); EXPECT_TRUE(input_file->is_open()); std::string input_contents; *input_file >> input_contents; EXPECT_EQ(input_contents, token); auto *output_file = dynamic_cast(&settings.output()); ASSERT_NE(output_file, nullptr); EXPECT_TRUE(output_file->is_open()); *output_file << token; output_file->flush(); std::ifstream verify(output_path); std::string output_contents; verify >> output_contents; EXPECT_EQ(output_contents, token); } }