# Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Tests to see if every python process renames itself."""
import unittest
import os
import os.path
import isc.util.process
import re

class TestRename(unittest.TestCase):
    """Test scanning all python scripts if they rename themself."""
    def __scan(self, directory, script, fun):
        # Scan one script if it contains call to the renaming function
        filename = os.path.join(directory, script)
        with open(filename) as f:
            data = ''.join(f.readlines())
        prettyname = 'src' + filename[filename.rfind('../') + 2:]
        self.assertTrue(fun.search(data),
            "Didn't find a call to isc.util.process.rename in " + prettyname)

    def test_calls(self):
        """
        Test if every script renames itself.

        Scan all Makefile and look for scripts.
        Then scan them by looking at the source text
        (without actually running them)
        """

        # Scripts named in this list are not expected to be renamed and
        # should be excluded from the scan.
        EXCLUDED_SCRIPTS = ['isc-sysinfo']

        # Regexp to find all the *_SCRIPTS = something lines (except for
        # noinst_SCRIPTS, which are scripts for tests), including line
        # continuations (backslash and newline)
        excluded_lines = re.compile(r'^(noinst_SCRIPTS.*$)', re.MULTILINE)
        lines = re.compile(r'^\w+_SCRIPTS\s*=\s*((.|\\\n)*)$',
            re.MULTILINE)
        # Script name regular expression
        scripts = re.compile(r'((\w|[-.0-9])+)')
        # Line with the call
        fun = re.compile(r'^\s*isc\.util\.process\.rename\s*\(.*\)\s*(|#.*)$',
            re.MULTILINE)

        # Find all Makefile and extract names of scripts
        for (d, _, fs) in os.walk('@top_builddir@'):
            if 'Makefile' in fs:
                with open(os.path.join(d, "Makefile")) as f:
                    makefile = ''.join(f.readlines())
                for (var, _) in lines.findall(re.sub(excluded_lines, '',
                                                     makefile)):
                    for (script, _) in scripts.findall(var):
                        if script in EXCLUDED_SCRIPTS:
                            continue
                        self.__scan(d, script, fun)

if __name__ == "__main__":
    unittest.main()
