]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
pytest:sddl: helpers to exchange SDDL strings with Windows testprogram
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Sat, 15 Apr 2023 08:29:53 +0000 (20:29 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 28 Apr 2023 02:15:36 +0000 (02:15 +0000)
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/tests/sddl.py

index 63883334755751cafd9734940b3441e3031c1cef..3bdc21383a221000ef33625c4ca0186cc3566f3f 100644 (file)
@@ -62,6 +62,94 @@ class SddlDecodeEncodeBase(TestCase):
         with self.assertRaises(ValueError):
             security.descriptor.from_sddl(s, self.domain_sid)
 
+    def _test_write_test_strings(self):
+        """The file libcli/security/tests/windows/windows-sddl-tests.c, if
+        compiled on Windows under Cygwin or MSYS64, can run SDDL
+        parsing tests using the Windows API. This allows us to run the
+        same tests here and on Windows, to ensure we get the same
+        results.
+
+        That test program can read examples in a bespoke text format,
+        in which each line looks like:
+
+           original sddl -> returned sddl
+
+        That is, the separator consists of the 4 bytes " -> ".
+        Multi-line examples are not possible.
+
+        If you rename this method to start with 'test_' and run these
+        tests, the examples here will be written in this format in
+        files in /tmp. If you then copy them to Windows and run them
+        in your POSIX-y shell with
+
+          windows-sddl-tests -i path/to/*.txt
+
+        the results on Windows will be shown.
+        """
+        if getattr(self, 'name', None) is None:
+            print(f"not reading changes in {c_RED(self)} with no name "
+                  "(it is probably the base class)")
+            return
+
+        name = f"/tmp/{self.name}.txt"
+        with open(name, 'w') as f:
+            for p in self.strings:
+                if isinstance(p, str):
+                    p = (p, p)
+                print(f"{p[0]} -> {p[1]}", file=f)
+
+    def _test_00_read_test_strings(self):
+        """This is a complementary non-test to _test_write_test_strings, which
+        writes these tests in a format usable on Windows. In this
+        case, if the method is enabled as a test by removing the
+        leading '_', examples will be read. Unlike the write function,
+        this reads from 'libcli/security/tests/windows/' in the source
+        tree, and will replace the examples here with the ones there.
+        Along the way it allerts you to the changes.
+
+        If run, this test should run first, hence the 00 in its name.
+        """
+        if getattr(self, 'name', None) is None:
+            print(f"not reading changes in {c_RED(self)} with no name "
+                  "(it is probably the base class)")
+            return
+
+        from pathlib import Path
+        p = Path(__file__).parent
+        while not (p / 'libcli').is_dir():
+            q = p.parent
+            self.assertNotEqual(p, q)
+            p = q
+
+        filename = p / f"libcli/security/tests/windows/{self.name}.txt"
+
+        old_pairs = set()
+        for s in self.strings:
+            if isinstance(s, str):
+                s = (s, s)
+            old_pairs.add(s)
+
+        new_pairs = set()
+        with open(filename) as f:
+            for line in f:
+                o, _, c = line.rstrip().partition(' -> ')
+                new_pairs.add((o, c))
+
+        if old_pairs == new_pairs:
+            print(f"no change in {c_GREEN(self.name)}")
+            # nothing to do
+            return
+
+        print(f"change in {c_RED(self.name)}")
+        print("added:")
+        for x in sorted(new_pairs - old_pairs):
+            print(x)
+        print("removed:")
+        for x in sorted(old_pairs - new_pairs):
+            print(x)
+
+        self.strings[:] = sorted(new_pairs)
+        self.fail("test cases out of sync")
 
 @DynamicTestCase
 class SddlNonCanonical(SddlDecodeEncodeBase):