150b87bb4SMauro Carvalho Chehab#!/usr/bin/env python3 250b87bb4SMauro Carvalho Chehab# SPDX-License-Identifier: GPL-2.0 350b87bb4SMauro Carvalho Chehab# Copyright(c) 2026: Mauro Carvalho Chehab <mchehab@kernel.org>. 450b87bb4SMauro Carvalho Chehab# 550b87bb4SMauro Carvalho Chehab# pylint: disable=C0413,R0904 650b87bb4SMauro Carvalho Chehab 750b87bb4SMauro Carvalho Chehab 850b87bb4SMauro Carvalho Chehab""" 950b87bb4SMauro Carvalho ChehabUnit tests for kernel-doc CMatch. 1050b87bb4SMauro Carvalho Chehab""" 1150b87bb4SMauro Carvalho Chehab 1250b87bb4SMauro Carvalho Chehabimport os 1350b87bb4SMauro Carvalho Chehabimport re 1450b87bb4SMauro Carvalho Chehabimport sys 1550b87bb4SMauro Carvalho Chehabimport unittest 1650b87bb4SMauro Carvalho Chehab 1750b87bb4SMauro Carvalho Chehab 1850b87bb4SMauro Carvalho Chehab# Import Python modules 1950b87bb4SMauro Carvalho Chehab 2050b87bb4SMauro Carvalho ChehabSRC_DIR = os.path.dirname(os.path.realpath(__file__)) 2150b87bb4SMauro Carvalho Chehabsys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) 2250b87bb4SMauro Carvalho Chehab 2350b87bb4SMauro Carvalho Chehabfrom kdoc.c_lex import CMatch 24*c22aa12cSMauro Carvalho Chehabfrom kdoc.kdoc_re import KernRe 2550b87bb4SMauro Carvalho Chehabfrom unittest_helper import run_unittest 2650b87bb4SMauro Carvalho Chehab 2750b87bb4SMauro Carvalho Chehab# 2850b87bb4SMauro Carvalho Chehab# Override unittest.TestCase to better compare diffs ignoring whitespaces 2950b87bb4SMauro Carvalho Chehab# 3050b87bb4SMauro Carvalho Chehabclass TestCaseDiff(unittest.TestCase): 3150b87bb4SMauro Carvalho Chehab """ 3250b87bb4SMauro Carvalho Chehab Disable maximum limit on diffs and add a method to better 3350b87bb4SMauro Carvalho Chehab handle diffs with whitespace differences. 3450b87bb4SMauro Carvalho Chehab """ 3550b87bb4SMauro Carvalho Chehab 3650b87bb4SMauro Carvalho Chehab @classmethod 3750b87bb4SMauro Carvalho Chehab def setUpClass(cls): 3850b87bb4SMauro Carvalho Chehab """Ensure that there won't be limit for diffs""" 3950b87bb4SMauro Carvalho Chehab cls.maxDiff = None 4050b87bb4SMauro Carvalho Chehab 4150b87bb4SMauro Carvalho Chehab 4250b87bb4SMauro Carvalho Chehab# 4350b87bb4SMauro Carvalho Chehab# Tests doing with different macros 4450b87bb4SMauro Carvalho Chehab# 4550b87bb4SMauro Carvalho Chehab 4650b87bb4SMauro Carvalho Chehabclass TestSearch(TestCaseDiff): 4750b87bb4SMauro Carvalho Chehab """ 4850b87bb4SMauro Carvalho Chehab Test search mechanism 4950b87bb4SMauro Carvalho Chehab """ 5050b87bb4SMauro Carvalho Chehab 5150b87bb4SMauro Carvalho Chehab def test_search_acquires_simple(self): 5250b87bb4SMauro Carvalho Chehab line = "__acquires(ctx) foo();" 5350b87bb4SMauro Carvalho Chehab result = ", ".join(CMatch("__acquires").search(line)) 5450b87bb4SMauro Carvalho Chehab self.assertEqual(result, "__acquires(ctx)") 5550b87bb4SMauro Carvalho Chehab 5650b87bb4SMauro Carvalho Chehab def test_search_acquires_multiple(self): 5750b87bb4SMauro Carvalho Chehab line = "__acquires(ctx) __acquires(other) bar();" 5850b87bb4SMauro Carvalho Chehab result = ", ".join(CMatch("__acquires").search(line)) 5950b87bb4SMauro Carvalho Chehab self.assertEqual(result, "__acquires(ctx), __acquires(other)") 6050b87bb4SMauro Carvalho Chehab 6150b87bb4SMauro Carvalho Chehab def test_search_acquires_nested_paren(self): 6250b87bb4SMauro Carvalho Chehab line = "__acquires((ctx1, ctx2)) baz();" 6350b87bb4SMauro Carvalho Chehab result = ", ".join(CMatch("__acquires").search(line)) 6450b87bb4SMauro Carvalho Chehab self.assertEqual(result, "__acquires((ctx1, ctx2))") 6550b87bb4SMauro Carvalho Chehab 6650b87bb4SMauro Carvalho Chehab def test_search_must_hold(self): 6750b87bb4SMauro Carvalho Chehab line = "__must_hold(&lock) do_something();" 6850b87bb4SMauro Carvalho Chehab result = ", ".join(CMatch("__must_hold").search(line)) 6950b87bb4SMauro Carvalho Chehab self.assertEqual(result, "__must_hold(&lock)") 7050b87bb4SMauro Carvalho Chehab 7150b87bb4SMauro Carvalho Chehab def test_search_must_hold_shared(self): 7250b87bb4SMauro Carvalho Chehab line = "__must_hold_shared(RCU) other();" 7350b87bb4SMauro Carvalho Chehab result = ", ".join(CMatch("__must_hold_shared").search(line)) 7450b87bb4SMauro Carvalho Chehab self.assertEqual(result, "__must_hold_shared(RCU)") 7550b87bb4SMauro Carvalho Chehab 7650b87bb4SMauro Carvalho Chehab def test_search_no_false_positive(self): 7750b87bb4SMauro Carvalho Chehab line = "call__acquires(foo); // should stay intact" 78*c22aa12cSMauro Carvalho Chehab result = ", ".join(CMatch(r"__acquires").search(line)) 7950b87bb4SMauro Carvalho Chehab self.assertEqual(result, "") 8050b87bb4SMauro Carvalho Chehab 8150b87bb4SMauro Carvalho Chehab def test_search_no_macro_remains(self): 8250b87bb4SMauro Carvalho Chehab line = "do_something_else();" 8350b87bb4SMauro Carvalho Chehab result = ", ".join(CMatch("__acquires").search(line)) 8450b87bb4SMauro Carvalho Chehab self.assertEqual(result, "") 8550b87bb4SMauro Carvalho Chehab 8650b87bb4SMauro Carvalho Chehab def test_search_no_function(self): 8750b87bb4SMauro Carvalho Chehab line = "something" 8850b87bb4SMauro Carvalho Chehab result = ", ".join(CMatch(line).search(line)) 8950b87bb4SMauro Carvalho Chehab self.assertEqual(result, "") 9050b87bb4SMauro Carvalho Chehab 9150b87bb4SMauro Carvalho Chehab# 92*c22aa12cSMauro Carvalho Chehab# Override unittest.TestCase to better compare diffs ignoring whitespaces 93*c22aa12cSMauro Carvalho Chehab# 94*c22aa12cSMauro Carvalho Chehabclass TestCaseDiff(unittest.TestCase): 95*c22aa12cSMauro Carvalho Chehab """ 96*c22aa12cSMauro Carvalho Chehab Disable maximum limit on diffs and add a method to better 97*c22aa12cSMauro Carvalho Chehab handle diffs with whitespace differences. 98*c22aa12cSMauro Carvalho Chehab """ 99*c22aa12cSMauro Carvalho Chehab 100*c22aa12cSMauro Carvalho Chehab @classmethod 101*c22aa12cSMauro Carvalho Chehab def setUpClass(cls): 102*c22aa12cSMauro Carvalho Chehab """Ensure that there won't be limit for diffs""" 103*c22aa12cSMauro Carvalho Chehab cls.maxDiff = None 104*c22aa12cSMauro Carvalho Chehab 105*c22aa12cSMauro Carvalho Chehab def assertLogicallyEqual(self, a, b): 106*c22aa12cSMauro Carvalho Chehab """ 107*c22aa12cSMauro Carvalho Chehab Compare two results ignoring multiple whitespace differences. 108*c22aa12cSMauro Carvalho Chehab 109*c22aa12cSMauro Carvalho Chehab This is useful to check more complex matches picked from examples. 110*c22aa12cSMauro Carvalho Chehab On a plus side, we also don't need to use dedent. 111*c22aa12cSMauro Carvalho Chehab Please notice that line breaks still need to match. We might 112*c22aa12cSMauro Carvalho Chehab remove it at the regex, but this way, checking the diff is easier. 113*c22aa12cSMauro Carvalho Chehab """ 114*c22aa12cSMauro Carvalho Chehab a = re.sub(r"[\t ]+", " ", a.strip()) 115*c22aa12cSMauro Carvalho Chehab b = re.sub(r"[\t ]+", " ", b.strip()) 116*c22aa12cSMauro Carvalho Chehab 117*c22aa12cSMauro Carvalho Chehab a = re.sub(r"\s+\n", "\n", a) 118*c22aa12cSMauro Carvalho Chehab b = re.sub(r"\s+\n", "\n", b) 119*c22aa12cSMauro Carvalho Chehab 120*c22aa12cSMauro Carvalho Chehab a = re.sub(" ;", ";", a) 121*c22aa12cSMauro Carvalho Chehab b = re.sub(" ;", ";", b) 122*c22aa12cSMauro Carvalho Chehab 123*c22aa12cSMauro Carvalho Chehab self.assertEqual(a, b) 124*c22aa12cSMauro Carvalho Chehab 125*c22aa12cSMauro Carvalho Chehab# 126*c22aa12cSMauro Carvalho Chehab# Tests doing with different macros 127*c22aa12cSMauro Carvalho Chehab# 128*c22aa12cSMauro Carvalho Chehab 129*c22aa12cSMauro Carvalho Chehabclass TestSubMultipleMacros(TestCaseDiff): 130*c22aa12cSMauro Carvalho Chehab """ 131*c22aa12cSMauro Carvalho Chehab Tests doing with different macros. 132*c22aa12cSMauro Carvalho Chehab 133*c22aa12cSMauro Carvalho Chehab Here, we won't use assertLogicallyEqual. Instead, we'll check if each 134*c22aa12cSMauro Carvalho Chehab of the expected patterns are present at the answer. 135*c22aa12cSMauro Carvalho Chehab """ 136*c22aa12cSMauro Carvalho Chehab 137*c22aa12cSMauro Carvalho Chehab def test_acquires_simple(self): 138*c22aa12cSMauro Carvalho Chehab """Simple replacement test with __acquires""" 139*c22aa12cSMauro Carvalho Chehab line = "__acquires(ctx) foo();" 140*c22aa12cSMauro Carvalho Chehab result = CMatch(r"__acquires").sub("REPLACED", line) 141*c22aa12cSMauro Carvalho Chehab 142*c22aa12cSMauro Carvalho Chehab self.assertEqual("REPLACED foo();", result) 143*c22aa12cSMauro Carvalho Chehab 144*c22aa12cSMauro Carvalho Chehab def test_acquires_multiple(self): 145*c22aa12cSMauro Carvalho Chehab """Multiple __acquires""" 146*c22aa12cSMauro Carvalho Chehab line = "__acquires(ctx) __acquires(other) bar();" 147*c22aa12cSMauro Carvalho Chehab result = CMatch(r"__acquires").sub("REPLACED", line) 148*c22aa12cSMauro Carvalho Chehab 149*c22aa12cSMauro Carvalho Chehab self.assertEqual("REPLACED REPLACED bar();", result) 150*c22aa12cSMauro Carvalho Chehab 151*c22aa12cSMauro Carvalho Chehab def test_acquires_nested_paren(self): 152*c22aa12cSMauro Carvalho Chehab """__acquires with nested pattern""" 153*c22aa12cSMauro Carvalho Chehab line = "__acquires((ctx1, ctx2)) baz();" 154*c22aa12cSMauro Carvalho Chehab result = CMatch(r"__acquires").sub("REPLACED", line) 155*c22aa12cSMauro Carvalho Chehab 156*c22aa12cSMauro Carvalho Chehab self.assertEqual("REPLACED baz();", result) 157*c22aa12cSMauro Carvalho Chehab 158*c22aa12cSMauro Carvalho Chehab def test_must_hold(self): 159*c22aa12cSMauro Carvalho Chehab """__must_hold with a pointer""" 160*c22aa12cSMauro Carvalho Chehab line = "__must_hold(&lock) do_something();" 161*c22aa12cSMauro Carvalho Chehab result = CMatch(r"__must_hold").sub("REPLACED", line) 162*c22aa12cSMauro Carvalho Chehab 163*c22aa12cSMauro Carvalho Chehab self.assertNotIn("__must_hold(", result) 164*c22aa12cSMauro Carvalho Chehab self.assertIn("do_something();", result) 165*c22aa12cSMauro Carvalho Chehab 166*c22aa12cSMauro Carvalho Chehab def test_must_hold_shared(self): 167*c22aa12cSMauro Carvalho Chehab """__must_hold with an upercase defined value""" 168*c22aa12cSMauro Carvalho Chehab line = "__must_hold_shared(RCU) other();" 169*c22aa12cSMauro Carvalho Chehab result = CMatch(r"__must_hold_shared").sub("REPLACED", line) 170*c22aa12cSMauro Carvalho Chehab 171*c22aa12cSMauro Carvalho Chehab self.assertNotIn("__must_hold_shared(", result) 172*c22aa12cSMauro Carvalho Chehab self.assertIn("other();", result) 173*c22aa12cSMauro Carvalho Chehab 174*c22aa12cSMauro Carvalho Chehab def test_no_false_positive(self): 175*c22aa12cSMauro Carvalho Chehab """ 176*c22aa12cSMauro Carvalho Chehab Ensure that unrelated text containing similar patterns is preserved 177*c22aa12cSMauro Carvalho Chehab """ 178*c22aa12cSMauro Carvalho Chehab line = "call__acquires(foo); // should stay intact" 179*c22aa12cSMauro Carvalho Chehab result = CMatch(r"\b__acquires").sub("REPLACED", line) 180*c22aa12cSMauro Carvalho Chehab 181*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual(result, "call__acquires(foo);") 182*c22aa12cSMauro Carvalho Chehab 183*c22aa12cSMauro Carvalho Chehab def test_mixed_macros(self): 184*c22aa12cSMauro Carvalho Chehab """Add a mix of macros""" 185*c22aa12cSMauro Carvalho Chehab line = "__acquires(ctx) __releases(ctx) __must_hold(&lock) foo();" 186*c22aa12cSMauro Carvalho Chehab 187*c22aa12cSMauro Carvalho Chehab result = CMatch(r"__acquires").sub("REPLACED", line) 188*c22aa12cSMauro Carvalho Chehab result = CMatch(r"__releases").sub("REPLACED", result) 189*c22aa12cSMauro Carvalho Chehab result = CMatch(r"__must_hold").sub("REPLACED", result) 190*c22aa12cSMauro Carvalho Chehab 191*c22aa12cSMauro Carvalho Chehab self.assertNotIn("__acquires(", result) 192*c22aa12cSMauro Carvalho Chehab self.assertNotIn("__releases(", result) 193*c22aa12cSMauro Carvalho Chehab self.assertNotIn("__must_hold(", result) 194*c22aa12cSMauro Carvalho Chehab 195*c22aa12cSMauro Carvalho Chehab self.assertIn("foo();", result) 196*c22aa12cSMauro Carvalho Chehab 197*c22aa12cSMauro Carvalho Chehab def test_no_macro_remains(self): 198*c22aa12cSMauro Carvalho Chehab """Ensures that unmatched macros are untouched""" 199*c22aa12cSMauro Carvalho Chehab line = "do_something_else();" 200*c22aa12cSMauro Carvalho Chehab result = CMatch(r"__acquires").sub("REPLACED", line) 201*c22aa12cSMauro Carvalho Chehab 202*c22aa12cSMauro Carvalho Chehab self.assertEqual(result, line) 203*c22aa12cSMauro Carvalho Chehab 204*c22aa12cSMauro Carvalho Chehab def test_no_function(self): 205*c22aa12cSMauro Carvalho Chehab """Ensures that no functions will remain untouched""" 206*c22aa12cSMauro Carvalho Chehab line = "something" 207*c22aa12cSMauro Carvalho Chehab result = CMatch(line).sub("REPLACED", line) 208*c22aa12cSMauro Carvalho Chehab 209*c22aa12cSMauro Carvalho Chehab self.assertEqual(result, line) 210*c22aa12cSMauro Carvalho Chehab 211*c22aa12cSMauro Carvalho Chehab# 212*c22aa12cSMauro Carvalho Chehab# Check if the diff is logically equivalent. To simplify, the tests here 213*c22aa12cSMauro Carvalho Chehab# use a single macro name for all replacements. 214*c22aa12cSMauro Carvalho Chehab# 215*c22aa12cSMauro Carvalho Chehab 216*c22aa12cSMauro Carvalho Chehabclass TestSubSimple(TestCaseDiff): 217*c22aa12cSMauro Carvalho Chehab """ 218*c22aa12cSMauro Carvalho Chehab Test argument replacements. 219*c22aa12cSMauro Carvalho Chehab 220*c22aa12cSMauro Carvalho Chehab Here, the function name can be anything. So, we picked __attribute__(), 221*c22aa12cSMauro Carvalho Chehab to mimic a macro found at the Kernel, but none of the replacements her 222*c22aa12cSMauro Carvalho Chehab has any relationship with the Kernel usage. 223*c22aa12cSMauro Carvalho Chehab """ 224*c22aa12cSMauro Carvalho Chehab 225*c22aa12cSMauro Carvalho Chehab MACRO = "__attribute__" 226*c22aa12cSMauro Carvalho Chehab 227*c22aa12cSMauro Carvalho Chehab @classmethod 228*c22aa12cSMauro Carvalho Chehab def setUpClass(cls): 229*c22aa12cSMauro Carvalho Chehab """Define a CMatch to be used for all tests""" 230*c22aa12cSMauro Carvalho Chehab cls.matcher = CMatch(cls.MACRO) 231*c22aa12cSMauro Carvalho Chehab 232*c22aa12cSMauro Carvalho Chehab def test_sub_with_capture(self): 233*c22aa12cSMauro Carvalho Chehab """Test all arguments replacement with a single arg""" 234*c22aa12cSMauro Carvalho Chehab line = f"{self.MACRO}(&ctx)\nfoo();" 235*c22aa12cSMauro Carvalho Chehab 236*c22aa12cSMauro Carvalho Chehab result = self.matcher.sub(r"ACQUIRED(\0)", line) 237*c22aa12cSMauro Carvalho Chehab 238*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual("ACQUIRED(&ctx)\nfoo();", result) 239*c22aa12cSMauro Carvalho Chehab 240*c22aa12cSMauro Carvalho Chehab def test_sub_zero_placeholder(self): 241*c22aa12cSMauro Carvalho Chehab """Test all arguments replacement with a multiple args""" 242*c22aa12cSMauro Carvalho Chehab line = f"{self.MACRO}(arg1, arg2)\nbar();" 243*c22aa12cSMauro Carvalho Chehab 244*c22aa12cSMauro Carvalho Chehab result = self.matcher.sub(r"REPLACED(\0)", line) 245*c22aa12cSMauro Carvalho Chehab 246*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual("REPLACED(arg1, arg2)\nbar();", result) 247*c22aa12cSMauro Carvalho Chehab 248*c22aa12cSMauro Carvalho Chehab def test_sub_single_placeholder(self): 249*c22aa12cSMauro Carvalho Chehab """Single replacement rule for \1""" 250*c22aa12cSMauro Carvalho Chehab line = f"{self.MACRO}(ctx, boo)\nfoo();" 251*c22aa12cSMauro Carvalho Chehab result = self.matcher.sub(r"ACQUIRED(\1)", line) 252*c22aa12cSMauro Carvalho Chehab 253*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual("ACQUIRED(ctx)\nfoo();", result) 254*c22aa12cSMauro Carvalho Chehab 255*c22aa12cSMauro Carvalho Chehab def test_sub_multiple_placeholders(self): 256*c22aa12cSMauro Carvalho Chehab """Replacement rule for both \1 and \2""" 257*c22aa12cSMauro Carvalho Chehab line = f"{self.MACRO}(arg1, arg2)\nbar();" 258*c22aa12cSMauro Carvalho Chehab result = self.matcher.sub(r"REPLACE(\1, \2)", line) 259*c22aa12cSMauro Carvalho Chehab 260*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual("REPLACE(arg1, arg2)\nbar();", result) 261*c22aa12cSMauro Carvalho Chehab 262*c22aa12cSMauro Carvalho Chehab def test_sub_mixed_placeholders(self): 263*c22aa12cSMauro Carvalho Chehab """Replacement rule for \0, \1 and additional text""" 264*c22aa12cSMauro Carvalho Chehab line = f"{self.MACRO}(foo, bar)\nbaz();" 265*c22aa12cSMauro Carvalho Chehab result = self.matcher.sub(r"ALL(\0) FIRST(\1)", line) 266*c22aa12cSMauro Carvalho Chehab 267*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual("ALL(foo, bar) FIRST(foo)\nbaz();", result) 268*c22aa12cSMauro Carvalho Chehab 269*c22aa12cSMauro Carvalho Chehab def test_sub_no_placeholder(self): 270*c22aa12cSMauro Carvalho Chehab """Replacement without placeholders""" 271*c22aa12cSMauro Carvalho Chehab line = f"{self.MACRO}(arg)\nfoo();" 272*c22aa12cSMauro Carvalho Chehab result = self.matcher.sub(r"NO_BACKREFS()", line) 273*c22aa12cSMauro Carvalho Chehab 274*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual("NO_BACKREFS()\nfoo();", result) 275*c22aa12cSMauro Carvalho Chehab 276*c22aa12cSMauro Carvalho Chehab def test_sub_count_parameter(self): 277*c22aa12cSMauro Carvalho Chehab """Verify that the algorithm stops after the requested count""" 278*c22aa12cSMauro Carvalho Chehab line = f"{self.MACRO}(a1) x();\n{self.MACRO}(a2) y();" 279*c22aa12cSMauro Carvalho Chehab result = self.matcher.sub(r"ONLY_FIRST(\1) ", line, count=1) 280*c22aa12cSMauro Carvalho Chehab 281*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual(f"ONLY_FIRST(a1) x();\n{self.MACRO}(a2) y();", 282*c22aa12cSMauro Carvalho Chehab result) 283*c22aa12cSMauro Carvalho Chehab 284*c22aa12cSMauro Carvalho Chehab def test_strip_multiple_acquires(self): 285*c22aa12cSMauro Carvalho Chehab """Check if spaces between removed delimiters will be dropped""" 286*c22aa12cSMauro Carvalho Chehab line = f"int {self.MACRO}(1) {self.MACRO}(2 ) {self.MACRO}(3) foo;" 287*c22aa12cSMauro Carvalho Chehab result = self.matcher.sub("", line) 288*c22aa12cSMauro Carvalho Chehab 289*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual(result, "int foo;") 290*c22aa12cSMauro Carvalho Chehab 291*c22aa12cSMauro Carvalho Chehab def test_rise_early_greedy(self): 292*c22aa12cSMauro Carvalho Chehab line = f"{self.MACRO}(a, b, c, d);" 293*c22aa12cSMauro Carvalho Chehab sub = r"\1, \2+, \3" 294*c22aa12cSMauro Carvalho Chehab 295*c22aa12cSMauro Carvalho Chehab with self.assertRaises(ValueError): 296*c22aa12cSMauro Carvalho Chehab result = self.matcher.sub(sub, line) 297*c22aa12cSMauro Carvalho Chehab 298*c22aa12cSMauro Carvalho Chehab def test_rise_multiple_greedy(self): 299*c22aa12cSMauro Carvalho Chehab line = f"{self.MACRO}(a, b, c, d);" 300*c22aa12cSMauro Carvalho Chehab sub = r"\1, \2+, \3+" 301*c22aa12cSMauro Carvalho Chehab 302*c22aa12cSMauro Carvalho Chehab with self.assertRaises(ValueError): 303*c22aa12cSMauro Carvalho Chehab result = self.matcher.sub(sub, line) 304*c22aa12cSMauro Carvalho Chehab 305*c22aa12cSMauro Carvalho Chehab# 306*c22aa12cSMauro Carvalho Chehab# Test replacements with slashrefs 307*c22aa12cSMauro Carvalho Chehab# 308*c22aa12cSMauro Carvalho Chehab 309*c22aa12cSMauro Carvalho Chehab 310*c22aa12cSMauro Carvalho Chehabclass TestSubWithLocalXforms(TestCaseDiff): 311*c22aa12cSMauro Carvalho Chehab """ 312*c22aa12cSMauro Carvalho Chehab Test diferent usecase patterns found at the Kernel. 313*c22aa12cSMauro Carvalho Chehab 314*c22aa12cSMauro Carvalho Chehab Here, replacements using both CMatch and KernRe can be tested, 315*c22aa12cSMauro Carvalho Chehab as it will import the actual replacement rules used by kernel-doc. 316*c22aa12cSMauro Carvalho Chehab """ 317*c22aa12cSMauro Carvalho Chehab 318*c22aa12cSMauro Carvalho Chehab struct_xforms = [ 319*c22aa12cSMauro Carvalho Chehab (CMatch("__attribute__"), ' '), 320*c22aa12cSMauro Carvalho Chehab (CMatch('__aligned'), ' '), 321*c22aa12cSMauro Carvalho Chehab (CMatch('__counted_by'), ' '), 322*c22aa12cSMauro Carvalho Chehab (CMatch('__counted_by_(le|be)'), ' '), 323*c22aa12cSMauro Carvalho Chehab (CMatch('__guarded_by'), ' '), 324*c22aa12cSMauro Carvalho Chehab (CMatch('__pt_guarded_by'), ' '), 325*c22aa12cSMauro Carvalho Chehab 326*c22aa12cSMauro Carvalho Chehab (CMatch('__cacheline_group_(begin|end)'), ''), 327*c22aa12cSMauro Carvalho Chehab 328*c22aa12cSMauro Carvalho Chehab (CMatch('struct_group'), r'\2'), 329*c22aa12cSMauro Carvalho Chehab (CMatch('struct_group_attr'), r'\3'), 330*c22aa12cSMauro Carvalho Chehab (CMatch('struct_group_tagged'), r'struct \1 { \3+ } \2;'), 331*c22aa12cSMauro Carvalho Chehab (CMatch('__struct_group'), r'\4'), 332*c22aa12cSMauro Carvalho Chehab 333*c22aa12cSMauro Carvalho Chehab (CMatch('__ETHTOOL_DECLARE_LINK_MODE_MASK'), r'DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)'), 334*c22aa12cSMauro Carvalho Chehab (CMatch('DECLARE_PHY_INTERFACE_MASK',), r'DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)'), 335*c22aa12cSMauro Carvalho Chehab (CMatch('DECLARE_BITMAP'), r'unsigned long \1[BITS_TO_LONGS(\2)]'), 336*c22aa12cSMauro Carvalho Chehab 337*c22aa12cSMauro Carvalho Chehab (CMatch('DECLARE_HASHTABLE'), r'unsigned long \1[1 << ((\2) - 1)]'), 338*c22aa12cSMauro Carvalho Chehab (CMatch('DECLARE_KFIFO'), r'\2 *\1'), 339*c22aa12cSMauro Carvalho Chehab (CMatch('DECLARE_KFIFO_PTR'), r'\2 *\1'), 340*c22aa12cSMauro Carvalho Chehab (CMatch('(?:__)?DECLARE_FLEX_ARRAY'), r'\1 \2[]'), 341*c22aa12cSMauro Carvalho Chehab (CMatch('DEFINE_DMA_UNMAP_ADDR'), r'dma_addr_t \1'), 342*c22aa12cSMauro Carvalho Chehab (CMatch('DEFINE_DMA_UNMAP_LEN'), r'__u32 \1'), 343*c22aa12cSMauro Carvalho Chehab (CMatch('VIRTIO_DECLARE_FEATURES'), r'union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }'), 344*c22aa12cSMauro Carvalho Chehab ] 345*c22aa12cSMauro Carvalho Chehab 346*c22aa12cSMauro Carvalho Chehab function_xforms = [ 347*c22aa12cSMauro Carvalho Chehab (CMatch('__printf'), ""), 348*c22aa12cSMauro Carvalho Chehab (CMatch('__(?:re)?alloc_size'), ""), 349*c22aa12cSMauro Carvalho Chehab (CMatch("__diagnose_as"), ""), 350*c22aa12cSMauro Carvalho Chehab (CMatch("DECL_BUCKET_PARAMS"), r"\1, \2"), 351*c22aa12cSMauro Carvalho Chehab 352*c22aa12cSMauro Carvalho Chehab (CMatch("__cond_acquires"), ""), 353*c22aa12cSMauro Carvalho Chehab (CMatch("__cond_releases"), ""), 354*c22aa12cSMauro Carvalho Chehab (CMatch("__acquires"), ""), 355*c22aa12cSMauro Carvalho Chehab (CMatch("__releases"), ""), 356*c22aa12cSMauro Carvalho Chehab (CMatch("__must_hold"), ""), 357*c22aa12cSMauro Carvalho Chehab (CMatch("__must_not_hold"), ""), 358*c22aa12cSMauro Carvalho Chehab (CMatch("__must_hold_shared"), ""), 359*c22aa12cSMauro Carvalho Chehab (CMatch("__cond_acquires_shared"), ""), 360*c22aa12cSMauro Carvalho Chehab (CMatch("__acquires_shared"), ""), 361*c22aa12cSMauro Carvalho Chehab (CMatch("__releases_shared"), ""), 362*c22aa12cSMauro Carvalho Chehab (CMatch("__attribute__"), ""), 363*c22aa12cSMauro Carvalho Chehab ] 364*c22aa12cSMauro Carvalho Chehab 365*c22aa12cSMauro Carvalho Chehab var_xforms = [ 366*c22aa12cSMauro Carvalho Chehab (CMatch('__guarded_by'), ""), 367*c22aa12cSMauro Carvalho Chehab (CMatch('__pt_guarded_by'), ""), 368*c22aa12cSMauro Carvalho Chehab (CMatch("LIST_HEAD"), r"struct list_head \1"), 369*c22aa12cSMauro Carvalho Chehab ] 370*c22aa12cSMauro Carvalho Chehab 371*c22aa12cSMauro Carvalho Chehab #: Transforms main dictionary used at apply_transforms(). 372*c22aa12cSMauro Carvalho Chehab xforms = { 373*c22aa12cSMauro Carvalho Chehab "struct": struct_xforms, 374*c22aa12cSMauro Carvalho Chehab "func": function_xforms, 375*c22aa12cSMauro Carvalho Chehab "var": var_xforms, 376*c22aa12cSMauro Carvalho Chehab } 377*c22aa12cSMauro Carvalho Chehab 378*c22aa12cSMauro Carvalho Chehab @classmethod 379*c22aa12cSMauro Carvalho Chehab def apply_transforms(cls, xform_type, text): 380*c22aa12cSMauro Carvalho Chehab """ 381*c22aa12cSMauro Carvalho Chehab Mimic the behavior of kdoc_parser.apply_transforms() method. 382*c22aa12cSMauro Carvalho Chehab 383*c22aa12cSMauro Carvalho Chehab For each element of STRUCT_XFORMS, apply apply_transforms. 384*c22aa12cSMauro Carvalho Chehab 385*c22aa12cSMauro Carvalho Chehab There are two parameters: 386*c22aa12cSMauro Carvalho Chehab 387*c22aa12cSMauro Carvalho Chehab - ``xform_type`` 388*c22aa12cSMauro Carvalho Chehab Can be ``func``, ``struct`` or ``var``; 389*c22aa12cSMauro Carvalho Chehab - ``text`` 390*c22aa12cSMauro Carvalho Chehab The text where the sub patterns from CTransforms will be applied. 391*c22aa12cSMauro Carvalho Chehab """ 392*c22aa12cSMauro Carvalho Chehab for search, subst in cls.xforms.get(xform_type): 393*c22aa12cSMauro Carvalho Chehab text = search.sub(subst, text) 394*c22aa12cSMauro Carvalho Chehab 395*c22aa12cSMauro Carvalho Chehab return text.strip() 396*c22aa12cSMauro Carvalho Chehab 397*c22aa12cSMauro Carvalho Chehab cls.matcher = CMatch(r"struct_group[\w\_]*") 398*c22aa12cSMauro Carvalho Chehab 399*c22aa12cSMauro Carvalho Chehab def test_struct_group(self): 400*c22aa12cSMauro Carvalho Chehab """ 401*c22aa12cSMauro Carvalho Chehab Test struct_group using a pattern from 402*c22aa12cSMauro Carvalho Chehab drivers/net/ethernet/asix/ax88796c_main.h. 403*c22aa12cSMauro Carvalho Chehab """ 404*c22aa12cSMauro Carvalho Chehab line = """ 405*c22aa12cSMauro Carvalho Chehab struct tx_pkt_info { 406*c22aa12cSMauro Carvalho Chehab struct_group(tx_overhead, 407*c22aa12cSMauro Carvalho Chehab struct tx_sop_header sop; 408*c22aa12cSMauro Carvalho Chehab struct tx_segment_header seg; 409*c22aa12cSMauro Carvalho Chehab ); 410*c22aa12cSMauro Carvalho Chehab struct tx_eop_header eop; 411*c22aa12cSMauro Carvalho Chehab u16 pkt_len; 412*c22aa12cSMauro Carvalho Chehab u16 seq_num; 413*c22aa12cSMauro Carvalho Chehab }; 414*c22aa12cSMauro Carvalho Chehab """ 415*c22aa12cSMauro Carvalho Chehab expected = """ 416*c22aa12cSMauro Carvalho Chehab struct tx_pkt_info { 417*c22aa12cSMauro Carvalho Chehab struct tx_sop_header sop; 418*c22aa12cSMauro Carvalho Chehab struct tx_segment_header seg; 419*c22aa12cSMauro Carvalho Chehab struct tx_eop_header eop; 420*c22aa12cSMauro Carvalho Chehab u16 pkt_len; 421*c22aa12cSMauro Carvalho Chehab u16 seq_num; 422*c22aa12cSMauro Carvalho Chehab }; 423*c22aa12cSMauro Carvalho Chehab """ 424*c22aa12cSMauro Carvalho Chehab 425*c22aa12cSMauro Carvalho Chehab result = self.apply_transforms("struct", line) 426*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual(result, expected) 427*c22aa12cSMauro Carvalho Chehab 428*c22aa12cSMauro Carvalho Chehab def test_struct_group_attr(self): 429*c22aa12cSMauro Carvalho Chehab """ 430*c22aa12cSMauro Carvalho Chehab Test two struct_group_attr using patterns from fs/smb/client/cifspdu.h. 431*c22aa12cSMauro Carvalho Chehab """ 432*c22aa12cSMauro Carvalho Chehab line = """ 433*c22aa12cSMauro Carvalho Chehab typedef struct smb_com_open_rsp { 434*c22aa12cSMauro Carvalho Chehab struct smb_hdr hdr; /* wct = 34 BB */ 435*c22aa12cSMauro Carvalho Chehab __u8 AndXCommand; 436*c22aa12cSMauro Carvalho Chehab __u8 AndXReserved; 437*c22aa12cSMauro Carvalho Chehab __le16 AndXOffset; 438*c22aa12cSMauro Carvalho Chehab __u8 OplockLevel; 439*c22aa12cSMauro Carvalho Chehab __u16 Fid; 440*c22aa12cSMauro Carvalho Chehab __le32 CreateAction; 441*c22aa12cSMauro Carvalho Chehab struct_group_attr(common_attributes,, 442*c22aa12cSMauro Carvalho Chehab __le64 CreationTime; 443*c22aa12cSMauro Carvalho Chehab __le64 LastAccessTime; 444*c22aa12cSMauro Carvalho Chehab __le64 LastWriteTime; 445*c22aa12cSMauro Carvalho Chehab __le64 ChangeTime; 446*c22aa12cSMauro Carvalho Chehab __le32 FileAttributes; 447*c22aa12cSMauro Carvalho Chehab ); 448*c22aa12cSMauro Carvalho Chehab __le64 AllocationSize; 449*c22aa12cSMauro Carvalho Chehab __le64 EndOfFile; 450*c22aa12cSMauro Carvalho Chehab __le16 FileType; 451*c22aa12cSMauro Carvalho Chehab __le16 DeviceState; 452*c22aa12cSMauro Carvalho Chehab __u8 DirectoryFlag; 453*c22aa12cSMauro Carvalho Chehab __u16 ByteCount; /* bct = 0 */ 454*c22aa12cSMauro Carvalho Chehab } OPEN_RSP; 455*c22aa12cSMauro Carvalho Chehab typedef struct { 456*c22aa12cSMauro Carvalho Chehab struct_group_attr(common_attributes,, 457*c22aa12cSMauro Carvalho Chehab __le64 CreationTime; 458*c22aa12cSMauro Carvalho Chehab __le64 LastAccessTime; 459*c22aa12cSMauro Carvalho Chehab __le64 LastWriteTime; 460*c22aa12cSMauro Carvalho Chehab __le64 ChangeTime; 461*c22aa12cSMauro Carvalho Chehab __le32 Attributes; 462*c22aa12cSMauro Carvalho Chehab ); 463*c22aa12cSMauro Carvalho Chehab __u32 Pad1; 464*c22aa12cSMauro Carvalho Chehab __le64 AllocationSize; 465*c22aa12cSMauro Carvalho Chehab __le64 EndOfFile; 466*c22aa12cSMauro Carvalho Chehab __le32 NumberOfLinks; 467*c22aa12cSMauro Carvalho Chehab __u8 DeletePending; 468*c22aa12cSMauro Carvalho Chehab __u8 Directory; 469*c22aa12cSMauro Carvalho Chehab __u16 Pad2; 470*c22aa12cSMauro Carvalho Chehab __le32 EASize; 471*c22aa12cSMauro Carvalho Chehab __le32 FileNameLength; 472*c22aa12cSMauro Carvalho Chehab union { 473*c22aa12cSMauro Carvalho Chehab char __pad; 474*c22aa12cSMauro Carvalho Chehab DECLARE_FLEX_ARRAY(char, FileName); 475*c22aa12cSMauro Carvalho Chehab }; 476*c22aa12cSMauro Carvalho Chehab } FILE_ALL_INFO; /* level 0x107 QPathInfo */ 477*c22aa12cSMauro Carvalho Chehab """ 478*c22aa12cSMauro Carvalho Chehab expected = """ 479*c22aa12cSMauro Carvalho Chehab typedef struct smb_com_open_rsp { 480*c22aa12cSMauro Carvalho Chehab struct smb_hdr hdr; 481*c22aa12cSMauro Carvalho Chehab __u8 AndXCommand; 482*c22aa12cSMauro Carvalho Chehab __u8 AndXReserved; 483*c22aa12cSMauro Carvalho Chehab __le16 AndXOffset; 484*c22aa12cSMauro Carvalho Chehab __u8 OplockLevel; 485*c22aa12cSMauro Carvalho Chehab __u16 Fid; 486*c22aa12cSMauro Carvalho Chehab __le32 CreateAction; 487*c22aa12cSMauro Carvalho Chehab __le64 CreationTime; 488*c22aa12cSMauro Carvalho Chehab __le64 LastAccessTime; 489*c22aa12cSMauro Carvalho Chehab __le64 LastWriteTime; 490*c22aa12cSMauro Carvalho Chehab __le64 ChangeTime; 491*c22aa12cSMauro Carvalho Chehab __le32 FileAttributes; 492*c22aa12cSMauro Carvalho Chehab __le64 AllocationSize; 493*c22aa12cSMauro Carvalho Chehab __le64 EndOfFile; 494*c22aa12cSMauro Carvalho Chehab __le16 FileType; 495*c22aa12cSMauro Carvalho Chehab __le16 DeviceState; 496*c22aa12cSMauro Carvalho Chehab __u8 DirectoryFlag; 497*c22aa12cSMauro Carvalho Chehab __u16 ByteCount; 498*c22aa12cSMauro Carvalho Chehab } OPEN_RSP; 499*c22aa12cSMauro Carvalho Chehab typedef struct { 500*c22aa12cSMauro Carvalho Chehab __le64 CreationTime; 501*c22aa12cSMauro Carvalho Chehab __le64 LastAccessTime; 502*c22aa12cSMauro Carvalho Chehab __le64 LastWriteTime; 503*c22aa12cSMauro Carvalho Chehab __le64 ChangeTime; 504*c22aa12cSMauro Carvalho Chehab __le32 Attributes; 505*c22aa12cSMauro Carvalho Chehab __u32 Pad1; 506*c22aa12cSMauro Carvalho Chehab __le64 AllocationSize; 507*c22aa12cSMauro Carvalho Chehab __le64 EndOfFile; 508*c22aa12cSMauro Carvalho Chehab __le32 NumberOfLinks; 509*c22aa12cSMauro Carvalho Chehab __u8 DeletePending; 510*c22aa12cSMauro Carvalho Chehab __u8 Directory; 511*c22aa12cSMauro Carvalho Chehab __u16 Pad2; 512*c22aa12cSMauro Carvalho Chehab __le32 EASize; 513*c22aa12cSMauro Carvalho Chehab __le32 FileNameLength; 514*c22aa12cSMauro Carvalho Chehab union { 515*c22aa12cSMauro Carvalho Chehab char __pad; 516*c22aa12cSMauro Carvalho Chehab char FileName[]; 517*c22aa12cSMauro Carvalho Chehab }; 518*c22aa12cSMauro Carvalho Chehab } FILE_ALL_INFO; 519*c22aa12cSMauro Carvalho Chehab """ 520*c22aa12cSMauro Carvalho Chehab 521*c22aa12cSMauro Carvalho Chehab result = self.apply_transforms("struct", line) 522*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual(result, expected) 523*c22aa12cSMauro Carvalho Chehab 524*c22aa12cSMauro Carvalho Chehab def test_raw_struct_group(self): 525*c22aa12cSMauro Carvalho Chehab """ 526*c22aa12cSMauro Carvalho Chehab Test a __struct_group pattern from include/uapi/cxl/features.h. 527*c22aa12cSMauro Carvalho Chehab """ 528*c22aa12cSMauro Carvalho Chehab line = """ 529*c22aa12cSMauro Carvalho Chehab struct cxl_mbox_get_sup_feats_out { 530*c22aa12cSMauro Carvalho Chehab __struct_group(cxl_mbox_get_sup_feats_out_hdr, hdr, /* empty */, 531*c22aa12cSMauro Carvalho Chehab __le16 num_entries; 532*c22aa12cSMauro Carvalho Chehab __le16 supported_feats; 533*c22aa12cSMauro Carvalho Chehab __u8 reserved[4]; 534*c22aa12cSMauro Carvalho Chehab ); 535*c22aa12cSMauro Carvalho Chehab struct cxl_feat_entry ents[] __counted_by_le(num_entries); 536*c22aa12cSMauro Carvalho Chehab } __attribute__ ((__packed__)); 537*c22aa12cSMauro Carvalho Chehab """ 538*c22aa12cSMauro Carvalho Chehab expected = """ 539*c22aa12cSMauro Carvalho Chehab struct cxl_mbox_get_sup_feats_out { 540*c22aa12cSMauro Carvalho Chehab __le16 num_entries; 541*c22aa12cSMauro Carvalho Chehab __le16 supported_feats; 542*c22aa12cSMauro Carvalho Chehab __u8 reserved[4]; 543*c22aa12cSMauro Carvalho Chehab struct cxl_feat_entry ents[]; 544*c22aa12cSMauro Carvalho Chehab }; 545*c22aa12cSMauro Carvalho Chehab """ 546*c22aa12cSMauro Carvalho Chehab 547*c22aa12cSMauro Carvalho Chehab result = self.apply_transforms("struct", line) 548*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual(result, expected) 549*c22aa12cSMauro Carvalho Chehab 550*c22aa12cSMauro Carvalho Chehab def test_raw_struct_group_tagged(self): 551*c22aa12cSMauro Carvalho Chehab r""" 552*c22aa12cSMauro Carvalho Chehab Test cxl_regs with struct_group_tagged patterns from drivers/cxl/cxl.h. 553*c22aa12cSMauro Carvalho Chehab 554*c22aa12cSMauro Carvalho Chehab NOTE: 555*c22aa12cSMauro Carvalho Chehab 556*c22aa12cSMauro Carvalho Chehab This one has actually a violation from what kernel-doc would 557*c22aa12cSMauro Carvalho Chehab expect: Kernel-doc regex expects only 3 members, but this is 558*c22aa12cSMauro Carvalho Chehab actually defined as:: 559*c22aa12cSMauro Carvalho Chehab 560*c22aa12cSMauro Carvalho Chehab #define struct_group_tagged(TAG, NAME, MEMBERS...) 561*c22aa12cSMauro Carvalho Chehab 562*c22aa12cSMauro Carvalho Chehab The replace expression there is:: 563*c22aa12cSMauro Carvalho Chehab 564*c22aa12cSMauro Carvalho Chehab struct \1 { \3 } \2; 565*c22aa12cSMauro Carvalho Chehab 566*c22aa12cSMauro Carvalho Chehab but it should be really something like:: 567*c22aa12cSMauro Carvalho Chehab 568*c22aa12cSMauro Carvalho Chehab struct \1 { \3 \4 \5 \6 \7 \8 ... } \2; 569*c22aa12cSMauro Carvalho Chehab 570*c22aa12cSMauro Carvalho Chehab a later fix would be needed to address it. 571*c22aa12cSMauro Carvalho Chehab 572*c22aa12cSMauro Carvalho Chehab """ 573*c22aa12cSMauro Carvalho Chehab line = """ 574*c22aa12cSMauro Carvalho Chehab struct cxl_regs { 575*c22aa12cSMauro Carvalho Chehab struct_group_tagged(cxl_component_regs, component, 576*c22aa12cSMauro Carvalho Chehab void __iomem *hdm_decoder; 577*c22aa12cSMauro Carvalho Chehab void __iomem *ras; 578*c22aa12cSMauro Carvalho Chehab ); 579*c22aa12cSMauro Carvalho Chehab 580*c22aa12cSMauro Carvalho Chehab 581*c22aa12cSMauro Carvalho Chehab /* This is actually a violation: too much commas */ 582*c22aa12cSMauro Carvalho Chehab struct_group_tagged(cxl_device_regs, device_regs, 583*c22aa12cSMauro Carvalho Chehab void __iomem *status, *mbox, *memdev; 584*c22aa12cSMauro Carvalho Chehab ); 585*c22aa12cSMauro Carvalho Chehab 586*c22aa12cSMauro Carvalho Chehab struct_group_tagged(cxl_pmu_regs, pmu_regs, 587*c22aa12cSMauro Carvalho Chehab void __iomem *pmu; 588*c22aa12cSMauro Carvalho Chehab ); 589*c22aa12cSMauro Carvalho Chehab 590*c22aa12cSMauro Carvalho Chehab struct_group_tagged(cxl_rch_regs, rch_regs, 591*c22aa12cSMauro Carvalho Chehab void __iomem *dport_aer; 592*c22aa12cSMauro Carvalho Chehab ); 593*c22aa12cSMauro Carvalho Chehab 594*c22aa12cSMauro Carvalho Chehab struct_group_tagged(cxl_rcd_regs, rcd_regs, 595*c22aa12cSMauro Carvalho Chehab void __iomem *rcd_pcie_cap; 596*c22aa12cSMauro Carvalho Chehab ); 597*c22aa12cSMauro Carvalho Chehab }; 598*c22aa12cSMauro Carvalho Chehab """ 599*c22aa12cSMauro Carvalho Chehab expected = """ 600*c22aa12cSMauro Carvalho Chehab struct cxl_regs { 601*c22aa12cSMauro Carvalho Chehab struct cxl_component_regs { 602*c22aa12cSMauro Carvalho Chehab void __iomem *hdm_decoder; 603*c22aa12cSMauro Carvalho Chehab void __iomem *ras; 604*c22aa12cSMauro Carvalho Chehab } component; 605*c22aa12cSMauro Carvalho Chehab 606*c22aa12cSMauro Carvalho Chehab struct cxl_device_regs { 607*c22aa12cSMauro Carvalho Chehab void __iomem *status, *mbox, *memdev; 608*c22aa12cSMauro Carvalho Chehab } device_regs; 609*c22aa12cSMauro Carvalho Chehab 610*c22aa12cSMauro Carvalho Chehab struct cxl_pmu_regs { 611*c22aa12cSMauro Carvalho Chehab void __iomem *pmu; 612*c22aa12cSMauro Carvalho Chehab } pmu_regs; 613*c22aa12cSMauro Carvalho Chehab 614*c22aa12cSMauro Carvalho Chehab struct cxl_rch_regs { 615*c22aa12cSMauro Carvalho Chehab void __iomem *dport_aer; 616*c22aa12cSMauro Carvalho Chehab } rch_regs; 617*c22aa12cSMauro Carvalho Chehab 618*c22aa12cSMauro Carvalho Chehab struct cxl_rcd_regs { 619*c22aa12cSMauro Carvalho Chehab void __iomem *rcd_pcie_cap; 620*c22aa12cSMauro Carvalho Chehab } rcd_regs; 621*c22aa12cSMauro Carvalho Chehab }; 622*c22aa12cSMauro Carvalho Chehab """ 623*c22aa12cSMauro Carvalho Chehab 624*c22aa12cSMauro Carvalho Chehab result = self.apply_transforms("struct", line) 625*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual(result, expected) 626*c22aa12cSMauro Carvalho Chehab 627*c22aa12cSMauro Carvalho Chehab def test_struct_group_tagged_with_private(self): 628*c22aa12cSMauro Carvalho Chehab """ 629*c22aa12cSMauro Carvalho Chehab Replace struct_group_tagged with private, using the same regex 630*c22aa12cSMauro Carvalho Chehab for the replacement as what happens in xforms_lists.py. 631*c22aa12cSMauro Carvalho Chehab 632*c22aa12cSMauro Carvalho Chehab As the private removal happens outside NestedGroup class, we manually 633*c22aa12cSMauro Carvalho Chehab dropped the remaining part of the struct, to simulate what happens 634*c22aa12cSMauro Carvalho Chehab at kdoc_parser. 635*c22aa12cSMauro Carvalho Chehab 636*c22aa12cSMauro Carvalho Chehab Taken from include/net/page_pool/types.h 637*c22aa12cSMauro Carvalho Chehab """ 638*c22aa12cSMauro Carvalho Chehab line = """ 639*c22aa12cSMauro Carvalho Chehab struct page_pool_params { 640*c22aa12cSMauro Carvalho Chehab struct_group_tagged(page_pool_params_slow, slow, 641*c22aa12cSMauro Carvalho Chehab struct net_device *netdev; 642*c22aa12cSMauro Carvalho Chehab unsigned int queue_idx; 643*c22aa12cSMauro Carvalho Chehab unsigned int flags; 644*c22aa12cSMauro Carvalho Chehab /* private: only under "slow" struct */ 645*c22aa12cSMauro Carvalho Chehab unsigned int ignored; 646*c22aa12cSMauro Carvalho Chehab ); 647*c22aa12cSMauro Carvalho Chehab /* Struct below shall not be ignored */ 648*c22aa12cSMauro Carvalho Chehab struct_group_tagged(page_pool_params_fast, fast, 649*c22aa12cSMauro Carvalho Chehab unsigned int order; 650*c22aa12cSMauro Carvalho Chehab unsigned int pool_size; 651*c22aa12cSMauro Carvalho Chehab int nid; 652*c22aa12cSMauro Carvalho Chehab struct device *dev; 653*c22aa12cSMauro Carvalho Chehab struct napi_struct *napi; 654*c22aa12cSMauro Carvalho Chehab enum dma_data_direction dma_dir; 655*c22aa12cSMauro Carvalho Chehab unsigned int max_len; 656*c22aa12cSMauro Carvalho Chehab unsigned int offset; 657*c22aa12cSMauro Carvalho Chehab ); 658*c22aa12cSMauro Carvalho Chehab }; 659*c22aa12cSMauro Carvalho Chehab """ 660*c22aa12cSMauro Carvalho Chehab expected = """ 661*c22aa12cSMauro Carvalho Chehab struct page_pool_params { 662*c22aa12cSMauro Carvalho Chehab struct page_pool_params_slow { 663*c22aa12cSMauro Carvalho Chehab struct net_device *netdev; 664*c22aa12cSMauro Carvalho Chehab unsigned int queue_idx; 665*c22aa12cSMauro Carvalho Chehab unsigned int flags; 666*c22aa12cSMauro Carvalho Chehab } slow; 667*c22aa12cSMauro Carvalho Chehab struct page_pool_params_fast { 668*c22aa12cSMauro Carvalho Chehab unsigned int order; 669*c22aa12cSMauro Carvalho Chehab unsigned int pool_size; 670*c22aa12cSMauro Carvalho Chehab int nid; 671*c22aa12cSMauro Carvalho Chehab struct device *dev; 672*c22aa12cSMauro Carvalho Chehab struct napi_struct *napi; 673*c22aa12cSMauro Carvalho Chehab enum dma_data_direction dma_dir; 674*c22aa12cSMauro Carvalho Chehab unsigned int max_len; 675*c22aa12cSMauro Carvalho Chehab unsigned int offset; 676*c22aa12cSMauro Carvalho Chehab } fast; 677*c22aa12cSMauro Carvalho Chehab }; 678*c22aa12cSMauro Carvalho Chehab """ 679*c22aa12cSMauro Carvalho Chehab 680*c22aa12cSMauro Carvalho Chehab result = self.apply_transforms("struct", line) 681*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual(result, expected) 682*c22aa12cSMauro Carvalho Chehab 683*c22aa12cSMauro Carvalho Chehab def test_struct_kcov(self): 684*c22aa12cSMauro Carvalho Chehab """ 685*c22aa12cSMauro Carvalho Chehab """ 686*c22aa12cSMauro Carvalho Chehab line = """ 687*c22aa12cSMauro Carvalho Chehab struct kcov { 688*c22aa12cSMauro Carvalho Chehab refcount_t refcount; 689*c22aa12cSMauro Carvalho Chehab spinlock_t lock; 690*c22aa12cSMauro Carvalho Chehab enum kcov_mode mode __guarded_by(&lock); 691*c22aa12cSMauro Carvalho Chehab unsigned int size __guarded_by(&lock); 692*c22aa12cSMauro Carvalho Chehab void *area __guarded_by(&lock); 693*c22aa12cSMauro Carvalho Chehab struct task_struct *t __guarded_by(&lock); 694*c22aa12cSMauro Carvalho Chehab bool remote; 695*c22aa12cSMauro Carvalho Chehab unsigned int remote_size; 696*c22aa12cSMauro Carvalho Chehab int sequence; 697*c22aa12cSMauro Carvalho Chehab }; 698*c22aa12cSMauro Carvalho Chehab """ 699*c22aa12cSMauro Carvalho Chehab expected = """ 700*c22aa12cSMauro Carvalho Chehab """ 701*c22aa12cSMauro Carvalho Chehab 702*c22aa12cSMauro Carvalho Chehab result = self.apply_transforms("struct", line) 703*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual(result, expected) 704*c22aa12cSMauro Carvalho Chehab 705*c22aa12cSMauro Carvalho Chehab 706*c22aa12cSMauro Carvalho Chehab def test_struct_kcov(self): 707*c22aa12cSMauro Carvalho Chehab """ 708*c22aa12cSMauro Carvalho Chehab Test a struct from kernel/kcov.c. 709*c22aa12cSMauro Carvalho Chehab """ 710*c22aa12cSMauro Carvalho Chehab line = """ 711*c22aa12cSMauro Carvalho Chehab struct kcov { 712*c22aa12cSMauro Carvalho Chehab refcount_t refcount; 713*c22aa12cSMauro Carvalho Chehab spinlock_t lock; 714*c22aa12cSMauro Carvalho Chehab enum kcov_mode mode __guarded_by(&lock); 715*c22aa12cSMauro Carvalho Chehab unsigned int size __guarded_by(&lock); 716*c22aa12cSMauro Carvalho Chehab void *area __guarded_by(&lock); 717*c22aa12cSMauro Carvalho Chehab struct task_struct *t __guarded_by(&lock); 718*c22aa12cSMauro Carvalho Chehab bool remote; 719*c22aa12cSMauro Carvalho Chehab unsigned int remote_size; 720*c22aa12cSMauro Carvalho Chehab int sequence; 721*c22aa12cSMauro Carvalho Chehab }; 722*c22aa12cSMauro Carvalho Chehab """ 723*c22aa12cSMauro Carvalho Chehab expected = """ 724*c22aa12cSMauro Carvalho Chehab struct kcov { 725*c22aa12cSMauro Carvalho Chehab refcount_t refcount; 726*c22aa12cSMauro Carvalho Chehab spinlock_t lock; 727*c22aa12cSMauro Carvalho Chehab enum kcov_mode mode; 728*c22aa12cSMauro Carvalho Chehab unsigned int size; 729*c22aa12cSMauro Carvalho Chehab void *area; 730*c22aa12cSMauro Carvalho Chehab struct task_struct *t; 731*c22aa12cSMauro Carvalho Chehab bool remote; 732*c22aa12cSMauro Carvalho Chehab unsigned int remote_size; 733*c22aa12cSMauro Carvalho Chehab int sequence; 734*c22aa12cSMauro Carvalho Chehab }; 735*c22aa12cSMauro Carvalho Chehab """ 736*c22aa12cSMauro Carvalho Chehab 737*c22aa12cSMauro Carvalho Chehab result = self.apply_transforms("struct", line) 738*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual(result, expected) 739*c22aa12cSMauro Carvalho Chehab 740*c22aa12cSMauro Carvalho Chehab def test_vars_stackdepot(self): 741*c22aa12cSMauro Carvalho Chehab """ 742*c22aa12cSMauro Carvalho Chehab Test guarded_by on vars from lib/stackdepot.c. 743*c22aa12cSMauro Carvalho Chehab """ 744*c22aa12cSMauro Carvalho Chehab line = """ 745*c22aa12cSMauro Carvalho Chehab size_t pool_offset __guarded_by(&pool_lock) = DEPOT_POOL_SIZE; 746*c22aa12cSMauro Carvalho Chehab __guarded_by(&pool_lock) LIST_HEAD(free_stacks); 747*c22aa12cSMauro Carvalho Chehab void **stack_pools __pt_guarded_by(&pool_lock); 748*c22aa12cSMauro Carvalho Chehab """ 749*c22aa12cSMauro Carvalho Chehab expected = """ 750*c22aa12cSMauro Carvalho Chehab size_t pool_offset = DEPOT_POOL_SIZE; 751*c22aa12cSMauro Carvalho Chehab struct list_head free_stacks; 752*c22aa12cSMauro Carvalho Chehab void **stack_pools; 753*c22aa12cSMauro Carvalho Chehab """ 754*c22aa12cSMauro Carvalho Chehab 755*c22aa12cSMauro Carvalho Chehab result = self.apply_transforms("var", line) 756*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual(result, expected) 757*c22aa12cSMauro Carvalho Chehab 758*c22aa12cSMauro Carvalho Chehab def test_functions_with_acquires_and_releases(self): 759*c22aa12cSMauro Carvalho Chehab """ 760*c22aa12cSMauro Carvalho Chehab Test guarded_by on vars from lib/stackdepot.c. 761*c22aa12cSMauro Carvalho Chehab """ 762*c22aa12cSMauro Carvalho Chehab line = """ 763*c22aa12cSMauro Carvalho Chehab bool prepare_report_consumer(unsigned long *flags, 764*c22aa12cSMauro Carvalho Chehab const struct access_info *ai, 765*c22aa12cSMauro Carvalho Chehab struct other_info *other_info) \ 766*c22aa12cSMauro Carvalho Chehab __cond_acquires(true, &report_lock); 767*c22aa12cSMauro Carvalho Chehab 768*c22aa12cSMauro Carvalho Chehab int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) \ 769*c22aa12cSMauro Carvalho Chehab __cond_acquires(0, RCU_BH); 770*c22aa12cSMauro Carvalho Chehab 771*c22aa12cSMauro Carvalho Chehab bool undo_report_consumer(unsigned long *flags, 772*c22aa12cSMauro Carvalho Chehab const struct access_info *ai, 773*c22aa12cSMauro Carvalho Chehab struct other_info *other_info) \ 774*c22aa12cSMauro Carvalho Chehab __cond_releases(true, &report_lock); 775*c22aa12cSMauro Carvalho Chehab 776*c22aa12cSMauro Carvalho Chehab void debugfs_enter_cancellation(struct file *file, 777*c22aa12cSMauro Carvalho Chehab struct debugfs_cancellation *c) \ 778*c22aa12cSMauro Carvalho Chehab __acquires(cancellation); 779*c22aa12cSMauro Carvalho Chehab 780*c22aa12cSMauro Carvalho Chehab void debugfs_leave_cancellation(struct file *file, 781*c22aa12cSMauro Carvalho Chehab struct debugfs_cancellation *c) \ 782*c22aa12cSMauro Carvalho Chehab __releases(cancellation); 783*c22aa12cSMauro Carvalho Chehab 784*c22aa12cSMauro Carvalho Chehab acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp) \ 785*c22aa12cSMauro Carvalho Chehab __acquires(lockp); 786*c22aa12cSMauro Carvalho Chehab 787*c22aa12cSMauro Carvalho Chehab void acpi_os_release_lock(acpi_spinlock lockp, 788*c22aa12cSMauro Carvalho Chehab acpi_cpu_flags not_used) \ 789*c22aa12cSMauro Carvalho Chehab __releases(lockp) 790*c22aa12cSMauro Carvalho Chehab """ 791*c22aa12cSMauro Carvalho Chehab expected = """ 792*c22aa12cSMauro Carvalho Chehab bool prepare_report_consumer(unsigned long *flags, 793*c22aa12cSMauro Carvalho Chehab const struct access_info *ai, 794*c22aa12cSMauro Carvalho Chehab struct other_info *other_info); 795*c22aa12cSMauro Carvalho Chehab 796*c22aa12cSMauro Carvalho Chehab int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c); 797*c22aa12cSMauro Carvalho Chehab 798*c22aa12cSMauro Carvalho Chehab bool undo_report_consumer(unsigned long *flags, 799*c22aa12cSMauro Carvalho Chehab const struct access_info *ai, 800*c22aa12cSMauro Carvalho Chehab struct other_info *other_info); 801*c22aa12cSMauro Carvalho Chehab 802*c22aa12cSMauro Carvalho Chehab void debugfs_enter_cancellation(struct file *file, 803*c22aa12cSMauro Carvalho Chehab struct debugfs_cancellation *c); 804*c22aa12cSMauro Carvalho Chehab 805*c22aa12cSMauro Carvalho Chehab void debugfs_leave_cancellation(struct file *file, 806*c22aa12cSMauro Carvalho Chehab struct debugfs_cancellation *c); 807*c22aa12cSMauro Carvalho Chehab 808*c22aa12cSMauro Carvalho Chehab acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp); 809*c22aa12cSMauro Carvalho Chehab 810*c22aa12cSMauro Carvalho Chehab void acpi_os_release_lock(acpi_spinlock lockp, 811*c22aa12cSMauro Carvalho Chehab acpi_cpu_flags not_used) 812*c22aa12cSMauro Carvalho Chehab """ 813*c22aa12cSMauro Carvalho Chehab 814*c22aa12cSMauro Carvalho Chehab result = self.apply_transforms("func", line) 815*c22aa12cSMauro Carvalho Chehab self.assertLogicallyEqual(result, expected) 816*c22aa12cSMauro Carvalho Chehab 817*c22aa12cSMauro Carvalho Chehab# 81850b87bb4SMauro Carvalho Chehab# Run all tests 81950b87bb4SMauro Carvalho Chehab# 82050b87bb4SMauro Carvalho Chehabif __name__ == "__main__": 82150b87bb4SMauro Carvalho Chehab run_unittest(__file__) 822