configtest.py (5476B)
1 #!/usr/bin/env python 2 # This Source Code Form is subject to the terms of the Mozilla Public 3 # License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 # You can obtain one at http://mozilla.org/MPL/2.0/. 5 """configtest.py 6 7 Verify the .json and .py files in the configs/ directory are well-formed. 8 Further tests to verify validity would be desirable. 9 10 This is also a good example script to look at to understand mozharness. 11 """ 12 13 import os 14 import pprint 15 import sys 16 17 try: 18 import simplejson as json 19 except ImportError: 20 import json 21 22 sys.path.insert(1, os.path.dirname(sys.path[0])) 23 24 from mozharness.base.script import BaseScript 25 26 27 # ConfigTest {{{1 28 class ConfigTest(BaseScript): 29 config_options = [ 30 [ 31 [ 32 "--test-file", 33 ], 34 { 35 "action": "extend", 36 "dest": "test_files", 37 "help": "Specify which config files to test", 38 }, 39 ] 40 ] 41 42 def __init__(self, require_config_file=False): 43 self.config_files = [] 44 BaseScript.__init__( 45 self, 46 config_options=self.config_options, 47 all_actions=[ 48 "list-config-files", 49 "test-json-configs", 50 "test-python-configs", 51 "summary", 52 ], 53 default_actions=[ 54 "test-json-configs", 55 "test-python-configs", 56 "summary", 57 ], 58 require_config_file=require_config_file, 59 ) 60 61 def query_config_files(self): 62 """This query method, much like others, caches its runtime 63 settings in self.VAR so we don't have to figure out config_files 64 multiple times. 65 """ 66 if self.config_files: 67 return self.config_files 68 c = self.config 69 if "test_files" in c: 70 self.config_files = c["test_files"] 71 return self.config_files 72 self.debug( 73 "No --test-file(s) specified; defaulting to crawling the configs/ directory." 74 ) 75 config_files = [] 76 for root, dirs, files in os.walk(os.path.join(sys.path[0], "..", "configs")): 77 for name in files: 78 # Hardcode =P 79 if name.endswith(".json") or name.endswith(".py"): 80 if not name.startswith("test_malformed"): 81 config_files.append(os.path.join(root, name)) 82 self.config_files = config_files 83 return self.config_files 84 85 def list_config_files(self): 86 """Non-default action that is mainly here to demonstrate how 87 non-default actions work in a mozharness script. 88 """ 89 config_files = self.query_config_files() 90 for config_file in config_files: 91 self.info(config_file) 92 93 def test_json_configs(self): 94 """Currently only "is this well-formed json?" """ 95 config_files = self.query_config_files() 96 filecount = [0, 0] 97 for config_file in config_files: 98 if config_file.endswith(".json"): 99 filecount[0] += 1 100 self.info("Testing %s." % config_file) 101 contents = self.read_from_file(config_file, verbose=False) 102 try: 103 json.loads(contents) 104 except ValueError: 105 self.add_summary("%s is invalid json." % config_file, level="error") 106 self.error(pprint.pformat(sys.exc_info()[1])) 107 else: 108 self.info("Good.") 109 filecount[1] += 1 110 if filecount[0]: 111 self.add_summary( 112 "%d of %d json config files were good." % (filecount[1], filecount[0]) 113 ) 114 else: 115 self.add_summary("No json config files to test.") 116 117 def test_python_configs(self): 118 """Currently only "will this give me a config dictionary?" """ 119 config_files = self.query_config_files() 120 filecount = [0, 0] 121 for config_file in config_files: 122 if config_file.endswith(".py"): 123 filecount[0] += 1 124 self.info("Testing %s." % config_file) 125 global_dict = {} 126 local_dict = {} 127 try: 128 with open(config_file) as f: 129 exec(f.read(), global_dict, local_dict) 130 except Exception: 131 self.add_summary( 132 "%s is invalid python." % config_file, level="error" 133 ) 134 self.error(pprint.pformat(sys.exc_info()[1])) 135 else: 136 if "config" in local_dict and isinstance( 137 local_dict["config"], dict 138 ): 139 self.info("Good.") 140 filecount[1] += 1 141 else: 142 self.add_summary( 143 "%s is valid python, " 144 "but doesn't create a config dictionary." % config_file, 145 level="error", 146 ) 147 if filecount[0]: 148 self.add_summary( 149 "%d of %d python config files were good." % (filecount[1], filecount[0]) 150 ) 151 else: 152 self.add_summary("No python config files to test.") 153 154 155 # __main__ {{{1 156 if __name__ == "__main__": 157 config_test = ConfigTest() 158 config_test.run_and_exit()