Bitcoin-Core

比特幣核心:單元測試失敗:system_tests.cpp:第 48 行 BOOST_AUTO_TEST(run_command)

  • July 5, 2021

我複製了比特幣核心並進行了建構。但是,我在 system_tests.cpp 第 48 行 BOOST_AUTO_TEST(run_command) 中遇到單元測試失敗。

首先,我的環境:

  1. 硬體:Intel i7-8550U @1.80GHz 2001 Mhz,4 核,8 個邏輯處理器,x64。
  2. 作業系統:Windows 10 家庭版
  3. 工具鏈:Visual Studios 2019 v142,配置:發布,平台 x64。

建構完成沒有錯誤,但我確實收到以下消息:

C:\Users\name\source\repos\bitcoin-first\build_msvc\test_bitcoin\test_bitcoin.vcxproj:警告:VC 項目不支持項目項中的萬用字元,並且可能導致 Visual Studio IDE 出現意外行為、不穩定和性能下降. 有關支持的選項,請參閱https://aka.ms/cpp/projectwildcards 。

執行 test_bitcoin,除了源 system_tests.cpp 第 48 行中的 run_command 之外的所有測試都通過了。我收到以下錯誤:

struct boost::process::process_error: CreateProcess failed: 系統找不到指定的文件。

VS 測試資源管理器另外提供:

未知位置(0):“run_command”中的異常:struct boost::process::process_error:CreateProcess failed:系統找不到指定的文件。system_tests.cpp(52):最後一個檢查點:

system_tests.cpp 中的相關程式碼(請忽略行號後的任何空格語法問題。我手動添加了它們,它們沒有問題):

48 BOOST_AUTO_TEST_CASE(run_command)
49 {
50    {
51        const UniValue result = RunCommandParseJSON("");
52        BOOST_CHECK(result.isNull());
53    }
54    {
55 #ifdef WIN32
56       // Windows requires single quotes to prevent escaping double quotes from the JSON...
57       // const UniValue result = RunCommandParseJSON("cmd.exe /c echo '{\"success\": true}'");
58        const UniValue result = RunCommandParseJSON("echo '{\"success\": true}'");
59   
60 #else
61        // ... but Linux and macOS echo a single quote if it's used
62        const UniValue result = RunCommandParseJSON("echo \"{\"success\": true}\"");
63 #endif
64        BOOST_CHECK(result.isObject());
65        const UniValue& success = find_value(result, "success");
66        BOOST_CHECK(!success.isNull());
67        BOOST_CHECK_EQUAL(success.getBool(), true);
68    }
69    {
70        // An invalid command is handled by Boost
71        BOOST_CHECK_EXCEPTION(RunCommandParseJSON("invalid_command"), boost::process::process_error, checkMessage); // Command failed
72    }
73    {
74        // Return non-zero exit code, no output to stderr
75        BOOST_CHECK_EXCEPTION(RunCommandParseJSON("false"), std::runtime_error, checkMessageFalse);
76    }
77    {
78        // Return non-zero exit code, with error message for stderr
79        BOOST_CHECK_EXCEPTION(RunCommandParseJSON("ls nosuchfile"), std::runtime_error, checkMessageStdErr);
80    }
81    {
82        BOOST_REQUIRE_THROW(RunCommandParseJSON("echo \"{\""), std::runtime_error); // Unable to parse JSON
83    }
84    // Test std::in, except for Windows
85 #ifndef WIN32
86    {
87        const UniValue result = RunCommandParseJSON("cat", "{\"success\": true}");
88        BOOST_CHECK(result.isObject());
89        const UniValue& success = find_value(result, "success");
90        BOOST_CHECK(!success.isNull());
91        BOOST_CHECK_EQUAL(success.getBool(), true);
92    }
93 #endif
94 }
95 #endif // HAVE_BOOST_PROCESS

第 58 行失敗。基於此<https://stackoverflow.com/questions/47028660/boost-createprocess-failed>,我註釋掉了第 58 行並添加了以下第 57 行:

57  const UniValue result = RunCommandParseJSON("cmd.exe /c echo '{\"success\": true}'");

