0

私が書いている単体テストには、ある種のポインターの問題があるようです。基本的には、一度構築されるとファイルに関する情報を返すクラスをテストしています。予想されるすべてのファイルが検出された場合、テストは正しく動作します。検出されたよりも多くのファイルが予想される場合、ルーチンはエラーを正しく報告します。しかし、予想よりも多くのファイルが検出された場合、実行可能ファイルはクラッシュします。デバッガーでステップスルーしようとすると、現在のコードポイントがメソッド全体にジャンプするため、これを追跡するのは困難でした.

私が間違っていることについてのアイデアはありますか?

これが私のコードです:

#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

}
4

3 に答える 3

2

ファイルが予期しないものだった場合、これは何を返すと思いますか? 有効なファイル名であることを期待しているようです。

std::vector<std::wstring>::const_iterator target = std::lower_bound(expectedResults.begin(), expectedResults.end(), theFileString);

実際には、配列の末尾を 1 つ過ぎたイテレータになります。これを有効なポインタとして扱うことはできません。

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);
}

この例を参照してください。 は、lower_boundoff-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);
}
于 2009-08-18T00:20:13.517 に答える
0

「現在のコードポイントはメソッド全体にジャンプします-期待するように行ごとに続きません」

コンパイラ オプションを確認してください。デバッグをオンにして最適化をオフにしましたか?

最適化コンパイラは、多くの場合、命令の順序を変更したり、ループを展開したりしてコードを完全に「書き換え」ます。そのため、デバッガーは実行可能な命令を元のコード行にマッピングすることが困難になります。

于 2009-08-18T01:10:28.653 に答える
0

「現在のコードポイントはメソッド全体にジャンプします-期待するように行ごとに続きません」

これは通常、一度に複数のスレッドがメソッドをヒットしていることを意味します。通常、aspx ページの複数のオブジェクトが同時にポストバックを引き起こす場合に、これが表示されます。

于 2009-08-18T00:28:39.090 に答える