我正在编写一个单元测试,它似乎有某种指针问题。基本上,它正在测试一个类,一旦构造,就会返回有关文件的信息。如果检测到所有预期的文件,则测试正常运行。如果预期文件多于检测到的文件,则例程会正确报告错误。但是,如果检测到的文件多于预期,则可执行文件崩溃。这很难理解,因为当我尝试使用调试器时,当前的代码点会跳过整个方法 - 它不像你期望的那样逐行跟随。
关于我做错了什么的任何想法?
这是我的代码:
#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()
谢谢!
Billy3
我使用以下代码解决了问题:
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
}
答案 0 :(得分:2)
如果文件出现意外,您认为这会返回什么?看起来您希望它是一个有效的文件名。
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." );
Normall,您将结果与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
将返回非正式值:
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
,它将返回文件名可以插入的位置,但不一定等于您要查找的文件名。换句话说,您不仅需要与off-the-end值进行比较,还需要与文件名进行比较,以防它返回有效的内容。
以下是使用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);
}
答案 1 :(得分:0)
“当前的代码点全都跳了起来 方法 - 它不遵循线 像你期望的那样排队“
这通常意味着您一次有超过1个线程命中该方法。当我的aspx页面上有多个对象同时导致回发时,我通常会看到这个。
答案 2 :(得分:0)
“当前的代码点遍布整个方法 - 它不像你期望的那样逐行”
检查编译器选项!你有调试和优化吗?
优化编译器通常会完全“重写”代码,改变指令的顺序, 展开循环等等,以便调试器难以将可执行指令映射到原始代码行。