]> xenbits.xensource.com Git - libvirt.git/commitdiff
Added 'mock' hypervisor driver for use by unit tests
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 6 Jun 2006 03:32:51 +0000 (03:32 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 6 Jun 2006 03:32:51 +0000 (03:32 +0000)
ChangeLog
src/Makefile.am
src/libvirt.c
src/test.c [new file with mode: 0644]
src/test.h [new file with mode: 0644]

index 4e874cde9b63e18e6c4acd6e503f1f93ec8a7012..9def3aaa20b790f5ed3102025afef5564c8add14 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Mon Jun 05 22:31:20 EDT 2006 Daniel P. Berrange <berrange@redhat.com>
+
+       * src/test.c, src/test.h: New 'mock' hypervisor driver providing
+       a way to write predictable unit tests which exercise libvirt APIs.
+       * src/libvirt.c, src/Makefile.am: Integrate test hypervisor driver
+
 Fri May 26 11:59:20 EDT 2006 Daniel P. Berrange <berrange@redhat.com>
 
        * src/hash.c, src/internal.h: Switch the uuid parameter in virGetDomain
index a4471e8b0b1189e5ab28336b9a560455b0e9aa94..2f814bf0583392b592a3193efbe88ea182f783a2 100644 (file)
@@ -16,6 +16,7 @@ libvirt_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libvirt_sym.version \
 libvirt_la_SOURCES =                                           \
                libvirt.c internal.h                            \
                hash.c hash.h                                   \
+               test.c test.h                                   \
                xml.c xml.h                                     \
                xen_internal.c xen_internal.h                   \
                xs_internal.c xs_internal.h                     \
index aba1ba7095e56b918637f436a230fbadde3decb9..f03a244c1f6672cc621e2c993f68e814740fbed6 100644 (file)
@@ -29,6 +29,7 @@
 #include "xend_internal.h"
 #include "xs_internal.h"
 #include "xml.h"
+#include "test.h"
 
 /*
  * TODO:
@@ -70,6 +71,7 @@ virInitialize(void)
     xenHypervisorRegister();
     xenDaemonRegister();
     xenStoreRegister();
+    testRegister();
     return(0);
 }
 
diff --git a/src/test.c b/src/test.c
new file mode 100644 (file)
index 0000000..ab161a9
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * test.c: A "mock" hypervisor for use by application unit tests
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Daniel Berrange <berrange@redhat.com>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <libxml/uri.h>
+
+#include "internal.h"
+#include "test.h"
+
+static virDriver testDriver = {
+  "Test",
+  NULL, /* init */
+  testOpen, /* open */
+  testClose, /* close */
+  NULL, /* type */
+  testGetVersion, /* version */
+  testNodeGetInfo, /* nodeGetInfo */
+  testListDomains, /* listDomains */
+  testNumOfDomains, /* numOfDomains */
+  NULL, /* domainCreateLinux */
+  testLookupDomainByID, /* domainLookupByID */
+  testLookupDomainByUUID, /* domainLookupByUUID */
+  testLookupDomainByName, /* domainLookupByName */
+  testPauseDomain, /* domainSuspend */
+  testResumeDomain, /* domainResume */
+  NULL, /* domainShutdown */
+  NULL, /* domainReboot */
+  testDestroyDomain, /* domainDestroy */
+  NULL, /* domainFree */
+  NULL, /* domainGetName */
+  NULL, /* domainGetID */
+  NULL, /* domainGetUUID */
+  NULL, /* domainGetOSType */
+  NULL, /* domainGetMaxMemory */
+  testSetMaxMemory, /* domainSetMaxMemory */
+  NULL, /* domainSetMemory */
+  testGetDomainInfo, /* domainGetInfo */
+  NULL, /* domainSave */
+  NULL /* domainRestore */
+};
+
+typedef struct _testDev {
+  char name[20];
+  virDeviceMode mode;
+} testDev;
+
+#define MAX_DEVICES 10
+
+typedef struct _testDom {
+  int active;
+  char name[20];
+  unsigned char uuid[16];
+  virDomainKernel kernel;
+  virDomainInfo info;
+  virDomainRestart onRestart;
+  int numDevices;
+  testDev devices[MAX_DEVICES];
+} testDom;
+
+#define MAX_DOMAINS 20
+
+typedef struct _testCon {
+  int active;
+  int numDomains;
+  testDom domains[MAX_DOMAINS];
+} testCon;
+
+#define MAX_CONNECTIONS 5
+
+typedef struct _testNode {
+  int numConnections;
+  testCon connections[MAX_CONNECTIONS];
+} testNode;
+
+/* XXX, how about we stuff this in a SHM
+   segment so multiple apps can run tests
+   against the mock hypervisor concurrently.
+   Would need a pthread process shared mutex
+   too probably */
+static testNode *node = NULL;
+
+static virNodeInfo nodeInfo = {
+  "i86",
+  1024*1024*3, /* 3 GB */
+  16,
+  1400,
+  2,
+  2,
+  2,
+  2,
+};
+
+static void
+testError(virConnectPtr con,
+         virDomainPtr dom,
+         virErrorNumber error,
+         const char *info)
+{
+  const char *errmsg;
+
+  if (error == VIR_ERR_OK)
+    return;
+
+  errmsg = __virErrorMsg(error, info);
+  __virRaiseError(con, dom, VIR_FROM_XEN, error, VIR_ERR_ERROR,
+                 errmsg, info, NULL, 0, 0, errmsg, info, 0);
+}
+
+
+/**
+ * testRegister:
+ *
+ * Registers the test driver
+ */
+void testRegister(void)
+{
+  virRegisterDriver(&testDriver);
+}
+
+
+int testOpen(virConnectPtr conn,
+             const char *name,
+             int flags)
+{
+  xmlURIPtr uri;
+  int i, j;
+
+  if (!name) {
+    return -1;
+  }
+
+  uri = xmlParseURI(name);
+  if (uri == NULL) {
+    if (!(flags & VIR_DRV_OPEN_QUIET))
+      testError(conn, NULL, VIR_ERR_NO_SUPPORT, name);
+    return(-1);
+  }
+
+  if (!uri->scheme ||
+      strcmp(uri->scheme, "test") ||
+      !uri->path ||
+      strcmp(uri->path, "/default")) {
+    xmlFreeURI(uri);
+    return -1;
+  }
+
+
+  xmlFreeURI(uri);
+
+  if (node == NULL) {
+    node = calloc(1, sizeof(testNode));
+    if (!node) {
+      testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot allocate memory");
+      return -1;
+    }
+  }
+
+  for (i = 0 ; i < MAX_CONNECTIONS ; i++) {
+    if (!node->connections[i].active) {
+      struct timeval tv;
+
+      if (gettimeofday(&tv, NULL) < 0) {
+       testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot get timeofday");
+       return -1;
+      }
+
+      conn->handle = i;
+      node->connections[i].active = 1;
+
+      node->connections[i].numDomains = 1;
+      node->connections[i].domains[0].active = 1;
+      strcpy(node->connections[i].domains[0].name, "Domain-0");
+      for (j = 0 ; j < 16 ; j++) {
+       node->connections[i].domains[0].uuid[j] = (j * 75)%255;
+      }
+      node->connections[i].domains[0].info.maxMem = 8192 * 1024;
+      node->connections[i].domains[0].info.memory = 2048 * 1024;
+      node->connections[i].domains[0].info.state = VIR_DOMAIN_RUNNING;
+      node->connections[i].domains[0].info.nrVirtCpu = 2;
+      node->connections[i].domains[0].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
+      return 0;
+    }
+  }
+
+
+  testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "too make connections");
+  return -1;
+}
+
+int testClose(virConnectPtr conn)
+{
+  testCon *con = &node->connections[conn->handle];
+  con->active = 0;
+  conn->handle = -1;
+  memset(con, 0, sizeof(testCon));
+  return 0;
+}
+
+int testGetVersion(virConnectPtr conn,
+                   unsigned long *hvVer)
+{
+  *hvVer = 1;
+  return 0;
+}
+
+int testNodeGetInfo(virConnectPtr conn,
+                    virNodeInfoPtr info)
+{
+  memcpy(info, &nodeInfo, sizeof(nodeInfo));
+  return 0;
+}
+
+int testNumOfDomains(virConnectPtr conn)
+{
+  testCon *con = &node->connections[conn->handle];
+  return con->numDomains;
+}
+
+virDomainPtr testLookupDomainByID(virConnectPtr conn,
+                                  int id)
+{
+  testCon *con = &node->connections[conn->handle];
+  virDomainPtr dom;
+  if (!con->domains[id].active) {
+    return NULL;
+  }
+  dom = virGetDomain(conn, con->domains[id].name, con->domains[id].uuid);
+  if (dom == NULL) {
+    testError(conn, NULL, VIR_ERR_NO_MEMORY, "Allocating domain");
+    return(NULL);
+  }
+  dom->handle = id;
+  return dom;
+}
+
+virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
+                                    const unsigned char *uuid)
+{
+  testCon *con = &node->connections[conn->handle];
+  virDomainPtr dom = NULL;
+  int i, id = -1;
+  for (i = 0 ; i < MAX_DOMAINS ; i++) {
+    if (con->domains[i].active &&
+       memcmp(uuid, con->domains[i].uuid, 16) == 0) {
+      id = i;
+      break;
+    }
+  }
+  if (id >= 0) {
+    dom = virGetDomain(conn, con->domains[id].name, con->domains[id].uuid);
+    if (dom == NULL) {
+      testError(conn, NULL, VIR_ERR_NO_MEMORY, "Allocating domain");
+      return(NULL);
+    }
+    dom->handle = id;
+  }
+  return dom;
+}
+
+virDomainPtr testLookupDomainByName(virConnectPtr conn,
+                                    const char *name)
+{
+  testCon *con = &node->connections[conn->handle];
+  virDomainPtr dom = NULL;
+  int i, id = -1;
+  for (i = 0 ; i < MAX_DOMAINS ; i++) {
+    if (con->domains[i].active &&
+       strcmp(name, con->domains[i].name) == 0) {
+      id = i;
+      break;
+    }
+  }
+  if (id >= 0) {
+    dom = virGetDomain(conn, con->domains[id].name, con->domains[id].uuid);
+    if (dom == NULL) {
+      testError(conn, NULL, VIR_ERR_NO_MEMORY, "Allocating domain");
+      return(NULL);
+    }
+    dom->handle = id;
+  }
+  return dom;
+}
+
+int testListDomains (virConnectPtr conn,
+                     int *ids,
+                     int maxids)
+{
+  testCon *con = &node->connections[conn->handle];
+  int n, i;
+
+  for (i = 0, n = 0 ; i < MAX_DOMAINS && n < maxids ; i++) {
+    if (con->domains[i].active) {
+      ids[n++] = i;
+    }
+  }
+  return n;
+}
+
+int testDestroyDomain (virDomainPtr domain)
+{
+  testCon *con = &node->connections[domain->conn->handle];
+  con->domains[domain->handle].active = 0;
+  return 0;
+}
+
+int testResumeDomain (virDomainPtr domain)
+{
+  testCon *con = &node->connections[domain->conn->handle];
+  con->domains[domain->handle].info.state = VIR_DOMAIN_RUNNING;
+  return 0;
+}
+
+int testPauseDomain (virDomainPtr domain)
+{
+  testCon *con = &node->connections[domain->conn->handle];
+  con->domains[domain->handle].info.state = VIR_DOMAIN_PAUSED;
+  return 0;
+}
+
+int testGetDomainInfo (virDomainPtr domain,
+                       virDomainInfoPtr info)
+{
+  testCon *con = &node->connections[domain->conn->handle];
+  struct timeval tv;
+  if (gettimeofday(&tv, NULL) < 0) {
+    testError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot get timeofday");
+    return -1;
+  }
+
+  con->domains[domain->handle].info.cpuTime = ((tv.tv_sec * 1000ll * 1000ll  * 1000ll) + (tv.tv_usec * 1000ll));
+  memcpy(info, &con->domains[domain->handle].info, sizeof(virDomainInfo));
+  return 0;
+}
+
+int testSetMaxMemory (virDomainPtr domain,
+                      unsigned long memory)
+{
+  testCon *con = &node->connections[domain->conn->handle];
+  con->domains[domain->handle].info.maxMem = memory;
+  return 0;
+}
diff --git a/src/test.h b/src/test.h
new file mode 100644 (file)
index 0000000..9281e27
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * test.h: A "mock" hypervisor for use by application unit tests
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Daniel Berrange <berrange@redhat.com>
+ */
+
+#ifndef __VIR_TEST_SIMPLE_INTERNAL_H__
+#define __VIR_TEST_SIMPLE_INTERNAL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <virterror.h>
+
+  void testRegister(void);
+  int testOpen(virConnectPtr conn,
+                    const char *name,
+                    int flags);
+  int testClose  (virConnectPtr conn);
+  int testGetVersion(virConnectPtr conn,
+                          unsigned long *hvVer);
+  int testNodeGetInfo(virConnectPtr conn,
+                           virNodeInfoPtr info);
+  int testNumOfDomains(virConnectPtr conn);
+  int testListDomains(virConnectPtr conn,
+                           int *ids,
+                           int maxids);
+  virDomainPtr testLookupDomainByID(virConnectPtr conn,
+                                         int id);
+  virDomainPtr testLookupDomainByUUID(virConnectPtr conn,
+                                           const unsigned char *uuid);
+  virDomainPtr testLookupDomainByName(virConnectPtr conn,
+                                           const char *name);
+  int testDestroyDomain(virDomainPtr domain);
+  int testResumeDomain(virDomainPtr domain);
+  int testPauseDomain(virDomainPtr domain);
+  int testGetDomainInfo(virDomainPtr domain,
+                             virDomainInfoPtr info);
+  int testGetDomainID(virDomainPtr domain);
+  const char*testGetDomainName(virDomainPtr domain);
+  int testSetMaxMemory(virDomainPtr domain,
+                            unsigned long memory);
+
+#ifdef __cplusplus
+}
+#endif
+#endif                          /* __VIR_TEST_INTERNAL_H__ */