Saturday, February 06, 2010

Using GoogleTest to Test a COM DLL

The following is a simple GoogleTest of a COM interface.  Used an example GoogleTest project, removed the example test, and added my simple test.  I abbreviate some of the names and changed some syntax to get a couple of includes to show. Each test is performed in order.

#include "iostream"

#include "gtest/gtest.h"


#import "..\..\interfaces\tlb\FAOServer.tlb" no_namespace, named_guids

int main(int argc, char **argv) {
  std::cout << "Running main() from TestFAOServer.cpp\n";

  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

#include "test/production.h"

TEST(FAOServerTest, InitializeCOMSubSystem)
{
    HRESULT hr = CoInitialize(NULL);
    ASSERT_EQ(hr,S_OK);
}

TEST(FAOServerTest, CreateInstance)
{
    IAO* pAPOL = NULL;
    bool pointerNull = false;

    ASSERT_EQ((pAPOL == NULL), true);

    HRESULT hr = CoCreateInstance
    (
        CLSID_AO,
        NULL,
        CLSCTX_ALL,
        IID_IAO,
        (void**)&pAPOL
    );

    ASSERT_EQ(hr, S_OK);

    if (hr == S_OK)
    {
        hr = pAPOL->OnDTC();

        ASSERT_EQ(hr, S_OK);
    }
}

TEST(FAOSTest, TerminateCOMSubSystem)
{
    CoUninitialize();
    ASSERT_EQ(0,0);
}

named_guids

It seems like the '#import' takes a bunch of parameters.  One of those parameters is 'named_guids'.  The parameter gives you access to the CLSID and IID constants you see in the *_i.c file that is created in the when you import the TLB file.

This all came up while creating while testing a COM DLL (non-managed).

Thursday, August 28, 2008

RaceOnRCWCleanup

RaceOnRCWCleanup

This is a discussion from a MS programmer: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=707167&SiteID=1

he says to look at the callstack when the MDA (managed debugging assistant) fires. This should tell me which RCW is being freed.

The call to release the RCW is Marshal.ReleaseCOmObject. This is being done while the RCW is still being reference in the stack of the current thread or in another thread.

Could be on of the following:

  1. RCW blocked on an outgoing call and a re-entrancy occured while is was block
  2. asynchronous call occured on a background thread.
There is not safe way to release a RCW while it is in the middle of a call. Doing this will most likely result in a crash.

May need to do one of the following:

  1. cancel the data transfer and wait
  2. to avoid re-entrancy more the data transfer to a background thread so I can control the canceling (this may be my problem)
To help the bugger work in this case I need to
  1. disable "Enable Just My Code" under Tools Options (Debugging)
  2. Enable unmanaged code debugging in the project properties settings
I need to ensure that the data transfer is either cancelled or completed for I exit.

RCW and CCW

Here is an OK intro: http://vbfaqs.blogspot.com/2008/06/overview-rcw-and-ccw.html

RCW is Runtime Callable Wripper. It is used by .NET to call COM objects.

CCW is COM callable wrapper. Used by COM to call .NET objects.

I am seeing the following error calling COM from .NET:

RaceOnRCWCleanup was detected.

An attempt has been made to free an RCW that is in use. The RCW is in use on the active thread or another thread. Attempting to free and in-use RCW can cause corruption or data loss.

Tuesday, May 30, 2006

Good Source



I have found that "The Code Project" seems like a good source for articles dealing with COM.

How To Start


For years I have avoid COM. I remember looking at C++ and hoping it would not catch on. Now I am at a point where I need to know about COM so that we can have or new C# code interact with old C++ code. What is most difficult is that we would like to write C# DLLs to access from our C++ application.

In addition to this I will not be personally writing the code that does this. However, I may be called upon to 'help' if somethings goes wrong.