github.com/canonical/ubuntu-image@v0.0.0-20240430122802-2202fe98b290/tests/lib/external/snapd-testing-tools/utils/check-test-format (about)

     1  #!/usr/bin/python3
     2  
     3  """
     4  This tool is used to verify a correct format of spread tests
     5  The input is a directory which is scanned recursively and all
     6  the task.yaml files are check
     7  """
     8  
     9  import argparse
    10  import glob
    11  import os
    12  import sys
    13  import yaml
    14  import yamlordereddictloader
    15  
    16  SUPPORTED_KEYS = [
    17      "summary",
    18      "details",
    19      "backends",
    20      "systems",
    21      "manual",
    22      "priority",
    23      "warn-timeout",
    24      "kill-timeout",
    25      "environment",
    26      "prepare",
    27      "restore",
    28      "debug",
    29      "execute",
    30  ]
    31  MANDATORY_KEYS = ["summary", "details", "execute"]
    32  
    33  
    34  def check_mandatory_keys(task_keys):
    35      findings = []
    36      for key in MANDATORY_KEYS:
    37          if key not in task_keys:
    38              findings.append("Key '{}' is mandatory".format(key))
    39  
    40      return findings
    41  
    42  
    43  def check_keys_order(task_keys):
    44      last_index = -1
    45      last_key = ""
    46      findings = []
    47  
    48      for curr_key in task_keys:
    49          try:
    50              curr_index = SUPPORTED_KEYS.index(curr_key)
    51              if curr_index <= last_index:
    52                  findings.append(
    53                      "Keys '{}' and '{}' do not follow the desired order: {}".format(
    54                          last_key, curr_key, SUPPORTED_KEYS
    55                      )
    56                  )
    57  
    58              last_index = curr_index
    59              last_key = curr_key
    60  
    61          except ValueError:
    62              findings.append(
    63                  "key '{}' is not among the supported keys: {}".format(
    64                      curr_key, SUPPORTED_KEYS
    65                  )
    66              )
    67  
    68      return findings
    69  
    70  
    71  def check_task_format(filepath):
    72      if not os.path.isfile(filepath):
    73          print("Format checks failed for task {}".format(filepath))
    74          print(" - The path is not a file")
    75          return False
    76  
    77      filemap = dict()
    78      try:
    79          with open(filepath, "r") as task:
    80              filemap = yaml.load(task, Loader=yamlordereddictloader.Loader)
    81      except yaml.scanner.ScannerError:
    82          print("Invalid task format, checks failed for task {}".format(filepath))
    83          return False
    84  
    85      findings = check_keys_order(filemap.keys())
    86      findings.extend(check_mandatory_keys(filemap.keys()))
    87      if findings:
    88          print("Format checks failed for task {}".format(filepath))
    89          for finding in findings:
    90              print(" - " + finding)
    91          return False
    92  
    93      return True
    94  
    95  def check_dir(directory):
    96      if not os.path.isdir(directory):
    97          print("Format checks failed for directory {}".format(directory))
    98          print(" - The path is not a directory")
    99          return False
   100  
   101      status = True
   102      for file in glob.glob(os.path.join(directory, "**/task.yaml"), recursive=True):
   103          if not check_task_format(file):
   104              status = False
   105  
   106      return status
   107  
   108  def check_tests(tests):
   109      status = True
   110      for test in tests:
   111          if not os.path.isfile(test):
   112              print("Format checks failed for test {}".format(test))
   113              print(" - The path is not a file")
   114              status = False
   115              continue
   116  
   117          if not check_task_format(test):
   118              status = False
   119  
   120      return status
   121  
   122  def _make_parser():
   123      parser = argparse.ArgumentParser()
   124      parser.add_argument(
   125          "--dir", help="path to the directory to check recursively"
   126      )
   127      parser.add_argument(
   128          "--tests", help="list of tests path to check", nargs='+'
   129      )
   130      return parser
   131  
   132  
   133  def main():
   134      parser = _make_parser()
   135      args = parser.parse_args()
   136  
   137      status = 0
   138      if args.tests:
   139          if not check_tests(args.tests):
   140              status = 1
   141  
   142      if args.dir:
   143          if not check_dir(args.dir):
   144              status = 1
   145  
   146      sys.exit(status)
   147  
   148  if __name__ == "__main__":
   149      main()