mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
Added 'mock' hypervisor driver for use by unit tests
This commit is contained in:
parent
88e6f39ae6
commit
e5bb0cb052
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
350
src/test.c
Normal file
350
src/test.c
Normal file
@ -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;
|
||||
}
|
52
src/test.h
Normal file
52
src/test.h
Normal file
@ -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__ */
|
Loading…
Reference in New Issue
Block a user