k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/metrics/bigquery_test.py (about) 1 #!/usr/bin/env python3 2 3 # Copyright 2017 The Kubernetes Authors. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 """Tests for bigquery.py""" 18 19 import argparse 20 import os 21 import re 22 import shutil 23 import sys 24 import tempfile 25 import unittest 26 27 import ruamel.yaml as yaml 28 29 import bigquery 30 31 class TestBigquery(unittest.TestCase): 32 """Tests the bigquery scenario.""" 33 34 def test_configs(self): 35 """All yaml files in metrics are valid.""" 36 config_metrics = set() 37 for path in bigquery.all_configs(search='**'): 38 name = os.path.basename(path) 39 if name in ['BUILD', 'BUILD.bazel', 'README.md']: 40 continue 41 if not path.endswith('.yaml'): 42 self.fail('Only .yaml files allowed: %s' % path) 43 44 with open(path) as config_file: 45 try: 46 config = yaml.safe_load(config_file) 47 except yaml.YAMLError: 48 self.fail(path) 49 self.assertIn('metric', config) 50 self.assertIn('query', config) 51 self.assertIn('jqfilter', config) 52 self.assertIn('description', config) 53 metric = config['metric'].strip() 54 bigquery.validate_metric_name(metric) 55 config_metrics.add(metric) 56 configs = bigquery.all_configs() 57 self.assertTrue(all(p.endswith('.yaml') for p in configs), configs) 58 59 # Check that the '**' search finds the same number of yaml 60 # files as the default search. 61 self.assertEqual(len(configs), len(config_metrics), "verify the `metric` feild is unique") 62 63 # Check that config files correlate with metrics listed in 64 # test-infra/metrics/README.md. 65 with open(os.path.join(os.path.dirname(__file__), 'README.md')) as readme_file: 66 readme = readme_file.read() 67 68 readme_metrics = set(re.findall( 69 r'\(http://storage\.googleapis\.com/k8s-metrics/([\w-]+)-latest\.json\)', 70 readme, 71 )) 72 missing = config_metrics - readme_metrics 73 if missing: 74 self.fail( 75 'test-infra/metrics/README.md is missing entries for metrics: %s.' 76 % ', '.join(sorted(missing)), 77 ) 78 extra = readme_metrics - config_metrics 79 if extra: 80 self.fail( 81 'test-infra/metrics/README.md includes metrics that are missing config files: %s.' 82 % ', '.join(sorted(extra)), 83 ) 84 85 # Check that all configs are linked in readme. 86 self.assertTrue(all(os.path.basename(p) in readme for p in configs)) 87 88 def test_jq(self): 89 """do_jq executes a jq filter properly.""" 90 def check(expr, data, expected): 91 """Check a test scenario.""" 92 with open(self.data_filename, 'w') as data_file: 93 data_file.write(data) 94 bigquery.do_jq( 95 expr, 96 self.data_filename, 97 self.out_filename, 98 jq_bin=ARGS.jq, 99 ) 100 with open(self.out_filename) as out_file: 101 actual = out_file.read().replace(' ', '').replace('\n', '') 102 self.assertEqual(actual, expected) 103 104 check( 105 expr='.', 106 data='{ "field": "value" }', 107 expected='{"field":"value"}', 108 ) 109 check( 110 expr='.field', 111 data='{ "field": "value" }', 112 expected='"value"', 113 ) 114 115 def test_validate_metric_name(self): 116 """validate_metric_name rejects invalid metric names.""" 117 bigquery.validate_metric_name('normal') 118 119 def check(test): 120 """Check invalid names.""" 121 self.assertRaises(ValueError, bigquery.validate_metric_name, test) 122 123 check('invalid#metric') 124 check('invalid/metric') 125 check('in\\valid') 126 check('invalid?yes') 127 check('*invalid') 128 check('[metric]') 129 check('metric\n') 130 check('met\ric') 131 check('metric& invalid') 132 133 def setUp(self): 134 self.assertTrue(ARGS.jq) 135 self.tmpdir = tempfile.mkdtemp(prefix='bigquery_test_') 136 self.out_filename = os.path.join(self.tmpdir, 'out.json') 137 self.data_filename = os.path.join(self.tmpdir, 'data.json') 138 139 def tearDown(self): 140 shutil.rmtree(self.tmpdir) 141 142 if __name__ == '__main__': 143 PARSER = argparse.ArgumentParser() 144 PARSER.add_argument('--jq', default='jq', help='path to jq binary') 145 ARGS, _ = PARSER.parse_known_args() 146 147 # Remove the --jq flag and its value so that unittest.main can parse the remaining args without 148 # complaining about an unknown flag. 149 for i in range(len(sys.argv)): 150 if sys.argv[i].startswith('--jq'): 151 arg = sys.argv.pop(i) 152 if '=' not in arg: 153 del sys.argv[i] 154 break 155 156 unittest.main()