def test_creates_event_mon_event_correctly(self): TestFile.add_file( 'master', 'builder', 'ui_tests', 123, 'full_results.json', json.dumps(TEST_JSON)) response = self.test_app.post('/internal/monitoring/upload', REQ_PAYLOAD) self.assertEqual(200, response.status_int) events = self.read_event_mon_file() self.assertEqual(1, len(events)) self.assertEqual(events[0].test_results.master_name, 'master') self.assertEqual(events[0].test_results.builder_name, 'builder') self.assertEqual(events[0].test_results.build_number, 123) self.assertEqual(events[0].test_results.test_type, 'ui_tests') self.assertEqual(events[0].test_results.step_name, 'ui_tests 12s pending') self.assertEqual(events[0].test_results.interrupted, False) self.assertEqual(events[0].test_results.version, 3) self.assertEqual(events[0].test_results.usec_since_epoch, 1457612314123000) self.assertEqual(1, len(events[0].test_results.tests)) self.assertEqual( events[0].test_results.tests[0].test_name, 'web-animations-api\\animation-state-changes.html') self.assertEqual( events[0].test_results.tests[0].expected, [ event_mon.protos.chrome_infra_log_pb2.TestResultsEvent.PASS, event_mon.protos.chrome_infra_log_pb2.TestResultsEvent.IMAGE_TEXT, event_mon.protos.chrome_infra_log_pb2.TestResultsEvent.UNKNOWN, ]) self.assertEqual( events[0].test_results.tests[0].actual, [event_mon.protos.chrome_infra_log_pb2.TestResultsEvent.PASS])
def testFromTestFile(self): test_file = TestFile(master='test_master', builder='test_builder_name', test_type='test_step', build_number=42, name='test_file_name') test_file.save_file(test_file, json.dumps(self.test_json_1)) step_result = StepResult.fromTestFile(test_file) self.assertEqual(step_result.master, 'test_master') self.assertEqual(step_result.builder_name, 'test_builder_name') self.assertEqual(step_result.build_number, 42) self.assertEqual(step_result.test_type, 'test_step') self.assertEqual(step_result.blink_revision, '54321') self.assertEqual(step_result.chromium_revision, 'deadbeef' * 5) self.assertEqual(step_result.version, 9) self.assertEqual( calendar.timegm(step_result.time.utctimetuple()), 1411715603) (master_out, test_type_out, json_out) = step_result.toJson() self.assertEqual(master_out, 'test_master') self.assertEqual(test_type_out, 'test_step') self.assertEqual(self._massage_json(copy.deepcopy(self.test_json_1)), self._massage_json(copy.deepcopy(json_out)))
def testFromTestFile(self): test_file = TestFile(master='test_master', builder='test_builder_name', test_type='test_step', build_number=42, name='test_file_name') test_file.save_file(test_file, json.dumps(self.test_json_1)) step_result = StepResult.fromTestFile(test_file) self.assertEqual(step_result.master, 'test_master') self.assertEqual(step_result.builder_name, 'test_builder_name') self.assertEqual(step_result.build_number, 42) self.assertEqual(step_result.test_type, 'test_step') self.assertEqual(step_result.blink_revision, '54321') self.assertEqual(step_result.chromium_revision, 'deadbeef' * 5) self.assertEqual(step_result.version, 9) self.assertEqual(calendar.timegm(step_result.time.utctimetuple()), 1411715603) (master_out, test_type_out, json_out) = step_result.toJson() self.assertEqual(master_out, 'test_master') self.assertEqual(test_type_out, 'test_step') self.assertEqual(self._massage_json(copy.deepcopy(self.test_json_1)), self._massage_json(copy.deepcopy(json_out)))
def test_does_not_crash_on_missing_required_fields_in_json(self): TestFile.add_file( 'master', 'builder', 'ui_tests', 123, 'full_results.json', '{}') response = self.test_app.post('/internal/monitoring/upload', REQ_PAYLOAD) self.assertEqual(200, response.status_int) events = self.read_event_mon_file() self.assertEqual(1, len(events)) self.assertFalse(events[0].test_results.HasField('interrupted')) self.assertFalse(events[0].test_results.HasField('version')) self.assertFalse(events[0].test_results.HasField('usec_since_epoch')) self.assertEqual(0, len(events[0].test_results.tests))
def test_creates_event_mon_event_correctly(self): TestFile.add_file( 'master', 'builder', 'ui_tests', 123, 'full_results.json', json.dumps(TEST_JSON)) response = self.test_app.post('/internal/monitoring/upload', { 'master': 'master', 'builder': 'builder', 'build_number': '123', 'test_type': 'ui_tests', }) self.assertEqual(200, response.status_int)
def _get_file_content(master, builder, test_type, build_number, name): # pragma: no cover """Return content of the file that matches builder and file name. Args: builder: builder name test_type: type of the test build_number: build number, or 'latest' name: file name """ files = TestFile.get_files(master, builder, test_type, build_number, name, load_data=True, limit=1) if not files: logging.info( ("File not found, master %s, builder: %s, test_type: %s, " "build_number: %s, name: %s."), master, builder, test_type, build_number, name) return None, None return files[0].data, files[0].date
def update_file(cls, builder, record, incremental_json, num_runs): # pragma: no cover new_results, status_code = cls.merge(builder, record.data, incremental_json, num_runs) if status_code != 200: return new_results, status_code return TestFile.save_file(record, new_results)
def update_file(cls, builder, record, incremental_json, num_runs): # pragma: no cover new_results, status_code = cls.merge( builder, record.data, incremental_json, num_runs) if status_code != 200: return new_results, status_code return TestFile.save_file(record, new_results)
def _get_last_upload_date(master_name, builder, test_type): build_number = None files = TestFile.get_files( master_name, builder, test_type, build_number, "full_results.json", load_data=False, limit=1 ) if files: return files[0].date else: return None
def _get_last_upload_date(master_name, builder, test_type): build_number = None files = TestFile.get_files(master_name, builder, test_type, build_number, 'full_results.json', load_data=False, limit=1) if files: return files[0].date else: return None
def _get_aggregate_file(cls, master, builder, test_type, filename, deprecated_master): # pragma: no cover files = TestFile.get_files(master, builder, test_type, None, filename) if files: return files[0] if deprecated_master: files = TestFile.get_files(deprecated_master, builder, test_type, None, filename) if files: deprecated_file = files[0] # Change the master so it gets saved out with the new master name. deprecated_file.master = master return deprecated_file record = TestFile() record.master = master record.builder = builder record.test_type = test_type record.build_number = None record.name = filename record.data = "" return record
def _get_file_list(self, master, builder, test_type, build_number, name, before, limit, callback_name=None): # pragma: no cover """Get and display a list of files that matches builder and file name. Args: builder: builder name test_type: type of the test name: file name """ files = TestFile.get_files(master, builder, test_type, build_number, name, before, load_data=False, limit=limit) if not files: logging.info( ("File not found, master: %s, builder: %s, test_type: %s, " "build_number: %s, name: %s."), master, builder, test_type, build_number, name) self.response.out.write("File not found") return template_values = { "admin": users.is_current_user_admin(), "master": master, "builder": builder, "test_type": test_type, "build_number": build_number, "name": name, "files": files, } if callback_name: json = template.render("templates/showfilelist.jsonp", template_values) self._serve_json(_replace_jsonp_callback(json, callback_name), files[0].date) return self.response.out.write( template.render("templates/showfilelist.html", template_values))
def _get_aggregate_file(cls, master, builder, test_type, filename, deprecated_master): # pragma: no cover files = TestFile.get_files(master, builder, test_type, None, filename) if files: return files[0] if deprecated_master: files = TestFile.get_files( deprecated_master, builder, test_type, None, filename) if files: deprecated_file = files[0] # Change the master so it gets saved out with the new master name. deprecated_file.master = master return deprecated_file record = TestFile() record.master = master record.builder = builder record.test_type = test_type record.build_number = None record.name = filename record.data = "" return record
def _get_file_content(master, builder, test_type, build_number, name): # pragma: no cover """Return content of the file that matches builder and file name. Args: builder: builder name test_type: type of the test build_number: build number, or 'latest' name: file name """ files = TestFile.get_files( master, builder, test_type, build_number, name, load_data=True, limit=1) if not files: logging.info(("File not found, master %s, builder: %s, test_type: %s, " "build_number: %s, name: %s."), master, builder, test_type, build_number, name) return None, None return files[0].data, files[0].date
def get(self): # pragma: no cover key = self.request.get(PARAM_KEY) # Intentionally don't munge the master from deprecated names here. # Assume anyone deleting files wants explicit control. master = self.request.get(PARAM_MASTER) builder = self.request.get(PARAM_BUILDER) test_type = self.request.get(PARAM_TEST_TYPE) build_number = self.request.get(PARAM_BUILD_NUMBER, default_value=None) name = self.request.get(PARAM_NAME) num_files = self.request.get(PARAM_NUM_FILES) before = self.request.get(PARAM_BEFORE) logging.debug(("Deleting File, master: %s, builder: %s, test_type: %s, " "build_number: %s, name: %s, before: %s, key: %s."), master, builder, test_type, build_number, name, before, key) limit = int(num_files) if num_files else 1 num_deleted = TestFile.delete_file( key, master, builder, test_type, build_number, name, before, limit) self.response.set_status(200) self.response.out.write("Deleted %d files." % num_deleted)
def get(self): # pragma: no cover key = self.request.get(PARAM_KEY) # Intentionally don't munge the master from deprecated names here. # Assume anyone deleting files wants explicit control. master = self.request.get(PARAM_MASTER) builder = self.request.get(PARAM_BUILDER) test_type = self.request.get(PARAM_TEST_TYPE) build_number = self.request.get(PARAM_BUILD_NUMBER, default_value=None) name = self.request.get(PARAM_NAME) num_files = self.request.get(PARAM_NUM_FILES) before = self.request.get(PARAM_BEFORE) logging.debug( ("Deleting File, master: %s, builder: %s, test_type: %s, " "build_number: %s, name: %s, before: %s, key: %s."), master, builder, test_type, build_number, name, before, key) limit = int(num_files) if num_files else 1 num_deleted = TestFile.delete_file(key, master, builder, test_type, build_number, name, before, limit) self.response.set_status(200) self.response.out.write("Deleted %d files." % num_deleted)
def _get_file_list(self, master, builder, test_type, build_number, name, before, limit, callback_name=None): # pragma: no cover """Get and display a list of files that matches builder and file name. Args: builder: builder name test_type: type of the test name: file name """ files = TestFile.get_files( master, builder, test_type, build_number, name, before, load_data=False, limit=limit) if not files: logging.info(("File not found, master: %s, builder: %s, test_type: %s, " "build_number: %s, name: %s."), master, builder, test_type, build_number, name) self.response.out.write("File not found") return template_values = { "admin": users.is_current_user_admin(), "master": master, "builder": builder, "test_type": test_type, "build_number": build_number, "name": name, "files": files, } if callback_name: json = template.render("templates/showfilelist.jsonp", template_values) self._serve_json( _replace_jsonp_callback(json, callback_name), files[0].date) return self.response.out.write(template.render("templates/showfilelist.html", template_values))
def post(self): # pragma: no cover file_params = self.request.POST.getall(PARAM_FILE) if not file_params: self.response.out.write("FAIL: missing upload file field.") return builder = self.request.get(PARAM_BUILDER) if not builder: self.response.out.write("FAIL: missing builder parameter.") return master_parameter = self.request.get(PARAM_MASTER) master_data = master_config.getMasterByMasterName(master_parameter) if master_data: deprecated_master = master_parameter master = master_data['url_name'] else: deprecated_master = None master = master_parameter test_type = self.request.get(PARAM_TEST_TYPE) logging.debug( "Processing upload request, master: %s, builder: %s, test_type: %s.", master, builder, test_type) # There are two possible types of each file_params in the request: # one file item or a list of file items. # Normalize file_params to a file item list. files = [] logging.debug("test: %s, type:%s", file_params, type(file_params)) for item in file_params: if not isinstance(item, list) and not isinstance(item, tuple): item = [item] files.extend(item) errors = [] final_status_code = 200 for record in files: file_json = JsonResults.load_json(record.value) if record.filename == "incremental_results.json": # FIXME: Ferret out and eliminate remaining incremental_results.json # producers. logging.info( ("incremental_results.json received from master: %s, " "builder: %s, test_type: %s."), master, builder, test_type) status_string, status_code = JsonResults.update( master, builder, test_type, file_json, deprecated_master=deprecated_master, is_full_results_format=False) else: try: build_number = int(file_json.get('build_number', 0)) status_string, status_code = TestFile.add_file( master, builder, test_type, build_number, record.filename, record.value) except (ValueError, TypeError): status_code = 403 status_string = ( 'Could not cast the build_number field in the ' 'json to an integer.') if status_code == 200: logging.info(status_string) else: logging.error(status_string) errors.append(status_string) final_status_code = status_code if status_code == 200 and record.filename == "full_results.json": status_string, status_code = JsonResults.update( master, builder, test_type, file_json, deprecated_master=deprecated_master, is_full_results_format=True) BuilderState.incremental_update(master, builder, test_type, datetime.now()) if status_code == 200: logging.info(status_string) else: logging.error(status_string) errors.append(status_string) final_status_code = status_code if errors: messages = "FAIL: " + "; ".join(errors) self.response.set_status(final_status_code, messages) self.response.out.write(messages) else: self.response.set_status(200) self.response.out.write("OK")
def post(self): if not self.request.body: logging.error('Missing request payload') self.response.set_status(400) return try: payload = json.loads(self.request.body) except ValueError: logging.error('Failed to parse request payload as JSON') self.response.set_status(400) return # Retrieve test json from datastore based on task parameters. master = payload.get('master') builder = payload.get('builder') build_number = payload.get('build_number') test_type = payload.get('test_type') step_name = payload.get('step_name') if (not master or not builder or build_number is None or not test_type or not step_name): logging.error( 'Missing required parameters: (master=%s, builder=%s, ' 'build_number=%s, test_type=%s, step_name=%s)' % (master, builder, build_number, test_type, step_name)) self.response.set_status(400) return files = TestFile.get_files( master, builder, test_type, build_number, 'full_results.json', load_data=True, limit=1) if not files: logging.error('Failed to find full_results.json for (%s, %s, %s, %s)' % ( master, builder, build_number, test_type)) self.response.set_status(404) return file_json = JsonResults.load_json(files[0].data) # Create a proto event and send it to event_mon. event = event_mon.Event('POINT') test_results = event.proto.test_results test_results.master_name = master test_results.builder_name = builder test_results.build_number = int(build_number) test_results.test_type = test_type test_results.step_name = step_name if 'interrupted' in file_json: test_results.interrupted = file_json['interrupted'] if 'version' in file_json: test_results.version = file_json['version'] if 'seconds_since_epoch' in file_json: test_results.usec_since_epoch = long( float(file_json['seconds_since_epoch']) * 1000 * 1000) def convert_test_result_type(json_val): self.num_test_results.increment({ 'result_type': json_val, 'master': master, 'builder': builder, 'test_type': test_type}) try: return (event_mon.protos.chrome_infra_log_pb2.TestResultsEvent. TestResultType.Value(json_val.upper().replace('+', '_'))) except ValueError: return event_mon.protos.chrome_infra_log_pb2.TestResultsEvent.UNKNOWN tests = util.flatten_tests_trie( file_json.get('tests', {}), file_json.get('path_delimiter', '/')) for name, test in tests.iteritems(): test_result = test_results.tests.add() test_result.test_name = name test_result.actual.extend( convert_test_result_type(res) for res in test['actual']) test_result.expected.extend( convert_test_result_type(res) for res in test['expected']) event.send()
def post(self): # pragma: no cover file_params = self.request.POST.getall(PARAM_FILE) if not file_params: self.response.out.write("FAIL: missing upload file field.") return builder = self.request.get(PARAM_BUILDER) if not builder: self.response.out.write("FAIL: missing builder parameter.") return master_parameter = self.request.get(PARAM_MASTER) master_data = master_config.getMasterByMasterName(master_parameter) if master_data: deprecated_master = master_parameter master = master_data['url_name'] else: deprecated_master = None master = master_parameter test_type = self.request.get(PARAM_TEST_TYPE) test_type = util.normalize_test_type(test_type) logging.debug( "Processing upload request, master: %s, builder: %s, test_type: %s.", master, builder, test_type) # There are two possible types of each file_params in the request: # one file item or a list of file items. # Normalize file_params to a file item list. files = [] logging.debug("test: %s, type:%s", file_params, type(file_params)) for item in file_params: if not isinstance(item, list) and not isinstance(item, tuple): item = [item] files.extend(item) errors = [] final_status_code = 200 for record in files: file_json = JsonResults.load_json(record.value) if record.filename == "incremental_results.json": # FIXME: Ferret out and eliminate remaining incremental_results.json # producers. logging.info(("incremental_results.json received from master: %s, " "builder: %s, test_type: %s."), master, builder, test_type) status_string, status_code = JsonResults.update(master, builder, test_type, file_json, deprecated_master=deprecated_master, is_full_results_format=False) else: try: build_number = int(file_json.get('build_number', 0)) status_string, status_code = TestFile.add_file(master, builder, test_type, build_number, record.filename, record.value) except (ValueError, TypeError): status_code = 403 status_string = ('Could not cast the build_number field in the ' 'json to an integer.') if status_code == 200: logging.info(status_string) else: logging.error(status_string) errors.append(status_string) final_status_code = status_code if status_code == 200 and record.filename == "full_results.json": status_string, status_code = JsonResults.update(master, builder, test_type, file_json, deprecated_master=deprecated_master, is_full_results_format=True) BuilderState.incremental_update(master, builder, test_type, datetime.now()) EventMonUploader.upload(master, builder, build_number, test_type, file_json) if status_code == 200: logging.info(status_string) else: logging.error(status_string) errors.append(status_string) final_status_code = status_code if errors: messages = "FAIL: " + "; ".join(errors) self.response.set_status(final_status_code, messages) self.response.out.write(messages) else: self.response.set_status(200) self.response.out.write("OK")