test_get_developers.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. """Test cases for utils/get-developers.
  2. It does not inherit from infra.basetest.BRTest and therefore does not generate
  3. a logfile. Only when the tests fail there will be output to the console.
  4. The file syntax is already tested by the GitLab-CI job check-DEVELOPERS.
  5. """
  6. import os
  7. import subprocess
  8. import tempfile
  9. import unittest
  10. import infra
  11. def call_script(args, env, cwd, stdin_data=None):
  12. """Call a script and return stdout and stderr as lists and the exit code."""
  13. if stdin_data is None:
  14. # We need stdin to be a tty, not just a pipe or whatever
  15. m_tty, s_tty = os.openpty()
  16. com_opts = dict()
  17. else:
  18. s_tty = subprocess.PIPE
  19. com_opts = dict([("input", stdin_data)])
  20. proc = subprocess.Popen(args, cwd=cwd,
  21. stdin=s_tty,
  22. stdout=subprocess.PIPE,
  23. stderr=subprocess.PIPE, env=env,
  24. universal_newlines=True)
  25. out, err = proc.communicate(**com_opts)
  26. if stdin_data is None:
  27. os.close(s_tty)
  28. os.close(m_tty)
  29. return out.splitlines(), err.splitlines(), proc.returncode
  30. def call_get_developers(cmd, args, env, cwd, developers_content, stdin_data=None):
  31. """Call get-developers overrinding the default DEVELOPERS file."""
  32. with tempfile.NamedTemporaryFile(buffering=0) as developers_file:
  33. developers_file.write(developers_content)
  34. return call_script([cmd, "-d", developers_file.name] + args, env, cwd, stdin_data)
  35. class TestGetDevelopers(unittest.TestCase):
  36. """Test the various ways the script can be called in a simple top to bottom sequence."""
  37. WITH_EMPTY_PATH = {}
  38. WITH_UTILS_IN_PATH = {"PATH": infra.basepath("utils") + ":" + os.environ["PATH"]}
  39. def test_run(self):
  40. topdir = infra.basepath()
  41. # no args, with syntax error in the file
  42. developers = b'text3\n'
  43. out, err, rc = call_get_developers("./utils/get-developers", [], self.WITH_EMPTY_PATH, topdir, developers)
  44. self.assertIn("No action specified", "\n".join(err))
  45. self.assertEqual(rc, 2)
  46. self.assertEqual(len(out), 0)
  47. # -v generating error, called from the main dir
  48. developers = b'text1\n'
  49. out, err, rc = call_get_developers("./utils/get-developers", ["-v"], self.WITH_EMPTY_PATH, topdir, developers)
  50. self.assertIn("Syntax error in DEVELOPERS file, line 1: 'text1'", err)
  51. self.assertEqual(rc, 1)
  52. self.assertEqual(len(out), 0)
  53. self.assertEqual(len(err), 1)
  54. # -v generating error, called from path
  55. developers = b'text2\n'
  56. out, err, rc = call_get_developers("get-developers", ["-v"], self.WITH_UTILS_IN_PATH, topdir, developers)
  57. self.assertIn("Syntax error in DEVELOPERS file, line 1: 'text2'", err)
  58. self.assertEqual(rc, 1)
  59. self.assertEqual(len(out), 0)
  60. self.assertEqual(len(err), 1)
  61. # -v generating error for file entry with no developer entry
  62. developers = b'# comment\n' \
  63. b'\n' \
  64. b'F:\tutils/get-developers\n' \
  65. b'\n' \
  66. b'N:\tAuthor2 <email>\n' \
  67. b'F:\tutils/get-developers\n'
  68. out, err, rc = call_get_developers("get-developers", ["-v"], self.WITH_UTILS_IN_PATH, topdir, developers)
  69. self.assertIn("Syntax error in DEVELOPERS file, line 4", err)
  70. self.assertEqual(rc, 1)
  71. self.assertEqual(len(out), 0)
  72. self.assertEqual(len(err), 1)
  73. # -v generating error for developer entry with no file entries, stopping on first error
  74. developers = b'# comment\n' \
  75. b'# comment\n' \
  76. b'\n' \
  77. b'N:\tAuthor1 <email>\n' \
  78. b'N:\tAuthor2 <email>\n' \
  79. b'N:\tAuthor3 <email>\n' \
  80. b'F:\tutils/get-developers\n'
  81. out, err, rc = call_get_developers("get-developers", ["-v"], self.WITH_UTILS_IN_PATH, topdir, developers)
  82. self.assertIn("Syntax error in DEVELOPERS file, line 4", err)
  83. self.assertEqual(rc, 1)
  84. self.assertEqual(len(out), 0)
  85. self.assertEqual(len(err), 1)
  86. # -v not generating error for developer entry with empty list of file entries
  87. developers = b'# comment\n' \
  88. b'# comment\n' \
  89. b'\n' \
  90. b'N:\tAuthor1 <email>\n' \
  91. b'\n' \
  92. b'N:\tAuthor2 <email>\n' \
  93. b'\n' \
  94. b'N:\tAuthor3 <email>\n' \
  95. b'F:\tutils/get-developers\n'
  96. out, err, rc = call_get_developers("get-developers", ["-v"], self.WITH_UTILS_IN_PATH, topdir, developers)
  97. self.assertEqual(rc, 0)
  98. self.assertEqual(len(out), 0)
  99. self.assertEqual(len(err), 0)
  100. # -v generating warning for old file entry
  101. developers = b'N:\tAuthor <email>\n' \
  102. b'F:\tpath/that/does/not/exists/1\n' \
  103. b'F:\tpath/that/does/not/exists/2\n'
  104. out, err, rc = call_get_developers("get-developers", ["-v"], self.WITH_UTILS_IN_PATH, topdir, developers)
  105. self.assertIn("WARNING: 'path/that/does/not/exists/1' doesn't match any file, line 2", err)
  106. self.assertIn("WARNING: 'path/that/does/not/exists/2' doesn't match any file, line 3", err)
  107. self.assertEqual(rc, 0)
  108. self.assertEqual(len(out), 0)
  109. self.assertEqual(len(err), 2)
  110. # -c generating warning and printing lots of files with no developer
  111. developers = b'N:\tAuthor <email>\n' \
  112. b'F:\tpath/that/does/not/exists/1\n' \
  113. b'F:\tpath/that/does/not/exists/2\n'
  114. out, err, rc = call_get_developers("./utils/get-developers", ["-c"], self.WITH_EMPTY_PATH, topdir, developers)
  115. self.assertIn("WARNING: 'path/that/does/not/exists/1' doesn't match any file, line 2", err)
  116. self.assertIn("WARNING: 'path/that/does/not/exists/2' doesn't match any file, line 3", err)
  117. self.assertEqual(rc, 0)
  118. self.assertGreater(len(out), 1000)
  119. self.assertEqual(len(err), 2)
  120. # -c printing lots of files with no developer
  121. developers = b'# comment\n' \
  122. b'\n' \
  123. b'N:\tAuthor <email>\n' \
  124. b'F:\tutils/get-developers\n'
  125. out, err, rc = call_get_developers("./utils/get-developers", ["-c"], self.WITH_EMPTY_PATH, topdir, developers)
  126. self.assertEqual(rc, 0)
  127. self.assertGreater(len(out), 1000)
  128. self.assertEqual(len(err), 0)
  129. # -p lists more than one developer
  130. developers = b'N:\tdev1\n' \
  131. b'F:\ttoolchain/\n' \
  132. b'\n' \
  133. b'N:\tdev2\n' \
  134. b'F:\ttoolchain/\n'
  135. out, err, rc = call_get_developers("./utils/get-developers", ["-p", "toolchain"], self.WITH_EMPTY_PATH, topdir, developers)
  136. self.assertIn("dev1", out)
  137. self.assertIn("dev2", out)
  138. self.assertEqual(rc, 0)
  139. self.assertEqual(len(err), 0)
  140. # no args, with syntax error in the file
  141. developers = b'text3\n'
  142. out, err, rc = call_get_developers("./utils/get-developers", [], self.WITH_EMPTY_PATH, topdir, developers)
  143. self.assertIn("No action specified", "\n".join(err))
  144. self.assertEqual(rc, 2)
  145. self.assertEqual(len(out), 0)
  146. # patchfile from topdir and from elsewhere
  147. abs_path = infra.filepath("tests/utils/test_get_developers/")
  148. rel_file = "0001-package-binutils-change-.mk.patch"
  149. abs_file = os.path.join(abs_path, rel_file)
  150. developers = b'N:\tdev1\n' \
  151. b'F:\tpackage/binutils/\n'
  152. out, err, rc = call_get_developers("./utils/get-developers", [abs_file], self.WITH_EMPTY_PATH, topdir, developers)
  153. self.assertIn('git send-email --to buildroot@buildroot.org --cc "dev1"', out)
  154. self.assertEqual(rc, 0)
  155. self.assertEqual(len(err), 0)
  156. out, err, rc = call_get_developers("get-developers", [rel_file], self.WITH_UTILS_IN_PATH, abs_path, developers)
  157. self.assertIn('git send-email --to buildroot@buildroot.org --cc "dev1"', out)
  158. self.assertEqual(rc, 0)
  159. self.assertEqual(len(err), 0)
  160. with open(abs_file, "r") as fd:
  161. patch_data = fd.read()
  162. out, err, rc = call_get_developers("./utils/get-developers", [], self.WITH_EMPTY_PATH, topdir, developers, patch_data)
  163. self.assertIn('git send-email --to buildroot@buildroot.org --cc "dev1"', out)
  164. self.assertEqual(rc, 0)
  165. self.assertEqual(len(err), 0)