Date: Mon, 21 Mar 2011 20:13:41 GMT From: John Baldwin <jhb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 190346 for review Message-ID: <201103212013.p2LKDfSG067384@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@190346?ac=10 Change 190346 by jhb@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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103212013.p2LKDfSG067384>