Tony Breeds
2005-Dec-09  05:55 UTC
[Xen-devel] [PATCH 2/3] make check infrastructure for xen/ directory
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
----- Forwarded message from Rusty Russell <rusty@rustcorp.com.au> -----
To: Tony Breeds <tony@bakeyournoodle.com>
From: Rusty Russell <rusty@rustcorp.com.au>
Subject: [PATCH 2/3] make check infrastructure for xen/ directory
Date: Fri, 09 Dec 2005 16:46:27 +1100
This introduces some fake xen core components and headers, so we can
test each C source file in xen/common in isolation.  The behaviour of
the functions is controlled by the test code, and it also contains extra
sanity checks (eg. memory leaks, locks held, irqs disabled).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
diff -urN --exclude=.hg --exclude=''*~''
--exclude=''*.aux''
xen-unstable.hg-mainline/xen/test/fake-include.h
xen-unstable.hg-check/xen/test/fake-include.h
--- xen-unstable.hg-mainline/xen/test/fake-include.h	1970-01-01
10:00:00.000000000 +1000
+++ xen-unstable.hg-check/xen/test/fake-include.h	2005-12-09 16:33:19.000000000
+1100
@@ -0,0 +1,237 @@
+#ifndef _XEN_TEST_FAKE_INCLUDE
+#define _XEN_TEST_FAKE_INCLUDE
+
+#if (ULONG_MAX >> (CHAR_BIT*4)) == 0
+#define BITS_PER_LONG (CHAR_BIT*4)
+#elif (ULONG_MAX >> (CHAR_BIT*8)) == 0
+#define BITS_PER_LONG (CHAR_BIT*8)
+#else
+#error Cannot determine BITS_PER_LONG
+#endif
+
+#define BITS_TO_LONGS(bits) \
+    (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
+#define DECLARE_BITMAP(name,bits) \
+    unsigned long name[BITS_TO_LONGS(bits)]
+
+/* FIXME: Get rid of EXPORT_SYMBOL */
+#define EXPORT_SYMBOL(sym)
+
+#define __user
+
+#define BUG_ON(x) assert(!(x))
+#define ASSERT(x) assert(x)
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define NR_EVENT_CHANNELS (sizeof(unsigned long) * sizeof(unsigned long) * 64)
+#define MAX_EVTCHNS        NR_EVENT_CHANNELS
+#define EVTCHNS_PER_BUCKET 128
+#define NR_EVTCHN_BUCKETS  (MAX_EVTCHNS / EVTCHNS_PER_BUCKET)
+
+#include "../include/xen/list.h"
+#include "../include/public/xen.h"
+
+unsigned int hweight32(unsigned int w);
+
+/* Linux-style typedefs */
+typedef int64_t s64;
+typedef uint64_t u64;
+typedef int32_t s32;
+typedef uint32_t u32;
+typedef int16_t s16;
+typedef uint16_t u16;
+typedef int8_t s8;
+typedef uint8_t u8;
+
+typedef int64_t s_time_t;
+
+typedef struct {
+	struct list_head _list;
+	const char *_name;
+	int _l;
+} spinlock_t;
+typedef struct {
+	struct list_head _list;
+	const char *_name;
+	unsigned int _w; unsigned int _r;
+} rwlock_t;
+
+#define __cacheline_aligned
+#define unlikely(x) (x)
+#define xmalloc(type)	((type *)fake_xmalloc(sizeof(type), __FILE__, __LINE__))
+#define xmalloc_array(type, num) ((type *)fake_xmalloc(sizeof(type) * (num),
__FILE__, __LINE__))
+void *fake_xmalloc(size_t size, const char *file, int line);
+void fake_xfree(void *p);
+#define xfree(p) fake_xfree(p)
+
+#define for_each_online_cpu(i) for ((i) = 0; (i) < NR_CPUS; (i)++)
+
+extern void printk(const char *format, ...)
+__attribute__ ((format (printf, 1, 2)));
+#define printf printk
+
+/* FIXME: Not used in Xen */
+#define __init
+
+#define NR_CPUS 2
+#define NR_PIRQS 256
+
+s_time_t NOW(void);
+
+void cpu_raise_softirq(unsigned int cpu, unsigned int nr);
+int smp_processor_id(void);
+
+typedef void keyhandler_t(unsigned char key);
+void register_keyhandler(unsigned char key, keyhandler_t *handler,
+			 char *desc);
+
+#define __stringify_1(x)	#x
+#define __stringify(x)		__stringify_1(x)
+
+void spin_lock_init(spinlock_t *lock);
+void _spin_lock_irq(spinlock_t *lock, const char *name);
+void spin_unlock_irq(spinlock_t *lock);
+#define spin_lock_irqsave(lock, flags) \
+	_spin_lock_irqsave((lock), &(flags), __stringify(lock))
+void _spin_lock_irqsave(spinlock_t *lock, unsigned long *flags,
+			const char *name);
+void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
+void _spin_lock(spinlock_t *lock, const char *name);
+void spin_unlock(spinlock_t *lock);
+void _spin_lock_recursive(spinlock_t *lock, const char *name);
+void spin_unlock_recursive(spinlock_t *lock);
+#define spin_lock(lock) _spin_lock(lock, __stringify(lock))
+#define spin_lock_recursive(lock) \
+	_spin_lock_recursive(lock, __stringify(lock))
+#define spin_lock_irq(lock) _spin_lock_irq((lock), __stringify(lock))
+#define SPIN_LOCK_UNLOCKED ((spinlock_t){ ._l = 88 })
+
+void _write_lock(rwlock_t *lock, const char *name);
+void _read_lock(rwlock_t *lock, const char *name);
+#define write_lock(lock) _write_lock((lock), __stringify(lock))
+#define read_lock(lock) _read_lock((lock), __stringify(lock))
+void write_unlock(rwlock_t *lock);
+void read_unlock(rwlock_t *lock);
+
+#define copy_from_user(to, from, n) \
+	fake_copy_from_user((to), (from), (n), __FILE__, __LINE__)
+unsigned long fake_copy_from_user(void *to, const void __user *from,
+				  unsigned n, const char *file, int line);
+#define copy_to_user(to, from, n) \
+	fake_copy_to_user((to), (from), (n), __FILE__, __LINE__)
+unsigned long fake_copy_to_user(void __user *to, const void *from,
+				unsigned n, const char *file, int line);
+
+#define prefetch(x) (0)
+
+#define __initcall(x) 
+
+typedef unsigned long cpumask_t;
+#define CPUMAP_RUNANYWHERE 0xFFFFFFFF
+
+typedef struct { int _val; } atomic_t;
+void atomic_set(atomic_t *a, int i);
+#define _atomic_set(a, i) atomic_set(&(a), (i))
+int atomic_read(atomic_t *a);
+#define _atomic_read(a) atomic_read(&(a))
+void atomic_inc(atomic_t *v);
+int atomic_dec_and_test(atomic_t *a);
+atomic_t atomic_compareandswap(atomic_t old, atomic_t new, atomic_t *v);
+unsigned int __cmpxchg(volatile void *ptr, 
+		       unsigned long old, 
+		       unsigned long new, 
+		       int size);
+
+void set_bit(int bit, void *addr);
+void clear_bit(int bit, void *addr);
+int test_bit(int bit, void *addr);
+int test_and_set_bit(int bit, void *addr);
+int test_and_clear_bit(int bit, void *addr);
+
+struct domain {
+	domid_t          domain_id;
+	spinlock_t       big_lock;
+	shared_info_t   *shared_info;
+	atomic_t         refcnt;
+	void            *ssid;
+	unsigned long    domain_flags;
+	int              shutdown_code;
+	struct list_head page_list;
+	struct list_head xenpage_list;
+	spinlock_t       page_alloc_lock;
+	struct domain   *next_in_list;
+	struct domain   *next_in_hashbucket;
+	struct vcpu     *vcpu[MAX_VIRT_CPUS];
+	cpumask_t        cpumask;
+	unsigned long    vm_assist;
+	struct evtchn   *evtchn[NR_EVTCHN_BUCKETS];
+	spinlock_t       evtchn_lock;
+	u16              pirq_to_evtchn[NR_PIRQS];
+	unsigned int     tot_pages;
+	unsigned int     max_pages;
+	xen_domain_handle_t handle;
+	u32              pirq_mask[NR_PIRQS/32];
+};
+
+struct vcpu {
+	int              vcpu_id;
+	int              processor;
+	struct domain   *domain;
+	struct vcpu     *next_in_list;
+	atomic_t         pausecnt;
+	unsigned long    vcpu_flags;
+	u16              virq_to_evtchn[NR_VIRQS];
+	s_time_t         cpu_time;
+	cpumap_t         cpumap;
+};
+
+struct cpu_info {
+    struct cpu_user_regs guest_cpu_user_regs;
+    unsigned int         processor_id;
+    struct vcpu         *current_ed;
+};
+
+/* evntchn state values */
+#define ECS_FREE         0
+#define ECS_RESERVED     1
+#define ECS_UNBOUND      2
+#define ECS_INTERDOMAIN  3
+#define ECS_PIRQ         4
+#define ECS_VIRQ         5
+#define ECS_IPI          6
+
+struct evtchn
+{
+    u16 state;
+    u16 notify_vcpu_id;
+    union {
+        struct {
+            domid_t remote_domid;
+        } unbound;
+        struct {
+            u16            remote_port;
+            struct domain *remote_dom;
+        } interdomain;
+        u16 pirq;
+        u16 virq;
+    } u;
+};
+
+extern struct vcpu *current;
+void domain_destruct(struct domain *d);
+void put_domain(struct domain *d);
+int get_domain(struct domain *d);
+int IS_PRIV(struct domain *d);
+
+struct domain *find_domain_by_id(domid_t dom);
+
+void put_domain(struct domain *d);
+
+#define IDLE_DOMAIN_ID   (0x7FFFU)
+#define is_idle_task(_d) (test_bit(_DOMF_idle_domain,
&(_d)->domain_flags))
+
+#define RW_LOCK_UNLOCKED ((rwlock_t) { ._r = 0, ._w = 0 })
+#define rwlock_init(x)	do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+
+#define always_inline
+#endif /* _XEN_TEST_FAKE_INCLUDE */
diff -urN --exclude=.hg --exclude=''*~''
--exclude=''*.aux''
xen-unstable.hg-mainline/xen/test/fake-support.h
xen-unstable.hg-check/xen/test/fake-support.h
--- xen-unstable.hg-mainline/xen/test/fake-support.h	1970-01-01
10:00:00.000000000 +1000
+++ xen-unstable.hg-check/xen/test/fake-support.h	2005-12-09 16:33:19.000000000
+1100
@@ -0,0 +1,81 @@
+/* Routines for tests to manipulate the results of the fake xen functions */
+#ifndef _FAKE_SUPPORT_H
+#define _FAKE_SUPPORT_H
+
+#include "fake-include.h"
+
+/* Use these in tests to create __user pointers. */
+void __user *fake_to_user(const void *p);
+void *fake_from_user(const void __user *p);
+
+/* Use this to make sure all memory has been initialized (under
+ * valgrind).  Ignore return val. */
+int fake_check_memory(void *mem, unsigned len);
+
+/* Locks held and irqs blocked. */
+extern unsigned int fake_lock_count;
+extern unsigned int fake_irq_state;
+
+/* cpu_raise_softirq */
+extern unsigned int fake_cpu_raise_softirq_in_cpu;
+extern unsigned int fake_cpu_raise_softirq_in_nr;
+
+/* register_keyhandler */
+extern unsigned char fake_register_keyhandler_in_key;
+extern keyhandler_t *fake_register_keyhandler_in_handler;
+extern char *fake_register_keyhandler_in_desc;
+
+/* NOW */
+extern s_time_t fake_NOW_out;
+
+/* get_domain */
+extern struct domain *fake_get_domain_in_d;
+extern int fake_get_domain_out;
+
+/* IS_PRIV */
+extern struct domain *_fake_IS_PRIV_in_d;
+extern int fake_IS_PRIV_out;
+
+/* xmalloc */
+extern int fake_xmalloc_out_FAIL;
+/* Adjust this if you know how many bytes will be allocated/freed */
+extern unsigned int fake_xmalloc_expected;
+/* Use these flags to indicate that something will be allocated/freed */
+extern int fake_expect_xmalloc, fake_expect_xfree;
+
+/* Sometimes the lock is not in scope, so we use name. */
+extern void fake_must_have_spinlock(const char *);
+extern void fake_must_have_readlock(const char *);
+extern void fake_must_have_writelock(const char *);
+
+/* xfree */
+extern void *fake_xfree_in_ptr;
+
+/* find_domain_by_id */
+extern struct domain *fake_find_domain_out;
+
+/* Test suite command line processor */
+extern void parse_test_args(int argc, char *argv[]);
+
+/* Dynamic suppression registration */
+extern void register_suppression(const char *file, int line);
+
+/* Checks no locks held, no irqs disabled, no memory leaks */
+extern void fake_check_status(const char *file, int line);
+
+#define test_cond(expr)	\
+do {								\
+	int _x = (expr);                                        \
+	fake_check_status(__FILE__, __LINE__);			\
+	if (!(_x))						\
+		test_cond_fail(#expr, __FILE__, __LINE__,	\
+				__PRETTY_FUNCTION__);		\
+} while (0)
+
+
+extern void __attribute__((noreturn)) test_cond_fail(const char *expression, 
+                                                     const char *file,
+						     int line, 
+						     const char *function);
+
+#endif /* _FAKE_SUPPORT_H */
diff -urN --exclude=.hg --exclude=''*~''
--exclude=''*.aux'' xen-unstable.hg-mainline/xen/test/fake.c
xen-unstable.hg-check/xen/test/fake.c
--- xen-unstable.hg-mainline/xen/test/fake.c	1970-01-01 10:00:00.000000000 +1000
+++ xen-unstable.hg-check/xen/test/fake.c	2005-12-09 16:33:19.000000000 +1100
@@ -0,0 +1,671 @@
+/*  Generic routines which most things in the Xen core expect.
+    Copyright (C) 2005 Rusty Russell IBM Corporation
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include "fake-support.h"
+
+/* All these functions can be overridden by individual tests. */
+#define __override __attribute__((weak))
+
+struct suppression {
+	struct list_head list;
+	int  line;
+	char *file;
+};
+
+enum test_is {ON=0, OFF=1};
+
+enum option_bits {
+	XMALLOC_FAIL=0,
+	USERCOPY_FAIL=1,
+};
+
+struct option {
+	enum option_bits bit;
+	char *name;
+};
+
+static struct option options[] = { 
+	{ .bit = XMALLOC_FAIL,  .name = "xmalloc"  },
+	{ .bit = USERCOPY_FAIL, .name = "usercopy" },
+};
+
+static char *arg_prefixes[] = {
+	"--fail-tests=", 
+	"--fail-", 
+	"--nofail-tests=", 
+	"--nofail-",
+};
+
+static char *sep = ",";
+static char *negate = "--no";
+
+static unsigned long active_tests = ULONG_MAX;
+
+struct failure {
+	struct list_head list;
+	const char *file;
+	int line;
+};
+static LIST_HEAD(failures);
+static LIST_HEAD(suppressions);
+
+void register_suppression(const char *file, int line)
+{
+	struct suppression *s;
+
+	s = malloc(sizeof(*s));
+	s->file = file;
+	s->line = line;
+	list_add_tail(&s->list, &suppressions);
+}
+
+static void print_failures(const char *file, int line)
+{
+	struct failure *i;
+
+	fprintf(stderr, "--failures=");
+	list_for_each_entry(i, &failures, list)
+		fprintf(stderr, "%s:%i,", i->file, i->line);
+	fprintf(stderr, "%s:%i\n", file, line);
+}
+
+static int should_i_fail(const char *file, int line, int option_bit)
+{
+	int status;
+	pid_t pid;
+	struct failure *f;
+	struct suppression *s;
+
+	if (!(active_tests & (1<<option_bit)))
+		return 0;
+
+	list_for_each_entry(s, &suppressions, list) {
+		if (s->line == line && strcmp(s->file, file) == 0) {
+			return 0;
+		}
+	}
+
+	pid = fork();
+	if (pid == 0) {
+		f = malloc(sizeof(*f));
+		f->file = file;
+		f->line = line;
+		list_add_tail(&f->list, &failures);
+		return 1;
+	}
+
+	if (pid == -1) {
+		fprintf(stderr, "Failed to fork() child: %s\n", 
+			strerror(errno));
+		exit(1);
+	}
+
+	waitpid(pid, &status, 0);
+	if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
+		/* 7 means child already printed error msg. */
+		if (!WIFEXITED(status) || WEXITSTATUS(status) != 7) {
+			fprintf(stderr, "Child %d %s %i\n", (int)pid,
+				WIFEXITED(status) ? "exited with status"
+				: "died with signal",
+				WIFEXITED(status) ? WEXITSTATUS(status)
+				: WTERMSIG(status));
+			print_failures(file, line);
+		}
+		exit(7);
+	}
+	return 0;
+}
+
+unsigned int __override hweight32(unsigned int w)
+{
+        unsigned int res = (w & 0x55555555) + ((w >> 1) &
0x55555555);
+
+        res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+        res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
+        res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
+        return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
+}
+
+void __override atomic_set(atomic_t *a, int i)
+{
+	a->_val = ~i;
+}
+
+int __override atomic_dec_and_test(atomic_t *a)
+{
+	assert(~(a->_val) != 0);
+	a->_val = ~(~a->_val - 1);
+	return (~a->_val == 0);
+}
+
+void __override atomic_inc(atomic_t *a)
+{
+	a->_val = ~(~a->_val + 1);
+}
+
+int __override atomic_read(atomic_t *a)
+{
+	return ~a->_val;
+}
+
+unsigned int __override __cmpxchg(volatile void *ptr, 
+				  unsigned long old, 
+				  unsigned long new, 
+				  int size)
+{
+	unsigned long prev;
+
+	switch (size) {
+	case 1:
+		prev = *(u8 *)ptr;
+		if (prev == old)
+			*(u8 *)ptr = new;
+		break;
+	case 2:
+		prev = *(u16 *)ptr;
+		if (prev == old)
+			*(u16 *)ptr = new;
+		break;
+	case 4:
+		prev = *(u32 *)ptr;
+		if (prev == old)
+			*(u32 *)ptr = new;
+		break;
+#ifdef __x86_64__
+	case 8:
+		prev = *(u64 *)ptr;
+		if (prev == old)
+			*(u64 *)ptr = new;
+		break;
+#endif
+	default:
+		assert(0);
+	}
+	return prev;
+}
+
+atomic_t __override atomic_compareandswap(atomic_t old, atomic_t new, atomic_t
*v)
+{
+	atomic_t rc;
+	rc._val = __cmpxchg(&v->_val, old._val, new._val, sizeof(*v));
+	return rc;
+}
+
+void __override printk(const char *format, ...)
+{
+	abort();
+}
+
+unsigned int fake_cpu_raise_softirq_in_cpu;
+unsigned int fake_cpu_raise_softirq_in_nr;
+void __override cpu_raise_softirq(unsigned int cpu, unsigned int nr)
+{
+	fake_cpu_raise_softirq_in_cpu = cpu;
+	fake_cpu_raise_softirq_in_nr = nr;
+}
+
+unsigned char fake_register_keyhandler_in_key;
+keyhandler_t *fake_register_keyhandler_in_handler;
+char *fake_register_keyhandler_in_desc;
+void __override register_keyhandler(unsigned char key, keyhandler_t *handler,
+				    char *desc)
+{
+	fake_register_keyhandler_in_key = key;
+	fake_register_keyhandler_in_handler = handler;
+	fake_register_keyhandler_in_desc = desc;
+}
+
+unsigned int fake_lock_count = 0;
+unsigned int fake_irq_state = 0;
+void __override spin_lock_init(spinlock_t *lock)
+{
+	*lock = SPIN_LOCK_UNLOCKED;
+}
+
+static LIST_HEAD(spinlocks);
+void _spin_lock(spinlock_t *lock, const char *name)
+{
+	assert(lock->_l == 88);
+	list_add(&lock->_list, &spinlocks);
+	lock->_name = name;
+	lock->_l = 89;
+	fake_lock_count++;
+}
+
+void spin_unlock(spinlock_t *lock)
+{
+	assert(lock->_l == 89);
+	list_del(&lock->_list);
+	*lock = SPIN_LOCK_UNLOCKED;
+	assert(fake_lock_count > 0);
+	fake_lock_count--;
+}
+
+void __override _spin_lock_irqsave(spinlock_t *lock, unsigned long *flags,
+				   const char *name)
+{
+	_spin_lock(lock, name);
+	*flags = (776 + (long)lock) | fake_irq_state;
+	fake_irq_state = 1;
+}
+
+void __override _spin_lock_irq(spinlock_t *lock, const char *name)
+{
+	_spin_lock(lock, name);
+	assert(fake_irq_state == 0);
+	fake_irq_state = 1;
+}
+
+void __override spin_unlock_irq(spinlock_t *lock)
+{
+	spin_unlock(lock);
+	assert(fake_irq_state == 1);
+	fake_irq_state = 0;
+}
+
+void __override spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
+{
+	spin_unlock(lock);
+	assert((flags & ~0x1UL) == 776 + (long)lock);
+	fake_irq_state = (flags & 1);
+}
+
+static LIST_HEAD(rwlocks);
+void __override _write_lock(rwlock_t *lock, const char *name)
+{
+	list_add(&lock->_list, &rwlocks);
+	lock->_name = name;
+	assert(lock->_w == 0);
+	assert(lock->_r == 0);
+	lock->_w = 1;
+}
+
+void __override _read_lock(rwlock_t *lock, const char *name)
+{
+	list_add(&lock->_list, &rwlocks);
+	lock->_name = name;
+	assert(lock->_w == 0);
+	assert(lock->_r == 0);
+	lock->_r = 1;
+}
+
+void __override write_unlock(rwlock_t *lock)
+{
+	list_del(&lock->_list);
+	assert(lock->_w == 1);
+	assert(lock->_r == 0);
+	lock->_w = 0;
+}
+
+void __override read_unlock(rwlock_t *lock)
+{
+	list_del(&lock->_list);
+	assert(lock->_w == 0);
+	assert(lock->_r == 1);
+	lock->_r = 0;
+}
+
+/* FIXME: Recursion isn''t actually supported in this test suite */
+void __override _spin_lock_recursive(spinlock_t *lock, const char *name)
+{
+	_spin_lock(lock, name);
+}
+
+void __override spin_unlock_recursive(spinlock_t *lock)
+{
+	spin_unlock(lock);
+}
+
+
+int __override smp_processor_id(void)
+{
+	return 0;
+}
+
+s_time_t fake_NOW_out;
+s_time_t __override NOW(void)
+{
+	return fake_NOW_out;
+}
+
+void __override domain_destruct(struct domain *d)
+{
+	free(d);
+}
+
+struct domain *fake_put_domain_in_d;
+void __override put_domain(struct domain *d)
+{
+	fake_put_domain_in_d = d;
+	if (atomic_dec_and_test(&d->refcnt))
+		domain_destruct(d);
+}
+
+struct domain *fake_get_domain_in_d;
+int fake_get_domain_out = 1;
+int __override get_domain(struct domain *d)
+{
+	fake_get_domain_in_d = d;
+	if (!fake_get_domain_out)
+		return 0;
+	atomic_inc(&d->refcnt);
+	return 1;
+}
+
+struct domain *fake_find_domain_out;
+struct domain *__override find_domain_by_id(domid_t dom)
+{
+	if (!fake_find_domain_out)
+		return NULL;
+
+	atomic_inc(&fake_find_domain_out->refcnt);
+	return fake_find_domain_out;
+}
+
+void __override set_bit(int bit, void *addr)
+{
+	unsigned long *bitmap = (unsigned long *)addr;
+	bitmap[bit/BITS_PER_LONG] |= (1 << (bit%BITS_PER_LONG));
+}
+
+void __override clear_bit(int bit, void *addr)
+{
+	unsigned long *bitmap = (unsigned long *)addr;
+	bitmap[bit/BITS_PER_LONG] &= ~(1 << (bit%BITS_PER_LONG));
+}
+
+int __override test_bit(int bit, void *addr)
+{
+	unsigned long *bitmap = (unsigned long *)addr;
+
+	return bitmap[bit/BITS_PER_LONG] & (1 << (bit%BITS_PER_LONG));
+}
+
+int __override test_and_set_bit(int bit, void *addr)
+{
+	int old = test_bit(bit, addr);
+	set_bit(bit, addr);
+
+	return old;
+}
+
+int __override test_and_clear_bit(int bit, void *addr)
+{
+	int old = test_bit(bit, addr);
+	clear_bit(bit, addr);
+
+	return old;
+}
+
+/* Use these in tests to create __user pointers: we bit-invert them. */
+void __user *__override fake_to_user(const void *p)
+{
+	return (void *)~((unsigned long)p);
+}
+	
+void *__override fake_from_user(const void __user *p)
+{
+	return (void *)~((unsigned long)p);
+}
+
+unsigned long __override fake_copy_from_user(void *to,
+					     const void __user *from,
+					     unsigned n,
+					     const char *file,
+					     int line)
+{
+	if (should_i_fail(file, line, USERCOPY_FAIL))
+		return 1;
+
+	memcpy(to, fake_from_user(from), n);
+	return 0;
+}
+
+unsigned long __override fake_copy_to_user(void __user *to, const void *from,
+					   unsigned n,
+					   const char *file,
+					   int line)
+{
+	if (should_i_fail(file, line, USERCOPY_FAIL))
+		return 1;
+
+	memcpy(fake_from_user(to), from, n);
+	return 0;
+}
+
+struct fake_xmalloc_hdr
+{
+	const char *file;
+	int line;
+	size_t size;
+};
+
+static int fake_xmalloc_bytes;
+unsigned int fake_xmalloc_expected;
+int fake_expect_xmalloc, fake_expect_xfree;
+void *fake_xmalloc(size_t size, const char *file, int line)
+{
+	struct fake_xmalloc_hdr *h;
+	if (should_i_fail(file, line, XMALLOC_FAIL))
+		return NULL;
+
+	h = malloc(sizeof(*h) + size);
+	h->file = file;
+	h->line = line;
+	h->size = size;
+
+	fake_xmalloc_bytes += size;
+	return h+1;
+}
+
+struct domain *fake_IS_PRIV_in_d;
+/* Assume privilege unless told otherwise */
+int fake_IS_PRIV_out = 1;
+int __override IS_PRIV(struct domain *d)
+{
+	fake_IS_PRIV_in_d = d;
+	return fake_IS_PRIV_out;
+}
+
+void *fake_xfree_in_ptr;
+void fake_xfree(void *ptr)
+{
+	struct fake_xmalloc_hdr *h;
+
+	if (ptr == NULL) 
+		return;
+
+	fake_xfree_in_ptr = ptr;
+
+	h = ((struct fake_xmalloc_hdr *)ptr)-1;
+
+	fake_xmalloc_bytes -= h->size;
+	assert(fake_xmalloc_bytes >= 0);
+
+	free(h);
+}
+
+struct vcpu *current;
+
+/* Use this to check that memory has been fully initialized (valgrind).
+ * We don''t use memcheck.h''s VALGRIND_CHECK_DEFINED since we
don''t want to
+ * depend on valgrind.  Ignore return value. */
+int fake_check_memory(void *mem, unsigned len)
+{
+	unsigned int i, sum = 0;
+
+	for (i = 0; i < len; i++) 
+		sum += ((char *)mem)[i];
+
+	/* Valgrind not that bright: as soon as we "use" result it will
+	 * complain if uninitialized */
+	if (sum)
+		return 100;
+	return 0;
+}
+
+static void process_test_arg(char *arg, enum test_is state)
+{
+	char *arg_pos;
+
+	arg_pos = strtok(arg, sep);
+	do {
+		int i;
+		unsigned long mask = 0UL;
+		int found = 0;
+
+		if (arg_pos == NULL)
+			break;
+
+		for(i=0; i<ARRAY_SIZE(options); i++) {
+			if (strcmp("all", arg_pos) == 0) {
+				found = 1;
+				mask = ULONG_MAX;
+				if (state == OFF) {
+					mask = 0UL;
+				}
+			} else if (strcmp("none", arg_pos) == 0) {
+				found = 1;
+				mask = 0UL;
+				if (state == OFF) {
+					mask = ULONG_MAX;
+				}
+			} else if (strcmp(options[i].name, arg_pos) == 0) {
+				found = 1;
+				mask = (1<<options[i].bit);
+			}
+
+			if (found) {
+				if (state == ON) {
+					active_tests |= mask;
+				} else {
+					active_tests ^= ~mask;
+				}
+
+				break;
+			}
+
+		}
+
+	} while ((arg_pos = strtok(NULL, sep)) != NULL);
+}
+
+void parse_test_args(int argc, char *argv[])
+{
+	int i = 0;
+
+	while (++i < argc) {
+		int j;
+		for(j=0; j<ARRAY_SIZE(arg_prefixes); j++) {
+			int len = strlen(arg_prefixes[j]);
+
+			if (strncmp(arg_prefixes[j], argv[i], len) == 0) {
+				enum test_is state = ON;
+				if (strstr(arg_prefixes[j], negate) != NULL) {
+					state = OFF;
+				}
+				process_test_arg(argv[i] +len, state);
+			}
+		}
+	}
+}
+
+static void __attribute__((noreturn))
+test_fail(const char *file, int line, const char *function,
+	  const char *expression)
+{
+	fprintf(stderr, "%s:%d: %s: Fake Assertion `%s'' failed.\n",
+			file, line, function, expression);
+	abort();
+}
+
+/* assert */
+void test_cond_fail(const char *expression, const char *file,
+                    int line, const char *function)
+{
+	/* Failures will... err... cause failure. */
+	if (!list_empty(&failures))
+		exit(0);
+
+	test_fail(file, line, function, expression);
+}
+
+void fake_must_have_spinlock(const char *name)
+{
+	spinlock_t *i;
+	list_for_each_entry(i, &spinlocks, _list)
+		if (strcmp(i->_name, name) == 0)
+			return;
+	assert(0);
+}
+
+void fake_must_have_readlock(const char *name)
+{
+	rwlock_t *i;
+	list_for_each_entry(i, &rwlocks, _list)
+		if (strcmp(i->_name, name) == 0) {
+			assert(i->_r && !i->_w);
+			return;
+		}
+	assert(0);
+}
+
+void fake_must_have_writelock(const char *name)
+{
+	rwlock_t *i;
+	list_for_each_entry(i, &rwlocks, _list)
+		if (strcmp(i->_name, name) == 0) {
+			assert(i->_w && !i->_r);
+			return;
+		}
+	assert(0);
+}
+
+/* Checks no locks held, no irqs disabled, no memory leaks */
+void fake_check_status(const char *file, int line)
+{
+	if (fake_expect_xmalloc) {
+		if (fake_xmalloc_bytes <= fake_xmalloc_expected)
+			test_cond_fail("xmalloc expected", file, line,
+				       "test_cond");
+		fake_xmalloc_expected = fake_xmalloc_bytes;
+		fake_expect_xmalloc = 0;
+	} else if (fake_expect_xfree) {
+		if (fake_xmalloc_bytes >= fake_xmalloc_expected)
+			test_cond_fail("xfree expected", file, line,
+				       "test_cond");
+		fake_xmalloc_expected = fake_xmalloc_bytes;
+		fake_expect_xfree = 0;
+	} else if (fake_xmalloc_bytes != fake_xmalloc_expected)
+		test_fail(file, line, "test_cond", "xmalloc leak");
+	if (fake_lock_count != 0)
+		test_fail(file, line, "test_cond", "spinlock leak");
+	if (fake_irq_state != 0)
+		test_fail(file, line, "test_cond", "irq leak");
+}
-- 
 ccontrol: http://freshmeat.net/projects/ccontrol
----- End forwarded message -----
Yours Tony
   linux.conf.au       http://linux.conf.au/ || http://lca2006.linux.org.au/
   Jan 23-28 2006      The Australian Linux Technical Conference!
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel