Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic dll load and googletest

I've several MFC based projects (DLLs). I want to add some GTest/GMock tests inside.

I need to do it with minimal efford so ma plan was:

  1. add test files to each of library and link it against gmock.lib
  2. prepare a single executable which would load dynamically desired dll with minimal main() like this:

    int main(int argc, char** argv)
    { 
        LoadLibrary(argv[1]);
        testing::InitGoogleMock(&argc, argv);
    
        const int status = RUN_ALL_TESTS();
    
        return status;
    }
    

The problem is that tests from loaded library are not visible to my exe file (dll is loaded and initialized for sure). The output is:

[==========] Running 0 tests from 0 test cases.
[==========] 0 tests from 0 test cases ran. (0 ms total)
[  PASSED  ] 0 tests.

It seems like I should somehow introduce tests from dll file into exe but I cannot find any information. Is my approach ok? Or maybe there are other, simple ways?

like image 589
Michał Walenciak Avatar asked Jan 22 '16 09:01

Michał Walenciak


1 Answers

Tests which will be executed are determined at compile time. What you are doing is simply loading the DLL into process address space using explicit DLL loading (function LoadLibrary) at runtime.

First of all, I would suggest that you do not add tests to your DLL projects at all. There is no need for unit test code to be inside a DLL which will be deployed to end users. Another problem is that, when you use explicit DLL loading, you have to explicitly retrieve address of a function from the DLL and use it to call the function:

https://msdn.microsoft.com/en-us/library/784bt7z7.aspx

This is not suitable for your what you want. What you should do is the following:

  1. Add tests (which use functions from all desired DLLs) to project that will build the executable that will run unit tests from all DLLs.
  2. Add paths of header files for functions and classes (from all desired DLLs) as additional include directories for project that builds this executable.
  3. Link this executable to gmock.lib
  4. Setup implicit DLL loading using dllimport storage class attribute, so you do not have to write code that explicitly acquires addresses of functions from the DLL which will be used in your unit tests.

For more information about implicit DLL loading see:

https://msdn.microsoft.com/en-us/library/d14wsce5.aspx

EDIT:

Since switching to implicit linking is not an option for you, modify your approach this way:

First, add an additional exported function, which runs unit tests, to each of your DLLs:

void runTests(int argc, char *argv[])
{
    testing::InitGoogleMock(&argc, argv);
    const int status = RUN_ALL_TESTS();
}

Then, in the main function of your executable, loop through all DLLs and execute this exported function for each of them using the following:

HMODULE hDLL = LoadLibraryA("MyDLL");
if(hDLL != NULL)
{
    fpRunTests runTestsFun = (fpRunTests)GetProcAddress(hDLL, "runTests");
    if(!runTestsFun)
    {
        // Handle the error
        FreeLibrary(hDLL);
    }
    else
    {
        // Call the function which runs tests
        runTestsFun(argc, argv);
    }
}
like image 67
Marko Popovic Avatar answered Sep 28 '22 16:09

Marko Popovic