#!/usr/bin/env python3
# Check against current udev rules for any redundant hwdb rules.

import os
import sys
import glob
import subprocess
import tempfile
import shutil
import unittest


def get_modalias_list(root=''):
    modalias_list = []

    for path in glob.glob('{}/**/*.hwdb'.format(root), recursive=True):
        with open(path, 'r') as f:
            lines = f.readlines()

        for line in lines:
            line = str(line).rstrip()
            if line.startswith(' ') or line.startswith('#'):
                continue

            if line in ['\n', '\r\n']:
                continue

            if not line in modalias_list:
                modalias_list.append(line)

    return modalias_list

def get_hwdb_properties(modalias_list, root=None):
    properties = {}

    cmd = ['systemd-hwdb', 'query']
    if root is not None:
        cmd += ['--root', root]

    for modalias in modalias_list:
        output = subprocess.run(cmd + [modalias],
                       stdout=subprocess.PIPE).stdout.decode('utf-8')
        properties[modalias] = [line for line in output.splitlines() if line]

    return properties


class RedundancyCheckTest(unittest.TestCase):
    """ Check for hwdb rule redundancies. """

    def setUp(self):
        # Using the hwdb rules from this package, generate a hwdb.bin
        # in a temporary directory
        self.tmpdir = tempfile.mkdtemp(prefix='systemd-hwe-hwdb-test')

        src = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                           '../hwdb.d')
        dst = os.path.join(self.tmpdir, 'etc/udev/hwdb.d')
        shutil.copytree(src, dst)
        p = subprocess.run(['systemd-hwdb', 'update', '--root', self.tmpdir],
                           stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        self.assertEqual(p.returncode, 0)
        self.assertEqual(p.stderr, b'', 'hwdb rules produced warnings')

    def tearDown(self):
        shutil.rmtree(self.tmpdir)

    def test_no_duplicates(self):
        modalias_list = get_modalias_list(root=self.tmpdir)
        existing_hwdb_props = get_hwdb_properties(modalias_list)
        new_hwdb_props = get_hwdb_properties(modalias_list, root=self.tmpdir)

        duplicates = {}
        for modalias in modalias_list:
            intersection = list(set(existing_hwdb_props[modalias]) &
                                set(new_hwdb_props[modalias]))
            if intersection:
                duplicates[modalias] = intersection

        self.assertEqual(
            len(duplicates), 0,
            'Duplicate hwdb rules\n  ' +
            '\n  '.join([f'{k} : {v}' for k, v in duplicates.items()])
        )


if __name__ == '__main__':
    unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
                                                     verbosity=2))
