0

我刚刚将我的所有测试从 Google Test 移植到 Visual Studio 2012 的单元测试框架。(长话短说;Google 的断言更好,但 Microsoft 使用开箱即用的 Dev11 单元测试资源管理器,这使得代码覆盖率变得非常容易......)

我把所有东西都移植好了,除了下面的类,它从 Win32 资源中读取一个以换行符分隔的文本文件,然后允许对该资源进行快速查找:

#include "pch.hpp"
#include "resource.h"
#include <functional>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <windows.h>
#include "Win32Exception.hpp"
#include "Whitelist.hpp"

using Instalog::SystemFacades::Win32Exception;

namespace Instalog {

    Whitelist::Whitelist( __int32 whitelistId , std::vector<std::pair<std::wstring, std::wstring>> const& replacements )
    {
        using namespace std::placeholders;

        HRSRC resourceHandle = ::FindResource(0, MAKEINTRESOURCEW(whitelistId), L"WHITELIST");
        if (resourceHandle == 0)
        {
            Win32Exception::ThrowFromLastError();
        }
        HGLOBAL resourceGlobal = ::LoadResource(0, resourceHandle);
        if (resourceGlobal == 0)
        {
            Win32Exception::ThrowFromLastError();
        }
        void * resourceData = ::LockResource(resourceGlobal);
        if (resourceData == 0)
        {
            Win32Exception::ThrowFromLastError();
        }
        wchar_t const* resourceDataCasted = static_cast<wchar_t const*>(resourceData);
        DWORD resourceLen = ::SizeofResource(0, resourceHandle);
        auto sourceRange = boost::make_iterator_range(resourceDataCasted, resourceDataCasted + (resourceLen / sizeof(wchar_t)));
        boost::algorithm::split(innards, sourceRange, std::bind1st(std::equal_to<wchar_t>(), L'\n'));
        std::for_each(innards.begin(), innards.end(), std::bind(boost::algorithm::to_lower<std::wstring>, _1, std::locale()));
        std::for_each(innards.begin(), innards.end(), [&replacements] (std::wstring &a) {
            std::for_each(replacements.begin(), replacements.end(), [&a] (std::pair<std::wstring, std::wstring> const&b) {
                if (boost::algorithm::starts_with(a, b.first))
                {
                    a.replace(a.begin(), a.begin() + b.first.size(), b.second);
                }
            });
        });
        std::sort(innards.begin(), innards.end());
    }

    bool Whitelist::IsOnWhitelist( std::wstring checked ) const
    {
        boost::algorithm::to_lower(checked);
        return std::binary_search(innards.begin(), innards.end(), checked);
    }

    void Whitelist::PrintAll( std::wostream & str ) const
    {
        std::copy(innards.begin(), innards.end(), std::ostream_iterator<std::wstring, wchar_t>(str, L"\n"));
    }

}

不幸的是,Dev11 的测试项目生成的是 DLL,而不是 EXE,就像在 Google Test 的系统下一样。因此,在我能够将资源嵌入 EXE 并传递NULLFindResource的第一个参数之前,现在 Visual Studio 在测试期间将 DLL 加载到其进程中。Visual Studio 里面当然没有我的自定义WHITELIST资源类型,所以这段代码很糟糕。

有什么办法可以吗

  1. 告诉这段代码以某种方式查看正确的二进制文件,无论是测试 DLL 还是 EXE,取决于上下文?(目前此代码位于与真实 EXE 和测试 DLL 链接的静态库中)或
  2. 在完全不使用 Win32 资源基础结构的情况下,将相对较大(几 MB)的文本文件干净地嵌入到 C++ 程序中?

应该注意的是,将资源放入附属 DLL(这可能是一个合理的解决方案)不是一种选择;该项目的一个要求是单个 EXE xcopy 部署。

4

1 回答 1

0

弄清楚了。我在GetCurrentModule这里使用了 hack ->如何获取当前执行代码的 HMODULE?. 这给了我需要传递给 XxxResource API 的 HMODULE。

于 2012-08-20T17:06:22.080 回答