From 058461bcea6065c16db0b1204cbc5aa4e336cb5d Mon Sep 17 00:00:00 2001 From: Tommy Nguyen <4123478+tido64@users.noreply.github.com> Date: Tue, 16 Mar 2021 08:32:03 +0100 Subject: [PATCH] fix(windows): unhandled exception thrown in std::_Xlen_string() (#288) Current working directory when running tests (with `VSTest.Console.exe`) changed between Visual Studio 16.8 and 16.9 and broke our pipelines. To prevent future build failures, we'll use the absolute path to the test source file to build the path to the test fixtures. --- .github/workflows/build.yml | 2 +- .../ReactTestAppTests/ManifestTests.cpp | 20 +++++++++++++++--- windows/ReactTestApp/Manifest.cpp | 21 ++++++++++--------- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 102efc78d..f74b5bbe1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -368,7 +368,7 @@ jobs: steps: - name: Set up MSBuild uses: microsoft/setup-msbuild@v1.0.2 - - name: Setup VSTest.console.exe + - name: Set up VSTest.console.exe uses: darenm/Setup-VSTest@v1 - name: Set up Node.js uses: actions/setup-node@v1 diff --git a/example/windows/ReactTestAppTests/ManifestTests.cpp b/example/windows/ReactTestAppTests/ManifestTests.cpp index de641b9e5..30e0b928f 100644 --- a/example/windows/ReactTestAppTests/ManifestTests.cpp +++ b/example/windows/ReactTestAppTests/ManifestTests.cpp @@ -8,6 +8,7 @@ #include "pch.h" #include +#include #include #include "Manifest.h" @@ -17,6 +18,19 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; using ReactTestApp::Component; using ReactTestApp::Manifest; +std::string fixturePath(std::filesystem::path file) +{ + // Current working directory when running tests (with VSTest.Console.exe) + // changed between Visual Studio 16.8 and 16.9 and broke our pipelines. To + // prevent future build failures, we'll use the absolute path to this + // source file to build the path to the test fixtures. + // + // To ensure that `__FILE__` is a full path, we must also enable `/FC` in + // Properties > C/C++ > Advanced. + const auto p = std::filesystem::path(__FILE__).replace_filename("manifestTestFiles") / file; + return p.string(); +} + // disable clang-format because it doesn't handle macros very well // clang-format off namespace ReactTestAppTests @@ -26,7 +40,7 @@ namespace ReactTestAppTests public: TEST_METHOD(ParseManifestWithOneComponent) { - auto result = ReactTestApp::GetManifest("manifestTestFiles/simpleManifest.json"); + auto result = ReactTestApp::GetManifest(fixturePath("simpleManifest.json")); if (!result.has_value()) { Assert::Fail(L"Couldn't read manifest file"); } @@ -42,7 +56,7 @@ namespace ReactTestAppTests TEST_METHOD(ParseManifestWithMultipleComponents) { - auto result = ReactTestApp::GetManifest("manifestTestFiles/withMultipleComponents.json"); + auto result = ReactTestApp::GetManifest(fixturePath("withMultipleComponents.json")); if (!result.has_value()) { Assert::Fail(L"Couldn't read manifest file"); } @@ -67,7 +81,7 @@ namespace ReactTestAppTests TEST_METHOD(ParseManifestWithComplexInitialProperties) { - auto result = ReactTestApp::GetManifest("manifestTestFiles/withComplexInitialProperties.json"); + auto result = ReactTestApp::GetManifest(fixturePath("withComplexInitialProperties.json")); if (!result.has_value()) { Assert::Fail(L"Couldn't read manifest file"); } diff --git a/windows/ReactTestApp/Manifest.cpp b/windows/ReactTestApp/Manifest.cpp index 537b905aa..6cae38f2a 100644 --- a/windows/ReactTestApp/Manifest.cpp +++ b/windows/ReactTestApp/Manifest.cpp @@ -9,8 +9,7 @@ #include "Manifest.h" -#include -#include +#include #include #include @@ -116,16 +115,18 @@ namespace ReactTestApp std::optional> GetManifest(std::string const &filename) { - std::string json; - { - std::ifstream stream(filename); + std::FILE *stream = nullptr; + if (fopen_s(&stream, filename.c_str(), "rb") != 0) { + return std::nullopt; + } - stream.seekg(0, std::ios::end); - json.reserve(static_cast(stream.tellg())); + std::string json; + std::fseek(stream, 0, SEEK_END); + json.resize(std::ftell(stream)); - stream.seekg(0, std::ios::beg); - json.assign(std::istreambuf_iterator(stream), {}); - } + std::rewind(stream); + std::fread(json.data(), 1, json.size(), stream); + std::fclose(stream); auto j = nlohmann::json::parse(json, nullptr, false); if (j.is_discarded()) {