views:

418

answers:

7

Hi.. I'm currently trying to use a certain SDK that has me loading functions off a DLL that a vendor provides.. I have to pass arguments to these functions and the DLL does all the work..

Now, the DLL is supposed to be communicating with another device, while I just wait for the results. However, I don't have this device, so how do I set up a mock interface to emulate the device?

To be clear, here's an example:

myfuncpointer.Open(someparam,anotherparam,...);

Now, because I don't have the device, the DLL can't actually perform the above function; it fails. How do I set up testing so that the DLL talks to a class that I designed rather than the device? Is there any way to redirect the DLL's call?

How do I make a DummyDevice class to do this?

Thanks..

P.S. If anything is not clear, please don't be too quick to downvote.. Comment as to what I need to explain and I'll try to clear it up.. Thanks.


EDIT: What I DO have, however, is a spec sheet with all of the data structures used and the expected/legal values that it has to contain. So for example, if I call a function:

myfuncpointer.getinfo(param,otherparam);

where one of the params is a data structure that the DLL fills up with info (say, if an option is enabled) after querying the device.. I can do this

param.option = true;

after it has finished the getinfo call.

Is this a good way to test the code? It seems very very dangerous to trick this DLL into thinking all the wrong things and seems to be really really hard to scale even just a bit..

+1  A: 

You'd probably have to write a device driver for that. Depending on your platform, you there might be devices available that might work for you (i.e., things like the 'lo' interface in Linux).

You're not the first person to have this problem, so be sure and scour the web before rolling your own :-)

Ben Collins
I see.. I've been looking around and mock/unit testing frameworks seem to be too complicated for what I'm trying to do atm..
krebstar
Yes....you just need something that exposes the appropriate driver API
Ben Collins
+1  A: 

If the DLL is communicating with an external hardware device, you would need to implement a driver that is compatible with the actual driver but with emulated responses.

Most likely if you don't have the device then the SDK will be useless anyway. If there is some functionality provided that does not relate to this external device it will almost certainly be easier to source an equivalent library without the hardware dependency.

Zooba
Aren't there people developing iPhone apps without iPhone? I'm in a similar situation, but don't have that nifty emulator that they have..
krebstar
+2  A: 

It depends on how the DLL accesses the device. If it does so by calling functions in another DLL, you can supply a mock DLL where you've replaced the appropriate functions. However, if the DLL is doing something low-level, such as calling directly into the kernel, you're going to have a much tougher time. In that case, you'll probably have to write a new device driver or kernel extension or something.

