diff --git a/.gitignore b/.gitignore
index 24469a16e1..2d364dcb25 100644
--- a/.gitignore
+++ b/.gitignore
@@ -159,6 +159,7 @@
/tests/networkxml2argvtest
/tests/nodeinfotest
/tests/nwfilterxml2xmltest
+/tests/objecteventtest
/tests/object-locking
/tests/object-locking-files.txt
/tests/object-locking.cm[ix]
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0900448c33..568b7a0b31 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -303,6 +303,8 @@ EXTRA_DIST += \
$(NULL)
endif ! WITH_LIBVIRTD
+test_programs += objecteventtest
+
if WITH_SECDRIVER_APPARMOR
test_scripts += virt-aa-helper-test
else ! WITH_SECDRIVER_APPARMOR
@@ -895,6 +897,11 @@ fdstreamtest_SOURCES = \
fdstreamtest.c testutils.h testutils.c
fdstreamtest_LDADD = $(LDADDS)
+objecteventtest_SOURCES = \
+ objecteventtest.c \
+ testutils.c testutils.h
+objecteventtest_LDADD = $(LDADDS)
+
if WITH_LINUX
fchosttest_SOURCES = \
fchosttest.c testutils.h testutils.c
diff --git a/tests/objecteventtest.c b/tests/objecteventtest.c
new file mode 100644
index 0000000000..33e2551f48
--- /dev/null
+++ b/tests/objecteventtest.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see
+ * .
+ *
+ * Author: Cedric Bosdonnat
+ */
+
+#include
+
+#include "testutils.h"
+
+#include "virerror.h"
+#include "virxml.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+
+static const char domainDef[] =
+""
+" test-domain"
+" 77a6fc12-07b5-9415-8abb-a803613f2a40"
+" 8388608"
+" 2097152"
+" 2"
+" "
+" hvm"
+" "
+"";
+
+typedef struct {
+ int startEvents;
+ int stopEvents;
+ int defineEvents;
+ int undefineEvents;
+ int unexpectedEvents;
+} lifecycleEventCounter;
+
+static void
+lifecycleEventCounter_reset(lifecycleEventCounter *counter)
+{
+ counter->startEvents = 0;
+ counter->stopEvents = 0;
+ counter->defineEvents = 0;
+ counter->undefineEvents = 0;
+ counter->unexpectedEvents = 0;
+}
+
+typedef struct {
+ virConnectPtr conn;
+} objecteventTest;
+
+
+static int
+domainLifecycleCb(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom ATTRIBUTE_UNUSED,
+ int event,
+ int detail ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ lifecycleEventCounter *counter = opaque;
+
+ switch (event) {
+ case VIR_DOMAIN_EVENT_STARTED:
+ counter->startEvents++;
+ break;
+ case VIR_DOMAIN_EVENT_STOPPED:
+ counter->stopEvents++;
+ break;
+ case VIR_DOMAIN_EVENT_DEFINED:
+ counter->defineEvents++;
+ break;
+ case VIR_DOMAIN_EVENT_UNDEFINED:
+ counter->undefineEvents++;
+ break;
+ default:
+ /* Ignore other events */
+ break;
+ }
+ return 0;
+}
+
+static int
+testDomainCreateXML(const void *data)
+{
+ const objecteventTest *test = data;
+ lifecycleEventCounter counter;
+ int eventId = VIR_DOMAIN_EVENT_ID_LIFECYCLE;
+ virDomainPtr dom;
+ int id;
+ int ret = 0;
+
+ lifecycleEventCounter_reset(&counter);
+
+ id = virConnectDomainEventRegisterAny(test->conn, NULL, eventId,
+ VIR_DOMAIN_EVENT_CALLBACK(&domainLifecycleCb),
+ &counter, NULL);
+ dom = virDomainCreateXML(test->conn, domainDef, 0);
+
+ if (dom == NULL || virEventRunDefaultImpl() < 0) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (counter.startEvents != 1 || counter.unexpectedEvents > 0) {
+ ret = -1;
+ goto cleanup;
+ }
+
+cleanup:
+ virConnectDomainEventDeregisterAny(test->conn, id);
+ if (dom != NULL) {
+ virDomainDestroy(dom);
+ virDomainFree(dom);
+ }
+
+ return ret;
+}
+
+static int
+testDomainDefine(const void *data)
+{
+ const objecteventTest *test = data;
+ lifecycleEventCounter counter;
+ int eventId = VIR_DOMAIN_EVENT_ID_LIFECYCLE;
+ virDomainPtr dom;
+ int id;
+ int ret = 0;
+
+ lifecycleEventCounter_reset(&counter);
+
+ id = virConnectDomainEventRegisterAny(test->conn, NULL, eventId,
+ VIR_DOMAIN_EVENT_CALLBACK(&domainLifecycleCb),
+ &counter, NULL);
+
+ /* Make sure the define event is triggered */
+ dom = virDomainDefineXML(test->conn, domainDef);
+
+ if (dom == NULL || virEventRunDefaultImpl() < 0) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (counter.defineEvents != 1 || counter.unexpectedEvents > 0) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ /* Make sure the undefine event is triggered */
+ virDomainUndefine(dom);
+
+ if (virEventRunDefaultImpl() < 0) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (counter.undefineEvents != 1 || counter.unexpectedEvents > 0) {
+ ret = -1;
+ goto cleanup;
+ }
+
+
+cleanup:
+ virConnectDomainEventDeregisterAny(test->conn, id);
+ if (dom != NULL)
+ virDomainFree(dom);
+
+ return ret;
+}
+
+static int
+testDomainStartStopEvent(const void *data)
+{
+ const objecteventTest *test = data;
+ lifecycleEventCounter counter;
+ int eventId = VIR_DOMAIN_EVENT_ID_LIFECYCLE;
+ int id;
+ int ret = 0;
+ virDomainPtr dom;
+
+ lifecycleEventCounter_reset(&counter);
+
+ dom = virDomainLookupByName(test->conn, "test");
+ if (dom == NULL)
+ return -1;
+
+ id = virConnectDomainEventRegisterAny(test->conn, dom, eventId,
+ VIR_DOMAIN_EVENT_CALLBACK(&domainLifecycleCb),
+ &counter, NULL);
+
+ /* Test domain is started */
+ virDomainDestroy(dom);
+ virDomainCreate(dom);
+
+ if (virEventRunDefaultImpl() < 0) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (counter.startEvents != 1 || counter.stopEvents != 1 ||
+ counter.unexpectedEvents > 0) {
+ ret = -1;
+ goto cleanup;
+ }
+
+cleanup:
+ virConnectDomainEventDeregisterAny(test->conn, id);
+ virDomainFree(dom);
+
+ return ret;
+}
+
+static int
+mymain(void)
+{
+ objecteventTest test;
+ int ret = EXIT_SUCCESS;
+
+ virEventRegisterDefaultImpl();
+
+ if (!(test.conn = virConnectOpen("test:///default")))
+ return EXIT_FAILURE;
+
+ virtTestQuiesceLibvirtErrors(false);
+
+ /* Domain event tests */
+ if (virtTestRun("Domain createXML start event ", testDomainCreateXML, &test) < 0)
+ ret = EXIT_FAILURE;
+ if (virtTestRun("Domain (un)define events", testDomainDefine, &test) < 0)
+ ret = EXIT_FAILURE;
+ if (virtTestRun("Domain start stop events", testDomainStartStopEvent, &test) < 0)
+ ret = EXIT_FAILURE;
+
+ virConnectClose(test.conn);
+
+ return ret;
+}
+
+VIRT_TEST_MAIN(mymain)