OLD | NEW |
1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import argparse | 5 import argparse |
6 import os | 6 import os |
7 import unittest | 7 import unittest |
8 | 8 |
| 9 import google.protobuf |
| 10 |
9 import infra_libs | 11 import infra_libs |
10 from infra_libs import event_mon | 12 from infra_libs import event_mon |
| 13 |
11 from infra.tools.send_monitoring_event import send_event | 14 from infra.tools.send_monitoring_event import send_event |
12 | 15 |
| 16 from infra_libs.event_mon import (BuildEvent, ServiceEvent, |
| 17 ChromeInfraEvent, LogRequestLite) |
13 | 18 |
14 DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') | 19 DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') |
15 | 20 |
16 | 21 |
17 class SendingEventBaseTest(unittest.TestCase): | 22 class SendingEventBaseTest(unittest.TestCase): |
18 """Base class for all tests that send events.""" | 23 """Base class for all tests that send events.""" |
19 def setUp(self): | 24 def setUp(self): |
20 # Use the dry run mode instead of a mock. | 25 # Use the dry run mode instead of a mock. |
21 event_mon.setup_monitoring(run_type='dry') | 26 event_mon.setup_monitoring(run_type='dry') |
22 | 27 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 send_event.send_service_event(args) | 86 send_event.send_service_event(args) |
82 | 87 |
83 | 88 |
84 class TestBuildEvent(SendingEventBaseTest): | 89 class TestBuildEvent(SendingEventBaseTest): |
85 def test_send_build_event_smoke(self): | 90 def test_send_build_event_smoke(self): |
86 args = send_event.get_arguments( | 91 args = send_event.get_arguments( |
87 ['--event-mon-service-name', 'thing', | 92 ['--event-mon-service-name', 'thing', |
88 '--build-event-type', 'SCHEDULER', | 93 '--build-event-type', 'SCHEDULER', |
89 '--build-event-hostname', 'foo.bar.dns', | 94 '--build-event-hostname', 'foo.bar.dns', |
90 '--build-event-build-name', 'whatever']) | 95 '--build-event-build-name', 'whatever']) |
91 self.assertEquals(args.event_mon_run_type, 'dry') | 96 self.assertTrue(send_event.send_build_event(args)) |
92 send_event.send_build_event(args) | 97 |
93 | 98 def test_send_build_event_smoke_missing_goma_file(self): |
94 | 99 args = send_event.get_arguments( |
95 class TestEventsFromFile(SendingEventBaseTest): | 100 ['--event-mon-service-name', 'thing', |
| 101 '--build-event-type', 'BUILD', |
| 102 '--build-event-hostname', 'foo.bar.dns', |
| 103 '--build-event-build-name', 'whatever', |
| 104 '--build-event-goma-stats-path', |
| 105 os.path.join(DATA_DIR, 'this-file-does-not-exist')]) |
| 106 with self.assertRaises(IOError): |
| 107 send_event.send_build_event(args) |
| 108 |
| 109 |
| 110 class TestInputModesFile(unittest.TestCase): |
| 111 # Test the various ways to pass information to send_monitoring_event |
| 112 # TODO(pgervais): test precedence order. |
| 113 def tearDown(self): |
| 114 event_mon.close() |
| 115 |
| 116 def test_send_build_event_with_goma_stats(self): |
| 117 # Write a file to avoid mocks |
| 118 with infra_libs.temporary_directory(prefix='send_event_test-') as tmpdir: |
| 119 outfile = os.path.join(tmpdir, 'out.bin') |
| 120 args = send_event.get_arguments( |
| 121 ['--event-mon-run-type', 'file', |
| 122 '--event-mon-output-file', outfile, |
| 123 '--event-mon-service-name', 'thing', |
| 124 '--build-event-type', 'BUILD', |
| 125 '--build-event-hostname', 'foo.bar.dns', |
| 126 '--build-event-build-name', 'whatever', |
| 127 '--build-event-goma-stats-path', |
| 128 os.path.join(DATA_DIR, 'goma_stats.bin')]) |
| 129 self.assertEquals(args.event_mon_run_type, 'file') |
| 130 event_mon.process_argparse_options(args) |
| 131 self.assertTrue(send_event.send_build_event(args)) |
| 132 |
| 133 # Now open the resulting file and check what was written |
| 134 with open(outfile, 'rb') as f: |
| 135 request = LogRequestLite.FromString(f.read()) |
| 136 |
| 137 self.assertEqual(len(request.log_event), 1) |
| 138 event = ChromeInfraEvent.FromString(request.log_event[0].source_extension) |
| 139 self.assertEqual(event.build_event.goma_stats.request_stats.total, 10) |
| 140 self.assertEqual(event.build_event.goma_stats.request_stats.success, 9) |
| 141 self.assertEqual(event.build_event.goma_stats.request_stats.failure, 1) |
| 142 self.assertEqual(event.build_event.host_name, 'foo.bar.dns') |
| 143 |
| 144 def test_send_build_event_with_invalid_goma_stats(self): |
| 145 # Write a file to avoid mocks |
| 146 with infra_libs.temporary_directory(prefix='send_event_test-') as tmpdir: |
| 147 outfile = os.path.join(tmpdir, 'out.bin') |
| 148 args = send_event.get_arguments( |
| 149 ['--event-mon-run-type', 'file', |
| 150 '--event-mon-output-file', outfile, |
| 151 '--event-mon-service-name', 'thing', |
| 152 '--build-event-type', 'BUILD', |
| 153 '--build-event-hostname', 'foo.bar.dns', |
| 154 '--build-event-build-name', 'whatever', |
| 155 '--build-event-goma-stats-path', |
| 156 os.path.join(DATA_DIR, 'garbage')]) |
| 157 self.assertEquals(args.event_mon_run_type, 'file') |
| 158 event_mon.process_argparse_options(args) |
| 159 with self.assertRaises(google.protobuf.message.DecodeError): |
| 160 send_event.send_build_event(args) |
| 161 |
| 162 # The default event used below (build-foo-builder.bin) has been generated by: |
| 163 # ./run.py infra.tools.send_monitoring_event \ |
| 164 # --event-mon-run-type=file \ |
| 165 # --event-mon-output-file=./build-foo-builder.bin \ |
| 166 # --build-event-hostname=myhostname \ |
| 167 # --event-mon-timestamp-kind=BEGIN \ |
| 168 # --event-mon-event-timestamp=123 \ |
| 169 # --build-event-type=BUILD \ |
| 170 # --build-event-build-name=foo" |
| 171 def test_logrequest_path_valid_build_event(self): |
| 172 with infra_libs.temporary_directory(prefix='send_event_test-') as tmpdir: |
| 173 outfile = os.path.join(tmpdir, 'out.bin') |
| 174 args = send_event.get_arguments( |
| 175 ['--event-mon-run-type', 'file', |
| 176 '--event-mon-output-file', outfile, |
| 177 '--event-mon-service-name', 'thing', |
| 178 '--event-logrequest-path', |
| 179 os.path.join(DATA_DIR, 'build-foo-builder.bin'), |
| 180 '--build-event-build-number', '3' |
| 181 ]) |
| 182 self.assertEquals(args.event_mon_run_type, 'file') |
| 183 event_mon.process_argparse_options(args) |
| 184 send_event._process_logrequest_path(args) |
| 185 self.assertTrue(send_event.send_build_event(args)) |
| 186 |
| 187 # Now open the resulting file and check what was written |
| 188 with open(outfile, 'rb') as f: |
| 189 request = LogRequestLite.FromString(f.read()) |
| 190 |
| 191 self.assertEqual(len(request.log_event), 1) |
| 192 event = ChromeInfraEvent.FromString(request.log_event[0].source_extension) |
| 193 self.assertEqual(event.build_event.host_name, 'myhostname') |
| 194 self.assertEqual(event.build_event.build_number, 3) |
| 195 self.assertEqual(event.timestamp_kind, ChromeInfraEvent.BEGIN) |
| 196 |
| 197 def test_logrequest_path_build_type_override(self): |
| 198 # logrequest contains build event, overrid the type with an arg. |
| 199 with infra_libs.temporary_directory(prefix='send_event_test-') as tmpdir: |
| 200 outfile = os.path.join(tmpdir, 'out.bin') |
| 201 args = send_event.get_arguments( |
| 202 ['--event-mon-run-type', 'file', |
| 203 '--event-mon-output-file', outfile, |
| 204 '--event-mon-service-name', 'thing', |
| 205 '--event-logrequest-path', |
| 206 os.path.join(DATA_DIR, 'build-foo-builder.bin'), |
| 207 '--build-event-build-number', '3', |
| 208 '--build-event-type', 'STEP', |
| 209 ]) |
| 210 self.assertEquals(args.event_mon_run_type, 'file') |
| 211 event_mon.process_argparse_options(args) |
| 212 send_event._process_logrequest_path(args) |
| 213 self.assertTrue(send_event.send_build_event(args)) |
| 214 |
| 215 # Now open the resulting file and check what was written |
| 216 with open(outfile, 'rb') as f: |
| 217 request = LogRequestLite.FromString(f.read()) |
| 218 |
| 219 self.assertEqual(len(request.log_event), 1) |
| 220 event = ChromeInfraEvent.FromString(request.log_event[0].source_extension) |
| 221 self.assertEqual(event.build_event.host_name, 'myhostname') |
| 222 self.assertEqual(event.build_event.type, BuildEvent.STEP) |
| 223 self.assertEqual(event.build_event.build_number, 3) |
| 224 self.assertEqual(event.timestamp_kind, ChromeInfraEvent.BEGIN) |
| 225 |
| 226 def test_logrequest_path_build_service_conflicts(self): |
| 227 # logrequest contains build event, provides service event as arg |
| 228 with infra_libs.temporary_directory(prefix='send_event_test-') as tmpdir: |
| 229 outfile = os.path.join(tmpdir, 'out.bin') |
| 230 args = send_event.get_arguments( |
| 231 ['--event-mon-run-type', 'file', |
| 232 '--event-mon-output-file', outfile, |
| 233 '--event-mon-service-name', 'thing', |
| 234 '--event-logrequest-path', |
| 235 os.path.join(DATA_DIR, 'build-foo-builder.bin'), |
| 236 '--build-event-build-number', '3', |
| 237 '--service-event-type', 'START', |
| 238 ]) |
| 239 self.assertEquals(args.event_mon_run_type, 'file') |
| 240 event_mon.process_argparse_options(args) |
| 241 with self.assertRaises(ValueError): |
| 242 send_event._process_logrequest_path(args) |
| 243 |
| 244 # The default event used below has been generated using: |
| 245 # ./run.py infra.tools.send_monitoring_event |
| 246 # --event-mon-run-type=file |
| 247 # --event-mon-output-file=./service-bar-service.bin |
| 248 # --service-event-type=START |
| 249 # --event-mon-service-name=bar |
| 250 # --event-mon-hostname=myhostname |
| 251 # --event-mon-timestamp-kind=BEGIN |
| 252 # --event-mon-event-timestamp=123 |
| 253 def test_logrequest_path_valid_service_event(self): |
| 254 with infra_libs.temporary_directory(prefix='send_event_test-') as tmpdir: |
| 255 outfile = os.path.join(tmpdir, 'out.bin') |
| 256 args = send_event.get_arguments( |
| 257 ['--event-mon-run-type', 'file', |
| 258 '--event-mon-output-file', outfile, |
| 259 '--event-mon-service-name', 'thing', |
| 260 '--event-logrequest-path', |
| 261 os.path.join(DATA_DIR, 'service-bar-service.bin'), |
| 262 ]) |
| 263 self.assertEquals(args.event_mon_run_type, 'file') |
| 264 event_mon.process_argparse_options(args) |
| 265 send_event._process_logrequest_path(args) |
| 266 self.assertTrue(send_event.send_service_event(args)) |
| 267 |
| 268 # Now open the resulting file and check what was written |
| 269 with open(outfile, 'rb') as f: |
| 270 request = LogRequestLite.FromString(f.read()) |
| 271 |
| 272 self.assertEqual(len(request.log_event), 1) |
| 273 event = ChromeInfraEvent.FromString(request.log_event[0].source_extension) |
| 274 self.assertEqual(event.event_source.host_name, 'myhostname') |
| 275 self.assertEqual(event.service_event.type, ServiceEvent.START) |
| 276 self.assertEqual(event.timestamp_kind, ChromeInfraEvent.BEGIN) |
| 277 |
| 278 def test_logrequest_path_service_type_override(self): |
| 279 with infra_libs.temporary_directory(prefix='send_event_test-') as tmpdir: |
| 280 outfile = os.path.join(tmpdir, 'out.bin') |
| 281 args = send_event.get_arguments( |
| 282 ['--event-mon-run-type', 'file', |
| 283 '--event-mon-output-file', outfile, |
| 284 '--event-mon-service-name', 'thing', |
| 285 '--event-logrequest-path', |
| 286 os.path.join(DATA_DIR, 'service-bar-service.bin'), |
| 287 '--service-event-type', 'STOP', |
| 288 ]) |
| 289 self.assertEquals(args.event_mon_run_type, 'file') |
| 290 event_mon.process_argparse_options(args) |
| 291 send_event._process_logrequest_path(args) |
| 292 self.assertTrue(send_event.send_service_event(args)) |
| 293 |
| 294 # Now open the resulting file and check what was written |
| 295 with open(outfile, 'rb') as f: |
| 296 request = LogRequestLite.FromString(f.read()) |
| 297 |
| 298 self.assertEqual(len(request.log_event), 1) |
| 299 event = ChromeInfraEvent.FromString(request.log_event[0].source_extension) |
| 300 self.assertEqual(event.event_source.host_name, 'myhostname') |
| 301 self.assertEqual(event.service_event.type, ServiceEvent.STOP) |
| 302 self.assertEqual(event.timestamp_kind, ChromeInfraEvent.END) |
| 303 |
| 304 def test_logrequest_path_service_build_conflict(self): |
| 305 with infra_libs.temporary_directory(prefix='send_event_test-') as tmpdir: |
| 306 outfile = os.path.join(tmpdir, 'out.bin') |
| 307 args = send_event.get_arguments( |
| 308 ['--event-mon-run-type', 'file', |
| 309 '--event-mon-output-file', outfile, |
| 310 '--event-mon-service-name', 'thing', |
| 311 '--event-logrequest-path', |
| 312 os.path.join(DATA_DIR, 'service-bar-service.bin'), |
| 313 '--build-event-type', 'BUILD', |
| 314 ]) |
| 315 self.assertEquals(args.event_mon_run_type, 'file') |
| 316 event_mon.process_argparse_options(args) |
| 317 with self.assertRaises(ValueError): |
| 318 send_event._process_logrequest_path(args) |
| 319 |
| 320 def test_logrequest_path_service_build_and_service(self): |
| 321 # The logrequest provided contains both a service and a build type, |
| 322 # which is invalid. |
| 323 with infra_libs.temporary_directory(prefix='send_event_test-') as tmpdir: |
| 324 outfile = os.path.join(tmpdir, 'out.bin') |
| 325 args = send_event.get_arguments( |
| 326 ['--event-mon-run-type', 'file', |
| 327 '--event-mon-output-file', outfile, |
| 328 '--event-mon-service-name', 'thing', |
| 329 '--event-logrequest-path', |
| 330 os.path.join(DATA_DIR, 'build-and-service-event.bin'), |
| 331 ]) |
| 332 self.assertEquals(args.event_mon_run_type, 'file') |
| 333 event_mon.process_argparse_options(args) |
| 334 with self.assertRaises(ValueError): |
| 335 send_event._process_logrequest_path(args) |
| 336 |
| 337 |
| 338 class TestEventsFromTextFile(SendingEventBaseTest): |
96 def test_send_events_from_file_smoke(self): | 339 def test_send_events_from_file_smoke(self): |
97 # Create a temporary file because we don't want to risk deleting a | 340 # Create a temporary file because we don't want to risk deleting a |
98 # checked-in file. | 341 # checked-in file. |
99 with infra_libs.temporary_directory(prefix='send-events-test') as tempdir: | 342 with infra_libs.temporary_directory(prefix='send-events-test') as tempdir: |
100 event_file = os.path.join(tempdir, 'events.log') | 343 event_file = os.path.join(tempdir, 'events.log') |
101 with open(event_file, 'w') as f: | 344 with open(event_file, 'w') as f: |
102 f.write('{"build-event-type": "STEP", ' | 345 f.write('{"build-event-type": "STEP", ' |
103 '"build-event-build-name": "infra-continuous-precise-64", ' | 346 '"build-event-build-name": "infra-continuous-precise-64", ' |
104 '"event-mon-service-name": "buildbot/master/chromium.infra", ' | 347 '"event-mon-service-name": "buildbot/master/chromium.infra", ' |
105 '"build-event-step-number": 9, ' | 348 '"build-event-step-number": 9, ' |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 self.assertTrue(any(fname.endswith(filename) for filename in filenames)) | 451 self.assertTrue(any(fname.endswith(filename) for filename in filenames)) |
209 | 452 |
210 def test_one_wildcard_one_file(self): | 453 def test_one_wildcard_one_file(self): |
211 filenames = ('events.log', 'events-1.log', 'events-2.log') | 454 filenames = ('events.log', 'events-1.log', 'events-2.log') |
212 file_list = send_event.get_event_file_list( | 455 file_list = send_event.get_event_file_list( |
213 [os.path.join(self.FILES_DIR, 'events-?.log'), | 456 [os.path.join(self.FILES_DIR, 'events-?.log'), |
214 os.path.join(self.FILES_DIR, 'events.log')]) | 457 os.path.join(self.FILES_DIR, 'events.log')]) |
215 self.assertTrue(len(file_list) == 3) | 458 self.assertTrue(len(file_list) == 3) |
216 for fname in file_list: | 459 for fname in file_list: |
217 self.assertTrue(any(fname.endswith(filename) for filename in filenames)) | 460 self.assertTrue(any(fname.endswith(filename) for filename in filenames)) |
| 461 |
| 462 |
| 463 class TestProcessRequestPath(SendingEventBaseTest): |
| 464 def test_logrequest_missing_args(self): |
| 465 orig_event = event_mon.get_default_event() |
| 466 self.assertIsNot(orig_event, None) |
| 467 |
| 468 args = argparse.Namespace() |
| 469 args.event_logrequest_path = None |
| 470 send_event._process_logrequest_path(args) |
| 471 |
| 472 self.assertEqual(orig_event, event_mon.get_default_event()) |
| 473 |
| 474 def test_logrequest_with_valid_file(self): |
| 475 orig_event = event_mon.get_default_event() |
| 476 self.assertIsNot(orig_event, None) |
| 477 |
| 478 args = argparse.Namespace() |
| 479 args.event_logrequest_path = os.path.join(DATA_DIR, 'logrequest-build.bin') |
| 480 args.service_event_type = None |
| 481 args.build_event_type = None |
| 482 send_event._process_logrequest_path(args) |
| 483 |
| 484 new_event = event_mon.get_default_event() |
| 485 self.assertNotEqual(orig_event, new_event) |
| 486 self.assertEqual(new_event.build_event.type, BuildEvent.BUILD) |
| 487 |
| 488 def test_logrequest_with_no_log_event(self): |
| 489 orig_event = event_mon.get_default_event() |
| 490 self.assertIsNot(orig_event, None) |
| 491 |
| 492 args = argparse.Namespace() |
| 493 args.event_logrequest_path = os.path.join(DATA_DIR, 'logrequest-empty.bin') |
| 494 with self.assertRaises(ValueError): |
| 495 send_event._process_logrequest_path(args) |
| 496 |
| 497 def test_logrequest_with_bad_content(self): |
| 498 orig_event = event_mon.get_default_event() |
| 499 self.assertIsNot(orig_event, None) |
| 500 |
| 501 args = argparse.Namespace() |
| 502 args.event_logrequest_path = os.path.join(DATA_DIR, 'garbage') |
| 503 with self.assertRaises(google.protobuf.message.DecodeError): |
| 504 send_event._process_logrequest_path(args) |
| 505 |
| 506 def test_logrequest_with_missing_file(self): |
| 507 args = argparse.Namespace() |
| 508 args.event_logrequest_path = os.path.join(DATA_DIR, 'non-existent-file.bin') |
| 509 with self.assertRaises(IOError): |
| 510 send_event._process_logrequest_path(args) |
OLD | NEW |