PERFORCE change 190346 for review
John Baldwin
jhb at FreeBSD.org
Mon Mar 21 20:13:42 UTC 2011
http://p4web.freebsd.org/@@190346?ac=10
Change 190346 by jhb at jhb_jhbbsd on 2011/03/21 20:12:48
Add an automated set of regression tests.
Affected files ...
.. //depot/projects/pci/sys/modules/rman/rman.c#3 edit
Differences ...
==== //depot/projects/pci/sys/modules/rman/rman.c#3 (text+ko) ====
@@ -12,6 +12,21 @@
struct rman test;
struct resource *r;
+/* XXX: Gross hack so we can do assertions. Copied from subr_rman.c. */
+struct resource_i {
+ struct resource r_r;
+ TAILQ_ENTRY(resource_i) r_link;
+ LIST_ENTRY(resource_i) r_sharelink;
+ LIST_HEAD(, resource_i) *r_sharehead;
+ u_long r_start; /* index of the first entry in this resource */
+ u_long r_end; /* index of the last entry (inclusive) */
+ u_int r_flags;
+ void *r_virtual; /* virtual address of this resource */
+ struct device *r_dev; /* device which has allocated this resource */
+ struct rman *r_rm; /* resource manager from whence this came */
+ int r_rid; /* optional rid for this resource. */
+};
+
SYSCTL_NODE(_debug, OID_AUTO, rman, CTLFLAG_RD, 0, "rman testing");
static u_long start_value;
@@ -89,7 +104,153 @@
SYSCTL_PROC(_debug_rman, OID_AUTO, release, CTLTYPE_INT | CTLFLAG_RW, 0, 0,
sysctl_rman_release, "I", "release a resource");
+/* Verify that the resource manager is in a correct state. */
+static void
+assert_rman_ok(void)
+{
+ struct resource_i *i;
+
+ i = TAILQ_FIRST(&test.rm_list);
+ KASSERT(i != NULL, ("empty rman"));
+ KASSERT(i->r_start == 0, ("first entry does not start at 0"));
+ if (r == NULL) {
+ /* There should be one free entry for the entire region. */
+ KASSERT(i->r_flags == 0 && i->r_end == 100, ("bad entry"));
+ return;
+ }
+
+ /*
+ * If r does not start at 0, then there should be one free entry
+ * before r.
+ */
+ if (rman_get_start(r) != 0) {
+ KASSERT(i->r_flags == 0 && i->r_end + 1 == rman_get_start(r),
+ ("bogus first free entry"));
+ i = TAILQ_NEXT(i, r_link);
+ }
+
+ /*
+ * 'i' should now be the entry holding allocated resource 'r'
+ */
+ KASSERT(r == &i->r_r, ("resource mismatch"));
+ KASSERT(i->r_flags & RF_ALLOCATED, ("r not allocated"));
+
+ /*
+ * If r does not end at 100, then there should be one free entry
+ * after r.
+ */
+ if (i->r_end != 100) {
+ i = TAILQ_NEXT(i, r_link);
+ KASSERT(i->r_flags == 0 && rman_get_end(r) + 1 == i->r_start,
+ ("bogus last free entry"));
+ }
+
+ /* 'i' should now reference the last entry ending at 100. */
+ KASSERT(i->r_end == 100 && TAILQ_NEXT(i, r_link) == NULL,
+ ("bad last entry"));
+}
+
+static void
+regression_tests(void)
+{
+ int error;
+
+#define ADJUST_SHOULD_FAIL(start, end, err) do { \
+ error = rman_adjust_resource(r, (start), (end)); \
+ if (error == (err)) \
+ printf("Correctly failed to adjust to (%u, %u)\n", \
+ (start), (end)); \
+ else { \
+ if (error) \
+ printf("Failed to adjust to (%u, %u) with %d\n", \
+ (start), (end), error); \
+ else \
+ printf("Incorrectly adjusted to (%lu, %lu)\n", \
+ rman_get_start(r), rman_get_end(r)); \
+ return; \
+ } \
+ assert_rman_ok(); \
+} while (0)
+
+#define ADJUST_SHOULD_WORK(start, end) do { \
+ error = rman_adjust_resource(r, (start), (end)); \
+ if (error) { \
+ printf("Failed to adjust to (%u, %u) with %d\n", \
+ (start), (end), error); \
+ return; \
+ } \
+ if (rman_get_start(r) != (start) || rman_get_end(r) != (end)) { \
+ printf("Adjusted incorrectly, tried (%u, %u)," \
+ " got (%lu, %lu)\n", (start), (end), \
+ rman_get_start(r), rman_get_end(r)); \
+ return; \
+ } \
+ printf("Adjusted to (%lu, %lu)\n", rman_get_start(r), \
+ rman_get_end(r)); \
+ assert_rman_ok(); \
+} while (0)
+
+ /* Allocate a range in the middle: 30-60. */
+ if (r != NULL)
+ rman_release_resource(r);
+ r = rman_reserve_resource(&test, 30, 60, 30, 0, NULL);
+ if (r == NULL) {
+ printf("Failed to allocate resource\n");
+ return;
+ }
+ printf("Allocated (%lu, %lu)\n", rman_get_start(r), rman_get_end(r));
+ assert_rman_ok();
+
+ /* Non-overlapping adjust regions should fail. */
+ ADJUST_SHOULD_FAIL(5, 10, EINVAL);
+ ADJUST_SHOULD_FAIL(5, 29, EINVAL);
+ ADJUST_SHOULD_FAIL(65, 70, EINVAL);
+ ADJUST_SHOULD_FAIL(61, 70, EINVAL);
+
+ /* Shrinking just one end should work. */
+ ADJUST_SHOULD_WORK(35, 60);
+ ADJUST_SHOULD_WORK(35, 55);
+
+ /* Expanding either end should work. */
+ ADJUST_SHOULD_WORK(30, 55);
+ ADJUST_SHOULD_WORK(30, 60);
+
+ /* Shrinking both ends. */
+ ADJUST_SHOULD_WORK(35, 55);
+
+ /* Expanding both ends. */
+ ADJUST_SHOULD_WORK(30, 60);
+
+ /* Shrinking one end, expanding the other. */
+ ADJUST_SHOULD_WORK(35, 65);
+ ADJUST_SHOULD_WORK(30, 60);
+
+ /* Only overlapping with old region at one end. */
+ ADJUST_SHOULD_WORK(60, 75);
+ ADJUST_SHOULD_WORK(30, 60);
+
+ /* Cleaning up. */
+ rman_release_resource(r);
+ r = NULL;
+ assert_rman_ok();
+}
+
static int
+sysctl_rman_test(SYSCTL_HANDLER_ARGS)
+{
+ int error, i = 0;
+
+ error = sysctl_handle_int(oidp, &i, sizeof(i), req);
+ if (error || req->newptr == NULL || i == 0)
+ return (error);
+ regression_tests();
+ return (error);
+}
+SYSCTL_PROC(_debug_rman, OID_AUTO, test, CTLTYPE_INT | CTLFLAG_RW, 0, 0,
+ sysctl_rman_test, "I", "run regression tests");
+
+
+static int
load(void)
{
int error;
@@ -108,6 +269,7 @@
printf("Failed to manage region: %d\n", error);
unload();
}
+ assert_rman_ok();
return (error);
}
@@ -116,8 +278,11 @@
{
int error;
- if (r != NULL)
+ if (r != NULL) {
+ assert_rman_ok();
rman_release_resource(r);
+ }
+ assert_rman_ok();
error = rman_fini(&test);
if (error)
printf("Failed to destroy rman: %d\n", error);
More information about the p4-projects
mailing list