kunit: add support for named resources
authorAlan Maguire <alan.maguire@oracle.com>
Fri, 29 May 2020 21:46:21 +0000 (22:46 +0100)
committerShuah Khan <skhan@linuxfoundation.org>
Fri, 26 Jun 2020 20:12:00 +0000 (14:12 -0600)
The kunit resources API allows for custom initialization and
cleanup code (init/fini); here a new resource add function sets
the "struct kunit_resource" "name" field, and calls the standard
add function.  Having a simple way to name resources is
useful in cases such as multithreaded tests where a set of
resources are shared among threads; a pointer to the
"struct kunit *" test state then is all that is needed to
retrieve and use named resources.  Support is provided to add,
find and destroy named resources; the latter two are simply
wrappers that use a "match-by-name" callback.

If an attempt to add a resource with a name that already exists
is made kunit_add_named_resource() will return -EEXIST.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
include/kunit/test.h
lib/kunit/kunit-test.c
lib/kunit/test.c

index f9b914e..59f3144 100644 (file)
@@ -72,9 +72,15 @@ typedef void (*kunit_resource_free_t)(struct kunit_resource *);
  *             return kunit_alloc_resource(test, kunit_kmalloc_init,
  *                     kunit_kmalloc_free, &params);
  *     }
+ *
+ * Resources can also be named, with lookup/removal done on a name
+ * basis also.  kunit_add_named_resource(), kunit_find_named_resource()
+ * and kunit_destroy_named_resource().  Resource names must be
+ * unique within the test instance.
  */
 struct kunit_resource {
        void *data;
+       const char *name;               /* optional name */
 
        /* private: internal use only. */
        kunit_resource_free_t free;
@@ -344,6 +350,21 @@ int kunit_add_resource(struct kunit *test,
                       kunit_resource_free_t free,
                       struct kunit_resource *res,
                       void *data);
+
+/**
+ * kunit_add_named_resource() - Add a named *test managed resource*.
+ * @test: The test context object.
+ * @init: a user-supplied function to initialize the resource data, if needed.
+ * @free: a user-supplied function to free the resource data, if needed.
+ * @name_data: name and data to be set for resource.
+ */
+int kunit_add_named_resource(struct kunit *test,
+                            kunit_resource_init_t init,
+                            kunit_resource_free_t free,
+                            struct kunit_resource *res,
+                            const char *name,
+                            void *data);
+
 /**
  * kunit_alloc_resource() - Allocates a *test managed resource*.
  * @test: The test context object.
@@ -399,6 +420,19 @@ static inline bool kunit_resource_instance_match(struct kunit *test,
 }
 
 /**
+ * kunit_resource_name_match() - Match a resource with the same name.
+ * @test: Test case to which the resource belongs.
+ * @res: The resource.
+ * @match_name: The name to match against.
+ */
+static inline bool kunit_resource_name_match(struct kunit *test,
+                                            struct kunit_resource *res,
+                                            void *match_name)
+{
+       return res->name && strcmp(res->name, match_name) == 0;
+}
+
+/**
  * kunit_find_resource() - Find a resource using match function/data.
  * @test: Test case to which the resource belongs.
  * @match: match function to be applied to resources/match data.
@@ -427,6 +461,19 @@ kunit_find_resource(struct kunit *test,
 }
 
 /**
+ * kunit_find_named_resource() - Find a resource using match name.
+ * @test: Test case to which the resource belongs.
+ * @name: match name.
+ */
+static inline struct kunit_resource *
+kunit_find_named_resource(struct kunit *test,
+                         const char *name)
+{
+       return kunit_find_resource(test, kunit_resource_name_match,
+                                  (void *)name);
+}
+
+/**
  * kunit_destroy_resource() - Find a kunit_resource and destroy it.
  * @test: Test case to which the resource belongs.
  * @match: Match function. Returns whether a given resource matches @match_data.
@@ -439,6 +486,13 @@ int kunit_destroy_resource(struct kunit *test,
                           kunit_resource_match_t match,
                           void *match_data);
 
+static inline int kunit_destroy_named_resource(struct kunit *test,
+                                              const char *name)
+{
+       return kunit_destroy_resource(test, kunit_resource_name_match,
+                                     (void *)name);
+}
+
 /**
  * kunit_remove_resource: remove resource from resource list associated with
  *                       test.
index 03f3eca..69f9024 100644 (file)
@@ -325,6 +325,42 @@ static void kunit_resource_test_static(struct kunit *test)
        KUNIT_EXPECT_TRUE(test, list_empty(&test->resources));
 }
 
+static void kunit_resource_test_named(struct kunit *test)
+{
+       struct kunit_resource res1, res2, *found = NULL;
+       struct kunit_test_resource_context ctx;
+
+       KUNIT_EXPECT_EQ(test,
+                       kunit_add_named_resource(test, NULL, NULL, &res1,
+                                                "resource_1", &ctx),
+                       0);
+       KUNIT_EXPECT_PTR_EQ(test, res1.data, (void *)&ctx);
+
+       KUNIT_EXPECT_EQ(test,
+                       kunit_add_named_resource(test, NULL, NULL, &res1,
+                                                "resource_1", &ctx),
+                       -EEXIST);
+
+       KUNIT_EXPECT_EQ(test,
+                       kunit_add_named_resource(test, NULL, NULL, &res2,
+                                                "resource_2", &ctx),
+                       0);
+
+       found = kunit_find_named_resource(test, "resource_1");
+
+       KUNIT_EXPECT_PTR_EQ(test, found, &res1);
+
+       if (found)
+               kunit_put_resource(&res1);
+
+       KUNIT_EXPECT_EQ(test, kunit_destroy_named_resource(test, "resource_2"),
+                       0);
+
+       kunit_cleanup(test);
+
+       KUNIT_EXPECT_TRUE(test, list_empty(&test->resources));
+}
+
 static int kunit_resource_test_init(struct kunit *test)
 {
        struct kunit_test_resource_context *ctx =
@@ -354,6 +390,7 @@ static struct kunit_case kunit_resource_test_cases[] = {
        KUNIT_CASE(kunit_resource_test_cleanup_resources),
        KUNIT_CASE(kunit_resource_test_proper_free_ordering),
        KUNIT_CASE(kunit_resource_test_static),
+       KUNIT_CASE(kunit_resource_test_named),
        {}
 };
 
index 569b7f9..c360372 100644 (file)
@@ -441,6 +441,30 @@ int kunit_add_resource(struct kunit *test,
 }
 EXPORT_SYMBOL_GPL(kunit_add_resource);
 
+int kunit_add_named_resource(struct kunit *test,
+                            kunit_resource_init_t init,
+                            kunit_resource_free_t free,
+                            struct kunit_resource *res,
+                            const char *name,
+                            void *data)
+{
+       struct kunit_resource *existing;
+
+       if (!name)
+               return -EINVAL;
+
+       existing = kunit_find_named_resource(test, name);
+       if (existing) {
+               kunit_put_resource(existing);
+               return -EEXIST;
+       }
+
+       res->name = name;
+
+       return kunit_add_resource(test, init, free, res, data);
+}
+EXPORT_SYMBOL_GPL(kunit_add_named_resource);
+
 struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
                                                    kunit_resource_init_t init,
                                                    kunit_resource_free_t free,