From owner-p4-projects@FreeBSD.ORG Mon Mar 21 20:13:42 2011 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3676B1065675; Mon, 21 Mar 2011 20:13:42 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id ED3E4106566B for ; Mon, 21 Mar 2011 20:13:41 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id DB08D8FC1B for ; Mon, 21 Mar 2011 20:13:41 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id p2LKDfEv067387 for ; Mon, 21 Mar 2011 20:13:41 GMT (envelope-from jhb@freebsd.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id p2LKDfSG067384 for perforce@freebsd.org; Mon, 21 Mar 2011 20:13:41 GMT (envelope-from jhb@freebsd.org) Date: Mon, 21 Mar 2011 20:13:41 GMT Message-Id: <201103212013.p2LKDfSG067384@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to jhb@freebsd.org using -f From: John Baldwin To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 190346 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 Mar 2011 20:13:42 -0000 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);