比特幣核心:單元測試失敗:system_tests.cpp:第 48 行 BOOST_AUTO_TEST(run_command)
我複製了比特幣核心並進行了建構。但是,我在 system_tests.cpp 第 48 行 BOOST_AUTO_TEST(run_command) 中遇到單元測試失敗。
首先,我的環境:
- 硬體:Intel i7-8550U @1.80GHz 2001 Mhz,4 核,8 個邏輯處理器,x64。
- 作業系統:Windows 10 家庭版
- 工具鏈: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 < end && (json_isspace(*raw))) // skip whitespace
到:
while (raw < 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 上遇到錯誤:
- 沒有輸出到標準錯誤
- 到 stderr 的錯誤消息
- 無法解析 JSON 錯誤
- 無輸出到 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);
- 到 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 版本的測試。
- 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}'");