再次執行 system_tests.cpp 讓我通過了 CreateProcess 失敗,但在 system_tests.cpp 第 48 行 run_command() 中產生了以下失敗:

類 std::runtime_error:無法解析 JSON:’{“success”: true}’。

VS Test Explorer 還指出:

未知位置(0):“run_command”中的異常:類std :: runtime_error:無法解析JSON:’{“成功”:true}‘system_tests.cpp(52):最後一個檢查點:

我很難相信測試是不正確的——我對這次失敗一無所知。相反,我懷疑我沒有在某處正確設置某些開關或選項或配置。

任何意見或幫助將不勝感激。

這是我的工作。我仍然很難相信測試程式碼需要修改,但這就是我所做的,現在測試通過了。

從上面,我更改了 RunCommandParseJSON() 的呼叫以提供命令視窗的顯式呼叫。顯然,這是 Windows 所需要的。該行變為:

57 const UniValue result = RunCommandParseJSON("cmd.exe /c echo '{\"success\": true}'");

從 /src/util/system.cpp 呼叫 RunCommandParseJSON()。它需要一個表示要啟動的子程序的字元串輸入。在這種情況下,啟動命令視窗並回顯字元串 ‘{“success”: true}’。

這產生了執行時錯誤:

class std::runtime_error: Unable to parse JSON: '{"success": true}'

注意:從 echo 命令輸出的字元串以單引號開始和結束。如程式碼的原始註釋中所述,需要單引號以避免 Windows 從 JSON 中轉義雙引號。

RunCommandParseJSON() 從 /src/univalue/lib/univalue_read.cpp 呼叫 UniValue::read()。UniValue::read(),似乎不適應字元串輸入以單引號開頭和結尾的情況。

因此,我將第 59 行從:

while (raw &lt; end && (json_isspace(*raw))) // skip whitespace

到:

while (raw &lt; end && (json_isspace(*raw) || (*raw == '\''))) // skip whitespace and skip single quote to begin and end a json string

這使得對於

const UniValue result = RunCommandParseJSON("cmd.exe /c echo '{\"success\": true}'");

run_command 測試成功的方面。

儘管如此,在進一步測試引發正確錯誤時,我在 run_command 上遇到錯誤:

  1. 沒有輸出到標準錯誤
  2. 到 stderr 的錯誤消息
  3. 無法解析 JSON 錯誤
  4. 無輸出到 stderr 案例測試您何時可以啟動命令視窗程序,但給出的命令無效。此測試已修改為允許正確呼叫 Window 的命令視窗,更改為:

BOOST_CHECK_EXCEPTION(RunCommandParseJSON("false"), std::runtime_error, checkMessageFalse);

到:

BOOST_CHECK_EXCEPTION(RunCommandParseJSON("cmd.exe /c false"), std::runtime_error, checkMessageFalse);

這產生了所需的錯誤,但不是測試要求的確切錯誤消息。我將支票更改為:

const std::string what(ex.what()); BOOST_CHECK(what.find("returned 1") != std::string::npos);

  1. 到 Stderr 的錯誤消息測試是否能夠啟動命令視窗程序,接收有效命令,但輸入無效。這是從:

BOOST_CHECK_EXCEPTION(RunCommandParseJSON("ls nosuchfile"), std::runtime_error, checkMessageStdErr);

到:

BOOST_CHECK_EXCEPTION(RunCommandParseJSON("cmd.exe /c dir nosuchfile"), std::runtime_error, checkMessageStdErr);

複製我所看到的 Window 版本的測試。

  1. Unable to ParseJSON 錯誤測試是否能夠啟動命令視窗程序、發送具有有效輸入的有效命令,但無法解析字元串。(這個錯誤實際上很早就遇到了。)這被改為:

BOOST_REQUIRE_THROW(RunCommandParseJSON("cmd.exe /c echo '{'"), std::runtime_error); // Unable to parse JSON

通過這些更改,所有單元測試現在都通過了。

我沒有看到這些變化改變了測試的性質。如果有人注意到他們這樣做,我絕對會很感激被告知。

也許以下將起作用。

RunCommandParseJSON("cmd.exe", "/c echo '{\"success\": true}'");

引用自:https://bitcoin.stackexchange.com/questions/105167