diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 1c69a17..1bd3a78 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -27,7 +27,7 @@ jobs: run: sudo apt-get update -qy && sudo apt-get install gcovr -qy - name: configure - run: cmake -DBUILD_TESTING=on -DPATCH_ENABLE_COVERAGE=yes -S . -B build + run: cmake -DBUILD_TESTING=on -DPATCH_ENABLE_COVERAGE=yes -DPATCH_WARNINGS_AS_ERRORS=on -S . -B build - name: compile run: cmake --build build -j2 - name: test @@ -49,7 +49,7 @@ jobs: steps: - uses: actions/checkout@v6 - name: configure - run: cmake -DBUILD_TESTING=on -S . -B build + run: cmake -DBUILD_TESTING=on -DPATCH_WARNINGS_AS_ERRORS=on -S . -B build - name: compile run: cmake --build build -j2 - name: test @@ -73,7 +73,7 @@ jobs: mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-ninja - name: configure - run: cmake -G Ninja -DBUILD_TESTING=on -S . -B build + run: cmake -G Ninja -DBUILD_TESTING=on -DPATCH_WARNINGS_AS_ERRORS=on -S . -B build - name: compile run: cmake --build build -j2 - name: test diff --git a/.github/workflows/msvc.yml b/.github/workflows/msvc.yml index 140f26a..fd91eed 100644 --- a/.github/workflows/msvc.yml +++ b/.github/workflows/msvc.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@v6 - name: Configure CMake - run: cmake -B ${{ env.build }} -DCMAKE_BUILD_TYPE=${{ env.config }} + run: cmake -B ${{ env.build }} -DCMAKE_BUILD_TYPE=${{ env.config }} -DPATCH_WARNINGS_AS_ERRORS=on - name: Initialize MSVC Code Analysis uses: microsoft/msvc-code-analysis-action@v0.1.1 diff --git a/CMakeLists.txt b/CMakeLists.txt index f365d3b..20680d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,41 @@ include(GNUInstallDirs) include(coverage) option(PATCH_ENABLE_COVERAGE "Build with gcov support" OFF) +option(PATCH_WARNINGS_AS_ERRORS "Enable strict compiler warnings and treat them as errors" OFF) option(BUILD_TESTING "Build the tests" OFF) +function(patch_configure_target target_name) + if(WIN32) + target_compile_definitions(${target_name} PRIVATE + NOMINMAX + WIN32_LEAN_AND_MEAN + ) + endif() + + if(NOT PATCH_WARNINGS_AS_ERRORS) + return() + endif() + + if(MSVC) + target_compile_options(${target_name} PRIVATE /W4 /WX) + target_compile_definitions(${target_name} PRIVATE + _CRT_NONSTDC_NO_WARNINGS + _CRT_SECURE_NO_WARNINGS + ) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "^(AppleClang|Clang|GNU)$") + target_compile_options(${target_name} PRIVATE + -Wall + -Wextra + -Wpedantic + -Wconversion + -Wsign-conversion + -Werror + ) + else() + message(FATAL_ERROR "PATCH_WARNINGS_AS_ERRORS does not support ${CMAKE_CXX_COMPILER_ID}") + endif() +endfunction() + if(PATCH_ENABLE_COVERAGE) add_coverage_flags() endif() @@ -39,6 +72,7 @@ add_library(patch src/system.cpp src/file.cpp ) +patch_configure_target(patch) target_compile_features(patch PUBLIC cxx_std_11) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 35f57c6..5379870 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -2,6 +2,7 @@ # Copyright 2022 Shannon Booth add_executable(sb_patch main.cpp) +patch_configure_target(sb_patch) target_link_libraries(sb_patch PRIVATE patch::patch) install(TARGETS sb_patch diff --git a/include/patch/applier.h b/include/patch/applier.h index 0f5326a..d7ce2d3 100644 --- a/include/patch/applier.h +++ b/include/patch/applier.h @@ -24,19 +24,19 @@ class RejectWriter { void write_reject_file(const Hunk& hunk); - int rejected_hunks() const { return m_rejected_hunks; } + size_t rejected_hunks() const { return m_rejected_hunks; } private: bool should_write_as_unified() const; const Patch& m_patch; - int m_rejected_hunks { 0 }; + size_t m_rejected_hunks { 0 }; File& m_reject_file; Options::RejectFormat m_reject_format { Options::RejectFormat::Default }; }; struct Result { - int failed_hunks; + size_t failed_hunks; bool was_skipped; bool all_hunks_applied_perfectly; }; diff --git a/src/cmdline.cpp b/src/cmdline.cpp index 1fa2669..95b5731 100644 --- a/src/cmdline.cpp +++ b/src/cmdline.cpp @@ -2,6 +2,7 @@ // Copyright 2022-2023 Shannon Booth #include +#include #include #include #include @@ -11,6 +12,9 @@ #ifdef _WIN32 # include + +// shellapi.h depends on types and macros declared by windows.h. +# include #endif namespace Patch { @@ -29,8 +33,9 @@ CmdLine::CmdLine(int argc, const char* const* argv) if (!wide_argv) throw std::bad_alloc(); - narrowed_argv_str.reserve(m_argc); - narrowed_argv.reserve(m_argc); + const auto argument_count = static_cast(m_argc); + narrowed_argv_str.reserve(argument_count); + narrowed_argv.reserve(argument_count); for (int i = 0; i < m_argc; ++i) { narrowed_argv_str.emplace_back(to_narrow(wide_argv[i])); diff --git a/src/parser.cpp b/src/parser.cpp index 3c3a15b..7b332a5 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -124,20 +124,23 @@ std::string LineParser::parse_quoted_string() case '5': case '6': case '7': { - unsigned char result = static_cast(c) - '0'; + unsigned int result = static_cast(c - '0'); for (int i = 1; i < 3; ++i) { char octal_val = peek(); if (!is_octal(octal_val)) break; - unsigned char digit_val = static_cast(octal_val) - '0'; - result = result * 8 + digit_val; + unsigned int digit_val = static_cast(octal_val - '0'); + result = result * 8U + digit_val; ++m_current; } - output += static_cast(result); + if (result > static_cast(std::numeric_limits::max())) + throw std::invalid_argument("Octal escape is out of range in path " + std::string(begin, m_current)); + + output += static_cast(static_cast(result)); break; } default: @@ -807,7 +810,7 @@ void Parser::parse_context_hunk(std::vector& old_lines, LineNumber& o { std::string line; - LineNumber from_file_range_line_number = 0; + size_t from_file_range_line_number = 0; LineNumber old_end_line = 0; LineNumber new_end_line = 0; diff --git a/src/system.cpp b/src/system.cpp index d71443e..fefe012 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -20,9 +20,9 @@ #include #ifdef _WIN32 +# include "windows_error.h" # include # include -# include # define close _close # define read _read # define open _open @@ -79,7 +79,14 @@ std::string read_tty_until_enter() size_t offset = 0; while (true) { - auto ret = ::read(fd, &buffer[0] + offset, buffer.size() - offset); + const auto available_size = buffer.size() - offset; +#ifdef _WIN32 + const auto read_size = std::min(available_size, static_cast(INT_MAX)); + auto ret = ::read(fd, &buffer[0] + offset, static_cast(read_size)); +#else + const auto read_size = available_size; + auto ret = ::read(fd, &buffer[0] + offset, read_size); +#endif if (ret < 0) { int saved_errno = errno; ::close(fd); @@ -88,7 +95,7 @@ std::string read_tty_until_enter() // Finish if we didn't read up until the end of our buffer, indicating input has finished, or // if the last character given was an enter which means that the user has submitted their answer. - if (buffer.size() - offset != static_cast(ret) || buffer.back() == '\n') { + if (read_size != static_cast(ret) || buffer.back() == '\n') { // Trim to size, any pop any trailing '\n' since that is not part of their answer. buffer.resize(offset + static_cast(ret)); if (!buffer.empty() && buffer.back() == '\n') @@ -187,7 +194,7 @@ std::string current_path() const auto size = GetCurrentDirectoryW(requested_size, &result[0]); if (size == 0) - throw std::system_error(GetLastError(), std::system_category(), "Failed getting current directory"); + throw last_win32_error("Failed getting current directory"); result.resize(size); if (size <= requested_size) @@ -310,7 +317,7 @@ std::string temp_directory_path() const auto size = GetTempPathW(requested_size, &result[0]); if (size == 0) - throw std::system_error(GetLastError(), std::system_category(), "Failed getting current directory"); + throw last_win32_error("Failed getting current directory"); result.resize(size); if (size <= requested_size) @@ -372,7 +379,7 @@ void symlink(const std::string& target, const std::string& linkpath) error = GetLastError(); } - throw std::system_error(error, std::system_category(), "Can't create symbolic link " + target + " "); + throw win32_error(error, "Can't create symbolic link " + target + " "); #else int ret = ::symlink(target.c_str(), linkpath.c_str()); if (ret != 0) @@ -511,19 +518,23 @@ void rename(const std::string& old_path, const std::string& new_path) const DWORD attributes = GetFileAttributesW(native_new_path.c_str()); if (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_READONLY)) { const DWORD writable_attributes = attributes & ~static_cast(FILE_ATTRIBUTE_READONLY); - if (SetFileAttributesW(native_new_path.c_str(), writable_attributes) == 0) - throw std::system_error(GetLastError(), std::system_category(), "Unable to make file writable " + new_path); + if (SetFileAttributesW(native_new_path.c_str(), writable_attributes) == 0) { + const auto attributes_error = GetLastError(); + throw win32_error(attributes_error, "Unable to make file writable " + new_path); + } if (MoveFileExW(native_old_path.c_str(), native_new_path.c_str(), MOVEFILE_REPLACE_EXISTING) != 0) return; error = GetLastError(); - if (SetFileAttributesW(native_new_path.c_str(), attributes) == 0) - throw std::system_error(GetLastError(), std::system_category(), "Unable to restore permissions to " + new_path); + if (SetFileAttributesW(native_new_path.c_str(), attributes) == 0) { + const auto attributes_error = GetLastError(); + throw win32_error(attributes_error, "Unable to restore permissions to " + new_path); + } } } - throw std::system_error(error, std::system_category(), "Unable to rename " + old_path + " to " + new_path); + throw win32_error(error, "Unable to rename " + old_path + " to " + new_path); #else if (std::rename(old_path.c_str(), new_path.c_str()) != 0) throw std::system_error(errno, std::generic_category(), "Unable to rename " + old_path + " to " + new_path); @@ -539,8 +550,10 @@ void permissions(const std::string& path, perms permissions) const auto native = to_native(path); DWORD attributes = GetFileAttributesW(native.c_str()); - if (attributes == INVALID_FILE_ATTRIBUTES) - throw std::system_error(GetLastError(), std::system_category(), "Unable to set permissions to " + path); + if (attributes == INVALID_FILE_ATTRIBUTES) { + const auto attributes_error = GetLastError(); + throw win32_error(attributes_error, "Unable to set permissions to " + path); + } // No group/owner/all on Windows - if any are set treat as write permissions. const auto write_perms = perms::owner_write | perms::group_write | perms::others_write; @@ -554,10 +567,12 @@ void permissions(const std::string& path, perms permissions) if (should_be_read_only) attributes |= FILE_ATTRIBUTE_READONLY; else - attributes &= ~FILE_ATTRIBUTE_READONLY; + attributes &= ~static_cast(FILE_ATTRIBUTE_READONLY); - if (SetFileAttributesW(native.c_str(), attributes) == 0) - throw std::system_error(GetLastError(), std::system_category(), "Unable to set permissions to " + path); + if (SetFileAttributesW(native.c_str(), attributes) == 0) { + const auto attributes_error = GetLastError(); + throw win32_error(attributes_error, "Unable to set permissions to " + path); + } #else if (::chmod(path.c_str(), static_cast(permissions)) != 0) @@ -600,7 +615,7 @@ void permissions(FILE* file, perms permissions) FILE_BASIC_INFO info; if (GetFileInformationByHandleEx(handle, FileBasicInfo, &info, sizeof(info)) == 0) - throw std::system_error(GetLastError(), std::system_category(), "Unable to change permissions"); + throw last_win32_error("Unable to change permissions"); const auto write_permissions = perms::owner_write | perms::group_write | perms::others_write; if ((permissions & write_permissions) == perms::none) @@ -609,7 +624,7 @@ void permissions(FILE* file, perms permissions) info.FileAttributes &= ~static_cast(FILE_ATTRIBUTE_READONLY); if (SetFileInformationByHandle(handle, FileBasicInfo, &info, sizeof(info)) == 0) - throw std::system_error(GetLastError(), std::system_category(), "Unable to change permissions"); + throw last_win32_error("Unable to change permissions"); #else if (::fchmod(fileno(file), static_cast(permissions)) != 0) throw std::system_error(errno, std::generic_category(), "Unable to change permissions"); @@ -625,7 +640,7 @@ perms get_permissions(FILE* file) FILE_BASIC_INFO info; if (GetFileInformationByHandleEx(handle, FileBasicInfo, &info, sizeof(info)) == 0) - throw std::system_error(GetLastError(), std::system_category(), "Unable to get permissions"); + throw last_win32_error("Unable to get permissions"); perms permissions = perms::owner_read | perms::group_read | perms::others_read; if (!(info.FileAttributes & FILE_ATTRIBUTE_READONLY)) @@ -647,7 +662,10 @@ uintmax_t file_size(FILE* file) if (fstat(fileno(file), &buf) != 0) throw std::system_error(errno, std::generic_category(), "Unable to fstat file"); - return buf.st_size; + if (buf.st_size < 0) + throw std::system_error(std::make_error_code(std::errc::invalid_argument), "File has a negative size"); + + return static_cast(buf.st_size); } } // namespace filesystem @@ -661,14 +679,14 @@ std::wstring to_wide(const std::string& str) int length = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), nullptr, 0); if (length == 0) - throw std::system_error(GetLastError(), std::system_category(), "Failed widening string"); + throw last_win32_error("Failed widening string"); std::wstring wide_str; wide_str.resize(static_cast(length)); length = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), &wide_str[0], length); if (length == 0) - throw std::system_error(GetLastError(), std::system_category(), "Failed widening string"); + throw last_win32_error("Failed widening string"); return wide_str; } @@ -680,14 +698,14 @@ std::string to_narrow(const std::wstring& str) int length = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), static_cast(str.size()), nullptr, 0, nullptr, nullptr); if (length == 0) - throw std::system_error(GetLastError(), std::system_category(), "Failed narrowing string"); + throw last_win32_error("Failed narrowing string"); std::string narrow_str; narrow_str.resize(static_cast(length)); length = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), static_cast(str.size()), &narrow_str[0], length, nullptr, nullptr); if (length == 0) - throw std::system_error(GetLastError(), std::system_category(), "Failed narrowing string"); + throw last_win32_error("Failed narrowing string"); return narrow_str; } diff --git a/src/windows_error.h b/src/windows_error.h new file mode 100644 index 0000000..32c53c0 --- /dev/null +++ b/src/windows_error.h @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright 2026 Shannon Booth + +#pragma once + +#include +#include +#include + +namespace Patch { + +inline std::error_code win32_error_code(DWORD error) +{ + return { static_cast(error), std::system_category() }; +} + +class win32_error : public std::system_error { +public: + win32_error(DWORD error, const std::string& message) + : std::system_error(win32_error_code(error), message) + { + } +}; + +class last_win32_error : public win32_error { +public: + explicit last_win32_error(const char* message) + : win32_error(GetLastError(), message) + { + } +}; + +} // namespace Patch diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7dbccac..76c372f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -13,12 +13,14 @@ unset(CMAKE_REQUIRED_LIBRARIES) configure_file(lib/src/config.h.in lib/src/config.h) add_library(patch_test lib/src/test.cpp) +patch_configure_target(patch_test) target_link_libraries(patch_test PUBLIC patch) target_include_directories(patch_test PUBLIC lib/include PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/lib/src + ${PROJECT_SOURCE_DIR}/src ) find_program(GNU_PATCH patch) @@ -82,9 +84,11 @@ add_executable(patch_oom ${PROJECT_SOURCE_DIR}/src/options.cpp ${PROJECT_SOURCE_DIR}/app/main.cpp ) +patch_configure_target(patch_oom) target_include_directories(patch_oom PRIVATE ${PROJECT_SOURCE_DIR}/include) add_executable(test_oom test_oom.cpp) +patch_configure_target(test_oom) target_link_libraries(test_oom PRIVATE patch_test) patch_add_tests(test_oom patch_oom) @@ -108,6 +112,7 @@ add_executable(patch_tests test_reject.cpp test_strip.cpp ) +patch_configure_target(patch_tests) target_link_libraries(patch_tests PRIVATE patch_test) if(HAVE_FORKPTY_PTY OR HAVE_FORKPTY_UTIL) diff --git a/tests/lib/include/patch/test.h b/tests/lib/include/patch/test.h index 4a3d151..1918d4e 100644 --- a/tests/lib/include/patch/test.h +++ b/tests/lib/include/patch/test.h @@ -41,7 +41,8 @@ inline std::string escaped_string_for_test_output(const std::string& value) std::ostringstream out; out << '"'; - for (unsigned char c : value) { + for (char c : value) { + const auto byte = static_cast(c); switch (c) { case '\\': out << "\\\\"; @@ -59,10 +60,10 @@ inline std::string escaped_string_for_test_output(const std::string& value) out << "\\t"; break; default: - if (c >= 0x20 && c < 0x7f) { - out << static_cast(c); + if (byte >= 0x20 && byte < 0x7f) { + out << c; } else { - out << "\\x" << std::hex << std::setw(2) << std::setfill('0') << static_cast(c) << std::dec; + out << "\\x" << std::hex << std::setw(2) << std::setfill('0') << static_cast(byte) << std::dec; } break; } diff --git a/tests/lib/src/test.cpp b/tests/lib/src/test.cpp index cff19d8..225600c 100644 --- a/tests/lib/src/test.cpp +++ b/tests/lib/src/test.cpp @@ -10,7 +10,7 @@ #ifdef _WIN32 # include # include -# include +# include #else # include #endif @@ -52,7 +52,7 @@ void skip_without_symlink_support() filesystem::symlink("target", "symlink-support-probe"); filesystem::remove("symlink-support-probe"); } catch (const std::system_error& error) { - if (error.code() != std::error_code(ERROR_PRIVILEGE_NOT_HELD, std::system_category())) + if (error.code() != win32_error_code(ERROR_PRIVILEGE_NOT_HELD)) throw; skip_test("creating a symbolic link requires a privilege this environment does not grant"); } diff --git a/tests/lib/src/unix_process.cpp b/tests/lib/src/unix_process.cpp index 1f4773e..0e2a575 100644 --- a/tests/lib/src/unix_process.cpp +++ b/tests/lib/src/unix_process.cpp @@ -140,7 +140,7 @@ Process::Process(const char* cmd, const std::vector& args, const st if (fds.empty()) break; - int poll_result = ::poll(fds.data(), fds.size(), 5000); + int poll_result = ::poll(fds.data(), static_cast(fds.size()), 5000); if (poll_result < 0) throw std::system_error(errno, std::generic_category(), "Poll failed waiting for data"); diff --git a/tests/lib/src/windows_process.cpp b/tests/lib/src/windows_process.cpp index c92daa5..695f5ba 100644 --- a/tests/lib/src/windows_process.cpp +++ b/tests/lib/src/windows_process.cpp @@ -5,24 +5,24 @@ #include #include #include -#include +#include class Pipe { public: explicit Pipe(bool inherit_for_read = true) { SECURITY_ATTRIBUTES attr; - attr.nLength = sizeof(SECURITY_ATTRIBUTES); + attr.nLength = static_cast(sizeof(SECURITY_ATTRIBUTES)); attr.bInheritHandle = true; attr.lpSecurityDescriptor = nullptr; if (!CreatePipe(&m_read_handle, &m_write_handle, &attr, 0)) - throw std::system_error(GetLastError(), std::system_category(), "Failed creating stdout pipe"); + throw Patch::last_win32_error("Failed creating stdout pipe"); if (!SetHandleInformation(inherit_for_read ? m_read_handle : m_write_handle, HANDLE_FLAG_INHERIT, 0)) { CloseHandle(m_read_handle); CloseHandle(m_write_handle); - throw std::system_error(GetLastError(), std::system_category(), "Failed setting handle information"); + throw Patch::last_win32_error("Failed setting handle information"); } } @@ -115,7 +115,7 @@ Process::Process(const char* cmd, const std::vector& args, const st PROCESS_INFORMATION process_info {}; STARTUPINFOW start_info {}; - start_info.cb = sizeof(start_info); + start_info.cb = static_cast(sizeof(start_info)); start_info.hStdOutput = stdout_pipe.write_handle(); start_info.hStdError = stderr_pipe.write_handle(); start_info.hStdInput = stdin_pipe.read_handle(); @@ -136,7 +136,7 @@ Process::Process(const char* cmd, const std::vector& args, const st &process_info); // receives PROCESS_INFORMATION if (ret == 0) - throw std::system_error(GetLastError(), std::system_category(), "Failed creating process"); + throw Patch::last_win32_error("Failed creating process"); stdout_pipe.close_write_handle(); stderr_pipe.close_write_handle(); @@ -167,7 +167,7 @@ Process::Process(const char* cmd, const std::vector& args, const st CloseHandle(process_info.hThread); if (ret == 0) - throw std::system_error(GetLastError(), std::system_category(), "Failed getting process exit code"); + throw Patch::last_win32_error("Failed getting process exit code"); - m_return_code = exit_code; + m_return_code = static_cast(exit_code); } diff --git a/tests/test_basic.cpp b/tests/test_basic.cpp index b5408c1..3894bbf 100644 --- a/tests/test_basic.cpp +++ b/tests/test_basic.cpp @@ -2485,8 +2485,8 @@ new mode 100755 EXPECT_EQ(process.return_code(), 0); EXPECT_FILE_EQ("file", to_patch); - const auto perms = Patch::filesystem::get_permissions("file"); #ifndef _WIN32 + const auto perms = Patch::filesystem::get_permissions("file"); EXPECT_TRUE((perms & Patch::filesystem::perms::owner_exec) != Patch::filesystem::perms::none); EXPECT_TRUE((perms & Patch::filesystem::perms::group_exec) != Patch::filesystem::perms::none); EXPECT_TRUE((perms & Patch::filesystem::perms::others_exec) != Patch::filesystem::perms::none); @@ -2876,7 +2876,9 @@ COMPAT_TEST(reversed_patch_batch) COMPAT_TEST(basic_add_symlink_file) { -#ifndef _WIN32 +#ifdef _WIN32 + (void)patch_path; +#else { Patch::File file("diff.patch", std::ios_base::out); diff --git a/tests/test_quoting.cpp b/tests/test_quoting.cpp index c5685c1..1b22e30 100644 --- a/tests/test_quoting.cpp +++ b/tests/test_quoting.cpp @@ -60,7 +60,9 @@ COMPAT_TEST(quoting_c_style_single_quote) COMPAT_TEST(quoting_c_style_double_quote) { -#ifndef _WIN32 +#ifdef _WIN32 + (void)patch_path; +#else Patch::set_env("QUOTING_STYLE", "c"); test_quoting(patch_path, "with\"quote", "patching file \"with\\\"quote\"\n"); #endif @@ -68,7 +70,9 @@ COMPAT_TEST(quoting_c_style_double_quote) COMPAT_TEST(quoting_c_style_backslash) { -#ifndef _WIN32 +#ifdef _WIN32 + (void)patch_path; +#else Patch::set_env("QUOTING_STYLE", "c"); test_quoting(patch_path, "with\\slash", "patching file \"with\\\\slash\"\n"); #endif @@ -76,7 +80,9 @@ COMPAT_TEST(quoting_c_style_backslash) COMPAT_TEST(quoting_c_style_newline) { -#ifndef _WIN32 +#ifdef _WIN32 + (void)patch_path; +#else Patch::set_env("QUOTING_STYLE", "c"); test_quoting(patch_path, "with\nnewline", R"("with\nnewline")", "patching file \"with\\nnewline\"\n"); #endif @@ -84,7 +90,9 @@ COMPAT_TEST(quoting_c_style_newline) COMPAT_TEST(quoting_c_style_tab) { -#ifndef _WIN32 +#ifdef _WIN32 + (void)patch_path; +#else Patch::set_env("QUOTING_STYLE", "c"); test_quoting(patch_path, "with\ttab", R"("with\ttab")", "patching file \"with\\ttab\"\n"); #endif @@ -104,7 +112,9 @@ COMPAT_TEST(quoting_shell_always_style_single_quote_only) COMPAT_TEST(quoting_shell_always_style_double_quote_only) { -#ifndef _WIN32 +#ifdef _WIN32 + (void)patch_path; +#else Patch::set_env("QUOTING_STYLE", "shell-always"); test_quoting(patch_path, "with\"quote", "patching file 'with\"quote'\n"); #endif @@ -112,7 +122,9 @@ COMPAT_TEST(quoting_shell_always_style_double_quote_only) COMPAT_TEST(quoting_shell_style_double_quote_only) { -#ifndef _WIN32 +#ifdef _WIN32 + (void)patch_path; +#else Patch::set_env("QUOTING_STYLE", "shell"); test_quoting(patch_path, "with\"quote", "patching file 'with\"quote'\n"); #endif diff --git a/tests/test_strip.cpp b/tests/test_strip.cpp index 181d240..14ab5e6 100644 --- a/tests/test_strip.cpp +++ b/tests/test_strip.cpp @@ -109,6 +109,7 @@ TEST(strip_quoted_string_bad) EXPECT_THROW(parse_file_line("\"path/with unterminated comma", -1, path), std::invalid_argument); EXPECT_THROW(parse_file_line("\"secondUnterminatedCommaButAfterBackslash\\", -1, path), std::invalid_argument); EXPECT_THROW(parse_file_line("\"badEscapeChar\\l\"", -1, path), std::invalid_argument); + EXPECT_THROW(parse_file_line(R"("\400")", -1, path), std::invalid_argument); } TEST(strip_quoted_string_good)