1e81fdcb135d0325e3bc22fae0583555d20aae280Brendan Jackman#    Copyright 2015-2017 ARM Limited
2aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino#
3aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# Licensed under the Apache License, Version 2.0 (the "License");
4aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# you may not use this file except in compliance with the License.
5aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# You may obtain a copy of the License at
6aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino#
7aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino#     http://www.apache.org/licenses/LICENSE-2.0
8aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino#
9aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# Unless required by applicable law or agreed to in writing, software
10aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# distributed under the License is distributed on an "AS IS" BASIS,
11aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# See the License for the specific language governing permissions and
13aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# limitations under the License.
14a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino#
15a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino
16aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino
17a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merinofrom datetime import date
182f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merinofrom glob import glob
19a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merinoimport os
20dea8e9d314e5b0f9213c5f3ecf87ef4369537082Javi Merinoimport re
21a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merinoimport unittest
22a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino
23a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino
24a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merinodef copyright_is_valid(fname):
25a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino    """Return True if fname has a valid copyright"""
26a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino    with open(fname) as fin:
27a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino        # Read the first 2K of the file.  If the copyright is not there, you
28a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino        # are probably doing something wrong
29a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino        lines = fin.readlines(2048)
30a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino
31dea8e9d314e5b0f9213c5f3ecf87ef4369537082Javi Merino    # Either the first or the second line must have a "Copyright:" line
32dea8e9d314e5b0f9213c5f3ecf87ef4369537082Javi Merino    first_line = re.compile(r"(#| \*)    Copyright")
3369b10c287d6fb303042c348ab61434b3f124bdf8Javi Merino    try:
3469b10c287d6fb303042c348ab61434b3f124bdf8Javi Merino        if not first_line.search(lines[0]):
3569b10c287d6fb303042c348ab61434b3f124bdf8Javi Merino            if first_line.search(lines[1]):
3669b10c287d6fb303042c348ab61434b3f124bdf8Javi Merino                # Drop the first line to align the copyright to lines[0]
3769b10c287d6fb303042c348ab61434b3f124bdf8Javi Merino                lines = lines[1:]
3869b10c287d6fb303042c348ab61434b3f124bdf8Javi Merino            else:
3969b10c287d6fb303042c348ab61434b3f124bdf8Javi Merino                return False
4069b10c287d6fb303042c348ab61434b3f124bdf8Javi Merino    except IndexError:
4169b10c287d6fb303042c348ab61434b3f124bdf8Javi Merino        return False
42a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino
43aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino    # The copyright mentions ARM Limited
44aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino    if "ARM Limited" not in lines[0]:
45a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino        return False
46a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino
47e43094c18c7c0ef13daae4b20044d1d9951ef9a7Kapileshwar Singh    apache_line = 6
48e43094c18c7c0ef13daae4b20044d1d9951ef9a7Kapileshwar Singh    if "Google Inc" in lines[1]:
49e43094c18c7c0ef13daae4b20044d1d9951ef9a7Kapileshwar Singh        apache_line += 1
50e43094c18c7c0ef13daae4b20044d1d9951ef9a7Kapileshwar Singh
51aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino    # The Copyright includes the current year
52a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino    current_year = date.today().year
53aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino    if str(current_year) not in lines[0]:
54a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino        return False
55a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino
56aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino    # It's the apache license
57e43094c18c7c0ef13daae4b20044d1d9951ef9a7Kapileshwar Singh    if "http://www.apache.org/licenses/LICENSE-2.0" not in lines[apache_line]:
58a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino        return False
59a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino
60a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino    return True
61a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino
62a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino
63a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merinoclass TestCopyRight(unittest.TestCase):
64a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino    def test_copyrights(self):
65a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino        """Check that all files have valid copyrights"""
66a55880f6f01e74a3f2ba6974e0643d0ebbeb68caJavi Merino
6784cbf3b8bd8861743cdd63339b746d3e7049e51dKapileshwar Singh        tests_dir = os.path.dirname(os.path.abspath(__file__))
6884cbf3b8bd8861743cdd63339b746d3e7049e51dKapileshwar Singh        base_dir = os.path.dirname(tests_dir)
692f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino        patterns_to_ignore = {}
7084cbf3b8bd8861743cdd63339b746d3e7049e51dKapileshwar Singh
7145010cb7c5d27d6e655fb3459527825afeba0013Javi Merino        for root, dirs, files in os.walk(base_dir):
722f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino            if ".gitignore" in files:
732f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino                fname = os.path.join(root, ".gitignore")
742f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino                with open(fname) as fin:
752f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino                    lines = fin.readlines()
762f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino
772f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino            patterns_to_ignore[root] = [l.strip() for l in lines]
782f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino
792f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino            files_to_ignore = []
802f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino            for directory, patterns in patterns_to_ignore.iteritems():
812f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino                if root.startswith(directory):
822f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino                    for pat in patterns:
832f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino                        pat = os.path.join(root, pat)
842f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino                        files_to_ignore.extend(glob(pat))
852f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino
862f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino            for dirname in dirs:
872f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino                full_dirname = os.path.join(root, dirname)
882f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino                if full_dirname in files_to_ignore:
892f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino                    dirs.remove(dirname)
902f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino
912f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino
9284cbf3b8bd8861743cdd63339b746d3e7049e51dKapileshwar Singh            for fname in files:
9384cbf3b8bd8861743cdd63339b746d3e7049e51dKapileshwar Singh                fname = os.path.join(root, fname)
942f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino                if fname in files_to_ignore:
952f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino                    continue
962f7ee66a8b872d17839a0821817a2498d87bc61eJavi Merino
9784cbf3b8bd8861743cdd63339b746d3e7049e51dKapileshwar Singh                extension = os.path.splitext(fname)[1]
9884cbf3b8bd8861743cdd63339b746d3e7049e51dKapileshwar Singh                if extension in [".py", ".js", ".css"]:
9984cbf3b8bd8861743cdd63339b746d3e7049e51dKapileshwar Singh                    if not copyright_is_valid(fname):
10084cbf3b8bd8861743cdd63339b746d3e7049e51dKapileshwar Singh                        print("Invalid copyright in {}".format(fname))
10184cbf3b8bd8861743cdd63339b746d3e7049e51dKapileshwar Singh                        self.fail()
10245010cb7c5d27d6e655fb3459527825afeba0013Javi Merino
10345010cb7c5d27d6e655fb3459527825afeba0013Javi Merino            if '.git' in dirs:
10445010cb7c5d27d6e655fb3459527825afeba0013Javi Merino                dirs.remove('.git')
105