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..
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:
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.
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.
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.