]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
dt-bindings: add self-test fixtures for style checker
authorDaniel Golle <daniel@makrotopia.org>
Wed, 27 May 2026 19:32:34 +0000 (20:32 +0100)
committerRob Herring (Arm) <robh@kernel.org>
Wed, 10 Jun 2026 18:37:06 +0000 (13:37 -0500)
Provide good/ and bad/ DTS and YAML fixtures plus a small runner that
feeds them to dt-check-style and diffs the output against expected
text files. Wired into a new top-level dt_style_selftest make target
so the suite can be exercised independently of the full tree.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Link: https://patch.msgid.link/80fec5d2cfcdee0f9c5e2d4921ebbd4115d392b7.1779908995.git.daniel@makrotopia.org
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
54 files changed:
Makefile
scripts/dtc/dt-style-selftest/bad/dts-spaces.dts [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-child-addr-order.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-child-name-order.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-digit-node-order.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-indent-strict.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-label-in-string.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-multi-close.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-node-close.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-prop-pairing.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-required-blank.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-tab.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-trailing-comment.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-unclosed-comment.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-unit-addr-prefix.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-unit-addr.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-unused-label.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-value-ws-multiline.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/bad/yaml-value-ws.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/dts-spaces.dts.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-child-addr-order.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-child-name-order.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-digit-node-order.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-hex-case.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-indent-strict.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-label-in-string.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-line-length.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-multi-close.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-node-close.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-prop-order.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-prop-pairing.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-required-blank.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-tab.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-trailing-comment.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-trailing-ws.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-unclosed-comment.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-unit-addr-prefix.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-unit-addr.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-unused-label.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-value-ws-multiline.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/expected/yaml-value-ws.yaml.txt [new file with mode: 0644]
scripts/dtc/dt-style-selftest/good/dts-cont-align.dts [new file with mode: 0644]
scripts/dtc/dt-style-selftest/good/dts-tab.dts [new file with mode: 0644]
scripts/dtc/dt-style-selftest/good/yaml-4space.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/good/yaml-tricky-parsing.yaml [new file with mode: 0644]
scripts/dtc/dt-style-selftest/run.sh [new file with mode: 0755]

index e27c91ea56fcf8895660d2afe90042e71f37ec3b..c5513b573bbde0ec70ea87d815aabcc06be44b9f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -295,6 +295,7 @@ no-dot-config-targets := $(clean-targets) \
                         cscope gtags TAGS tags help% %docs check% coccicheck \
                         $(version_h) headers headers_% archheaders archscripts \
                         %asm-generic kernelversion %src-pkg dt_binding_check \
+                        dt_style_selftest \
                         outputmakefile rustavailable rustfmt rustfmtcheck \
                         run-command
 no-sync-config-targets := $(no-dot-config-targets) %install modules_sign kernelrelease \
@@ -1643,6 +1644,10 @@ PHONY += dt_compatible_check
 dt_compatible_check: dt_binding_schemas
        $(Q)$(MAKE) $(build)=$(dtbindingtree) $@
 
+PHONY += dt_style_selftest
+dt_style_selftest:
+       $(Q)$(srctree)/scripts/dtc/dt-style-selftest/run.sh
+
 # ---------------------------------------------------------------------------
 # Modules
 
@@ -1845,6 +1850,7 @@ help:
                echo '  dtbs_install       - Install dtbs to $(INSTALL_DTBS_PATH)'; \
                echo '  dt_binding_check   - Validate device tree binding documents and examples'; \
                echo '  dt_binding_schemas - Build processed device tree binding schemas'; \
+               echo '  dt_style_selftest  - Run dt-check-style fixture tests'; \
                echo '  dtbs_check         - Validate device tree source files';\
                echo '')
 
