File: screw_users_test.py

package info (click to toggle)
cmake-format 0.6.13-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,436 kB
  • sloc: python: 16,990; makefile: 14
file content (221 lines) | stat: -rw-r--r-- 7,226 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
"""
Ensure that changes to cmake-format don't screw current users
"""

# -*- coding: utf-8 -*-
# pylint: disable=R1708
from __future__ import print_function
from __future__ import unicode_literals

import os
import re
import shutil
import sys
import subprocess
import tempfile
import unittest


def iter_filelist(rootdir, include_patterns, exclude_patterns):
  """
  Walk a directory tree and yield each file matching the include patterns
  but not matching the exclude patterns.
  """
  include_patterns = [re.compile(pattern) for pattern in include_patterns]
  exclude_patterns = [re.compile(pattern) for pattern in exclude_patterns]

  for cwd, dirnames, filenames in os.walk(rootdir):
    relpath_cwd = os.path.relpath(cwd, rootdir)
    if relpath_cwd == ".":
      relpath_cwd = ""

    exclude_cwd = any(pattern.match(relpath_cwd)
                      for pattern in exclude_patterns)
    if exclude_cwd:
      dirnames[:] = []
      continue

    dirnames[:] = sorted(dirnames)
    for filename in filenames:
      relpath_filename = os.path.join(relpath_cwd, filename)
      include_filename = (
          any(pattern.match(filename) for pattern in include_patterns) or
          any(pattern.match(relpath_filename) for pattern in include_patterns)
      )
      exclude_filename = (
          any(pattern.match(filename) for pattern in exclude_patterns) or
          any(pattern.match(relpath_filename) for pattern in exclude_patterns)
      )

      if include_filename and not exclude_filename:
        yield relpath_filename


class WrapTestWithRunFun(object):
  """
  Given a instance of a bound test-method from a TestCase, wrap that with
  a callable that first calls the method, and then calls `
  test.assertCanFormat()`. Which is really just an opaque way of
  automatically calling `rest.assertCanFormat()` at the end of each test
  method.
  """

  def __init__(self, test_object, bound_method):
    self.test_object = test_object
    self.bound_method = bound_method

  def __call__(self):
    self.bound_method()
    self.test_object.assertCanFormat()


