我正在编写一个单元测试,它似乎存在某种指针问题。基本上,它是在测试一个类,该类一旦构建,就会返回有关文件的信息。如果检测到所有预期的文件,则测试正常运行。如果预期的文件多于检测到的文件,则例程会正确报告错误。但是,如果检测到的文件多于预期,则可执行文件会崩溃。这很难遵循,因为当我尝试使用调试器单步执行时,当前代码点会跳过整个方法——它不会像您期望的那样逐行执行。
关于我做错了什么有什么想法吗?
这是我的代码:
#include "stdafx.h"
#include "boostUnitTest.h"
#include "../pevFind/fileData.h" //Header file for tested code.
#include "../pevFind/stringUtil.h" //convertUnicode()
struct fileDataLoadingFixture
{
std::vector<fileData> testSuiteCandidates;
fileDataLoadingFixture()
{
WIN32_FIND_DATA curFileData;
HANDLE fData = FindFirstFile(L"testFiles\\*", &curFileData);
if (fData == INVALID_HANDLE_VALUE)
throw std::runtime_error("Failed to load file list!");
do {
if(boost::algorithm::equals(curFileData.cFileName, L".")) continue;
if(boost::algorithm::equals(curFileData.cFileName, L"..")) continue;
fileData theFile(curFileData, L".\\testFiles\\");
testSuiteCandidates.push_back(theFile);
} while (FindNextFile(fData, &curFileData));
FindClose(fData);
};
};
BOOST_FIXTURE_TEST_SUITE( fileDataTests, fileDataLoadingFixture )
BOOST_AUTO_TEST_CASE( testPEData )
{
std::vector<std::wstring> expectedResults;
expectedResults.push_back(L"a.cfexe");
expectedResults.push_back(L"b.cfexe");
//More files....
expectedResults.push_back(L"c.cfexe");
std::sort(expectedResults.begin(), expectedResults.end());
for (std::vector<fileData>::const_iterator it = testSuiteCandidates.begin(); it != testSuiteCandidates.end(); it++)
{
if (it->isPE())
{
std::wstring theFileString(it->getFileName().substr(it->getFileName().find_last_of(L'\\') + 1 ));
std::vector<std::wstring>::const_iterator target = std::lower_bound(expectedResults.begin(), expectedResults.end(), theFileString);
BOOST_REQUIRE_MESSAGE(*target == theFileString, std::string("The file ") + convertUnicode(theFileString) + " was unexpected." );
if (*target == theFileString)
{
expectedResults.erase(target);
}
}
}
BOOST_CHECK_MESSAGE(expectedResults.size() == 0, "Some expected results were not found." );
}
BOOST_AUTO_TEST_SUITE_END()
谢谢!
比利3
我使用以下代码解决了这个问题:
BOOST_AUTO_TEST_CASE( testPEData )
{
std::vector<std::wstring> expectedResults;
expectedResults.push_back(L"blah.cfexe");
//files
expectedResults.push_back(L"tail.cfexe");
expectedResults.push_back(L"zip.cfexe");
std::vector<std::wstring> actualResults;
for(std::vector<fileData>::const_iterator it = testSuiteCandidates.begin(); it != testSuiteCandidates.end(); it++)
{
if (it->isPE()) actualResults.push_back(it->getFileName().substr(it->getFileName().find_last_of(L'\\') + 1 ));
}
std::sort(expectedResults.begin(), expectedResults.end());
std::sort(actualResults.begin(), actualResults.end());
std::vector<std::wstring> missed;
std::set_difference(expectedResults.begin(), expectedResults.end(), actualResults.begin(), actualResults.end(), std::back_inserter(missed));
std::vector<std::wstring> incorrect;
std::set_difference(actualResults.begin(), actualResults.end(), expectedResults.begin(), expectedResults.end(), std::back_inserter(incorrect));
for(std::vector<std::wstring>::const_iterator it = missed.begin(); it != missed.end(); it++)
{
BOOST_ERROR(std::string("The file ") + convertUnicode(*it) + " was expected but not returned.");
}
for(std::vector<std::wstring>::const_iterator it = incorrect.begin(); it != incorrect.end(); it++)
{
BOOST_ERROR(std::string("The file ") + convertUnicode(*it) + " was returned but not expected.");
}
BOOST_CHECK(true); //Suppress commandline "No assertions" warning
}
最佳答案
如果文件是意外的,你认为这会返回什么?看起来您希望它是一个有效的文件名。
std::vector<std::wstring>::const_iterator target = std::lower_bound(expectedResults.begin(), expectedResults.end(), theFileString);
它实际上是数组末尾之后的一个迭代器——你不能把它当作一个有效的指针:
BOOST_REQUIRE_MESSAGE(*target == theFileString, std::string("The file ") + convertUnicode(theFileString) + " was unexpected." );
正常,你将结果与end()
的值进行比较(固定):
BOOST_REQUIRE_MESSAGE(target != expectedResults.end() || *target == theFileString, std::string("The file ") + convertUnicode(theFileString) + " was unexpected." );
if (target != expectedResults.end() && *target == theFileString)
{
expectedResults.erase(target);
}
参见this example here , lower_bound
将返回 off-then-end 值:
int main()
{
int A[] = { 1, 2, 3, 3, 3, 5, 8 };
const int N = sizeof(A) / sizeof(int);
for (int i = 1; i <= 10; ++i) {
int* p = lower_bound(A, A + N, i);
cout << "Searching for " << i << ". ";
cout << "Result: index = " << p - A << ", ";
if (p != A + N)
cout << "A[" << p - A << "] == " << *p << endl;
else
cout << "which is off-the-end." << endl;
}
}
The output is:
Searching for 1. Result: index = 0, A[0] == 1
Searching for 2. Result: index = 1, A[1] == 2
Searching for 3. Result: index = 2, A[2] == 3
Searching for 4. Result: index = 5, A[5] == 5
Searching for 5. Result: index = 5, A[5] == 5
Searching for 6. Result: index = 6, A[6] == 8
Searching for 7. Result: index = 6, A[6] == 8
Searching for 8. Result: index = 6, A[6] == 8
Searching for 9. Result: index = 7, which is off-the-end.
Searching for 10. Result: index = 7, which is off-the-end.
您不能安全地解除对尾部值的引用,但您可以将其用于比较目的或作为插入点。
你为什么要使用 lower_bound
?出于搜索的目的,您肯定应该使用 find
吗?如果您使用 lower_bound
,它会返回一个位置,其中可以插入文件名,但不一定等于您要查找的文件名。换句话说,您不仅需要与结束值进行比较,还需要与文件名进行比较,以防返回有效内容。
这是一个使用find
的版本。如您所见,它比上面的固定版本更简单。
std::vector<std::wstring>::const_iterator target = std::find(expectedResults.begin(), expectedResults.end(), theFileString);
BOOST_REQUIRE_MESSAGE(target != expectedResults.end(), std::string("The file ") + convertUnicode(theFileString) + " was unexpected." );
if (target != expectedResults.end())
{
expectedResults.erase(target);
}
关于c++ - 应用程序中奇怪的执行错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1291150/