1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * KUnit test for KUnit platform driver infrastructure. 4 */ 5 6 #include <linux/platform_device.h> 7 8 #include <kunit/platform_device.h> 9 #include <kunit/test.h> 10 11 /* 12 * Test that kunit_platform_device_alloc() creates a platform device. 13 */ 14 static void kunit_platform_device_alloc_test(struct kunit *test) 15 { 16 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 17 kunit_platform_device_alloc(test, "kunit-platform", 1)); 18 } 19 20 /* 21 * Test that kunit_platform_device_add() registers a platform device on the 22 * platform bus with the proper name and id. 23 */ 24 static void kunit_platform_device_add_test(struct kunit *test) 25 { 26 struct platform_device *pdev; 27 const char *name = "kunit-platform-add"; 28 const int id = -1; 29 30 pdev = kunit_platform_device_alloc(test, name, id); 31 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 32 33 KUNIT_EXPECT_EQ(test, 0, kunit_platform_device_add(test, pdev)); 34 KUNIT_EXPECT_TRUE(test, dev_is_platform(&pdev->dev)); 35 KUNIT_EXPECT_STREQ(test, pdev->name, name); 36 KUNIT_EXPECT_EQ(test, pdev->id, id); 37 } 38 39 /* 40 * Test that kunit_platform_device_add() called twice with the same device name 41 * and id fails the second time and properly cleans up. 42 */ 43 static void kunit_platform_device_add_twice_fails_test(struct kunit *test) 44 { 45 struct platform_device *pdev; 46 const char *name = "kunit-platform-add-2"; 47 const int id = -1; 48 49 pdev = kunit_platform_device_alloc(test, name, id); 50 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 51 KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_add(test, pdev)); 52 53 pdev = kunit_platform_device_alloc(test, name, id); 54 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 55 56 KUNIT_EXPECT_NE(test, 0, kunit_platform_device_add(test, pdev)); 57 } 58 59 static int kunit_platform_device_find_by_name(struct device *dev, const void *data) 60 { 61 return strcmp(dev_name(dev), data) == 0; 62 } 63 64 /* 65 * Test that kunit_platform_device_add() cleans up by removing the platform 66 * device when the test finishes. */ 67 static void kunit_platform_device_add_cleans_up(struct kunit *test) 68 { 69 struct platform_device *pdev; 70 const char *name = "kunit-platform-clean"; 71 const int id = -1; 72 struct kunit fake; 73 struct device *dev; 74 75 kunit_init_test(&fake, "kunit_platform_device_add_fake_test", NULL); 76 KUNIT_ASSERT_EQ(test, fake.status, KUNIT_SUCCESS); 77 78 pdev = kunit_platform_device_alloc(&fake, name, id); 79 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 80 KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_add(&fake, pdev)); 81 dev = bus_find_device(&platform_bus_type, NULL, name, 82 kunit_platform_device_find_by_name); 83 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); 84 put_device(dev); 85 86 /* Remove pdev */ 87 kunit_cleanup(&fake); 88 89 /* 90 * Failing to migrate the kunit_resource would lead to an extra 91 * put_device() call on the platform device. The best we can do here is 92 * make sure the device no longer exists on the bus, but if something 93 * is wrong we'll see a refcount underflow here. We can't test for a 94 * refcount underflow because the kref matches the lifetime of the 95 * device which should already be freed and could be used by something 96 * else. 97 */ 98 dev = bus_find_device(&platform_bus_type, NULL, name, 99 kunit_platform_device_find_by_name); 100 KUNIT_EXPECT_PTR_EQ(test, NULL, dev); 101 put_device(dev); 102 } 103 104 /* 105 * Test suite for struct platform_device kunit APIs 106 */ 107 static struct kunit_case kunit_platform_device_test_cases[] = { 108 KUNIT_CASE(kunit_platform_device_alloc_test), 109 KUNIT_CASE(kunit_platform_device_add_test), 110 KUNIT_CASE(kunit_platform_device_add_twice_fails_test), 111 KUNIT_CASE(kunit_platform_device_add_cleans_up), 112 {} 113 }; 114 115 static struct kunit_suite kunit_platform_device_suite = { 116 .name = "kunit_platform_device", 117 .test_cases = kunit_platform_device_test_cases, 118 }; 119 120 struct kunit_platform_driver_test_context { 121 struct platform_driver pdrv; 122 const char *data; 123 }; 124 125 static const char * const test_data = "test data"; 126 127 static inline struct kunit_platform_driver_test_context * 128 to_test_context(struct platform_device *pdev) 129 { 130 return container_of(to_platform_driver(pdev->dev.driver), 131 struct kunit_platform_driver_test_context, 132 pdrv); 133 } 134 135 static int kunit_platform_driver_probe(struct platform_device *pdev) 136 { 137 struct kunit_platform_driver_test_context *ctx; 138 139 ctx = to_test_context(pdev); 140 ctx->data = test_data; 141 142 return 0; 143 } 144 145 /* Test that kunit_platform_driver_register() registers a driver that probes. */ 146 static void kunit_platform_driver_register_test(struct kunit *test) 147 { 148 struct platform_device *pdev; 149 struct kunit_platform_driver_test_context *ctx; 150 DECLARE_COMPLETION_ONSTACK(comp); 151 const char *name = "kunit-platform-register"; 152 153 ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 154 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); 155 156 pdev = kunit_platform_device_alloc(test, name, -1); 157 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 158 KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_add(test, pdev)); 159 160 ctx->pdrv.probe = kunit_platform_driver_probe; 161 ctx->pdrv.driver.name = name; 162 ctx->pdrv.driver.owner = THIS_MODULE; 163 164 KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_prepare_wait_for_probe(test, pdev, &comp)); 165 166 KUNIT_EXPECT_EQ(test, 0, kunit_platform_driver_register(test, &ctx->pdrv)); 167 KUNIT_EXPECT_NE(test, 0, wait_for_completion_timeout(&comp, 3 * HZ)); 168 KUNIT_EXPECT_STREQ(test, ctx->data, test_data); 169 } 170 171 /* 172 * Test that kunit_platform_device_prepare_wait_for_probe() completes the completion 173 * when the device is already probed. 174 */ 175 static void kunit_platform_device_prepare_wait_for_probe_completes_when_already_probed(struct kunit *test) 176 { 177 struct platform_device *pdev; 178 struct kunit_platform_driver_test_context *ctx; 179 DECLARE_COMPLETION_ONSTACK(comp); 180 const char *name = "kunit-platform-wait"; 181 182 ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 183 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); 184 185 pdev = kunit_platform_device_alloc(test, name, -1); 186 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 187 KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_add(test, pdev)); 188 189 ctx->pdrv.probe = kunit_platform_driver_probe; 190 ctx->pdrv.driver.name = name; 191 ctx->pdrv.driver.owner = THIS_MODULE; 192 193 /* Make sure driver has actually probed */ 194 KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_prepare_wait_for_probe(test, pdev, &comp)); 195 KUNIT_ASSERT_EQ(test, 0, kunit_platform_driver_register(test, &ctx->pdrv)); 196 KUNIT_ASSERT_NE(test, 0, wait_for_completion_timeout(&comp, 3 * HZ)); 197 198 reinit_completion(&comp); 199 KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_prepare_wait_for_probe(test, pdev, &comp)); 200 201 KUNIT_EXPECT_NE(test, 0, wait_for_completion_timeout(&comp, HZ)); 202 } 203 204 static struct kunit_case kunit_platform_driver_test_cases[] = { 205 KUNIT_CASE(kunit_platform_driver_register_test), 206 KUNIT_CASE(kunit_platform_device_prepare_wait_for_probe_completes_when_already_probed), 207 {} 208 }; 209 210 /* 211 * Test suite for struct platform_driver kunit APIs 212 */ 213 static struct kunit_suite kunit_platform_driver_suite = { 214 .name = "kunit_platform_driver", 215 .test_cases = kunit_platform_driver_test_cases, 216 }; 217 218 kunit_test_suites( 219 &kunit_platform_device_suite, 220 &kunit_platform_driver_suite, 221 ); 222 223 MODULE_LICENSE("GPL"); 224 MODULE_DESCRIPTION("KUnit test for KUnit platform driver infrastructure"); 225
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.