Adam Rosenfield
I see.. It seems to be the latter case.. :(
krebstar
+6  A: 

Is emulated device access a stopgap solution for until you get hardware? If so, I recommend finding some other way to be productive: work on something else, write unit tests, etc.

Is emulated device access a permanent requirement? If so, here are a few approaches you could take:

  1. If the other vendor's SDK has a "simulation" or "emulation" mode, use it. You might be surprised. You're probably not the only client that needs to be able to test/run their application without the other vendor's hardware installed.

  2. Take the other vendor's code out of the picture. Emulate only the functionality that your application needs, and base it on your program's requirements. Everything is under your control.

    a. Add an indirection layer. Use polymorphism to switch between two implementations: one that calls into the other vendor's DLL, and one that emulates its behavior. Having your code call into an abstract base class instead of directly calling into the other vendor's DLL also will make it easier to write unit tests for your code.

    b. Write a mock DLL (as Adam Rosenfield suggested). You need to match the function names and calling conventions exactly. As you upgrade to new versions of the other vendor's DLL, you will need to extend the mock DLL to support any new entrypoints that your application uses.

    If you need to choose which DLL to use at runtime, this may require converting your code to load the DLL dynamically (but it sounds like you might already be doing this, given that you said something about function pointers). You may be able to decide at install time whether to install the other vendor's DLL or the mock DLL. And if this is purely for testing purposes, you may be able to choose which DLL to use at compile time, and just build two versions of your application.

  3. Write a mock device driver (as others have suggested).

    If you have the spec for the interface between the other vendor's user mode DLL and their device driver, this may be doable. It will probably take longer than any of the other approaches, even if you're an experienced device driver developer, and especially if you don't have the source to the other vendor's DLL. UMDF (User Mode Driver Framework) might make this slightly easier or less time consuming.

    If the spec you mentioned does not describe the user/kernel interface, you will need to reverse engineer that interface. This is probably not going to be an effective use of your time compared with the other options, particularly if the driver interface is complex (e.g. it passes a lot of complex data structures to DeviceIoControl()).

    In both cases, you will need to revisit this every time you upgrade to a new version of the other vendor's SDK. The same exported DLL functions may require using new DeviceIoControl() codes and structures.

bk1e
Thanks for the post bk1e. I'm not sure how to describe it, but I need to learn how to use the DLL and its functions properly so I can integrate it with my company's software. So no, it's not a stopgap solution, we'll probably never get the hardware either.
krebstar
1. No, it doesn't have an emulation mode, and the documentation is pretty bad (japanese vendor). It's missing bits and pieces here and there..
krebstar
2. Emulating the functionality is somewhat close to impossible, because that would mean I would have to know how the underlying hardware works, doesn't it? That would somewhat be like making my own drivers for it..
krebstar
3. Are you suggesting I replace the called DLL with a mock dll of my own and then replace the mock DLL with the vendor DLL when it's ready for shipping? I think I might have some problems with this as I probably can't recreate the functionality that the vendor DLL supports, but it might be doable.
krebstar
oops that was supposed to be 2b.
krebstar
Anyway, I think I'll investigate your 2b. solution as it seems the most sensible.. Am I wrong here? I'm such a n00b.. :S
krebstar
By the way, I have found the device drivers for the device, so the DLL is able to communicate with the device driver. But the device is not present so it just.. gets timed out.. :S
krebstar
A: 

I've used a relatively hacky, non-portable method for mocking functions, in WIN32 environment (I think it's 32 bit only, but not sure). here it is:

#define INJECTED_BYTES  5

static void replace_target(void *Target, void *Server)
{
    DWORD dwOld;

    VirtualProtect(Target, INJECTED_BYTES, PAGE_WRITECOPY, &dwOld);
    *((unsigned char *)Target)++ = 0xe9 ; // jump relative
    *(unsigned int *)Target = (unsigned int)((unsigned char *)Server - (unsigned char *)Target)-4;
    VirtualProtect(((unsigned char *)Target)-1, INJECTED_BYTES, PAGE_EXECUTE, &dwOld);
    FlushInstructionCache(GetCurrentProcess(), 0, 0);
}

What this does is, it replaces the first few bytes of the target function with a jump to your mocked function. So when you call the target, it jumps directly to your stub. Just remember to keep a copy of the replaced bytes (INJECTED_BYTES) so you can later on undo your mock.

Come to think of it, what's stopping you from writing your own DLL that only stubs out what the real DLL does?

Dushara
BTW you might want to create a wrapper for the DLL and mock that wrapper.
Dushara
I dont understand this well enough at the moment, maybe if i read it again some other time.. Don't think this deserves a -1 tho.. :S
krebstar
+2  A: 

There are a number of places were you can insert a mock object:

  1. Mock calls to the DLL: Within your application, write a Facade/wrapper class that encapsulates the function pointer calls into the vendor's DLL. This is a good idea in general because you can put a cleaner class API over the DLL function calls.

  2. Mock the DLL: write your own DLL that emulates

  3. Mock the device: write a device driver that emulates the device. I would not recommend this because it will be a lot of work and emulating the device's behavior (including bugs and quirks) will be difficult.

I would recommend #1 because it is the least amount of work and it is not throw-away code.

The Facade class interface you design to hide the calls into the vendor's DLL will improve the design of your other code. It will reduce your code's coupling with the low-level implementation details of vendor's DLL and APIs. If the vendor delivers new DLL APIs, you will be able to integrate it with your code more easily. You might even be able to replace that vendor's DLL with a different vendor or device. :)

cpeterso
A: 

only use Xcode or Eclipse when threatened. another night in the boro, the usually smoke n maintain while the uv flows dad was one of those scary cowboys fans. i maintain he'd scare any child away from football. :) girl I got a rep to

thvdjwqp
What the hell are you talking about?
krebstar