[Libvir] A 'mock' driver enabling application unit testing

The attached patch adds a new driver which provides a 'mock' hypervisor connection. The idea behind this is to provide a completely predictable and isolated hypervisor implementation, which will facilitate creation of unit tests in applications using libvirt. The code attached is not a complete implementation, providing support only for connecting, listing domains, getting a domain by id/uuid/name, getting domain info, getting node info. Further work will hook up methods for creating domains, exporting XML & the other various libvirt APIs. The driver is intended to operate as a black box, closed system - the only interaction an application will have is via the libVirt entry points. It starts off with a single domain present, and fixed node info, and updates domain CPU time based on elapsed wall clock time. When the domain create API is hooked up this will let apps create new dummy domains within the context of the process. As I said, I delibrately implemented this driver to only have process local state. When the process shuts down all state is discarded. This keeps application usage very simple. Longer term I think it would be useful to have a 2nd, dynamic, which would allow fault injection, cross-process interaction & more to allow advanced scripting of a test scenario. I don't have time to create such a driver myself though, so I stuck with the simplest possible impl which will allow 95% of application unit testing needs to be satisfied. To use this driver, simply pass 'TestSimple' as the name parameter to virConnectOpen / virConnectOpenReadonly instead of NULL. If you are using 'virsh' then my previous patch will let you call 'virsh --connect TestSimple' I've also tested this with the 'gnome-vm-applet' panel applet. The only problem I have found is that the 'xend_internal.c' driver will always return success from its 'xenDaemonOpen' method, regardless of whether there is actually a Xen Daemon present. So when using the test driver, every method will first try to ue the XenD driver impl, fail (printing an error message) and then go onto use the test driver. The xenDaemonOpen method really needs to be fixed to only succeed when Xen is actually present. Or perhaps it should only try to run when the 'name' passed to virConnectOpen is NULL or 'Xen' - ie be a no op if the name is 'TestSimple' / QEMU / any other driver implementation. I'm not sure whether we want to commit this to the libvirt codebae just, since there is a fair bit more work to be done to hook up additional methods. Regards, Dan. -- |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=| |=- Perl modules: http://search.cpan.org/~danberr/ -=| |=- Projects: http://freshmeat.net/~danielpb/ -=| |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|

On Fri, May 26, 2006 at 07:35:37PM +0100, Daniel P. Berrange wrote:
The attached patch adds a new driver which provides a 'mock' hypervisor connection. The idea behind this is to provide a completely predictable and isolated hypervisor implementation, which will facilitate creation of unit tests in applications using libvirt.
Sounds good on two counts: - this forces to clean up the code internally and test the driver based approach - testing testing testing :-) thanks !
The code attached is not a complete implementation, providing support only for connecting, listing domains, getting a domain by id/uuid/name, getting domain info, getting node info. Further work will hook up methods for creating domains, exporting XML & the other various libvirt APIs. The driver is intended to operate as a black box, closed system - the only interaction an application will have is via the libVirt entry points. It starts off with a single domain present, and fixed node info, and updates domain CPU time based on elapsed wall clock time. When the domain create API is hooked up this will let apps create new dummy domains within the context of the process.
Okay, simplistic but a good first start :-)
As I said, I delibrately implemented this driver to only have process local state. When the process shuts down all state is discarded. This keeps application usage very simple. Longer term I think it would be useful to have a 2nd, dynamic, which would allow fault injection, cross-process interaction & more to allow advanced scripting of a test scenario. I don't have time to create such a driver myself though, so I stuck with the simplest possible impl which will allow 95% of application unit testing needs to be satisfied.
Understandable, but I would really like to be able to go one step behind and be able to provide a runtime scenario in a config file.
To use this driver, simply pass 'TestSimple' as the name parameter to virConnectOpen / virConnectOpenReadonly instead of NULL. If you are using 'virsh' then my previous patch will let you call 'virsh --connect TestSimple' I've also tested this with the 'gnome-vm-applet' panel applet.
That's probably the only part where I have a slight concern, shouldn't we just use something like "test:///default" for this simple fallback case and probably something like "test:///path/to/config" in the more general case where there will be some state. But it really should not be a big deal.
The only problem I have found is that the 'xend_internal.c' driver will always return success from its 'xenDaemonOpen' method, regardless of whether there is actually a Xen Daemon present. So when using the test driver, every method will first try to ue the XenD driver impl, fail (printing an error message) and then go onto use the test driver. The xenDaemonOpen method really needs to be fixed to only succeed when Xen is actually present.
Right this need some cleanup I think. I though I had left a TODO there.
Or perhaps it should only try to run when the 'name' passed to virConnectOpen is NULL or 'Xen' - ie be a no op if the name is 'TestSimple' / QEMU / any other driver implementation.
I'm not sure whether we want to commit this to the libvirt codebae just, since there is a fair bit more work to be done to hook up additional methods.
Do you think you will need to change radically that code when completing it ? Looks to me it's just additional code, so what's there should be commited because it's code you expect to be present in the end. So please commit (I think your CVS account works, right ?) Daniel -- Daniel Veillard | Red Hat http://redhat.com/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

