multirunner.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. # -*- coding: utf-8 -*-
  2. """Testing framework module for running tests in Python unittest fashion
  3. Copyright (C) 2014 by the GRASS Development Team
  4. This program is free software under the GNU General Public
  5. License (>=v2). Read the file COPYING that comes with GRASS GIS
  6. for details.
  7. :authors: Vaclav Petras
  8. """
  9. from __future__ import print_function
  10. import sys
  11. import os
  12. import argparse
  13. import subprocess
  14. import locale
  15. try:
  16. from itertools import izip as zip
  17. except ImportError: # will be 3.x series
  18. pass
  19. if sys.version_info.major >= 3:
  20. unicode = str
  21. def _get_encoding():
  22. encoding = locale.getdefaultlocale()[1]
  23. if not encoding:
  24. encoding = "UTF-8"
  25. return encoding
  26. def decode(bytes_, encoding=None):
  27. if isinstance(bytes_, bytes):
  28. return bytes_.decode(_get_encoding())
  29. else:
  30. return bytes_
  31. def encode(string, encoding=None):
  32. if isinstance(string, unicode):
  33. return string.encode(_get_encoding())
  34. else:
  35. return string
  36. def text_to_string(text):
  37. """Convert text to str. Useful when passing text into environments,
  38. in Python 2 it needs to be bytes on Windows, in Python 3 in needs unicode.
  39. """
  40. if sys.version[0] == "2":
  41. # Python 2
  42. return encode(text)
  43. else:
  44. # Python 3
  45. return decode(text)
  46. def main():
  47. parser = argparse.ArgumentParser(description="Run tests with new")
  48. parser.add_argument(
  49. "--location",
  50. "-l",
  51. required=True,
  52. action="append",
  53. dest="locations",
  54. metavar="LOCATION",
  55. help="Directories with reports",
  56. )
  57. parser.add_argument(
  58. "--location-type",
  59. "-t",
  60. action="append",
  61. dest="location_types",
  62. default=[],
  63. metavar="TYPE",
  64. help="Add repeated values to a list",
  65. )
  66. parser.add_argument(
  67. "--grassbin",
  68. required=True,
  69. help="Use file timestamp instead of date in test summary",
  70. )
  71. # TODO: rename since every src can be used?
  72. parser.add_argument(
  73. "--grasssrc", required=True, help="GRASS GIS source code (to take tests from)"
  74. )
  75. parser.add_argument(
  76. "--grassdata", required=True, help="GRASS GIS data base (GISDBASE)"
  77. )
  78. parser.add_argument(
  79. "--create-main-report",
  80. help="Create also main report for all tests",
  81. action="store_true",
  82. default=False,
  83. dest="main_report",
  84. )
  85. args = parser.parse_args()
  86. gisdb = args.grassdata
  87. locations = args.locations
  88. locations_types = args.location_types
  89. # TODO: if locations empty or just one we can suppose the same all the time
  90. if len(locations) != len(locations_types):
  91. print(
  92. "ERROR: Number of locations and their tags must be the same",
  93. file=sys.stderr,
  94. )
  95. return 1
  96. main_report = args.main_report
  97. grasssrc = args.grasssrc # TODO: can be guessed from dist
  98. # TODO: create directory according to date and revision and create reports there
  99. # some predefined variables, name of the GRASS launch script + location/mapset
  100. # grass7bin = 'C:\Program Files (x86)\GRASS GIS 7.9.git\grass79dev.bat'
  101. grass7bin = args.grassbin # TODO: can be used if pressent
  102. ########### SOFTWARE
  103. # query GRASS 7 itself for its GISBASE
  104. # we assume that GRASS GIS' start script is available and in the PATH
  105. # the shell=True is here because of MS Windows? (code taken from wiki)
  106. startcmd = grass7bin + " --config path"
  107. p = subprocess.Popen(
  108. startcmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
  109. )
  110. out, err = p.communicate()
  111. if p.returncode != 0:
  112. print(
  113. "ERROR: Cannot find GRASS GIS 7 start script (%s):\n%s" % (startcmd, err),
  114. file=sys.stderr,
  115. )
  116. return 1
  117. gisbase = decode(out.strip())
  118. # set GISBASE environment variable
  119. os.environ["GISBASE"] = text_to_string(gisbase)
  120. # define GRASS Python environment
  121. grass_python_dir = os.path.join(gisbase, "etc", "python")
  122. sys.path.append(grass_python_dir)
  123. ########### DATA
  124. # define GRASS DATABASE
  125. # Set GISDBASE environment variable
  126. os.environ["GISDBASE"] = text_to_string(gisdb)
  127. # import GRASS Python package for initialization
  128. import grass.script.setup as gsetup
  129. # launch session
  130. # we need some location and mapset here
  131. # TODO: can init work without it or is there some demo location in dist?
  132. location = locations[0].split(":")[0]
  133. mapset = "PERMANENT"
  134. gsetup.init(gisbase, gisdb, location, mapset)
  135. reports = []
  136. for location, location_type in zip(locations, locations_types):
  137. # here it is quite a good place to parallelize
  138. # including also type to make it unique and preserve it for sure
  139. report = "report_for_" + location + "_" + location_type
  140. absreport = os.path.abspath(report)
  141. p = subprocess.Popen(
  142. [
  143. sys.executable,
  144. "-tt",
  145. "-m",
  146. "grass.gunittest.main",
  147. "--grassdata",
  148. gisdb,
  149. "--location",
  150. location,
  151. "--location-type",
  152. location_type,
  153. "--output",
  154. absreport,
  155. ],
  156. cwd=grasssrc,
  157. )
  158. returncode = p.wait()
  159. reports.append(report)
  160. if main_report:
  161. # TODO: solve the path to source code (work now only for grass source code)
  162. arguments = [
  163. sys.executable,
  164. grasssrc + "/python/grass/gunittest/" + "multireport.py",
  165. "--timestapms",
  166. ]
  167. arguments.extend(reports)
  168. p = subprocess.Popen(arguments)
  169. returncode = p.wait()
  170. if returncode != 0:
  171. print("ERROR: Creation of main report failed.", file=sys.stderr)
  172. return 1
  173. return 0
  174. if __name__ == "__main__":
  175. sys.exit(main())