Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(418)

Side by Side Diff: appengine/findit/test/findit_api_test.py

Issue 2425853005: [Findit] Modify Findit API to return more information to Sheriff-O-Matic. (Closed)
Patch Set: fix nits Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 json 5 import json
6 import mock 6 import mock
7 import re 7 import re
8 8
9 import endpoints
10 from google.appengine.api import taskqueue 9 from google.appengine.api import taskqueue
11 import webtest 10 import webtest
12 11
13 from testing_utils import testing 12 from testing_utils import testing
14 13
15 from common.waterfall import failure_type 14 from common.waterfall import failure_type
16 import findit_api 15 import findit_api
17 from findit_api import FindItApi 16 from findit_api import FindItApi
17 from model import analysis_approach_type
18 from model.base_build_model import BaseBuildModel
18 from model.wf_analysis import WfAnalysis 19 from model.wf_analysis import WfAnalysis
20 from model.wf_suspected_cl import WfSuspectedCL
19 from model.wf_swarming_task import WfSwarmingTask 21 from model.wf_swarming_task import WfSwarmingTask
20 from model.wf_try_job import WfTryJob 22 from model.wf_try_job import WfTryJob
21 from model import analysis_status 23 from model import analysis_status
24 from waterfall import suspected_cl_util
22 from waterfall import waterfall_config 25 from waterfall import waterfall_config
23 26
24 27
25 class FinditApiTest(testing.EndpointsTestCase): 28 class FinditApiTest(testing.EndpointsTestCase):
26 api_service_cls = FindItApi 29 api_service_cls = FindItApi
27 30
28 def setUp(self): 31 def setUp(self):
29 super(FinditApiTest, self).setUp() 32 super(FinditApiTest, self).setUp()
30 self.taskqueue_requests = [] 33 self.taskqueue_requests = []
31 def Mocked_taskqueue_add(**kwargs): 34 def Mocked_taskqueue_add(**kwargs):
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 'builder_name': builder_name, 215 'builder_name': builder_name,
213 'build_number': build_number, 216 'build_number': build_number,
214 'step_name': 'a', 217 'step_name': 'a',
215 'is_sub_test': False, 218 'is_sub_test': False,
216 'first_known_failed_build_number': 23, 219 'first_known_failed_build_number': 23,
217 'suspected_cls': [ 220 'suspected_cls': [
218 { 221 {
219 'repo_name': 'chromium', 222 'repo_name': 'chromium',
220 'revision': 'git_hash', 223 'revision': 'git_hash',
221 'commit_position': 123, 224 'commit_position': 123,
225 'analysis_approach': 'HEURISTIC'
222 } 226 }
223 ], 227 ],
224 'analysis_approach': 'HEURISTIC', 228 'analysis_approach': 'HEURISTIC',
229 'try_job_status': 'FINISHED',
230 'is_flaky_test': False
225 }, 231 },
226 ] 232 ]
227 233
228 analysis = WfAnalysis.Create(master_name, builder_name, build_number) 234 analysis = WfAnalysis.Create(master_name, builder_name, build_number)
229 analysis.status = analysis_status.RUNNING 235 analysis.status = analysis_status.RUNNING
230 analysis.result = analysis_result 236 analysis.result = analysis_result
231 analysis.put() 237 analysis.put()
232 238
233 response = self.call_api('AnalyzeBuildFailures', body=builds) 239 response = self.call_api('AnalyzeBuildFailures', body=builds)
234 self.assertEqual(200, response.status_int) 240 self.assertEqual(200, response.status_int)
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 'builder_name': builder_name, 337 'builder_name': builder_name,
332 'build_number': build_number, 338 'build_number': build_number,
333 'step_name': 'test', 339 'step_name': 'test',
334 'is_sub_test': False, 340 'is_sub_test': False,
335 'first_known_failed_build_number': 3, 341 'first_known_failed_build_number': 3,
336 'suspected_cls': [ 342 'suspected_cls': [
337 { 343 {
338 'repo_name': 'chromium', 344 'repo_name': 'chromium',
339 'revision': 'git_hash1', 345 'revision': 'git_hash1',
340 'commit_position': 234, 346 'commit_position': 234,
347 'analysis_approach': 'HEURISTIC'
341 }, 348 },
342 { 349 {
343 'repo_name': 'chromium', 350 'repo_name': 'chromium',
344 'revision': 'git_hash2', 351 'revision': 'git_hash2',
345 'commit_position': 288, 352 'commit_position': 288,
353 'analysis_approach': 'HEURISTIC'
346 } 354 }
347 ], 355 ],
348 'analysis_approach': 'HEURISTIC', 356 'analysis_approach': 'HEURISTIC',
357 'is_flaky_test': False,
358 'try_job_status': 'FINISHED'
349 } 359 }
350 ] 360 ]
351 361
352 self._MockMasterIsSupported(supported=True) 362 self._MockMasterIsSupported(supported=True)
353 363
354 response = self.call_api('AnalyzeBuildFailures', body=builds) 364 response = self.call_api('AnalyzeBuildFailures', body=builds)
355 self.assertEqual(200, response.status_int) 365 self.assertEqual(200, response.status_int)
356 self.assertEqual(expected_results, response.json_body.get('results')) 366 self.assertEqual(expected_results, response.json_body.get('results'))
357 367
358 def testTryJobResultReturnedForCompileFailure(self): 368 def testTryJobResultReturnedForCompileFailure(self):
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 'builder_name': builder_name, 432 'builder_name': builder_name,
423 'build_number': build_number, 433 'build_number': build_number,
424 'step_name': 'compile', 434 'step_name': 'compile',
425 'is_sub_test': False, 435 'is_sub_test': False,
426 'first_known_failed_build_number': 3, 436 'first_known_failed_build_number': 3,
427 'suspected_cls': [ 437 'suspected_cls': [
428 { 438 {
429 'repo_name': 'chromium', 439 'repo_name': 'chromium',
430 'revision': 'r3', 440 'revision': 'r3',
431 'commit_position': 3, 441 'commit_position': 3,
442 'analysis_approach': 'TRY_JOB'
432 }, 443 },
433 ], 444 ],
434 'analysis_approach': 'TRY_JOB', 445 'analysis_approach': 'TRY_JOB',
446 'is_flaky_test': False,
447 'try_job_status': 'FINISHED'
435 } 448 }
436 ] 449 ]
437 450
438 self._MockMasterIsSupported(supported=True) 451 self._MockMasterIsSupported(supported=True)
439 452
440 response = self.call_api('AnalyzeBuildFailures', body=builds) 453 response = self.call_api('AnalyzeBuildFailures', body=builds)
441 self.assertEqual(200, response.status_int) 454 self.assertEqual(200, response.status_int)
442 self.assertEqual(expected_results, response.json_body.get('results')) 455 self.assertEqual(expected_results, response.json_body.get('results'))
443 456
444 def testTestLevelResultIsReturned(self): 457 def testTryJobIsRunning(self):
445 master_name = 'm' 458 master_name = 'm'
446 builder_name = 'b' 459 builder_name = 'b'
447 build_number = 5 460 build_number = 5
461
462 master_url = 'https://build.chromium.org/p/%s' % master_name
463 builds = {
464 'builds': [
465 {
466 'master_url': master_url,
467 'builder_name': builder_name,
468 'build_number': build_number
469 }
470 ]
471 }
472
473 try_job = WfTryJob.Create(master_name, builder_name, 3)
474 try_job.status = analysis_status.RUNNING
475 try_job.put()
476
477 analysis = WfAnalysis.Create(master_name, builder_name, build_number)
478 analysis.status = analysis_status.COMPLETED
479 analysis.build_failure_type = failure_type.COMPILE
480 analysis.failure_result_map = {
481 'compile': '/'.join([master_name, builder_name, '3']),
482 }
483 analysis.result = {
484 'failures': [
485 {
486 'step_name': 'compile',
487 'first_failure': 3,
488 'last_pass': 1,
489 'suspected_cls': [
490 {
491 'build_number': 3,
492 'repo_name': 'chromium',
493 'revision': 'git_hash2',
494 'commit_position': 288,
495 'score': 1,
496 'hints': {
497 'modify d/e/f.cc': 1,
498 }
499 }
500 ]
501 }
502 ]
503 }
504 analysis.put()
505
506 expected_results = [
507 {
508 'master_url': master_url,
509 'builder_name': builder_name,
510 'build_number': build_number,
511 'step_name': 'compile',
512 'is_sub_test': False,
513 'first_known_failed_build_number': 3,
514 'suspected_cls': [
515 {
516 'repo_name': 'chromium',
517 'revision': 'git_hash2',
518 'commit_position': 288,
519 'analysis_approach': 'HEURISTIC'
520 },
521 ],
522 'analysis_approach': 'HEURISTIC',
523 'is_flaky_test': False,
524 'try_job_status': 'RUNNING'
525 }
526 ]
527
528 self._MockMasterIsSupported(supported=True)
529
530 response = self.call_api('AnalyzeBuildFailures', body=builds)
531 self.assertEqual(200, response.status_int)
532 self.assertEqual(expected_results, response.json_body.get('results'))
533
534 def testTestIsFlaky(self):
535 master_name = 'm'
536 builder_name = 'b'
537 build_number = 5
538
539 master_url = 'https://build.chromium.org/p/%s' % master_name
540 builds = {
541 'builds': [
542 {
543 'master_url': master_url,
544 'builder_name': builder_name,
545 'build_number': build_number
546 }
547 ]
548 }
549
550 task = WfSwarmingTask.Create(master_name, builder_name, 3, 'b on platform')
551 task.tests_statuses = {
552 'Unittest3.Subtest1': {
553 'total_run': 4,
554 'SUCCESS': 2,
555 'FAILURE': 2
556 }
557 }
558 task.put()
559
560 analysis = WfAnalysis.Create(master_name, builder_name, build_number)
561 analysis.status = analysis_status.COMPLETED
562 analysis.failure_result_map = {
563 'b on platform': {
564 'Unittest3.Subtest1': '/'.join([master_name, builder_name, '3']),
565 },
566 }
567 analysis.result = {
568 'failures': [
569 {
570 'step_name': 'b on platform',
571 'first_failure': 3,
572 'last_pass': 2,
573 'suspected_cls': [],
574 'tests': [
575 {
576 'test_name': 'Unittest3.Subtest1',
577 'first_failure': 3,
578 'last_pass': 2,
579 'suspected_cls': []
580 }
581 ]
582 }
583 ]
584 }
585 analysis.put()
586
587 expected_results = [
588 {
589 'master_url': master_url,
590 'builder_name': builder_name,
591 'build_number': build_number,
592 'step_name': 'b on platform',
593 'is_sub_test': True,
594 'test_name': 'Unittest3.Subtest1',
595 'first_known_failed_build_number': 3,
596 'analysis_approach': 'HEURISTIC',
597 'is_flaky_test': True,
598 'try_job_status': 'FINISHED'
599 }
600 ]
601
602 self._MockMasterIsSupported(supported=True)
603
604 response = self.call_api('AnalyzeBuildFailures', body=builds)
605 self.assertEqual(200, response.status_int)
606 self.assertEqual(expected_results, response.json_body.get('results'))
607
608 @mock.patch.object(suspected_cl_util, 'GetSuspectedCLConfidenceScore')
609 def testTestLevelResultIsReturned(self, mock_fn):
610 master_name = 'm'
611 builder_name = 'b'
612 build_number = 5
448 613
449 master_url = 'https://build.chromium.org/p/%s' % master_name 614 master_url = 'https://build.chromium.org/p/%s' % master_name
450 builds = { 615 builds = {
451 'builds': [ 616 'builds': [
452 { 617 {
453 'master_url': master_url, 618 'master_url': master_url,
454 'builder_name': builder_name, 619 'builder_name': builder_name,
455 'build_number': build_number 620 'build_number': build_number
456 } 621 }
457 ] 622 ]
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 'first_failure': 4, 751 'first_failure': 4,
587 'last_pass': 2, 752 'last_pass': 2,
588 'suspected_cls': [] 753 'suspected_cls': []
589 } 754 }
590 ] 755 ]
591 } 756 }
592 ] 757 ]
593 } 758 }
594 analysis.put() 759 analysis.put()
595 760
761 suspected_cl_42 = WfSuspectedCL.Create('chromium', 'r4_2', 42)
762 suspected_cl_42.builds = {
763 BaseBuildModel.CreateBuildId(master_name, builder_name, 4): {
764 'approaches': [analysis_approach_type.TRY_JOB]
765 }
766 }
767 suspected_cl_42.put()
768
769 suspected_cl_21 = WfSuspectedCL.Create('chromium', 'r2_1', None)
770 suspected_cl_21.builds = {
771 BaseBuildModel.CreateBuildId(master_name, builder_name, build_number): {
772 'approaches': [analysis_approach_type.HEURISTIC],
773 'top_score': 5
774 }
775 }
776 suspected_cl_21.put()
777
778 def confidence_side_effect(_, build_info):
779 if build_info.get('top_score'):
780 return 90
781 return 98
782
783 mock_fn.side_effect = confidence_side_effect
784
596 expected_results = [ 785 expected_results = [
597 { 786 {
598 'master_url': master_url, 787 'master_url': master_url,
599 'builder_name': builder_name, 788 'builder_name': builder_name,
600 'build_number': build_number, 789 'build_number': build_number,
601 'step_name': 'a', 790 'step_name': 'a',
602 'is_sub_test': False, 791 'is_sub_test': False,
603 'first_known_failed_build_number': 4, 792 'first_known_failed_build_number': 4,
604 'suspected_cls': [ 793 'suspected_cls': [
605 { 794 {
606 'repo_name': 'chromium', 795 'repo_name': 'chromium',
607 'revision': 'r4_2', 796 'revision': 'r4_2',
608 'commit_position': 42, 797 'commit_position': 42,
798 'confidence': 98,
799 'analysis_approach': 'TRY_JOB'
609 } 800 }
610 ], 801 ],
611 'analysis_approach': 'TRY_JOB', 802 'analysis_approach': 'TRY_JOB',
803 'is_flaky_test': False,
804 'try_job_status': 'FINISHED'
612 }, 805 },
613 { 806 {
614 'master_url': master_url, 807 'master_url': master_url,
615 'builder_name': builder_name, 808 'builder_name': builder_name,
616 'build_number': build_number, 809 'build_number': build_number,
617 'step_name': 'b on platform', 810 'step_name': 'b on platform',
618 'is_sub_test': True, 811 'is_sub_test': True,
619 'test_name': 'Unittest1.Subtest1', 812 'test_name': 'Unittest1.Subtest1',
620 'first_known_failed_build_number': 3, 813 'first_known_failed_build_number': 3,
621 'suspected_cls': [ 814 'suspected_cls': [
622 { 815 {
623 'repo_name': 'chromium', 816 'repo_name': 'chromium',
624 'revision': 'r2_1', 817 'revision': 'r2_1',
818 'confidence': 90,
819 'analysis_approach': 'HEURISTIC'
625 } 820 }
626 ], 821 ],
627 'analysis_approach': 'HEURISTIC', 822 'analysis_approach': 'HEURISTIC',
823 'is_flaky_test': False,
824 'try_job_status': 'FINISHED'
628 }, 825 },
629 { 826 {
630 'master_url': master_url, 827 'master_url': master_url,
631 'builder_name': builder_name, 828 'builder_name': builder_name,
632 'build_number': build_number, 829 'build_number': build_number,
633 'step_name': 'b on platform', 830 'step_name': 'b on platform',
634 'is_sub_test': True, 831 'is_sub_test': True,
635 'test_name': 'Unittest2.Subtest1', 832 'test_name': 'Unittest2.Subtest1',
636 'first_known_failed_build_number': 4, 833 'first_known_failed_build_number': 4,
637 'suspected_cls': [ 834 'suspected_cls': [
638 { 835 {
639 'repo_name': 'chromium', 836 'repo_name': 'chromium',
640 'revision': 'r2_1', 837 'revision': 'r2_1',
838 'confidence': 90,
839 'analysis_approach': 'HEURISTIC'
641 } 840 }
642 ], 841 ],
643 'analysis_approach': 'HEURISTIC', 842 'analysis_approach': 'HEURISTIC',
843 'is_flaky_test': False,
844 'try_job_status': 'FINISHED'
644 }, 845 },
645 { 846 {
646 'master_url': master_url, 847 'master_url': master_url,
647 'builder_name': builder_name, 848 'builder_name': builder_name,
648 'build_number': build_number, 849 'build_number': build_number,
649 'step_name': 'b on platform', 850 'step_name': 'b on platform',
650 'is_sub_test': True, 851 'is_sub_test': True,
651 'test_name': 'Unittest3.Subtest1', 852 'test_name': 'Unittest3.Subtest1',
652 'first_known_failed_build_number': 4, 853 'first_known_failed_build_number': 4,
653 'suspected_cls': [ 854 'suspected_cls': [
654 { 855 {
655 'repo_name': 'chromium', 856 'repo_name': 'chromium',
656 'revision': 'r4_10', 857 'revision': 'r4_10',
657 'commit_position': 410, 858 'commit_position': 410,
859 'analysis_approach': 'TRY_JOB'
658 } 860 }
659 ], 861 ],
660 'analysis_approach': 'TRY_JOB', 862 'analysis_approach': 'TRY_JOB',
863 'is_flaky_test': False,
864 'try_job_status': 'FINISHED'
661 } 865 }
662 ] 866 ]
663 867
664 self._MockMasterIsSupported(supported=True) 868 self._MockMasterIsSupported(supported=True)
665 869
666 response = self.call_api('AnalyzeBuildFailures', body=builds) 870 response = self.call_api('AnalyzeBuildFailures', body=builds)
667 self.assertEqual(200, response.status_int) 871 self.assertEqual(200, response.status_int)
668 self.assertEqual(expected_results, response.json_body.get('results')) 872 self.assertEqual(expected_results, response.json_body.get('results'))
669 873
670 def testAnalysisRequestQueuedAsExpected(self): 874 def testAnalysisRequestQueuedAsExpected(self):
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 'builder_name': 'b', 952 'builder_name': 'b',
749 'build_number': 456, 953 'build_number': 456,
750 'step_name': 'name (with patch) on Windows-7-SP1', 954 'step_name': 'name (with patch) on Windows-7-SP1',
751 } 955 }
752 ] 956 ]
753 } 957 }
754 958
755 response = self.call_api('AnalyzeFlake', body=flake) 959 response = self.call_api('AnalyzeFlake', body=flake)
756 self.assertEqual(200, response.status_int) 960 self.assertEqual(200, response.status_int)
757 self.assertTrue(response.json_body.get('analysis_triggered')) 961 self.assertTrue(response.json_body.get('analysis_triggered'))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698