Unit Tests for C++ plugin

Hey all,

I’m currently setting up a CI pipeline for a C++ Rhino plugin and wonder how to integrate unit testing.
I am aware of the fact that many things can only be tested in a running Rhino instance.
For the moment, I would like to only cover more or less isolated code which technically mostly just needs the OpenNurbs library.

I use cmake to build the plugin (that works reliable) and plan to use catch as testing framework.
Now I run into the following problem: I need to include and use some of my classes, which in turn include the main PlugIn.h and PlugIn.cpp (e.g. to retrieve a config object from the static plugin class). So I have to build the PlugIn.obj binary and link to it from my test executable.
If I do so, the main() function from my test framework is not invoked anymore.
It looks like the PlugIn also defines a main / dllMain entrypoint? But I can’t figure out whether that’s the case and what I can do about it.
It might also be somehow related to the precompiled headers (I currently re-build them for the test-binary).

Running dumpbin.exe on my test.exe outputs the following:


  Section contains the following exports for test_kinematic.exe

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
          17 number of functions
          17 number of names

    ordinal hint RVA      name

          1    0 00002176 RhinoPlugInDescription = @ILT+4465(RhinoPlugInDescription)
          2    1 00001F8C RhinoPlugInDeveloperAddress = @ILT+3975(RhinoPlugInDeveloperAddress)
          3    2 00002644 RhinoPlugInDeveloperCountry = @ILT+5695(RhinoPlugInDeveloperCountry)
          4    3 0000286A RhinoPlugInDeveloperEmail = @ILT+6245(RhinoPlugInDeveloperEmail)
          5    4 00004890 RhinoPlugInDeveloperOrganization = @ILT+14475(RhinoPlugInDeveloperOrganization)
          6    5 00001CFD RhinoPlugInDeveloperPhone = @ILT+3320(RhinoPlugInDeveloperPhone)
          7    6 00004935 RhinoPlugInDeveloperWebsite = @ILT+14640(RhinoPlugInDeveloperWebsite)
          8    7 00004B6F RhinoPlugInIconResourceId = @ILT+15210(RhinoPlugInIconResourceId)
          9    8 00002E73 RhinoPlugInId = @ILT+7790(RhinoPlugInId)
         10    9 00004E49 RhinoPlugInMfcVersion = @ILT+15940(RhinoPlugInMfcVersion)
         11    A 000014D8 RhinoPlugInMscVersion = @ILT+1235(RhinoPlugInMscVersion)
         12    B 00001A00 RhinoPlugInName = @ILT+2555(RhinoPlugInName)
         13    C 000037AB RhinoPlugInSdkServiceRelease = @ILT+10150(RhinoPlugInSdkServiceRelease)
         14    D 000040B1 RhinoPlugInSdkVersion = @ILT+12460(RhinoPlugInSdkVersion)
         15    E 00002F7C RhinoPlugInUpdateURL = @ILT+8055(RhinoPlugInUpdateURL)
         16    F 00001A5F RhinoPlugInUsesMfc = @ILT+2650(RhinoPlugInUsesMfc)
         17   10 0000483B RhinoPlugInVersion = @ILT+14390(RhinoPlugInVersion)


        1000 .00cfg
        7000 .data
        C000 .idata
        B000 .pdata
       32000 .rdata
        3000 .reloc
        B000 .rsrc
       C7000 .text
        1000 .tls

Which is obviously the PlugIn interface and not the unit-test interface.

The cmake file looks like this (only the important things)

# build shared binary objects to be linked from plugin and unit test
add_library(libCommonObjects OBJECT "src/Kinematic.cpp" "src/demoPlugIn.cpp" etc...)

# build main plugin
#add_library(${PROJECT_NAME} SHARED "other files" $<TARGET_OBJECTS:libCommonObjects>)

# build test executable
add_executable(test_kinematic kinematic.cpp catch_amalgamated.cpp)
# link test executable against plugin binaries
target_link_libraries(test_kinematic PRIVATE $<TARGET_OBJECTS:libCommonObjects>)

I am fairly experienced with C++ but have never worked with Windows and MSVS before.
Any hints or ideas? Am I getting something fundamentally wrong?

I think you will have to separate out your truly only opennurbs-dependent code into a separate lib, which you can then link in your test (and of course in your plugin), along with opennurbs, because your actual plugin code will be linking rhino import libs through headers included in the plugin.h, such that the test exe should completely fail to run at all (you say it doesn’t run main, my guess is it would be dying earlier than that, in some static ctor that expects rhino to be present)

Thanks for the hint.
I can’t figure out where exactly my test.exe fails, but it doesn’t matter in the end.
First attempt to fence the core components off from Rhino looks promising, although it doesn’t exactly feel exactly like a clean, straight-forward solution…