On Mon, May 29, 2006 at 01:19:49PM -0400, Daniel Veillard wrote:
On Fri, May 26, 2006 at 07:35:37PM +0100, Daniel P. Berrange wrote:
To use this driver, simply pass 'TestSimple' as the name parameter to virConnectOpen / virConnectOpenReadonly instead of NULL. If you are using 'virsh' then my previous patch will let you call 'virsh --connect TestSimple' I've also tested this with the 'gnome-vm-applet' panel applet.
That's probably the only part where I have a slight concern, shouldn't we just use something like "test:///default" for this simple fallback case and probably something like "test:///path/to/config" in the more general case where there will be some state. But it really should not be a big deal.
That sounds reasonable - I wasn't not sure what format you were planning for the 'name' parameter - I'll adapt it to expect this URI style format.
The only problem I have found is that the 'xend_internal.c' driver will always return success from its 'xenDaemonOpen' method, regardless of whether there is actually a Xen Daemon present. So when using the test driver, every method will first try to ue the XenD driver impl, fail (printing an error message) and then go onto use the test driver. The xenDaemonOpen method really needs to be fixed to only succeed when Xen is actually present.
Right this need some cleanup I think. I though I had left a TODO there.
Or perhaps it should only try to run when the 'name' passed to virConnectOpen is NULL or 'Xen' - ie be a no op if the name is 'TestSimple' / QEMU / any other driver implementation.
I'm not sure whether we want to commit this to the libvirt codebae just, since there is a fair bit more work to be done to hook up additional methods.
Do you think you will need to change radically that code when completing it ? Looks to me it's just additional code, so what's there should be commited because it's code you expect to be present in the end. So please commit (I think your CVS account works, right ?)
Aside from making it expect a URI style name, the one change I need to make is change the internal storage to dynamically allocate the data structures. Currently it just has a huge statically allocating struct, which wastes 32k of memory even if your not using the test driver. Regards, Dan. -- |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=| |=- Perl modules: http://search.cpan.org/~danberr/ -=| |=- Projects: http://freshmeat.net/~danielpb/ -=| |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|

On Mon, May 29, 2006 at 06:43:24PM +0100, Daniel P. Berrange wrote:
Aside from making it expect a URI style name, the one change I need to make is change the internal storage to dynamically allocate the data structures. Currently it just has a huge statically allocating struct, which wastes 32k of memory even if your not using the test driver.
Okay, but that should not require even internal API changes isn't it ? Another interesting extension would be to use the test driver to increase the existing set of regression tests, this should help the coverage of the common code (i.e. driver independant), and since it makes the run more or less standalone, valgrind regression testing should become easier too. Daniel -- Daniel Veillard | Red Hat http://redhat.com/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

On Wed, May 31, 2006 at 03:48:03AM -0400, Daniel Veillard wrote:
On Mon, May 29, 2006 at 06:43:24PM +0100, Daniel P. Berrange wrote:
Aside from making it expect a URI style name, the one change I need to make is change the internal storage to dynamically allocate the data structures. Currently it just has a huge statically allocating struct, which wastes 32k of memory even if your not using the test driver.
Okay, but that should not require even internal API changes isn't it ? Another interesting extension would be to use the test driver to increase the existing set of regression tests, this should help the coverage of the common code (i.e. driver independant), and since it makes the run more or less standalone, valgrind regression testing should become easier too.
Ok, I've committed this code now, with the two cleanups I mention above. Example usage looks like: $ virsh --connect test:///default list Id Name State ---------------------------------- 0 Domain-0 running $ virsh --connect test:///default dominfo 0 Id: 0 Name: Domain-0 UUID: 00000000-0000-0000-0000-000000000000 OS Type: linux State: running CPU(s): 2 CPU time: 1149561216.0s Max memory: 8388608 kB Used memory: 2097152 kB Regards, Dan. -- |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=| |=- Perl modules: http://search.cpan.org/~danberr/ -=| |=- Projects: http://freshmeat.net/~danielpb/ -=| |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
participants (2)
-
Daniel P. Berrange
-
Daniel Veillard