From 9ad3de64b1d6fdcb06113ce845bd57911e032907 Mon Sep 17 00:00:00 2001 From: Nicolas Benech Date: Fri, 27 Sep 2019 10:23:51 -0400 Subject: [PATCH] gpu: nvgpu: unit: SWUTS for interface.rbtree Add SWUTS documentation for the interface.rbtree unit. JIRA NVGPU-3943 Change-Id: I9555090bc986f5cea76add6a46309a13b37f371c Signed-off-by: Nicolas Benech Reviewed-on: https://git-master.nvidia.com/r/2207312 Reviewed-by: mobile promotions Tested-by: mobile promotions --- userspace/SWUTS.h | 1 + userspace/SWUTS.sources | 1 + userspace/units/interface/rbtree/rbtree.c | 100 +------- userspace/units/interface/rbtree/rbtree.h | 282 ++++++++++++++++++++++ 4 files changed, 292 insertions(+), 92 deletions(-) create mode 100644 userspace/units/interface/rbtree/rbtree.h diff --git a/userspace/SWUTS.h b/userspace/SWUTS.h index 0cc8717d5..e4d9e41e6 100644 --- a/userspace/SWUTS.h +++ b/userspace/SWUTS.h @@ -33,6 +33,7 @@ * - @ref SWUTS-enabled * - @ref SWUTS-interface-bsearch * - @ref SWUTS-interface-lock + * - @ref SWUTS-interface-rbtree * - @ref SWUTS-fifo * - @ref SWUTS-fifo-channel * - @ref SWUTS-fifo-runlist diff --git a/userspace/SWUTS.sources b/userspace/SWUTS.sources index 7c8e4d1bb..270ffcef8 100644 --- a/userspace/SWUTS.sources +++ b/userspace/SWUTS.sources @@ -3,6 +3,7 @@ INPUT += ../../../userspace/units/cg/nvgpu-cg.h INPUT += ../../../userspace/units/enabled/nvgpu-enabled.h INPUT += ../../../userspace/units/interface/bsearch/bsearch.h INPUT += ../../../userspace/units/interface/lock/lock.h +INPUT += ../../../userspace/units/interface/rbtree/rbtree.h INPUT += ../../../userspace/units/fifo/nvgpu-fifo.h INPUT += ../../../userspace/units/fifo/channel/nvgpu-channel.h INPUT += ../../../userspace/units/fifo/runlist/nvgpu-runlist.h diff --git a/userspace/units/interface/rbtree/rbtree.c b/userspace/units/interface/rbtree/rbtree.c index f80d1b9f0..9062542c5 100644 --- a/userspace/units/interface/rbtree/rbtree.c +++ b/userspace/units/interface/rbtree/rbtree.c @@ -27,56 +27,7 @@ #include #include -/* - * To make testing easier, most tests will use the same rbtree that is built - * according to: - * - The tree will contain 9 nodes (10 insertions, but one rejected as - * duplicate) - * - The values in the tree express a range. All nodes have the same range. - * - The values and the order in which they are inserted is carefully chosen - * to maximize code coverage by ensuring that all corner cases are hit - */ -#define INITIAL_ELEMENTS 10 -#define RANGE_SIZE 10U - -/* - * Sample tree used throughout this unit. Node values below are key_start. - * - * 130 (Black) - * / \ - * / \ - * 50 200 (Red) - * / \ / \ - * 30 80 170 300 (Black) - * / / - * 10 120 (Red) - * - * NOTE: There is a duplicate entry that will be ignored during insertion. - */ -#define DUPLICATE_VALUE 300 -u64 initial_key_start[] = {50, 30, 80, 100, 170, 10, 200, DUPLICATE_VALUE, - DUPLICATE_VALUE, 120}; - -/* - * The following key value should not exist or cover a range from the keys - * above. - */ -#define INVALID_KEY_START 2000 - -/* - * The following key will be used to search and range_search in the tree. It is - * chosen so that paths taken will involve both left and right branches. - */ -#define SEARCH_KEY 120 - -/* - * The values below will cause the red-black properties to be violated upon - * insertion into the tree defined above. As a result, these will trigger - * specific cases during the tree rebalancing procedure. - */ -#define RED_BLACK_VIOLATION_1 20 -#define RED_BLACK_VIOLATION_2 320 - +#include "rbtree.h" struct nvgpu_rbtree_node *elements[INITIAL_ELEMENTS]; @@ -194,13 +145,7 @@ static void free_test_tree(struct unit_module *m, /* No need to explicitly free the root as it was one of the elements */ } -/* - * Test to check the nvgpu_rbtree_insert operation. - * First will create the test tree and check that it is valid. - * Then it will insert some well chosen values to target specific branches - * in the re-balancing code. - */ -static int test_insert(struct unit_module *m, struct gk20a *g, void *args) +int test_insert(struct unit_module *m, struct gk20a *g, void *args) { struct nvgpu_rbtree_node *root = NULL; struct nvgpu_rbtree_node *node1, *node2 = NULL; @@ -236,13 +181,7 @@ free_tree: return status; } -/* - * Test to check the nvgpu_rbtree_unlink operation by removing every node from - * the tree. - * This test will also use the nvgpu_rbtree_search operation to check that - * the node was effectively removed. - */ -static int test_unlink(struct unit_module *m, struct gk20a *g, void *args) +int test_unlink(struct unit_module *m, struct gk20a *g, void *args) { struct nvgpu_rbtree_node *root = NULL; struct nvgpu_rbtree_node *result = NULL; @@ -301,11 +240,7 @@ cleanup: return status; } -/* - * Test to check the nvgpu_rbtree_search and nvgpu_rbtree_range_search routines - * and go over some error handling. - */ -static int test_search(struct unit_module *m, struct gk20a *g, void *args) +int test_search(struct unit_module *m, struct gk20a *g, void *args) { struct nvgpu_rbtree_node *root = NULL; struct nvgpu_rbtree_node *result1, *result2 = NULL; @@ -370,11 +305,7 @@ cleanup: return status; } -/* - * Test to check the nvgpu_rbtree_enum_start routine and go over some error - * handling. - */ -static int test_enum(struct unit_module *m, struct gk20a *g, void *args) +int test_enum(struct unit_module *m, struct gk20a *g, void *args) { struct nvgpu_rbtree_node *root = NULL; struct nvgpu_rbtree_node *node = NULL; @@ -414,13 +345,7 @@ cleanup: return status; } -/* - * Test to check the nvgpu_rbtree_enum_next routine and go over some error - * handling. - * nvgpu_rbtree_enum_next will find the next node whose key_start value is - * greater than the one in the provided node. - */ -static int test_enum_next(struct unit_module *m, struct gk20a *g, void *args) +int test_enum_next(struct unit_module *m, struct gk20a *g, void *args) { struct nvgpu_rbtree_node *root = NULL; struct nvgpu_rbtree_node *node = NULL; @@ -468,11 +393,7 @@ cleanup: return status; } -/* - * Test to check the nvgpu_rbtree_less_than_search routine. - * Given a key_start value, find a node with a lower key_start value. - */ -static int test_search_less(struct unit_module *m, struct gk20a *g, void *args) +int test_search_less(struct unit_module *m, struct gk20a *g, void *args) { struct nvgpu_rbtree_node *root = NULL; struct nvgpu_rbtree_node *result; @@ -505,12 +426,7 @@ cleanup: return status; } -/* - * Test corner cases in nvgpu_rbtree_unlink (and delete_fixup) to increase - * branch and line coverage. - */ -static int test_unlink_corner_cases(struct unit_module *m, struct gk20a *g, - void *args) +int test_unlink_corner_cases(struct unit_module *m, struct gk20a *g, void *args) { struct nvgpu_rbtree_node *root = NULL; u64 more_key_start[] = {0x1000, 0x61000, 0x79000, 0x7d000, 0x7f000, diff --git a/userspace/units/interface/rbtree/rbtree.h b/userspace/units/interface/rbtree/rbtree.h new file mode 100644 index 000000000..02cf44a23 --- /dev/null +++ b/userspace/units/interface/rbtree/rbtree.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef UNIT_RBTREE_H +#define UNIT_RBTREE_H + +struct gk20a; +struct unit_module; + +/** @addtogroup SWUTS-interface-rbtree + * @{ + * + * Software Unit Test Specification for interface.rbtree + * + * To make testing easier, most tests will use the same rbtree that is built + * according to: + * - The tree will contain 9 nodes (10 insertions, but one rejected as + * duplicate). + * - The values in the tree express a range. All nodes have the same range. + * - The values and the order in which they are inserted is carefully chosen + * to maximize code coverage by ensuring that all corner cases are hit. + * + * Refer to #initial_key_start for the definition of the test tree. + */ + +/** + * Number of initial elements in the test tree. + */ +#define INITIAL_ELEMENTS 10 + +/** + * Range of each element in the test tree. + */ +#define RANGE_SIZE 10U + +/** + * This value is to be used twice in the test tree to create a duplicate. + */ +#define DUPLICATE_VALUE 300 + +/** + * Sample tree used throughout this unit. Node values below are key_start. + * + * 130 (Black) + * / \ + * / \ + * 50 200 (Red) + * / \ / \ + * 30 80 170 300 (Black) + * / / + * 10 120 (Red) + * + * NOTE: There is a duplicate entry that will be ignored during insertion. + */ + +u64 initial_key_start[] = {50, 30, 80, 100, 170, 10, 200, DUPLICATE_VALUE, + DUPLICATE_VALUE, 120}; + +/** + * The following key value should not exist or cover a range from the keys + * above. + */ +#define INVALID_KEY_START 2000 + +/** + * The following key will be used to search and range_search in the tree. It is + * chosen so that paths taken will involve both left and right branches. + */ +#define SEARCH_KEY 120 + +/** + * The values below will cause the red-black properties to be violated upon + * insertion into the tree defined above. As a result, these will trigger + * specific cases during the tree rebalancing procedure. + */ +#define RED_BLACK_VIOLATION_1 20 +#define RED_BLACK_VIOLATION_2 320 + +/** + * Test specification for: test_insert + * + * Description: Test to check the nvgpu_rbtree_insert operation. + * + * Test Type: Feature + * + * Input: None + * + * Steps: + * - Create a test tree with known values. + * - Perform all the checks to ensure the resulting tree has all the properties + * of a red-black tree. + * - Insert 2 well known values defined by RED_BLACK_VIOLATION_1 and + * RED_BLACK_VIOLATION_2 to cause red-black violations upon insertion. + * - Check the red-black correctness again to ensure that the insertion + * algorithm rebalanced the tree after the 2 insertions. + * - Free the test tree. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_insert(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_unlink + * + * Description: Test to check the nvgpu_rbtree_unlink operation by removing + * every node from a test tree + * + * Test Type: Feature + * + * Input: None + * + * Steps: + * - Create a test tree with known values. + * - For each of the known values used to create the tree" + * - Use nvgpu_rbtree_search to search for the node and ensure it exists in + * the tree. + * - Use nvgpu_rbtree_unlink to unlink the node. + * - Run search again to ensure the node is not in the tree anymore. + * - Free the test tree. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_unlink(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_search + * + * Description: Test to check the nvgpu_rbtree_search and + * nvgpu_rbtree_range_search routines and go over some error handling. + * + * Test Type: Feature + * + * Input: None + * + * Steps: + * - Create a test tree with known values. + * - Ensure that searching with a NULL root returns NULL. + * - Ensure that range searching with a NULL root returns NULL. + * - Ensure that searching for a known value returns a valid result. + * - Perform a range search on a value that falls within a known existing range + * and ensure it returns the correct result. + * - Free the test tree. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_search(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_enum + * + * Description: Test to check the nvgpu_rbtree_enum_start routine and go over + * some error handling. + * + * Test Type: Feature + * + * Input: None + * + * Steps: + * - Create a test tree with known values. + * - Ensure that enumerating with a NULL root returns NULL. + * - For each known value of the tree, start an enumeration with the value + * itself and ensure that the resulting node's key_start is the same. + * - Start an enumeration of a key that is know to not be in the tree and ensure + * that the returned value is NULL. + * - Free the test tree. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_enum(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_enum_next + * + * Description: Test to check the nvgpu_rbtree_enum_next routine and go over + * some error handling. nvgpu_rbtree_enum_next will find the next node whose + * key_start value is greater than the one in the provided node. + * + * Test Type: Feature + * + * Input: None + * + * Steps: + * - Create a test tree with known values. + * - Ensure that enum_next with a NULL root returns NULL. + * - Set a node pointer to point to the root of the tree. + * - While the node pointer is not NULL, do the following: + * - Perform an enum_next operation from the node pointer. The result is + * stored in the node pointer. + * - Ensure that the node pointer's key_start is not lower than the key_start + * value of the previous node. + * - Continue until there are no more results and enum_next changes the node + * pointer to NULL. + * - Free the test tree. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_enum_next(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_enum_next + * + * Description: Test to check the nvgpu_rbtree_less_than_search routine: given + * a key_start value, find a node with a lower key_start value. + * + * Test Type: Feature + * + * Input: None + * + * Steps: + * - Create a test tree with known values. + * - Considering that after creating the tree is balanced, this implies that the + * key_start value of root is somewhere in the middle of the key_start values + * of the other nodes of the tree. So root->key_start is used for the + * less_than_search operation. + * - Perform the less_than_search operation and ensure that: + * - It yields a non-NULL result. + * - The key_start value of the resulting node is lower than root->key_start. + * - Free the test tree. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_search_less(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_unlink_corner_cases + * + * Description: Test corner cases in nvgpu_rbtree_unlink (and delete_fixup) to + * increase branch and line coverage. + * + * Test Type: Feature + * + * Input: None + * + * Steps: + * - Create a test tree with known values. + * - Unlink well chosen values to create conditions where nodes are removed on + * the left and subsequently the right side needs to become red. + * - Unlink well chosen values to create conditions where nodes are removed on + * the left and the right is NULL. + * - Unlink well chosen values to create conditions where nodes are removed on + * the left and the right side is red, requiring a tree rotation to the left. + * - Unlink well chosen values to create conditions where nodes are removed on + * the right and the left side needs to become black. + * - Unlink well chosen values to create conditions where right sibling of + * deleted node is black or has a right sentinel. + * - Unlink well chosen values to create conditions where the left rotation + * will create a new root. + * - Free the test tree. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_unlink_corner_cases(struct unit_module *m, struct gk20a *g, + void *args); + +/** }@ */ +#endif /* UNIT_RBTREE_H */