class DontScrewUsers(unittest.TestCase):
  """
  Given a bunch of public repositories, check that cmake-format runs on
  all of them.
  """

  TMPDIR = None

  def __init__(self, *args, **kwargs):
    super(DontScrewUsers, self).__init__(*args, **kwargs)
    self.repository = None
    self.clonedir = None
    self.configpath = None
    self.include_patterns = [r".*\.cmake$", "CMakeLists.txt"]
    self.exclude_patterns = [r"\.git", r"\.build", r".*third_party.*"]
    self.last_known_good = None

    # NOTE(josh): hacky introspective way of automatically calling
    # assertExpectations() at the end of every test_XXX() function
    for name in dir(self):
      if not name.startswith("test_"):
        continue
      value = getattr(self, name)
      if callable(value):
        setattr(self, name, WrapTestWithRunFun(self, value))

  @classmethod
  def setUpClass(cls):
    if os.environ.get("CMFSCREWTEST_REUSE"):
      cls.TMPDIR = os.path.join(tempfile.gettempdir(), "cmf-unscrew")
      if not os.path.exists(cls.TMPDIR):
        os.makedirs(cls.TMPDIR)
    else:
      cls.TMPDIR = tempfile.mkdtemp(prefix="cmf-unscrew_")

  @classmethod
  def tearDownClass(cls):
    if not os.environ.get("CMFSCREWTEST_REUSE"):
      shutil.rmtree(cls.TMPDIR)

  def assertCanFormat(self):
    if self.clonedir is None:
      self.clonedir = self.repository.rsplit("/", 1)[1]
    clonepath = os.path.join(self.TMPDIR, self.clonedir)
    if not os.path.exists(os.path.join(clonepath, ".git")):
      subprocess.check_call(["git", "clone", "--depth", "1",
                             self.repository, self.clonedir], cwd=self.TMPDIR)

    env = os.environ.copy()
    thisdir = os.path.dirname(__file__)
    base_override = os.getenv("PYBUILD_TEST_BASE_OVERRIDE")
    if base_override is not None:
      thisdir = thisdir.replace(os.environ['PWD'], base_override)
    thisdir = os.path.dirname(thisdir)
    repodir = os.path.dirname(thisdir)
    env["PYTHONPATH"] = os.path.realpath(repodir)

    fmtcmd = [sys.executable, "-Bm", "cmakelang"]
    if self.configpath:
      fmtcmd += ["--config", self.configpath]
    fmtcmd += ["-i"]

    pathiter = iter_filelist(
        clonepath,
        self.include_patterns,
        self.exclude_patterns)

    nsuccess = 0
    failed_files = []
    for relpath in pathiter:
      result = subprocess.call(fmtcmd + [relpath], cwd=clonepath, env=env)
      if result == 0:
        nsuccess += 1
      else:
        failed_files.append(relpath)

    print("{}: Successfully ran on {} files".format(self.clonedir, nsuccess))
    if failed_files:
      print("  " + "\n  ".join(failed_files))

    self.assertFalse(failed_files)

  def test_thisrepo(self):
    thisdir = os.path.realpath(os.path.dirname(__file__))
    self.repository = os.sep.join(thisdir.split(os.sep)[:-2])
    self.configpath = ".cmake-format.py"
    self.last_known_good = "efb0d6256fcbc4a3cfad9f5ebdaa34172d230ea2"
    self.exclude_patterns += [
        r"test_latin.*\.cmake"
    ]

  def test_elektra(self):
    self.repository = "https://github.com/sanssecours/elektra"
    self.configpath = ".cmake-format.yaml"
    self.last_known_good = "483752d182bc12546a2902989d63ea1cfcaae861"

  def test_pcl(self):
    self.repository = "https://github.com/PointCloudLibrary/pcl"
    self.last_known_good = "711b12144e2cb250fcbccf56b0c523a1d279297a"

  def test_arrow(self):
    self.repository = "https://github.com/apache/arrow"
    self.configpath = "cmake-format.py"
    self.last_known_good = "e32c0b3279df76d68c93724f476dfcf0c1c44fa5"
    self.exclude_patterns += [
        r".*\.h\.cmake",
        r".*Dockerfile\.cmake",
    ]

  def test_aom(self):
    self.repository = "https://aomedia.googlesource.com/aom"
    self.configpath = ".cmake-format.py"
    self.last_known_good = "81259cf147effcd93fc50fca768ade453fce0bfe"

  def test_vulkan_tools(self):
    self.repository = "https://github.com/KhronosGroup/Vulkan-Tools"
    self.configpath = ".cmake-format.py"
    self.last_known_good = "4c6673b2973a7434716a9325a0b22861beed9244"

  def test_vulkan_validation_layers(self):
    self.repository = "https://github.com/KhronosGroup/Vulkan-ValidationLayers"
    self.configpath = "scripts/cmake-format.py"
    self.last_known_good = "adbfa85caafb5f240474dd2ae2414f0b78026a3f"
    self.exclude_patterns += [
        ".*build-android/cmake/layerlib/CMakeLists.txt"
    ]

  def test_vulkan_validation_loader(self):
    self.repository = "https://github.com/KhronosGroup/Vulkan-Loader"
    self.configpath = ".cmake-format.py"

  def test_pdfslicer(self):
    self.repository = "https://github.com/junrrein/pdfslicer"
    self.configpath = ".cmake-format.py"

  def test_opencensus(self):
    self.repository = "https://github.com/census-instrumentation/opencensus-cpp"
    self.configpath = ".cmake-format.py"

  def test_openbmc_ipmbbridge(self):
    self.repository = "https://github.com/openbmc/ipmbbridge"
    self.configpath = "cmake-format.json"

  def test_openbmc_dbus_sensors(self):
    self.repository = "https://github.com/openbmc/dbus-sensors"
    self.configpath = "cmake-format.json"


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