diff --git a/scripts/dtc/dt-style-selftest/bad/dts-spaces.dts b/scripts/dtc/dt-style-selftest/bad/dts-spaces.dts
new file mode 100644 (file)
index 0000000..9dad22a
--- /dev/null
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/*
+ * Test fixture: a .dts using space indent (must use tabs).
+ */
+
+/dts-v1/;
+
+/ {
+    compatible = "example,test-board";
+    #address-cells = <1>;
+    #size-cells = <1>;
+};
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-child-addr-order.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-child-addr-order.yaml
new file mode 100644 (file)
index 0000000..3df56e6
--- /dev/null
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-child-order.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with addressed children out of order
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-child-order
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    bus@10000 {
+        compatible = "simple-bus";
+        reg = <0x10000 0x1000>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+
+        device@200 {
+            compatible = "example,test-child-order";
+            reg = <0x200 0x10>;
+        };
+
+        device@100 {
+            compatible = "example,test-child-order";
+            reg = <0x100 0x10>;
+        };
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-child-name-order.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-child-name-order.yaml
new file mode 100644 (file)
index 0000000..35d85e5
--- /dev/null
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-child-name-order.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with unaddressed children out of name order
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-child-name-order
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    bus@10000 {
+        compatible = "simple-bus";
+        reg = <0x10000 0x1000>;
+
+        foo {
+            label = "foo";
+        };
+
+        bar {
+            label = "bar";
+        };
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml
new file mode 100644 (file)
index 0000000..9277854
--- /dev/null
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-cont-align.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with mis-aligned multi-line property
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-cont-align
+  reg:
+    maxItems: 2
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    foo@1000 {
+        compatible = "example,test-cont-align";
+        reg = <0x1000 0x100>,
+            <0x2000 0x100>;
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-digit-node-order.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-digit-node-order.yaml
new file mode 100644 (file)
index 0000000..44a9d25
--- /dev/null
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-digit-node-order.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with digit-leading nodes out of address order
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-digit-node-order
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    bus@0 {
+        compatible = "simple-bus";
+        #address-cells = <1>;
+        #size-cells = <1>;
+
+        3d-engine@20 {
+            compatible = "example,3d-engine";
+            reg = <0x20 0x4>;
+        };
+
+        1wire@10 {
+            compatible = "example,1wire";
+            reg = <0x10 0x4>;
+        };
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml
new file mode 100644 (file)
index 0000000..b26d1bf
--- /dev/null
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-hex-case.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with uppercase hex literals
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-hex-case
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    foo@1000 {
+        compatible = "example,test-hex-case";
+        reg = <0xABCD 0x100>;
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-indent-strict.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-indent-strict.yaml
new file mode 100644 (file)
index 0000000..bee4cf1
--- /dev/null
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-indent-strict.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture using 2-space indent (rejected by strict mode)
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-indent-strict
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    device@1000 {
+      compatible = "example,test-indent-strict";
+      reg = <0x1000 0x100>;
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-label-in-string.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-label-in-string.yaml
new file mode 100644 (file)
index 0000000..ba51286
--- /dev/null
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-label-in-string.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture where a label is only "referenced" inside a string
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-label-in-string
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    foo: device@1000 {
+        compatible = "example,test-label-in-string";
+        reg = <0x1000 0x100>;
+        info = "see &foo for details";
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml
new file mode 100644 (file)
index 0000000..64427bf
--- /dev/null
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-line-length.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture exceeding 80 columns
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-line-length
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    foo@1000 {
+        compatible = "example,test-line-length-this-is-a-very-long-name-indeed-yeah";
+        reg = <0x1000 0x100>;
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml
new file mode 100644 (file)
index 0000000..5401d1a
--- /dev/null
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-mixed-indent.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture mixing tabs and spaces in indent
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-mixed
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    device@1000 {
+          compatible = "example,test-mixed";
+        reg = <0x1000 0x100>;
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-multi-close.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-multi-close.yaml
new file mode 100644 (file)
index 0000000..4d9fa27
--- /dev/null
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-multi-close.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with two closing braces on one line
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-multi-close
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    bus@10000 {
+        compatible = "simple-bus";
+        reg = <0x10000 0x1000>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+
+        device@100 {
+            compatible = "example,test-multi-close";
+            reg = <0x100 0x10>;
+        }; };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-node-close.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-node-close.yaml
new file mode 100644 (file)
index 0000000..e107659
--- /dev/null
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-node-close.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with closing brace not on its own line
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-node-close
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    bus@10000 {
+        compatible = "simple-bus";
+        reg = <0x10000 0x1000>;
+
+        empty {};
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml
new file mode 100644 (file)
index 0000000..75582a3
--- /dev/null
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-prop-order.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with reg before compatible
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-prop-order
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    device@1000 {
+        reg = <0x1000 0x100>;
+        compatible = "example,test-prop-order";
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-prop-pairing.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-prop-pairing.yaml
new file mode 100644 (file)
index 0000000..767ab21
--- /dev/null
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-prop-pairing.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture exercising <x>-names and pinctrl-names pairing
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-prop-pairing
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    foo@1000 {
+        compatible = "example,test-prop-pairing";
+        reg = <0x1000 0x100>;
+        clock-names = "bus";
+        clocks = <&clk 0>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&p0>;
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-required-blank.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-required-blank.yaml
new file mode 100644 (file)
index 0000000..8bb5324
--- /dev/null
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-required-blank.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture missing required blank lines
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-required-blank
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    bus@10000 {
+        compatible = "simple-bus";
+        reg = <0x10000 0x1000>;
+        status = "okay";
+        child@100 {
+            reg = <0x100>;
+        };
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-tab.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-tab.yaml
new file mode 100644 (file)
index 0000000..487d07f
--- /dev/null
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-tab.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with a tab in a DTS line
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-tab
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    device@1000 {
+        compatible = "example,test-tab";
+        reg = <0x1000 0x100>;  /* registers */
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-trailing-comment.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-trailing-comment.yaml
new file mode 100644 (file)
index 0000000..2368ada
--- /dev/null
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-trailing-comment.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with properties out of order behind trailing comments
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-trailing-comment
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    foo@0 {  /* the device node */
+        reg = <0x0 0x4>;  /* registers */
+        compatible = "example,test-trailing-comment";  // misplaced
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml
new file mode 100644 (file)
index 0000000..5c4b4bd
--- /dev/null
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-trailing.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with trailing whitespace
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-trailing
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    device@1000 {
+        compatible = "example,test-trailing";  
+        reg = <0x1000 0x100>;
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-unclosed-comment.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-unclosed-comment.yaml
new file mode 100644 (file)
index 0000000..63c1c08
--- /dev/null
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-unclosed-comment.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with an unclosed /* block comment
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-unclosed-comment
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    /* this comment never closes
+    device@1000 {
+        compatible = "example,test-unclosed-comment";
+        reg = <0x1000 0x100>;
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-unit-addr-prefix.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-unit-addr-prefix.yaml
new file mode 100644 (file)
index 0000000..9b3fe50
--- /dev/null
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-unit-addr-prefix.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with 0x-prefixed unit address
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-unit-addr-prefix
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    memory@0x1000 {
+        compatible = "example,test-unit-addr-prefix";
+        reg = <0x1000 0x100>;
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-unit-addr.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-unit-addr.yaml
new file mode 100644 (file)
index 0000000..93705cd
--- /dev/null
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-unit-addr.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with malformed unit address
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-unit-addr
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    foo@01000 {
+        compatible = "example,test-unit-addr";
+        reg = <0x1000 0x100>;
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-unused-label.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-unused-label.yaml
new file mode 100644 (file)
index 0000000..28d7176
--- /dev/null
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-unused-label.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with an unused label
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-unused-label
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    dev: device@1000 {
+        compatible = "example,test-unused-label";
+        reg = <0x1000 0x100>;
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-value-ws-multiline.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-value-ws-multiline.yaml
new file mode 100644 (file)
index 0000000..504bf09
--- /dev/null
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-value-ws-multiline.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with extra whitespace in a multi-line cell array
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-value-ws-multiline
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    foo@0 {
+        compatible = "example,test-value-ws-multiline";
+        reg = < 0x0 0x4
+              0x8 0xc>;
+    };
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-value-ws.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-value-ws.yaml
new file mode 100644 (file)
index 0000000..342ab9f
--- /dev/null
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-value-ws.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with extra whitespace inside <...>
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-value-ws
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    foo@1000 {
+        compatible = "example,test-value-ws";
+        reg = < 0x1000 0x100 >;
+    };
diff --git a/scripts/dtc/dt-style-selftest/expected/dts-spaces.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-spaces.dts.txt
new file mode 100644 (file)
index 0000000..070025c
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=relaxed
+bad/dts-spaces.dts:1: [indent-unit-dts] indent unit must be 1 tab in DTS, got '    '
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-child-addr-order.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-child-addr-order.yaml.txt
new file mode 100644 (file)
index 0000000..f0db79a
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-child-addr-order.yaml:37: example 0 [child-address-order] child node @100 out of address order
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-child-name-order.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-child-name-order.yaml.txt
new file mode 100644 (file)
index 0000000..bb434b1
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-child-name-order.yaml:34: example 0 [child-name-order] child node 'bar' out of name order
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt
new file mode 100644 (file)
index 0000000..b5576dd
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-cont-align.yaml:29: example 0 [continuation-alignment] continuation should align to column 11 (under "<" or \")
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-digit-node-order.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-digit-node-order.yaml.txt
new file mode 100644 (file)
index 0000000..6de275e
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-digit-node-order.yaml:33: example 0 [child-address-order] child node @10 out of address order
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-hex-case.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-hex-case.yaml.txt
new file mode 100644 (file)
index 0000000..6600f7c
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-hex-case.yaml:28: example 0 [hex-case] hex literal '0xABCD' must be lowercase
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-indent-strict.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-indent-strict.yaml.txt
new file mode 100644 (file)
index 0000000..5ef290d
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-indent-strict.yaml:26: example 0 [indent-unit-strict] indent unit must be 4 spaces in strict mode, got '  '
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-label-in-string.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-label-in-string.yaml.txt
new file mode 100644 (file)
index 0000000..05da06f
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-label-in-string.yaml:26: example 0 [unused-labels] label 'foo' defined but never &-referenced
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-line-length.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-line-length.yaml.txt
new file mode 100644 (file)
index 0000000..89b3636
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-line-length.yaml:27: example 0 [line-length] line exceeds 80 columns (81)
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt
new file mode 100644 (file)
index 0000000..c989f8f
--- /dev/null
@@ -0,0 +1,3 @@
+# mode=relaxed
+bad/yaml-mixed-indent.yaml:27: example 0 [mixed-indent-chars] mixed tabs and spaces in indent
+bad/yaml-mixed-indent.yaml:27: example 0 [tab-in-dts] tab character not allowed in DTS example
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-multi-close.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-multi-close.yaml.txt
new file mode 100644 (file)
index 0000000..637d0f8
--- /dev/null
@@ -0,0 +1,3 @@
+# mode=strict
+bad/yaml-multi-close.yaml:35: example 0 [indent-consistent] indent mismatch (expected depth 0 * '    ')
+bad/yaml-multi-close.yaml:35: example 0 [node-close-alone] closing brace must be on its own line
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-node-close.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-node-close.yaml.txt
new file mode 100644 (file)
index 0000000..ee89474
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-node-close.yaml:30: example 0 [node-close-alone] closing brace must be on its own line
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-prop-order.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-prop-order.yaml.txt
new file mode 100644 (file)
index 0000000..578df72
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-prop-order.yaml:28: example 0 [property-order] property 'compatible' out of canonical order (should sort before 'reg')
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-prop-pairing.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-prop-pairing.yaml.txt
new file mode 100644 (file)
index 0000000..e6e2134
--- /dev/null
@@ -0,0 +1,3 @@
+# mode=strict
+bad/yaml-prop-pairing.yaml:30: example 0 [property-order] property 'clocks' out of canonical order (should sort before 'clock-names')
+bad/yaml-prop-pairing.yaml:32: example 0 [property-order] property 'pinctrl-0' out of canonical order (should sort before 'pinctrl-names')
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-required-blank.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-required-blank.yaml.txt
new file mode 100644 (file)
index 0000000..04ea0ba
--- /dev/null
@@ -0,0 +1,3 @@
+# mode=strict
+bad/yaml-required-blank.yaml:29: example 0 [required-blank-lines] "status" must be preceded by a blank line
+bad/yaml-required-blank.yaml:30: example 0 [required-blank-lines] child node must be preceded by a blank line
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-tab.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-tab.yaml.txt
new file mode 100644 (file)
index 0000000..9e83246
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=relaxed
+bad/yaml-tab.yaml:28: example 0 [tab-in-dts] tab character not allowed in DTS example
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-trailing-comment.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-trailing-comment.yaml.txt
new file mode 100644 (file)
index 0000000..69dbb1d
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-trailing-comment.yaml:25: example 0 [property-order] property 'compatible' out of canonical order (should sort before 'reg')
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-trailing-ws.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-trailing-ws.yaml.txt
new file mode 100644 (file)
index 0000000..cfdbc84
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=relaxed
+bad/yaml-trailing-ws.yaml:27: example 0 [trailing-whitespace] trailing whitespace
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-unclosed-comment.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-unclosed-comment.yaml.txt
new file mode 100644 (file)
index 0000000..9a30ee7
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-unclosed-comment.yaml:26: example 0 [unclosed-block-comment] unclosed /* block comment
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-unit-addr-prefix.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-unit-addr-prefix.yaml.txt
new file mode 100644 (file)
index 0000000..8dec6c1
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-unit-addr-prefix.yaml:26: example 0 [unit-address-format] unit address '0x1000' must not have a "0x" prefix
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-unit-addr.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-unit-addr.yaml.txt
new file mode 100644 (file)
index 0000000..b52f0ef
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-unit-addr.yaml:26: example 0 [unit-address-format] unit address '01000' has leading zeros
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-unused-label.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-unused-label.yaml.txt
new file mode 100644 (file)
index 0000000..4f00202
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-unused-label.yaml:26: example 0 [unused-labels] label 'dev' defined but never &-referenced
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-value-ws-multiline.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-value-ws-multiline.yaml.txt
new file mode 100644 (file)
index 0000000..3df55b1
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-value-ws-multiline.yaml:25: example 0 [value-whitespace] extra whitespace inside <...>
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-value-ws.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-value-ws.yaml.txt
new file mode 100644 (file)
index 0000000..cbb5f88
--- /dev/null
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-value-ws.yaml:28: example 0 [value-whitespace] extra whitespace inside <...>
diff --git a/scripts/dtc/dt-style-selftest/good/dts-cont-align.dts b/scripts/dtc/dt-style-selftest/good/dts-cont-align.dts
new file mode 100644 (file)
index 0000000..36fb4ee
--- /dev/null
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/*
+ * Test fixture: tab-indented .dts with a tab-and-space aligned
+ * multi-line property. Continuation lines mix tabs for indent and
+ * spaces for alignment by design; that must not be flagged.
+ */
+
+/dts-v1/;
+
+/ {
+       compatible = "example,test-board";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       interrupt-controller@10000 {
+               compatible = "example,intc";
+               reg = <0x10000 0x1000>;
+               interrupts = <1 2 3>,
+                            <4 5 6>,
+                            <7 8 9>;
+               pinmux = <
+                        0x01
+                        0x02
+                        >;
+       };
+};
diff --git a/scripts/dtc/dt-style-selftest/good/dts-tab.dts b/scripts/dtc/dt-style-selftest/good/dts-tab.dts
new file mode 100644 (file)
index 0000000..ab7b5d1
--- /dev/null
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/*
+ * Test fixture: a properly formatted .dts using one-tab indent.
+ */
+
+/dts-v1/;
+
+/ {
+       compatible = "example,test-board";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       bus@10000 {
+               compatible = "simple-bus";
+               reg = <0x10000 0x1000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               device@100 {
+                       compatible = "example,test";
+                       reg = <0x100 0x10>;
+               };
+
+               device@200 {
+                       compatible = "example,test";
+                       reg = <0x200 0x10>;
+               };
+       };
+};
diff --git a/scripts/dtc/dt-style-selftest/good/yaml-4space.yaml b/scripts/dtc/dt-style-selftest/good/yaml-4space.yaml
new file mode 100644 (file)
index 0000000..1502f80
--- /dev/null
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-good-4space.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture for dt-check-style
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-4space
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    bus@10000 {
+        compatible = "simple-bus";
+        reg = <0x10000 0x1000>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+
+        device@100 {
+            compatible = "example,test-4space";
+            reg = <0x100 0x10>;
+        };
+
+        device@200 {
+            compatible = "example,test-4space";
+            reg = <0x200 0x10>;
+        };
+    };
diff --git a/scripts/dtc/dt-style-selftest/good/yaml-tricky-parsing.yaml b/scripts/dtc/dt-style-selftest/good/yaml-tricky-parsing.yaml
new file mode 100644 (file)
index 0000000..a836d5f
--- /dev/null
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-good-tricky-parsing.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture exercising parser corner cases
+
+description: |
+  Covers patterns that previously broke the classifier:
+    - "/* ... */ code;" with code following the closing of a one-line
+      block comment must still parse the code.
+    - a label on a node whose name starts with a digit (1wire@10).
+    - a multi-line C preprocessor macro using backslash continuations
+      must not be parsed as DTS lines.
+    - a /* comment that opens and closes on the same code line must
+      not leave the parser in block-comment state.
+
+maintainers:
+  - Test User <test@example.com>
+
+properties:
+  compatible:
+    const: example,test-tricky-parsing
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #define MY_REG(a, b) \
+        ((a) << 16 |     \
+         (b) << 0)
+
+    one_wire: 1wire@10 {
+        compatible = "example,test-tricky-parsing";
+        reg = <MY_REG(0x10, 0)>;
+        /* inline-closed */ status = "okay";
+    };
+
+    other: device@20 {
+        compatible = "example,test-tricky-parsing";
+        reg = <0x20 0x10>;
+    };
+
+    &one_wire {
+        status = "okay";
+    };
+
+    &other {
+        status = "okay";
+    };
diff --git a/scripts/dtc/dt-style-selftest/run.sh b/scripts/dtc/dt-style-selftest/run.sh
new file mode 100755 (executable)
index 0000000..8117dd9
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Run dt-check-style against fixtures under good/ and bad/.
+# good/ files must produce no output and exit 0 in both modes.
+# bad/ files must produce the expected output (in expected/<name>.txt)
+# and exit 1.
+#
+# The mode used for a bad fixture is whichever produces a violation:
+# trailing-whitespace and tab fixtures use the default (relaxed),
+# the rest use --mode=strict. The expected output files name the
+# mode in their first line.
+
+set -u
+
+here=$(cd "$(dirname "$0")" && pwd)
+tool="$here/../dt-check-style"
+fail=0
+
+run() {
+    file=$1
+    mode=$2
+    "$tool" --mode="$mode" "$file" 2>&1
+}
+
+# good/ -- must exit 0 and produce no output in both modes
+for f in "$here"/good/*; do
+    [ -e "$f" ] || continue
+    for mode in relaxed strict; do
+        out=$(run "$f" "$mode")
+        rc=$?
+        if [ -n "$out" ] || [ "$rc" -ne 0 ]; then
+            echo "FAIL good/$mode: $(basename "$f") (exit $rc, want 0):"
+            echo "$out" | sed 's/^/  /'
+            fail=$((fail + 1))
+        fi
+    done
+done
+
+# bad/ -- must match expected/<name>.txt
+for f in "$here"/bad/*; do
+    [ -e "$f" ] || continue
+    name=$(basename "$f")
+    expected="$here/expected/$name.txt"
+    if [ ! -f "$expected" ]; then
+        echo "FAIL bad: missing $expected"
+        fail=$((fail + 1))
+        continue
+    fi
+    mode=$(head -1 "$expected" | sed 's/^# mode=//')
+    body=$(tail -n +2 "$expected")
+    out=$(run "$f" "$mode")
+    rc=$?
+    # Strip the directory prefix so expected files are portable.
+    out=$(printf '%s\n' "$out" | sed "s|$here/bad/|bad/|g")
+    if [ "$out" != "$body" ] || [ "$rc" -ne 1 ]; then
+        echo "FAIL bad/$mode: $name (exit $rc, want 1):"
+        bf=$(mktemp)
+        printf '%s\n' "$body" > "$bf"
+        printf '%s\n' "$out" | diff -u "$bf" - | sed 's/^/  /'
+        rm -f "$bf"
+        fail=$((fail + 1))
+    fi
+done
+
+if [ "$fail" -eq 0 ]; then
+    echo "PASS"
+    exit 0
+fi
+echo "FAILED ($fail)"
+exit 1