aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/sonar-core-plugin/pom.xml2
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java7
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/dashboards/ProjectIssuesDashboard.java12
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/MissingOverallCoverageDecorator.java82
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/FalsePositiveIssuesWidget.java36
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/IssueFilterWidget.java6
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/ProjectIssueFilterWidget.java46
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/UnresolvedIssuesPerAssigneeWidget.java30
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/custom_measures.html.erb2
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/events.html.erb2
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/hotspots/hotspot_most_violated_rules.html.erb124
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/false_positive_issues.html.erb14
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/issue_filter.html.erb49
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/my_unresolved_issues.html.erb18
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/project_issue_filter.html.erb49
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_per_assignee.html.erb84
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_statuses.html.erb58
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/size.html.erb19
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/dashboards/ProjectIssuesDashboardTest.java2
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/MissingOverallCoverageDecoratorTest.java114
-rw-r--r--plugins/sonar-email-notifications-plugin/pom.xml2
-rw-r--r--plugins/sonar-l10n-en-plugin/pom.xml2
-rw-r--r--plugins/sonar-xoo-plugin/pom.xml2
-rw-r--r--pom.xml24
-rw-r--r--server/pom.xml2
-rw-r--r--server/sonar-process-monitor/pom.xml2
-rw-r--r--server/sonar-process/pom.xml2
-rw-r--r--server/sonar-search/pom.xml2
-rw-r--r--server/sonar-server-benchmarks/pom.xml2
-rw-r--r--server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/Benchmark.java9
-rw-r--r--server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java2
-rw-r--r--server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceDbBenchmarkTest.java4
-rw-r--r--server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceIndexBenchmarkTest.java2
-rw-r--r--server/sonar-server/pom.xml2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/core/computation/dbcleaner/ProjectCleaner.java20
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/Activity.java72
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/ActivityService.java63
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/RubyQProfileActivityService.java17
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/db/ActivityDao.java49
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityDoc.java84
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndex.java151
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndexDefinition.java75
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndexer.java88
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityNormalizer.java81
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityQuery.java41
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityResultSetIterator.java86
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/ws/ActivityMapping.java21
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/activity/ws/SearchAction.java56
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportLog.java63
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportQueue.java130
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContainer.java (renamed from server/sonar-server/src/main/java/org/sonar/server/computation/ComputationComponents.java)32
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContext.java40
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java85
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ComputationThread.java55
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ComputationThreadLauncher.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java188
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueueCleaner.java (renamed from server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportQueueCleaner.java)28
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/db/AnalysisReportDao.java88
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueComputation.java39
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java7
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java71
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/step/PurgeDatastoresStep.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/step/SendIssueNotificationsStep.java17
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/step/SwitchSnapshotStep.java22
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryWsAction.java56
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/IsQueueEmptyWebService.java8
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueWsAction.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportWsAction.java31
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMigration.java19
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/es/BaseIndexer.java52
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java11
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/es/EsClient.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/es/IndexCreator.java14
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/es/IndexDefinitionHash.java8
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/es/IndexDefinitions.java (renamed from server/sonar-server/src/main/java/org/sonar/server/es/IndexRegistry.java)4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/es/NewIndex.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueAuthorizationIndexer.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexer.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueResultSetIterator.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesEmailTemplate.java135
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotification.java54
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesStatistics.java129
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java10
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/InternalPermissionService.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java225
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/properties/ProjectSettingsFactory.java5
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java32
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileActivity.java10
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileActivityQuery.java24
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java27
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java9
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java12
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java5
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java56
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java28
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java10
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/search/Facets.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/search/IndexDefinition.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java35
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/search/StickyFacetBuilder.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineDoc.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexDefinition.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/source/ws/LinesAction.java17
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java11
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexer.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/ws/UsersWs.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/core/computation/dbcleaner/ProjectCleanerTest.java18
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/activity/ActivityBackendMediumTest.java215
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/activity/ActivityServiceMediumTest.java217
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/activity/ActivityServiceTest.java91
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/activity/RubyQProfileActivityServiceTest.java17
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/activity/db/ActivityDaoTest.java120
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityIndexDefinitionTest.java60
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityIndexTest.java111
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityResultSetIteratorTest.java91
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/activity/ws/ActivitiesWebServiceMediumTest.java33
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportLogMediumTest.java96
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportQueueCleanerTest.java67
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportQueueMediumTest.java179
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ComputationContainerTest.java (renamed from sonar-core/src/main/java/org/sonar/core/activity/ActivityLog.java)17
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ComputationContextTest.java (renamed from plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/UnresolvedIssuesStatusesWidget.java)25
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java119
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ComputationThreadLauncherTest.java10
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ComputationThreadTest.java61
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueCleanerTest.java (renamed from plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/MyUnresolvedIssuesWidget.java)36
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java205
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/db/AnalysisReportDaoTest.java55
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueComputationTest.java46
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/ApplyPermissionsStepTest.java14
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/BaseStepTest.java (renamed from server/sonar-server/src/test/java/org/sonar/server/computation/ComputationComponentsTest.java)22
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexComponentsStepTest.java21
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexSourceLinesStepTest.java (renamed from sonar-core/src/main/java/org/sonar/core/activity/Activity.java)30
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexViewsStepTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/ParseReportStepTest.java76
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeDatastoresStepMediumTest.java144
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeDatastoresStepTest.java26
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeRemovedViewsStepTest.java33
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/SendIssueNotificationsStepTest.java31
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/SwitchSnapshotStepTest.java19
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryWsActionMediumTest.java125
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ws/IsQueueEmptyWebServiceTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueWsActionTest.java8
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportWsActionTest.java42
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest.java22
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/es/BulkIndexerTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java9
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/es/IndexCreatorTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/es/IndexDefinitionHashTest.java4
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java14
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java19
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java146
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationTest.java102
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesStatisticsTest.java70
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/properties/ProjectSettingsFactoryTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ActiveRuleChangeMediumTest.java77
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java85
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java50
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java16
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/db/RuleDaoTest.java29
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexMediumTest.java121
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceMediumTest.java35
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/search/BaseIndexTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java160
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java1
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexerTest.java12
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java1
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/activity/index/ActivityResultSetIteratorTest/traverse.xml7
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/ComputationServiceTest/shared.xml2
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/any-analysis-reports.xml11
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml8
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/insert-result.xml6
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_analysis_report.xml5
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_available_analysis.xml20
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_available_analysis_but_another_busy_on_same_project.xml20
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_busy_report_analysis.xml11
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml11
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/pop_oldest_pending.xml12
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select.xml11
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select_oldest_available_report_with_working_reports_older.xml29
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/three_analysis_reports.xml11
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending-result.xml9
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending.xml9
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryWsActionMediumTest/list_history_reports.json19
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/ws/SubmitReportWsActionTest/submit_report.json3
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/index/IssueIndexerTest/index.xml4
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rule.json4
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rules_sticky.json4
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/source/ws/LinesActionTest/show_source.json21
-rw-r--r--server/sonar-web/Gruntfile.coffee75
-rw-r--r--server/sonar-web/package.json5
-rw-r--r--server/sonar-web/pom.xml5
-rw-r--r--server/sonar-web/src/main/hbs/coding-rules/facets/coding-rules-characteristic-facet.hbs18
-rw-r--r--server/sonar-web/src/main/hbs/coding-rules/rule/coding-rules-rule-issues.hbs2
-rw-r--r--server/sonar-web/src/main/hbs/source-viewer/source-viewer-coverage-popup.hbs4
-rw-r--r--server/sonar-web/src/main/hbs/source-viewer/source-viewer-duplication-popup.hbs2
-rw-r--r--server/sonar-web/src/main/hbs/source-viewer/source-viewer.hbs19
-rw-r--r--server/sonar-web/src/main/hbs/widgets/_widget-issue-filter-total.hbs11
-rw-r--r--server/sonar-web/src/main/hbs/widgets/widget-issue-filter-action-plans.hbs22
-rw-r--r--server/sonar-web/src/main/hbs/widgets/widget-issue-filter-assignees.hbs22
-rw-r--r--server/sonar-web/src/main/hbs/widgets/widget-issue-filter-resolutions.hbs22
-rw-r--r--server/sonar-web/src/main/hbs/widgets/widget-issue-filter-severities.hbs19
-rw-r--r--server/sonar-web/src/main/hbs/widgets/widget-issue-filter-statuses.hbs19
-rw-r--r--server/sonar-web/src/main/hbs/widgets/widget-issue-filter.hbs18
-rw-r--r--server/sonar-web/src/main/js/application.js33
-rw-r--r--server/sonar-web/src/main/js/coding-rules/facets/characteristic-facet.js37
-rw-r--r--server/sonar-web/src/main/js/coding-rules/models/state.js4
-rw-r--r--server/sonar-web/src/main/js/common/handlebars-extensions.js33
-rw-r--r--server/sonar-web/src/main/js/nav/search-view.js2
-rw-r--r--server/sonar-web/src/main/js/source-viewer/popups/coverage-popup.js11
-rw-r--r--server/sonar-web/src/main/js/source-viewer/source.js15
-rw-r--r--server/sonar-web/src/main/js/source-viewer/viewer.js48
-rw-r--r--server/sonar-web/src/main/js/tests/e2e/views/layouts/main.jade26
-rw-r--r--server/sonar-web/src/main/js/widgets/bubble-chart.js79
-rw-r--r--server/sonar-web/src/main/js/widgets/issue-filter.js296
-rw-r--r--server/sonar-web/src/main/less/init/misc.less16
-rw-r--r--server/sonar-web/src/main/less/init/tables.less3
-rw-r--r--server/sonar-web/src/main/less/pages/dashboard.less16
-rw-r--r--server/sonar-web/src/main/less/style.less3
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb3
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/helpers/application_helper.rb4
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/helpers/properties_helper.rb4
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/models/project_measure.rb2
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/models/property_type.rb1
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/profiles/changelog.html.erb8
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/settings/_type_USER_LOGIN.html.erb5
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/db/migrate/796_add_uuid_to_analysis_reports.rb32
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-active-severity-facet.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-available-since.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-available-since.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-inheritance-facet.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-no-available-profiles-for-activation.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-no-available-profiles-for-activation.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-quality-profile-facet.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-query-facet.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-query-facet.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-rule-should-have-permalink.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-rule-should-have-permalink.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-activate-profile.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-create-custom-rules.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-create-manual-rules.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-manual-rules.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-delete-custom-rules.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-delete-manual-rules.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-show-custom-rules.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-show-deprecated-label.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-deprecated-label.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-show-details.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-details.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-show-empty-list.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-empty-list.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-show-facets.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-facets.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-show-rule-issues.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-show-rule.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule.js)4
-rw-r--r--server/sonar-web/src/test/js/coding-rules-page-should-show-rules.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rules.js)4
-rw-r--r--server/sonar-web/src/test/js/design-spec.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/design-spec.js)4
-rw-r--r--server/sonar-web/src/test/js/global-issue-filter-widget.js853
-rw-r--r--server/sonar-web/src/test/js/issues-page-should-open-issue-permalink.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink.js)4
-rw-r--r--server/sonar-web/src/test/js/issues-page-spec.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-page-spec.js)28
-rw-r--r--server/sonar-web/src/test/js/project-issue-filter-widget.js221
-rw-r--r--server/sonar-web/src/test/js/quality-gates-spec.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec.js)4
-rw-r--r--server/sonar-web/src/test/js/source-viewer-coverage.js66
-rw-r--r--server/sonar-web/src/test/js/source-viewer-create-manual-issue.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue.js)4
-rw-r--r--server/sonar-web/src/test/js/source-viewer-duplications.js70
-rw-r--r--server/sonar-web/src/test/js/source-viewer-favorite-spec.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-favorite-spec.js)8
-rw-r--r--server/sonar-web/src/test/js/source-viewer-link-to-raw-spec.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-link-to-raw-spec.js)4
-rw-r--r--server/sonar-web/src/test/js/source-viewer-scm.js71
-rw-r--r--server/sonar-web/src/test/js/source-viewer-should-not-show-source-if-no-permission.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-not-show-source-if-no-permission.js)4
-rw-r--r--server/sonar-web/src/test/js/source-viewer-should-open-in-new-window-with-line.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window-with-line.js)4
-rw-r--r--server/sonar-web/src/test/js/source-viewer-should-open-in-new-window.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window.js)4
-rw-r--r--server/sonar-web/src/test/js/source-viewer-spec.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec.js)12
-rw-r--r--server/sonar-web/src/test/js/treemap-spec.js (renamed from server/sonar-web/src/main/js/tests/e2e/tests/treemap-spec.js)3
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-active-severity-facet/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-active-severity-facet/search-BLOCKER.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet/search-BLOCKER.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-active-severity-facet/search-qprofile.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet/search-qprofile.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-active-severity-facet/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-available-since/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-available-since/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-available-since/search-limited.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-available-since/search-limited.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-available-since/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-available-since/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-inherited.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-inherited.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-not-inherited.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-not-inherited.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-overriden.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-overriden.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-qprofile.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-qprofile.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-qprofile2.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-qprofile2.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-no-available-profiles-for-activation/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-no-available-profiles-for-activation/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-no-available-profiles-for-activation/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-no-available-profiles-for-activation/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-no-available-profiles-for-activation/show.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-no-available-profiles-for-activation/show.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-quality-profile-facet/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-quality-profile-facet/search-qprofile-active.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet/search-qprofile-active.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-quality-profile-facet/search-qprofile-inactive.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet/search-qprofile-inactive.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-quality-profile-facet/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-query-facet/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-query-facet/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-query-facet/search-query.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-query-facet/search-query.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-query-facet/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-query-facet/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-rule-permalink/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-rule-permalink/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-rule-permalink/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-rule-permalink/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-rule-permalink/show.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-rule-permalink/show.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-activate-profile/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-activate-profile/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-activate-profile/show-with-profile.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile/show-with-profile.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-activate-profile/show.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile/show.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/search-custom-rules.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/search-custom-rules.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/search-custom-rules2.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/search-custom-rules2.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/show.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/show.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-create-manual-rules/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-manual-rules/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-create-manual-rules/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-manual-rules/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-create-manual-rules/show.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-manual-rules/show.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-delete-custom-rules/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-delete-custom-rules/search-custom-rules.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules/search-custom-rules.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-delete-custom-rules/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-delete-custom-rules/show.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules/show.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-delete-manual-rules/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-delete-manual-rules/search-after.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules/search-after.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-delete-manual-rules/search-before.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules/search-before.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-delete-manual-rules/show.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules/show.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-custom-rules/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-custom-rules/search-custom-rules.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules/search-custom-rules.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-custom-rules/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-custom-rules/show.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules/show.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-deprecated-label/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-deprecated-label/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-deprecated-label/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-deprecated-label/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-details/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-details/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-details/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-details/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-details/show.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-details/show.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-empty-list/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-empty-list/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-empty-list/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-empty-list/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-rule-issues/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-rule-issues/issues-search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues/issues-search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-rule-issues/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues/search.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules-page-should-show-rule-issues/show.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues/show.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules/app.json)0
-rw-r--r--server/sonar-web/src/test/json/coding-rules/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/coding-rules/search.json)0
-rw-r--r--server/sonar-web/src/test/json/design-spec/dependencies.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/design-spec/dependencies.json)0
-rw-r--r--server/sonar-web/src/test/json/design-spec/resources.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/design-spec/resources.json)0
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-resolution.json32
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-status.json32
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/red-issues-by-severity.json32
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-action-plan.json63
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-assignee.json48
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date-limited.json24
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date.json32
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-language.json46
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-project.json62
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-resolution.json32
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-rule.json186
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-severity.json32
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unassigned-issues-by-assignee.json48
-rw-r--r--server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unplanned-issues-by-action-plan.json63
-rw-r--r--server/sonar-web/src/test/json/issues-page-should-open-issue-permalink/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink/app.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-page-should-open-issue-permalink/components-app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink/components-app.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-page-should-open-issue-permalink/lines.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink/lines.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-page-should-open-issue-permalink/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink/search.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/app.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/file-level/components-app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/file-level/components-app.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/file-level/lines.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/file-level/lines.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/file-level/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/file-level/search.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/search-reopened.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/search-reopened.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/search-with-tags.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/search-with-tags.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/search.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/show-open.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/show-open.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/show-resolved.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/show-resolved.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/show-with-tags.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/show-with-tags.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/show.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/show.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/tags-modified.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/tags-modified.json)0
-rw-r--r--server/sonar-web/src/test/json/issues-spec/tags.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/tags.json)0
-rw-r--r--server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-date.json32
-rw-r--r--server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity-with-differential-period.json32
-rw-r--r--server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity.json32
-rw-r--r--server/sonar-web/src/test/json/quality-gates-spec/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec/app.json)0
-rw-r--r--server/sonar-web/src/test/json/quality-gates-spec/list.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec/list.json)0
-rw-r--r--server/sonar-web/src/test/json/quality-gates-spec/show.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec/show.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-coverage/app.json19
-rw-r--r--server/sonar-web/src/test/json/source-viewer-coverage/issues.json14
-rw-r--r--server/sonar-web/src/test/json/source-viewer-coverage/lines.json18
-rw-r--r--server/sonar-web/src/test/json/source-viewer-coverage/test-cases.json17
-rw-r--r--server/sonar-web/src/test/json/source-viewer-create-manual-issue/api-rules-search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/api-rules-search.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-create-manual-issue/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/app.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-create-manual-issue/create-issue.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/create-issue.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-create-manual-issue/issues.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/issues.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-create-manual-issue/lines.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/lines.json)420
-rw-r--r--server/sonar-web/src/test/json/source-viewer-duplications/app.json19
-rw-r--r--server/sonar-web/src/test/json/source-viewer-duplications/duplications.json41
-rw-r--r--server/sonar-web/src/test/json/source-viewer-duplications/issues.json14
-rw-r--r--server/sonar-web/src/test/json/source-viewer-duplications/lines.json22
-rw-r--r--server/sonar-web/src/test/json/source-viewer-scm/app.json19
-rw-r--r--server/sonar-web/src/test/json/source-viewer-scm/issues.json14
-rw-r--r--server/sonar-web/src/test/json/source-viewer-scm/lines.json11
-rw-r--r--server/sonar-web/src/test/json/source-viewer-should-not-show-source-if-no-permission/api-components-app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-not-show-source-if-no-permission/api-components-app.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-should-not-show-source-if-no-permission/api-issues-search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-not-show-source-if-no-permission/api-issues-search.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-should-open-in-new-window/api-components-app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-components-app.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-should-open-in-new-window/api-issues-search.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-issues-search.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-should-open-in-new-window/api-sources-lines.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-sources-lines.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/app-not-logged-in.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/app-not-logged-in.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/app.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/coverage.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/coverage.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/cross-project-duplications.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/cross-project-duplications.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/duplications-in-deleted-files.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/duplications-in-deleted-files.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/duplications.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/duplications.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/issues.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/issues.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/lines.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/lines.json)420
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/resources-without-ncloc-data.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/resources-without-ncloc-data.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/resources.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/resources.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/scm.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/scm.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/source.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/source.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/test-cases.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/test-cases.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/tests/app.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/tests/app.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/tests/lines.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/tests/lines.json)0
-rw-r--r--server/sonar-web/src/test/json/source-viewer-spec/tests/tests.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/tests/tests.json)0
-rw-r--r--server/sonar-web/src/test/json/treemap-spec/treemap-resources.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/treemap-spec/treemap-resources.json)0
-rw-r--r--server/sonar-web/src/test/json/treemap-spec/treemap.json (renamed from server/sonar-web/src/main/js/tests/e2e/tests/treemap-spec/treemap.json)0
-rw-r--r--server/sonar-web/src/test/lib.js (renamed from server/sonar-web/src/main/js/tests/e2e/lib.js)23
-rw-r--r--server/sonar-web/src/test/server-coverage.js30
-rw-r--r--server/sonar-web/src/test/server.js (renamed from server/sonar-web/src/main/js/tests/e2e/server.js)10
-rw-r--r--server/sonar-web/src/test/views/coding-rules.jade (renamed from server/sonar-web/src/main/js/tests/e2e/views/coding-rules.jade)2
-rw-r--r--server/sonar-web/src/test/views/design.jade (renamed from server/sonar-web/src/main/js/tests/e2e/views/design.jade)2
-rw-r--r--server/sonar-web/src/test/views/issue-filter-widget.jade9
-rw-r--r--server/sonar-web/src/test/views/issues.jade (renamed from server/sonar-web/src/main/js/tests/e2e/views/issues.jade)2
-rw-r--r--server/sonar-web/src/test/views/layouts/main.jade67
-rw-r--r--server/sonar-web/src/test/views/quality-gates.jade (renamed from server/sonar-web/src/main/js/tests/e2e/views/quality-gates.jade)2
-rw-r--r--server/sonar-web/src/test/views/source-viewer.jade (renamed from server/sonar-web/src/main/js/tests/e2e/views/source-viewer.jade)2
-rw-r--r--server/sonar-web/src/test/views/treemap.jade (renamed from server/sonar-web/src/main/js/tests/e2e/views/treemap.jade)2
-rw-r--r--server/sonar-ws-client/pom.xml2
-rw-r--r--sonar-application/pom.xml8
-rw-r--r--sonar-batch-maven-compat/pom.xml2
-rw-r--r--sonar-batch-protocol/pom.xml2
-rw-r--r--sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/input/BatchInput.java909
-rw-r--r--sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchReport.java450
-rw-r--r--sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportReader.java (renamed from sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchOutputReader.java)25
-rw-r--r--sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java (renamed from sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchOutputWriter.java)18
-rw-r--r--sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java2
-rw-r--r--sonar-batch-protocol/src/main/protobuf/batch_report.proto7
-rw-r--r--sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportReaderTest.java (renamed from sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchOutputReaderTest.java)58
-rw-r--r--sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportWriterTest.java (renamed from sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchOutputWriterTest.java)37
-rw-r--r--sonar-batch/pom.xml2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/design/DsmDecorator.java1
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java13
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/language/LanguageDistributionDecorator.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java13
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java54
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java16
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java4
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/language/LanguageDistributionDecoratorTest.java15
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java4
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/report/IssuesPublisherTest.java166
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java8
-rw-r--r--sonar-check-api/pom.xml2
-rw-r--r--sonar-colorizer/pom.xml2
-rw-r--r--sonar-core/pom.xml2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/activity/db/ActivityDto.java63
-rw-r--r--sonar-core/src/main/java/org/sonar/core/activity/db/ActivityMapper.java15
-rw-r--r--sonar-core/src/main/java/org/sonar/core/activity/package-info.java24
-rw-r--r--sonar-core/src/main/java/org/sonar/core/component/ComponentDto.java33
-rw-r--r--sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportDto.java29
-rw-r--r--sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportMapper.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleaner.java8
-rw-r--r--sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DeleteAllFilter.java4
-rw-r--r--sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/KeepOneFilter.java4
-rw-r--r--sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java12
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java12
-rw-r--r--sonar-core/src/main/java/org/sonar/core/user/UserDao.java9
-rw-r--r--sonar-core/src/main/java/org/sonar/core/util/MultiSets.java62
-rw-r--r--sonar-core/src/main/java/org/sonar/core/util/NonNullInputFunction.java5
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/activity/db/ActivityMapper.xml35
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/computation/db/AnalysisReportMapper.xml20
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql1
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl7
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties90
-rw-r--r--sonar-core/src/test/java/org/sonar/core/component/ComponentDtoTest.java6
-rw-r--r--sonar-core/src/test/java/org/sonar/core/persistence/DbTester.java9
-rw-r--r--sonar-core/src/test/java/org/sonar/core/util/MultiSetsTest.java49
-rw-r--r--sonar-deprecated/pom.xml2
-rw-r--r--sonar-deprecated/src/main/java/org/sonar/api/rules/XMLRuleParser.java8
-rw-r--r--sonar-duplications/pom.xml2
-rw-r--r--sonar-graph/pom.xml2
-rw-r--r--sonar-home/pom.xml2
-rw-r--r--sonar-java-api/pom.xml2
-rw-r--r--sonar-markdown/pom.xml2
-rw-r--r--sonar-maven-plugin/pom.xml2
-rw-r--r--sonar-maven3-plugin/pom.xml2
-rw-r--r--sonar-plugin-api/pom.xml2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java10
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/PropertyType.java8
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java69
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java24
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java108
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/utils/log/BaseLogger.java42
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/utils/log/ListInterceptor.java33
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogInterceptor.java10
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTester.java12
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/utils/log/NullInterceptor.java10
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/JUnitTempFolderTest.java (renamed from plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/HotspotMostViolatedRulesWidget.java)48
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterTest.java4
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/utils/log/NullInterceptorTest.java10
-rw-r--r--sonar-testing-harness/pom.xml2
498 files changed, 9300 insertions, 5289 deletions
diff --git a/plugins/sonar-core-plugin/pom.xml b/plugins/sonar-core-plugin/pom.xml
index 090c34c4901..f81408953c1 100644
--- a/plugins/sonar-core-plugin/pom.xml
+++ b/plugins/sonar-core-plugin/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<groupId>org.codehaus.sonar.plugins</groupId>
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
index 8dd1801b406..fb064dc3486 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
@@ -256,13 +256,9 @@ public final class CorePlugin extends SonarPlugin {
// issues
CountUnresolvedIssuesDecorator.class,
CountFalsePositivesDecorator.class,
- HotspotMostViolatedRulesWidget.class,
- MyUnresolvedIssuesWidget.class,
- FalsePositiveIssuesWidget.class,
ActionPlansWidget.class,
- UnresolvedIssuesPerAssigneeWidget.class,
- UnresolvedIssuesStatusesWidget.class,
IssueFilterWidget.class,
+ ProjectIssueFilterWidget.class,
IssueTagCloudWidget.class,
// batch
@@ -281,7 +277,6 @@ public final class CorePlugin extends SonarPlugin {
DirectoriesDecorator.class,
FilesDecorator.class,
ManualMeasureDecorator.class,
- MissingOverallCoverageDecorator.class,
// time machine
TendencyDecorator.class,
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/dashboards/ProjectIssuesDashboard.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/dashboards/ProjectIssuesDashboard.java
index 7eb982f3b07..295e62a67a8 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/dashboards/ProjectIssuesDashboard.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/dashboards/ProjectIssuesDashboard.java
@@ -40,19 +40,19 @@ public final class ProjectIssuesDashboard extends DashboardTemplate {
Dashboard dashboard = Dashboard.create();
dashboard.setLayout(DashboardLayout.TWO_COLUMNS);
addFirstColumn(dashboard);
- addSecondColumn(dashboard);
+ addSecondColumn();
return dashboard;
}
private void addFirstColumn(Dashboard dashboard) {
- dashboard.addWidget("unresolved_issues_statuses", 1);
+ // TODO: + unresolved issues by status
dashboard.addWidget("action_plans", 1);
}
- private void addSecondColumn(Dashboard dashboard) {
- dashboard.addWidget("reviews_per_developer", 2);
- dashboard.addWidget("my_reviews", 2);
- dashboard.addWidget("false_positive_reviews", 2);
+ private void addSecondColumn() {
+ // TODO: + unresolved issues by assignee
+ // TODO: + my unresolved issues
+ // TODO: + false positive and won't fix issues
}
}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/MissingOverallCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/MissingOverallCoverageDecorator.java
deleted file mode 100644
index bdae925a865..00000000000
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/MissingOverallCoverageDecorator.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.plugins.core.sensors;
-
-import org.sonar.api.batch.Decorator;
-import org.sonar.api.batch.DecoratorContext;
-import org.sonar.api.batch.DependedUpon;
-import org.sonar.api.batch.DependsUpon;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.CoverageMeasuresBuilder;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasureUtils;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Resource;
-
-import java.util.List;
-
-/**
- * Compute overall coverage when it was not already saved by language plugin.
- */
-public final class MissingOverallCoverageDecorator implements Decorator {
-
- @DependsUpon
- public Metric dependsUpon() {
- return CoreMetrics.LINES_TO_COVER;
- }
-
- @DependedUpon
- public List<Metric> provides() {
- return CoverageMeasuresBuilder.CoverageType.OVERALL.all();
- }
-
- @Override
- public boolean shouldExecuteOnProject(Project project) {
- return true;
- }
-
- @Override
- public void decorate(Resource resource, DecoratorContext context) {
- if (Qualifiers.isFile(resource) && !MeasureUtils.hasValue(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER))) {
- copyMeasure(context, CoreMetrics.LINES_TO_COVER, CoreMetrics.OVERALL_LINES_TO_COVER);
- copyMeasure(context, CoreMetrics.UNCOVERED_LINES, CoreMetrics.OVERALL_UNCOVERED_LINES);
- copyMeasure(context, CoreMetrics.COVERAGE_LINE_HITS_DATA, CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA);
- copyMeasure(context, CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.OVERALL_CONDITIONS_TO_COVER);
- copyMeasure(context, CoreMetrics.UNCOVERED_CONDITIONS, CoreMetrics.OVERALL_UNCOVERED_CONDITIONS);
- copyMeasure(context, CoreMetrics.CONDITIONS_BY_LINE, CoreMetrics.OVERALL_CONDITIONS_BY_LINE);
- copyMeasure(context, CoreMetrics.COVERED_CONDITIONS_BY_LINE, CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE);
- }
- }
-
- private void copyMeasure(DecoratorContext context, Metric<?> from, Metric<?> to) {
- Measure sourceMeasure = context.getMeasure(from);
- if (sourceMeasure != null) {
- Double value = sourceMeasure.getValue();
- if (value != null) {
- context.saveMeasure(to, value);
- } else if (sourceMeasure.hasData()) {
- context.saveMeasure(new Measure(to, sourceMeasure.getData()));
- }
- }
-
- }
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/FalsePositiveIssuesWidget.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/FalsePositiveIssuesWidget.java
deleted file mode 100644
index a37203aef67..00000000000
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/FalsePositiveIssuesWidget.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.plugins.core.widgets.issues;
-
-import org.sonar.api.web.WidgetCategory;
-import org.sonar.api.web.WidgetProperties;
-import org.sonar.api.web.WidgetProperty;
-import org.sonar.api.web.WidgetPropertyType;
-import org.sonar.plugins.core.widgets.CoreWidget;
-
-@WidgetCategory({"Issues"})
-@WidgetProperties({
- @WidgetProperty(key = "numberOfLines", type = WidgetPropertyType.INTEGER, defaultValue = "5")
-})
-public class FalsePositiveIssuesWidget extends CoreWidget {
- public FalsePositiveIssuesWidget() {
- super("false_positive_reviews", "False positive open issues", "/org/sonar/plugins/core/widgets/issues/false_positive_issues.html.erb");
- }
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/IssueFilterWidget.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/IssueFilterWidget.java
index a8baf1053ac..f02fda9677d 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/IssueFilterWidget.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/IssueFilterWidget.java
@@ -28,13 +28,15 @@ import static org.sonar.api.web.WidgetScope.GLOBAL;
@WidgetScope(GLOBAL)
@WidgetProperties({
@WidgetProperty(key = IssueFilterWidget.FILTER_PROPERTY, type = WidgetPropertyType.ISSUE_FILTER, optional = false),
- @WidgetProperty(key = IssueFilterWidget.PAGE_SIZE_PROPERTY, type = WidgetPropertyType.INTEGER, defaultValue = "30"),
+ @WidgetProperty(key = IssueFilterWidget.DISTRIBUTION_AXIS_PROPERTY, type = WidgetPropertyType.SINGLE_SELECT_LIST, defaultValue = "severities",
+ options = {"severities", "resolutions", "statuses", "rules", "tags", "projectUuids", "assignees", "reporters",
+ "authors", "languages", "actionPlans", "createdAt"}),
@WidgetProperty(key = IssueFilterWidget.DISPLAY_FILTER_DESCRIPTION, type = WidgetPropertyType.BOOLEAN, defaultValue = "false")
})
public class IssueFilterWidget extends CoreWidget {
public static final String FILTER_PROPERTY = "filter";
- public static final String PAGE_SIZE_PROPERTY = "numberOfLines";
+ public static final String DISTRIBUTION_AXIS_PROPERTY = "distributionAxis";
public static final String DISPLAY_FILTER_DESCRIPTION = "displayFilterDescription";
public static final String ID = "issue_filter";
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/ProjectIssueFilterWidget.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/ProjectIssueFilterWidget.java
new file mode 100644
index 00000000000..5e45af9272a
--- /dev/null
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/ProjectIssueFilterWidget.java
@@ -0,0 +1,46 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.plugins.core.widgets.issues;
+
+import org.sonar.api.web.*;
+import org.sonar.plugins.core.widgets.CoreWidget;
+
+import static org.sonar.api.web.WidgetScope.PROJECT;
+
+@WidgetCategory({"Filters", "Issues"})
+@WidgetScope(PROJECT)
+@WidgetProperties({
+ @WidgetProperty(key = ProjectIssueFilterWidget.FILTER_PROPERTY, type = WidgetPropertyType.ISSUE_FILTER, optional = false),
+ @WidgetProperty(key = ProjectIssueFilterWidget.DISTRIBUTION_AXIS_PROPERTY, type = WidgetPropertyType.SINGLE_SELECT_LIST, defaultValue = "severities",
+ options = {"severities", "resolutions", "statuses", "rules", "tags", "assignees", "reporters", "authors",
+ "languages", "actionPlans", "createdAt"}),
+ @WidgetProperty(key = ProjectIssueFilterWidget.DISPLAY_FILTER_DESCRIPTION, type = WidgetPropertyType.BOOLEAN, defaultValue = "false")
+})
+public class ProjectIssueFilterWidget extends CoreWidget {
+
+ public static final String FILTER_PROPERTY = "filter";
+ public static final String DISTRIBUTION_AXIS_PROPERTY = "distributionAxis";
+ public static final String DISPLAY_FILTER_DESCRIPTION = "displayFilterDescription";
+ public static final String ID = "project_issue_filter";
+
+ public ProjectIssueFilterWidget() {
+ super(ID, "Project Issue Filter", "/org/sonar/plugins/core/widgets/issues/project_issue_filter.html.erb");
+ }
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/UnresolvedIssuesPerAssigneeWidget.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/UnresolvedIssuesPerAssigneeWidget.java
deleted file mode 100644
index a8f8e8d41e6..00000000000
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/UnresolvedIssuesPerAssigneeWidget.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.plugins.core.widgets.issues;
-
-import org.sonar.api.web.WidgetCategory;
-import org.sonar.plugins.core.widgets.CoreWidget;
-
-@WidgetCategory({"Issues"})
-public class UnresolvedIssuesPerAssigneeWidget extends CoreWidget {
- public UnresolvedIssuesPerAssigneeWidget() {
- super("reviews_per_developer", "Unresolved issues per assignee", "/org/sonar/plugins/core/widgets/issues/unresolved_issues_per_assignee.html.erb");
- }
-}
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/custom_measures.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/custom_measures.html.erb
index 6f084e38350..3ea96e27bd8 100644
--- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/custom_measures.html.erb
+++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/custom_measures.html.erb
@@ -18,7 +18,7 @@
<p class="widget-measure widget-measure-main">
<span class="widget-label"><%= measure.metric.short_name -%></span>
<span class="nowrap">
- <% if measure.value.nil? -%>
+ <% if measure.value.nil? && measure.text_value.nil? -%>
<%= format_measure(measure, :url => url_for_drilldown(measure, :period => period), :period => period) -%>
<% else %>
<%= format_measure(measure, :url => url_for_drilldown(measure)) -%>
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/events.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/events.html.erb
index 1ee56e96fcf..9f0381f48cb 100644
--- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/events.html.erb
+++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/events.html.erb
@@ -111,7 +111,7 @@
<span class="empty_widget"><%= message('widget.events.no_event') -%></span>
</div>
-<a href="#" onclick="showAllEvents(<%= widget.id -%>);" id="show_more_events_<%= widget.id -%>" class="action"><%= message('widget.events.show_more') -%></a>
+<a href="#" onclick="showAllEvents(<%= widget.id -%>);return false;" id="show_more_events_<%= widget.id -%>" class="action"><%= message('widget.events.show_all') -%></a>
<script type="text/javascript">
changeCategory('all', <%= widget.id -%>);
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/hotspots/hotspot_most_violated_rules.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/hotspots/hotspot_most_violated_rules.html.erb
deleted file mode 100644
index d30b7b700db..00000000000
--- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/hotspots/hotspot_most_violated_rules.html.erb
+++ /dev/null
@@ -1,124 +0,0 @@
-<%
- limit = widget_properties["numberOfLines"]
- metric_prefix = dashboard_configuration.selected_period? ? 'new_' : ''
- value_column = (dashboard_configuration.selected_period? ? "variation_value_#{dashboard_configuration.period_index}" : 'value')
- measures_by_severity = {}
- all_measures=[]
-
- Severity::KEYS.each do |key|
- rule_measures = @snapshot.rule_measures(Metric.by_key("#{metric_prefix}#{key.downcase}_violations"))
- sorted_measures = rule_measures.select { |a|
- val = a.send(value_column)
- val && val>0
- }.sort { |a, b| b.send(value_column) <=> a.send(value_column) }[0...limit]
- measures_by_severity[key] = sorted_measures
- all_measures.concat(sorted_measures)
- end
- measures_by_severity['all']=all_measures.sort { |a, b| b.send(value_column) <=> a.send(value_column) }[0...limit]
-
- default_severity = widget_properties['defaultSeverity']
- default_severity = 'all' unless Severity::KEYS.include?(default_severity)
-%>
-
-<script type="text/javascript">
- function showMostViolatedRules<%= widget.id -%>(severity) {
- $j('#block_<%= widget.id-%> div.hotspot').hide();
- $j('#most-violated-rules-<%= widget.id -%>-' + severity).show();
- }
-
- function severityForLink() {
- var severity = $j('#select-severity_<%= widget.id -%>').val();
- if (severity == 'all') {
- return '';
- } else {
- return severity;
- }
- }
-</script>
-
-<div class="line-block">
- <div style="float:right">
- <a class="underlined-link" href="#" onclick="window.location.href='<%= url_for(:controller => 'drilldown', :action => 'issues') -%>/<%= @resource.id -%>?period=<%= dashboard_configuration.period_index -%>&severity=' + severityForLink() ">
- <%= message('widget.hotspot_metric.more') -%>
- </a>
- </div>
- <h3>
- <%= message(dashboard_configuration.selected_period? ? 'widget.hotspot_most_violated_rules.name_when_period' : 'widget.hotspot_most_violated_rules.name') %>
-
- <select class="small withIcons" style="margin-left: 20px" onchange="showMostViolatedRules<%= widget.id -%>(this.value);" id="select-severity_<%= widget.id -%>">
- <option value="all" <%= 'selected' if default_severity=='all' -%>><%= message('widget.hotspot_most_violated_rules.any_severity') -%></option>
- <% Severity::KEYS.each do |key| %>
- <option class="sev_<%= key -%>" value="<%= key -%>" <%= 'selected' if default_severity==key -%>><%= message("severity.#{key}") -%></option>
- <% end %>
- </select>
-
- <script>
- $j(function() {
- $j('#select-severity_<%= widget.id -%>').select2({ width: '130px' });
- });
- </script>
- </h3>
-</div>
-
-
-<div>
- <%
- measures_by_severity.each do |severity, measures|
- if measures.empty?
- %>
-
- <div id="most-violated-rules-<%= widget.id -%>-<%= severity -%>" class="hotspot" style="padding-top:10px">
- <span class="empty_widget"><%= message('widget.hotspot_most_violated_rules.no_violation_for_severity') -%></span>
- </div>
-
- <%
- else
- %>
-
- <div id="most-violated-rules-<%= widget.id -%>-<%= severity -%>" class="hotspot">
- <table class="data">
- <thead>
- <tr>
- <th colspan="3"></th>
- </tr>
- </thead>
- <tbody>
- <%
- max_value = measures.first.send(value_column)
- measures.each do |m|
- rule = m.rule
- value = m.send(value_column)
- %>
- <tr class="<%= cycle 'even', 'odd', :name => ("hotspot_most_violated_rules-#{widget.id}-#{severity}") -%>">
- <td class="thin">
- <i class="icon-severity-<%= m.severity.downcase -%>"></i>
- </td>
- <td>
- <%= h rule.name -%>
- </td>
- <td class="right nowrap">
- <a class="underlined-link <%= widget.key %>_<%= rule.key.parameterize %>" href="<%= url_for(:controller => 'drilldown', :action => 'issues', :id => @resource.key, :rule => rule.key, :rule_sev => m.severity, :period => dashboard_configuration.period_index) -%>">
- <%= dashboard_configuration.selected_period? ? format_variation(m) : format_measure(m) -%>
- </a>
- </td>
- <td class="barchart">
- <div class="barchart" style="width: <%= (value*100/max_value).round.to_i -%>%">
- <div style="width: 100%;"></div>
- </div>
- </td>
- </tr>
- <%
- end
- %>
- </tbody>
- </table>
- </div>
-
- <%
- end
- end
- %>
-</div>
-<script type="text/javascript">
- showMostViolatedRules<%= widget.id -%>("<%= default_severity -%>");
-</script>
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/false_positive_issues.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/false_positive_issues.html.erb
deleted file mode 100644
index bd32fb74fb9..00000000000
--- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/false_positive_issues.html.erb
+++ /dev/null
@@ -1,14 +0,0 @@
-<%
- if has_role?(:user, @project)
-
- search_options = {}
- search_options['componentUuids'] = @project.uuid
- search_options['resolutions'] = 'FALSE-POSITIVE'
- title = message('widget.false_positive_reviews.name')
-%>
-
- <%= render :partial => 'project/widgets/issues/issues_list_widget',
- :locals => {:search_options => search_options, :title => title,
- :widget_id => widget.id.to_s, :widget_properties => widget_properties} %>
-
-<% end %>
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/issue_filter.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/issue_filter.html.erb
index 9f0dfa07851..0836a22ad9d 100644
--- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/issue_filter.html.erb
+++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/issue_filter.html.erb
@@ -1,25 +1,38 @@
<%
+ container_id = 'widget-issue-filter-' + widget.id.to_s
filter_id = widget_properties['filter']
filter = Internal.issues.findIssueFilterById(filter_id.to_i)
- if filter
- if Internal.issues.isUserAuthorized(filter)
- search_options = {}
- search_options['filter'] = filter_id
- @widget_title = link_to h(filter.name), {:controller => 'issues', :action => 'filter', :id => filter.id}
+ distribution_axis = widget_properties['distributionAxis']
%>
+
+<% if filter %>
+ <% if Internal.issues.isUserAuthorized(filter) %>
+
+ <% @widget_title = "<a href=\"#{url_for({:controller => 'issues', :action => 'index'})}#id=#{filter.id}\">#{h(filter.name)}</a>" %>
<% if widget_properties['displayFilterDescription'] && !filter.description.blank? %>
- <div style="padding-bottom: 5px">
- <span class="note"><%= h filter.description -%></span>
- </div>
+ <p class="note spacer-bottom"><%= h filter.description -%></p>
<% end %>
- <%= render :partial => 'project/widgets/issues/issues_list_widget',
- :locals => {:search_options => search_options, :widget_id => widget.id.to_s, :widget_properties => widget_properties} %>
- <%
- end
- else
- %>
- <p><%= image_tag 'warning.png' %> <%= message 'widget.issue_filter.unknown_filter_warning' -%></p>
-<%
- end
-%>
+ <div id="<%= container_id -%>"></div>
+ <script>
+ require(['widgets/issue-filter'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#<%= container_id -%>',
+ query: '<%= filter.data -%>',
+ distributionAxis: '<%= distribution_axis -%>'
+ });
+ });
+ });
+ </script>
+
+ <% else %>
+
+ <p class="message-alert"><%= message 'widget.issue_filter.insufficient_privileges_warning' -%></p>
+
+ <% end %>
+<% else %>
+
+ <p class="message-alert"><%= message 'widget.issue_filter.unknown_filter_warning' -%></p>
+
+<% end %>
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/my_unresolved_issues.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/my_unresolved_issues.html.erb
deleted file mode 100644
index c73cefa4d44..00000000000
--- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/my_unresolved_issues.html.erb
+++ /dev/null
@@ -1,18 +0,0 @@
-<%
- if current_user && (!@project || has_role?(:user, @project))
-
- search_options = {}
- if @project
- search_options['componentUuids'] = @project.uuid
- end
- search_options['resolved'] = 'false'
- search_options['assignees'] = current_user.login
-
- title = message('widget.my_reviews.name')
-%>
-
- <%= render :partial => 'project/widgets/issues/issues_list_widget',
- :locals => {:search_options => search_options, :title => title,
- :widget_id => widget.id.to_s, :widget_properties => widget_properties} %>
-
-<% end %>
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/project_issue_filter.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/project_issue_filter.html.erb
new file mode 100644
index 00000000000..c68f07565ce
--- /dev/null
+++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/project_issue_filter.html.erb
@@ -0,0 +1,49 @@
+<%
+ container_id = 'widget-issue-filter-' + widget.id.to_s
+ filter_id = widget_properties['filter']
+ filter = Internal.issues.findIssueFilterById(filter_id.to_i)
+ distribution_axis = widget_properties['distributionAxis']
+
+ if @dashboard_configuration.selected_period?
+ period_date = @snapshot.period_datetime(@dashboard_configuration.period_index).strftime('%FT%T%z')
+ else
+ period_date = nil
+ end
+%>
+
+<% if filter %>
+ <% if Internal.issues.isUserAuthorized(filter) %>
+
+ <% @widget_title = "<a href=\"#{url_for({:controller => 'component_issues', :action => 'index'})}?id=#{u(@project.key)}##{filter.data}\">#{h(filter.name)}</a>" %>
+ <% if widget_properties['displayFilterDescription'] && !filter.description.blank? %>
+ <p class="note spacer-bottom"><%= h filter.description -%></p>
+ <% end %>
+
+ <div id="<%= container_id -%>"></div>
+ <script>
+ require(['widgets/issue-filter'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#<%= container_id -%>',
+ query: '<%= filter.data -%>',
+ distributionAxis: '<%= distribution_axis -%>',
+ <% if period_date %>
+ periodDate: '<%= period_date -%>',
+ <% end %>
+ componentUuid: '<%= @project.uuid -%>',
+ componentKey: '<%= @project.key -%>'
+ });
+ });
+ });
+ </script>
+
+ <% else %>
+
+ <p class="message-alert"><%= message 'widget.issue_filter.insufficient_privileges_warning' -%></p>
+
+ <% end %>
+<% else %>
+
+ <p class="message-alert"><%= message 'widget.issue_filter.unknown_filter_warning' -%></p>
+
+<% end %>
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_per_assignee.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_per_assignee.html.erb
deleted file mode 100644
index 1dcab1fbeae..00000000000
--- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_per_assignee.html.erb
+++ /dev/null
@@ -1,84 +0,0 @@
-<%
- options = {}
- options['resolved'] = 'false'
- options['componentUuids'] = @project.uuid
- if @dashboard_configuration.selected_period?
- options['createdAfter'] = Api::Utils.format_datetime(@dashboard_configuration.from_datetime)
- options['createdBefore'] = Api::Utils.format_datetime(DateTime.now)
- end
- issues_by_assignee = Internal.issues.findIssueAssignees(options)
-
- unless issues_by_assignee.empty?
- users = Internal.users_api.find({'logins', issues_by_assignee.keySet(), 'includeDeactivated', true})
- users_by_login = {}
- users.each do |u|
- users_by_login[u.login()] = u
- end
-
- counter_no_assignee = issues_by_assignee.get(nil)
- counter_max = 0
- counter_max = issues_by_assignee.values().max unless issues_by_assignee.empty?
- counter_max = counter_no_assignee if counter_no_assignee > counter_max
-
- div_id = "unresolved-issues-per-assignee-widget-#{widget.id.to_s}"
- end
-%>
-
-<h3><%= message('widget.reviews_per_developer.name') -%></h3>
-
-<% if issues_by_assignee.size ==0 %>
- <span class="empty_widget"><%= message('issue_filter.no_issues') -%></span>
-
-<% else %>
-<div id="<%= div_id -%>">
-
- <table class="data width100">
- <thead>
- <tr>
- <th coslpan="3">
- </th>
- </tr>
- </thead>
- <tbody>
- <%
- issues_by_assignee.each do |assignee, count|
- if assignee
- %>
- <tr class="<%= cycle 'even', 'odd', :name => (div_id) -%>">
- <td class="max-width">
- <%= link_to users_by_login[assignee].name(), url_for_component_issues(@project, options.merge(:assignees => assignee)) -%>
- </td>
- <td class="nowrap">
- <%= '+' if @dashboard_configuration.selected_period? -%><%= count.to_s -%>
- </td>
- <% if counter_max > 0 %>
- <td>
- <%= barchart(:width => 100, :percent => (100 * count / counter_max).to_i) %>
- </td>
- <% end %>
- </tr>
- <%
- # And now show the unassigned issues counter
- else
- %>
- <tr class="<%= cycle 'even', 'odd', :name => (div_id) -%>">
- <td class="max-width">
- <%= link_to message('widget.reviews_per_developer.not_assigned'), url_for_component_issues(@project, options.merge(:assigned => 'false')) -%>
- </td>
- <td class="nowrap">
- <%= '+' if @dashboard_configuration.selected_period? -%><%= counter_no_assignee.to_s -%>
- </td>
- <% if counter_max > 0 %>
- <td>
- <%= barchart(:width => 100, :percent => (100 * counter_no_assignee / counter_max).to_i) %>
- </td>
- <% end %>
- </tr>
- <% end
- end %>
- </tbody>
- </table>
-
-</div>
-
-<% end %>
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_statuses.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_statuses.html.erb
deleted file mode 100644
index 782472f4575..00000000000
--- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_statuses.html.erb
+++ /dev/null
@@ -1,58 +0,0 @@
-<%
- issues = @snapshot.measure('violations')
- open_issues = @snapshot.measure('open_issues')
- reopened_issues = @snapshot.measure('reopened_issues')
- confirmed_issues = @snapshot.measure('confirmed_issues')
-
- issues_search_options = {}
- issues_search_options['resolved'] = 'false'
- issues_search_options['componentUuids'] = @project.uuid
-%>
-<table width="100%">
- <tr>
- <td valign="top" width="25%">
- <div class="dashbox">
- <h3><%= message('issues') -%></h3>
- <div class="marginbottom10">
- <span class="big">
- <%= format_measure(issues, :url => url_for_component_issues(@project, issues_search_options)) -%>
- </span>
- <%= dashboard_configuration.selected_period? ? format_variation(issues) : trend_icon(issues) -%>
- </div>
- </div>
- </td>
- <td valign="top" width="25%">
- <div class="dashbox">
- <h3><%= message('issue.status.OPEN') -%></h3>
- <div class="marginbottom10">
- <span class="big">
- <%= format_measure(open_issues, :url => url_for_component_issues(@project, issues_search_options.merge(:statuses => 'OPEN'))) -%>
- </span>
- <%= dashboard_configuration.selected_period? ? format_variation(open_issues) : trend_icon(open_issues) -%>
- </div>
- </div>
- </td>
- <td valign="top" width="25%">
- <div class="dashbox">
- <h3><%= message('issue.status.REOPENED') -%></h3>
- <div class="marginbottom10">
- <span class="big">
- <%= format_measure(reopened_issues, :url => url_for_component_issues(@project, issues_search_options.merge(:statuses => 'REOPENED'))) -%>
- </span>
- <%= dashboard_configuration.selected_period? ? format_variation(reopened_issues) : trend_icon(reopened_issues) -%>
- </div>
- </div>
- </td>
- <td valign="top" width="25%">
- <div class="dashbox">
- <h3><%= message('issue.status.CONFIRMED') -%></h3>
- <div class="marginbottom10">
- <span class="big">
- <%= format_measure(confirmed_issues, :url => url_for_component_issues(@project, issues_search_options.merge(:statuses => 'CONFIRMED'))) -%>
- </span>
- <%= dashboard_configuration.selected_period? ? format_variation(confirmed_issues) : trend_icon(confirmed_issues) -%>
- </div>
- </div>
- </td>
- </tr>
-</table>
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/size.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/size.html.erb
index 0a28f86c05c..9e0797f8005 100644
--- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/size.html.erb
+++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/size.html.erb
@@ -49,8 +49,12 @@
%>
<tr>
<td>
- <% language = languages.find { |l| l.getKey()==language_key.to_s } -%>
- <%= language ? language.getName() : language_key -%>
+ <% if language_key.eql? '<null>' %>
+ <%= message('other') -%>
+ <% else %>
+ <% language = languages.find { |l| l.getKey()==language_key.to_s } -%>
+ <%= language ? language.getName() : language_key -%>
+ <% end %>
</td>
<td class="thin right nowrap">
<%= ncloc.format_numeric_value(language_ncloc) %>
@@ -73,11 +77,14 @@
});
</script>
<% else %>
- <%
+ <%
language_key = ncloc_language_dist_hash.first[0]
- language = languages.find { |l| l.getKey()==language_key.to_s }
- -%>
- <%= language ? language.getName() : language_key -%>
+ if language_key.eql? '<null>' %>
+ <%= message('other') -%>
+ <% else %>
+ <% language = languages.find { |l| l.getKey()==language_key.to_s } -%>
+ <%= language ? language.getName() : language_key -%>
+ <% end %>
<% end %>
<% end %>
<% else %>
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/dashboards/ProjectIssuesDashboardTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/dashboards/ProjectIssuesDashboardTest.java
index 364c0d8f1df..7aa7d11bae0 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/dashboards/ProjectIssuesDashboardTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/dashboards/ProjectIssuesDashboardTest.java
@@ -46,7 +46,7 @@ public class ProjectIssuesDashboardTest {
Dashboard dashboard = template.createDashboard();
assertThat(dashboard.getLayout()).isEqualTo(DashboardLayout.TWO_COLUMNS);
- assertThat(dashboard.getWidgets()).hasSize(5);
+ assertThat(dashboard.getWidgets()).hasSize(1);
}
}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/MissingOverallCoverageDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/MissingOverallCoverageDecoratorTest.java
deleted file mode 100644
index c94eb3bce52..00000000000
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/MissingOverallCoverageDecoratorTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.plugins.core.sensors;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.batch.DecoratorContext;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.resources.Directory;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Java;
-import org.sonar.api.resources.Project;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.anyDouble;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-public class MissingOverallCoverageDecoratorTest {
-
- private MissingOverallCoverageDecorator decorator;
-
- @Before
- public void prepare() {
- decorator = new MissingOverallCoverageDecorator();
- }
-
- @Test
- public void increaseCoverage() {
- assertThat(decorator.provides()).isNotEmpty();
- assertThat(decorator.dependsUpon()).isEqualTo(CoreMetrics.LINES_TO_COVER);
- assertThat(decorator.shouldExecuteOnProject(new Project("foo"))).isTrue();
- }
-
- @Test
- public void testExecuteOnlyOnMainFile() {
- DecoratorContext context = mock(DecoratorContext.class);
- decorator.decorate(File.create("test/FooTest.java", Java.INSTANCE, true), context);
- decorator.decorate(Directory.create("src"), context);
- decorator.decorate(new Project("foo"), context);
- verifyNoMoreInteractions(context);
- }
-
- @Test
- public void dontDoAnythingIfOverallCoverageAlreadyDefined() {
- DecoratorContext context = mock(DecoratorContext.class);
- File file = File.create("src/Foo.java");
-
- when(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER)).thenReturn(new Measure<>(CoreMetrics.OVERALL_LINES_TO_COVER, 0.0));
-
- decorator.decorate(file, context);
-
- verify(context, never()).saveMeasure(eq(CoreMetrics.OVERALL_LINES_TO_COVER), anyDouble());
- }
-
- @Test
- public void testCopyUnitTestMeasures() {
- DecoratorContext context = mock(DecoratorContext.class);
- File file = File.create("src/Foo.java");
-
- when(context.getMeasure(CoreMetrics.LINES_TO_COVER)).thenReturn(new Measure<>(CoreMetrics.LINES_TO_COVER, 10.0));
- when(context.getMeasure(CoreMetrics.UNCOVERED_LINES)).thenReturn(new Measure<>(CoreMetrics.UNCOVERED_LINES, 5.0));
- when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn(new Measure<>(CoreMetrics.COVERAGE_LINE_HITS_DATA, "1=1;2=2;"));
- when(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER)).thenReturn(new Measure<>(CoreMetrics.CONDITIONS_TO_COVER, 2.0));
- when(context.getMeasure(CoreMetrics.UNCOVERED_CONDITIONS)).thenReturn(new Measure<>(CoreMetrics.UNCOVERED_CONDITIONS, 1.0));
- when(context.getMeasure(CoreMetrics.CONDITIONS_BY_LINE)).thenReturn(new Measure<>(CoreMetrics.CONDITIONS_BY_LINE, "1=4"));
- when(context.getMeasure(CoreMetrics.COVERED_CONDITIONS_BY_LINE)).thenReturn(new Measure<>(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "1=2"));
-
- decorator.decorate(file, context);
-
- verify(context).saveMeasure(CoreMetrics.OVERALL_LINES_TO_COVER, 10.0);
- verify(context).saveMeasure(CoreMetrics.OVERALL_UNCOVERED_LINES, 5.0);
- verify(context).saveMeasure(new Measure(CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA, "1=1;2=2;"));
- verify(context).saveMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER, 2.0);
- verify(context).saveMeasure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, 1.0);
- verify(context).saveMeasure(new Measure(CoreMetrics.OVERALL_CONDITIONS_BY_LINE, "1=4"));
- verify(context).saveMeasure(new Measure(CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE, "1=2"));
- }
-
- @Test
- public void dontFailOnBrokenValues() {
- DecoratorContext context = mock(DecoratorContext.class);
- File file = File.create("src/Foo.java");
-
- when(context.getMeasure(CoreMetrics.LINES_TO_COVER)).thenReturn(new Measure<>(CoreMetrics.LINES_TO_COVER, 10.0));
- when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn(new Measure<>(CoreMetrics.COVERAGE_LINE_HITS_DATA));
-
- decorator.decorate(file, context);
-
- verify(context).saveMeasure(CoreMetrics.OVERALL_LINES_TO_COVER, 10.0);
- }
-}
diff --git a/plugins/sonar-email-notifications-plugin/pom.xml b/plugins/sonar-email-notifications-plugin/pom.xml
index 5ed2d2b0151..35e83bda58b 100644
--- a/plugins/sonar-email-notifications-plugin/pom.xml
+++ b/plugins/sonar-email-notifications-plugin/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
diff --git a/plugins/sonar-l10n-en-plugin/pom.xml b/plugins/sonar-l10n-en-plugin/pom.xml
index b73653fb170..817eb99e375 100644
--- a/plugins/sonar-l10n-en-plugin/pom.xml
+++ b/plugins/sonar-l10n-en-plugin/pom.xml
@@ -25,7 +25,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
diff --git a/plugins/sonar-xoo-plugin/pom.xml b/plugins/sonar-xoo-plugin/pom.xml
index 32fc1f0adf4..26dddfe9e71 100644
--- a/plugins/sonar-xoo-plugin/pom.xml
+++ b/plugins/sonar-xoo-plugin/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<groupId>org.codehaus.sonar.plugins</groupId>
diff --git a/pom.xml b/pom.xml
index 6226633a9ca..b52201d8516 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
<packaging>pom</packaging>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<name>SonarQube</name>
<url>http://www.sonarqube.org/</url>
<description>Open source platform for continuous inspection of code quality</description>
@@ -66,15 +66,15 @@
<properties>
<sonarUpdateCenter.version>1.11</sonarUpdateCenter.version>
- <sonarJava.version>2.9.1</sonarJava.version>
- <sonarGit.version>1.0-RC1</sonarGit.version>
- <sonarSvn.version>1.0-RC1</sonarSvn.version>
+ <sonarJava.version>3.0</sonarJava.version>
+ <sonarGit.version>1.0</sonarGit.version>
+ <sonarSvn.version>1.0</sonarSvn.version>
<h2.version>1.3.176</h2.version>
<jetty.version>8.1.12.v20130726</jetty.version>
<logback.version>1.1.2</logback.version>
<slf4j.version>1.7.10</slf4j.version>
<tomcat.version>8.0.18</tomcat.version>
- <elasticsearch.version>1.4.2</elasticsearch.version>
+ <elasticsearch.version>1.4.4</elasticsearch.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.min.version>3.0.5</maven.min.version>
<maven.api.version>3.0.5</maven.api.version>
@@ -85,6 +85,7 @@
<skipBatchTests>false</skipBatchTests>
<skipServerTests>false</skipServerTests>
<skipWebTests>false</skipWebTests>
+ <jsCoverage>nocoverage</jsCoverage>
<version.maven-license.plugin>1.9.0</version.maven-license.plugin>
<skipSanityChecks>false</skipSanityChecks>
@@ -649,12 +650,6 @@
</exclusions>
</dependency>
<dependency>
- <groupId>org.codehaus.sonar-plugins.java</groupId>
- <artifactId>sonar-findbugs-plugin</artifactId>
- <version>3.1</version>
- <type>sonar-plugin</type>
- </dependency>
- <dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
<version>2.5.1</version>
@@ -1550,6 +1545,13 @@
</plugins>
</build>
</profile>
+
+ <profile>
+ <id>analysis</id>
+ <properties>
+ <jsCoverage>coverage</jsCoverage>
+ </properties>
+ </profile>
</profiles>
</project>
diff --git a/server/pom.xml b/server/pom.xml
index 0bfd128c231..b198220c6b3 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>server</artifactId>
<packaging>pom</packaging>
diff --git a/server/sonar-process-monitor/pom.xml b/server/sonar-process-monitor/pom.xml
index 10131e432cd..c1b0f4ea123 100644
--- a/server/sonar-process-monitor/pom.xml
+++ b/server/sonar-process-monitor/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>server</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/server/sonar-process/pom.xml b/server/sonar-process/pom.xml
index 03bbf3d7c81..85dc25c5778 100644
--- a/server/sonar-process/pom.xml
+++ b/server/sonar-process/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>server</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/server/sonar-search/pom.xml b/server/sonar-search/pom.xml
index 48b37cee245..0263b8a1320 100644
--- a/server/sonar-search/pom.xml
+++ b/server/sonar-search/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>server</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/server/sonar-server-benchmarks/pom.xml b/server/sonar-server-benchmarks/pom.xml
index d87fbf40b21..a12a517dcf8 100644
--- a/server/sonar-server-benchmarks/pom.xml
+++ b/server/sonar-server-benchmarks/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>server</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>sonar-server-benchmarks</artifactId>
diff --git a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/Benchmark.java b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/Benchmark.java
index 05ddb828634..a6003b576b0 100644
--- a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/Benchmark.java
+++ b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/Benchmark.java
@@ -40,9 +40,14 @@ public class Benchmark extends ErrorCollector {
}
}
- public void expectLessThanOrEqualTo(String label, long val, long max) {
+ public void expectAround(String label, long val, long expect, double marginPercents) {
if (ENABLED) {
- checkThat(label, val, Matchers.lessThan(max));
+ if (marginPercents > 0.2) {
+ throw new IllegalArgumentException("Error margin must be less than 0.2 (20%). Has: " + marginPercents);
+ }
+ long min = (long) (expect * (1.0 - marginPercents));
+ long max = (long) (expect * (1.0 + marginPercents));
+ checkThat(label, val, Matchers.allOf(Matchers.greaterThan(min), Matchers.lessThan(max)));
}
}
diff --git a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java
index 4d2a9de9f5b..ba5a6aa4d9c 100644
--- a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java
+++ b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java
@@ -112,7 +112,7 @@ public class IssueIndexBenchmarkTest {
long period = System.currentTimeMillis() - start;
long throughputPerSecond = 1000 * issues.count.get() / period;
LOGGER.info(String.format("%d issues indexed in %d ms (%d docs/second)", issues.count.get(), period, throughputPerSecond));
- benchmark.expectBetween("Throughput to index issues", throughputPerSecond, 3000, 3400);
+ benchmark.expectAround("Throughput to index issues", throughputPerSecond, 3400, 0.06);
// be sure that physical files do not evolve during estimation of size
tester.get(EsClient.class).prepareOptimize("issues").get();
diff --git a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceDbBenchmarkTest.java b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceDbBenchmarkTest.java
index 3d6dbf32645..479408f6745 100644
--- a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceDbBenchmarkTest.java
+++ b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceDbBenchmarkTest.java
@@ -53,6 +53,9 @@ public class SourceDbBenchmarkTest {
@Rule
public DbTester dbTester = new DbTester();
+ @Rule
+ public Benchmark benchmark = new Benchmark();
+
@Test
public void benchmark() throws Exception {
prepareTable();
@@ -81,6 +84,7 @@ public class SourceDbBenchmarkTest {
long period = end - start;
long throughputPerSecond = 1000L * counter.get() / period;
LOGGER.info(String.format("%d FILE_SOURCES rows scrolled in %d ms (%d rows/second)", counter.get(), period, throughputPerSecond));
+ benchmark.expectAround("Throughput to scroll FILE_SOURCES", throughputPerSecond, 120, 0.08);
} finally {
DbUtils.closeQuietly(connection);
diff --git a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceIndexBenchmarkTest.java b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceIndexBenchmarkTest.java
index 7ed033e45a9..6480c4ef0df 100644
--- a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceIndexBenchmarkTest.java
+++ b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceIndexBenchmarkTest.java
@@ -88,7 +88,7 @@ public class SourceIndexBenchmarkTest {
long nbLines = files.count.get() * LINES_PER_FILE;
long throughputPerSecond = 1000L * nbLines / period;
LOGGER.info(String.format("%d lines indexed in %d ms (%d docs/second)", nbLines, period, throughputPerSecond));
- benchmark.expectBetween("Throughput to index source lines", throughputPerSecond, 7500, 8000);
+ benchmark.expectAround("Throughput to index source lines", throughputPerSecond, 7800, 0.04);
// be sure that physical files do not evolve during estimation of size
tester.get(EsClient.class).prepareOptimize(SourceLineIndexDefinition.INDEX).get();
diff --git a/server/sonar-server/pom.xml b/server/sonar-server/pom.xml
index 12419aa2142..511964cf982 100644
--- a/server/sonar-server/pom.xml
+++ b/server/sonar-server/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>server</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>sonar-server</artifactId>
diff --git a/server/sonar-server/src/main/java/org/sonar/core/computation/dbcleaner/ProjectCleaner.java b/server/sonar-server/src/main/java/org/sonar/core/computation/dbcleaner/ProjectCleaner.java
index 6c341d54e0e..db97f41b182 100644
--- a/server/sonar-server/src/main/java/org/sonar/core/computation/dbcleaner/ProjectCleaner.java
+++ b/server/sonar-server/src/main/java/org/sonar/core/computation/dbcleaner/ProjectCleaner.java
@@ -28,13 +28,8 @@ import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
import org.sonar.core.persistence.DbSession;
-import org.sonar.core.purge.IdUuidPair;
-import org.sonar.core.purge.PurgeConfiguration;
-import org.sonar.core.purge.PurgeDao;
-import org.sonar.core.purge.PurgeListener;
-import org.sonar.core.purge.PurgeProfiler;
+import org.sonar.core.purge.*;
import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.properties.ProjectSettingsFactory;
import javax.annotation.Nullable;
@@ -49,33 +44,30 @@ public class ProjectCleaner implements ServerComponent {
private final PurgeListener purgeListener;
private final PurgeDao purgeDao;
private final DefaultPeriodCleaner periodCleaner;
- private final ProjectSettingsFactory projectSettingsFactory;
private final IssueIndex issueIndex;
public ProjectCleaner(PurgeDao purgeDao, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler, PurgeListener purgeListener,
- ProjectSettingsFactory projectSettingsFactory, IssueIndex issueIndex) {
+ IssueIndex issueIndex) {
this.purgeDao = purgeDao;
this.periodCleaner = periodCleaner;
this.profiler = profiler;
this.purgeListener = purgeListener;
- this.projectSettingsFactory = projectSettingsFactory;
this.issueIndex = issueIndex;
}
- public ProjectCleaner purge(DbSession session, IdUuidPair idUuidPair) {
+ public ProjectCleaner purge(DbSession session, IdUuidPair idUuidPair, Settings projectSettings) {
long start = System.currentTimeMillis();
profiler.reset();
- Settings settings = projectSettingsFactory.newProjectSettings(session, idUuidPair.getId());
- PurgeConfiguration configuration = newDefaultPurgeConfiguration(settings, idUuidPair);
+ PurgeConfiguration configuration = newDefaultPurgeConfiguration(projectSettings, idUuidPair);
- cleanHistoricalData(session, configuration.rootProjectIdUuid().getId(), settings);
+ cleanHistoricalData(session, configuration.rootProjectIdUuid().getId(), projectSettings);
doPurge(session, configuration);
deleteIndexedIssuesBefore(idUuidPair.getUuid(), configuration.maxLiveDateOfClosedIssues());
session.commit();
- logProfiling(start, settings);
+ logProfiling(start, projectSettings);
return this;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/Activity.java b/server/sonar-server/src/main/java/org/sonar/server/activity/Activity.java
new file mode 100644
index 00000000000..ff9a5a2d145
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/activity/Activity.java
@@ -0,0 +1,72 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.activity;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class Activity {
+
+ public static enum Type {
+ QPROFILE, SERVER, ANALYSIS_REPORT
+ }
+
+ private Type type;
+ private String action;
+ private String message;
+ private final Map<String,Object> data = new LinkedHashMap<>();
+
+ public Type getType() {
+ return type;
+ }
+
+ public void setType(Type type) {
+ this.type = type;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ @CheckForNull
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(@Nullable String message) {
+ this.message = message;
+ }
+
+ public Map<String, Object> getData() {
+ return data;
+ }
+
+ public Activity setData(String key, Object val) {
+ this.data.put(key, val);
+ return this;
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/ActivityService.java b/server/sonar-server/src/main/java/org/sonar/server/activity/ActivityService.java
index bb91bf20967..a108c0db063 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/activity/ActivityService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/activity/ActivityService.java
@@ -19,60 +19,33 @@
*/
package org.sonar.server.activity;
-import org.sonar.core.activity.Activity;
-import org.sonar.core.activity.ActivityLog;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.api.utils.internal.Uuids;
import org.sonar.core.activity.db.ActivityDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.server.activity.index.ActivityIndex;
-import org.sonar.server.activity.index.ActivityQuery;
+import org.sonar.server.activity.index.ActivityIndexer;
import org.sonar.server.db.DbClient;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryContext;
-import org.sonar.server.search.Result;
import org.sonar.server.user.UserSession;
-import javax.annotation.Nullable;
-
-/**
- * Log service is used to log Activity classes which represents an event to DB and Index.
- *
- * @see org.sonar.core.activity.ActivityLog
- */
-public class ActivityService {
+public class ActivityService implements ServerComponent {
private final DbClient dbClient;
- private final IndexClient indexClient;
+ private final ActivityIndexer indexer;
- public ActivityService(DbClient dbClient, IndexClient indexClient) {
+ public ActivityService(DbClient dbClient, ActivityIndexer indexer) {
this.dbClient = dbClient;
- this.indexClient = indexClient;
- }
-
- @Nullable
- private String getAuthor() {
- return (UserSession.get().login() != null) ? UserSession.get().login() : null;
- }
-
- private void save(DbSession session, ActivityDto log) {
- dbClient.activityDao().insert(session,
- log.setAuthor(getAuthor()));
- }
-
- public void write(DbSession session, Activity.Type type, String message) {
- save(session, ActivityDto.createFor(message).setType(type));
- }
-
- public <L extends ActivityLog> void write(DbSession session, Activity.Type type, L log) {
- this.save(session, ActivityDto.createFor(log)
- .setType(type));
- }
-
- public ActivityQuery newActivityQuery() {
- return new ActivityQuery();
+ this.indexer = indexer;
}
- public Result<Activity> search(ActivityQuery query, QueryContext options) {
- ActivityIndex index = indexClient.get(ActivityIndex.class);
- return new Result<Activity>(index, index.search(query, options));
+ public void save(Activity activity) {
+ ActivityDto dto = new ActivityDto()
+ .setKey(Uuids.create())
+ .setAuthor(UserSession.get().login())
+ .setAction(activity.getAction())
+ .setMessage(activity.getMessage())
+ .setData(KeyValueFormat.format(activity.getData()))
+ .setType(activity.getType().name());
+ dbClient.activityDao().insert(dto);
+ indexer.index();
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/RubyQProfileActivityService.java b/server/sonar-server/src/main/java/org/sonar/server/activity/RubyQProfileActivityService.java
index 744a3c05fd6..d0e3c7a0794 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/activity/RubyQProfileActivityService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/activity/RubyQProfileActivityService.java
@@ -23,10 +23,10 @@ package org.sonar.server.activity;
import org.picocontainer.Startable;
import org.sonar.api.ServerComponent;
import org.sonar.api.utils.Paging;
+import org.sonar.server.es.SearchOptions;
import org.sonar.server.qualityprofile.QProfileActivity;
import org.sonar.server.qualityprofile.QProfileActivityQuery;
import org.sonar.server.qualityprofile.QProfileService;
-import org.sonar.server.search.QueryContext;
import org.sonar.server.search.Result;
import org.sonar.server.util.RubyUtils;
@@ -51,11 +51,8 @@ public class RubyQProfileActivityService implements ServerComponent, Startable {
*/
public QProfileActivityResult search(Map<String, Object> params) {
QProfileActivityQuery query = new QProfileActivityQuery();
- QueryContext queryContext = new QueryContext().setMaxLimit();
- List<String> profileKeys = RubyUtils.toStrings(params.get("profileKeys"));
- if (profileKeys != null) {
- query.setQprofileKeys(profileKeys);
- }
+
+ query.setQprofileKey((String)params.get("profileKey"));
Date since = RubyUtils.toDate(params.get("since"));
if (since != null) {
query.setSince(since);
@@ -64,12 +61,14 @@ public class RubyQProfileActivityService implements ServerComponent, Startable {
if (to != null) {
query.setTo(to);
}
+
+ SearchOptions options = new SearchOptions();
Integer page = RubyUtils.toInteger(params.get("p"));
int pageIndex = page != null ? page : 1;
- queryContext.setPage(pageIndex, 50);
+ options.setPage(pageIndex, 50);
- Result<QProfileActivity> result = service.searchActivities(query, queryContext);
- return new QProfileActivityResult(result.getHits(), Paging.create(queryContext.getLimit(), pageIndex, (int) result.getTotal()));
+ Result<QProfileActivity> result = service.searchActivities(query, options);
+ return new QProfileActivityResult(result.getHits(), Paging.create(options.getLimit(), pageIndex, (int) result.getTotal()));
}
@Override
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/db/ActivityDao.java b/server/sonar-server/src/main/java/org/sonar/server/activity/db/ActivityDao.java
index 7d4a636947f..c6a9a271632 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/activity/db/ActivityDao.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/activity/db/ActivityDao.java
@@ -19,46 +19,39 @@
*/
package org.sonar.server.activity.db;
+import org.sonar.api.ServerComponent;
import org.sonar.api.utils.System2;
import org.sonar.core.activity.db.ActivityDto;
import org.sonar.core.activity.db.ActivityMapper;
+import org.sonar.core.persistence.DaoComponent;
import org.sonar.core.persistence.DbSession;
-import org.sonar.server.db.BaseDao;
-import org.sonar.server.search.IndexDefinition;
+import org.sonar.core.persistence.MyBatis;
-import java.util.List;
+import java.util.Date;
-/**
- * @since 4.4
- */
-public class ActivityDao extends BaseDao<ActivityMapper, ActivityDto, String> {
+public class ActivityDao implements DaoComponent, ServerComponent {
- public ActivityDao(System2 system) {
- super(IndexDefinition.LOG, ActivityMapper.class, system);
- }
+ private final MyBatis mybatis;
+ private final System2 system;
- @Override
- protected ActivityDto doGetNullableByKey(DbSession session, String key) {
- throw new IllegalStateException("Cannot execute getByKey on Activities in DB");
+ public ActivityDao(MyBatis mybatis, System2 system) {
+ this.mybatis = mybatis;
+ this.system = system;
}
- @Override
- protected ActivityDto doInsert(DbSession session, ActivityDto item) {
- mapper(session).insert(item);
- return item;
+ public void insert(ActivityDto dto) {
+ DbSession session = mybatis.openSession(false);
+ try {
+ insert(session, dto);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
}
- @Override
- protected ActivityDto doUpdate(DbSession session, ActivityDto item) {
- throw new IllegalStateException("Cannot update Log!");
+ public void insert(DbSession session, ActivityDto dto) {
+ dto.setCreatedAt(new Date(system.now()));
+ session.getMapper(ActivityMapper.class).insert(dto);
}
- @Override
- protected void doDeleteByKey(DbSession session, String key) {
- throw new IllegalStateException("Cannot delete Log!");
- }
-
- public List<ActivityDto> findAll(DbSession session) {
- return mapper(session).selectAll();
- }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityDoc.java b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityDoc.java
index a438fa3a61d..c0472856ada 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityDoc.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityDoc.java
@@ -19,51 +19,85 @@
*/
package org.sonar.server.activity.index;
+import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
-import org.sonar.core.activity.Activity;
import org.sonar.server.search.BaseDoc;
-import org.sonar.server.search.IndexUtils;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import java.util.Date;
+import java.util.HashMap;
import java.util.Map;
-/**
- * @since 4.4
- */
-public class ActivityDoc extends BaseDoc implements Activity {
+public class ActivityDoc extends BaseDoc {
- protected ActivityDoc(Map<String, Object> fields) {
+ public ActivityDoc(Map<String, Object> fields) {
super(fields);
}
- @Override
- public Date time() {
- return IndexUtils.parseDateTime((String) getField(ActivityNormalizer.LogFields.CREATED_AT.field()));
+ @VisibleForTesting
+ ActivityDoc() {
+ super(new HashMap<String, Object>());
}
- @Override
- public String login() {
- return this.getNullableField(ActivityNormalizer.LogFields.LOGIN.field());
+ public void setCreatedAt(Date date) {
+ setField(ActivityIndexDefinition.FIELD_CREATED_AT, date);
}
- @Override
- public Type type() {
- return Type.valueOf((String) getField(ActivityNormalizer.LogFields.TYPE.field()));
+ public Date getCreatedAt() {
+ return getFieldAsDate(ActivityIndexDefinition.FIELD_CREATED_AT);
}
- @Override
- public String action() {
- return this.getNullableField(ActivityNormalizer.LogFields.ACTION.field());
+ public String getKey() {
+ return this.getField(ActivityIndexDefinition.FIELD_KEY);
}
- @Override
- public Map<String, String> details() {
- return this.getNullableField(ActivityNormalizer.LogFields.DETAILS.field());
+ public void setKey(String s) {
+ setField(ActivityIndexDefinition.FIELD_KEY, s);
}
- @Override
- public String message() {
- return this.getNullableField(ActivityNormalizer.LogFields.MESSAGE.field());
+ @CheckForNull
+ public String getLogin() {
+ return this.getNullableField(ActivityIndexDefinition.FIELD_LOGIN);
+ }
+
+ public void setLogin(@Nullable String s) {
+ setField(ActivityIndexDefinition.FIELD_LOGIN, s);
+ }
+
+ public String getType() {
+ return (String) getField(ActivityIndexDefinition.FIELD_TYPE);
+ }
+
+ public void setType(String s) {
+ setField(ActivityIndexDefinition.FIELD_TYPE, s);
+ }
+
+ @CheckForNull
+ public String getAction() {
+ return this.getNullableField(ActivityIndexDefinition.FIELD_ACTION);
+ }
+
+ public void setAction(@Nullable String s) {
+ setField(ActivityIndexDefinition.FIELD_ACTION, s);
+ }
+
+ public Map<String, String> getDetails() {
+ return this.getField(ActivityIndexDefinition.FIELD_DETAILS);
+ }
+
+ public void setDetails(Map<String, String> details) {
+ setField(ActivityIndexDefinition.FIELD_DETAILS, details);
+ }
+
+ @CheckForNull
+ public String getMessage() {
+ return this.getNullableField(ActivityIndexDefinition.FIELD_MESSAGE);
+ }
+
+ public void setMessage(@Nullable String s) {
+ setField(ActivityIndexDefinition.FIELD_MESSAGE, s);
}
@Override
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndex.java b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndex.java
index 0e1ced87c50..ee082d63d43 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndex.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndex.java
@@ -19,119 +19,86 @@
*/
package org.sonar.server.activity.index;
+import com.google.common.base.Function;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.action.search.SearchType;
-import org.elasticsearch.common.settings.ImmutableSettings;
-import org.elasticsearch.common.unit.TimeValue;
-import org.elasticsearch.index.query.*;
+import org.elasticsearch.index.query.AndFilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+import org.elasticsearch.index.query.OrFilterBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortOrder;
-import org.sonar.core.activity.Activity;
-import org.sonar.core.activity.db.ActivityDto;
-import org.sonar.server.search.*;
+import org.sonar.core.util.NonNullInputFunction;
+import org.sonar.server.es.BaseIndex;
+import org.sonar.server.es.EsClient;
+import org.sonar.server.es.SearchOptions;
+import org.sonar.server.es.SearchResult;
-import javax.annotation.Nullable;
-
-import java.util.HashMap;
+import java.util.Date;
import java.util.Map;
-/**
- * @since 4.4
- */
-public class ActivityIndex extends BaseIndex<Activity, ActivityDto, String> {
-
- public ActivityIndex(ActivityNormalizer normalizer, SearchClient node) {
- super(IndexDefinition.LOG, normalizer, node);
- }
-
- @Override
- protected String getKeyValue(String key) {
- return key;
- }
-
- @Override
- protected Map mapKey() {
- Map<String, Object> mapping = new HashMap<String, Object>();
- mapping.put("path", ActivityNormalizer.LogFields.KEY.field());
- return mapping;
- }
-
- @Override
- protected ImmutableSettings.Builder addCustomIndexSettings(ImmutableSettings.Builder settings) {
- return settings
- .put("analysis.analyzer.default.type", "keyword");
- }
+public class ActivityIndex extends BaseIndex {
- @Override
- protected Map mapProperties() {
- Map<String, Object> mapping = new HashMap<String, Object>();
- for (IndexField field : ActivityNormalizer.LogFields.ALL_FIELDS) {
- mapping.put(field.field(), mapField(field));
+ /**
+ * Convert an Elasticsearch result (a map) to an {@link org.sonar.server.activity.index.ActivityDoc}. It's
+ * used for {@link org.sonar.server.es.SearchResult}.
+ */
+ private static final Function<Map<String, Object>, ActivityDoc> DOC_CONVERTER = new NonNullInputFunction<Map<String, Object>, ActivityDoc>() {
+ @Override
+ protected ActivityDoc doApply(Map<String, Object> input) {
+ return new ActivityDoc(input);
}
- return mapping;
- }
-
- @Override
- protected Activity toDoc(final Map<String, Object> fields) {
- return new ActivityDoc(fields);
- }
+ };
- public Result<Activity> findAll() {
- SearchRequestBuilder request = getClient().prepareSearch(this.getIndexName())
- .setQuery(QueryBuilders.matchAllQuery())
- .setTypes(this.getIndexType())
- .setSize(Integer.MAX_VALUE);
- SearchResponse response = request.get();
- return new Result<Activity>(this, response);
+ public ActivityIndex(EsClient esClient) {
+ super(esClient);
}
- public SearchResponse search(ActivityQuery query, QueryContext options) {
- return search(query, options, null);
+ public SearchResult<ActivityDoc> search(ActivityQuery query, SearchOptions options) {
+ SearchResponse response = doSearch(query, options);
+ return new SearchResult<>(response, DOC_CONVERTER);
}
- public SearchResponse search(ActivityQuery query, QueryContext options,
- @Nullable FilterBuilder domainFilter) {
-
- // Prepare query
- SearchRequestBuilder esSearch = getClient()
- .prepareSearch(this.getIndexName())
- .setTypes(this.getIndexType())
- .setIndices(this.getIndexName());
-
- // Integrate Pagination
- esSearch.setFrom(options.getOffset());
- esSearch.setSize(options.getLimit());
+ public SearchResponse doSearch(ActivityQuery query, SearchOptions options) {
+ SearchRequestBuilder requestBuilder = getClient()
+ .prepareSearch(ActivityIndexDefinition.INDEX)
+ .setTypes(ActivityIndexDefinition.TYPE);
- // Sort Date Desc
- esSearch.addSort(ActivityNormalizer.LogFields.CREATED_AT.field(), SortOrder.DESC);
+ requestBuilder.setFrom(options.getOffset());
+ requestBuilder.setSize(options.getLimit());
+ requestBuilder.addSort(ActivityIndexDefinition.FIELD_CREATED_AT, SortOrder.DESC);
AndFilterBuilder filter = FilterBuilders.andFilter();
-
- // implement Type Filtering
- OrFilterBuilder typeFilter = FilterBuilders.orFilter();
- for (Activity.Type type : query.getTypes()) {
- typeFilter.add(FilterBuilders.termFilter(ActivityNormalizer.LogFields.TYPE.field(), type));
+ if (!query.getTypes().isEmpty()) {
+ OrFilterBuilder typeFilter = FilterBuilders.orFilter();
+ for (String type : query.getTypes()) {
+ typeFilter.add(FilterBuilders.termFilter(ActivityIndexDefinition.FIELD_TYPE, type));
+ }
+ filter.add(typeFilter);
}
- filter.add(typeFilter);
-
- // Implement date Filter
- filter.add(FilterBuilders.rangeFilter(ActivityNormalizer.LogFields.CREATED_AT.field())
- .from(query.getSince())
- .to(query.getTo()));
- // Add any additional domain filter
- if (domainFilter != null) {
- filter.add(domainFilter);
+ if (!query.getDataOrFilters().isEmpty()) {
+ for (Map.Entry<String, Object> entry : query.getDataOrFilters().entrySet()) {
+ OrFilterBuilder orFilter = FilterBuilders.orFilter();
+ orFilter.add(FilterBuilders.nestedFilter(ActivityIndexDefinition.FIELD_DETAILS,
+ FilterBuilders.termFilter(ActivityIndexDefinition.FIELD_DETAILS + "." + entry.getKey(), entry.getValue())));
+ filter.add(orFilter);
+ }
}
- esSearch.setQuery(QueryBuilders.filteredQuery(
- QueryBuilders.matchAllQuery(), filter));
-
- if (options.isScroll()) {
- esSearch.setSearchType(SearchType.SCAN);
- esSearch.setScroll(TimeValue.timeValueMinutes(3));
+ Date since = query.getSince();
+ if (since != null) {
+ filter.add(FilterBuilders.rangeFilter(ActivityIndexDefinition.FIELD_CREATED_AT)
+ .gt(since)
+ .cache(false));
+ }
+ Date to = query.getTo();
+ if (to != null) {
+ filter.add(FilterBuilders.rangeFilter(ActivityIndexDefinition.FIELD_CREATED_AT)
+ .lt(to)
+ .cache(false));
}
- return esSearch.get();
+ requestBuilder.setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), filter));
+ return requestBuilder.get();
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndexDefinition.java b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndexDefinition.java
new file mode 100644
index 00000000000..bac57c04233
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndexDefinition.java
@@ -0,0 +1,75 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.activity.index;
+
+import com.google.common.collect.ImmutableMap;
+import org.elasticsearch.cluster.metadata.IndexMetaData;
+import org.sonar.api.config.Settings;
+import org.sonar.process.ProcessConstants;
+import org.sonar.server.es.IndexDefinition;
+import org.sonar.server.es.NewIndex;
+
+/**
+ * Definition of ES index "activities", including settings and fields.
+ */
+public class ActivityIndexDefinition implements IndexDefinition {
+
+ public static final String INDEX = "activities";
+ public static final String TYPE = "activity";
+ public static final String FIELD_KEY = "key";
+ public static final String FIELD_TYPE = "type";
+ public static final String FIELD_ACTION = "action";
+ public static final String FIELD_CREATED_AT = "createdAt";
+ public static final String FIELD_LOGIN = "login";
+ public static final String FIELD_DETAILS = "details";
+ public static final String FIELD_MESSAGE = "message";
+
+ private final Settings settings;
+
+ public ActivityIndexDefinition(Settings settings) {
+ this.settings = settings;
+ }
+
+ @Override
+ public void define(IndexDefinitionContext context) {
+ NewIndex index = context.create(INDEX);
+ index.getSettings().put("index.refresh_interval", "-1");
+ index.getSettings().put("analysis.analyzer.default.type", "keyword");
+
+ // shards
+ boolean clusterMode = settings.getBoolean(ProcessConstants.CLUSTER_ACTIVATE);
+ if (clusterMode) {
+ index.getSettings().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 4);
+ index.getSettings().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 1);
+ // else keep defaults (one shard)
+ }
+
+ // type "activity"
+ NewIndex.NewIndexType mapping = index.createType(TYPE);
+ mapping.setAttribute("_id", ImmutableMap.of("path", FIELD_KEY));
+ mapping.stringFieldBuilder(FIELD_KEY).build();
+ mapping.stringFieldBuilder(FIELD_TYPE).build();
+ mapping.stringFieldBuilder(FIELD_ACTION).build();
+ mapping.stringFieldBuilder(FIELD_LOGIN).build();
+ mapping.createDynamicNestedField(FIELD_DETAILS);
+ mapping.stringFieldBuilder(FIELD_MESSAGE).build();
+ mapping.createDateTimeField(FIELD_CREATED_AT);
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndexer.java
new file mode 100644
index 00000000000..babf3f671bd
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndexer.java
@@ -0,0 +1,88 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.activity.index;
+
+import org.elasticsearch.action.update.UpdateRequest;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.BaseIndexer;
+import org.sonar.server.es.BulkIndexer;
+import org.sonar.server.es.EsClient;
+
+import java.sql.Connection;
+import java.util.Iterator;
+
+/**
+ * Add to Elasticsearch index {@link org.sonar.server.activity.index.ActivityIndexDefinition} the rows of
+ * db table ACTIVITIES that are not indexed yet
+ * <p/>
+ */
+public class ActivityIndexer extends BaseIndexer {
+
+ private final DbClient dbClient;
+
+ public ActivityIndexer(DbClient dbClient, EsClient esClient) {
+ super(esClient, 0L, ActivityIndexDefinition.INDEX, ActivityIndexDefinition.TYPE, ActivityIndexDefinition.FIELD_CREATED_AT);
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ protected long doIndex(long lastUpdatedAt) {
+ BulkIndexer bulk = new BulkIndexer(esClient, ActivityIndexDefinition.INDEX);
+ bulk.setLarge(lastUpdatedAt == 0L);
+
+ DbSession dbSession = dbClient.openSession(false);
+ Connection dbConnection = dbSession.getConnection();
+ try {
+ ActivityResultSetIterator rowIt = ActivityResultSetIterator.create(dbClient, dbConnection, lastUpdatedAt);
+ long maxUpdatedAt = doIndex(bulk, rowIt);
+ rowIt.close();
+ return maxUpdatedAt;
+
+ } finally {
+ dbSession.close();
+ }
+ }
+
+ public long index(Iterator<ActivityDoc> activities) {
+ BulkIndexer bulk = new BulkIndexer(esClient, ActivityIndexDefinition.INDEX);
+ return doIndex(bulk, activities);
+ }
+
+ private long doIndex(BulkIndexer bulk, Iterator<ActivityDoc> activities) {
+ long maxUpdatedAt = 0L;
+ bulk.start();
+ while (activities.hasNext()) {
+ ActivityDoc activity = activities.next();
+ bulk.add(newUpsertRequest(activity));
+
+ // it's more efficient to sort programmatically than in SQL on some databases (MySQL for instance)
+ maxUpdatedAt = Math.max(maxUpdatedAt, activity.getCreatedAt().getTime());
+ }
+ bulk.stop();
+ return maxUpdatedAt;
+ }
+
+ private UpdateRequest newUpsertRequest(ActivityDoc doc) {
+ return new UpdateRequest(ActivityIndexDefinition.INDEX, ActivityIndexDefinition.TYPE, doc.getKey())
+ .doc(doc.getFields())
+ .upsert(doc.getFields());
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityNormalizer.java b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityNormalizer.java
deleted file mode 100644
index 2e64ed487a7..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityNormalizer.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.activity.index;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import org.elasticsearch.action.support.replication.ReplicationType;
-import org.elasticsearch.action.update.UpdateRequest;
-import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.core.activity.db.ActivityDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.search.BaseNormalizer;
-import org.sonar.server.search.IndexField;
-import org.sonar.server.search.Indexable;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @since 4.4
- */
-public class ActivityNormalizer extends BaseNormalizer<ActivityDto, String> {
-
- public static final class LogFields extends Indexable {
-
- public static final IndexField KEY = add(IndexField.Type.STRING, "key");
- public static final IndexField TYPE = addSortable(IndexField.Type.STRING, "type");
- public static final IndexField ACTION = addSortable(IndexField.Type.STRING, "action");
- public static final IndexField CREATED_AT = addSortable(IndexField.Type.DATE, "createdAt");
- public static final IndexField UPDATED_AT = addSortable(IndexField.Type.DATE, BaseNormalizer.UPDATED_AT_FIELD);
- public static final IndexField LOGIN = addSearchable(IndexField.Type.STRING, "login");
- public static final IndexField DETAILS = addSearchable(IndexField.Type.OBJECT, "details");
- public static final IndexField MESSAGE = addSearchable(IndexField.Type.STRING, "message");
- public static final Set<IndexField> ALL_FIELDS = ImmutableSet.of(KEY, TYPE, ACTION, CREATED_AT, UPDATED_AT, LOGIN, DETAILS, MESSAGE);
- }
-
- public ActivityNormalizer(DbClient db) {
- super(db);
- }
-
- @Override
- public List<UpdateRequest> normalize(ActivityDto dto) {
-
- Map<String, Object> logDoc = new HashMap<String, Object>();
- logDoc.put(LogFields.KEY.field(), dto.getKey());
- logDoc.put(LogFields.TYPE.field(), dto.getType());
- logDoc.put(LogFields.ACTION.field(), dto.getAction());
- logDoc.put(LogFields.LOGIN.field(), dto.getAuthor());
- logDoc.put(LogFields.MESSAGE.field(), dto.getMessage());
- logDoc.put(LogFields.CREATED_AT.field(), dto.getCreatedAt());
- logDoc.put(LogFields.UPDATED_AT.field(), dto.getUpdatedAt());
-
- logDoc.put(LogFields.DETAILS.field(), KeyValueFormat.parse(dto.getData()));
-
- /* Creating updateRequest */
- return ImmutableList.of(new UpdateRequest()
- .id(dto.getKey())
- .replicationType(ReplicationType.ASYNC)
- .doc(logDoc)
- .upsert(logDoc));
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityQuery.java b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityQuery.java
index 53c8749ae21..b8e25d91c15 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityQuery.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityQuery.java
@@ -19,49 +19,60 @@
*/
package org.sonar.server.activity.index;
-import com.google.common.collect.Lists;
-import org.sonar.core.activity.Activity;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.Map;
-/**
- * @since 4.4
- */
public class ActivityQuery {
private Date since;
private Date to;
- private Collection<Activity.Type> types;
-
- public ActivityQuery() {
- types = Lists.newArrayList();
- }
+ private final Collection<String> types = new ArrayList<>();
+ private final Map<String, Object> dataOrFilters = new LinkedHashMap<>();
+ @CheckForNull
public Date getSince() {
return since;
}
- public ActivityQuery setSince(Date since) {
+ public ActivityQuery setSince(@Nullable Date since) {
this.since = since;
return this;
}
+ @CheckForNull
public Date getTo() {
return to;
}
- public ActivityQuery setTo(Date to) {
+ public ActivityQuery setTo(@Nullable Date to) {
this.to = to;
return this;
}
- public Collection<Activity.Type> getTypes() {
+ public Collection<String> getTypes() {
return types;
}
- public ActivityQuery setTypes(Collection<Activity.Type> types) {
- this.types = types;
+ public ActivityQuery setTypes(@Nullable Collection<String> types) {
+ this.types.clear();
+ if (types != null) {
+ this.types.addAll(types);
+ }
+ return this;
+ }
+
+ public Map<String, Object> getDataOrFilters() {
+ return dataOrFilters;
+ }
+
+ public ActivityQuery addDataOrFilter(String dataKey, Object dataValue) {
+ dataOrFilters.put(dataKey, dataValue);
return this;
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityResultSetIterator.java b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityResultSetIterator.java
new file mode 100644
index 00000000000..701d649ff8f
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityResultSetIterator.java
@@ -0,0 +1,86 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.activity.index;
+
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.db.ResultSetIterator;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.HashMap;
+
+/**
+ * Scrolls over table ACTIVITIES and reads documents to populate
+ * the index "activities/activity"
+ */
+class ActivityResultSetIterator extends ResultSetIterator<ActivityDoc> {
+
+ private static final String[] FIELDS = {
+ // column 1
+ "log_key",
+ "log_action",
+ "log_message",
+ "data_field",
+ "user_login",
+ "log_type",
+ "created_at"
+ };
+
+ private static final String SQL_ALL = "select " + StringUtils.join(FIELDS, ",") + " from activities ";
+
+ private static final String SQL_AFTER_DATE = SQL_ALL + " where created_at>=?";
+
+ private ActivityResultSetIterator(PreparedStatement stmt) throws SQLException {
+ super(stmt);
+ }
+
+ static ActivityResultSetIterator create(DbClient dbClient, Connection connection, long afterDate) {
+ try {
+ String sql = afterDate > 0L ? SQL_AFTER_DATE : SQL_ALL;
+ PreparedStatement stmt = dbClient.newScrollingSelectStatement(connection, sql);
+ if (afterDate > 0L) {
+ stmt.setTimestamp(1, new Timestamp(afterDate));
+ }
+ return new ActivityResultSetIterator(stmt);
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to prepare SQL request to select activities", e);
+ }
+ }
+
+ @Override
+ protected ActivityDoc read(ResultSet rs) throws SQLException {
+ ActivityDoc doc = new ActivityDoc(new HashMap<String, Object>(10));
+
+ // all the fields must be present, even if value is null
+ doc.setKey(rs.getString(1));
+ doc.setAction(rs.getString(2));
+ doc.setMessage(rs.getString(3));
+ doc.setDetails(KeyValueFormat.parse(rs.getString(4)));
+ doc.setLogin(rs.getString(5));
+ doc.setType(rs.getString(6));
+ doc.setCreatedAt(rs.getTimestamp(7));
+ return doc;
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/ws/ActivityMapping.java b/server/sonar-server/src/main/java/org/sonar/server/activity/ws/ActivityMapping.java
index aee5b31cdc6..07a756335cf 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/activity/ws/ActivityMapping.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/activity/ws/ActivityMapping.java
@@ -20,9 +20,8 @@
package org.sonar.server.activity.ws;
import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.activity.Activity;
import org.sonar.server.activity.index.ActivityDoc;
-import org.sonar.server.activity.index.ActivityNormalizer;
+import org.sonar.server.activity.index.ActivityIndexDefinition;
import org.sonar.server.search.QueryContext;
import org.sonar.server.search.ws.BaseMapping;
@@ -34,16 +33,16 @@ import java.util.Map;
public class ActivityMapping extends BaseMapping<ActivityDoc, Object> {
public ActivityMapping() {
- map("type", ActivityNormalizer.LogFields.TYPE.field());
- map("action", ActivityNormalizer.LogFields.ACTION.field());
- mapDateTime("createdAt", ActivityNormalizer.LogFields.CREATED_AT.field());
- map("login", ActivityNormalizer.LogFields.LOGIN.field());
- map("message", ActivityNormalizer.LogFields.MESSAGE.field());
- map("details", new IndexMapper<ActivityDoc, Object>(ActivityNormalizer.LogFields.DETAILS.field()) {
+ map("type", ActivityIndexDefinition.FIELD_TYPE);
+ map("action", ActivityIndexDefinition.FIELD_ACTION);
+ mapDateTime("createdAt", ActivityIndexDefinition.FIELD_CREATED_AT);
+ map("login", ActivityIndexDefinition.FIELD_LOGIN);
+ map("message", ActivityIndexDefinition.FIELD_MESSAGE);
+ map("details", new IndexMapper<ActivityDoc, Object>(ActivityIndexDefinition.FIELD_DETAILS) {
@Override
public void write(JsonWriter json, ActivityDoc activity, Object context) {
json.name("details").beginObject();
- for (Map.Entry<String, String> detail : activity.details().entrySet()) {
+ for (Map.Entry<String, String> detail : activity.getDetails().entrySet()) {
json.prop(detail.getKey(), detail.getValue());
}
json.endObject();
@@ -51,8 +50,8 @@ public class ActivityMapping extends BaseMapping<ActivityDoc, Object> {
});
}
- public void write(Activity activity, JsonWriter writer, QueryContext context) {
- doWrite((ActivityDoc) activity, null, writer, context);
+ public void write(ActivityDoc activity, JsonWriter writer, QueryContext context) {
+ doWrite(activity, null, writer, context);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/activity/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/activity/ws/SearchAction.java
index 256028e0209..0bb0647f753 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/activity/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/activity/ws/SearchAction.java
@@ -19,34 +19,30 @@
*/
package org.sonar.server.activity.ws;
-import org.apache.commons.lang.StringUtils;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.RequestHandler;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.activity.Activity;
-import org.sonar.server.activity.ActivityService;
+import org.sonar.server.activity.Activity;
+import org.sonar.server.activity.index.ActivityDoc;
+import org.sonar.server.activity.index.ActivityIndex;
import org.sonar.server.activity.index.ActivityQuery;
+import org.sonar.server.es.SearchOptions;
+import org.sonar.server.es.SearchResult;
import org.sonar.server.search.QueryContext;
-import org.sonar.server.search.Result;
-import org.sonar.server.search.ws.SearchOptions;
-/**
- * @since 4.4
- */
public class SearchAction implements RequestHandler {
public static final String PARAM_TYPE = "type";
-
public static final String SEARCH_ACTION = "search";
- private final ActivityService logService;
- private final ActivityMapping mapping;
+ private final ActivityIndex activityIndex;
+ private final ActivityMapping docToJsonMapping;
- public SearchAction(ActivityService logService, ActivityMapping mapping) {
- this.logService = logService;
- this.mapping = mapping;
+ public SearchAction(ActivityIndex activityIndex, ActivityMapping docToJsonMapping) {
+ this.activityIndex = activityIndex;
+ this.docToJsonMapping = docToJsonMapping;
}
void define(WebService.NewController controller) {
@@ -57,36 +53,34 @@ public class SearchAction implements RequestHandler {
.setInternal(true)
.setHandler(this);
- // Other parameters
action.createParam(PARAM_TYPE)
- .setDescription("Types of activities to search")
- .setPossibleValues(Activity.Type.values())
- .setDefaultValue(StringUtils.join(Activity.Type.values(), ","));
+ .setDescription("Activity type")
+ .setPossibleValues(Activity.Type.values());
- // Generic search parameters
- SearchOptions.defineFieldsParam(action, mapping.supportedFields());
-
- SearchOptions.definePageParams(action);
+ action.addPagingParams(10);
+ action.addFieldsParam(docToJsonMapping.supportedFields());
}
@Override
public void handle(Request request, Response response) {
- ActivityQuery query = logService.newActivityQuery();
- SearchOptions searchOptions = SearchOptions.create(request);
- QueryContext queryContext = mapping.newQueryOptions(searchOptions);
+ ActivityQuery query = new ActivityQuery();
+ query.setTypes(request.paramAsStrings(PARAM_TYPE));
+
+ SearchOptions options = new SearchOptions();
+ options.setPage(request.mandatoryParamAsInt(WebService.Param.PAGE), request.mandatoryParamAsInt(WebService.Param.PAGE_SIZE));
- Result<Activity> results = logService.search(query, queryContext);
+ SearchResult<ActivityDoc> results = activityIndex.search(query, options);
JsonWriter json = response.newJsonWriter().beginObject();
- searchOptions.writeStatistics(json, results);
- writeLogs(results, json, queryContext);
+ options.writeJson(json, results.getTotal());
+ writeActivities(results, json, new QueryContext().setFieldsToReturn(request.paramAsStrings(WebService.Param.FIELDS)));
json.endObject().close();
}
- private void writeLogs(Result<Activity> result, JsonWriter json, QueryContext context) {
+ private void writeActivities(SearchResult<ActivityDoc> docs, JsonWriter json, QueryContext context) {
json.name("logs").beginArray();
- for (Activity log : result.getHits()) {
- mapping.write(log, json, context);
+ for (ActivityDoc doc : docs.getDocs()) {
+ docToJsonMapping.write(doc, json, context);
}
json.endArray();
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportLog.java b/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportLog.java
deleted file mode 100644
index 1b307d69171..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportLog.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation;
-
-import com.google.common.collect.ImmutableMap;
-import org.sonar.core.activity.ActivityLog;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.computation.db.AnalysisReportDto;
-
-import java.util.Map;
-
-import static org.sonar.api.utils.DateUtils.formatDateTimeNullSafe;
-import static org.sonar.api.utils.DateUtils.longToDate;
-
-public class AnalysisReportLog implements ActivityLog {
-
- private static final String ACTION = "LOG_ANALYSIS_REPORT";
-
- private final AnalysisReportDto report;
- private final ComponentDto project;
-
- public AnalysisReportLog(AnalysisReportDto report, ComponentDto project) {
- this.report = report;
- this.project = project;
- }
-
- @Override
- public Map<String, String> getDetails() {
- return ImmutableMap.<String, String>builder()
- .put("key", String.valueOf(report.getId()))
- .put("projectKey", project.key())
- .put("projectName", project.name())
- .put("projectUuid", project.uuid())
- .put("status", String.valueOf(report.getStatus()))
- .put("submittedAt", formatDateTimeNullSafe(longToDate(report.getCreatedAt())))
- .put("startedAt", formatDateTimeNullSafe(longToDate(report.getStartedAt())))
- .put("finishedAt", formatDateTimeNullSafe(longToDate(report.getFinishedAt())))
- .build();
- }
-
- @Override
- public String getAction() {
- return ACTION;
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportQueue.java b/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportQueue.java
deleted file mode 100644
index 3c57b1c5e91..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportQueue.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation;
-
-import org.sonar.api.ServerComponent;
-import org.sonar.api.utils.System2;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.user.UserSession;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import java.io.InputStream;
-import java.util.List;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING;
-
-public class AnalysisReportQueue implements ServerComponent {
-
- private final DbClient dbClient;
- private final System2 system2;
-
- public AnalysisReportQueue(DbClient dbClient, System2 system2) {
- this.dbClient = dbClient;
- this.system2 = system2;
- }
-
- /**
- * Adds a report to the queue and returns the generated key
- */
- public String add(String projectKey, Long snapshotId, @Nullable InputStream reportData) {
- // TODO security must not be handled here
- UserSession.get().checkGlobalPermission(GlobalPermissions.SCAN_EXECUTION);
-
- AnalysisReportDto report = newPendingAnalysisReport(projectKey)
- .setSnapshotId(snapshotId)
- .setData(reportData);
- DbSession session = dbClient.openSession(false);
- try {
- checkThatProjectExistsInDatabase(projectKey, session);
- return insertInDb(report, session).getKey();
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
- private AnalysisReportDto newPendingAnalysisReport(String projectKey) {
- return new AnalysisReportDto()
- .setProjectKey(projectKey)
- .setStatus(PENDING);
- }
-
- private void checkThatProjectExistsInDatabase(String projectKey, DbSession session) {
- dbClient.componentDao().getByKey(session, projectKey);
- }
-
- private AnalysisReportDto insertInDb(AnalysisReportDto reportTemplate, DbSession session) {
- AnalysisReportDto report = dbClient.analysisReportDao().insert(session, reportTemplate);
- session.commit();
-
- return report;
- }
-
- public void remove(AnalysisReportDto report) {
- checkArgument(report.getStatus().isInFinalState());
-
- DbSession session = dbClient.openSession(false);
- try {
- report.setFinishedAt(system2.now());
- dbClient.analysisReportDao().delete(session, report.getId());
- session.commit();
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
- @CheckForNull
- public AnalysisReportDto pop() {
- DbSession session = dbClient.openSession(false);
- try {
- return dbClient.analysisReportDao().pop(session);
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
- public List<AnalysisReportDto> findByProjectKey(String projectKey) {
- DbSession session = dbClient.openSession(false);
- try {
- return dbClient.analysisReportDao().selectByProjectKey(session, projectKey);
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
- /**
- * All the reports of the queue, whatever the status
- */
- public List<AnalysisReportDto> all() {
- DbSession session = dbClient.openSession(false);
- try {
- return dbClient.analysisReportDao().selectAll(session);
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationComponents.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContainer.java
index a26e06d99d4..21e9e7c9cb2 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationComponents.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContainer.java
@@ -19,25 +19,45 @@
*/
package org.sonar.server.computation;
+import org.sonar.api.platform.ComponentContainer;
import org.sonar.core.issue.db.UpdateConflictResolver;
-import org.sonar.server.computation.issue.*;
+import org.sonar.server.computation.issue.IssueCache;
+import org.sonar.server.computation.issue.IssueComputation;
+import org.sonar.server.computation.issue.RuleCache;
+import org.sonar.server.computation.issue.RuleCacheLoader;
+import org.sonar.server.computation.issue.ScmAccountCache;
+import org.sonar.server.computation.issue.ScmAccountCacheLoader;
+import org.sonar.server.computation.issue.SourceLinesCache;
import org.sonar.server.computation.step.ComputationSteps;
+import org.sonar.server.platform.Platform;
import org.sonar.server.view.index.ViewIndex;
import java.util.Arrays;
import java.util.List;
-public class ComputationComponents {
+public class ComputationContainer {
- private ComputationComponents() {
- // only static stuff
+ public void execute(ReportQueue.Item item) {
+ ComponentContainer container = Platform.getInstance().getContainer();
+ ComponentContainer child = container.createChild();
+ child.addSingletons(componentClasses());
+ child.addSingletons(ComputationSteps.orderedStepClasses());
+ child.startComponents();
+ try {
+ child.getComponentByType(ComputationService.class).process(item);
+ } finally {
+ child.stopComponents();
+ // TODO not possible to have multiple children -> will be
+ // a problem when we will have multiple concurrent computation workers
+ container.removeChild();
+ }
}
/**
- * List of all objects to be injected in the picocontainer dedicated to computation stack.
+ * List of all objects to be injected in the picocontainer dedicated to computation stack.
* Does not contain the steps declared in {@link org.sonar.server.computation.step.ComputationSteps#orderedStepClasses()}.
*/
- public static List nonStepComponents() {
+ static List componentClasses() {
return Arrays.asList(
ComputationService.class,
ComputationSteps.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContext.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContext.java
index a7709c8e139..9df00c9c6a5 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContext.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContext.java
@@ -20,41 +20,45 @@
package org.sonar.server.computation;
-import com.google.common.base.Preconditions;
+import org.sonar.api.config.Settings;
import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.core.component.ComponentDto;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.server.computation.step.ParseReportStep;
+
+import static com.google.common.base.Preconditions.checkState;
public class ComputationContext {
- private final AnalysisReportDto reportDto;
+ private final BatchReportReader reportReader;
private final ComponentDto project;
+ // cache of metadata as it's frequently accessed
+ private final BatchReport.Metadata reportMetadata;
+ private Settings projectSettings;
- /**
- * Cache of analysis date as it can be accessed several times
- */
- private BatchReport.Metadata reportMetadata = null;
-
- public ComputationContext(AnalysisReportDto reportDto, ComponentDto project) {
- this.reportDto = reportDto;
+ public ComputationContext(BatchReportReader reportReader, ComponentDto project) {
+ this.reportReader = reportReader;
this.project = project;
+ this.reportMetadata = reportReader.readMetadata();
}
- public AnalysisReportDto getReportDto() {
- return reportDto;
+ public BatchReport.Metadata getReportMetadata() {
+ return reportMetadata;
}
public ComponentDto getProject() {
return project;
}
- public BatchReport.Metadata getReportMetadata() {
- Preconditions.checkState(reportMetadata != null, "Report metadata is available after execution of " + ParseReportStep.class);
- return reportMetadata;
+ public BatchReportReader getReportReader() {
+ return reportReader;
+ }
+
+ public Settings getProjectSettings() {
+ return projectSettings;
}
- public void setReportMetadata(BatchReport.Metadata m) {
- this.reportMetadata = m;
+ public void setProjectSettings(Settings projectSettings) {
+ checkState(this.projectSettings == null, "can't set project settings twice");
+ this.projectSettings = projectSettings;
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java
index 77ee77fb272..422f09851ca 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java
@@ -21,21 +21,32 @@
package org.sonar.server.computation;
import com.google.common.base.Throwables;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.ArrayUtils;
import org.sonar.api.ServerComponent;
import org.sonar.api.utils.System2;
+import org.sonar.api.utils.TempFolder;
+import org.sonar.api.utils.ZipUtils;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
-import org.sonar.core.activity.Activity;
+import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.activity.Activity;
import org.sonar.server.activity.ActivityService;
import org.sonar.server.computation.step.ComputationStep;
import org.sonar.server.computation.step.ComputationSteps;
import org.sonar.server.db.DbClient;
+import org.sonar.server.properties.ProjectSettingsFactory;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.sonar.api.utils.DateUtils.formatDateTimeNullSafe;
+import static org.sonar.api.utils.DateUtils.longToDate;
public class ComputationService implements ServerComponent {
@@ -44,56 +55,88 @@ public class ComputationService implements ServerComponent {
private final DbClient dbClient;
private final ComputationSteps steps;
private final ActivityService activityService;
+ private final ProjectSettingsFactory projectSettingsFactory;
+ private final TempFolder tempFolder;
+ private final System2 system;
- public ComputationService(DbClient dbClient, ComputationSteps steps, ActivityService activityService) {
+ public ComputationService(DbClient dbClient, ComputationSteps steps, ActivityService activityService,
+ ProjectSettingsFactory projectSettingsFactory, TempFolder tempFolder, System2 system) {
this.dbClient = dbClient;
this.steps = steps;
this.activityService = activityService;
+ this.projectSettingsFactory = projectSettingsFactory;
+ this.tempFolder = tempFolder;
+ this.system = system;
}
- public void process(AnalysisReportDto report) {
- Profiler profiler = Profiler.create(LOG).startInfo(String.format(
- "#%s - %s - processing analysis report", report.getId(), report.getProjectKey()));
+ public void process(ReportQueue.Item item) {
+ Profiler profiler = Profiler.create(LOG).startDebug(String.format(
+ "Analysis of project %s (report %d)", item.dto.getProjectKey(), item.dto.getId()));
- ComponentDto project = loadProject(report);
+ ComponentDto project = loadProject(item);
try {
- ComputationContext context = new ComputationContext(report, project);
+ File reportDir = extractReportInDir(item);
+ BatchReportReader reader = new BatchReportReader(reportDir);
+ ComputationContext context = new ComputationContext(reader, project);
+ context.setProjectSettings(projectSettingsFactory.newProjectSettings(project.getId()));
for (ComputationStep step : steps.orderedSteps()) {
if (ArrayUtils.contains(step.supportedProjectQualifiers(), context.getProject().qualifier())) {
- Profiler stepProfiler = Profiler.create(LOG).startInfo(step.getDescription());
+ Profiler stepProfiler = Profiler.createIfDebug(LOG).startDebug(step.getDescription());
step.execute(context);
- stepProfiler.stopInfo();
+ stepProfiler.stopDebug();
}
}
- report.succeed();
+ item.dto.succeed();
} catch (Exception e) {
- report.fail();
+ item.dto.fail();
throw Throwables.propagate(e);
} finally {
- logActivity(report, project);
+ item.dto.setFinishedAt(system.now());
+ saveActivity(item.dto, project);
profiler.stopInfo();
}
}
- private ComponentDto loadProject(AnalysisReportDto report) {
- DbSession session = dbClient.openSession(false);
+ private File extractReportInDir(ReportQueue.Item item) {
+ File dir = tempFolder.newDir();
try {
- return dbClient.componentDao().getByKey(session, report.getProjectKey());
- } finally {
- MyBatis.closeQuietly(session);
+ Profiler profiler = Profiler.createIfDebug(LOG).start();
+ ZipUtils.unzip(item.zipFile, dir);
+ if (profiler.isDebugEnabled()) {
+ String message = String.format("Report extracted | size=%s | project=%s",
+ FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(dir)), item.dto.getProjectKey());
+ profiler.stopDebug(message);
+ }
+ return dir;
+ } catch (IOException e) {
+ throw new IllegalStateException(String.format("Fail to unzip %s into %s", item.zipFile, dir), e);
}
}
- private void logActivity(AnalysisReportDto report, ComponentDto project) {
+ private ComponentDto loadProject(ReportQueue.Item queueItem) {
DbSession session = dbClient.openSession(false);
try {
- report.setFinishedAt(System2.INSTANCE.now());
- activityService.write(session, Activity.Type.ANALYSIS_REPORT, new AnalysisReportLog(report, project));
- session.commit();
+ return dbClient.componentDao().getByKey(session, queueItem.dto.getProjectKey());
} finally {
MyBatis.closeQuietly(session);
}
}
+
+ private void saveActivity(AnalysisReportDto report, ComponentDto project) {
+ Activity activity = new Activity();
+ activity.setType(Activity.Type.ANALYSIS_REPORT);
+ activity.setAction("LOG_ANALYSIS_REPORT");
+ activity
+ .setData("key", String.valueOf(report.getId()))
+ .setData("projectKey", project.key())
+ .setData("projectName", project.name())
+ .setData("projectUuid", project.uuid())
+ .setData("status", String.valueOf(report.getStatus()))
+ .setData("submittedAt", formatDateTimeNullSafe(longToDate(report.getCreatedAt())))
+ .setData("startedAt", formatDateTimeNullSafe(longToDate(report.getStartedAt())))
+ .setData("finishedAt", formatDateTimeNullSafe(longToDate(report.getFinishedAt())));
+ activityService.save(activity);
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationThread.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationThread.java
index 07c9a23e3a0..e70b15feb73 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationThread.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationThread.java
@@ -20,67 +20,56 @@
package org.sonar.server.computation;
-
-import org.sonar.api.platform.ComponentContainer;
+import com.google.common.annotations.VisibleForTesting;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.server.computation.step.ComputationSteps;
-import org.sonar.server.platform.Platform;
/**
- * This thread pops queue of reports and processes the report if present
+ * This thread pops a report from the queue and integrate it.
*/
public class ComputationThread implements Runnable {
+
private static final Logger LOG = Loggers.get(ComputationThread.class);
- private final AnalysisReportQueue queue;
+ private final ReportQueue queue;
+ private final ComputationContainer container;
+
+ public ComputationThread(ReportQueue queue) {
+ this.queue = queue;
+ this.container = new ComputationContainer();
+ }
- public ComputationThread(AnalysisReportQueue queue) {
+ @VisibleForTesting
+ ComputationThread(ReportQueue queue, ComputationContainer container) {
this.queue = queue;
+ this.container = container;
}
@Override
public void run() {
- AnalysisReportDto report = null;
+ ReportQueue.Item item = null;
try {
- report = queue.pop();
+ item = queue.pop();
} catch (Exception e) {
LOG.error("Failed to pop the queue of analysis reports", e);
}
- if (report != null) {
+ if (item != null) {
try {
- process(report);
+ container.execute(item);
} catch (Exception e) {
LOG.error(String.format(
- "Failed to process analysis report %d of project %s", report.getId(), report.getProjectKey()), e);
+ "Failed to process analysis report %d of project %s", item.dto.getId(), item.dto.getProjectKey()), e);
} finally {
- removeSilentlyFromQueue(report);
+ removeSilentlyFromQueue(item);
}
}
}
- private void removeSilentlyFromQueue(AnalysisReportDto report) {
+ private void removeSilentlyFromQueue(ReportQueue.Item item) {
try {
- queue.remove(report);
+ queue.remove(item);
} catch (Exception e) {
- LOG.error(String.format("Failed to remove analysis report %d from queue", report.getId()), e);
- }
- }
-
- private void process(AnalysisReportDto report) {
- ComponentContainer container = Platform.getInstance().getContainer();
- ComponentContainer child = container.createChild();
- child.addSingletons(ComputationSteps.orderedStepClasses());
- child.addSingletons(ComputationComponents.nonStepComponents());
- child.startComponents();
- try {
- child.getComponentByType(ComputationService.class).process(report);
- } finally {
- child.stopComponents();
- // TODO not possible to have multiple children -> will be
- // a problem when we will have multiple concurrent computation workers
- container.removeChild();
+ LOG.error(String.format("Failed to remove analysis report %d from queue", item.dto.getId()), e);
}
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationThreadLauncher.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationThreadLauncher.java
index c19b80a0a7b..18bf2a35633 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationThreadLauncher.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationThreadLauncher.java
@@ -36,14 +36,14 @@ public class ComputationThreadLauncher implements Startable, ServerComponent, Se
public static final String THREAD_NAME_PREFIX = "computation-";
- private final AnalysisReportQueue queue;
+ private final ReportQueue queue;
private final ScheduledExecutorService executorService;
private final long delayBetweenTasks;
private final long delayForFirstStart;
private final TimeUnit timeUnit;
- public ComputationThreadLauncher(AnalysisReportQueue queue) {
+ public ComputationThreadLauncher(ReportQueue queue) {
this.queue = queue;
this.executorService = Executors.newSingleThreadScheduledExecutor(newThreadFactory());
@@ -53,7 +53,7 @@ public class ComputationThreadLauncher implements Startable, ServerComponent, Se
}
@VisibleForTesting
- ComputationThreadLauncher(AnalysisReportQueue queue, long delayForFirstStart, long delayBetweenTasks, TimeUnit timeUnit) {
+ ComputationThreadLauncher(ReportQueue queue, long delayForFirstStart, long delayBetweenTasks, TimeUnit timeUnit) {
this.queue = queue;
this.executorService = Executors.newSingleThreadScheduledExecutor(newThreadFactory());
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java
new file mode 100644
index 00000000000..8139db0d050
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java
@@ -0,0 +1,188 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.computation;
+
+import org.apache.commons.io.FileUtils;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.internal.Uuids;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.process.ProcessConstants;
+import org.sonar.server.db.DbClient;
+
+import javax.annotation.CheckForNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING;
+
+public class ReportQueue implements ServerComponent {
+
+ public static class Item {
+ public final AnalysisReportDto dto;
+ public final File zipFile;
+
+ public Item(AnalysisReportDto dto, File zipFile) {
+ this.dto = dto;
+ this.zipFile = zipFile;
+ }
+ }
+
+ private final DbClient dbClient;
+ private final Settings settings;
+
+ public ReportQueue(DbClient dbClient, Settings settings) {
+ this.dbClient = dbClient;
+ this.settings = settings;
+ }
+
+ public Item add(String projectKey, InputStream reportData) {
+ String uuid = Uuids.create();
+ File file = reportFileForUuid(uuid);
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ checkThatProjectExistsInDatabase(projectKey, session);
+
+ // save report data on file. Directory is created if it does not exist yet.
+ FileUtils.copyInputStreamToFile(reportData, file);
+
+ // add report metadata to the queue
+ AnalysisReportDto dto = new AnalysisReportDto()
+ .setProjectKey(projectKey)
+ .setStatus(PENDING)
+ .setUuid(uuid);
+ dbClient.analysisReportDao().insert(session, dto);
+ session.commit();
+ return new Item(dto, file);
+
+ } catch (Exception e) {
+ FileUtils.deleteQuietly(file);
+ throw new IllegalStateException("Fail to store analysis report of project " + projectKey, e);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ private void checkThatProjectExistsInDatabase(String projectKey, DbSession session) {
+ dbClient.componentDao().getByKey(session, projectKey);
+ }
+
+ public void remove(Item item) {
+ DbSession session = dbClient.openSession(false);
+ try {
+ FileUtils.deleteQuietly(item.zipFile);
+ dbClient.analysisReportDao().delete(session, item.dto.getId());
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ @CheckForNull
+ public Item pop() {
+ DbSession session = dbClient.openSession(false);
+ try {
+ AnalysisReportDto dto = dbClient.analysisReportDao().pop(session);
+ if (dto != null) {
+ File file = reportFileForUuid(dto.getUuid());
+ if (file.exists()) {
+ return new Item(dto, file);
+ }
+ Loggers.get(getClass()).error("Analysis report not found: " + file.getAbsolutePath());
+ dbClient.analysisReportDao().delete(session, dto.getId());
+ session.commit();
+ }
+ return null;
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public List<AnalysisReportDto> findByProjectKey(String projectKey) {
+ DbSession session = dbClient.openSession(false);
+ try {
+ return dbClient.analysisReportDao().selectByProjectKey(session, projectKey);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ /**
+ * Truncates table ANALYSIS_REPORTS and delete all files from directory {data}/analysis
+ */
+ public void clear() {
+ File dir = reportsDir();
+ try {
+ FileUtils.deleteDirectory(dir);
+ } catch (IOException e) {
+ throw new IllegalStateException("Fail to delete directory: " + dir.getAbsolutePath(), e);
+ }
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ dbClient.analysisReportDao().truncate(session);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public void resetToPendingStatus() {
+ DbSession session = dbClient.openSession(false);
+ try {
+ dbClient.analysisReportDao().resetAllToPendingStatus(session);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ /**
+ * All the reports of the queue, whatever the status
+ */
+ public List<AnalysisReportDto> all() {
+ DbSession session = dbClient.openSession(false);
+ try {
+ return dbClient.analysisReportDao().selectAll(session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ /**
+ * This directory is a flat list of the reports referenced in table ANALYSIS_REPORTS.
+ * Never return null but the directory may not exist.
+ */
+ private File reportsDir() {
+ return new File(settings.getString(ProcessConstants.PATH_DATA), "analysis");
+ }
+
+ private File reportFileForUuid(String uuid) {
+ return new File(reportsDir(), String.format("%s.zip", uuid));
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportQueueCleaner.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueueCleaner.java
index 9e660b68c7e..7abc9f1953e 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportQueueCleaner.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueueCleaner.java
@@ -23,10 +23,6 @@ package org.sonar.server.computation;
import org.picocontainer.Startable;
import org.sonar.api.ServerComponent;
import org.sonar.api.platform.ServerUpgradeStatus;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.server.computation.db.AnalysisReportDao;
-import org.sonar.server.db.DbClient;
/**
* Clean-up queue of reports at server startup:
@@ -36,30 +32,22 @@ import org.sonar.server.db.DbClient;
* <li>reset reports that were in status WORKING while server stopped</li>
* </ul>
*/
-public class AnalysisReportQueueCleaner implements Startable, ServerComponent {
+public class ReportQueueCleaner implements Startable, ServerComponent {
private final ServerUpgradeStatus serverUpgradeStatus;
- private final DbClient dbClient;
+ private final ReportQueue queue;
- public AnalysisReportQueueCleaner(ServerUpgradeStatus serverUpgradeStatus, DbClient dbClient) {
+ public ReportQueueCleaner(ServerUpgradeStatus serverUpgradeStatus, ReportQueue queue) {
this.serverUpgradeStatus = serverUpgradeStatus;
- this.dbClient = dbClient;
+ this.queue = queue;
}
@Override
public void start() {
- AnalysisReportDao dao = dbClient.analysisReportDao();
- DbSession session = dbClient.openSession(false);
- try {
- if (serverUpgradeStatus.isUpgraded()) {
- dao.truncate(session);
- } else {
- dao.resetAllToPendingStatus(session);
- }
-
- session.commit();
- } finally {
- MyBatis.closeQuietly(session);
+ if (serverUpgradeStatus.isUpgraded()) {
+ queue.clear();
+ } else {
+ queue.resetToPendingStatus();
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/db/AnalysisReportDao.java b/server/sonar-server/src/main/java/org/sonar/server/computation/db/AnalysisReportDao.java
index 11f22499c5f..f08edbf5b3a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/db/AnalysisReportDao.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/db/AnalysisReportDao.java
@@ -21,27 +21,14 @@
package org.sonar.server.computation.db;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.io.ByteStreams;
-import org.apache.commons.io.IOUtils;
import org.sonar.api.utils.System2;
-import org.sonar.api.utils.ZipUtils;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.computation.db.AnalysisReportMapper;
import org.sonar.core.persistence.DaoComponent;
-import org.sonar.core.persistence.DatabaseUtils;
import org.sonar.core.persistence.DbSession;
import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Types;
+
import java.util.List;
import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING;
@@ -55,8 +42,7 @@ public class AnalysisReportDao implements DaoComponent {
this(System2.INSTANCE);
}
- @VisibleForTesting
- AnalysisReportDao(System2 system2) {
+ public AnalysisReportDao(System2 system2) {
this.system2 = system2;
}
@@ -111,78 +97,10 @@ public class AnalysisReportDao implements DaoComponent {
public AnalysisReportDto insert(DbSession session, AnalysisReportDto report) {
report.setCreatedAt(system2.now());
report.setUpdatedAt(system2.now());
-
- Connection connection = session.getConnection();
- PreparedStatement ps = null;
- try {
- ps = connection.prepareStatement(
- "insert into analysis_reports " +
- " (project_key, snapshot_id, report_status, report_data, created_at, updated_at, started_at, finished_at)" +
- " values (?, ?, ?, ?, ?, ?, ?, ?)");
- ps.setString(1, report.getProjectKey());
- ps.setLong(2, report.getSnapshotId());
- ps.setString(3, report.getStatus().toString());
- setData(ps, 4, report.getData());
- ps.setLong(5, report.getCreatedAt());
- setLong(ps, 6, report.getUpdatedAt());
- setLong(ps, 7, report.getStartedAt());
- setLong(ps, 8, report.getFinishedAt());
- ps.executeUpdate();
- connection.commit();
- } catch (SQLException | IOException e) {
- throw new IllegalStateException(String.format("Failed to insert %s in the database", report), e);
- } finally {
- DatabaseUtils.closeQuietly(ps);
- }
-
+ mapper(session).insert(report);
return report;
}
- private void setLong(PreparedStatement ps, int index, @Nullable Long time) throws SQLException {
- if (time == null) {
- ps.setNull(index, Types.BIGINT);
- } else {
- ps.setLong(index, time);
- }
- }
-
- private void setData(PreparedStatement ps, int parameterIndex, @Nullable InputStream reportDataStream) throws IOException, SQLException {
- if (reportDataStream == null) {
- ps.setBytes(parameterIndex, null);
- } else {
- ps.setBytes(parameterIndex, ByteStreams.toByteArray(reportDataStream));
- }
- }
-
- @CheckForNull
- public void selectAndDecompressToDir(DbSession session, long id, File toDir) {
- Connection connection = session.getConnection();
- InputStream stream = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
- try {
- ps = connection.prepareStatement("select report_data from analysis_reports where id=?");
- ps.setLong(1, id);
-
- rs = ps.executeQuery();
- if (rs.next()) {
- stream = rs.getBinaryStream(1);
- if (stream != null) {
- ZipUtils.unzip(stream, toDir);
- }
- }
- // TODO what to do if id not found or no stream ?
- } catch (SQLException e) {
- throw new IllegalStateException(String.format("Failed to read report '%d' in the database", id), e);
- } catch (IOException e) {
- throw new IllegalStateException(String.format("Failed to decompress report '%d'", id), e);
- } finally {
- IOUtils.closeQuietly(stream);
- DatabaseUtils.closeQuietly(rs);
- DatabaseUtils.closeQuietly(ps);
- }
- }
-
public void delete(DbSession session, long id) {
mapper(session).delete(id);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueComputation.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueComputation.java
index b503e2c74ac..6400979ffb4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueComputation.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueComputation.java
@@ -19,41 +19,56 @@
*/
package org.sonar.server.computation.issue;
+import com.google.common.base.Strings;
import com.google.common.collect.Sets;
+import org.sonar.api.CoreProperties;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.issue.internal.FieldDiffs;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.user.index.UserDoc;
+import org.sonar.server.user.index.UserIndex;
import org.sonar.server.util.cache.DiskCache;
+import javax.annotation.Nullable;
+
import java.util.Date;
public class IssueComputation {
+ private static final Logger LOG = Loggers.get(IssueComputation.class);
+
private final RuleCache ruleCache;
private final ScmAccountCache scmAccountCache;
private final SourceLinesCache linesCache;
private final DiskCache<DefaultIssue>.DiskAppender diskIssuesAppender;
+ private final UserIndex userIndex;
+ private boolean hasAssigneeBeenComputed = false;
+ private String defaultAssignee = null;
public IssueComputation(RuleCache ruleCache, SourceLinesCache linesCache, ScmAccountCache scmAccountCache,
- IssueCache issueCache) {
+ IssueCache issueCache, UserIndex userIndex) {
this.ruleCache = ruleCache;
this.linesCache = linesCache;
this.scmAccountCache = scmAccountCache;
+ this.userIndex = userIndex;
this.diskIssuesAppender = issueCache.newAppender();
}
public void processComponentIssues(ComputationContext context, String componentUuid, Iterable<BatchReport.Issue> issues) {
linesCache.init(componentUuid);
+ computeDefaultAssignee(context.getProjectSettings().getString(CoreProperties.DEFAULT_ISSUE_ASSIGNEE));
for (BatchReport.Issue reportIssue : issues) {
DefaultIssue issue = toDefaultIssue(context, componentUuid, reportIssue);
if (issue.isNew()) {
guessAuthor(issue);
- autoAssign(issue);
+ autoAssign(issue, defaultAssignee);
copyRuleTags(issue);
}
diskIssuesAppender.append(issue);
@@ -110,7 +125,7 @@ public class IssueComputation {
}
}
- private void autoAssign(DefaultIssue issue) {
+ private void autoAssign(DefaultIssue issue, @Nullable String defaultAssignee) {
// issue.assignee() can be not-null if the issue-assign-plugin is
// still installed and executed during analysis
if (issue.assignee() == null) {
@@ -118,6 +133,9 @@ public class IssueComputation {
if (scmAccount != null) {
issue.setAssignee(scmAccountCache.getNullable(scmAccount));
}
+ if (issue.assignee() == null && defaultAssignee != null) {
+ issue.setAssignee(defaultAssignee);
+ }
}
}
@@ -126,4 +144,19 @@ public class IssueComputation {
issue.setTags(Sets.union(rule.getTags(), rule.getSystemTags()));
}
+ private void computeDefaultAssignee(@Nullable String login) {
+ if (hasAssigneeBeenComputed) {
+ return;
+ }
+
+ hasAssigneeBeenComputed = true;
+ if (!Strings.isNullOrEmpty(login)) {
+ UserDoc user = userIndex.getNullableByLogin(login);
+ if (user == null) {
+ LOG.info("the {} property was set with an unknown login: {}", CoreProperties.DEFAULT_ISSUE_ASSIGNEE, login);
+ } else {
+ defaultAssignee = login;
+ }
+ }
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java
index d73706b7060..973c5dadf55 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java
@@ -21,11 +21,14 @@
package org.sonar.server.computation.step;
import com.google.common.collect.Lists;
-import org.sonar.server.computation.ComputationComponents;
+import org.sonar.server.computation.ComputationContainer;
import java.util.Arrays;
import java.util.List;
+/**
+ * Ordered list of steps to be executed
+ */
public class ComputationSteps {
/**
@@ -77,6 +80,6 @@ public class ComputationSteps {
return step;
}
}
- throw new IllegalStateException("Component not found: " + clazz + ". Check " + ComputationComponents.class);
+ throw new IllegalStateException("Component not found: " + clazz + ". Check " + ComputationContainer.class);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java
index 9d6f4a547e4..c9a8c173b23 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java
@@ -20,34 +20,20 @@
package org.sonar.server.computation.step;
-import org.apache.commons.io.FileUtils;
import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.utils.TempFolder;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.batch.protocol.output.BatchOutputReader;
import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
+import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.server.computation.ComputationContext;
import org.sonar.server.computation.issue.IssueComputation;
-import org.sonar.server.db.DbClient;
-import java.io.File;
+import java.util.List;
public class ParseReportStep implements ComputationStep {
- private static final Logger LOG = Loggers.get(ParseReportStep.class);
-
private final IssueComputation issueComputation;
- private final DbClient dbClient;
- private final TempFolder tempFolder;
- public ParseReportStep(IssueComputation issueComputation, DbClient dbClient, TempFolder tempFolder) {
+ public ParseReportStep(IssueComputation issueComputation) {
this.issueComputation = issueComputation;
- this.dbClient = dbClient;
- this.tempFolder = tempFolder;
}
@Override
@@ -57,46 +43,27 @@ public class ParseReportStep implements ComputationStep {
@Override
public void execute(ComputationContext context) {
- File reportDir = tempFolder.newDir();
- try {
- // extract compressed report from database and uncompress it in temporary directory
- extractReport(context.getReportDto(), reportDir);
-
- // prepare parsing of report
- BatchOutputReader reader = new BatchOutputReader(reportDir);
- BatchReport.Metadata reportMetadata = reader.readMetadata();
- context.setReportMetadata(reportMetadata);
-
- // and parse!
- int rootComponentRef = reportMetadata.getRootComponentRef();
- recursivelyProcessComponent(reader, context, rootComponentRef);
- issueComputation.afterReportProcessing();
-
- } finally {
- FileUtils.deleteQuietly(reportDir);
- }
+ int rootComponentRef = context.getReportMetadata().getRootComponentRef();
+ recursivelyProcessComponent(context, rootComponentRef);
+ processDeletedComponents(context);
+ issueComputation.afterReportProcessing();
}
- private void extractReport(AnalysisReportDto report, File toDir) {
- long startTime = System.currentTimeMillis();
- DbSession session = dbClient.openSession(false);
- try {
- dbClient.analysisReportDao().selectAndDecompressToDir(session, report.getId(), toDir);
- } finally {
- MyBatis.closeQuietly(session);
+ private void recursivelyProcessComponent(ComputationContext context, int componentRef) {
+ BatchReportReader reportReader = context.getReportReader();
+ BatchReport.Component component = reportReader.readComponent(componentRef);
+ List<BatchReport.Issue> issues = reportReader.readComponentIssues(componentRef);
+ issueComputation.processComponentIssues(context, component.getUuid(), issues);
+ for (Integer childRef : component.getChildRefsList()) {
+ recursivelyProcessComponent(context, childRef);
}
- long stopTime = System.currentTimeMillis();
- LOG.info(String.format("Report extracted in %dms | uncompressed size=%s | project=%s",
- stopTime - startTime, FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(toDir)), report.getProjectKey()));
}
- private void recursivelyProcessComponent(BatchOutputReader reportReader, ComputationContext context, int componentRef) {
- BatchReport.Component component = reportReader.readComponent(componentRef);
- if (component != null) {
- issueComputation.processComponentIssues(context, component.getUuid(), reportReader.readComponentIssues(componentRef));
- for (Integer childRef : component.getChildRefsList()) {
- recursivelyProcessComponent(reportReader, context, childRef);
- }
+ private void processDeletedComponents(ComputationContext context) {
+ int deletedComponentsCount = context.getReportMetadata().getDeletedComponentsCount();
+ for (int componentRef = 1; componentRef <= deletedComponentsCount; componentRef++) {
+ BatchReport.Issues issues = context.getReportReader().readDeletedComponentIssues(componentRef);
+ issueComputation.processComponentIssues(context, issues.getComponentUuid(), issues.getListList());
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PurgeDatastoresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PurgeDatastoresStep.java
index d9fa522e40f..8e9417f4626 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PurgeDatastoresStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PurgeDatastoresStep.java
@@ -47,7 +47,7 @@ public class PurgeDatastoresStep implements ComputationStep {
public void execute(ComputationContext context) {
DbSession session = dbClient.openSession(true);
try {
- projectCleaner.purge(session, new IdUuidPair(context.getProject().getId(), context.getProject().uuid()));
+ projectCleaner.purge(session, new IdUuidPair(context.getProject().getId(), context.getProject().uuid()), context.getProjectSettings());
session.commit();
} finally {
MyBatis.closeQuietly(session);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/SendIssueNotificationsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/SendIssueNotificationsStep.java
index 1d3fc613aad..f67a92860d0 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/SendIssueNotificationsStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/SendIssueNotificationsStep.java
@@ -22,12 +22,14 @@ package org.sonar.server.computation.step;
import com.google.common.collect.ImmutableSet;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.utils.Durations;
import org.sonar.core.component.ComponentDto;
import org.sonar.server.computation.ComputationContext;
import org.sonar.server.computation.issue.IssueCache;
import org.sonar.server.computation.issue.RuleCache;
import org.sonar.server.issue.notification.IssueChangeNotification;
import org.sonar.server.issue.notification.NewIssuesNotification;
+import org.sonar.server.issue.notification.NewIssuesStatistics;
import org.sonar.server.notifications.NotificationService;
import org.sonar.server.util.CloseableIterator;
@@ -48,11 +50,13 @@ public class SendIssueNotificationsStep implements ComputationStep {
private final IssueCache issueCache;
private final RuleCache rules;
private final NotificationService service;
+ private final Durations durations;
- public SendIssueNotificationsStep(IssueCache issueCache, RuleCache rules, NotificationService service) {
+ public SendIssueNotificationsStep(IssueCache issueCache, RuleCache rules, NotificationService service, Durations durations) {
this.issueCache = issueCache;
this.rules = rules;
this.service = service;
+ this.durations = durations;
}
@Override
@@ -68,13 +72,13 @@ public class SendIssueNotificationsStep implements ComputationStep {
}
private void doExecute(ComputationContext context) {
- NewIssuesNotification.Stats newIssueStats = new NewIssuesNotification.Stats();
+ NewIssuesStatistics newIssuesStats = new NewIssuesStatistics();
CloseableIterator<DefaultIssue> issues = issueCache.traverse();
try {
while (issues.hasNext()) {
DefaultIssue issue = issues.next();
if (issue.isNew() && issue.resolution() == null) {
- newIssueStats.add(issue);
+ newIssuesStats.add(issue);
} else if (issue.isChanged() && issue.mustSendNotifications()) {
IssueChangeNotification changeNotification = new IssueChangeNotification();
changeNotification.setRuleName(rules.ruleName(issue.ruleKey()));
@@ -87,16 +91,17 @@ public class SendIssueNotificationsStep implements ComputationStep {
} finally {
issues.close();
}
- sendNewIssuesStatistics(context, newIssueStats);
+ sendNewIssuesStatistics(context, newIssuesStats);
}
- private void sendNewIssuesStatistics(ComputationContext context, NewIssuesNotification.Stats stats) {
- if (stats.size() > 0) {
+ private void sendNewIssuesStatistics(ComputationContext context, NewIssuesStatistics stats) {
+ if (stats.hasIssues()) {
ComponentDto project = context.getProject();
NewIssuesNotification notification = new NewIssuesNotification();
notification.setProject(project);
notification.setAnalysisDate(new Date(context.getReportMetadata().getAnalysisDate()));
notification.setStatistics(project, stats);
+ notification.setDebt(durations.encode(stats.debt()));
service.deliver(notification);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/SwitchSnapshotStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/SwitchSnapshotStep.java
index 1be36deb720..b073cd53ca1 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/SwitchSnapshotStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/SwitchSnapshotStep.java
@@ -22,7 +22,6 @@ package org.sonar.server.computation.step;
import org.sonar.api.resources.Qualifiers;
import org.sonar.core.component.SnapshotDto;
-import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.server.component.db.SnapshotDao;
@@ -48,8 +47,9 @@ public class SwitchSnapshotStep implements ComputationStep {
public void execute(ComputationContext context) {
DbSession session = dbClient.openSession(true);
try {
- disablePreviousSnapshot(session, context.getReportDto());
- enableCurrentSnapshot(session, context.getReportDto());
+ long snapshotId = context.getReportMetadata().getSnapshotId();
+ disablePreviousSnapshot(session, snapshotId);
+ enableCurrentSnapshot(session, snapshotId);
} finally {
MyBatis.closeQuietly(session);
}
@@ -60,16 +60,8 @@ public class SwitchSnapshotStep implements ComputationStep {
return "Switch last snapshot flag";
}
- private void disablePreviousSnapshot(DbSession session, AnalysisReportDto report) {
- SnapshotDto referenceSnapshot;
-
- try {
- referenceSnapshot = dbClient.snapshotDao().getByKey(session, report.getSnapshotId());
- } catch (Exception exception) {
- throw new IllegalStateException(String.format("Unexpected error while trying to retrieve snapshot of analysis %s", report), exception);
- }
-
- List<SnapshotDto> snapshots = dbClient.snapshotDao().findSnapshotAndChildrenOfProjectScope(session, referenceSnapshot);
+ private void disablePreviousSnapshot(DbSession session, long reportSnapshotId) {
+ List<SnapshotDto> snapshots = dbClient.snapshotDao().findSnapshotAndChildrenOfProjectScope(session, dbClient.snapshotDao().getByKey(session, reportSnapshotId));
for (SnapshotDto snapshot : snapshots) {
SnapshotDto previousLastSnapshot = dbClient.snapshotDao().getLastSnapshot(session, snapshot);
if (previousLastSnapshot != null) {
@@ -79,9 +71,9 @@ public class SwitchSnapshotStep implements ComputationStep {
}
}
- private void enableCurrentSnapshot(DbSession session, AnalysisReportDto report) {
+ private void enableCurrentSnapshot(DbSession session, long reportSnapshotId) {
SnapshotDao dao = dbClient.snapshotDao();
- SnapshotDto snapshot = dao.getByKey(session, report.getSnapshotId());
+ SnapshotDto snapshot = dao.getByKey(session, reportSnapshotId);
SnapshotDto previousLastSnapshot = dao.getLastSnapshot(session, snapshot);
boolean isLast = dao.isLast(snapshot, previousLastSnapshot);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryWsAction.java
index b1448a53792..82135a2c15f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryWsAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryWsAction.java
@@ -25,74 +25,64 @@ import org.sonar.api.server.ws.RequestHandler;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.activity.Activity;
import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.activity.ActivityService;
+import org.sonar.server.activity.Activity;
+import org.sonar.server.activity.index.ActivityDoc;
+import org.sonar.server.activity.index.ActivityIndex;
import org.sonar.server.activity.index.ActivityQuery;
-import org.sonar.server.activity.ws.ActivityMapping;
-import org.sonar.server.search.QueryContext;
-import org.sonar.server.search.Result;
-import org.sonar.server.search.ws.SearchOptions;
+import org.sonar.server.es.SearchOptions;
+import org.sonar.server.es.SearchResult;
+import org.sonar.server.issue.ws.IssuesWs;
import org.sonar.server.user.UserSession;
import java.util.Arrays;
import java.util.Map;
+// FIXME replace by api/activities/search
public class HistoryWsAction implements ComputationWsAction, RequestHandler {
public static final String PARAM_TYPE = "type";
- public static final String SEARCH_ACTION = "history";
+ private final ActivityIndex activityIndex;
- private final ActivityService logService;
- private final ActivityMapping mapping;
-
- public HistoryWsAction(ActivityService logService, ActivityMapping mapping) {
- this.logService = logService;
- this.mapping = mapping;
+ public HistoryWsAction(ActivityIndex activityIndex) {
+ this.activityIndex = activityIndex;
}
@Override
public void define(WebService.NewController controller) {
WebService.NewAction action = controller
- .createAction(SEARCH_ACTION)
- .setDescription("Search for activities")
+ .createAction("history")
+ .setDescription("Past integrations of analysis reports")
.setSince("5.0")
.setInternal(true)
.setHandler(this);
- // Generic search parameters
- SearchOptions.defineFieldsParam(action, mapping.supportedFields());
- SearchOptions.definePageParams(action);
+ action.addPagingParams(10);
}
@Override
public void handle(Request request, Response response) {
- checkUserRights();
-
- ActivityQuery query = logService.newActivityQuery();
- query.setTypes(Arrays.asList(Activity.Type.ANALYSIS_REPORT));
+ UserSession.get().checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
- SearchOptions searchOptions = SearchOptions.create(request);
- QueryContext queryContext = mapping.newQueryOptions(searchOptions);
+ ActivityQuery query = new ActivityQuery();
+ query.setTypes(Arrays.asList(Activity.Type.ANALYSIS_REPORT.name()));
- Result<Activity> results = logService.search(query, queryContext);
+ SearchOptions options = new SearchOptions();
+ options.setPage(request.mandatoryParamAsInt(IssuesWs.Param.PAGE), request.mandatoryParamAsInt(IssuesWs.Param.PAGE_SIZE));
+ SearchResult<ActivityDoc> results = activityIndex.search(query, options);
JsonWriter json = response.newJsonWriter().beginObject();
- searchOptions.writeStatistics(json, results);
+ options.writeJson(json, results.getTotal());
writeReports(results, json);
json.endObject().close();
}
- private void checkUserRights() {
- UserSession.get().checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
- }
-
- private void writeReports(Result<Activity> result, JsonWriter json) {
+ private void writeReports(SearchResult<ActivityDoc> result, JsonWriter json) {
json.name("reports").beginArray();
- for (Activity reportActivity : result.getHits()) {
+ for (ActivityDoc doc : result.getDocs()) {
json.beginObject();
- for (Map.Entry<String, String> detail : reportActivity.details().entrySet()) {
+ for (Map.Entry<String, String> detail : doc.getDetails().entrySet()) {
json.prop(detail.getKey(), detail.getValue());
}
json.endObject();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/IsQueueEmptyWebService.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/IsQueueEmptyWebService.java
index 986438a7883..611043076e6 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/IsQueueEmptyWebService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/IsQueueEmptyWebService.java
@@ -26,7 +26,7 @@ import org.sonar.api.server.ws.RequestHandler;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.server.computation.AnalysisReportQueue;
+import org.sonar.server.computation.ReportQueue;
import java.util.List;
@@ -38,7 +38,7 @@ public class IsQueueEmptyWebService implements WebService {
private final IsQueueEmptyWsAction action;
- public IsQueueEmptyWebService(AnalysisReportQueue queue) {
+ public IsQueueEmptyWebService(ReportQueue queue) {
this.action = new IsQueueEmptyWsAction(queue);
}
@@ -52,9 +52,9 @@ public class IsQueueEmptyWebService implements WebService {
}
static class IsQueueEmptyWsAction implements RequestHandler {
- private final AnalysisReportQueue queue;
+ private final ReportQueue queue;
- public IsQueueEmptyWsAction(AnalysisReportQueue queue) {
+ public IsQueueEmptyWsAction(ReportQueue queue) {
this.queue = queue;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueWsAction.java
index cf9f54029cc..39e6d3dcff4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueWsAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueWsAction.java
@@ -26,7 +26,7 @@ import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.server.computation.AnalysisReportQueue;
+import org.sonar.server.computation.ReportQueue;
import java.util.List;
@@ -36,9 +36,9 @@ import static org.sonar.api.utils.DateUtils.longToDate;
* @since 5.0
*/
public class QueueWsAction implements ComputationWsAction, RequestHandler {
- private final AnalysisReportQueue queue;
+ private final ReportQueue queue;
- public QueueWsAction(AnalysisReportQueue queue) {
+ public QueueWsAction(ReportQueue queue) {
this.queue = queue;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportWsAction.java
index d474e73bb3b..7a7c54d001d 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportWsAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportWsAction.java
@@ -20,12 +20,15 @@
package org.sonar.server.computation.ws;
+import org.apache.commons.io.IOUtils;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.RequestHandler;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
-import org.sonar.server.computation.AnalysisReportQueue;
+import org.sonar.core.permission.GlobalPermissions;
import org.sonar.server.computation.ComputationThreadLauncher;
+import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.user.UserSession;
import java.io.InputStream;
@@ -33,13 +36,12 @@ public class SubmitReportWsAction implements ComputationWsAction, RequestHandler
public static final String ACTION = "submit_report";
public static final String PARAM_PROJECT_KEY = "projectKey";
- public static final String PARAM_SNAPSHOT = "snapshot";
public static final String PARAM_REPORT_DATA = "report";
- private final AnalysisReportQueue queue;
+ private final ReportQueue queue;
private final ComputationThreadLauncher workerLauncher;
- public SubmitReportWsAction(AnalysisReportQueue queue, ComputationThreadLauncher workerLauncher) {
+ public SubmitReportWsAction(ReportQueue queue, ComputationThreadLauncher workerLauncher) {
this.queue = queue;
this.workerLauncher = workerLauncher;
}
@@ -59,29 +61,28 @@ public class SubmitReportWsAction implements ComputationWsAction, RequestHandler
.setExampleValue("org.codehaus.sonar:sonar");
action
- .createParam(PARAM_SNAPSHOT)
- .setRequired(true)
- .setDescription("Snapshot ID")
- .setExampleValue("123");
-
- action
.createParam(PARAM_REPORT_DATA)
- .setRequired(false)
+ .setRequired(true)
.setDescription("Report file. Format is not an API, it changes among SonarQube versions.");
}
@Override
public void handle(Request request, Response response) throws Exception {
+ UserSession.get().checkGlobalPermission(GlobalPermissions.SCAN_EXECUTION);
String projectKey = request.mandatoryParam(PARAM_PROJECT_KEY);
- long snapshotId = request.mandatoryParamAsLong(PARAM_SNAPSHOT);
- try (InputStream reportData = request.paramAsInputStream(PARAM_REPORT_DATA)) {
- String reportKey = queue.add(projectKey, snapshotId, reportData);
+ InputStream reportData = request.paramAsInputStream(PARAM_REPORT_DATA);
+ try {
+ ReportQueue.Item item = queue.add(projectKey, reportData);
workerLauncher.startAnalysisTaskNow();
response.newJsonWriter()
.beginObject()
- .prop("key", reportKey)
+ // do not write integer for forward-compatibility, for example
+ // if we want to write UUID later
+ .prop("key", String.valueOf(item.dto.getId()))
.endObject()
.close();
+ } finally {
+ IOUtils.closeQuietly(reportData);
}
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMigration.java b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMigration.java
index 41b28a488dd..ca1ca126cd8 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMigration.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMigration.java
@@ -21,13 +21,15 @@ package org.sonar.server.db.migrations.v44;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.rule.RuleKey;
-import org.sonar.core.activity.Activity;
+import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.api.utils.internal.Uuids;
import org.sonar.core.activity.db.ActivityDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.migration.v44.ChangeLog;
import org.sonar.core.persistence.migration.v44.Migration44Mapper;
import org.sonar.core.qualityprofile.db.ActiveRuleKey;
import org.sonar.core.rule.SeverityUtil;
+import org.sonar.server.activity.Activity;
import org.sonar.server.activity.db.ActivityDao;
import org.sonar.server.db.DbClient;
import org.sonar.server.db.migrations.DatabaseMigration;
@@ -99,11 +101,16 @@ public class ChangeLogMigration implements DatabaseMigration {
}
private void saveActiveRuleChange(DbSession session, ActiveRuleChange ruleChange, String author, Date currentTimeStamp) {
- ActivityDto activity = ActivityDto.createFor(ruleChange);
- activity.setType(Activity.Type.QPROFILE);
- activity.setAuthor(author);
- activity.setCreatedAt(currentTimeStamp);
- dao.insert(session, activity);
+ Activity activity = ruleChange.toActivity();
+ ActivityDto dto = new ActivityDto();
+ dto.setKey(Uuids.create());
+ dto.setType(Activity.Type.QPROFILE.name());
+ dto.setAction(activity.getAction());
+ dto.setMessage(activity.getMessage());
+ dto.setAuthor(author);
+ dto.setData(KeyValueFormat.format(activity.getData()));
+ dto.setCreatedAt(currentTimeStamp);
+ dao.insert(session, dto);
}
private void processRuleChange(ActiveRuleChange ruleChange, ChangeLog change) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/es/BaseIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/es/BaseIndexer.java
index 5f88f181b3c..39a0f443e89 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/es/BaseIndexer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/es/BaseIndexer.java
@@ -33,42 +33,62 @@ import java.util.concurrent.TimeUnit;
public abstract class BaseIndexer implements ServerComponent, Startable {
private final ThreadPoolExecutor executor;
- private final String indexName, typeName;
+ private final String indexName, typeName, dateFieldName;
protected final EsClient esClient;
private volatile long lastUpdatedAt = 0L;
- protected BaseIndexer(EsClient client, long threadKeepAliveSeconds, String indexName, String typeName) {
+ /**
+ * Indexers are disabled during server startup, to avoid too many consecutive refreshes of the same index
+ * An example is RegisterQualityProfiles. If {@link org.sonar.server.activity.index.ActivityIndexer} is enabled by
+ * default during startup, then each new activated rule generates a bulk request with a single document and then
+ * asks for index refresh -> big performance hit.
+ *
+ * Indices are populated and refreshed when all startup components have been executed. See
+ * {@link org.sonar.server.search.IndexSynchronizer}
+ */
+ private boolean enabled = false;
+
+ protected BaseIndexer(EsClient client, long threadKeepAliveSeconds, String indexName, String typeName,
+ String dateFieldName) {
this.indexName = indexName;
this.typeName = typeName;
+ this.dateFieldName = dateFieldName;
this.esClient = client;
this.executor = new ThreadPoolExecutor(0, 1,
threadKeepAliveSeconds, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
}
public void index() {
- final long requestedAt = System.currentTimeMillis();
- Future submit = executor.submit(new Runnable() {
- @Override
- public void run() {
- if (requestedAt > lastUpdatedAt) {
- long l = doIndex(lastUpdatedAt);
- // l can be 0 if no documents were indexed
- lastUpdatedAt = Math.max(l, lastUpdatedAt);
+ if (enabled) {
+ final long requestedAt = System.currentTimeMillis();
+ Future submit = executor.submit(new Runnable() {
+ @Override
+ public void run() {
+ if (requestedAt > lastUpdatedAt) {
+ long l = doIndex(lastUpdatedAt);
+ // l can be 0 if no documents were indexed
+ lastUpdatedAt = Math.max(l, lastUpdatedAt);
+ }
}
+ });
+ try {
+ Uninterruptibles.getUninterruptibly(submit);
+ } catch (ExecutionException e) {
+ Throwables.propagate(e);
}
- });
- try {
- Uninterruptibles.getUninterruptibly(submit);
- } catch (ExecutionException e) {
- Throwables.propagate(e);
}
}
protected abstract long doIndex(long lastUpdatedAt);
+ public BaseIndexer setEnabled(boolean b) {
+ this.enabled = b;
+ return this;
+ }
+
@Override
public void start() {
- lastUpdatedAt = esClient.getLastUpdatedAt(indexName, typeName);
+ lastUpdatedAt = esClient.getMaxFieldValue(indexName, typeName, dateFieldName);
}
@Override
diff --git a/server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java
index 28384f0f074..fd6f3fec50c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java
@@ -57,7 +57,6 @@ public class BulkIndexer implements Startable {
private final EsClient client;
private final String indexName;
private boolean large = false;
- private boolean refresh = true;
private long flushByteSize = FLUSH_BYTE_SIZE;
private BulkRequestBuilder bulkRequest = null;
private Map<String, Object> largeInitialSettings = null;
@@ -83,12 +82,6 @@ public class BulkIndexer implements Startable {
return this;
}
- public BulkIndexer setRefresh(boolean b) {
- Preconditions.checkState(bulkRequest == null, ALREADY_STARTED_MESSAGE);
- this.refresh = b;
- return this;
- }
-
/**
* Default value is {@link org.sonar.server.es.BulkIndexer#FLUSH_BYTE_SIZE}
* @see org.elasticsearch.common.unit.ByteSizeValue
@@ -144,9 +137,7 @@ public class BulkIndexer implements Startable {
progress.stop();
}
- if (refresh) {
- client.prepareRefresh(indexName).get();
- }
+ client.prepareRefresh(indexName).get();
if (large) {
// optimize lucene segments and revert index settings
// Optimization must be done before re-applying replicas:
diff --git a/server/sonar-server/src/main/java/org/sonar/server/es/EsClient.java b/server/sonar-server/src/main/java/org/sonar/server/es/EsClient.java
index 5c252935bc4..61e61608210 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/es/EsClient.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/es/EsClient.java
@@ -183,12 +183,12 @@ public class EsClient implements Startable {
return new ProxyClearCacheRequestBuilder(client).setIndices(indices);
}
- public long getLastUpdatedAt(String indexName, String typeName) {
+ public long getMaxFieldValue(String indexName, String typeName, String fieldName) {
SearchRequestBuilder request = prepareSearch(indexName)
.setTypes(typeName)
.setQuery(QueryBuilders.matchAllQuery())
.setSize(0)
- .addAggregation(AggregationBuilders.max("latest").field("updatedAt"));
+ .addAggregation(AggregationBuilders.max("latest").field(fieldName));
Max max = request.get().getAggregations().get("latest");
return (long) max.getValue();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/es/IndexCreator.java b/server/sonar-server/src/main/java/org/sonar/server/es/IndexCreator.java
index 909fd00bcba..1ef1d9ce3b8 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/es/IndexCreator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/es/IndexCreator.java
@@ -45,17 +45,17 @@ public class IndexCreator implements ServerComponent, Startable {
private static final String SETTING_HASH = "sonar_hash";
private final EsClient client;
- private final IndexRegistry registry;
+ private final IndexDefinitions definitions;
- public IndexCreator(EsClient client, IndexRegistry registry) {
+ public IndexCreator(EsClient client, IndexDefinitions definitions) {
this.client = client;
- this.registry = registry;
+ this.definitions = definitions;
}
@Override
public void start() {
// create indices that do not exist or that have a new definition (different mapping, cluster enabled, ...)
- for (IndexRegistry.Index index : registry.getIndices().values()) {
+ for (IndexDefinitions.Index index : definitions.getIndices().values()) {
boolean exists = client.prepareIndicesExist(index.getName()).get().isExists();
if (exists && needsToDeleteIndex(index)) {
LOGGER.info(String.format("Delete index %s (settings changed)", index.getName()));
@@ -73,7 +73,7 @@ public class IndexCreator implements ServerComponent, Startable {
// nothing to do
}
- private void createIndex(IndexRegistry.Index index) {
+ private void createIndex(IndexDefinitions.Index index) {
LOGGER.info(String.format("Create index %s", index.getName()));
ImmutableSettings.Builder settings = ImmutableSettings.builder();
settings.put(index.getSettings());
@@ -88,7 +88,7 @@ public class IndexCreator implements ServerComponent, Startable {
client.waitForStatus(ClusterHealthStatus.YELLOW);
// create types
- for (Map.Entry<String, IndexRegistry.IndexType> entry : index.getTypes().entrySet()) {
+ for (Map.Entry<String, IndexDefinitions.IndexType> entry : index.getTypes().entrySet()) {
LOGGER.info(String.format("Create type %s/%s", index.getName(), entry.getKey()));
PutMappingResponse mappingResponse = client.preparePutMapping(index.getName())
.setType(entry.getKey())
@@ -106,7 +106,7 @@ public class IndexCreator implements ServerComponent, Startable {
client.nativeClient().admin().indices().prepareDelete(indexName).get();
}
- private boolean needsToDeleteIndex(IndexRegistry.Index index) {
+ private boolean needsToDeleteIndex(IndexDefinitions.Index index) {
boolean toBeDeleted = false;
String hash = client.nativeClient().admin().indices().prepareGetSettings(index.getName()).get().getSetting(index.getName(), "index." + SETTING_HASH);
if (hash != null) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/es/IndexDefinitionHash.java b/server/sonar-server/src/main/java/org/sonar/server/es/IndexDefinitionHash.java
index 6df309abaa2..6b2c208d022 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/es/IndexDefinitionHash.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/es/IndexDefinitionHash.java
@@ -37,7 +37,7 @@ class IndexDefinitionHash {
private static final char DELIMITER = ',';
- String of(IndexRegistry.Index index) {
+ String of(IndexDefinitions.Index index) {
return of(index.getSettings().getAsMap(), index.getTypes());
}
@@ -50,8 +50,8 @@ class IndexDefinitionHash {
}
private void appendObject(StringBuilder sb, Object value) {
- if (value instanceof IndexRegistry.IndexType) {
- appendIndexType(sb, (IndexRegistry.IndexType) value);
+ if (value instanceof IndexDefinitions.IndexType) {
+ appendIndexType(sb, (IndexDefinitions.IndexType) value);
} else if (value instanceof Map) {
appendMap(sb, (Map) value);
} else if (value instanceof Iterable) {
@@ -61,7 +61,7 @@ class IndexDefinitionHash {
}
}
- private void appendIndexType(StringBuilder sb, IndexRegistry.IndexType type) {
+ private void appendIndexType(StringBuilder sb, IndexDefinitions.IndexType type) {
appendMap(sb, type.getAttributes());
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/es/IndexRegistry.java b/server/sonar-server/src/main/java/org/sonar/server/es/IndexDefinitions.java
index 972830067be..771f9b8ed31 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/es/IndexRegistry.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/es/IndexDefinitions.java
@@ -30,7 +30,7 @@ import java.util.Map;
/**
* This class collects definitions of all Elasticsearch indices during server startup
*/
-public class IndexRegistry implements ServerComponent, Startable {
+public class IndexDefinitions implements ServerComponent, Startable {
/**
* Immutable copy of {@link org.sonar.server.es.NewIndex}
@@ -88,7 +88,7 @@ public class IndexRegistry implements ServerComponent, Startable {
private final Map<String, Index> byKey = Maps.newHashMap();
private final IndexDefinition[] defs;
- public IndexRegistry(IndexDefinition[] defs) {
+ public IndexDefinitions(IndexDefinition[] defs) {
this.defs = defs;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/es/NewIndex.java b/server/sonar-server/src/main/java/org/sonar/server/es/NewIndex.java
index 4459fd5b3db..22493030b9e 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/es/NewIndex.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/es/NewIndex.java
@@ -96,6 +96,10 @@ public class NewIndex {
return setProperty(fieldName, ImmutableMap.of("type", "long"));
}
+ public NewIndexType createDynamicNestedField(String fieldName) {
+ return setProperty(fieldName, ImmutableMap.of("type", "nested", "dynamic", "true"));
+ }
+
public NewIndexType createShortField(String fieldName) {
return setProperty(fieldName, ImmutableMap.of("type", "short"));
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueAuthorizationIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueAuthorizationIndexer.java
index 04bf850b395..0a8c3efd3f4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueAuthorizationIndexer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueAuthorizationIndexer.java
@@ -47,7 +47,7 @@ public class IssueAuthorizationIndexer extends BaseIndexer {
private final DbClient dbClient;
public IssueAuthorizationIndexer(DbClient dbClient, EsClient esClient) {
- super(esClient, 0L, IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION);
+ super(esClient, 0L, IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, IssueIndexDefinition.FIELD_ISSUE_TECHNICAL_UPDATED_AT);
this.dbClient = dbClient;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java
index fdfedca9850..efbe0b67abe 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java
@@ -311,6 +311,10 @@ public class IssueDoc extends BaseDoc implements Issue {
return this;
}
+ public Date getTechnicalUpdateDate() {
+ return getFieldAsDate(IssueIndexDefinition.FIELD_ISSUE_TECHNICAL_UPDATED_AT);
+ }
+
public IssueDoc setTechnicalUpdateDate(@Nullable Date d) {
setField(IssueIndexDefinition.FIELD_ISSUE_TECHNICAL_UPDATED_AT, d);
return this;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java
index f705776bed4..68292b43a93 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java
@@ -93,6 +93,9 @@ public class IssueIndexDefinition implements IndexDefinition {
public void define(IndexDefinitionContext context) {
NewIndex index = context.create(INDEX);
+ // refresh is handled by IssueIndexer
+ index.getSettings().put("index.refresh_interval", "-1");
+
// shards
boolean clusterMode = settings.getBoolean(ProcessConstants.CLUSTER_ACTIVATE);
if (clusterMode) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexer.java
index e43df41dd98..84420be5d48 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexer.java
@@ -38,7 +38,7 @@ public class IssueIndexer extends BaseIndexer {
private final DbClient dbClient;
public IssueIndexer(DbClient dbClient, EsClient esClient) {
- super(esClient, 300, IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE);
+ super(esClient, 300, IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, IssueIndexDefinition.FIELD_ISSUE_TECHNICAL_UPDATED_AT);
this.dbClient = dbClient;
}
@@ -82,7 +82,7 @@ public class IssueIndexer extends BaseIndexer {
bulk.add(newUpsertRequest(issue));
// it's more efficient to sort programmatically than in SQL on some databases (MySQL for instance)
- maxDate = Math.max(maxDate, issue.updateDate().getTime());
+ maxDate = Math.max(maxDate, issue.getTechnicalUpdateDate().getTime());
}
bulk.stop();
return maxDate;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueResultSetIterator.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueResultSetIterator.java
index 7f24b0a56cd..76de0d82363 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueResultSetIterator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueResultSetIterator.java
@@ -150,7 +150,7 @@ class IssueResultSetIterator extends ResultSetIterator<IssueDoc> {
String key = rs.getString(1);
String projectUuid = rs.getString(2);
- // all the keys must be present, even if value is null
+ // all the fields must be present, even if value is null
doc.setKey(key);
doc.setProjectUuid(projectUuid);
doc.setTechnicalUpdateDate(new Date(rs.getLong(3)));
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesEmailTemplate.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesEmailTemplate.java
index 9caba17934a..df98f6eee5e 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesEmailTemplate.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesEmailTemplate.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.issue.notification;
+import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import org.sonar.api.config.EmailSettings;
import org.sonar.api.i18n.I18n;
@@ -27,6 +28,9 @@ import org.sonar.api.rule.Severity;
import org.sonar.api.utils.DateUtils;
import org.sonar.plugins.emailnotifications.api.EmailMessage;
import org.sonar.plugins.emailnotifications.api.EmailTemplate;
+import org.sonar.server.issue.notification.NewIssuesStatistics.METRIC;
+import org.sonar.server.user.index.UserDoc;
+import org.sonar.server.user.index.UserIndex;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
@@ -42,13 +46,30 @@ public class NewIssuesEmailTemplate extends EmailTemplate {
public static final String FIELD_PROJECT_NAME = "projectName";
public static final String FIELD_PROJECT_KEY = "projectKey";
public static final String FIELD_PROJECT_DATE = "projectDate";
+ public static final String FIELD_PROJECT_UUID = "projectUuid";
+
+ private static final char NEW_LINE = '\n';
+ private static final String TAB = " ";
+ private static final String DOT = ".";
+ private static final String COUNT = DOT + "count";
+ private static final String LABEL = DOT + "label";
private final EmailSettings settings;
private final I18n i18n;
+ private final UserIndex userIndex;
- public NewIssuesEmailTemplate(EmailSettings settings, I18n i18n) {
+ public NewIssuesEmailTemplate(EmailSettings settings, I18n i18n, UserIndex userIndex) {
this.settings = settings;
this.i18n = i18n;
+ this.userIndex = userIndex;
+ }
+
+ public static String encode(String toEncode) {
+ try {
+ return URLEncoder.encode(toEncode, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalStateException("Encoding not supported", e);
+ }
}
@Override
@@ -58,44 +79,106 @@ public class NewIssuesEmailTemplate extends EmailTemplate {
}
String projectName = notification.getFieldValue(FIELD_PROJECT_NAME);
- StringBuilder sb = new StringBuilder();
- sb.append("Project: ").append(projectName).append("\n\n");
- sb.append(notification.getFieldValue("count")).append(" new issues").append("\n\n");
- sb.append(" ");
+ StringBuilder message = new StringBuilder();
+ message.append("Project: ").append(projectName).append(NEW_LINE).append(NEW_LINE);
+ appendSeverity(message, notification);
+ appendAssignees(message, notification);
+ appendTags(message, notification);
+ appendComponents(message, notification);
+ appendFooter(message, notification);
+
+ return new EmailMessage()
+ .setMessageId("new-issues/" + notification.getFieldValue(FIELD_PROJECT_KEY))
+ .setSubject(projectName + ": " + notification.getFieldValue(METRIC.SEVERITY + COUNT) + " new issues")
+ .setMessage(message.toString());
+ }
+
+ private void appendComponents(StringBuilder message, Notification notification) {
+ if (notification.getFieldValue(METRIC.COMPONENT + ".1.label") == null) {
+ return;
+ }
+
+ message.append(" Components:\n");
+ int i = 1;
+ while (notification.getFieldValue(METRIC.COMPONENT + DOT + i + LABEL) != null && i <= 5) {
+ String component = notification.getFieldValue(METRIC.COMPONENT + DOT + i + LABEL);
+ message
+ .append(TAB).append(TAB)
+ .append(component)
+ .append(" : ")
+ .append(notification.getFieldValue(METRIC.COMPONENT + DOT + i + COUNT))
+ .append("\n");
+ i += 1;
+ }
+ }
+
+ private void appendAssignees(StringBuilder message, Notification notification) {
+ if (notification.getFieldValue(METRIC.LOGIN + DOT + "1" + LABEL) == null) {
+ return;
+ }
+
+ message.append(TAB + "Assignee - ");
+ int i = 1;
+ while (notification.getFieldValue(METRIC.LOGIN + DOT + i + LABEL) != null && i <= 5) {
+ String login = notification.getFieldValue(METRIC.LOGIN + DOT + i + LABEL);
+ UserDoc user = userIndex.getNullableByLogin(login);
+ String name = user == null ? null : user.name();
+ message.append(Objects.firstNonNull(name, login))
+ .append(": ")
+ .append(notification.getFieldValue(METRIC.LOGIN + DOT + i + COUNT));
+ if (i < 5) {
+ message.append(TAB);
+ }
+ i += 1;
+ }
+
+ message.append("\n");
+ }
+
+ private void appendTags(StringBuilder message, Notification notification) {
+ if (notification.getFieldValue(METRIC.TAGS + DOT + "1" + LABEL) == null) {
+ return;
+ }
+
+ message.append(TAB + "Tags - ");
+ int i = 1;
+ while (notification.getFieldValue(METRIC.TAGS + DOT + i + LABEL) != null && i <= 5) {
+ String tag = notification.getFieldValue(METRIC.TAGS + DOT + i + LABEL);
+ message.append(tag)
+ .append(": ")
+ .append(notification.getFieldValue(METRIC.TAGS + DOT + i + COUNT));
+ if (i < 5) {
+ message.append(TAB);
+ }
+ i += 1;
+ }
+ message.append(NEW_LINE);
+ }
+
+ private void appendSeverity(StringBuilder message, Notification notification) {
+ message.append(notification.getFieldValue(METRIC.SEVERITY + COUNT)).append(" new issues - Total debt: ")
+ .append(notification.getFieldValue(METRIC.DEBT + COUNT))
+ .append(NEW_LINE).append(NEW_LINE)
+ .append(TAB + "Severity - ");
for (Iterator<String> severityIterator = Lists.reverse(Severity.ALL).iterator(); severityIterator.hasNext();) {
String severity = severityIterator.next();
String severityLabel = i18n.message(getLocale(), "severity." + severity, severity);
- sb.append(severityLabel).append(": ").append(notification.getFieldValue("count-" + severity));
+ message.append(severityLabel).append(": ").append(notification.getFieldValue(METRIC.SEVERITY + DOT + severity + COUNT));
if (severityIterator.hasNext()) {
- sb.append(" ");
+ message.append(TAB);
}
}
- sb.append('\n');
-
- appendFooter(sb, notification);
-
- return new EmailMessage()
- .setMessageId("new-issues/" + notification.getFieldValue(FIELD_PROJECT_KEY))
- .setSubject(projectName + ": new issues")
- .setMessage(sb.toString());
+ message.append(NEW_LINE);
}
- private void appendFooter(StringBuilder sb, Notification notification) {
- String projectUuid = notification.getFieldValue("projectUuid");
+ private void appendFooter(StringBuilder message, Notification notification) {
+ String projectUuid = notification.getFieldValue(FIELD_PROJECT_UUID);
String dateString = notification.getFieldValue(FIELD_PROJECT_DATE);
if (projectUuid != null && dateString != null) {
Date date = DateUtils.parseDateTime(dateString);
String url = String.format("%s/issues/search#projectUuids=%s|createdAt=%s",
settings.getServerBaseURL(), encode(projectUuid), encode(DateUtils.formatDateTime(date)));
- sb.append("\n").append("See it in SonarQube: ").append(url).append("\n");
- }
- }
-
- public static String encode(String toEncode) {
- try {
- return URLEncoder.encode(toEncode, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new IllegalStateException("Encoding not supported", e);
+ message.append("\n").append("See it in SonarQube: ").append(url).append(NEW_LINE);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotification.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotification.java
index ccade3f7025..ae387b1598d 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotification.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotification.java
@@ -19,59 +19,69 @@
*/
package org.sonar.server.issue.notification;
-import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import org.sonar.api.component.Component;
-import org.sonar.api.issue.Issue;
import org.sonar.api.notifications.Notification;
import org.sonar.api.rule.Severity;
import org.sonar.api.utils.DateUtils;
import org.sonar.core.component.ComponentDto;
+import org.sonar.server.issue.notification.NewIssuesStatistics.METRIC;
import java.util.Date;
+import java.util.List;
+
+import static org.sonar.server.issue.notification.NewIssuesEmailTemplate.*;
+import static org.sonar.server.issue.notification.NewIssuesStatistics.METRIC.SEVERITY;
public class NewIssuesNotification extends Notification {
public static final String TYPE = "new-issues";
+ private static final String COUNT = ".count";
public NewIssuesNotification() {
super(TYPE);
}
public NewIssuesNotification setAnalysisDate(Date d) {
- setFieldValue("projectDate", DateUtils.formatDateTime(d));
+ setFieldValue(FIELD_PROJECT_DATE, DateUtils.formatDateTime(d));
return this;
}
public NewIssuesNotification setProject(ComponentDto project) {
- setFieldValue("projectName", project.longName());
- setFieldValue("projectKey", project.key());
- setFieldValue("projectUuid", project.uuid());
+ setFieldValue(FIELD_PROJECT_NAME, project.longName());
+ setFieldValue(FIELD_PROJECT_KEY, project.key());
+ setFieldValue(FIELD_PROJECT_UUID, project.uuid());
return this;
}
- public NewIssuesNotification setStatistics(Component project, Stats stats) {
- setDefaultMessage(stats.size() + " new issues on " + project.longName() + ".\n");
- setFieldValue("count", String.valueOf(stats.size()));
- for (String severity : Severity.ALL) {
- setFieldValue("count-" + severity, String.valueOf(stats.countIssuesWithSeverity(severity)));
- }
+ public NewIssuesNotification setStatistics(Component project, NewIssuesStatistics stats) {
+ setDefaultMessage(stats.countForMetric(SEVERITY) + " new issues on " + project.longName() + ".\n");
+
+ setSeverityStatistics(stats);
+ setTop5CountsForMetric(stats, METRIC.LOGIN);
+ setTop5CountsForMetric(stats, METRIC.TAGS);
+ setTop5CountsForMetric(stats, METRIC.COMPONENT);
+
return this;
}
- public static class Stats {
- private final Multiset<String> set = HashMultiset.create();
-
- public void add(Issue issue) {
- set.add(issue.severity());
- }
+ public NewIssuesNotification setDebt(String debt) {
+ setFieldValue(METRIC.DEBT + COUNT, debt);
+ return this;
+ }
- public int countIssuesWithSeverity(String severity) {
- return set.count(severity);
+ private void setTop5CountsForMetric(NewIssuesStatistics stats, METRIC metric) {
+ List<Multiset.Entry<String>> loginStats = stats.statsForMetric(metric);
+ for (int i = 0; i < 5 && i < loginStats.size(); i++) {
+ setFieldValue(metric + "." + (i + 1) + COUNT, String.valueOf(loginStats.get(i).getCount()));
+ setFieldValue(metric + "." + (i + 1) + ".label", loginStats.get(i).getElement());
}
+ }
- public int size() {
- return set.size();
+ private void setSeverityStatistics(NewIssuesStatistics stats) {
+ setFieldValue(SEVERITY + COUNT, String.valueOf(stats.countForMetric(SEVERITY)));
+ for (String severity : Severity.ALL) {
+ setFieldValue(SEVERITY + "." + severity + COUNT, String.valueOf(stats.countForMetric(SEVERITY, severity)));
}
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesStatistics.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesStatistics.java
new file mode 100644
index 00000000000..e2ca668151c
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesStatistics.java
@@ -0,0 +1,129 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.issue.notification;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.utils.Duration;
+import org.sonar.core.util.MultiSets;
+
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.sonar.server.issue.notification.NewIssuesStatistics.METRIC.*;
+
+public class NewIssuesStatistics {
+ private Map<String, Stats> statisticsByLogin = new HashMap<>();
+ private Stats globalStatistics = new Stats();
+
+ public void add(Issue issue) {
+ globalStatistics.add(issue);
+ String login = issue.assignee();
+ if (login != null) {
+ statisticsForLogin(login).add(issue);
+ }
+ }
+
+ private Stats statisticsForLogin(String login) {
+ if (statisticsByLogin.get(login) == null) {
+ statisticsByLogin.put(login, new Stats());
+ }
+ return statisticsByLogin.get(login);
+ }
+
+ public int countForMetric(METRIC metric) {
+ return globalStatistics.distributionFor(metric).size();
+ }
+
+ public int countForMetric(METRIC metric, String label) {
+ return globalStatistics.distributionFor(metric).count(label);
+ }
+
+ public List<Multiset.Entry<String>> statsForMetric(METRIC metric) {
+ return MultiSets.listOrderedByHighestCounts(globalStatistics.distributionFor(metric));
+ }
+
+ public Duration debt() {
+ return globalStatistics.debt();
+ }
+
+ public boolean hasIssues() {
+ return globalStatistics.hasIssues();
+ }
+
+ public enum METRIC {
+ SEVERITY(true), TAGS(true), COMPONENT(true), LOGIN(true), DEBT(false);
+ private final boolean computeDistribution;
+
+ METRIC(boolean computeDistribution) {
+ this.computeDistribution = computeDistribution;
+ }
+
+ boolean isComputedByDistribution() {
+ return this.computeDistribution;
+ }
+ }
+
+ private static class Stats {
+ private final Map<METRIC, Multiset<String>> distributions = new EnumMap<>(METRIC.class);
+ private long debtInMinutes = 0L;
+
+ public Stats() {
+ for (METRIC metric : METRIC.values()) {
+ if (metric.isComputedByDistribution()) {
+ distributions.put(metric, HashMultiset.<String>create());
+ }
+ }
+ }
+
+ public void add(Issue issue) {
+ distributions.get(SEVERITY).add(issue.severity());
+ distributions.get(COMPONENT).add(issue.componentUuid());
+ if (issue.assignee() != null) {
+ distributions.get(LOGIN).add(issue.assignee());
+ }
+ for (String tag : issue.tags()) {
+ distributions.get(TAGS).add(tag);
+ }
+ Duration debt = issue.debt();
+ if (debt != null) {
+ debtInMinutes += debt.toMinutes();
+ }
+ }
+
+ public Multiset<String> distributionFor(METRIC metric) {
+ checkArgument(metric.isComputedByDistribution());
+ return distributions.get(metric);
+ }
+
+ public Duration debt() {
+ return Duration.create(debtInMinutes);
+ }
+
+ public boolean hasIssues() {
+ return distributions.get(SEVERITY) != null;
+ }
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
index c5e4b4770a0..9898640cb76 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
@@ -63,7 +63,13 @@ import org.sonar.server.user.UserSession;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
@@ -263,7 +269,7 @@ public class SearchAction implements BaseIssuesWsAction {
@Override
public final void handle(Request request, Response response) throws Exception {
SearchOptions options = new SearchOptions();
- options.setPage(request.mandatoryParamAsInt(IssuesWs.Param.PAGE), request.mandatoryParamAsInt(IssuesWs.Param.PAGE_SIZE));
+ options.setPage(request.mandatoryParamAsInt(WebService.Param.PAGE), request.mandatoryParamAsInt(WebService.Param.PAGE_SIZE));
options.addFacets(request.paramAsStrings(WebService.Param.FACETS));
IssueQuery query = issueQueryService.createFromRequest(request);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/InternalPermissionService.java b/server/sonar-server/src/main/java/org/sonar/server/permission/InternalPermissionService.java
index 13b1897e2e9..f28de356546 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/InternalPermissionService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/permission/InternalPermissionService.java
@@ -227,7 +227,7 @@ public class InternalPermissionService implements ServerComponent {
}
private Long getTargetedUser(DbSession session, String userLogin) {
- UserDto user = dbClient.userDao().selectActiveUserByLogin(userLogin, session);
+ UserDto user = dbClient.userDao().selectActiveUserByLogin(session, userLogin);
badRequestIfNullResult(user, OBJECT_TYPE_USER, userLogin);
return user.getId();
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
index 959fe205322..1c03d4fb89c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
@@ -53,7 +53,12 @@ import org.sonar.core.measure.db.MeasureFilterDao;
import org.sonar.core.metric.DefaultMetricFinder;
import org.sonar.core.notification.DefaultNotificationManager;
import org.sonar.core.permission.PermissionFacade;
-import org.sonar.core.persistence.*;
+import org.sonar.core.persistence.DaoUtils;
+import org.sonar.core.persistence.DatabaseVersion;
+import org.sonar.core.persistence.DefaultDatabase;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.persistence.SemaphoreUpdater;
+import org.sonar.core.persistence.SemaphoresImpl;
import org.sonar.core.purge.PurgeProfiler;
import org.sonar.core.qualitygate.db.ProjectQgateAssociationDao;
import org.sonar.core.qualitygate.db.QualityGateConditionDao;
@@ -73,11 +78,17 @@ import org.sonar.server.activity.ActivityService;
import org.sonar.server.activity.RubyQProfileActivityService;
import org.sonar.server.activity.db.ActivityDao;
import org.sonar.server.activity.index.ActivityIndex;
-import org.sonar.server.activity.index.ActivityNormalizer;
+import org.sonar.server.activity.index.ActivityIndexDefinition;
+import org.sonar.server.activity.index.ActivityIndexer;
import org.sonar.server.activity.ws.ActivitiesWebService;
import org.sonar.server.activity.ws.ActivityMapping;
import org.sonar.server.authentication.ws.AuthenticationWs;
-import org.sonar.server.batch.*;
+import org.sonar.server.batch.BatchIndex;
+import org.sonar.server.batch.BatchWs;
+import org.sonar.server.batch.GlobalRepositoryAction;
+import org.sonar.server.batch.IssuesAction;
+import org.sonar.server.batch.ProjectRepositoryAction;
+import org.sonar.server.batch.ProjectRepositoryLoader;
import org.sonar.server.charts.ChartFactory;
import org.sonar.server.component.ComponentCleanerService;
import org.sonar.server.component.ComponentService;
@@ -86,12 +97,20 @@ import org.sonar.server.component.DefaultRubyComponentService;
import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.component.db.ComponentIndexDao;
import org.sonar.server.component.db.SnapshotDao;
-import org.sonar.server.component.ws.*;
-import org.sonar.server.computation.AnalysisReportQueue;
-import org.sonar.server.computation.AnalysisReportQueueCleaner;
+import org.sonar.server.component.ws.ComponentAppAction;
+import org.sonar.server.component.ws.ComponentsWs;
+import org.sonar.server.component.ws.EventsWs;
+import org.sonar.server.component.ws.ProjectsWs;
+import org.sonar.server.component.ws.ResourcesWs;
import org.sonar.server.computation.ComputationThreadLauncher;
+import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.computation.ReportQueueCleaner;
import org.sonar.server.computation.db.AnalysisReportDao;
-import org.sonar.server.computation.ws.*;
+import org.sonar.server.computation.ws.ComputationWebService;
+import org.sonar.server.computation.ws.HistoryWsAction;
+import org.sonar.server.computation.ws.IsQueueEmptyWebService;
+import org.sonar.server.computation.ws.QueueWsAction;
+import org.sonar.server.computation.ws.SubmitReportWsAction;
import org.sonar.server.config.ws.PropertiesWs;
import org.sonar.server.dashboard.db.DashboardDao;
import org.sonar.server.dashboard.db.WidgetDao;
@@ -103,15 +122,37 @@ import org.sonar.server.db.DbClient;
import org.sonar.server.db.EmbeddedDatabaseFactory;
import org.sonar.server.db.migrations.DatabaseMigrations;
import org.sonar.server.db.migrations.DatabaseMigrator;
-import org.sonar.server.debt.*;
+import org.sonar.server.debt.DebtCharacteristicsXMLImporter;
+import org.sonar.server.debt.DebtModelBackup;
+import org.sonar.server.debt.DebtModelLookup;
+import org.sonar.server.debt.DebtModelOperations;
+import org.sonar.server.debt.DebtModelPluginRepository;
+import org.sonar.server.debt.DebtModelService;
+import org.sonar.server.debt.DebtModelXMLExporter;
+import org.sonar.server.debt.DebtRulesXMLImporter;
import org.sonar.server.design.FileDesignWidget;
import org.sonar.server.duplication.ws.DuplicationsJsonWriter;
import org.sonar.server.duplication.ws.DuplicationsParser;
import org.sonar.server.duplication.ws.DuplicationsWs;
import org.sonar.server.es.EsClient;
import org.sonar.server.es.IndexCreator;
-import org.sonar.server.es.IndexRegistry;
-import org.sonar.server.issue.*;
+import org.sonar.server.es.IndexDefinitions;
+import org.sonar.server.issue.ActionService;
+import org.sonar.server.issue.AddTagsAction;
+import org.sonar.server.issue.AssignAction;
+import org.sonar.server.issue.CommentAction;
+import org.sonar.server.issue.InternalRubyIssueService;
+import org.sonar.server.issue.IssueBulkChangeService;
+import org.sonar.server.issue.IssueChangelogFormatter;
+import org.sonar.server.issue.IssueChangelogService;
+import org.sonar.server.issue.IssueCommentService;
+import org.sonar.server.issue.IssueQueryService;
+import org.sonar.server.issue.IssueService;
+import org.sonar.server.issue.PlanAction;
+import org.sonar.server.issue.RemoveTagsAction;
+import org.sonar.server.issue.ServerIssueStorage;
+import org.sonar.server.issue.SetSeverityAction;
+import org.sonar.server.issue.TransitionAction;
import org.sonar.server.issue.actionplan.ActionPlanService;
import org.sonar.server.issue.actionplan.ActionPlanWs;
import org.sonar.server.issue.db.IssueDao;
@@ -122,8 +163,16 @@ import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueIndex;
import org.sonar.server.issue.index.IssueIndexDefinition;
import org.sonar.server.issue.index.IssueIndexer;
-import org.sonar.server.issue.notification.*;
-import org.sonar.server.issue.ws.*;
+import org.sonar.server.issue.notification.ChangesOnMyIssueNotificationDispatcher;
+import org.sonar.server.issue.notification.IssueChangesEmailTemplate;
+import org.sonar.server.issue.notification.NewFalsePositiveNotificationDispatcher;
+import org.sonar.server.issue.notification.NewIssuesEmailTemplate;
+import org.sonar.server.issue.notification.NewIssuesNotificationDispatcher;
+import org.sonar.server.issue.ws.ComponentTagsAction;
+import org.sonar.server.issue.ws.IssueActionsWriter;
+import org.sonar.server.issue.ws.IssueShowAction;
+import org.sonar.server.issue.ws.IssuesWs;
+import org.sonar.server.issue.ws.SetTagsAction;
import org.sonar.server.language.ws.LanguageWs;
import org.sonar.server.language.ws.ListAction;
import org.sonar.server.measure.MeasureFilterEngine;
@@ -140,44 +189,141 @@ import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.InternalPermissionTemplateService;
import org.sonar.server.permission.PermissionFinder;
import org.sonar.server.permission.ws.PermissionsWs;
-import org.sonar.server.platform.monitoring.*;
-import org.sonar.server.platform.ws.*;
-import org.sonar.server.plugins.*;
+import org.sonar.server.platform.monitoring.DatabaseMonitor;
+import org.sonar.server.platform.monitoring.EsMonitor;
+import org.sonar.server.platform.monitoring.JvmPropertiesMonitor;
+import org.sonar.server.platform.monitoring.PluginsMonitor;
+import org.sonar.server.platform.monitoring.SonarQubeMonitor;
+import org.sonar.server.platform.monitoring.SystemMonitor;
+import org.sonar.server.platform.ws.L10nWs;
+import org.sonar.server.platform.ws.ServerWs;
+import org.sonar.server.platform.ws.SystemInfoWsAction;
+import org.sonar.server.platform.ws.SystemRestartWsAction;
+import org.sonar.server.platform.ws.SystemWs;
+import org.sonar.server.plugins.InstalledPluginReferentialFactory;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.ServerExtensionInstaller;
+import org.sonar.server.plugins.ServerPluginJarInstaller;
+import org.sonar.server.plugins.ServerPluginJarsInstaller;
+import org.sonar.server.plugins.ServerPluginRepository;
+import org.sonar.server.plugins.UpdateCenterClient;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
import org.sonar.server.properties.ProjectSettingsFactory;
import org.sonar.server.qualitygate.QgateProjectFinder;
import org.sonar.server.qualitygate.QualityGates;
import org.sonar.server.qualitygate.RegisterQualityGates;
-import org.sonar.server.qualitygate.ws.*;
-import org.sonar.server.qualityprofile.*;
+import org.sonar.server.qualitygate.ws.QGatesAppAction;
+import org.sonar.server.qualitygate.ws.QGatesCopyAction;
+import org.sonar.server.qualitygate.ws.QGatesCreateAction;
+import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction;
+import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction;
+import org.sonar.server.qualitygate.ws.QGatesDeselectAction;
+import org.sonar.server.qualitygate.ws.QGatesDestroyAction;
+import org.sonar.server.qualitygate.ws.QGatesListAction;
+import org.sonar.server.qualitygate.ws.QGatesRenameAction;
+import org.sonar.server.qualitygate.ws.QGatesSearchAction;
+import org.sonar.server.qualitygate.ws.QGatesSelectAction;
+import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction;
+import org.sonar.server.qualitygate.ws.QGatesShowAction;
+import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction;
+import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction;
+import org.sonar.server.qualitygate.ws.QGatesWs;
+import org.sonar.server.qualityprofile.BuiltInProfiles;
+import org.sonar.server.qualityprofile.QProfileBackuper;
+import org.sonar.server.qualityprofile.QProfileCopier;
+import org.sonar.server.qualityprofile.QProfileExporters;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.QProfileLoader;
+import org.sonar.server.qualityprofile.QProfileLookup;
+import org.sonar.server.qualityprofile.QProfileProjectLookup;
+import org.sonar.server.qualityprofile.QProfileProjectOperations;
+import org.sonar.server.qualityprofile.QProfileReset;
+import org.sonar.server.qualityprofile.QProfileService;
+import org.sonar.server.qualityprofile.QProfiles;
+import org.sonar.server.qualityprofile.RegisterQualityProfiles;
+import org.sonar.server.qualityprofile.RuleActivator;
+import org.sonar.server.qualityprofile.RuleActivatorContextFactory;
import org.sonar.server.qualityprofile.db.ActiveRuleDao;
import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
-import org.sonar.server.qualityprofile.ws.*;
-import org.sonar.server.rule.*;
+import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions;
+import org.sonar.server.qualityprofile.ws.ProfilesWs;
+import org.sonar.server.qualityprofile.ws.QProfileRestoreBuiltInAction;
+import org.sonar.server.qualityprofile.ws.QProfilesWs;
+import org.sonar.server.qualityprofile.ws.RuleActivationActions;
+import org.sonar.server.rule.DefaultRuleFinder;
+import org.sonar.server.rule.DeprecatedRulesDefinitionLoader;
+import org.sonar.server.rule.RegisterRules;
+import org.sonar.server.rule.RubyRuleService;
+import org.sonar.server.rule.RuleCreator;
+import org.sonar.server.rule.RuleDefinitionsLoader;
+import org.sonar.server.rule.RuleDeleter;
+import org.sonar.server.rule.RuleOperations;
+import org.sonar.server.rule.RuleRepositories;
+import org.sonar.server.rule.RuleService;
+import org.sonar.server.rule.RuleUpdater;
import org.sonar.server.rule.db.RuleDao;
import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.rule.index.RuleNormalizer;
-import org.sonar.server.rule.ws.*;
+import org.sonar.server.rule.ws.ActiveRuleCompleter;
+import org.sonar.server.rule.ws.AppAction;
+import org.sonar.server.rule.ws.DeleteAction;
+import org.sonar.server.rule.ws.RepositoriesAction;
+import org.sonar.server.rule.ws.RuleMapping;
+import org.sonar.server.rule.ws.RulesWebService;
import org.sonar.server.rule.ws.SearchAction;
import org.sonar.server.rule.ws.TagsAction;
-import org.sonar.server.search.*;
+import org.sonar.server.rule.ws.UpdateAction;
+import org.sonar.server.search.IndexClient;
+import org.sonar.server.search.IndexQueue;
+import org.sonar.server.search.IndexSynchronizer;
+import org.sonar.server.search.SearchClient;
import org.sonar.server.source.HtmlSourceDecorator;
import org.sonar.server.source.SourceService;
import org.sonar.server.source.index.SourceLineIndex;
import org.sonar.server.source.index.SourceLineIndexDefinition;
import org.sonar.server.source.index.SourceLineIndexer;
-import org.sonar.server.source.ws.*;
+import org.sonar.server.source.ws.HashAction;
+import org.sonar.server.source.ws.IndexAction;
+import org.sonar.server.source.ws.LinesAction;
+import org.sonar.server.source.ws.RawAction;
+import org.sonar.server.source.ws.ScmAction;
+import org.sonar.server.source.ws.ScmWriter;
import org.sonar.server.source.ws.ShowAction;
-import org.sonar.server.startup.*;
+import org.sonar.server.source.ws.SourcesWs;
+import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules;
+import org.sonar.server.startup.GeneratePluginIndex;
+import org.sonar.server.startup.JdbcDriverDeployer;
+import org.sonar.server.startup.LogServerId;
+import org.sonar.server.startup.RegisterDashboards;
+import org.sonar.server.startup.RegisterDebtModel;
+import org.sonar.server.startup.RegisterMetrics;
+import org.sonar.server.startup.RegisterNewMeasureFilters;
+import org.sonar.server.startup.RegisterPermissionTemplates;
+import org.sonar.server.startup.RegisterServletFilters;
+import org.sonar.server.startup.RenameDeprecatedPropertyKeys;
+import org.sonar.server.startup.ServerMetadataPersister;
import org.sonar.server.test.CoverageService;
-import org.sonar.server.test.ws.*;
+import org.sonar.server.test.ws.CoverageShowAction;
+import org.sonar.server.test.ws.CoverageWs;
+import org.sonar.server.test.ws.TestsCoveredFilesAction;
+import org.sonar.server.test.ws.TestsShowAction;
+import org.sonar.server.test.ws.TestsTestCasesAction;
+import org.sonar.server.test.ws.TestsWs;
import org.sonar.server.text.MacroInterpreter;
import org.sonar.server.text.RubyTextService;
import org.sonar.server.ui.JRubyI18n;
import org.sonar.server.ui.PageDecorations;
import org.sonar.server.ui.Views;
import org.sonar.server.updatecenter.ws.UpdateCenterWs;
-import org.sonar.server.user.*;
+import org.sonar.server.user.DefaultUserService;
+import org.sonar.server.user.DoPrivileged;
+import org.sonar.server.user.GroupMembershipFinder;
+import org.sonar.server.user.GroupMembershipService;
+import org.sonar.server.user.NewUserNotifier;
+import org.sonar.server.user.SecurityRealmFactory;
+import org.sonar.server.user.UserService;
+import org.sonar.server.user.UserUpdater;
import org.sonar.server.user.db.GroupDao;
import org.sonar.server.user.db.UserDao;
import org.sonar.server.user.db.UserGroupDao;
@@ -187,7 +333,13 @@ import org.sonar.server.user.index.UserIndexer;
import org.sonar.server.user.ws.FavoritesWs;
import org.sonar.server.user.ws.UserPropertiesWs;
import org.sonar.server.user.ws.UsersWs;
-import org.sonar.server.util.*;
+import org.sonar.server.util.BooleanTypeValidation;
+import org.sonar.server.util.FloatTypeValidation;
+import org.sonar.server.util.IntegerTypeValidation;
+import org.sonar.server.util.StringListTypeValidation;
+import org.sonar.server.util.StringTypeValidation;
+import org.sonar.server.util.TextTypeValidation;
+import org.sonar.server.util.TypeValidations;
import org.sonar.server.view.index.ViewIndex;
import org.sonar.server.view.index.ViewIndexDefinition;
import org.sonar.server.view.index.ViewIndexer;
@@ -272,10 +424,6 @@ class ServerComponents {
IssueIndex.class,
IssueDao.class,
- // Activity
- ActivityService.class,
- ActivityNormalizer.class,
- ActivityIndex.class,
ActivityDao.class
));
components.addAll(CorePropertyDefinitions.all());
@@ -337,9 +485,15 @@ class ServerComponents {
pico.addSingleton(Periods.class);
pico.addSingleton(ServerWs.class);
pico.addSingleton(BackendCleanup.class);
- pico.addSingleton(IndexRegistry.class);
+ pico.addSingleton(IndexDefinitions.class);
pico.addSingleton(IndexCreator.class);
+ // Activity
+ pico.addSingleton(ActivityService.class);
+ pico.addSingleton(ActivityIndexDefinition.class);
+ pico.addSingleton(ActivityIndexer.class);
+ pico.addSingleton(ActivityIndex.class);
+
// batch
pico.addSingleton(BatchIndex.class);
pico.addSingleton(GlobalRepositoryAction.class);
@@ -642,10 +796,10 @@ class ServerComponents {
PluginsMonitor.class,
JvmPropertiesMonitor.class,
DatabaseMonitor.class
- ));
+ ));
// Compute engine
- pico.addSingleton(AnalysisReportQueue.class);
+ pico.addSingleton(ReportQueue.class);
pico.addSingleton(ComputationThreadLauncher.class);
pico.addSingleton(ComputationWebService.class);
pico.addSingleton(IsQueueEmptyWebService.class);
@@ -688,13 +842,14 @@ class ServerComponents {
startupContainer.addSingleton(LogServerId.class);
startupContainer.addSingleton(RegisterServletFilters.class);
startupContainer.addSingleton(CopyRequirementsFromCharacteristicsToRules.class);
- startupContainer.addSingleton(AnalysisReportQueueCleaner.class);
+ startupContainer.addSingleton(ReportQueueCleaner.class);
DoPrivileged.execute(new DoPrivileged.Task() {
@Override
protected void doPrivileged() {
- startupContainer.getComponentsByType(IndexSynchronizer.class).get(0).execute();
+ startupContainer.getComponentByType(IndexSynchronizer.class).executeDeprecated();
startupContainer.startComponents();
+ startupContainer.getComponentByType(IndexSynchronizer.class).execute();
startupContainer.getComponentByType(ServerLifecycleNotifier.class).notifyStart();
}
});
diff --git a/server/sonar-server/src/main/java/org/sonar/server/properties/ProjectSettingsFactory.java b/server/sonar-server/src/main/java/org/sonar/server/properties/ProjectSettingsFactory.java
index 3a9793e7fb9..e3b84813f30 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/properties/ProjectSettingsFactory.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/properties/ProjectSettingsFactory.java
@@ -24,7 +24,6 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import org.sonar.api.ServerComponent;
import org.sonar.api.config.Settings;
-import org.sonar.core.persistence.DbSession;
import org.sonar.core.properties.PropertiesDao;
import org.sonar.core.properties.PropertyDto;
@@ -41,8 +40,8 @@ public class ProjectSettingsFactory implements ServerComponent {
this.settings = settings;
}
- public Settings newProjectSettings(DbSession session, long projectId) {
- List<PropertyDto> propertyList = dao.selectProjectProperties(projectId, session);
+ public Settings newProjectSettings(long projectId) {
+ List<PropertyDto> propertyList = dao.selectProjectProperties(projectId);
return new ProjectSettings(settings, getPropertyMap(propertyList));
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java
index 44391663eec..ae29ee90da5 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java
@@ -22,16 +22,15 @@ package org.sonar.server.qualityprofile;
import com.google.common.base.Objects;
import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
-import org.sonar.core.activity.ActivityLog;
import org.sonar.core.qualityprofile.db.ActiveRuleKey;
+import org.sonar.server.activity.Activity;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import java.util.HashMap;
import java.util.Map;
-public class ActiveRuleChange implements ActivityLog {
+public class ActiveRuleChange {
public static enum Type {
ACTIVATED, DEACTIVATED, UPDATED
@@ -91,26 +90,26 @@ public class ActiveRuleChange implements ActivityLog {
return this;
}
- @Override
- public Map<String, String> getDetails() {
- HashMap<String, String> details = new HashMap<String, String>();
-
- details.put("key", getKey().toString());
- details.put("ruleKey", getKey().ruleKey().toString());
- details.put("profileKey", getKey().qProfile().toString());
+ public Activity toActivity() {
+ Activity activity = new Activity();
+ activity.setType(Activity.Type.QPROFILE);
+ activity.setAction(type.name());
+ activity.setData("key", getKey().toString());
+ activity.setData("ruleKey", getKey().ruleKey().toString());
+ activity.setData("profileKey", getKey().qProfile().toString());
for (Map.Entry<String, String> param : parameters.entrySet()) {
if (!param.getKey().isEmpty()) {
- details.put("param_" + param.getKey(), param.getValue());
+ activity.setData("param_" + param.getKey(), param.getValue());
}
}
if (StringUtils.isNotEmpty(severity)) {
- details.put("severity", severity);
+ activity.setData("severity", severity);
}
if (inheritance != null) {
- details.put("inheritance", inheritance.name());
+ activity.setData("inheritance", inheritance.name());
}
- return details;
+ return activity;
}
public static ActiveRuleChange createFor(Type type, ActiveRuleKey key) {
@@ -127,9 +126,4 @@ public class ActiveRuleChange implements ActivityLog {
.add("parameters", parameters)
.toString();
}
-
- @Override
- public String getAction() {
- return type.name();
- }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileActivity.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileActivity.java
index 8b294dfa62f..fa49d3695e4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileActivity.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileActivity.java
@@ -21,19 +21,17 @@ package org.sonar.server.qualityprofile;
import com.google.common.collect.Maps;
import org.sonar.api.rule.RuleKey;
-import org.sonar.core.activity.Activity;
import org.sonar.server.activity.index.ActivityDoc;
-import org.sonar.server.activity.index.ActivityNormalizer;
+import org.sonar.server.activity.index.ActivityIndexDefinition;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-
import java.util.Map;
/**
* @since 4.4
*/
-public class QProfileActivity extends ActivityDoc implements Activity {
+public class QProfileActivity extends ActivityDoc {
private String ruleName = null;
private String authorName = null;
@@ -77,8 +75,8 @@ public class QProfileActivity extends ActivityDoc implements Activity {
@Override
@CheckForNull
- public String login() {
- return getNullableField(ActivityNormalizer.LogFields.LOGIN.field());
+ public String getLogin() {
+ return getNullableField(ActivityIndexDefinition.FIELD_LOGIN);
}
@CheckForNull
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileActivityQuery.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileActivityQuery.java
index cc303dab5a1..fd41cdd86b4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileActivityQuery.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileActivityQuery.java
@@ -19,32 +19,32 @@
*/
package org.sonar.server.qualityprofile;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import org.sonar.core.activity.Activity;
+import org.sonar.server.activity.Activity;
import org.sonar.server.activity.index.ActivityQuery;
-import java.util.Collection;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import java.util.Arrays;
/**
* @since 4.4
*/
public class QProfileActivityQuery extends ActivityQuery {
- Collection<String> qprofileKeys;
-
public QProfileActivityQuery() {
super();
- this.setTypes(ImmutableSet.of(Activity.Type.QPROFILE));
- qprofileKeys = Lists.newArrayList();
+ setTypes(Arrays.asList(Activity.Type.QPROFILE.name()));
}
- public Collection<String> getQprofileKeys() {
- return qprofileKeys;
+ @CheckForNull
+ public String getQprofileKey() {
+ return (String)getDataOrFilters().get("profileKey");
}
- public QProfileActivityQuery setQprofileKeys(Collection<String> qprofileKeys) {
- this.qprofileKeys = qprofileKeys;
+ public QProfileActivityQuery setQprofileKey(@Nullable String qprofileKey) {
+ if (qprofileKey != null) {
+ addDataOrFilter("profileKey", qprofileKey);
+ }
return this;
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java
index 0e0a7acb4ac..32eec19eb53 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java
@@ -20,9 +20,6 @@
package org.sonar.server.qualityprofile;
import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.index.query.FilterBuilders;
-import org.elasticsearch.index.query.OrFilterBuilder;
-import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.sonar.api.ServerComponent;
import org.sonar.core.permission.GlobalPermissions;
@@ -33,15 +30,13 @@ import org.sonar.core.rule.RuleDto;
import org.sonar.core.user.UserDto;
import org.sonar.server.activity.index.ActivityIndex;
import org.sonar.server.db.DbClient;
+import org.sonar.server.es.SearchOptions;
import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryContext;
import org.sonar.server.search.Result;
import org.sonar.server.user.UserSession;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
@@ -53,7 +48,7 @@ import java.util.Map;
public class QProfileService implements ServerComponent {
private final DbClient db;
- private final IndexClient index;
+ private final ActivityIndex activityIndex;
private final RuleActivator ruleActivator;
private final QProfileFactory factory;
private final QProfileBackuper backuper;
@@ -61,10 +56,10 @@ public class QProfileService implements ServerComponent {
private final QProfileReset reset;
private final QProfileExporters exporters;
- public QProfileService(DbClient db, IndexClient index, RuleActivator ruleActivator, QProfileFactory factory,
+ public QProfileService(DbClient db, ActivityIndex activityIndex, RuleActivator ruleActivator, QProfileFactory factory,
QProfileBackuper backuper, QProfileCopier copier, QProfileReset reset, QProfileExporters exporters) {
this.db = db;
- this.index = index;
+ this.activityIndex = activityIndex;
this.ruleActivator = ruleActivator;
this.factory = factory;
this.backuper = backuper;
@@ -214,25 +209,19 @@ public class QProfileService implements ServerComponent {
UserSession.get().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
}
- public Result<QProfileActivity> searchActivities(QProfileActivityQuery query, QueryContext options) {
+ public Result<QProfileActivity> searchActivities(QProfileActivityQuery query, SearchOptions options) {
DbSession session = db.openSession(false);
try {
- OrFilterBuilder activityFilter = FilterBuilders.orFilter();
- for (String profileKey : query.getQprofileKeys()) {
- activityFilter.add(FilterBuilders.nestedFilter("details",
- QueryBuilders.matchQuery("details.profileKey", profileKey)));
- }
-
- SearchResponse response = index.get(ActivityIndex.class).search(query, options, activityFilter);
+ SearchResponse response = activityIndex.doSearch(query, options);
Result<QProfileActivity> result = new Result<QProfileActivity>(response);
for (SearchHit hit : response.getHits().getHits()) {
QProfileActivity profileActivity = new QProfileActivity(hit.getSource());
RuleDto ruleDto = db.ruleDao().getNullableByKey(session, profileActivity.ruleKey());
profileActivity.ruleName(ruleDto != null ? ruleDto.getName() : null);
- String login = profileActivity.login();
+ String login = profileActivity.getLogin();
if (login != null) {
- UserDto user = db.userDao().selectActiveUserByLogin(login, session);
+ UserDto user = db.userDao().selectActiveUserByLogin(session, login);
profileActivity.authorName(user != null ? user.getName() : null);
}
result.getHits().add(profileActivity);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java
index 96bc7511f2f..757334f7100 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java
@@ -23,7 +23,6 @@ import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import org.sonar.api.ServerComponent;
import org.sonar.api.server.rule.RuleParamType;
-import org.sonar.core.activity.Activity;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.qualityprofile.db.ActiveRuleDto;
import org.sonar.core.qualityprofile.db.ActiveRuleKey;
@@ -63,16 +62,16 @@ public class RuleActivator implements ServerComponent {
private final TypeValidations typeValidations;
private final RuleActivatorContextFactory contextFactory;
private final IndexClient index;
- private final ActivityService log;
+ private final ActivityService activityService;
public RuleActivator(DbClient db, IndexClient index,
RuleActivatorContextFactory contextFactory, TypeValidations typeValidations,
- ActivityService log) {
+ ActivityService activityService) {
this.db = db;
this.index = index;
this.contextFactory = contextFactory;
this.typeValidations = typeValidations;
- this.log = log;
+ this.activityService = activityService;
}
public List<ActiveRuleChange> activate(DbSession dbSession, RuleActivation activation, String profileKey) {
@@ -240,7 +239,7 @@ public class RuleActivator implements ServerComponent {
} else if (change.getType() == ActiveRuleChange.Type.UPDATED) {
activeRule = doUpdate(change, context, dbSession);
}
- log.write(dbSession, Activity.Type.QPROFILE, change);
+ activityService.save(change.toActivity());
return activeRule;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java
index e2ea5e4ff98..674e9cade10 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java
@@ -51,12 +51,8 @@ import org.sonar.server.startup.RegisterDebtModel;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+
+import java.util.*;
import static com.google.common.collect.Lists.newArrayList;
@@ -228,7 +224,9 @@ public class RegisterRules implements Startable {
dto.setName(def.name());
changed = true;
}
- changed = mergeDescription(def, dto);
+ if (mergeDescription(def, dto)) {
+ changed= true;
+ }
if (!dto.getSystemTags().containsAll(def.tags())) {
dto.setSystemTags(def.tags());
changed = true;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java
index 29d6ef12df3..c90d6c71819 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java
@@ -83,6 +83,11 @@ public class RubyRuleService implements ServerComponent, Startable {
query.setDebtCharacteristics(RubyUtils.toStrings(params.get("debtCharacteristics")));
query.setHasDebtCharacteristic(RubyUtils.toBoolean(params.get("hasDebtCharacteristic")));
query.setSortField(RuleNormalizer.RuleField.NAME);
+ String profile = Strings.emptyToNull((String) params.get("profile"));
+ if (profile != null) {
+ query.setQProfileKey(profile);
+ query.setActivation(true);
+ }
QueryContext options = new QueryContext();
Integer pageSize = RubyUtils.toInteger(params.get("pageSize"));
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java
index d3432183f19..483d6b2c55e 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java
@@ -61,6 +61,7 @@ import static com.google.common.collect.Lists.newArrayList;
public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
private static final String FILTER_DEBT_CHARACTERISTICS = "debtCharacteristics";
+ private static final String FILTER_HAS_DEBT_CHARACTERISTICS = "hasDebtCharacteristic";
public static final String FACET_LANGUAGES = "languages";
public static final String FACET_TAGS = "tags";
public static final String FACET_REPOSITORIES = "repositories";
@@ -270,14 +271,25 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
// Debt char exist filter
Boolean hasDebtCharacteristic = query.getHasDebtCharacteristic();
- if (hasDebtCharacteristic != null && hasDebtCharacteristic) {
- filters.put("hasDebtCharacteristic",
- FilterBuilders.boolFilter().mustNot(
- FilterBuilders.termsFilter(RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field(), DebtCharacteristic.NONE))
- .should(
- FilterBuilders.existsFilter(RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field()))
- .should(
- FilterBuilders.existsFilter(RuleNormalizer.RuleField.DEFAULT_SUB_CHARACTERISTIC.field())));
+ if (hasDebtCharacteristic != null) {
+ if (hasDebtCharacteristic) {
+ filters.put(FILTER_HAS_DEBT_CHARACTERISTICS,
+ // Match either characteristic is not disabled, either characteristic or default characteristic is defined on the rule
+ FilterBuilders.boolFilter()
+ .mustNot(FilterBuilders.termsFilter(RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field(), DebtCharacteristic.NONE))
+ .should(FilterBuilders.existsFilter(RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field()))
+ .should(FilterBuilders.existsFilter(RuleNormalizer.RuleField.DEFAULT_SUB_CHARACTERISTIC.field())));
+ } else {
+ filters.put(FILTER_HAS_DEBT_CHARACTERISTICS,
+ // Match either characteristic is disabled, either no characteristic or default characteristic is defined on the rule
+ FilterBuilders.orFilter(
+ FilterBuilders.termsFilter(RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field(), DebtCharacteristic.NONE),
+ FilterBuilders.andFilter(
+ FilterBuilders.missingFilter(RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field()),
+ FilterBuilders.missingFilter(RuleNormalizer.RuleField.DEFAULT_SUB_CHARACTERISTIC.field())
+ )
+ ));
+ }
}
if (query.getAvailableSince() != null) {
@@ -373,24 +385,46 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
}
private void addCharacteristicsFacetIfNeeded(RuleQuery query, QueryContext options, Map<String, AggregationBuilder> aggregations, StickyFacetBuilder stickyFacetBuilder) {
+
if (options.facets().contains(FACET_DEBT_CHARACTERISTICS)) {
+ /*
+ * Since this facet concerns 2 fields, we're using an aggregation structure like this:
+ * global aggregation
+ * |- sub-aggregation on characteristics: filter
+ * | |- classic sub-aggregation with top-n terms, excluding NONE
+ * | |- classic sub-aggregation with selected terms
+ * | |- terms aggregation on "NONE"
+ * | |- missing aggregation
+ * |- sub-aggregation on sub-characteristics: filter, excluding NONE
+ * |- classic sub-aggregation with top-n terms
+ * |- classic sub-aggregation with selected terms
+ */
int characsSize = 10;
int subCharacsSize = 300;
Collection<String> characsFromQuery = query.getDebtCharacteristics();
Object[] selectedChars = characsFromQuery == null ? new Object[0] : characsFromQuery.toArray();
+ BoolFilterBuilder stickyFacetFilter = stickyFacetBuilder.getStickyFacetFilter(FILTER_DEBT_CHARACTERISTICS, FILTER_HAS_DEBT_CHARACTERISTICS);
AggregationBuilder debtChar = AggregationBuilders.filter(FACET_DEBT_CHARACTERISTICS + "__chars")
- .filter(stickyFacetBuilder.getStickyFacetFilter(FILTER_DEBT_CHARACTERISTICS))
+ .filter(stickyFacetFilter)
.subAggregation(
AggregationBuilders.terms(FACET_DEBT_CHARACTERISTICS + "__chars_top").field(RuleNormalizer.RuleField.CHARACTERISTIC.field())
+ .exclude(DebtCharacteristic.NONE)
.size(characsSize))
.subAggregation(
AggregationBuilders.terms(FACET_DEBT_CHARACTERISTICS + "__chars_selected").field(RuleNormalizer.RuleField.CHARACTERISTIC.field())
.include(Joiner.on('|').join(selectedChars))
- .size(characsSize));
+ .size(characsSize))
+ .subAggregation(
+ AggregationBuilders.terms(FACET_DEBT_CHARACTERISTICS + "__chars_none").field(RuleNormalizer.RuleField.CHARACTERISTIC.field())
+ .include(DebtCharacteristic.NONE)
+ .size(characsSize))
+ .subAggregation(
+ AggregationBuilders.missing(FACET_DEBT_CHARACTERISTICS + "__chars_missing").field(RuleNormalizer.RuleField.CHARACTERISTIC.field()));
AggregationBuilder debtSubChar = AggregationBuilders.filter(FACET_DEBT_CHARACTERISTICS + "__subchars")
- .filter(stickyFacetBuilder.getStickyFacetFilter(FILTER_DEBT_CHARACTERISTICS))
+ .filter(stickyFacetFilter)
.subAggregation(
AggregationBuilders.terms(FACET_DEBT_CHARACTERISTICS + "__subchars_top").field(RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field())
+ .exclude(DebtCharacteristic.NONE)
.size(subCharacsSize))
.subAggregation(
AggregationBuilders.terms(FACET_DEBT_CHARACTERISTICS + "__chars_selected").field(RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field())
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
index d2c00afe29b..66bbea4f747 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
@@ -25,6 +25,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.io.Resources;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rule.Severity;
+import org.sonar.api.server.debt.DebtCharacteristic;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.text.JsonWriter;
@@ -35,6 +36,7 @@ import org.sonar.server.rule.RuleService;
import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.rule.index.RuleNormalizer;
import org.sonar.server.rule.index.RuleQuery;
+import org.sonar.server.search.FacetValue;
import org.sonar.server.search.QueryContext;
import org.sonar.server.search.Result;
import org.sonar.server.search.ws.SearchOptions;
@@ -44,6 +46,7 @@ import javax.annotation.CheckForNull;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Iterator;
/**
* @since 4.4
@@ -314,6 +317,31 @@ public class SearchAction extends SearchRequestHandler<RuleQuery, Rule> implemen
addMandatoryFacetValues(results, RuleIndex.FACET_STATUSES, RuleIndex.ALL_STATUSES_EXCEPT_REMOVED);
addMandatoryFacetValues(results, RuleIndex.FACET_SEVERITIES, Severity.ALL);
addMandatoryFacetValues(results, RuleIndex.FACET_TAGS, request.paramAsStrings(PARAM_TAGS));
+
+ mergeNoneAndEmptyBucketOnCharacteristics(results);
+
super.writeFacets(request, context, results, json);
}
+
+ protected void mergeNoneAndEmptyBucketOnCharacteristics(Result<?> results) {
+ if (results.getFacets().containsKey(RuleIndex.FACET_DEBT_CHARACTERISTICS)) {
+ Collection<FacetValue> characValues = results.getFacetValues(RuleIndex.FACET_DEBT_CHARACTERISTICS);
+ if (characValues == null) {
+ return;
+ }
+
+ long mergedCount = 0L;
+ Iterator<FacetValue> characIterator = characValues.iterator();
+ while (characIterator.hasNext()) {
+ FacetValue characValue = characIterator.next();
+ if ("".equals(characValue.getKey()) || DebtCharacteristic.NONE.equals(characValue.getKey())) {
+ mergedCount += characValue.getValue();
+ characIterator.remove();
+ }
+ }
+
+ FacetValue mergedNoneValue = new FacetValue(DebtCharacteristic.NONE, mergedCount);
+ characValues.add(mergedNoneValue);
+ }
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java b/server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java
index 1a03ce18662..65d82a82998 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java
@@ -55,6 +55,10 @@ import javax.annotation.Nullable;
import java.io.Serializable;
import java.util.*;
+/**
+ * @deprecated replaced by {@link org.sonar.server.es.BaseIndex}
+ */
+@Deprecated
public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serializable>
implements Index<DOMAIN, DTO, KEY> {
@@ -215,7 +219,7 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial
protected abstract String getKeyValue(KEY key);
public final Settings getIndexSettings() {
- ImmutableSettings.Builder settings = this.addCustomIndexSettings(this.getBaseIndexSettings());
+ ImmutableSettings.Builder settings = this.getBaseIndexSettings();
// In case there is a replication factor set by the index,
// it is removed since we're using global cluster state
@@ -225,10 +229,6 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial
return settings.build();
}
- protected ImmutableSettings.Builder addCustomIndexSettings(ImmutableSettings.Builder baseIndexSettings) {
- return baseIndexSettings;
- }
-
protected abstract Map mapProperties();
protected abstract Map mapKey();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/Facets.java b/server/sonar-server/src/main/java/org/sonar/server/search/Facets.java
index 58f6b140bc4..2b23c003331 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/search/Facets.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/search/Facets.java
@@ -71,7 +71,11 @@ class Facets {
Missing missing = (Missing) aggregation;
long docCount = missing.getDocCount();
if (docCount > 0L) {
- this.facetValues.put(aggregation.getName().replace("_missing", ""), new FacetValue("", docCount));
+ String facetName = aggregation.getName();
+ if (facetName.contains("__") && !facetName.startsWith("__")) {
+ facetName = facetName.substring(0, facetName.indexOf("__"));
+ }
+ this.facetValues.put(facetName.replace("_missing", ""), new FacetValue("", docCount));
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/IndexDefinition.java b/server/sonar-server/src/main/java/org/sonar/server/search/IndexDefinition.java
index fc9b36ebe17..ffafa74a18a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/search/IndexDefinition.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/search/IndexDefinition.java
@@ -40,7 +40,6 @@ public class IndexDefinition {
public static final IndexDefinition RULE = new IndexDefinition("rules", "rule");
public static final IndexDefinition ACTIVE_RULE = new IndexDefinition("rules", "activeRule");
public static final IndexDefinition ISSUES = new IndexDefinition("issues", "issue");
- public static final IndexDefinition LOG = new IndexDefinition("logs", "sonarLog");
// Only used for test
static final IndexDefinition TEST = new IndexDefinition("test", "test");
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java b/server/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java
index 2aaa1e874b7..95bafedf6ee 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java
@@ -23,7 +23,7 @@ package org.sonar.server.search;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.persistence.DbSession;
-import org.sonar.server.activity.index.ActivityIndex;
+import org.sonar.server.activity.index.ActivityIndexer;
import org.sonar.server.db.Dao;
import org.sonar.server.db.DbClient;
import org.sonar.server.issue.index.IssueAuthorizationIndexer;
@@ -47,9 +47,16 @@ public class IndexSynchronizer {
private final IssueIndexer issueIndexer;
private final UserIndexer userIndexer;
private final ViewIndexer viewIndexer;
+ private final ActivityIndexer activityIndexer;
+ /**
+ * Limitation - {@link org.sonar.server.es.BaseIndexer} are not injected through an array or a collection
+ * because we need {@link org.sonar.server.issue.index.IssueAuthorizationIndexer} to be executed before
+ * {@link org.sonar.server.issue.index.IssueIndexer}
+ */
public IndexSynchronizer(DbClient db, IndexClient index, SourceLineIndexer sourceLineIndexer,
- IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer, UserIndexer userIndexer, ViewIndexer viewIndexer) {
+ IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer,
+ UserIndexer userIndexer, ViewIndexer viewIndexer, ActivityIndexer activityIndexer) {
this.db = db;
this.index = index;
this.sourceLineIndexer = sourceLineIndexer;
@@ -57,41 +64,45 @@ public class IndexSynchronizer {
this.issueIndexer = issueIndexer;
this.userIndexer = userIndexer;
this.viewIndexer = viewIndexer;
+ this.activityIndexer = activityIndexer;
}
- public void execute() {
+ public void executeDeprecated() {
DbSession session = db.openSession(false);
try {
synchronize(session, db.ruleDao(), index.get(RuleIndex.class));
synchronize(session, db.activeRuleDao(), index.get(ActiveRuleIndex.class));
- synchronize(session, db.activityDao(), index.get(ActivityIndex.class));
session.commit();
} finally {
session.close();
}
+ }
+
+ public void execute() {
+ LOG.info("Index activities");
+ activityIndexer.setEnabled(true).index();
LOG.info("Index issues");
- issueAuthorizationIndexer.index();
- issueIndexer.index();
+ issueAuthorizationIndexer.setEnabled(true).index();
+ issueIndexer.setEnabled(true).index();
- LOG.info("Index source files");
- sourceLineIndexer.index();
+ LOG.info("Index source lines");
+ sourceLineIndexer.setEnabled(true).index();
LOG.info("Index users");
- userIndexer.index();
+ userIndexer.setEnabled(true).index();
LOG.info("Index views");
- viewIndexer.index();
+ viewIndexer.setEnabled(true).index();
}
void synchronize(DbSession session, Dao dao, Index index) {
long count = index.getIndexStat().getDocumentCount();
Date lastSynch = index.getLastSynchronization();
+ LOG.info("Index {}s", index.getIndexType());
if (count <= 0) {
- LOG.info("Index {}s", index.getIndexType());
dao.synchronizeAfter(session);
} else {
- LOG.info("Index {}s for updates after {}", index.getIndexType(), lastSynch);
dao.synchronizeAfter(session, lastSynch);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/StickyFacetBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/StickyFacetBuilder.java
index 53b36c093ba..589536f1484 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/search/StickyFacetBuilder.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/search/StickyFacetBuilder.java
@@ -20,7 +20,7 @@
package org.sonar.server.search;
import com.google.common.base.Joiner;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.ArrayUtils;
import org.elasticsearch.index.query.BoolFilterBuilder;
import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.FilterBuilders;
@@ -67,10 +67,10 @@ public class StickyFacetBuilder {
.subAggregation(facetTopAggregation);
}
- public BoolFilterBuilder getStickyFacetFilter(String fieldName) {
+ public BoolFilterBuilder getStickyFacetFilter(String... fieldNames) {
BoolFilterBuilder facetFilter = FilterBuilders.boolFilter().must(FilterBuilders.queryFilter(query));
for (Map.Entry<String, FilterBuilder> filter : filters.entrySet()) {
- if (filter.getValue() != null && !StringUtils.equals(filter.getKey(), fieldName)) {
+ if (filter.getValue() != null && !ArrayUtils.contains(fieldNames, filter.getKey())) {
facetFilter.must(filter.getValue());
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineDoc.java b/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineDoc.java
index fd8e475a4d1..f00a5b8c457 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineDoc.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineDoc.java
@@ -21,12 +21,10 @@ package org.sonar.server.source.index;
import com.google.common.collect.ImmutableList;
import org.sonar.server.search.BaseDoc;
-import org.sonar.server.search.BaseNormalizer;
import org.sonar.server.search.IndexUtils;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
@@ -119,11 +117,11 @@ public class SourceLineDoc extends BaseDoc {
}
public Date updateDate() {
- return getFieldAsDate(BaseNormalizer.UPDATED_AT_FIELD);
+ return getFieldAsDate(SourceLineIndexDefinition.FIELD_UPDATED_AT);
}
public SourceLineDoc setUpdateDate(@Nullable Date updatedAt) {
- setField(BaseNormalizer.UPDATED_AT_FIELD, updatedAt);
+ setField(SourceLineIndexDefinition.FIELD_UPDATED_AT, updatedAt);
return this;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexDefinition.java b/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexDefinition.java
index 70aa212006d..ad5615fdd9a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexDefinition.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexDefinition.java
@@ -24,7 +24,6 @@ import org.sonar.api.config.Settings;
import org.sonar.process.ProcessConstants;
import org.sonar.server.es.IndexDefinition;
import org.sonar.server.es.NewIndex;
-import org.sonar.server.search.BaseNormalizer;
public class SourceLineIndexDefinition implements IndexDefinition {
@@ -47,6 +46,7 @@ public class SourceLineIndexDefinition implements IndexDefinition {
public static final String FIELD_OVERALL_COVERED_CONDITIONS = "overallCoveredConditions";
public static final String FIELD_SYMBOLS = "symbols";
public static final String FIELD_DUPLICATIONS = "duplications";
+ public static final String FIELD_UPDATED_AT = "updatedAt";
public static final String INDEX = "sourcelines";
@@ -95,6 +95,6 @@ public class SourceLineIndexDefinition implements IndexDefinition {
sourceLineMapping.createIntegerField(FIELD_OVERALL_COVERED_CONDITIONS);
sourceLineMapping.stringFieldBuilder(FIELD_SYMBOLS).disableSearch().build();
sourceLineMapping.createShortField(FIELD_DUPLICATIONS);
- sourceLineMapping.createDateTimeField(BaseNormalizer.UPDATED_AT_FIELD);
+ sourceLineMapping.createDateTimeField(FIELD_UPDATED_AT);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java
index 3e7ce485a15..9e862e6b389 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java
@@ -43,7 +43,7 @@ public class SourceLineIndexer extends BaseIndexer {
private final DbClient dbClient;
public SourceLineIndexer(DbClient dbClient, EsClient esClient) {
- super(esClient, 0L, SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE);
+ super(esClient, 0L, SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE, SourceLineIndexDefinition.FIELD_UPDATED_AT);
this.dbClient = dbClient;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/ws/LinesAction.java b/server/sonar-server/src/main/java/org/sonar/server/source/ws/LinesAction.java
index 969e7fc40d5..4ad075bdb77 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/source/ws/LinesAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/source/ws/LinesAction.java
@@ -61,6 +61,12 @@ public class LinesAction implements RequestHandler {
"<li>Author of the line (from SCM information)</li>" +
"<li>Revision of the line (from SCM information)</li>" +
"<li>Last commit date of the line (from SCM information)</li>" +
+ "<li>Line hits from unit test coverage</li>" +
+ "<li>Number of conditions to cover in unit tests</li>" +
+ "<li>Number of conditions covered by unit tests</li>" +
+ "<li>Line hits from integration test coverage</li>" +
+ "<li>Number of conditions to cover in integration tests</li>" +
+ "<li>Number of conditions covered by integration tests</li>" +
"</ol>")
.setSince("5.0")
.setInternal(true)
@@ -89,7 +95,7 @@ public class LinesAction implements RequestHandler {
public void handle(Request request, Response response) {
String fileUuid = request.mandatoryParam("uuid");
ComponentDto component = componentService.getByUuid(fileUuid);
- UserSession.get().checkComponentPermission(UserRole.CODEVIEWER, component.key());
+ UserSession.get().checkProjectUuidPermission(UserRole.CODEVIEWER, component.projectUuid());
int from = Math.max(request.mandatoryParamAsInt("from"), 1);
int to = (Integer) ObjectUtils.defaultIfNull(request.paramAsInt("to"), Integer.MAX_VALUE);
@@ -115,9 +121,12 @@ public class LinesAction implements RequestHandler {
.prop("scmRevision", line.scmRevision());
Date scmDate = line.scmDate();
json.prop("scmDate", scmDate == null ? null : DateUtils.formatDateTime(scmDate));
- json.prop("lineHits", line.overallLineHits())
- .prop("conditions", line.overallConditions())
- .prop("coveredConditions", line.overallCoveredConditions());
+ json.prop("utLineHits", line.utLineHits())
+ .prop("utConditions", line.utConditions())
+ .prop("utCoveredConditions", line.utCoveredConditions())
+ .prop("itLineHits", line.itLineHits())
+ .prop("itConditions", line.itConditions())
+ .prop("itCoveredConditions", line.itCoveredConditions());
if (! line.duplications().isEmpty()) {
json.prop("duplicated", true);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
index f7a3a25875f..0101265cad3 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
@@ -19,7 +19,6 @@
*/
package org.sonar.server.ui;
-import org.sonar.api.utils.log.Loggers;
import org.sonar.api.config.License;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.Settings;
@@ -30,6 +29,7 @@ import org.sonar.api.platform.PluginRepository;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.ResourceType;
import org.sonar.api.resources.ResourceTypes;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.api.web.Footer;
import org.sonar.api.web.Page;
import org.sonar.api.web.RubyRailsWebservice;
@@ -46,11 +46,7 @@ import org.sonar.server.platform.Platform;
import org.sonar.server.platform.ServerIdGenerator;
import org.sonar.server.platform.ServerSettings;
import org.sonar.server.platform.SettingsChangeNotifier;
-import org.sonar.server.plugins.InstalledPluginReferentialFactory;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
-import org.sonar.server.plugins.ServerPluginRepository;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.plugins.*;
import org.sonar.server.rule.RuleRepositories;
import org.sonar.server.user.NewUserNotifier;
import org.sonar.updatecenter.common.PluginReferential;
@@ -309,6 +305,9 @@ public final class JRubyFacade {
get(ResourceIndexerDao.class).indexResource(resourceId);
}
+ /*
+ * /!\ Used by Views
+ */
public void deleteResourceTree(String projectKey) {
try {
get(ComponentCleanerService.class).delete(projectKey);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexer.java
index 611b776a1ee..302b522b58c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexer.java
@@ -36,7 +36,7 @@ public class UserIndexer extends BaseIndexer {
private final DbClient dbClient;
public UserIndexer(DbClient dbClient, EsClient esClient) {
- super(esClient, 300, UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER);
+ super(esClient, 300, UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, UserIndexDefinition.FIELD_UPDATED_AT);
this.dbClient = dbClient;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/UsersWs.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/UsersWs.java
index 4a44637627c..6677468eac5 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/user/ws/UsersWs.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/user/ws/UsersWs.java
@@ -64,6 +64,10 @@ public class UsersWs implements WebService {
.setDescription("Comma-separated list of user logins")
.setExampleValue("admin,sbrandhof");
+ action.createParam("s")
+ .setDescription("UTF-8 search query on login or name")
+ .setExampleValue("bran");
+
RailsHandler.addFormatParam(action);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java
index 3f00775cbf3..bc6f501be0b 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java
@@ -41,7 +41,7 @@ public class ViewIndexer extends BaseIndexer {
private final EsClient esClient;
public ViewIndexer(DbClient dbClient, EsClient esClient) {
- super(esClient, 300, ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW);
+ super(esClient, 300, ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW, "updatedAt");
this.dbClient = dbClient;
this.esClient = esClient;
}
diff --git a/server/sonar-server/src/test/java/org/sonar/core/computation/dbcleaner/ProjectCleanerTest.java b/server/sonar-server/src/test/java/org/sonar/core/computation/dbcleaner/ProjectCleanerTest.java
index d72ffb96335..c8fceca3a3d 100644
--- a/server/sonar-server/src/test/java/org/sonar/core/computation/dbcleaner/ProjectCleanerTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/core/computation/dbcleaner/ProjectCleanerTest.java
@@ -55,26 +55,22 @@ public class ProjectCleanerTest {
@Before
public void before() throws Exception {
this.projectSettingsFactory = mock(ProjectSettingsFactory.class);
- when(projectSettingsFactory.newProjectSettings(any(DbSession.class), any(Long.class))).thenReturn(settings);
- this.sut = new ProjectCleaner(dao, periodCleaner, profiler, purgeListener, projectSettingsFactory, issueIndex);
+ this.sut = new ProjectCleaner(dao, periodCleaner, profiler, purgeListener, issueIndex);
}
@Test
public void no_profiling_when_property_is_false() throws Exception {
settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, false);
- when(projectSettingsFactory.newProjectSettings(any(DbSession.class), any(Long.class))).thenReturn(settings);
- sut.purge(mock(DbSession.class), mock(IdUuidPair.class));
+ sut.purge(mock(DbSession.class), mock(IdUuidPair.class), settings);
verify(profiler, never()).dump(anyLong(), any(Logger.class));
}
@Test
public void no_indexing_when_no_issue_to_delete() throws Exception {
- when(projectSettingsFactory.newProjectSettings(any(DbSession.class), any(Long.class))).thenReturn(settings);
-
- sut.purge(mock(DbSession.class), mock(IdUuidPair.class));
+ sut.purge(mock(DbSession.class), mock(IdUuidPair.class), settings);
verifyZeroInteractions(issueIndex);
}
@@ -83,7 +79,7 @@ public class ProjectCleanerTest {
public void profiling_when_property_is_true() throws Exception {
settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, true);
- sut.purge(mock(DbSession.class), mock(IdUuidPair.class));
+ sut.purge(mock(DbSession.class), mock(IdUuidPair.class), settings);
verify(profiler).dump(anyLong(), any(Logger.class));
}
@@ -92,7 +88,7 @@ public class ProjectCleanerTest {
public void call_period_cleaner_index_client_and_purge_dao() throws Exception {
settings.setProperty(DbCleanerConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES, 5);
- sut.purge(mock(DbSession.class), mock(IdUuidPair.class));
+ sut.purge(mock(DbSession.class), mock(IdUuidPair.class), settings);
verify(periodCleaner).clean(any(DbSession.class), any(Long.class), any(Settings.class));
verify(dao).purge(any(DbSession.class), any(PurgeConfiguration.class), any(PurgeListener.class));
@@ -103,7 +99,7 @@ public class ProjectCleanerTest {
public void if_dao_purge_fails_it_should_not_interrupt_program_execution() throws Exception {
doThrow(RuntimeException.class).when(dao).purge(any(DbSession.class), any(PurgeConfiguration.class), any(PurgeListener.class));
- sut.purge(mock(DbSession.class), mock(IdUuidPair.class));
+ sut.purge(mock(DbSession.class), mock(IdUuidPair.class), settings);
verify(dao).purge(any(DbSession.class), any(PurgeConfiguration.class), any(PurgeListener.class));
}
@@ -112,7 +108,7 @@ public class ProjectCleanerTest {
public void if_profiler_cleaning_fails_it_should_not_interrupt_program_execution() throws Exception {
doThrow(RuntimeException.class).when(periodCleaner).clean(any(DbSession.class), anyLong(), any(Settings.class));
- sut.purge(mock(DbSession.class), mock(IdUuidPair.class));
+ sut.purge(mock(DbSession.class), mock(IdUuidPair.class), settings);
verify(periodCleaner).clean(any(DbSession.class), anyLong(), any(Settings.class));
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/activity/ActivityBackendMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/activity/ActivityBackendMediumTest.java
deleted file mode 100644
index d89298a63db..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/activity/ActivityBackendMediumTest.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.activity;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import org.elasticsearch.action.search.SearchResponse;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.core.activity.Activity;
-import org.sonar.core.activity.ActivityLog;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.server.activity.db.ActivityDao;
-import org.sonar.server.activity.index.ActivityIndex;
-import org.sonar.server.activity.index.ActivityQuery;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.platform.Platform;
-import org.sonar.server.search.QueryContext;
-import org.sonar.server.search.Result;
-import org.sonar.server.tester.ServerTester;
-
-import java.util.Iterator;
-import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ActivityBackendMediumTest {
-
- @ClassRule
- public static ServerTester tester = new ServerTester();
-
- ActivityService service = tester.get(ActivityService.class);
- ActivityDao dao = tester.get(ActivityDao.class);
- ActivityIndex index = tester.get(ActivityIndex.class);
- DbSession dbSession;
-
- @Before
- public void before() {
- tester.clearDbAndIndexes();
- dbSession = tester.get(DbClient.class).openSession(false);
- }
-
- @After
- public void after() {
- dbSession.close();
- }
-
- @Test
- public void insert_find_text_log() throws InterruptedException {
- final String testValue = "hello world";
- service.write(dbSession, Activity.Type.QPROFILE, testValue);
- dbSession.commit();
- assertThat(index.findAll().getTotal()).isEqualTo(1);
-
- Activity activity = Iterables.getFirst(index.findAll().getHits(), null);
- assertThat(activity).isNotNull();
- assertThat(activity.message()).isEqualTo(testValue);
- }
-
- @Test
- public void insert_find_loggable_log() {
- final String testKey = "message";
- final String testValue = "hello world";
- service.write(dbSession, Activity.Type.QPROFILE, new ActivityLog() {
-
- @Override
- public Map<String, String> getDetails() {
- return ImmutableMap.of(testKey, testValue);
- }
-
- @Override
- public String getAction() {
- return "myAction";
- }
- });
- dbSession.commit();
-
- assertThat(index.findAll().getTotal()).isEqualTo(1);
-
- Activity activity = Iterables.getFirst(index.findAll().getHits(), null);
- assertThat(activity).isNotNull();
- assertThat(activity.details().get(testKey)).isEqualTo(testValue);
- }
-
- @Test
- public void current_time_zone() {
- service.write(dbSession, Activity.Type.QPROFILE, "now");
- dbSession.commit();
-
- Activity activity = service.search(new ActivityQuery(), new QueryContext()).getHits().get(0);
- assertThat(System.currentTimeMillis() - activity.time().getTime()).isLessThan(1000L);
- }
-
- @Test
- public void massive_insert() {
-
- // 0 Assert no logs in DB
- assertThat(dao.findAll(dbSession)).hasSize(0);
- int max = 35;
- final String testValue = "hello world";
- for (int i = 0; i < max; i++) {
-
- service.write(dbSession, Activity.Type.QPROFILE, testValue + "_" + i);
- }
- dbSession.commit();
-
- // 1. assert both backends have all logs
- assertThat(dao.findAll(dbSession)).hasSize(max);
- assertThat(index.findAll().getHits()).hasSize(max);
-
- // 2. assert scrollable
- int count = 0;
- SearchResponse result = index.search(new ActivityQuery(), new QueryContext().setScroll(true));
- Iterator<Activity> logs = new Result<Activity>(index, result).scroll();
- while (logs.hasNext()) {
- logs.next();
- count++;
- }
- assertThat(count).isEqualTo(max);
-
- // 3 assert synchronize above IndexQueue threshold
- tester.clearIndexes();
- tester.get(Platform.class).executeStartupTasks();
- result = index.search(new ActivityQuery(), new QueryContext().setScroll(true));
- logs = new Result<Activity>(index, result).scroll();
- count = 0;
- while (logs.hasNext()) {
- logs.next();
- count++;
- }
- assertThat(count).isEqualTo(max);
-
- }
-
- @Test
- public void massive_log_insert() {
-
- // 0 Assert no logs in DB
- assertThat(dao.findAll(dbSession)).hasSize(0);
- int max = 40;
- final String testValue = "hello world";
- for (int i = 0; i < max; i++) {
- TestActivityLog log = new TestActivityLog(testValue + "_" + i, Activity.Type.QPROFILE.toString());
- service.write(dbSession, Activity.Type.QPROFILE, log);
- }
- dbSession.commit();
-
- // 1. assert both backends have all logs
- assertThat(dao.findAll(dbSession)).hasSize(max);
- assertThat(index.findAll().getHits()).hasSize(max);
-
- // 2. assert scrollable
- int count = 0;
- SearchResponse result = index.search(new ActivityQuery(), new QueryContext().setScroll(true));
- Iterator<Activity> logs = new Result<Activity>(index, result).scroll();
- while (logs.hasNext()) {
- logs.next();
- count++;
- }
- assertThat(count).isEqualTo(max);
-
- // 3 assert synchronize above IndexQueue threshold
- tester.clearIndexes();
- tester.get(Platform.class).executeStartupTasks();
- result = index.search(new ActivityQuery(), new QueryContext().setScroll(true));
- logs = new Result<Activity>(index, result).scroll();
- count = 0;
- while (logs.hasNext()) {
- logs.next();
- count++;
- }
- assertThat(count).isEqualTo(max);
-
- }
-
- class TestActivityLog implements ActivityLog {
-
- private final String name;
- private final String action;
-
- TestActivityLog(String name, String action) {
- this.name = name;
- this.action = action;
- }
-
- @Override
- public Map<String, String> getDetails() {
- return ImmutableMap.<String, String>of("name", name);
- }
-
- @Override
- public String getAction() {
- return action;
- }
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/activity/ActivityServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/activity/ActivityServiceMediumTest.java
deleted file mode 100644
index 71fec3c117d..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/activity/ActivityServiceMediumTest.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.activity;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import org.elasticsearch.action.search.SearchResponse;
-import org.joda.time.DateTime;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.core.activity.Activity;
-import org.sonar.core.activity.ActivityLog;
-import org.sonar.core.activity.db.ActivityDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.server.activity.db.ActivityDao;
-import org.sonar.server.activity.index.ActivityIndex;
-import org.sonar.server.activity.index.ActivityQuery;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.search.QueryContext;
-import org.sonar.server.search.Result;
-import org.sonar.server.tester.ServerTester;
-
-import java.util.Iterator;
-import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ActivityServiceMediumTest {
-
- @ClassRule
- public static ServerTester tester = new ServerTester();
-
- ActivityService service = tester.get(ActivityService.class);
- ActivityDao dao = tester.get(ActivityDao.class);
- ActivityIndex index = tester.get(ActivityIndex.class);
- DbSession dbSession;
-
- @Before
- public void before() {
- tester.clearDbAndIndexes();
- dbSession = tester.get(DbClient.class).openSession(false);
- }
-
- @After
- public void after() {
- dbSession.close();
- }
-
- @Test
- public void find_all() throws InterruptedException {
- service.write(dbSession, Activity.Type.QPROFILE, testValue);
- dbSession.commit();
- assertThat(index.findAll().getTotal()).isEqualTo(1);
-
- Activity activity = Iterables.getFirst(index.findAll().getHits(), null);
- assertThat(activity).isNotNull();
- assertThat(activity.message()).isEqualTo(testValue);
- }
-
- @Test
- public void search_message_log() throws InterruptedException {
- service.write(dbSession, Activity.Type.QPROFILE, testValue);
- dbSession.commit();
- assertThat(index.findAll().getTotal()).isEqualTo(1);
-
- SearchResponse result = index.search(service.newActivityQuery(), new QueryContext());
- assertThat(result.getHits().getTotalHits()).isEqualTo(1L);
- Result<Activity> activityResult = new Result<Activity>(index, result);
- assertThat(activityResult.getHits().get(0).message()).isEqualTo(testValue);
- }
-
- @Test
- public void search_activity_log() throws InterruptedException {
-
- service.write(dbSession, Activity.Type.QPROFILE, getActivity());
- dbSession.commit();
- assertThat(index.findAll().getTotal()).isEqualTo(1);
-
- SearchResponse result = index.search(service.newActivityQuery(), new QueryContext());
- assertThat(result.getHits().getTotalHits()).isEqualTo(1L);
- Result<Activity> activityResult = new Result<Activity>(index, result);
- assertThat(activityResult.getHits().get(0).details().get(test_key)).isEqualTo(test_value);
- }
-
- @Test
- public void filter_by_type() {
- service.write(dbSession, Activity.Type.NONE, getActivity());
- service.write(dbSession, Activity.Type.SERVER, getActivity());
- service.write(dbSession, Activity.Type.SERVER, testValue);
- service.write(dbSession, Activity.Type.QPROFILE, getActivity());
- dbSession.commit();
-
- assertThat(service.search(new ActivityQuery(),
- new QueryContext()).getHits()).hasSize(4);
-
- assertThat(service.search(new ActivityQuery()
- .setTypes(ImmutableSet.of(Activity.Type.SERVER)),
- new QueryContext()).getHits()).hasSize(2);
-
- assertThat(service.search(new ActivityQuery()
- .setTypes(ImmutableSet.of(Activity.Type.QPROFILE)),
- new QueryContext()).getHits()).hasSize(1);
- }
-
- @Test
- public void filter_by_date() throws InterruptedException {
-
- DateTime t0 = new DateTime().minusHours(1);
- ActivityDto activity = getActivityDto();
- activity.setCreatedAt(t0.toDate());
- dao.insert(dbSession, activity);
- activity = getActivityDto();
- activity.setCreatedAt(t0.toDate());
- dao.insert(dbSession, activity);
- dbSession.commit();
- DateTime t1 = new DateTime();
- activity = getActivityDto();
- activity.setCreatedAt(t1.toDate());
- dao.insert(dbSession, activity);
- dbSession.commit();
- DateTime t2 = new DateTime().plusHours(1);
-
- assertThat(service.search(new ActivityQuery(),
- new QueryContext()).getHits()).hasSize(3);
-
- assertThat(service.search(new ActivityQuery()
- .setSince(t0.minusSeconds(5).toDate()),
- new QueryContext()).getHits()).hasSize(3);
-
- assertThat(service.search(new ActivityQuery()
- .setSince(t1.minusSeconds(5).toDate()),
- new QueryContext()).getHits()).hasSize(1);
-
- assertThat(service.search(new ActivityQuery()
- .setSince(t2.minusSeconds(5).toDate()),
- new QueryContext()).getHits()).hasSize(0);
-
- assertThat(service.search(new ActivityQuery()
- .setTo(t1.minusSeconds(5).toDate()),
- new QueryContext()).getHits()).hasSize(2);
-
- assertThat(service.search(new ActivityQuery()
- .setSince(t1.minusSeconds(5).toDate())
- .setTo(t2.plusSeconds(5).toDate()),
- new QueryContext()).getHits()).hasSize(1);
- }
-
- private ActivityDto getActivityDto() {
- return ActivityDto.createFor(testValue)
- .setType(Activity.Type.NONE).setAuthor("testing");
- }
-
- @Test
- public void iterate_all() throws InterruptedException {
- int max = QueryContext.DEFAULT_LIMIT + 3;
- final String testValue = "hello world";
- for (int i = 0; i < max; i++) {
- service.write(dbSession, Activity.Type.QPROFILE, testValue + "_" + i);
- }
- dbSession.commit();
-
- // 0. assert Base case
- assertThat(dao.findAll(dbSession)).hasSize(max);
-
- SearchResponse result = index.search(service.newActivityQuery(), new QueryContext().setScroll(true));
- assertThat(result.getHits().getTotalHits()).isEqualTo(max);
- Result<Activity> activityResult = new Result<Activity>(index, result);
-
- assertThat(activityResult.getTotal()).isEqualTo(max);
- assertThat(activityResult.getHits()).hasSize(0);
- int count = 0;
- Iterator<Activity> logIterator = activityResult.scroll();
- while (logIterator.hasNext()) {
- count++;
- logIterator.next();
- }
- assertThat(count).isEqualTo(max);
- }
-
- final String test_key = "hello";
- final String test_value = "world";
- final String testValue = "hello world";
-
- private ActivityLog getActivity() {
- return new ActivityLog() {
- @Override
- public Map<String, String> getDetails() {
- return ImmutableMap.of(test_key, test_value);
- }
-
- @Override
- public String getAction() {
- return "myAction";
- }
- };
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/activity/ActivityServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/activity/ActivityServiceTest.java
new file mode 100644
index 00000000000..d12d072f1f3
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/activity/ActivityServiceTest.java
@@ -0,0 +1,91 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.activity;
+
+import org.assertj.core.data.MapEntry;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.activity.db.ActivityDao;
+import org.sonar.server.activity.index.ActivityDoc;
+import org.sonar.server.activity.index.ActivityIndexDefinition;
+import org.sonar.server.activity.index.ActivityIndexer;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.issue.db.IssueDao;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ActivityServiceTest {
+
+ @ClassRule
+ public static DbTester db = new DbTester();
+
+ @ClassRule
+ public static EsTester es = new EsTester().addDefinitions(new ActivityIndexDefinition(new Settings()));
+
+ System2 system = mock(System2.class);
+ ActivityService service;
+
+ @Before
+ public void before() {
+ ActivityDao activityDao = new ActivityDao(db.myBatis(), system);
+ IssueDao issueDao = new IssueDao(db.myBatis());
+ DbClient dbClient = new DbClient(db.database(), db.myBatis(), issueDao, activityDao);
+ ActivityIndexer indexer = new ActivityIndexer(dbClient, es.client());
+ // indexers are disabled by default
+ indexer.setEnabled(true);
+ service = new ActivityService(dbClient, indexer);
+ }
+
+ @Test
+ public void insert_and_index() throws Exception {
+ when(system.now()).thenReturn(1_500_000_000_000L);
+
+ Activity activity = new Activity();
+ activity.setType(Activity.Type.ANALYSIS_REPORT);
+ activity.setAction("THE_ACTION");
+ activity.setMessage("THE_MSG");
+ activity.setData("foo", "bar");
+ service.save(activity);
+
+ Map<String, Object> dbMap = db.selectFirst("select log_type as \"type\", log_action as \"action\", log_message as \"msg\", data_field as \"data\" from activities");
+ assertThat(dbMap).containsEntry("type", "ANALYSIS_REPORT");
+ assertThat(dbMap).containsEntry("action", "THE_ACTION");
+ assertThat(dbMap).containsEntry("msg", "THE_MSG");
+ assertThat(dbMap.get("data")).isEqualTo("foo=bar");
+
+ List<ActivityDoc> docs = es.getDocuments("activities", "activity", ActivityDoc.class);
+ assertThat(docs).hasSize(1);
+ assertThat(docs.get(0).getKey()).isNotEmpty();
+ assertThat(docs.get(0).getAction()).isEqualTo("THE_ACTION");
+ assertThat(docs.get(0).getMessage()).isEqualTo("THE_MSG");
+ assertThat(docs.get(0).getDetails()).containsOnly(MapEntry.entry("foo", "bar"));
+ }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/activity/RubyQProfileActivityServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/activity/RubyQProfileActivityServiceTest.java
index 10a2e55b65f..ef446052923 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/activity/RubyQProfileActivityServiceTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/activity/RubyQProfileActivityServiceTest.java
@@ -30,11 +30,10 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.sonar.api.utils.DateUtils;
-import org.sonar.core.activity.Activity;
+import org.sonar.server.es.SearchOptions;
import org.sonar.server.qualityprofile.QProfileActivity;
import org.sonar.server.qualityprofile.QProfileActivityQuery;
import org.sonar.server.qualityprofile.QProfileService;
-import org.sonar.server.search.QueryContext;
import org.sonar.server.search.Result;
import java.util.Date;
@@ -53,7 +52,7 @@ public class RubyQProfileActivityServiceTest {
ArgumentCaptor<QProfileActivityQuery> activityArgumentCaptor;
@Captor
- ArgumentCaptor<QueryContext> queryOptionsArgumentCaptor;
+ ArgumentCaptor<SearchOptions> queryOptionsArgumentCaptor;
RubyQProfileActivityService rubyQProfileActivityService;
@@ -70,16 +69,16 @@ public class RubyQProfileActivityServiceTest {
Result<QProfileActivity> result = mock(Result.class);
when(result.getHits()).thenReturn(Lists.<QProfileActivity>newArrayList());
when(result.getTotal()).thenReturn(10L);
- when(service.searchActivities(any(QProfileActivityQuery.class), any(QueryContext.class))).thenReturn(result);
+ when(service.searchActivities(any(QProfileActivityQuery.class), any(SearchOptions.class))).thenReturn(result);
- rubyQProfileActivityService.search(ImmutableMap.<String, Object>of("profileKeys", "PROFILE_KEY", "since", since, "to", to));
+ rubyQProfileActivityService.search(ImmutableMap.<String, Object>of("profileKey", "PROFILE_KEY", "since", since, "to", to));
verify(service).searchActivities(activityArgumentCaptor.capture(), queryOptionsArgumentCaptor.capture());
assertThat(queryOptionsArgumentCaptor.getValue().getLimit()).isEqualTo(50);
- assertThat(activityArgumentCaptor.getValue().getQprofileKeys()).containsOnly("PROFILE_KEY");
- assertThat(activityArgumentCaptor.getValue().getTypes()).containsOnly(Activity.Type.QPROFILE);
+ assertThat(activityArgumentCaptor.getValue().getQprofileKey()).isEqualTo("PROFILE_KEY");
+ assertThat(activityArgumentCaptor.getValue().getTypes()).containsOnly(Activity.Type.QPROFILE.name());
assertThat(activityArgumentCaptor.getValue().getSince()).isEqualTo(since);
assertThat(activityArgumentCaptor.getValue().getTo()).isEqualTo(to);
}
@@ -89,7 +88,7 @@ public class RubyQProfileActivityServiceTest {
Result<QProfileActivity> result = mock(Result.class);
when(result.getHits()).thenReturn(Lists.<QProfileActivity>newArrayList());
when(result.getTotal()).thenReturn(10L);
- when(service.searchActivities(any(QProfileActivityQuery.class), any(QueryContext.class))).thenReturn(result);
+ when(service.searchActivities(any(QProfileActivityQuery.class), any(SearchOptions.class))).thenReturn(result);
rubyQProfileActivityService.search(ImmutableMap.<String, Object>of());
@@ -97,7 +96,7 @@ public class RubyQProfileActivityServiceTest {
assertThat(queryOptionsArgumentCaptor.getValue().getLimit()).isEqualTo(50);
- assertThat(activityArgumentCaptor.getValue().getQprofileKeys()).isEmpty();
+ assertThat(activityArgumentCaptor.getValue().getQprofileKey()).isNull();
assertThat(activityArgumentCaptor.getValue().getSince()).isNull();
assertThat(activityArgumentCaptor.getValue().getTo()).isNull();
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/activity/db/ActivityDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/activity/db/ActivityDaoTest.java
index 1a2cd967c17..2aea0522ce8 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/activity/db/ActivityDaoTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/activity/db/ActivityDaoTest.java
@@ -19,116 +19,48 @@
*/
package org.sonar.server.activity.db;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.sonar.api.utils.KeyValueFormat;
+import org.junit.experimental.categories.Category;
import org.sonar.api.utils.System2;
-import org.sonar.core.activity.Activity;
-import org.sonar.core.activity.ActivityLog;
import org.sonar.core.activity.db.ActivityDto;
-import org.sonar.core.persistence.AbstractDaoTestCase;
-import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.test.DbTests;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@Category(DbTests.class)
+public class ActivityDaoTest {
-public class ActivityDaoTest extends AbstractDaoTestCase {
+ @Rule
+ public DbTester dbTester = new DbTester();
- private ActivityDao dao;
- private DbSession session;
+ System2 system = mock(System2.class);
+ ActivityDao sut;
@Before
public void before() throws Exception {
- this.session = getMyBatis().openSession(false);
- this.dao = new ActivityDao(mock(System2.class));
- }
-
- @After
- public void after() {
- session.close();
- }
-
- @Test
- public void fail_insert_missing_type() {
- String testValue = "hello world";
- ActivityDto log = ActivityDto.createFor(testValue);
- try {
- dao.insert(session, log);
- } catch (IllegalArgumentException e) {
- assertThat(e.getMessage()).isEqualTo("Type must be set");
- }
- }
-
-
- @Test
- public void fail_get_by_key() {
- try {
- dao.getByKey(session, "hello world");
- } catch (IllegalStateException e) {
- assertThat(e.getMessage()).isEqualTo("Cannot execute getByKey on Activities in DB");
- }
- }
-
-
- @Test
- public void fail_insert_missing_author() {
- String testValue = "hello world";
- ActivityDto log = ActivityDto.createFor(testValue)
- .setType(Activity.Type.QPROFILE);
- try {
- dao.insert(session, log);
- } catch (IllegalArgumentException e) {
- assertThat(e.getMessage()).isEqualTo("Type must be set");
- }
- }
-
- @Test
- public void insert_text_log() {
- String testValue = "hello world";
- ActivityDto log = ActivityDto.createFor(testValue)
- .setType(Activity.Type.QPROFILE)
- .setAuthor("jUnit");
- dao.insert(session, log);
-
- ActivityDto newDto = Iterables.getFirst(dao.findAll(session), null);
- assertThat(newDto).isNotNull();
- assertThat(newDto.getAuthor()).isEqualTo(log.getAuthor());
- assertThat(newDto.getMessage()).isEqualTo(testValue);
+ sut = new ActivityDao(dbTester.myBatis(), system);
}
@Test
- public void insert_loggable_log() {
- final String testKey = "message";
- final String testValue = "hello world";
- ActivityDto log = ActivityDto.createFor(new ActivityLog() {
-
- @Override
- public Map<String, String> getDetails() {
- return ImmutableMap.of(testKey, testValue);
- }
-
- @Override
- public String getAction() {
- return "myAction";
- }
- })
- .setAuthor("jUnit")
- .setType(Activity.Type.QPROFILE);
-
- dao.insert(session, log);
-
- ActivityDto newDto = Iterables.getFirst(dao.findAll(session), null);
- assertThat(newDto).isNotNull();
- assertThat(newDto.getAuthor()).isEqualTo(log.getAuthor());
- assertThat(newDto.getData()).isNotNull();
- Map<String, String> details = KeyValueFormat.parse(newDto.getData());
- assertThat(details.get(testKey)).isEqualTo(testValue);
+ public void insert() throws Exception {
+ when(system.now()).thenReturn(1_500_000_000_000L);
+ ActivityDto dto = new ActivityDto()
+ .setKey("UUID_1").setAction("THE_ACTION").setType("THE_TYPE")
+ .setAuthor("THE_AUTHOR").setData("THE_DATA");
+ sut.insert(dto);
+
+ Map<String, Object> map = dbTester.selectFirst("select created_at as \"createdAt\", log_action as \"action\", data_field as \"data\" from activities where log_key='UUID_1'");
+ assertThat(map.get("action")).isEqualTo("THE_ACTION");
+ // not possible to check exact date yet. dbTester#selectFirst() uses ResultSet#getObject(), which returns
+ // non-JDBC interface in Oracle driver.
+ assertThat(map.get("createdAt")).isNotNull();
+ assertThat(map.get("data")).isEqualTo("THE_DATA");
}
-
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityIndexDefinitionTest.java b/server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityIndexDefinitionTest.java
new file mode 100644
index 00000000000..80ef2f2fba0
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityIndexDefinitionTest.java
@@ -0,0 +1,60 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.activity.index;
+
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.process.ProcessConstants;
+import org.sonar.server.es.IndexDefinition;
+import org.sonar.server.es.NewIndex;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ActivityIndexDefinitionTest {
+
+ IndexDefinition.IndexDefinitionContext context = new IndexDefinition.IndexDefinitionContext();
+
+ @Test
+ public void define() throws Exception {
+ ActivityIndexDefinition def = new ActivityIndexDefinition(new Settings());
+ def.define(context);
+
+ assertThat(context.getIndices()).hasSize(1);
+ NewIndex index = context.getIndices().get("activities");
+ assertThat(index).isNotNull();
+ assertThat(index.getTypes().keySet()).containsOnly("activity");
+
+ // no cluster by default
+ assertThat(index.getSettings().get("index.number_of_shards")).isEqualTo("1");
+ assertThat(index.getSettings().get("index.number_of_replicas")).isEqualTo("0");
+ }
+
+ @Test
+ public void enable_cluster() throws Exception {
+ Settings settings = new Settings();
+ settings.setProperty(ProcessConstants.CLUSTER_ACTIVATE, true);
+ ActivityIndexDefinition def = new ActivityIndexDefinition(settings);
+ def.define(context);
+
+ NewIndex index = context.getIndices().get("activities");
+ assertThat(index.getSettings().get("index.number_of_shards")).isEqualTo("4");
+ assertThat(index.getSettings().get("index.number_of_replicas")).isEqualTo("1");
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityIndexTest.java
new file mode 100644
index 00000000000..8ace24aa377
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityIndexTest.java
@@ -0,0 +1,111 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.activity.index;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.server.activity.Activity;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.es.SearchOptions;
+import org.sonar.server.es.SearchResult;
+
+import java.util.Arrays;
+import java.util.Date;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ActivityIndexTest {
+
+ @ClassRule
+ public static EsTester es = new EsTester().addDefinitions(new ActivityIndexDefinition(new Settings()));
+
+ ActivityIndex sut;
+
+ @Before
+ public void before() {
+ sut = new ActivityIndex(es.client());
+ }
+
+ @Test
+ public void search_all() throws Exception {
+ es.putDocuments("activities", "activity", newDoc(1, 1_500_000_000_000L), newDoc(2, 1_600_000_000_000L));
+
+ SearchResult<ActivityDoc> results = sut.search(new ActivityQuery(), new SearchOptions());
+ assertThat(results.getTotal()).isEqualTo(2L);
+ assertThat(results.getDocs()).hasSize(2);
+ assertThat(results.getDocs()).extracting("message").containsOnly("THE_MSG 1", "THE_MSG 2");
+ }
+
+ @Test
+ public void search_by_type() throws Exception {
+ es.putDocuments("activities", "activity", newDoc(1, 1_500_000_000_000L), newDoc(2, 1_600_000_000_000L));
+
+ ActivityQuery query = new ActivityQuery();
+ query.setTypes(Arrays.asList("ANALYSIS_REPORT"));
+ assertThat(sut.search(query, new SearchOptions()).getTotal()).isEqualTo(2L);
+
+ query = new ActivityQuery();
+ query.setTypes(Arrays.asList("OTHER", "TYPES"));
+ assertThat(sut.search(query, new SearchOptions()).getTotal()).isEqualTo(0L);
+ }
+
+ @Test
+ public void search_by_data() throws Exception {
+ es.putDocuments("activities", "activity", newDoc(1, 1_500_000_000_000L), newDoc(2, 1_600_000_000_000L));
+
+ ActivityQuery query = new ActivityQuery();
+ query.addDataOrFilter("foo", "bar2");
+ SearchResult<ActivityDoc> results = sut.search(query, new SearchOptions());
+ assertThat(results.getDocs()).hasSize(1);
+ assertThat(results.getDocs().get(0).getKey()).isEqualTo("UUID2");
+ }
+
+ @Test
+ public void search_by_date() throws Exception {
+ es.putDocuments("activities", "activity", newDoc(1, 1_500_000_000_000L), newDoc(2, 1_600_000_000_000L));
+
+ ActivityQuery query = new ActivityQuery();
+ query.setSince(new Date(1_550_000_000_000L));
+ SearchResult<ActivityDoc> results = sut.search(query, new SearchOptions());
+ assertThat(results.getDocs()).hasSize(1);
+ assertThat(results.getDocs().get(0).getKey()).isEqualTo("UUID2");
+
+ query = new ActivityQuery();
+ query.setTo(new Date(1_550_000_000_000L));
+ results = sut.search(query, new SearchOptions());
+ assertThat(results.getDocs()).hasSize(1);
+ assertThat(results.getDocs().get(0).getKey()).isEqualTo("UUID1");
+ }
+
+ ActivityDoc newDoc(int id, long date) {
+ ActivityDoc doc = new ActivityDoc();
+ doc.setKey("UUID" + id);
+ doc.setType(Activity.Type.ANALYSIS_REPORT.name());
+ doc.setAction("THE_ACTION " + id);
+ doc.setMessage("THE_MSG " + id);
+ doc.setDetails(ImmutableMap.of("foo", "bar" + id));
+ doc.setLogin("THE_GUY " + id);
+ doc.setCreatedAt(new Date(date));
+ return doc;
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityResultSetIteratorTest.java b/server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityResultSetIteratorTest.java
new file mode 100644
index 00000000000..6a986068ae5
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityResultSetIteratorTest.java
@@ -0,0 +1,91 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.activity.index;
+
+import org.apache.commons.dbutils.DbUtils;
+import org.assertj.core.data.MapEntry;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.db.DbClient;
+import org.sonar.test.DbTests;
+
+import java.sql.Connection;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Category(DbTests.class)
+public class ActivityResultSetIteratorTest {
+
+ @ClassRule
+ public static DbTester dbTester = new DbTester();
+
+ DbClient client;
+ Connection connection;
+
+ @Before
+ public void setUp() throws Exception {
+ dbTester.truncateTables();
+ client = new DbClient(dbTester.database(), dbTester.myBatis());
+ connection = dbTester.openConnection();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ DbUtils.closeQuietly(connection);
+ }
+
+ @Test
+ public void traverse() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "traverse.xml");
+ ActivityResultSetIterator it = ActivityResultSetIterator.create(client, connection, 0L);
+ assertThat(it.hasNext()).isTrue();
+ ActivityDoc doc = it.next();
+ assertThat(doc).isNotNull();
+ assertThat(doc.getKey()).isEqualTo("UUID1");
+ assertThat(doc.getAction()).isEqualTo("THE_ACTION");
+ assertThat(doc.getMessage()).isEqualTo("THE_MSG");
+ assertThat(doc.getDetails()).containsOnly(MapEntry.entry("foo", "bar"));
+ assertThat(doc.getLogin()).isEqualTo("THE_AUTHOR");
+
+ assertThat(it.hasNext()).isTrue();
+ assertThat(it.next()).isNotNull();
+ assertThat(it.hasNext()).isFalse();
+ it.close();
+ }
+
+ @Test
+ public void traverse_after_date() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "traverse.xml");
+ ActivityResultSetIterator it = ActivityResultSetIterator.create(client, connection, DateUtils.parseDate("2014-12-01").getTime());
+
+ assertThat(it.hasNext()).isTrue();
+ ActivityDoc doc = it.next();
+ assertThat(doc).isNotNull();
+ assertThat(doc.getKey()).isEqualTo("UUID2");
+
+ assertThat(it.hasNext()).isFalse();
+ it.close();
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/activity/ws/ActivitiesWebServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/activity/ws/ActivitiesWebServiceMediumTest.java
index 36920b23461..f5462dc69fa 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/activity/ws/ActivitiesWebServiceMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/activity/ws/ActivitiesWebServiceMediumTest.java
@@ -19,15 +19,12 @@
*/
package org.sonar.server.activity.ws;
-import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.sonar.api.server.ws.WebService;
-import org.sonar.core.activity.Activity;
-import org.sonar.core.persistence.DbSession;
+import org.sonar.server.activity.Activity;
import org.sonar.server.activity.ActivityService;
-import org.sonar.server.db.DbClient;
import org.sonar.server.tester.ServerTester;
import org.sonar.server.user.MockUserSession;
import org.sonar.server.ws.WsTester;
@@ -39,22 +36,14 @@ public class ActivitiesWebServiceMediumTest {
@ClassRule
public static ServerTester tester = new ServerTester();
- private ActivitiesWebService ws;
- private ActivityService service;
- private DbSession session;
-
+ ActivitiesWebService ws;
+ ActivityService service;
@Before
public void setUp() throws Exception {
tester.clearDbAndIndexes();
ws = tester.get(ActivitiesWebService.class);
service = tester.get(ActivityService.class);
- session = tester.get(DbClient.class).openSession(false);
- }
-
- @After
- public void after() {
- session.close();
}
@Test
@@ -70,14 +59,20 @@ public class ActivitiesWebServiceMediumTest {
}
@Test
- public void search_logs() throws Exception {
- service.write(session, Activity.Type.QPROFILE, "Hello World");
- session.commit();
+ public void search() throws Exception {
+ Activity activity = new Activity();
+ activity.setType(Activity.Type.ANALYSIS_REPORT);
+ activity.setAction("THE_ACTION");
+ activity.setMessage("THE_MSG");
+ activity.setData("foo", "bar");
+ service.save(activity);
MockUserSession.set();
- // 1. List single Text log
- WsTester.TestRequest request = tester.wsTester().newGetRequest(ActivitiesWebService.API_ENDPOINT, SearchAction.SEARCH_ACTION);
+ WsTester.TestRequest request = tester.wsTester().newGetRequest("api/activities", "search");
WsTester.Result result = request.execute();
+ assertThat(result.outputAsString()).contains("\"total\":1");
+ assertThat(result.outputAsString()).contains("\"type\":\"ANALYSIS_REPORT\"");
+ assertThat(result.outputAsString()).contains("\"details\":{\"foo\":\"bar\"}");
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportLogMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportLogMediumTest.java
deleted file mode 100644
index 986a364c59c..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportLogMediumTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation;
-
-import com.google.common.collect.Iterables;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.activity.Activity;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.server.activity.ActivityService;
-import org.sonar.server.activity.index.ActivityIndex;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.tester.ServerTester;
-
-import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.activity.Activity.Type.ANALYSIS_REPORT;
-import static org.sonar.core.computation.db.AnalysisReportDto.Status.FAILED;
-
-public class AnalysisReportLogMediumTest {
- @ClassRule
- public static ServerTester tester = new ServerTester();
-
- private ActivityService service = tester.get(ActivityService.class);
- private ActivityIndex index = tester.get(ActivityIndex.class);
- private DbSession dbSession;
-
- private AnalysisReportLog sut;
-
- @Before
- public void before() {
- tester.clearDbAndIndexes();
- dbSession = tester.get(DbClient.class).openSession(false);
- }
-
- @After
- public void after() {
- dbSession.close();
- }
-
- @Test
- public void insert_find_analysis_report_log() {
- AnalysisReportDto report = AnalysisReportDto.newForTests(1L)
- .setProjectKey("projectKey")
- .setStatus(FAILED)
- .setCreatedAt(DateUtils.parseDate("2014-10-15").getTime())
- .setUpdatedAt(DateUtils.parseDate("2014-10-16").getTime())
- .setStartedAt(DateUtils.parseDate("2014-10-17").getTime())
- .setFinishedAt(DateUtils.parseDate("2014-10-18").getTime());
- ComponentDto project = ComponentTesting.newProjectDto();
-
- service.write(dbSession, ANALYSIS_REPORT, new AnalysisReportLog(report, project));
- dbSession.commit();
-
- // 0. AssertBase case
- assertThat(index.findAll().getHits()).hasSize(1);
-
- Activity activity = Iterables.getFirst(index.findAll().getHits(), null);
- assertThat(activity).isNotNull();
- Map<String, String> details = activity.details();
- assertThat(details.get("key")).isEqualTo(String.valueOf(report.getId()));
- assertThat(details.get("projectKey")).isEqualTo(project.key());
- assertThat(details.get("projectName")).isEqualTo(project.name());
- assertThat(details.get("projectUuid")).isEqualTo(project.uuid());
- assertThat(details.get("status")).isEqualTo("FAILED");
- assertThat(details.get("submittedAt")).isEqualTo("2014-10-15T00:00:00+0200");
- assertThat(details.get("startedAt")).isEqualTo("2014-10-17T00:00:00+0200");
- assertThat(details.get("finishedAt")).isEqualTo("2014-10-18T00:00:00+0200");
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportQueueCleanerTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportQueueCleanerTest.java
deleted file mode 100644
index 1a8f5aa55ad..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportQueueCleanerTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.platform.ServerUpgradeStatus;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.server.computation.db.AnalysisReportDao;
-import org.sonar.server.db.DbClient;
-
-import static org.mockito.Mockito.*;
-
-public class AnalysisReportQueueCleanerTest {
-
- AnalysisReportQueueCleaner sut;
- ServerUpgradeStatus serverUpgradeStatus;
- DbClient dbClient;
- AnalysisReportDao analysisReportDao;
- DbSession session;
-
- @Before
- public void before() {
- analysisReportDao = mock(AnalysisReportDao.class);
- serverUpgradeStatus = mock(ServerUpgradeStatus.class);
- dbClient = mock(DbClient.class);
- session = mock(DbSession.class);
-
- when(dbClient.analysisReportDao()).thenReturn(analysisReportDao);
- when(dbClient.openSession(false)).thenReturn(session);
-
- sut = new AnalysisReportQueueCleaner(serverUpgradeStatus, dbClient);
- }
-
- @Test
- public void start_must_call_dao_clean_update_to_pending_by_default() {
- sut.start();
- verify(analysisReportDao).resetAllToPendingStatus(any(DbSession.class));
- sut.stop();
- }
-
- @Test
- public void start_must_call_dao_truncate_when_upgrading() {
- when(serverUpgradeStatus.isUpgraded()).thenReturn(Boolean.TRUE);
- sut.start();
- verify(analysisReportDao).truncate(any(DbSession.class));
- sut.stop();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportQueueMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportQueueMediumTest.java
deleted file mode 100644
index 2b76903a7ca..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportQueueMediumTest.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation;
-
-import org.apache.commons.io.IOUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.security.DefaultGroups;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.permission.PermissionFacade;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.user.UserDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.user.MockUserSession;
-
-import java.io.InputStream;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.computation.db.AnalysisReportDto.Status.SUCCESS;
-import static org.sonar.core.computation.db.AnalysisReportDto.Status.WORKING;
-
-public class AnalysisReportQueueMediumTest {
- private static final String DEFAULT_PROJECT_KEY = "123456789-987654321";
-
- @ClassRule
- public static ServerTester tester = new ServerTester();
-
- private AnalysisReportQueue sut;
-
- private DbClient db;
- private DbSession session;
- private MockUserSession userSession;
-
- @Before
- public void setUp() throws Exception {
- tester.clearDbAndIndexes();
- db = tester.get(DbClient.class);
- session = db.openSession(false);
-
- sut = tester.get(AnalysisReportQueue.class);
-
- UserDto connectedUser = new UserDto().setLogin("gandalf").setName("Gandalf");
- db.userDao().insert(session, connectedUser);
-
- userSession = MockUserSession.set()
- .setLogin(connectedUser.getLogin())
- .setUserId(connectedUser.getId().intValue())
- .setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-
- session.commit();
- }
-
- @After
- public void after() {
- MyBatis.closeQuietly(session);
- }
-
- @Test
- public void create_analysis_report_and_retrieve_it() {
- insertPermissionsForProject(DEFAULT_PROJECT_KEY);
- sut.add(DEFAULT_PROJECT_KEY, 123L, defaultReportData());
-
- List<AnalysisReportDto> reports = sut.findByProjectKey(DEFAULT_PROJECT_KEY);
- AnalysisReportDto report = reports.get(0);
-
- assertThat(reports).hasSize(1);
- assertThat(report.getProjectKey()).isEqualTo(DEFAULT_PROJECT_KEY);
- assertThat(report.getSnapshotId()).isEqualTo(123L);
- assertThat(report.getCreatedAt()).isNotNull();
- }
-
- private ComponentDto insertPermissionsForProject(String projectKey) {
- ComponentDto project = new ComponentDto().setKey(projectKey);
- db.componentDao().insert(session, project);
-
- tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
- userSession.addProjectPermissions(UserRole.USER, project.key());
-
- session.commit();
-
- return project;
- }
-
- @Test
- public void create_and_book_oldest_available_analysis_report_thrice() {
- insertPermissionsForProject(DEFAULT_PROJECT_KEY);
- insertPermissionsForProject("2");
- insertPermissionsForProject("3");
-
- sut.add(DEFAULT_PROJECT_KEY, 123L, defaultReportData());
- sut.add("2", 123L, defaultReportData());
- sut.add("3", 123L, defaultReportData());
-
- AnalysisReportDto firstBookedReport = sut.pop();
- AnalysisReportDto secondBookedReport = sut.pop();
- AnalysisReportDto thirdBookedReport = sut.pop();
-
- assertThat(firstBookedReport.getProjectKey()).isEqualTo(DEFAULT_PROJECT_KEY);
- assertThat(firstBookedReport.getStatus()).isEqualTo(WORKING);
- assertThat(firstBookedReport.getStartedAt()).isNotNull();
- assertThat(secondBookedReport.getProjectKey()).isEqualTo("2");
- assertThat(thirdBookedReport.getProjectKey()).isEqualTo("3");
- }
-
- @Test
- public void search_for_available_report_when_no_report_available() {
- AnalysisReportDto nullAnalysisReport = sut.pop();
-
- assertThat(nullAnalysisReport).isNull();
- }
-
- @Test
- public void all() {
- insertPermissionsForProject(DEFAULT_PROJECT_KEY);
-
- sut.add(DEFAULT_PROJECT_KEY, 123L, defaultReportData());
- sut.add(DEFAULT_PROJECT_KEY, 123L, defaultReportData());
- sut.add(DEFAULT_PROJECT_KEY, 123L, defaultReportData());
-
- List<AnalysisReportDto> reports = sut.all();
-
- assertThat(reports).hasSize(3);
- }
-
- @Test
- public void remove_remove_from_queue() {
- insertPermissionsForProject(DEFAULT_PROJECT_KEY);
- sut.add(DEFAULT_PROJECT_KEY, 123L, defaultReportData());
- AnalysisReportDto report = sut.pop();
- report.setStatus(SUCCESS);
-
- sut.remove(report);
-
- assertThat(sut.all()).isEmpty();
- }
-
- @Test(expected = ForbiddenException.class)
- public void cannot_add_report_when_not_the_right_rights() {
- ComponentDto project = new ComponentDto()
- .setKey("MyProject");
- db.componentDao().insert(session, project);
- session.commit();
-
- MockUserSession.set().setLogin("gandalf").addProjectPermissions(UserRole.USER, project.key());
-
- sut.add(project.getKey(), 123L, defaultReportData());
- }
-
- private InputStream defaultReportData() {
- return IOUtils.toInputStream("default-project");
- }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/activity/ActivityLog.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationContainerTest.java
index 9b0a7f54a24..bd391ffbed2 100644
--- a/sonar-core/src/main/java/org/sonar/core/activity/ActivityLog.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationContainerTest.java
@@ -17,17 +17,16 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.core.activity;
+package org.sonar.server.computation;
-import java.util.Map;
+import org.junit.Test;
-/**
- * @since 4.4
- */
-public interface ActivityLog {
-
- Map<String, String> getDetails();
+import static org.assertj.core.api.Assertions.assertThat;
- public String getAction();
+public class ComputationContainerTest {
+ @Test
+ public void componentClasses() throws Exception {
+ assertThat(ComputationContainer.componentClasses()).isNotEmpty();
+ }
}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/UnresolvedIssuesStatusesWidget.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationContextTest.java
index d2ac0d22aa0..5f20e21bb36 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/UnresolvedIssuesStatusesWidget.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationContextTest.java
@@ -17,14 +17,23 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.plugins.core.widgets.issues;
-import org.sonar.api.web.WidgetCategory;
-import org.sonar.plugins.core.widgets.CoreWidget;
+package org.sonar.server.computation;
-@WidgetCategory({"Issues"})
-public class UnresolvedIssuesStatusesWidget extends CoreWidget {
- public UnresolvedIssuesStatusesWidget() {
- super("unresolved_issues_statuses", "Unresolved issues by status", "/org/sonar/plugins/core/widgets/issues/unresolved_issues_statuses.html.erb");
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.batch.protocol.output.BatchReportReader;
+import org.sonar.core.component.ComponentDto;
+
+import static org.mockito.Mockito.mock;
+
+public class ComputationContextTest {
+
+ ComputationContext sut = new ComputationContext(mock(BatchReportReader.class), mock(ComponentDto.class));
+
+ @Test(expected = IllegalStateException.class)
+ public void setProjectSettings() throws Exception {
+ sut.setProjectSettings(mock(Settings.class));
+ sut.setProjectSettings(mock(Settings.class));
}
-}
+} \ No newline at end of file
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java
index e983b901cef..b2e8f78452a 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java
@@ -19,21 +19,33 @@
*/
package org.sonar.server.computation;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.junit.Before;
import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
+import org.mockito.Mockito;
import org.sonar.api.resources.Qualifiers;
-import org.sonar.core.activity.Activity;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.ZipUtils;
+import org.sonar.api.utils.internal.JUnitTempFolder;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.DbTester;
+import org.sonar.server.activity.Activity;
import org.sonar.server.activity.ActivityService;
import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.computation.step.ComputationStep;
import org.sonar.server.computation.step.ComputationSteps;
import org.sonar.server.db.DbClient;
+import org.sonar.server.properties.ProjectSettingsFactory;
+import java.io.File;
+import java.io.IOException;
import java.util.Arrays;
import static org.assertj.core.api.Assertions.assertThat;
@@ -46,62 +58,98 @@ public class ComputationServiceTest {
@ClassRule
public static DbTester dbTester = new DbTester();
+ @Rule
+ public JUnitTempFolder tempFolder = new JUnitTempFolder();
+
+ @Rule
+ public LogTester logTester = new LogTester();
+
ComputationStep projectStep1 = mockStep(Qualifiers.PROJECT);
ComputationStep projectStep2 = mockStep(Qualifiers.PROJECT);
ComputationStep viewStep = mockStep(Qualifiers.VIEW);
ComputationSteps steps = mock(ComputationSteps.class);
ActivityService activityService = mock(ActivityService.class);
+ System2 system = mock(System2.class);
+ ComputationService sut;
+ ProjectSettingsFactory settingsFactory = mock(ProjectSettingsFactory.class, Mockito.RETURNS_DEEP_STUBS);
@Before
public void setUp() throws Exception {
- dbTester.truncateTables();
+ DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao());
+ sut = new ComputationService(dbClient, steps, activityService, settingsFactory, tempFolder, system);
+
+ // db contains project with key "P1"
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
}
@Test
public void process_project() throws Exception {
- // db contains project with key "PROJECT_KEY"
- dbTester.prepareDbUnit(getClass(), "shared.xml");
- DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao());
+ logTester.setLevel(LoggerLevel.INFO);
+ // view step is not supposed to be executed
when(steps.orderedSteps()).thenReturn(Arrays.asList(projectStep1, projectStep2, viewStep));
+ AnalysisReportDto dto = AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1");
+ File zip = generateZip();
+
+ sut.process(new ReportQueue.Item(dto, zip));
- // load report from db and parse it
- ComputationService sut = new ComputationService(dbClient, steps, activityService);
- AnalysisReportDto report = AnalysisReportDto.newForTests(1L);
- report.setProjectKey("PROJECT_KEY");
- assertThat(report.getStatus()).isNull();
- sut.process(report);
+ // report is integrated -> status is set to SUCCESS
+ assertThat(dto.getStatus()).isEqualTo(AnalysisReportDto.Status.SUCCESS);
+ assertThat(dto.getFinishedAt()).isNotNull();
- // status of report is set
- assertThat(report.getStatus()).isEqualTo(AnalysisReportDto.Status.SUCCESS);
+ // one info log at the end
+ assertThat(logTester.logs(LoggerLevel.INFO)).hasSize(1);
+ assertThat(logTester.logs(LoggerLevel.INFO).get(0)).startsWith("Analysis of project P1 (report 1) (done) | time=");
// execute only the steps supporting the project qualifier
verify(projectStep1).execute(any(ComputationContext.class));
verify(projectStep2).execute(any(ComputationContext.class));
verify(viewStep, never()).execute(any(ComputationContext.class));
- verify(activityService).write(any(DbSession.class), eq(Activity.Type.ANALYSIS_REPORT), any(AnalysisReportLog.class));
+ verify(activityService).save(any(Activity.class));
}
@Test
- public void fail_to_parse_report() throws Exception {
- // db contains project with key "PROJECT_KEY"
- dbTester.prepareDbUnit(getClass(), "shared.xml");
- DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao());
+ public void debug_logs() throws Exception {
+ logTester.setLevel(LoggerLevel.DEBUG);
+
+ AnalysisReportDto dto = AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1");
+ File zip = generateZip();
+ sut.process(new ReportQueue.Item(dto, zip));
+
+ assertThat(logTester.logs(LoggerLevel.DEBUG)).isNotEmpty();
+ }
+
+ @Test
+ public void fail_if_corrupted_zip() throws Exception {
+ AnalysisReportDto dto = AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1");
+ File zip = tempFolder.newFile();
+ FileUtils.write(zip, "not a file");
+
+ try {
+ sut.process(new ReportQueue.Item(dto, zip));
+ fail();
+ } catch (IllegalStateException e) {
+ assertThat(e.getMessage()).startsWith("Fail to unzip " + zip.getAbsolutePath() + " into ");
+ assertThat(dto.getStatus()).isEqualTo(AnalysisReportDto.Status.FAILED);
+ assertThat(dto.getFinishedAt()).isNotNull();
+ }
+ }
+ @Test
+ public void step_error() throws Exception {
when(steps.orderedSteps()).thenReturn(Arrays.asList(projectStep1));
- doThrow(new UnsupportedOperationException()).when(projectStep1).execute(any(ComputationContext.class));
+ doThrow(new IllegalStateException("pb")).when(projectStep1).execute(any(ComputationContext.class));
+
+ AnalysisReportDto dto = AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1");
+ File zip = generateZip();
- // load report from db and parse it
- ComputationService sut = new ComputationService(dbClient, steps, activityService);
- AnalysisReportDto report = AnalysisReportDto.newForTests(1L);
- report.setProjectKey("PROJECT_KEY");
try {
- sut.process(report);
+ sut.process(new ReportQueue.Item(dto, zip));
fail();
- } catch (UnsupportedOperationException e) {
- // status of report is set
- assertThat(report.getStatus()).isEqualTo(AnalysisReportDto.Status.FAILED);
- verify(activityService).write(any(DbSession.class), eq(Activity.Type.ANALYSIS_REPORT), any(AnalysisReportLog.class));
+ } catch (IllegalStateException e) {
+ assertThat(e.getMessage()).isEqualTo("pb");
+ assertThat(dto.getStatus()).isEqualTo(AnalysisReportDto.Status.FAILED);
+ assertThat(dto.getFinishedAt()).isNotNull();
}
}
@@ -111,4 +159,17 @@ public class ComputationServiceTest {
when(step.getDescription()).thenReturn(RandomStringUtils.randomAscii(5));
return step;
}
+
+ private File generateZip() throws IOException {
+ File dir = tempFolder.newDir();
+ BatchReportWriter writer = new BatchReportWriter(dir);
+ writer.writeMetadata(BatchReport.Metadata.newBuilder()
+ .setRootComponentRef(1)
+ .setProjectKey("PROJECT_KEY")
+ .setAnalysisDate(150000000L)
+ .build());
+ File zip = tempFolder.newFile();
+ ZipUtils.zipDir(dir, zip);
+ return zip;
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationThreadLauncherTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationThreadLauncherTest.java
index 61379a03b03..09f80a61872 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationThreadLauncherTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationThreadLauncherTest.java
@@ -39,11 +39,11 @@ public class ComputationThreadLauncherTest {
public TestRule timeout = new DisableOnDebug(Timeout.seconds(5));
ComputationThreadLauncher sut;
- AnalysisReportQueue queue;
+ ReportQueue queue;
@Before
public void before() {
- this.queue = mock(AnalysisReportQueue.class);
+ this.queue = mock(ReportQueue.class);
}
@After
@@ -74,6 +74,12 @@ public class ComputationThreadLauncherTest {
verify(queue, atLeastOnce()).pop();
}
+ @Test
+ public void test_real_constructor() throws Exception {
+ sut = new ComputationThreadLauncher(queue);
+ sut.start();
+ }
+
private void sleep() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(500L);
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationThreadTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationThreadTest.java
index d3ecf46306e..43cac0b1700 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationThreadTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationThreadTest.java
@@ -20,44 +20,81 @@
package org.sonar.server.computation;
-import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.utils.log.LogTester;
import org.sonar.core.computation.db.AnalysisReportDto;
+import java.io.IOException;
+
+import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;
public class ComputationThreadTest {
- private ComputationThread sut;
- private AnalysisReportQueue queue;
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
- @Before
- public void before() {
- this.queue = mock(AnalysisReportQueue.class);
- this.sut = new ComputationThread(queue);
- }
+ @Rule
+ public LogTester logTester = new LogTester();
+
+ ComputationContainer container = mock(ComputationContainer.class);
+ ReportQueue queue = mock(ReportQueue.class);
+ ComputationThread sut = new ComputationThread(queue, container);
@Test
- public void call_findAndBook_and_no_call_to_analyze_if_no_report_found() {
+ public void do_nothing_if_queue_empty() {
+ when(queue.pop()).thenReturn(null);
+
sut.run();
verify(queue).pop();
+ verifyZeroInteractions(container);
}
@Test
- public void call_findAndBook_and_then_analyze_if_there_is_a_report() {
+ public void pop_queue_and_integrate_report() throws IOException {
AnalysisReportDto report = AnalysisReportDto.newForTests(1L);
- when(queue.pop()).thenReturn(report);
+ ReportQueue.Item item = new ReportQueue.Item(report, temp.newFile());
+ when(queue.pop()).thenReturn(item);
sut.run();
verify(queue).pop();
+ verify(container).execute(item);
}
@Test
- public void when_the_analysis_throws_an_exception_it_does_not_break_the_task() throws Exception {
+ public void handle_error_during_queue_pop() throws Exception {
when(queue.pop()).thenThrow(new IllegalStateException());
sut.run();
+
+ assertThat(logTester.logs()).contains("Failed to pop the queue of analysis reports");
+ }
+
+ @Test
+ public void handle_error_during_integration() throws Exception {
+ AnalysisReportDto report = AnalysisReportDto.newForTests(1L).setProjectKey("P1");
+ ReportQueue.Item item = new ReportQueue.Item(report, temp.newFile());
+ when(queue.pop()).thenReturn(item);
+ doThrow(new IllegalStateException("pb")).when(container).execute(item);
+
+ sut.run();
+
+ assertThat(logTester.logs()).contains("Failed to process analysis report 1 of project P1");
+ }
+
+ @Test
+ public void handle_error_during_removal_from_queue() throws Exception {
+ AnalysisReportDto report = AnalysisReportDto.newForTests(1L).setProjectKey("P1");
+ ReportQueue.Item item = new ReportQueue.Item(report, temp.newFile());
+ when(queue.pop()).thenReturn(item);
+ doThrow(new IllegalStateException("pb")).when(queue).remove(item);
+
+ sut.run();
+
+ assertThat(logTester.logs()).contains("Failed to remove analysis report 1 from queue");
}
}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/MyUnresolvedIssuesWidget.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueCleanerTest.java
index 5c212aee71f..dde45514bd4 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/issues/MyUnresolvedIssuesWidget.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueCleanerTest.java
@@ -17,20 +17,32 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.plugins.core.widgets.issues;
-import org.sonar.api.web.*;
-import org.sonar.plugins.core.widgets.CoreWidget;
+package org.sonar.server.computation;
-import static org.sonar.api.web.WidgetScope.GLOBAL;
+import org.junit.Test;
+import org.sonar.api.platform.ServerUpgradeStatus;
-@WidgetCategory({"Issues"})
-@WidgetScope(GLOBAL)
-@WidgetProperties({
- @WidgetProperty(key = "numberOfLines", type = WidgetPropertyType.INTEGER, defaultValue = "5")
-})
-public class MyUnresolvedIssuesWidget extends CoreWidget {
- public MyUnresolvedIssuesWidget() {
- super("my_reviews", "My unresolved issues", "/org/sonar/plugins/core/widgets/issues/my_unresolved_issues.html.erb");
+import static org.mockito.Mockito.*;
+
+public class ReportQueueCleanerTest {
+
+ ServerUpgradeStatus serverUpgradeStatus = mock(ServerUpgradeStatus.class);
+ ReportQueue queue = mock(ReportQueue.class);
+ ReportQueueCleaner sut = new ReportQueueCleaner(serverUpgradeStatus, queue);
+
+ @Test
+ public void reset_reports_on_restart() {
+ sut.start();
+ verify(queue).resetToPendingStatus();
+ sut.stop();
+ }
+
+ @Test
+ public void delete_all_reports_on_upgrade() {
+ when(serverUpgradeStatus.isUpgraded()).thenReturn(Boolean.TRUE);
+ sut.start();
+ verify(queue).clear();
+ sut.stop();
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java
new file mode 100644
index 00000000000..6db7d0c9eb8
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java
@@ -0,0 +1,205 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.computation;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.System2;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.process.ProcessConstants;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.computation.db.AnalysisReportDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.test.DbTests;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING;
+import static org.sonar.core.computation.db.AnalysisReportDto.Status.WORKING;
+
+@Category(DbTests.class)
+public class ReportQueueTest {
+
+ static final long NOW = 1_500_000_000_000L;
+
+ @Rule
+ public DbTester dbTester = new DbTester();
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ Settings settings = new Settings();
+ File dataDir;
+ System2 system = mock(System2.class);
+ ReportQueue sut;
+
+ @Before
+ public void setUp() throws Exception {
+ dataDir = temp.newFolder();
+ settings.setProperty(ProcessConstants.PATH_DATA, dataDir.getAbsolutePath());
+ when(system.now()).thenReturn(NOW);
+
+ DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao(), new AnalysisReportDao(system));
+ sut = new ReportQueue(dbClient, settings);
+
+ try (DbSession session = dbClient.openSession(false)) {
+ dbClient.componentDao().insert(session, ComponentTesting.newProjectDto().setKey("P1"));
+ dbClient.componentDao().insert(session, ComponentTesting.newProjectDto().setKey("P2"));
+ dbClient.componentDao().insert(session, ComponentTesting.newProjectDto().setKey("P3"));
+ session.commit();
+ }
+ }
+
+ @Test
+ public void add_report_to_queue() throws IOException {
+ // must:
+ // 1. insert metadata in db
+ // 2. copy report content to directory /data/analysis
+ ReportQueue.Item item = sut.add("P1", generateData());
+
+ assertThat(item).isNotNull();
+ assertThat(item.zipFile).isFile().exists().hasContent("some data").hasParent(new File(dataDir, "analysis"));
+ assertThat(item.dto.getUuid()).isNotEmpty();
+ assertThat(item.dto.getId()).isGreaterThan(0L);
+
+ List<AnalysisReportDto> reports = sut.findByProjectKey("P1");
+ assertThat(reports).hasSize(1);
+ AnalysisReportDto report = reports.get(0);
+
+ assertThat(reports).hasSize(1);
+ assertThat(report.getStatus()).isEqualTo(PENDING);
+ assertThat(report.getProjectKey()).isEqualTo("P1");
+ assertThat(report.getUuid()).isNotEmpty();
+ assertThat(report.getId()).isGreaterThan(0L);
+ assertThat(report.getCreatedAt()).isEqualTo(NOW);
+ assertThat(report.getUpdatedAt()).isEqualTo(NOW);
+ assertThat(report.getStartedAt()).isNull();
+ assertThat(report.getFinishedAt()).isNull();
+
+ assertThat(FileUtils.listFiles(analysisDir(), new String[] {"zip"}, false)).hasSize(1);
+ }
+
+ @Test
+ public void find_by_project_key() throws Exception {
+ sut.add("P1", generateData());
+ assertThat(sut.findByProjectKey("P1")).hasSize(1).extracting("projectKey").containsExactly("P1");
+ assertThat(sut.findByProjectKey("P2")).isEmpty();
+ }
+
+ @Test
+ public void pop_pending_items_in_fifo_order() {
+ sut.add("P1", generateData());
+ sut.add("P2", generateData());
+ sut.add("P3", generateData());
+
+ ReportQueue.Item item = sut.pop();
+ assertThat(item.dto.getProjectKey()).isEqualTo("P1");
+ assertThat(item.zipFile).exists().isFile().hasExtension("zip");
+
+ // status changed from PENDING to WORKING
+ assertThat(item.dto.getStatus()).isEqualTo(WORKING);
+
+ assertThat(sut.pop().dto.getProjectKey()).isEqualTo("P2");
+ assertThat(sut.pop().dto.getProjectKey()).isEqualTo("P3");
+
+ // queue is empty
+ assertThat(sut.pop()).isNull();
+
+ // items are still in db, but in WORKING status
+ List<AnalysisReportDto> reports = sut.all();
+ assertThat(reports).hasSize(3);
+ assertThat(reports).extracting("status").containsOnly(WORKING);
+ }
+
+ @Test
+ public void remove() {
+ ReportQueue.Item item = sut.add("P1", generateData());
+ assertThat(dbTester.countRowsOfTable("analysis_reports")).isEqualTo(1);
+
+ sut.remove(item);
+ assertThat(dbTester.countRowsOfTable("analysis_reports")).isEqualTo(0);
+ assertThat(item.zipFile).doesNotExist();
+ }
+
+ @Test
+ public void do_not_pop_corrupted_item() throws Exception {
+ ReportQueue.Item item = sut.add("P1", generateData());
+
+ // emulate corruption: file is missing on FS
+ FileUtils.deleteQuietly(item.zipFile);
+
+ assertThat(sut.pop()).isNull();
+
+ // table sanitized
+ assertThat(dbTester.countRowsOfTable("analysis_reports")).isEqualTo(0);
+ }
+
+ @Test
+ public void clear() throws Exception {
+ sut.add("P1", generateData());
+ sut.add("P2", generateData());
+ assertThat(analysisDir()).exists().isDirectory();
+
+ sut.clear();
+
+ assertThat(dbTester.countRowsOfTable("analysis_reports")).isEqualTo(0);
+ assertThat(analysisDir()).doesNotExist();
+ }
+
+ @Test
+ public void reset_to_pending_status() throws Exception {
+ // 2 pending
+ sut.add("P1", generateData());
+ sut.add("P2", generateData());
+
+ // pop 1 -> 1 pending and 1 working
+ ReportQueue.Item workingItem = sut.pop();
+ assertThat(workingItem.dto.getStatus()).isEqualTo(WORKING);
+ assertThat(sut.all()).extracting("status").contains(PENDING, WORKING);
+
+ sut.resetToPendingStatus();
+ assertThat(sut.all()).extracting("status").containsOnly(PENDING).hasSize(2);
+
+ }
+
+ private InputStream generateData() {
+ return IOUtils.toInputStream("some data");
+ }
+
+ private File analysisDir() {
+ return new File(dataDir, "analysis");
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/db/AnalysisReportDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/db/AnalysisReportDaoTest.java
index eddb4326798..bf4456f66ab 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/db/AnalysisReportDaoTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/db/AnalysisReportDaoTest.java
@@ -20,8 +20,11 @@
package org.sonar.server.computation.db;
-import org.apache.commons.io.IOUtils;
-import org.junit.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.utils.System2;
@@ -31,8 +34,6 @@ import org.sonar.core.persistence.DbTester;
import org.sonar.core.persistence.MyBatis;
import org.sonar.test.DbTests;
-import java.io.File;
-import java.io.InputStream;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@@ -46,7 +47,6 @@ import static org.sonar.core.computation.db.AnalysisReportDto.Status.WORKING;
public class AnalysisReportDaoTest {
private static final String DEFAULT_PROJECT_KEY = "123456789-987654321";
- private static final long DEFAULT_SNAPSHOT_ID = 123L;
@ClassRule
public static DbTester db = new DbTester();
@@ -54,13 +54,12 @@ public class AnalysisReportDaoTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
- private AnalysisReportDao sut;
- private DbSession session;
- private System2 system2;
+ AnalysisReportDao sut;
+ DbSession session;
+ System2 system2;
@Before
public void before() {
- db.truncateTables();
this.session = db.myBatis().openSession(false);
this.system2 = mock(System2.class);
this.sut = new AnalysisReportDao(system2);
@@ -78,8 +77,8 @@ public class AnalysisReportDaoTest {
public void insert_multiple_reports() throws Exception {
db.prepareDbUnit(getClass(), "empty.xml");
- AnalysisReportDto report1 = newDefaultAnalysisReport();
- AnalysisReportDto report2 = newDefaultAnalysisReport();
+ AnalysisReportDto report1 = newDefaultAnalysisReport().setUuid("UUID_1");
+ AnalysisReportDto report2 = newDefaultAnalysisReport().setUuid("UUID_2");
sut.insert(session, report1);
sut.insert(session, report2);
@@ -89,15 +88,6 @@ public class AnalysisReportDaoTest {
}
@Test
- public void insert_report_data_do_not_throw_exception() throws Exception {
- db.prepareDbUnit(getClass(), "empty.xml");
- AnalysisReportDto report = newDefaultAnalysisReport()
- .setData(getClass().getResource("/org/sonar/server/computation/db/AnalysisReportDaoTest/zip.zip").openStream());
-
- sut.insert(session, report);
- }
-
- @Test
public void resetAllToPendingStatus() {
db.prepareDbUnit(getClass(), "update-all-to-status-pending.xml");
@@ -171,8 +161,6 @@ public class AnalysisReportDaoTest {
assertThat(report.getStartedAt()).isEqualTo(parseDate("2014-09-26").getTime());
assertThat(report.getFinishedAt()).isEqualTo(parseDate("2014-09-27").getTime());
assertThat(report.getStatus()).isEqualTo(WORKING);
- assertThat(report.getData()).isNull();
- assertThat(report.getKey()).isEqualTo("1");
}
@Test
@@ -221,31 +209,10 @@ public class AnalysisReportDaoTest {
assertThat(reports).hasSize(3);
}
- @Test
- public void insert_and_then_retrieve_report_data_with_decompressed_files_medium_test() throws Exception {
- // ARRANGE
- db.prepareDbUnit(getClass(), "empty.xml");
- AnalysisReportDto report = newDefaultAnalysisReport();
- InputStream zip = getClass().getResource("/org/sonar/server/computation/db/AnalysisReportDaoTest/zip.zip").openStream();
- report.setData(zip);
-
- File toDir = temp.newFolder();
- sut.insert(session, report);
- session.commit();
- IOUtils.closeQuietly(zip);
-
- // ACT
- sut.selectAndDecompressToDir(session, 1L, toDir);
-
- // ASSERT
- assertThat(toDir.list()).hasSize(3);
- }
-
private AnalysisReportDto newDefaultAnalysisReport() {
return AnalysisReportDto.newForTests(1L)
.setProjectKey(DEFAULT_PROJECT_KEY)
- .setSnapshotId(DEFAULT_SNAPSHOT_ID)
- .setData(null)
+ .setUuid("REPORT_UUID")
.setStatus(PENDING);
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueComputationTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueComputationTest.java
index 93a8ee42290..fcd90b2c4cd 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueComputationTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueComputationTest.java
@@ -21,18 +21,23 @@ package org.sonar.server.computation.issue;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.Mockito;
+import org.sonar.api.CoreProperties;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.System2;
+import org.sonar.api.utils.log.LogTester;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.user.index.UserDoc;
+import org.sonar.server.user.index.UserIndex;
import java.io.IOException;
import java.util.Arrays;
@@ -47,6 +52,9 @@ public class IssueComputationTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
+ @Rule
+ public LogTester logTester = new LogTester();
+
IssueComputation sut;
// inputs
@@ -59,6 +67,8 @@ public class IssueComputationTest {
.setRuleRepository(RULE_KEY.repository())
.setRuleKey(RULE_KEY.rule())
.setStatus(Issue.STATUS_OPEN);
+ ComputationContext context = mock(ComputationContext.class, Mockito.RETURNS_DEEP_STUBS);
+ UserIndex userIndex = mock(UserIndex.class);
// output
IssueCache outputIssues;
@@ -67,7 +77,12 @@ public class IssueComputationTest {
public void setUp() throws IOException {
when(ruleCache.get(RULE_KEY)).thenReturn(rule);
outputIssues = new IssueCache(temp.newFile(), System2.INSTANCE);
- sut = new IssueComputation(ruleCache, lineCache, scmAccountCache, outputIssues);
+ sut = new IssueComputation(ruleCache, lineCache, scmAccountCache, outputIssues, userIndex);
+ }
+
+ @After
+ public void after() throws Exception {
+ sut.afterReportProcessing();
}
@Test
@@ -172,8 +187,33 @@ public class IssueComputationTest {
verifyZeroInteractions(scmAccountCache);
}
+ @Test
+ public void assign_default_assignee_when_available() throws Exception {
+ inputIssue.setIsNew(true);
+ String wolinski = "wolinski";
+ when(context.getProjectSettings().getString(CoreProperties.DEFAULT_ISSUE_ASSIGNEE)).thenReturn(wolinski);
+ when(userIndex.getNullableByLogin(wolinski)).thenReturn(new UserDoc());
+
+ process();
+
+ assertThat(Iterators.getOnlyElement(outputIssues.traverse()).assignee()).isEqualTo(wolinski);
+ assertThat(logTester.logs()).doesNotContain(String.format("the %s property was set with an unknown login: %s", CoreProperties.DEFAULT_ISSUE_ASSIGNEE, wolinski));
+ }
+
+ @Test
+ public void do_not_assign_default_assignee_when_not_found_in_index() throws Exception {
+ inputIssue.setIsNew(true);
+ String wolinski = "wolinski";
+ when(context.getProjectSettings().getString(CoreProperties.DEFAULT_ISSUE_ASSIGNEE)).thenReturn(wolinski);
+ when(userIndex.getNullableByLogin(wolinski)).thenReturn(null);
+
+ process();
+
+ assertThat(Iterators.getOnlyElement(outputIssues.traverse()).assignee()).isNull();
+ assertThat(logTester.logs()).contains(String.format("the %s property was set with an unknown login: %s", CoreProperties.DEFAULT_ISSUE_ASSIGNEE, wolinski));
+ }
+
private void process() {
- sut.processComponentIssues(mock(ComputationContext.class, Mockito.RETURNS_DEEP_STUBS), "FILE_A", Arrays.asList(inputIssue.build()));
- sut.afterReportProcessing();
+ sut.processComponentIssues(context, "FILE_A", Arrays.asList(inputIssue.build()));
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ApplyPermissionsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ApplyPermissionsStepTest.java
index a7554148090..938a2d49d48 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ApplyPermissionsStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ApplyPermissionsStepTest.java
@@ -20,17 +20,25 @@
package org.sonar.server.computation.step;
import org.junit.Test;
+import org.sonar.server.computation.ComputationContext;
import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-public class ApplyPermissionsStepTest {
+public class ApplyPermissionsStepTest extends BaseStepTest {
+
+ IssueAuthorizationIndexer indexer = mock(IssueAuthorizationIndexer.class);
+ ApplyPermissionsStep step = new ApplyPermissionsStep(indexer);
@Test
public void index_issue_permissions() throws Exception {
- IssueAuthorizationIndexer indexer = mock(IssueAuthorizationIndexer.class);
- new ApplyPermissionsStep(indexer).execute(null);
+ step.execute(mock(ComputationContext.class));
verify(indexer).index();
}
+
+ @Override
+ protected ComputationStep step() {
+ return step;
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationComponentsTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/BaseStepTest.java
index ae7590ce6fe..6515c697fe7 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationComponentsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/BaseStepTest.java
@@ -17,22 +17,26 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.server.computation;
+package org.sonar.server.computation.step;
import org.junit.Test;
-import org.sonar.test.TestUtils;
+
+import java.io.IOException;
import static org.assertj.core.api.Assertions.assertThat;
-public class ComputationComponentsTest {
+/**
+ * Temporary solution to test metadata. Should be replaced by a medium test of
+ * all computation stack
+ */
+public abstract class BaseStepTest {
- @Test
- public void nonStepComponents() throws Exception {
- assertThat(ComputationComponents.nonStepComponents()).isNotEmpty();
- }
+ protected abstract ComputationStep step() throws IOException;
@Test
- public void util_class() throws Exception {
- assertThat(TestUtils.hasOnlyPrivateConstructors(ComputationComponents.class)).isTrue();
+ public void test_metadata() throws Exception {
+ assertThat(step().toString()).isNotEmpty();
+ assertThat(step().supportedProjectQualifiers().length).isGreaterThan(0);
+
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexComponentsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexComponentsStepTest.java
index bd6fb0263d8..ccb4223c2a5 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexComponentsStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexComponentsStepTest.java
@@ -20,10 +20,9 @@
package org.sonar.server.computation.step;
-import org.junit.Before;
import org.junit.Test;
+import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.core.component.ComponentDto;
-import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.resource.ResourceIndexerDao;
import org.sonar.server.computation.ComputationContext;
@@ -31,26 +30,24 @@ import java.io.IOException;
import static org.mockito.Mockito.*;
-public class IndexComponentsStepTest {
+public class IndexComponentsStepTest extends BaseStepTest {
- IndexComponentsStep sut;
- ResourceIndexerDao resourceIndexerDao;
-
- @Before
- public void before() {
- this.resourceIndexerDao = mock(ResourceIndexerDao.class);
- this.sut = new IndexComponentsStep(resourceIndexerDao);
- }
+ ResourceIndexerDao resourceIndexerDao = mock(ResourceIndexerDao.class);
+ IndexComponentsStep sut = new IndexComponentsStep(resourceIndexerDao);
@Test
public void call_indexProject_of_dao() throws IOException {
ComponentDto project = mock(ComponentDto.class);
when(project.getId()).thenReturn(123L);
- ComputationContext context = new ComputationContext(mock(AnalysisReportDto.class), project);
+ ComputationContext context = new ComputationContext(mock(BatchReportReader.class), project);
sut.execute(context);
verify(resourceIndexerDao).indexProject(123L);
}
+ @Override
+ protected ComputationStep step() {
+ return sut;
+ }
}
diff --git a/sonar-core/src/main/java/org/sonar/core/activity/Activity.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexSourceLinesStepTest.java
index c5ede01df71..fb0042ba9ea 100644
--- a/sonar-core/src/main/java/org/sonar/core/activity/Activity.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexSourceLinesStepTest.java
@@ -17,30 +17,24 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.core.activity;
+package org.sonar.server.computation.step;
-import java.util.Date;
-import java.util.Map;
+import org.junit.Test;
+import org.sonar.server.source.index.SourceLineIndexer;
-/**
- * @since 4.4
- */
-public interface Activity {
-
- Type type();
-
- String action();
+import java.io.IOException;
- Date time();
+import static org.mockito.Mockito.mock;
- String login();
+public class IndexSourceLinesStepTest extends BaseStepTest {
- Map<String, String> details();
+ @Test
+ public void supportedProjectQualifiers() throws Exception {
- String message();
-
- public static enum Type {
- NONE, QPROFILE, SERVER, ANALYSIS_REPORT
}
+ @Override
+ protected ComputationStep step() throws IOException {
+ return new IndexSourceLinesStep(mock(SourceLineIndexer.class));
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexViewsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexViewsStepTest.java
index 8c8fbd5409f..fc1c913232a 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexViewsStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexViewsStepTest.java
@@ -28,7 +28,7 @@ import org.sonar.server.view.index.ViewIndexer;
import static org.mockito.Mockito.*;
-public class IndexViewsStepTest {
+public class IndexViewsStepTest extends BaseStepTest {
ComputationContext context = mock(ComputationContext.class);
ViewIndexer indexer = mock(ViewIndexer.class);
@@ -43,4 +43,8 @@ public class IndexViewsStepTest {
verify(indexer).index("ABCD");
}
+ @Override
+ protected ComputationStep step() {
+ return sut;
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ParseReportStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ParseReportStepTest.java
index 2d3c8204029..d12664859de 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ParseReportStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ParseReportStepTest.java
@@ -19,35 +19,38 @@
*/
package org.sonar.server.computation.step;
-import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
+import org.sonar.api.config.Settings;
import org.sonar.api.utils.ZipUtils;
import org.sonar.api.utils.internal.DefaultTempFolder;
import org.sonar.batch.protocol.Constants;
-import org.sonar.batch.protocol.output.BatchOutputWriter;
+import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.core.component.ComponentDto;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.DbTester;
import org.sonar.server.computation.ComputationContext;
-import org.sonar.server.computation.db.AnalysisReportDao;
import org.sonar.server.computation.issue.IssueComputation;
-import org.sonar.server.db.DbClient;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
+import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-public class ParseReportStepTest {
+public class ParseReportStepTest extends BaseStepTest {
+
+ private static final List<BatchReport.Issue> ISSUES_ON_DELETED_COMPONENT = Arrays.asList(BatchReport.Issue.newBuilder()
+ .setUuid("DELETED_ISSUE_UUID")
+ .build());
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@@ -55,39 +58,38 @@ public class ParseReportStepTest {
@ClassRule
public static DbTester dbTester = new DbTester();
- @Before
- public void setUp() throws Exception {
- dbTester.truncateTables();
- }
+ IssueComputation issueComputation = mock(IssueComputation.class);
+ ParseReportStep sut = new ParseReportStep(issueComputation);
@Test
public void extract_report_from_db_and_browse_components() throws Exception {
- AnalysisReportDto reportDto = prepareAnalysisReportInDb();
+ File reportDir = generateReport();
+ ComputationContext context = new ComputationContext(new BatchReportReader(reportDir), mock(ComponentDto.class));
+ sut.execute(context);
- IssueComputation issueComputation = mock(IssueComputation.class);
- DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new AnalysisReportDao());
- ParseReportStep step = new ParseReportStep(issueComputation, dbClient, new DefaultTempFolder(temp.newFolder()));
- ComputationContext context = new ComputationContext(reportDto, mock(ComponentDto.class));
- step.execute(context);
+ assertThat(context.getReportMetadata().getRootComponentRef()).isEqualTo(1);
+ assertThat(context.getReportMetadata().getDeletedComponentsCount()).isEqualTo(1);
// verify that all components are processed (currently only for issues)
verify(issueComputation).processComponentIssues(context, "PROJECT_UUID", Collections.<BatchReport.Issue>emptyList());
verify(issueComputation).processComponentIssues(context, "FILE1_UUID", Collections.<BatchReport.Issue>emptyList());
verify(issueComputation).processComponentIssues(context, "FILE2_UUID", Collections.<BatchReport.Issue>emptyList());
+ verify(issueComputation).processComponentIssues(context, "DELETED_UUID", ISSUES_ON_DELETED_COMPONENT);
verify(issueComputation).afterReportProcessing();
- assertThat(context.getReportMetadata().getRootComponentRef()).isEqualTo(1);
}
- private AnalysisReportDto prepareAnalysisReportInDb() throws IOException {
+ private File generateReport() throws IOException {
File dir = temp.newFolder();
// project and 2 files
- BatchOutputWriter writer = new BatchOutputWriter(dir);
+ BatchReportWriter writer = new BatchReportWriter(dir);
writer.writeMetadata(BatchReport.Metadata.newBuilder()
.setRootComponentRef(1)
.setProjectKey("PROJECT_KEY")
.setAnalysisDate(150000000L)
+ .setDeletedComponentsCount(1)
.build());
+
writer.writeComponent(BatchReport.Component.newBuilder()
.setRef(1)
.setType(Constants.ComponentType.PROJECT)
@@ -105,28 +107,14 @@ public class ParseReportStepTest {
.setType(Constants.ComponentType.FILE)
.setUuid("FILE2_UUID")
.build());
- File zipFile = temp.newFile();
- ZipUtils.zipDir(dir, zipFile);
-
- AnalysisReportDto dto = new AnalysisReportDto();
- DbSession dbSession = dbTester.myBatis().openSession(false);
- try {
- dto.setProjectKey("PROJECT_KEY");
- dto.setCreatedAt(System.currentTimeMillis());
- dto.setSnapshotId(1L);
- dto.setStatus(AnalysisReportDto.Status.PENDING);
- FileInputStream inputStream = new FileInputStream(zipFile);
- dto.setData(inputStream);
- AnalysisReportDao dao = new AnalysisReportDao();
- dao.insert(dbSession, dto);
- inputStream.close();
- dbSession.commit();
-
- // dao#insert() does not set the generated id, so the row
- // is loaded again to get its id
- return dao.selectByProjectKey(dbSession, "PROJECT_KEY").get(0);
- } finally {
- dbSession.close();
- }
+
+ // deleted components
+ writer.writeDeletedComponentIssues(1, "DELETED_UUID", ISSUES_ON_DELETED_COMPONENT);
+ return dir;
+ }
+
+ @Override
+ protected ComputationStep step() {
+ return sut;
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeDatastoresStepMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeDatastoresStepMediumTest.java
deleted file mode 100644
index 004265d841c..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeDatastoresStepMediumTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation.step;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.component.SnapshotDto;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.computation.db.AnalysisReportDto.Status;
-import org.sonar.core.computation.dbcleaner.DbCleanerConstants;
-import org.sonar.core.computation.dbcleaner.ProjectCleaner;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.properties.PropertyDto;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.component.SnapshotTesting;
-import org.sonar.server.computation.ComputationContext;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.tester.ServerTester;
-
-import java.util.Date;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class PurgeDatastoresStepMediumTest {
-
- @ClassRule
- public static ServerTester tester = new ServerTester();
-
- private PurgeDatastoresStep sut;
- private DbClient dbClient;
- private DbSession dbSession;
- private ProjectCleaner purgeTask;
-
- @Before
- public void before() throws Exception {
- this.dbClient = tester.get(DbClient.class);
- this.dbSession = dbClient.openSession(false);
-
- this.purgeTask = tester.get(ProjectCleaner.class);
-
- this.sut = new PurgeDatastoresStep(dbClient, purgeTask);
- }
-
- @After
- public void after() throws Exception {
- MyBatis.closeQuietly(dbSession);
- }
-
- @Test
- public void use_global_settings_when_no_other_specified() throws Exception {
- // ARRANGE
- Date now = new Date();
- Date aWeekAgo = DateUtils.addDays(now, -7);
-
- ComponentDto project = ComponentTesting.newProjectDto()
- .setId(1L)
- .setKey("123")
- .setCreatedAt(aWeekAgo)
- .setUpdatedAt(aWeekAgo);
- dbClient.componentDao().insert(dbSession, project);
-
- SnapshotDto snapshot = SnapshotTesting.createForProject(project)
- .setCreatedAt(aWeekAgo.getTime());
- dbClient.snapshotDao().insert(dbSession, snapshot);
-
- AnalysisReportDto report = AnalysisReportDto.newForTests(1L)
- .setProjectKey("123")
- .setSnapshotId(snapshot.getId())
- .setStatus(Status.PENDING);
- dbClient.analysisReportDao().insert(dbSession, report);
-
- dbClient.propertiesDao().setProperty(new PropertyDto().setKey(DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS).setValue("52"));
- dbSession.commit();
- ComputationContext context = new ComputationContext(report, project);
-
- // ACT
- sut.execute(context);
-
- // ASSERT
- assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshot.getId())).isNotNull();
- }
-
- @Test
- public void use_project_settings_if_specified() throws Exception {
- // ARRANGE
- Date now = new Date();
- Date twoWeeksAgo = DateUtils.addDays(now, -2 * 7);
- Date aLongTimeAgo = DateUtils.addDays(now, -365 * 7);
-
- ComponentDto project = ComponentTesting.newProjectDto()
- .setKey("123")
- .setCreatedAt(aLongTimeAgo)
- .setUpdatedAt(aLongTimeAgo);
- dbClient.componentDao().insert(dbSession, project);
-
- SnapshotDto snapshot = SnapshotTesting.createForProject(project)
- .setCreatedAt(twoWeeksAgo.getTime())
- .setStatus("P")
- .setLast(true);
-
- dbClient.snapshotDao().insert(dbSession, snapshot);
-
- AnalysisReportDto report = new AnalysisReportDto()
- .setProjectKey("123")
- .setSnapshotId(snapshot.getId())
- .setStatus(Status.PENDING);
- dbClient.analysisReportDao().insert(dbSession, report);
-
- dbClient.propertiesDao().setProperty(new PropertyDto().setKey(DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS).setValue("4"));
- dbClient.propertiesDao().setProperty(new PropertyDto().setKey(DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS).setValue("1").setResourceId(project.getId()));
- dbSession.commit();
- ComputationContext context = new ComputationContext(report, project);
-
- // ACT
- sut.execute(context);
- dbSession.commit();
-
- // ASSERT
- assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshot.getId())).isNull();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeDatastoresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeDatastoresStepTest.java
index a98bb1ddb00..a2588058de4 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeDatastoresStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeDatastoresStepTest.java
@@ -20,13 +20,13 @@
package org.sonar.server.computation.step;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.Mockito;
+import org.sonar.api.config.Settings;
+import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.core.component.ComponentDto;
-import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.computation.dbcleaner.ProjectCleaner;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.purge.IdUuidPair;
@@ -38,30 +38,28 @@ import java.io.IOException;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
-public class PurgeDatastoresStepTest {
+public class PurgeDatastoresStepTest extends BaseStepTest {
- PurgeDatastoresStep sut;
- ProjectCleaner projectCleaner;
+ ProjectCleaner projectCleaner = mock(ProjectCleaner.class);;
+ PurgeDatastoresStep sut = new PurgeDatastoresStep(mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS), projectCleaner);
@Rule
public TemporaryFolder temp = new TemporaryFolder();
- @Before
- public void before() {
- this.projectCleaner = mock(ProjectCleaner.class);
-
- this.sut = new PurgeDatastoresStep(mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS), projectCleaner);
- }
-
@Test
public void call_purge_method_of_the_purge_task() throws IOException {
ComponentDto project = mock(ComponentDto.class);
when(project.getId()).thenReturn(123L);
when(project.uuid()).thenReturn("UUID-1234");
- ComputationContext context = new ComputationContext(mock(AnalysisReportDto.class), project);
+ ComputationContext context = new ComputationContext(mock(BatchReportReader.class), project);
sut.execute(context);
- verify(projectCleaner).purge(any(DbSession.class), any(IdUuidPair.class));
+ verify(projectCleaner).purge(any(DbSession.class), any(IdUuidPair.class), any(Settings.class));
+ }
+
+ @Override
+ protected ComputationStep step() {
+ return sut;
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeRemovedViewsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeRemovedViewsStepTest.java
index 0fd843bf5ca..86fce27ddb2 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeRemovedViewsStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeRemovedViewsStepTest.java
@@ -20,10 +20,7 @@
package org.sonar.server.computation.step;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
+import org.junit.*;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Qualifiers;
import org.sonar.core.component.ComponentDto;
@@ -45,31 +42,25 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-public class PurgeRemovedViewsStepTest {
+public class PurgeRemovedViewsStepTest extends BaseStepTest {
@ClassRule
public static EsTester esTester = new EsTester().addDefinitions(new ViewIndexDefinition(new Settings()));
- @ClassRule
- public static DbTester db = new DbTester();
-
- ComputationContext context;
+ @Rule
+ public DbTester db = new DbTester();
+ ComputationContext context = mock(ComputationContext.class);
DbSession session;
-
DbClient dbClient;
-
- PurgeRemovedViewsStep step;
+ PurgeRemovedViewsStep sut;
@Before
public void setUp() {
esTester.truncateIndices();
- db.truncateTables();
-
- context = mock(ComputationContext.class);
session = db.myBatis().openSession(false);
dbClient = new DbClient(db.database(), db.myBatis(), new IssueDao(db.myBatis()), new ComponentDao());
- step = new PurgeRemovedViewsStep(new ViewIndex(esTester.client()), dbClient);
+ sut = new PurgeRemovedViewsStep(new ViewIndex(esTester.client()), dbClient);
}
@After
@@ -92,15 +83,19 @@ public class PurgeRemovedViewsStepTest {
dbClient.componentDao().insert(session, view, subView);
session.commit();
- step.execute(context);
+ sut.execute(context);
- List<String> viewUuids = esTester.getDocumentFields(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW, ViewIndexDefinition.FIELD_UUID);
+ List<String> viewUuids = esTester.getDocumentFieldValues(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW, ViewIndexDefinition.FIELD_UUID);
assertThat(viewUuids).containsOnly("ABCD", "BCDE");
}
@Test
public void only_support_views() throws Exception {
- assertThat(step.supportedProjectQualifiers()).containsOnly(Qualifiers.VIEW);
+ assertThat(sut.supportedProjectQualifiers()).containsOnly(Qualifiers.VIEW);
}
+ @Override
+ protected ComputationStep step() {
+ return sut;
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/SendIssueNotificationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/SendIssueNotificationsStepTest.java
index 9f0f7b982d7..a2d4eb842d0 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/SendIssueNotificationsStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/SendIssueNotificationsStepTest.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.computation.step;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -26,6 +27,7 @@ import org.mockito.Mockito;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.notifications.Notification;
import org.sonar.api.rule.Severity;
+import org.sonar.api.utils.Durations;
import org.sonar.api.utils.System2;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.server.computation.ComputationContext;
@@ -35,10 +37,12 @@ import org.sonar.server.issue.notification.IssueChangeNotification;
import org.sonar.server.issue.notification.NewIssuesNotification;
import org.sonar.server.notifications.NotificationService;
+import java.io.IOException;
+
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
-public class SendIssueNotificationsStepTest {
+public class SendIssueNotificationsStepTest extends BaseStepTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@@ -46,32 +50,43 @@ public class SendIssueNotificationsStepTest {
RuleCache ruleCache = mock(RuleCache.class);
NotificationService notifService = mock(NotificationService.class);
ComputationContext context = mock(ComputationContext.class, Mockito.RETURNS_DEEP_STUBS);
+ IssueCache issueCache;
+ Durations durations = mock(Durations.class);
+ SendIssueNotificationsStep sut;
+
+ @Before
+ public void setUp() throws Exception {
+ issueCache = new IssueCache(temp.newFile(), System2.INSTANCE);
+ sut = new SendIssueNotificationsStep(issueCache, ruleCache, notifService, durations);
+ }
@Test
public void do_not_send_notifications_if_no_subscribers() throws Exception {
- IssueCache issueCache = new IssueCache(temp.newFile(), System2.INSTANCE);
when(context.getProject().uuid()).thenReturn("PROJECT_UUID");
when(notifService.hasProjectSubscribersForTypes("PROJECT_UUID", SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(false);
- SendIssueNotificationsStep step = new SendIssueNotificationsStep(issueCache, ruleCache, notifService);
- step.execute(context);
+ sut.execute(context);
verify(notifService, never()).deliver(any(Notification.class));
}
@Test
public void send_notifications_if_subscribers() throws Exception {
- IssueCache issueCache = new IssueCache(temp.newFile(), System2.INSTANCE);
- issueCache.newAppender().append(new DefaultIssue().setSeverity(Severity.BLOCKER)).close();
+ issueCache.newAppender().append(new DefaultIssue()
+ .setSeverity(Severity.BLOCKER)).close();
when(context.getProject().uuid()).thenReturn("PROJECT_UUID");
when(context.getReportMetadata()).thenReturn(BatchReport.Metadata.newBuilder().build());
when(notifService.hasProjectSubscribersForTypes("PROJECT_UUID", SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
- SendIssueNotificationsStep step = new SendIssueNotificationsStep(issueCache, ruleCache, notifService);
- step.execute(context);
+ sut.execute(context);
verify(notifService).deliver(any(NewIssuesNotification.class));
verify(notifService, atLeastOnce()).deliver(any(IssueChangeNotification.class));
}
+
+ @Override
+ protected ComputationStep step() throws IOException {
+ return sut;
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/SwitchSnapshotStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/SwitchSnapshotStepTest.java
index dbf46f40a74..cc4dfa9be6b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/SwitchSnapshotStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/SwitchSnapshotStepTest.java
@@ -26,9 +26,8 @@ import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
-import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.persistence.DbTester;
-import org.sonar.server.component.ComponentTesting;
import org.sonar.server.component.db.SnapshotDao;
import org.sonar.server.computation.ComputationContext;
import org.sonar.server.db.DbClient;
@@ -58,20 +57,14 @@ public class SwitchSnapshotStepTest {
@Test
public void one_switch_with_a_snapshot_and_his_children() throws IOException {
db.prepareDbUnit(getClass(), "snapshots.xml");
- ComputationContext context = new ComputationContext(AnalysisReportDto.newForTests(1L).setSnapshotId(1L),
- ComponentTesting.newProjectDto());
+
+ BatchReport.Metadata metadata = BatchReport.Metadata.newBuilder()
+ .setSnapshotId(1L).build();
+ ComputationContext context = mock(ComputationContext.class);
+ when(context.getReportMetadata()).thenReturn(metadata);
sut.execute(context);
db.assertDbUnit(getClass(), "snapshots-result.xml", "snapshots");
}
-
- @Test(expected = IllegalStateException.class)
- public void throw_IllegalStateException_when_not_finding_snapshot() throws IOException {
- db.prepareDbUnit(getClass(), "empty.xml");
- ComputationContext context = new ComputationContext(AnalysisReportDto.newForTests(1L).setSnapshotId(1L),
- ComponentTesting.newProjectDto());
-
- sut.execute(context);
- }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryWsActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryWsActionMediumTest.java
index 51e8ca6c117..26fe86462b3 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryWsActionMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryWsActionMediumTest.java
@@ -20,126 +20,71 @@
package org.sonar.server.computation.ws;
-import org.apache.commons.io.IOUtils;
-import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
-import org.sonar.api.security.DefaultGroups;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.activity.Activity;
-import org.sonar.core.component.ComponentDto;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.permission.PermissionFacade;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.user.UserDto;
+import org.sonar.server.activity.Activity;
import org.sonar.server.activity.ActivityService;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.computation.AnalysisReportLog;
-import org.sonar.server.computation.AnalysisReportQueue;
-import org.sonar.server.db.DbClient;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.tester.ServerTester;
import org.sonar.server.user.MockUserSession;
import org.sonar.server.ws.WsTester;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
+import java.util.Date;
/**
* TODO replace this medium test by a small test
*/
public class HistoryWsActionMediumTest {
- private static final String DEFAULT_PROJECT_KEY = "DefaultProjectKey";
- private static final String DEFAULT_PROJECT_NAME = "DefaultProjectName";
- private static final String DEFAULT_REPORT_DATA = "default-project";
@ClassRule
public static ServerTester tester = new ServerTester();
- private DbClient dbClient;
- private DbSession session;
- private WsTester wsTester;
- private AnalysisReportQueue queue;
- private MockUserSession userSession;
- private ActivityService activityService;
+ HistoryWsAction sut;
+ ActivityService activityService;
@Before
- public void before() {
+ public void setUp() throws Exception {
tester.clearDbAndIndexes();
- dbClient = tester.get(DbClient.class);
- wsTester = tester.get(WsTester.class);
- session = dbClient.openSession(false);
- queue = tester.get(AnalysisReportQueue.class);
+ sut = tester.get(HistoryWsAction.class);
activityService = tester.get(ActivityService.class);
-
- UserDto connectedUser = new UserDto().setLogin("gandalf").setName("Gandalf");
- dbClient.userDao().insert(session, connectedUser);
-
- userSession = MockUserSession.set()
- .setLogin(connectedUser.getLogin())
- .setUserId(connectedUser.getId().intValue())
- .setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
- }
-
- @After
- public void after() {
- MyBatis.closeQuietly(session);
}
@Test
- public void add_and_try_to_retrieve_activities() throws Exception {
- insertPermissionsForProject(DEFAULT_PROJECT_KEY);
- queue.add(DEFAULT_PROJECT_KEY, 123L, IOUtils.toInputStream(DEFAULT_REPORT_DATA));
- queue.add(DEFAULT_PROJECT_KEY, 123L, IOUtils.toInputStream(DEFAULT_REPORT_DATA));
- queue.add(DEFAULT_PROJECT_KEY, 123L, IOUtils.toInputStream(DEFAULT_REPORT_DATA));
-
- List<AnalysisReportDto> reports = queue.all();
- ComponentDto project = ComponentTesting.newProjectDto()
- .setName(DEFAULT_PROJECT_NAME)
- .setKey(DEFAULT_PROJECT_KEY);
- for (AnalysisReportDto report : reports) {
- report.succeed();
- activityService.write(session, Activity.Type.ANALYSIS_REPORT, new AnalysisReportLog(report, project));
- }
-
- session.commit();
- userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
- WsTester.TestRequest request = wsTester.newGetRequest(ComputationWebService.API_ENDPOINT, HistoryWsAction.SEARCH_ACTION);
- WsTester.Result result = request.execute();
-
- assertThat(result).isNotNull();
- result.assertJson(getClass(), "list_history_reports.json", false);
- }
-
- private ComponentDto insertPermissionsForProject(String projectKey) {
- ComponentDto project = new ComponentDto().setKey(projectKey).setId(1L);
- dbClient.componentDao().insert(session, project);
-
- tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
- userSession.addProjectPermissions(UserRole.ADMIN, project.key());
- userSession.addProjectPermissions(UserRole.USER, project.key());
-
- session.commit();
-
- return project;
+ public void search() throws Exception {
+ Activity activity1 = new Activity();
+ activity1.setType(Activity.Type.ANALYSIS_REPORT);
+ activity1.setAction("LOG_ANALYSIS_REPORT");
+ activity1.setData("projectKey", "P1");
+ activity1.setData("projectName", "POne");
+ activity1.setData("projectUuid", "U1");
+ activity1.setData("status", AnalysisReportDto.Status.SUCCESS);
+ activity1.setData("submittedAt", new Date());
+ activityService.save(activity1);
+
+ Activity activity2 = new Activity();
+ activity2.setType(Activity.Type.ANALYSIS_REPORT);
+ activity2.setAction("LOG_ANALYSIS_REPORT");
+ activity2.setData("projectKey", "P2");
+ activity2.setData("projectName", "PTwo");
+ activity2.setData("projectUuid", "U2");
+ activity2.setData("status", AnalysisReportDto.Status.FAILED);
+ activity2.setData("submittedAt", new Date());
+ activityService.save(activity2);
+
+ MockUserSession.set().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+ WsTester.TestRequest request = tester.wsTester().newGetRequest("api/computation", "history");
+ request.execute().assertJson(getClass(), "list_history_reports.json", false);
}
@Test(expected = ForbiddenException.class)
- public void user_rights_is_not_enough_throw_ForbiddenException() throws Exception {
- insertPermissionsForProject(DEFAULT_PROJECT_KEY);
- queue.add(DEFAULT_PROJECT_KEY, 123L, IOUtils.toInputStream(DEFAULT_REPORT_DATA));
-
- AnalysisReportDto report = queue.all().get(0);
- report.succeed();
- queue.remove(report);
- userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
+ public void requires_admin_right() throws Exception {
+ MockUserSession.set();
- WsTester.TestRequest sut = wsTester.newGetRequest(ComputationWebService.API_ENDPOINT, HistoryWsAction.SEARCH_ACTION);
- sut.execute();
+ WsTester.TestRequest request = tester.wsTester().newGetRequest("api/computation", "history");
+ request.execute();
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/IsQueueEmptyWebServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/IsQueueEmptyWebServiceTest.java
index 346d871631f..2be42fa3111 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/IsQueueEmptyWebServiceTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/IsQueueEmptyWebServiceTest.java
@@ -26,7 +26,7 @@ import org.junit.Test;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.server.computation.AnalysisReportQueue;
+import org.sonar.server.computation.ReportQueue;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
@@ -39,12 +39,12 @@ import static org.mockito.Mockito.when;
public class IsQueueEmptyWebServiceTest {
IsQueueEmptyWebService.IsQueueEmptyWsAction sut;
- AnalysisReportQueue queue;
+ ReportQueue queue;
Response response;
@Before
public void before() throws Exception {
- queue = mock(AnalysisReportQueue.class);
+ queue = mock(ReportQueue.class);
sut = new IsQueueEmptyWebService.IsQueueEmptyWsAction(queue);
response = mock(Response.class);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueWsActionTest.java
index f3821946deb..846f8d095b3 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueWsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueWsActionTest.java
@@ -25,7 +25,7 @@ import org.junit.Before;
import org.junit.Test;
import org.sonar.api.utils.DateUtils;
import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.server.computation.AnalysisReportQueue;
+import org.sonar.server.computation.ReportQueue;
import org.sonar.server.ws.WsTester;
import java.util.List;
@@ -38,11 +38,11 @@ import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING;
public class QueueWsActionTest {
WsTester tester;
- private AnalysisReportQueue queue;
+ private ReportQueue queue;
@Before
public void setup() throws Exception {
- queue = mock(AnalysisReportQueue.class);
+ queue = mock(ReportQueue.class);
tester = new WsTester(new ComputationWebService(new QueueWsAction(queue)));
}
@@ -52,7 +52,7 @@ public class QueueWsActionTest {
.newForTests(1L)
.setProjectKey("project-key")
.setStatus(PENDING)
- .setData(null)
+ .setUuid("PROJECT_UUID")
.setCreatedAt(DateUtils.parseDateTime("2014-10-13T00:00:00+0200").getTime())
.setStartedAt(DateUtils.parseDateTime("2014-10-13T00:00:00+0200").getTime())
.setFinishedAt(DateUtils.parseDateTime("2014-10-13T00:00:00+0200").getTime());
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportWsActionTest.java
index 44e5bfe2936..e88d651d591 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportWsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportWsActionTest.java
@@ -23,8 +23,12 @@ package org.sonar.server.computation.ws;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.server.ws.WebService;
-import org.sonar.server.computation.AnalysisReportQueue;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.permission.GlobalPermissions;
import org.sonar.server.computation.ComputationThreadLauncher;
+import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.user.MockUserSession;
import org.sonar.server.ws.WsTester;
import java.io.InputStream;
@@ -34,16 +38,13 @@ import static org.mockito.Mockito.*;
public class SubmitReportWsActionTest {
- private static final String DEFAULT_PROJECT_KEY = "123456789-987654321";
- private SubmitReportWsAction sut;
-
- private WsTester wsTester;
- private ComputationThreadLauncher workerLauncher = mock(ComputationThreadLauncher.class);
- private AnalysisReportQueue queue;
+ ComputationThreadLauncher workerLauncher = mock(ComputationThreadLauncher.class);
+ ReportQueue queue = mock(ReportQueue.class);
+ WsTester wsTester;
+ SubmitReportWsAction sut;
@Before
public void before() {
- queue = mock(AnalysisReportQueue.class);
sut = new SubmitReportWsAction(queue, workerLauncher);
wsTester = new WsTester(new ComputationWebService(sut));
}
@@ -57,33 +58,36 @@ public class SubmitReportWsActionTest {
WebService.Action action = context.controller("api/computation").action("submit_report");
assertThat(action).isNotNull();
- assertThat(action.params()).hasSize(3);
+ assertThat(action.params()).hasSize(2);
}
@Test
public void add_element_to_queue_and_launch_analysis_task() throws Exception {
- when(queue.add(any(String.class), anyLong(), any(InputStream.class))).thenReturn("P1");
+ MockUserSession.set().setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
+ AnalysisReportDto dto = mock(AnalysisReportDto.class);
+ when(dto.getId()).thenReturn(42L);
+ when(queue.add(any(String.class), any(InputStream.class))).thenReturn(new ReportQueue.Item(dto, null));
WsTester.TestRequest request = wsTester
.newGetRequest(ComputationWebService.API_ENDPOINT, "submit_report")
.setParam(SubmitReportWsAction.PARAM_PROJECT_KEY, "P1")
- .setParam(SubmitReportWsAction.PARAM_SNAPSHOT, "456")
.setParam(SubmitReportWsAction.PARAM_REPORT_DATA, null);
- request.execute();
+ WsTester.Result response = request.execute();
- verify(queue).add(eq("P1"), eq(456L), any(InputStream.class));
+ verify(queue).add(eq("P1"), any(InputStream.class));
verify(workerLauncher).startAnalysisTaskNow();
+ assertThat(response.outputAsString()).isEqualTo("{\"key\":\"42\"}");
}
- @Test
- public void return_report_key() throws Exception {
- when(queue.add(any(String.class), anyLong(), any(InputStream.class))).thenReturn("P1");
+ @Test(expected = ForbiddenException.class)
+ public void requires_scan_permission() throws Exception {
+ MockUserSession.set().setGlobalPermissions(GlobalPermissions.DASHBOARD_SHARING);
WsTester.TestRequest request = wsTester
- .newPostRequest(ComputationWebService.API_ENDPOINT, "submit_report")
+ .newGetRequest(ComputationWebService.API_ENDPOINT, "submit_report")
.setParam(SubmitReportWsAction.PARAM_PROJECT_KEY, "P1")
- .setParam(SubmitReportWsAction.PARAM_SNAPSHOT, "456")
.setParam(SubmitReportWsAction.PARAM_REPORT_DATA, null);
- request.execute().assertJson(getClass(), "submit_report.json", false);
+ request.execute();
+
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest.java b/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest.java
index 699581a22b6..ceb22da3b6a 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest.java
@@ -23,31 +23,23 @@ import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
-import org.sonar.core.activity.db.ActivityDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.DbTester;
import org.sonar.server.activity.db.ActivityDao;
import org.sonar.server.db.DbClient;
-import java.util.List;
-
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-@RunWith(MockitoJUnitRunner.class)
public class ChangeLogMigrationTest {
@ClassRule
public static DbTester db = new DbTester().schema(ChangeLogMigrationTest.class, "schema.sql");
- @Mock
- System2 system2;
-
+ System2 system2 = mock(System2.class);
DbClient dbClient;
ActivityDao dao;
ChangeLogMigration migration;
@@ -56,7 +48,7 @@ public class ChangeLogMigrationTest {
@Before
public void setUp() throws Exception {
when(system2.now()).thenReturn(DateUtils.parseDate("2014-03-13").getTime());
- dao = new ActivityDao(system2);
+ dao = new ActivityDao(db.myBatis(), system2);
dbClient = new DbClient(db.database(), db.myBatis(), dao);
migration = new ChangeLogMigration(dao, dbClient);
session = dbClient.openSession(false);
@@ -71,10 +63,10 @@ public class ChangeLogMigrationTest {
public void migrate() throws Exception {
db.prepareDbUnit(getClass(), "active_rules_changes.xml");
migration.execute();
- assertThat(dao.findAll(session)).hasSize(5);
+ assertThat(db.countRowsOfTable("activities")).isEqualTo(5);
- List<ActivityDto> changes = dao.findAll(session);
- assertThat(changes.get(1).getData()).contains("param_PARAM1=TODO");
+ int count = db.countSql("select count(*) from activities where data_field like '%param_PARAM1=TODO%'");
+ assertThat(count).isGreaterThan(0);
}
@Test
@@ -82,6 +74,6 @@ public class ChangeLogMigrationTest {
db.prepareDbUnit(getClass(), "migrate_when_no_changelog.xml");
migration.execute();
- assertThat(dao.findAll(session)).isEmpty();
+ assertThat(db.countRowsOfTable("activities")).isEqualTo(0);
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/es/BulkIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/es/BulkIndexerTest.java
index bd4be80943d..7f4e4e6a16f 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/es/BulkIndexerTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/es/BulkIndexerTest.java
@@ -48,8 +48,7 @@ public class BulkIndexerTest {
@Test
public void index_documents() throws Exception {
- BulkIndexer indexer = new BulkIndexer(esTester.client(), FakeIndexDefinition.INDEX)
- .setRefresh(true);
+ BulkIndexer indexer = new BulkIndexer(esTester.client(), FakeIndexDefinition.INDEX);
indexer.start();
indexer.add(newIndexRequest(42));
indexer.add(newIndexRequest(78));
diff --git a/server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java b/server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java
index 47a1954dac5..5c49de4aef1 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java
@@ -103,7 +103,7 @@ public class EsTester extends ExternalResource {
ComponentContainer container = new ComponentContainer();
container.addSingletons(definitions);
container.addSingleton(client);
- container.addSingleton(IndexRegistry.class);
+ container.addSingleton(IndexDefinitions.class);
container.addSingleton(IndexCreator.class);
container.startComponents();
}
@@ -206,11 +206,14 @@ public class EsTester extends ExternalResource {
return result;
}
- public <T> List<T> getDocumentFields(String indexName, String typeName, final String fieldName) {
+ /**
+ * Get a list of a specific field from all indexed documents.
+ */
+ public <T> List<T> getDocumentFieldValues(String indexName, String typeName, final String fieldNameToReturn) {
return newArrayList(Iterables.transform(getDocuments(indexName, typeName), new Function<SearchHit, T>() {
@Override
public T apply(SearchHit input) {
- return (T) input.sourceAsMap().get(fieldName);
+ return (T) input.sourceAsMap().get(fieldNameToReturn);
}
}));
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/es/IndexCreatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/es/IndexCreatorTest.java
index 06ba9d18d4a..ac55e4e4c53 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/es/IndexCreatorTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/es/IndexCreatorTest.java
@@ -41,7 +41,7 @@ public class IndexCreatorTest {
public void create_index() throws Exception {
assertThat(mappings()).isEmpty();
- IndexRegistry registry = new IndexRegistry(new IndexDefinition[] {new FakeIndexDefinition()});
+ IndexDefinitions registry = new IndexDefinitions(new IndexDefinition[] {new FakeIndexDefinition()});
registry.start();
IndexCreator creator = new IndexCreator(es.client(), registry);
creator.start();
@@ -66,7 +66,7 @@ public class IndexCreatorTest {
assertThat(mappings()).isEmpty();
// v1
- IndexRegistry registry = new IndexRegistry(new IndexDefinition[] {new FakeIndexDefinition()});
+ IndexDefinitions registry = new IndexDefinitions(new IndexDefinition[] {new FakeIndexDefinition()});
registry.start();
IndexCreator creator = new IndexCreator(es.client(), registry);
creator.start();
@@ -75,7 +75,7 @@ public class IndexCreatorTest {
assertThat(hashV1).isNotEmpty();
// v2
- registry = new IndexRegistry(new IndexDefinition[] {new FakeIndexDefinitionV2()});
+ registry = new IndexDefinitions(new IndexDefinition[] {new FakeIndexDefinitionV2()});
registry.start();
creator = new IndexCreator(es.client(), registry);
creator.start();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/es/IndexDefinitionHashTest.java b/server/sonar-server/src/test/java/org/sonar/server/es/IndexDefinitionHashTest.java
index 958247d87a5..20cff8f8548 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/es/IndexDefinitionHashTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/es/IndexDefinitionHashTest.java
@@ -29,7 +29,7 @@ public class IndexDefinitionHashTest {
@Test
public void of() throws Exception {
- IndexRegistry.Index indexV1 = new IndexRegistry.Index(createIndex());
+ IndexDefinitions.Index indexV1 = new IndexDefinitions.Index(createIndex());
String hashV1 = new IndexDefinitionHash().of(indexV1);
assertThat(hashV1).isNotEmpty();
// always the same
@@ -37,7 +37,7 @@ public class IndexDefinitionHashTest {
NewIndex newIndexV2 = createIndex();
newIndexV2.getTypes().get("fake").createIntegerField("max");
- String hashV2 = new IndexDefinitionHash().of(new IndexRegistry.Index(newIndexV2));
+ String hashV2 = new IndexDefinitionHash().of(new IndexDefinitions.Index(newIndexV2));
assertThat(hashV2).isNotEmpty().isNotEqualTo(hashV1);
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java
index 3023ae60034..2caaa0bd6b5 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java
@@ -19,7 +19,11 @@
*/
package org.sonar.server.issue;
-import com.google.common.collect.*;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Multiset;
+import com.google.common.collect.Sets;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
@@ -56,7 +60,6 @@ import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.PermissionChange;
import org.sonar.server.rule.RuleTesting;
import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.search.BaseNormalizer;
import org.sonar.server.source.index.SourceLineDoc;
import org.sonar.server.source.index.SourceLineIndexer;
import org.sonar.server.source.index.SourceLineResultSetIterator;
@@ -74,10 +77,7 @@ import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
import static org.junit.Assert.fail;
-import static org.sonar.server.source.index.SourceLineIndexDefinition.FIELD_FILE_UUID;
-import static org.sonar.server.source.index.SourceLineIndexDefinition.FIELD_LINE;
-import static org.sonar.server.source.index.SourceLineIndexDefinition.FIELD_PROJECT_UUID;
-import static org.sonar.server.source.index.SourceLineIndexDefinition.FIELD_SCM_AUTHOR;
+import static org.sonar.server.source.index.SourceLineIndexDefinition.*;
public class IssueServiceMediumTest {
@@ -652,7 +652,7 @@ public class IssueServiceMediumTest {
.put(FIELD_PROJECT_UUID, file.projectUuid())
.put(FIELD_FILE_UUID, file.uuid())
.put(FIELD_LINE, line)
- .put(BaseNormalizer.UPDATED_AT_FIELD, new Date())
+ .put(FIELD_UPDATED_AT, new Date())
.put(FIELD_SCM_AUTHOR, scmAuthor)
.build());
SourceLineResultSetIterator.SourceFile sourceFile = new SourceLineResultSetIterator.SourceFile(file.uuid(), System.currentTimeMillis());
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java
index cc87af2c9a8..03c7bbb8fc3 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java
@@ -58,6 +58,15 @@ public class IssueIndexerTest {
}
@Test
+ public void index_nothing_if_disabled() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "index.xml");
+
+ createIndexer().setEnabled(false).index();
+
+ assertThat(esTester.countDocuments("issues", "issue")).isEqualTo(0);
+ }
+
+ @Test
public void index() throws Exception {
dbTester.prepareDbUnit(getClass(), "index.xml");
@@ -75,6 +84,12 @@ public class IssueIndexerTest {
assertThat(doc.severity()).isEqualTo("BLOCKER");
assertThat(doc.ruleKey()).isEqualTo(RuleKey.of("squid", "AvoidCycles"));
+ // functional date
+ assertThat(doc.updateDate().getTime()).isEqualTo(1368828000000L);
+
+ // technical date
+ assertThat(doc.getTechnicalUpdateDate().getTime()).isEqualTo(1550000000000L);
+
// delete project
indexer.deleteProject("THE_PROJECT", true);
@@ -82,6 +97,8 @@ public class IssueIndexerTest {
}
private IssueIndexer createIndexer() {
- return new IssueIndexer(new DbClient(dbTester.database(), dbTester.myBatis()), esTester.client());
+ IssueIndexer indexer = new IssueIndexer(new DbClient(dbTester.database(), dbTester.myBatis()), esTester.client());
+ indexer.setEnabled(true);
+ return indexer;
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java
index c436301c8cc..b8c03d252ac 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java
@@ -21,36 +21,59 @@ package org.sonar.server.issue.notification;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import org.sonar.api.config.EmailSettings;
import org.sonar.api.notifications.Notification;
import org.sonar.core.i18n.DefaultI18n;
import org.sonar.plugins.emailnotifications.api.EmailMessage;
+import org.sonar.server.user.index.UserDoc;
+import org.sonar.server.user.index.UserIndex;
import java.util.Locale;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import static org.sonar.server.issue.notification.NewIssuesStatistics.METRIC.*;
-@RunWith(MockitoJUnitRunner.class)
public class NewIssuesEmailTemplateTest {
- NewIssuesEmailTemplate template;
+ private static final String EMAIL_HEADER = "Project: Struts\n\n";
+ private static final String EMAIL_TOTAL_ISSUES = "32 new issues - Total debt: 1d3h\n\n";
+ private static final String EMAIL_ISSUES = " Severity - Blocker: 0 Critical: 5 Major: 10 Minor: 3 Info: 1\n";
+ private static final String EMAIL_ASSIGNEES = " Assignee - robin.williams: 5 al.pacino: 7 \n";
+ private static final String EMAIL_TAGS = " Tags - oscar: 3 cesar: 10 \n";
+ private static final String EMAIL_COMPONENTS = " Components:\n" +
+ " /path/to/file : 3\n" +
+ " /path/to/directory : 7\n";
+ private static final String EMAIL_FOOTER = "\nSee it in SonarQube: http://nemo.sonarsource.org/issues/search#projectUuids=ABCDE|createdAt=2010-05-1";
- @Mock
+ NewIssuesEmailTemplate template;
DefaultI18n i18n;
+ UserIndex userIndex;
@Before
public void setUp() {
EmailSettings settings = mock(EmailSettings.class);
when(settings.getServerBaseURL()).thenReturn("http://nemo.sonarsource.org");
- template = new NewIssuesEmailTemplate(settings, i18n);
+ i18n = mock(DefaultI18n.class);
+ userIndex = mock(UserIndex.class);
+ // returns the login passed in parameter
+ when(userIndex.getNullableByLogin(anyString())).thenAnswer(new Answer<UserDoc>() {
+ @Override
+ public UserDoc answer(InvocationOnMock invocationOnMock) throws Throwable {
+ return new UserDoc().setName((String) invocationOnMock.getArguments()[0]);
+ }
+ });
+ when(i18n.message(any(Locale.class), eq("severity.BLOCKER"), anyString())).thenReturn("Blocker");
+ when(i18n.message(any(Locale.class), eq("severity.CRITICAL"), anyString())).thenReturn("Critical");
+ when(i18n.message(any(Locale.class), eq("severity.MAJOR"), anyString())).thenReturn("Major");
+ when(i18n.message(any(Locale.class), eq("severity.MINOR"), anyString())).thenReturn("Minor");
+ when(i18n.message(any(Locale.class), eq("severity.INFO"), anyString())).thenReturn("Info");
+
+ template = new NewIssuesEmailTemplate(settings, i18n, userIndex);
}
@Test
@@ -66,24 +89,44 @@ public class NewIssuesEmailTemplateTest {
* From: Sonar
*
* Project: Foo
- * 32 new issues
+ * 32 new issues - Total debt: 1d3h
+ *
+ * Severity - Blocker: 0 Critical: 5 Major: 10 Minor: 3 Info: 1
+ * Assignee - robin.williams: 5 al.pacino: 7
+ * Tags - oscar: 3 cesar:10
+ * Components:
+ * /path/to/file : 3
+ * /path/to/directoy : 7
*
* See it in SonarQube: http://nemo.sonarsource.org/drilldown/measures/org.sonar.foo:foo?metric=new_violations
* </pre>
*/
@Test
- public void shouldFormatCommentAdded() {
- Notification notification = new NewIssuesNotification()
- .setFieldValue("count", "32")
- .setFieldValue("count-INFO", "1")
- .setFieldValue("count-MINOR", "3")
- .setFieldValue("count-MAJOR", "10")
- .setFieldValue("count-CRITICAL", "5")
- .setFieldValue("count-BLOCKER", "0")
- .setFieldValue("projectName", "Struts")
- .setFieldValue("projectKey", "org.apache:struts")
- .setFieldValue("projectUuid", "ABCDE")
- .setFieldValue("projectDate", "2010-05-18T14:50:45+0000");
+ public void format_email_with_all_fields_filled() {
+ Notification notification = newNotification();
+ addAssignees(notification);
+ addTags(notification);
+ addComponents(notification);
+
+ EmailMessage message = template.format(notification);
+
+ assertThat(message.getMessageId()).isEqualTo("new-issues/org.apache:struts");
+ assertThat(message.getSubject()).isEqualTo("Struts: 32 new issues");
+
+ // TODO datetime to be completed when test is isolated from JVM timezone
+ assertThat(message.getMessage()).startsWith("" +
+ EMAIL_HEADER +
+ EMAIL_TOTAL_ISSUES +
+ EMAIL_ISSUES +
+ EMAIL_ASSIGNEES +
+ EMAIL_TAGS +
+ EMAIL_COMPONENTS +
+ EMAIL_FOOTER);
+ }
+
+ @Test
+ public void format_email_with_no_assignees_tags_nor_components() throws Exception {
+ Notification notification = newNotification();
when(i18n.message(any(Locale.class), eq("severity.BLOCKER"), anyString())).thenReturn("Blocker");
when(i18n.message(any(Locale.class), eq("severity.CRITICAL"), anyString())).thenReturn("Critical");
@@ -92,27 +135,64 @@ public class NewIssuesEmailTemplateTest {
when(i18n.message(any(Locale.class), eq("severity.INFO"), anyString())).thenReturn("Info");
EmailMessage message = template.format(notification);
+
assertThat(message.getMessageId()).isEqualTo("new-issues/org.apache:struts");
- assertThat(message.getSubject()).isEqualTo("Struts: new issues");
+ assertThat(message.getSubject()).isEqualTo("Struts: 32 new issues");
// TODO datetime to be completed when test is isolated from JVM timezone
assertThat(message.getMessage()).startsWith("" +
- "Project: Struts\n" +
- "\n" +
- "32 new issues\n" +
- "\n" +
- " Blocker: 0 Critical: 5 Major: 10 Minor: 3 Info: 1\n" +
- "\n" +
- "See it in SonarQube: http://nemo.sonarsource.org/issues/search#projectUuids=ABCDE|createdAt=2010-05-1");
+ EMAIL_HEADER +
+ EMAIL_TOTAL_ISSUES +
+ EMAIL_ISSUES +
+ EMAIL_FOOTER);
}
@Test
- public void shouldNotAddFooterIfMissingProperties() {
+ public void do_not_add_footer_when_properties_missing() {
Notification notification = new NewIssuesNotification()
- .setFieldValue("count", "32")
+ .setFieldValue(SEVERITY + ".count", "32")
.setFieldValue("projectName", "Struts");
EmailMessage message = template.format(notification);
assertThat(message.getMessage()).doesNotContain("See it");
}
+
+ private Notification newNotification() {
+ return new NewIssuesNotification()
+ .setFieldValue("projectName", "Struts")
+ .setFieldValue("projectKey", "org.apache:struts")
+ .setFieldValue("projectUuid", "ABCDE")
+ .setFieldValue("projectDate", "2010-05-18T14:50:45+0000")
+ .setFieldValue(DEBT + ".count", "1d3h")
+ .setFieldValue(SEVERITY + ".count", "32")
+ .setFieldValue(SEVERITY + ".INFO.count", "1")
+ .setFieldValue(SEVERITY + ".MINOR.count", "3")
+ .setFieldValue(SEVERITY + ".MAJOR.count", "10")
+ .setFieldValue(SEVERITY + ".CRITICAL.count", "5")
+ .setFieldValue(SEVERITY + ".BLOCKER.count", "0");
+ }
+
+ private void addAssignees(Notification notification) {
+ notification
+ .setFieldValue(LOGIN + ".1.label", "robin.williams")
+ .setFieldValue(LOGIN + ".1.count", "5")
+ .setFieldValue(LOGIN + ".2.label", "al.pacino")
+ .setFieldValue(LOGIN + ".2.count", "7");
+ }
+
+ private void addTags(Notification notification) {
+ notification
+ .setFieldValue(TAGS + ".1.label", "oscar")
+ .setFieldValue(TAGS + ".1.count", "3")
+ .setFieldValue(TAGS + ".2.label", "cesar")
+ .setFieldValue(TAGS + ".2.count", "10");
+ }
+
+ private void addComponents(Notification notification) {
+ notification
+ .setFieldValue(COMPONENT + ".1.label", "/path/to/file")
+ .setFieldValue(COMPONENT + ".1.count", "3")
+ .setFieldValue(COMPONENT + ".2.label", "/path/to/directory")
+ .setFieldValue(COMPONENT + ".2.count", "7");
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationTest.java
index 4c208547406..73c52db97c8 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationTest.java
@@ -17,27 +17,105 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
package org.sonar.server.issue.notification;
+import com.google.common.collect.Lists;
import org.junit.Test;
import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.Duration;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.server.component.ComponentTesting;
+
+import java.util.Date;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.issue.notification.NewIssuesStatistics.METRIC.*;
public class NewIssuesNotificationTest {
+ NewIssuesNotification sut = new NewIssuesNotification();
+ NewIssuesStatistics stats = new NewIssuesStatistics();
+
+ @Test
+ public void set_project() throws Exception {
+ ComponentDto component = ComponentTesting.newProjectDto()
+ .setLongName("project-long-name")
+ .setUuid("project-uuid")
+ .setKey("project-key");
+
+ sut.setProject(component);
+
+ assertThat(sut.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_NAME)).isEqualTo("project-long-name");
+ assertThat(sut.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_UUID)).isEqualTo("project-uuid");
+ assertThat(sut.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_KEY)).isEqualTo("project-key");
+ }
+
+ @Test
+ public void set_date() throws Exception {
+ Date date = new Date();
+
+ sut.setAnalysisDate(date);
+
+ assertThat(sut.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_DATE)).isEqualTo(DateUtils.formatDateTime(date));
+ }
+
@Test
- public void stats() {
- NewIssuesNotification.Stats sut = new NewIssuesNotification.Stats();
- assertThat(sut.size()).isEqualTo(0);
-
- sut.add(new DefaultIssue().setSeverity("MINOR"));
- sut.add(new DefaultIssue().setSeverity("BLOCKER"));
- sut.add(new DefaultIssue().setSeverity("MINOR"));
-
- assertThat(sut.size()).isEqualTo(3);
- assertThat(sut.countIssuesWithSeverity("INFO")).isEqualTo(0);
- assertThat(sut.countIssuesWithSeverity("MINOR")).isEqualTo(2);
- assertThat(sut.countIssuesWithSeverity("BLOCKER")).isEqualTo(1);
+ public void set_statistics() throws Exception {
+ ComponentDto component = ComponentTesting.newProjectDto()
+ .setLongName("project-long-name");
+ addIssueNTimes(newIssue1(), 5);
+ addIssueNTimes(newIssue2(), 3);
+
+ sut.setStatistics(component, stats);
+
+ assertThat(sut.getFieldValue(SEVERITY + ".INFO.count")).isEqualTo("5");
+ assertThat(sut.getFieldValue(SEVERITY + ".BLOCKER.count")).isEqualTo("3");
+ assertThat(sut.getFieldValue(LOGIN + ".1.label")).isEqualTo("maynard");
+ assertThat(sut.getFieldValue(LOGIN + ".1.count")).isEqualTo("5");
+ assertThat(sut.getFieldValue(LOGIN + ".2.label")).isEqualTo("keenan");
+ assertThat(sut.getFieldValue(LOGIN + ".2.count")).isEqualTo("3");
+ assertThat(sut.getFieldValue(TAGS + ".1.label")).isEqualTo("owasp");
+ assertThat(sut.getFieldValue(TAGS + ".1.count")).isEqualTo("8");
+ assertThat(sut.getFieldValue(TAGS + ".2.label")).isEqualTo("bug");
+ assertThat(sut.getFieldValue(TAGS + ".2.count")).isEqualTo("5");
+ assertThat(sut.getFieldValue(COMPONENT + ".1.label")).isEqualTo("file-uuid");
+ assertThat(sut.getFieldValue(COMPONENT + ".1.count")).isEqualTo("5");
+ assertThat(sut.getFieldValue(COMPONENT + ".2.label")).isEqualTo("directory-uuid");
+ assertThat(sut.getFieldValue(COMPONENT + ".2.count")).isEqualTo("3");
+ assertThat(sut.getDefaultMessage()).startsWith("8 new issues on project-long-name");
+ }
+
+ @Test
+ public void set_debt() throws Exception {
+ sut.setDebt("55min");
+
+ assertThat(sut.getFieldValue(DEBT + ".count")).isEqualTo("55min");
+ }
+
+ private void addIssueNTimes(DefaultIssue issue, int times) {
+ for (int i = 0; i < times; i++) {
+ stats.add(issue);
+ }
+ }
+
+ private DefaultIssue newIssue1() {
+ return new DefaultIssue()
+ .setAssignee("maynard")
+ .setComponentUuid("file-uuid")
+ .setSeverity(Severity.INFO)
+ .setTags(Lists.newArrayList("bug", "owasp"))
+ .setDebt(Duration.create(5L));
+ }
+
+ private DefaultIssue newIssue2() {
+ return new DefaultIssue()
+ .setAssignee("keenan")
+ .setComponentUuid("directory-uuid")
+ .setSeverity(Severity.BLOCKER)
+ .setTags(Lists.newArrayList("owasp"))
+ .setDebt(Duration.create(10L));
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesStatisticsTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesStatisticsTest.java
new file mode 100644
index 00000000000..2bc1c2c3d66
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesStatisticsTest.java
@@ -0,0 +1,70 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.issue.notification;
+
+import com.google.common.collect.Lists;
+import org.junit.Test;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.utils.Duration;
+import org.sonar.server.issue.notification.NewIssuesStatistics.METRIC;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class NewIssuesStatisticsTest {
+
+ NewIssuesStatistics sut = new NewIssuesStatistics();
+
+ @Test
+ public void add_issues_with_correct_global_statistics() throws Exception {
+ DefaultIssue issue = defaultIssue();
+
+ sut.add(issue);
+ sut.add(issue.setAssignee("james"));
+ sut.add(issue.setAssignee("keenan"));
+
+ assertThat(countDistribution(METRIC.LOGIN, "maynard")).isEqualTo(1);
+ assertThat(countDistribution(METRIC.LOGIN, "james")).isEqualTo(1);
+ assertThat(countDistribution(METRIC.LOGIN, "keenan")).isEqualTo(1);
+ assertThat(countDistribution(METRIC.LOGIN, "wrong.login")).isEqualTo(0);
+ assertThat(countDistribution(METRIC.COMPONENT, "file-uuid")).isEqualTo(3);
+ assertThat(countDistribution(METRIC.COMPONENT, "wrong-uuid")).isEqualTo(0);
+ assertThat(countDistribution(METRIC.SEVERITY, Severity.INFO)).isEqualTo(3);
+ assertThat(countDistribution(METRIC.SEVERITY, Severity.CRITICAL)).isEqualTo(0);
+ assertThat(countDistribution(METRIC.TAGS, "owasp")).isEqualTo(3);
+ assertThat(countDistribution(METRIC.TAGS, "wrong-tag")).isEqualTo(0);
+ assertThat(sut.debt().toMinutes()).isEqualTo(15L);
+ }
+
+ private int countDistribution(METRIC metric, String label) {
+ return sut.countForMetric(metric, label);
+ }
+
+ private DefaultIssue defaultIssue() {
+ return new DefaultIssue()
+ .setAssignee("maynard")
+ .setComponentUuid("file-uuid")
+ .setNew(true)
+ .setSeverity(Severity.INFO)
+ .setTags(Lists.newArrayList("bug", "owasp"))
+ .setDebt(Duration.create(5L));
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/properties/ProjectSettingsFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/properties/ProjectSettingsFactoryTest.java
index d894cf48f65..1ca4a8cc6d6 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/properties/ProjectSettingsFactoryTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/properties/ProjectSettingsFactoryTest.java
@@ -24,7 +24,6 @@ import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.config.Settings;
-import org.sonar.core.persistence.DbSession;
import org.sonar.core.properties.PropertiesDao;
import org.sonar.core.properties.PropertyDto;
@@ -50,7 +49,7 @@ public class ProjectSettingsFactoryTest {
@Test
public void newProjectSettings_returns_a_ProjectSettings() throws Exception {
- Settings projectSettings = sut.newProjectSettings(mock(DbSession.class), 1L);
+ Settings projectSettings = sut.newProjectSettings(1L);
assertThat(projectSettings).isInstanceOf(ProjectSettings.class);
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ActiveRuleChangeMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ActiveRuleChangeMediumTest.java
deleted file mode 100644
index c57d29fb178..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ActiveRuleChangeMediumTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-import com.google.common.collect.Iterables;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.core.activity.Activity;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.qualityprofile.db.ActiveRuleKey;
-import org.sonar.server.activity.ActivityService;
-import org.sonar.server.activity.index.ActivityIndex;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.tester.ServerTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ActiveRuleChangeMediumTest {
-
- @ClassRule
- public static ServerTester tester = new ServerTester();
-
- ActivityService service = tester.get(ActivityService.class);
- ActivityIndex index = tester.get(ActivityIndex.class);
- DbSession dbSession;
-
- @Before
- public void before() {
- tester.clearDbAndIndexes();
- dbSession = tester.get(DbClient.class).openSession(false);
- }
-
- @After
- public void after() {
- dbSession.close();
- }
-
- @Test
- public void insert_find_active_rule_change() {
- ActiveRuleKey key = ActiveRuleKey.of("XOO_P1", RuleKey.of("xoo", "X1"));
- ActiveRuleChange change = ActiveRuleChange
- .createFor(ActiveRuleChange.Type.ACTIVATED, key)
- .setInheritance(ActiveRule.Inheritance.INHERITED)
- .setSeverity("BLOCKER")
- .setParameter("param1", "value1");
-
- service.write(dbSession, Activity.Type.QPROFILE, change);
- dbSession.commit();
-
- // 0. AssertBase case
- assertThat(index.findAll().getHits()).hasSize(1);
-
- Activity activity = Iterables.getFirst(index.findAll().getHits(), null);
- assertThat(activity).isNotNull();
- assertThat(activity.details().get("key")).isEqualTo(key.toString());
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java
index 2015af9ab51..034bb052ef9 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java
@@ -20,7 +20,6 @@
package org.sonar.server.qualityprofile;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import org.junit.After;
@@ -36,19 +35,19 @@ import org.sonar.api.rule.Severity;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.utils.ValidationMessages;
-import org.sonar.core.activity.Activity;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.qualityprofile.db.ActiveRuleKey;
import org.sonar.core.qualityprofile.db.QualityProfileDto;
import org.sonar.core.rule.RuleDto;
import org.sonar.core.user.UserDto;
+import org.sonar.server.activity.Activity;
import org.sonar.server.activity.ActivityService;
import org.sonar.server.db.DbClient;
+import org.sonar.server.es.SearchOptions;
import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
import org.sonar.server.rule.RuleTesting;
import org.sonar.server.search.FacetValue;
-import org.sonar.server.search.QueryContext;
import org.sonar.server.search.Result;
import org.sonar.server.tester.ServerTester;
import org.sonar.server.user.MockUserSession;
@@ -187,24 +186,23 @@ public class QProfileServiceMediumTest {
// We need an actual rule in DB to test RuleName in Activity
RuleDto rule = db.ruleDao().getByKey(dbSession, RuleTesting.XOO_X1);
- tester.get(ActivityService.class).write(dbSession, Activity.Type.QPROFILE,
- ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1))
- .setSeverity(Severity.MAJOR)
- .setParameter("max", "10")
- );
dbSession.commit();
- Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new QueryContext());
+ tester.get(ActivityService.class).save(ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1))
+ .setSeverity(Severity.MAJOR)
+ .setParameter("max", "10").toActivity());
+
+ Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new SearchOptions());
assertThat(activities.getHits()).hasSize(1);
QProfileActivity activity = activities.getHits().get(0);
- assertThat(activity.type()).isEqualTo(Activity.Type.QPROFILE);
- assertThat(activity.action()).isEqualTo(ActiveRuleChange.Type.ACTIVATED.name());
+ assertThat(activity.getType()).isEqualTo(Activity.Type.QPROFILE.name());
+ assertThat(activity.getAction()).isEqualTo(ActiveRuleChange.Type.ACTIVATED.name());
assertThat(activity.ruleKey()).isEqualTo(RuleTesting.XOO_X1);
assertThat(activity.profileKey()).isEqualTo(XOO_P1_KEY);
assertThat(activity.severity()).isEqualTo(Severity.MAJOR);
assertThat(activity.ruleName()).isEqualTo(rule.getName());
- assertThat(activity.login()).isEqualTo("david");
+ assertThat(activity.getLogin()).isEqualTo("david");
assertThat(activity.authorName()).isEqualTo("David");
assertThat(activity.parameters()).hasSize(1);
@@ -217,13 +215,11 @@ public class QProfileServiceMediumTest {
RuleKey ruleKey = RuleKey.of("xoo", "deleted_rule");
- tester.get(ActivityService.class).write(dbSession, Activity.Type.QPROFILE,
- ActiveRuleChange.createFor(ActiveRuleChange.Type.UPDATED, ActiveRuleKey.of(XOO_P1_KEY, ruleKey))
- .setParameter("max", "10")
+ tester.get(ActivityService.class).save(ActiveRuleChange.createFor(ActiveRuleChange.Type.UPDATED, ActiveRuleKey.of(XOO_P1_KEY, ruleKey))
+ .setParameter("max", "10").toActivity()
);
- dbSession.commit();
- Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new QueryContext());
+ Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new SearchOptions());
assertThat(activities.getHits()).hasSize(1);
QProfileActivity activity = activities.getHits().get(0);
@@ -238,19 +234,20 @@ public class QProfileServiceMediumTest {
// We need an actual rule in DB to test RuleName in Activity
db.ruleDao().getByKey(dbSession, RuleTesting.XOO_X1);
+ dbSession.commit();
- tester.get(ActivityService.class).write(dbSession, Activity.Type.QPROFILE,
+ tester.get(ActivityService.class).save(
ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1))
.setSeverity(Severity.MAJOR)
.setParameter("max", "10")
+ .toActivity()
);
- dbSession.commit();
- Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new QueryContext());
+ Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new SearchOptions());
assertThat(activities.getHits()).hasSize(1);
QProfileActivity activity = activities.getHits().get(0);
- assertThat(activity.login()).isEqualTo("david");
+ assertThat(activity.getLogin()).isEqualTo("david");
assertThat(activity.authorName()).isNull();
}
@@ -260,14 +257,14 @@ public class QProfileServiceMediumTest {
RuleKey ruleKey = RuleKey.of("xoo", "deleted_rule");
- tester.get(ActivityService.class).write(dbSession, Activity.Type.QPROFILE,
- ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, ruleKey))
- .setSeverity(Severity.MAJOR)
- .setParameter("max", "10")
+ tester.get(ActivityService.class).save(ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, ruleKey))
+ .setSeverity(Severity.MAJOR)
+ .setParameter("max", "10")
+ .toActivity()
);
dbSession.commit();
- Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new QueryContext());
+ Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new SearchOptions());
assertThat(activities.getHits()).hasSize(1);
QProfileActivity activity = activities.getHits().get(0);
@@ -278,48 +275,36 @@ public class QProfileServiceMediumTest {
@Test
public void search_activity_by_qprofile() throws InterruptedException {
- tester.get(ActivityService.class).write(dbSession, Activity.Type.QPROFILE,
- ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1)));
- tester.get(ActivityService.class).write(dbSession, Activity.Type.QPROFILE,
- ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P2_KEY, RuleTesting.XOO_X1)));
- dbSession.commit();
+ tester.get(ActivityService.class).save(
+ ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1)).toActivity());
+ tester.get(ActivityService.class).save(
+ ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P2_KEY, RuleTesting.XOO_X1)).toActivity());
// 0. Base case verify 2 activities in index
- assertThat(service.searchActivities(new QProfileActivityQuery(), new QueryContext()).getHits())
+ assertThat(service.searchActivities(new QProfileActivityQuery(), new SearchOptions()).getHits())
.hasSize(2);
// 1. filter by QProfile
List<QProfileActivity> result = service.searchActivities(new QProfileActivityQuery()
- .setQprofileKeys(ImmutableSet.of(XOO_P1_KEY)), new QueryContext()).getHits();
+ .setQprofileKey(XOO_P1_KEY), new SearchOptions()).getHits();
assertThat(result).hasSize(1);
-
- // 1. filter by QProfiles
- assertThat(service.searchActivities(new QProfileActivityQuery()
- .setQprofileKeys(ImmutableSet.of(XOO_P1_KEY, XOO_P2_KEY))
- , new QueryContext()).getHits()).hasSize(2);
}
@Test
public void search_activity_by_qprofile_having_dashes_in_keys() throws InterruptedException {
- tester.get(ActivityService.class).write(dbSession, Activity.Type.QPROFILE,
- ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of("java-default", RuleTesting.XOO_X1)));
- tester.get(ActivityService.class).write(dbSession, Activity.Type.QPROFILE,
- ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of("java-toto", RuleTesting.XOO_X1)));
- dbSession.commit();
+ tester.get(ActivityService.class).save(
+ ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of("java-default", RuleTesting.XOO_X1)).toActivity());
+ tester.get(ActivityService.class).save(
+ ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of("java-toto", RuleTesting.XOO_X1)).toActivity());
// 0. Base case verify 2 activities in index
- assertThat(service.searchActivities(new QProfileActivityQuery(), new QueryContext()).getHits())
+ assertThat(service.searchActivities(new QProfileActivityQuery(), new SearchOptions()).getHits())
.hasSize(2);
// 1. filter by QProfile
List<QProfileActivity> result = service.searchActivities(new QProfileActivityQuery()
- .setQprofileKeys(ImmutableSet.of("java-default")), new QueryContext()).getHits();
+ .setQprofileKey("java-default"), new SearchOptions()).getHits();
assertThat(result).hasSize(1);
-
- // 1. filter by QProfiles
- assertThat(service.searchActivities(new QProfileActivityQuery()
- .setQprofileKeys(ImmutableSet.of("java-default", "java-toto"))
- , new QueryContext()).getHits()).hasSize(2);
}
@Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java
index 292b0e3effb..2bc554247f7 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java
@@ -253,6 +253,56 @@ public class RegisterRulesMediumTest {
}
@Test
+ public void update_only_rule_name() {
+ register(new Rules() {
+ @Override
+ public void init(RulesDefinition.NewRepository repository) {
+ repository.createRule("x1")
+ .setName("Name1")
+ .setHtmlDescription("Desc1");
+ }
+ });
+
+ register(new Rules() {
+ @Override
+ public void init(RulesDefinition.NewRepository repository) {
+ repository.createRule(RuleTesting.XOO_X1.rule())
+ .setName("Name2")
+ .setHtmlDescription("Desc1");
+ }
+ });
+
+ Rule rule = ruleIndex.getByKey(RuleTesting.XOO_X1);
+ assertThat(rule.name()).isEqualTo("Name2");
+ assertThat(rule.htmlDescription()).isEqualTo("Desc1");
+ }
+
+ @Test
+ public void update_only_rule_description() {
+ register(new Rules() {
+ @Override
+ public void init(RulesDefinition.NewRepository repository) {
+ repository.createRule("x1")
+ .setName("Name1")
+ .setHtmlDescription("Desc1");
+ }
+ });
+
+ register(new Rules() {
+ @Override
+ public void init(RulesDefinition.NewRepository repository) {
+ repository.createRule(RuleTesting.XOO_X1.rule())
+ .setName("Name1")
+ .setHtmlDescription("Desc2");
+ }
+ });
+
+ Rule rule = ruleIndex.getByKey(RuleTesting.XOO_X1);
+ assertThat(rule.name()).isEqualTo("Name1");
+ assertThat(rule.htmlDescription()).isEqualTo("Desc2");
+ }
+
+ @Test
public void do_not_update_rules_if_no_changes() throws Exception {
Rules rules = new Rules() {
@Override
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java
index 930515c1de7..7c1abbfedc7 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java
@@ -218,6 +218,8 @@ public class RegisterRulesTest extends AbstractDaoTestCase {
RegisterRules task = new RegisterRules(loader, ruleActivator, dbClient, languages);
task.start();
+ // Execute a commit to refresh session state as the task is using its own session
+ dbSession.commit();
}
private RuleParamDto getParam(List<RuleParamDto> params, String key) {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java
index 62cb7da516a..777f540f15d 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java
@@ -103,12 +103,28 @@ public class RubyRuleServiceTest {
assertThat(ruleQueryCaptor.getValue().getTags()).containsOnly("tag1", "tag2");
assertThat(ruleQueryCaptor.getValue().getDebtCharacteristics()).containsOnly("char1", "char2");
assertThat(ruleQueryCaptor.getValue().getHasDebtCharacteristic()).isTrue();
+ assertThat(ruleQueryCaptor.getValue().getQProfileKey()).isNull();
+ assertThat(ruleQueryCaptor.getValue().getActivation()).isNull();
assertThat(optionsCaptor.getValue().getLimit()).isEqualTo(40);
assertThat(optionsCaptor.getValue().getOffset()).isEqualTo(0);
}
@Test
+ public void search_rules_activated_on_a_profile() throws Exception {
+ when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(mock(Result.class));
+
+ HashMap<String, Object> params = newHashMap();
+ params.put("profile", "xoo-profile");
+ service.find(params);
+
+ verify(ruleService).search(ruleQueryCaptor.capture(), optionsCaptor.capture());
+
+ assertThat(ruleQueryCaptor.getValue().getQProfileKey()).isEqualTo("xoo-profile");
+ assertThat(ruleQueryCaptor.getValue().getActivation()).isTrue();
+ }
+
+ @Test
public void search_rules_without_page_size_param() throws Exception {
when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(mock(Result.class));
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/db/RuleDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/db/RuleDaoTest.java
index 15ce8518841..2b82eb2aaa9 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/db/RuleDaoTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/db/RuleDaoTest.java
@@ -34,9 +34,7 @@ import org.sonar.core.persistence.DbSession;
import org.sonar.core.rule.RuleDto;
import org.sonar.core.rule.RuleDto.Format;
import org.sonar.core.rule.RuleParamDto;
-import org.sonar.server.rule.RuleTesting;
-import java.util.Date;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@@ -368,31 +366,4 @@ public class RuleDaoTest extends AbstractDaoTestCase {
checkTables("update_parameter", "rules_parameters");
}
-
- @Test
- public void findAfterDate() throws Exception {
- long t0 = DateUtils.parseDate("2014-01-01").getTime();
- when(system2.now()).thenReturn(t0);
- dao.insert(session, RuleTesting.newXooX1());
- session.commit();
- assertThat(dao.getByKey(session, RuleTesting.XOO_X1).getCreatedAt().after(new Date(t0)));
-
-
- long t1 = DateUtils.parseDate("2014-02-01").getTime();
- when(system2.now()).thenReturn(t1);
- dao.insert(session, RuleTesting.newXooX2());
- session.commit();
- assertThat(dao.getByKey(session, RuleTesting.XOO_X2).getCreatedAt().after(new Date(t1)));
-
- long t2 = DateUtils.parseDate("2014-03-01").getTime();
- when(system2.now()).thenReturn(t2);
- session.flushStatements();
-
-
- assertThat(dao.findAll(session)).hasSize(2);
- assertThat(dao.findAfterDate(session, new Date(0))).hasSize(2);
- assertThat(dao.findAfterDate(session, new Date(t0))).hasSize(2);
- assertThat(dao.findAfterDate(session, new Date(t1))).hasSize(1);
- assertThat(dao.findAfterDate(session, new Date(t2))).hasSize(0);
- }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexMediumTest.java
index 50c8bf802ba..10f7dfba5da 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexMediumTest.java
@@ -52,15 +52,7 @@ import org.sonar.server.tester.ServerTester;
import javax.annotation.Nullable;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
@@ -329,15 +321,114 @@ public class RuleIndexMediumTest {
.setRemediationFunction("LINEAR").setRemediationCoefficient("2h")
.setDefaultSubCharacteristicId(null)
.setDefaultRemediationFunction(null));
+ // Rule without debt characteristic
+ dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("xoo", "S001"))
+ .setSubCharacteristicId(null)
+ .setRemediationFunction(null).setRemediationCoefficient(null)
+ .setDefaultSubCharacteristicId(null)
+ .setDefaultRemediationFunction(null).setDefaultRemediationCoefficient(null));
+ // Rule with disabled debt characteristic
+ dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("xoo", "S002"))
+ .setSubCharacteristicId(-1)
+ .setRemediationFunction(null).setRemediationCoefficient(null)
+ .setDefaultSubCharacteristicId(null)
+ .setDefaultRemediationFunction(null).setDefaultRemediationCoefficient(null));
dbSession.commit();
- // 0. assert base case
- assertThat(index.search(new RuleQuery(), new QueryContext()).getTotal()).isEqualTo(2);
- assertThat(db.debtCharacteristicDao().selectCharacteristics()).hasSize(2);
+ assertThat(index.search(new RuleQuery().setHasDebtCharacteristic(null), new QueryContext()).getTotal()).isEqualTo(4);
+ assertThat(index.search(new RuleQuery().setHasDebtCharacteristic(true), new QueryContext()).getTotal()).isEqualTo(2);
+ assertThat(index.search(new RuleQuery().setHasDebtCharacteristic(false), new QueryContext()).getTotal()).isEqualTo(2);
+ }
+
+ @Test
+ public void facet_on_debt_characteristic() throws InterruptedException {
+ CharacteristicDto char1 = DebtTesting.newCharacteristicDto("c1")
+ .setEnabled(true)
+ .setName("char1");
+ db.debtCharacteristicDao().insert(char1, dbSession);
+ dbSession.commit();
+
+ CharacteristicDto char11 = DebtTesting.newCharacteristicDto("c11")
+ .setEnabled(true)
+ .setName("char11")
+ .setParentId(char1.getId());
+ db.debtCharacteristicDao().insert(char11, dbSession);
+
+ // Rule with default characteristic
+ dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("findbugs", "S001"))
+ .setSubCharacteristicId(null)
+ .setRemediationFunction(null)
+ .setDefaultSubCharacteristicId(char11.getId())
+ .setDefaultRemediationFunction("LINEAR").setDefaultRemediationCoefficient("2h"));
+ // Rule with overridden characteristic
+ dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("pmd", "S002"))
+ .setSubCharacteristicId(char11.getId())
+ .setRemediationFunction("LINEAR").setRemediationCoefficient("2h")
+ .setDefaultSubCharacteristicId(null)
+ .setDefaultRemediationFunction(null));
+ // Rule without debt characteristic
+ dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("xoo", "S001"))
+ .setSubCharacteristicId(null)
+ .setRemediationFunction(null).setRemediationCoefficient(null)
+ .setDefaultSubCharacteristicId(null)
+ .setDefaultRemediationFunction(null).setDefaultRemediationCoefficient(null));
+ // Rule with disabled debt characteristic
+ dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("xoo", "S002"))
+ .setSubCharacteristicId(-1)
+ .setRemediationFunction(null).setRemediationCoefficient(null)
+ .setDefaultSubCharacteristicId(null)
+ .setDefaultRemediationFunction(null).setDefaultRemediationCoefficient(null));
+ dbSession.commit();
- // 1. assert hasSubChar filter
- assertThat(index.search(new RuleQuery().setHasDebtCharacteristic(true), new QueryContext()).getTotal())
- .isEqualTo(2);
+ QueryContext withDebtCharFacet = new QueryContext().addFacets(Arrays.asList(RuleIndex.FACET_DEBT_CHARACTERISTICS));
+
+ // Facet show results on characs, subcharacs and uncharacterized rules
+ Result<Rule> result1 = index.search(new RuleQuery(), withDebtCharFacet);
+ assertThat(result1.getFacetValues(RuleIndex.FACET_DEBT_CHARACTERISTICS)).containsOnly(
+ new FacetValue("c1", 2L),
+ new FacetValue("c11", 2L),
+ new FacetValue("", 1L),
+ new FacetValue("NONE", 1L)
+ );
+
+ // Facet is sticky when using a charac filter
+ Result<Rule> result2 = index.search(new RuleQuery().setDebtCharacteristics(Arrays.asList("c1")), withDebtCharFacet);
+ assertThat(result2.getFacetValues(RuleIndex.FACET_DEBT_CHARACTERISTICS)).containsOnly(
+ new FacetValue("c1", 2L),
+ new FacetValue("c11", 2L),
+ new FacetValue("", 1L),
+ new FacetValue("NONE", 1L)
+ );
+
+ // Facet is sticky when using a sub-charac filter
+ Result<Rule> result3 = index.search(new RuleQuery().setDebtCharacteristics(Arrays.asList("c11")), withDebtCharFacet);
+ assertThat(result3.getFacetValues(RuleIndex.FACET_DEBT_CHARACTERISTICS)).containsOnly(
+ new FacetValue("c1", 2L),
+ new FacetValue("c11", 2L),
+ new FacetValue("", 1L),
+ new FacetValue("NONE", 1L)
+ );
+
+ // Facet is sticky when using hasCharac filter
+ Result<Rule> result4 = index.search(new RuleQuery().setHasDebtCharacteristic(false), withDebtCharFacet);
+ assertThat(result4.getFacetValues(RuleIndex.FACET_DEBT_CHARACTERISTICS)).containsOnly(
+ new FacetValue("c1", 2L),
+ new FacetValue("c11", 2L),
+ new FacetValue("", 1L),
+ new FacetValue("NONE", 1L)
+ );
+
+ // Facet applies other filters
+ Result<Rule> result5 = index.search(new RuleQuery().setRepositories(Arrays.asList("xoo")), withDebtCharFacet);
+ assertThat(result5.getFacetValues(RuleIndex.FACET_DEBT_CHARACTERISTICS)).containsOnly(
+ new FacetValue("", 1L),
+ new FacetValue("NONE", 1L)
+ );
+ Result<Rule> result6 = index.search(new RuleQuery().setRepositories(Arrays.asList("findbugs")), withDebtCharFacet);
+ assertThat(result6.getFacetValues(RuleIndex.FACET_DEBT_CHARACTERISTICS)).containsOnly(
+ new FacetValue("c1", 1L),
+ new FacetValue("c11", 1L)
+ );
}
@Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceMediumTest.java
index eca79f58f1c..4a97bf50e68 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceMediumTest.java
@@ -19,8 +19,6 @@
*/
package org.sonar.server.rule.ws;
-import org.sonar.core.rule.RuleDto.Format;
-
import com.google.common.collect.ImmutableSet;
import org.junit.After;
import org.junit.Before;
@@ -38,6 +36,7 @@ import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
import org.sonar.core.qualityprofile.db.QualityProfileDao;
import org.sonar.core.qualityprofile.db.QualityProfileDto;
import org.sonar.core.rule.RuleDto;
+import org.sonar.core.rule.RuleDto.Format;
import org.sonar.core.rule.RuleParamDto;
import org.sonar.core.technicaldebt.db.CharacteristicDto;
import org.sonar.server.db.DbClient;
@@ -316,14 +315,36 @@ public class RulesWebServiceMediumTest {
.setRemediationCoefficient("30min")
.setRemediationOffset("5min")
);
+ ruleDao.insert(session, RuleTesting.newXooX3()
+ .setDefaultSubCharacteristicId(null)
+ .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name())
+ .setDefaultRemediationCoefficient("2min")
+ .setDefaultRemediationOffset("1min")
+
+ .setSubCharacteristicId(null)
+ .setRemediationFunction(null)
+ .setRemediationCoefficient(null)
+ .setRemediationOffset(null)
+ );
+ ruleDao.insert(session, RuleTesting.newDto(RuleKey.of("xoo", "x4")).setLanguage("xoo")
+ .setDefaultSubCharacteristicId(softReliabilityId)
+ .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name())
+ .setDefaultRemediationCoefficient("2min")
+ .setDefaultRemediationOffset("1min")
+
+ .setSubCharacteristicId(-1)
+ .setRemediationFunction(null)
+ .setRemediationCoefficient(null)
+ .setRemediationOffset(null)
+ );
session.commit();
MockUserSession.set();
- WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD);
- request.setParam(SearchOptions.PARAM_FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn");
- request.setParam("debt_characteristics", "SOFT_RELIABILITY");
- request.setParam(SearchAction.PARAM_FACETS, "debt_characteristics");
- WsTester.Result result = request.execute();
+ WsTester.Result result = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD)
+ .setParam(SearchOptions.PARAM_FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn")
+ .setParam("debt_characteristics", "SOFT_RELIABILITY")
+ .setParam(SearchAction.PARAM_FACETS, "debt_characteristics")
+ .execute();
result.assertJson(this.getClass(), "search_debt_rules_sticky.json", false);
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/BaseIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/BaseIndexTest.java
index 9eeecef377d..006e153ef06 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/search/BaseIndexTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/search/BaseIndexTest.java
@@ -20,7 +20,6 @@
package org.sonar.server.search;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
-import org.elasticsearch.common.settings.ImmutableSettings;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
@@ -91,11 +90,6 @@ public class BaseIndexTest {
null, searchClient) {
@Override
- protected ImmutableSettings.Builder addCustomIndexSettings(ImmutableSettings.Builder baseIndexSettings) {
- return baseIndexSettings.put("index.number_of_replicas", 22);
- }
-
- @Override
protected String getKeyValue(Serializable key) {
return null;
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java
index 5ba75c5f6ec..8560c032717 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java
@@ -37,7 +37,6 @@ import org.sonar.api.utils.DateUtils;
import org.sonar.core.persistence.DbTester;
import org.sonar.server.db.DbClient;
import org.sonar.server.es.EsTester;
-import org.sonar.server.search.BaseNormalizer;
import org.sonar.server.source.db.FileSourceTesting;
import org.sonar.test.DbTests;
import org.sonar.test.TestUtils;
@@ -68,6 +67,7 @@ public class SourceLineIndexerTest {
es.truncateIndices();
db.truncateTables();
indexer = new SourceLineIndexer(new DbClient(db.database(), db.myBatis()), es.client());
+ indexer.setEnabled(true);
}
@Test
@@ -102,7 +102,7 @@ public class SourceLineIndexerTest {
.put(FIELD_SCM_AUTHOR, "polop")
.put(FIELD_SOURCE, "package org.sonar.server.source;")
.put(FIELD_DUPLICATIONS, duplications)
- .put(BaseNormalizer.UPDATED_AT_FIELD, new Date())
+ .put(FIELD_UPDATED_AT, new Date())
.build());
SourceLineResultSetIterator.SourceFile file = new SourceLineResultSetIterator.SourceFile("efgh", System.currentTimeMillis());
file.addLine(line1);
@@ -175,7 +175,7 @@ public class SourceLineIndexerTest {
.put(FIELD_OVERALL_LINE_HITS, bigValue)
.put(FIELD_OVERALL_CONDITIONS, bigValue)
.put(FIELD_OVERALL_COVERED_CONDITIONS, bigValue)
- .put(BaseNormalizer.UPDATED_AT_FIELD, new Date())
+ .put(FIELD_UPDATED_AT, new Date())
.build());
SourceLineResultSetIterator.SourceFile file = new SourceLineResultSetIterator.SourceFile("efgh", System.currentTimeMillis());
file.addLine(line1);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java
index 0b49bbf16cb..acfc1527b63 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java
@@ -20,10 +20,8 @@
package org.sonar.server.source.ws;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
import org.apache.commons.lang.StringEscapeUtils;
-import org.elasticsearch.common.collect.Lists;
-import org.elasticsearch.common.collect.Maps;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -36,7 +34,6 @@ import org.sonar.core.component.ComponentDto;
import org.sonar.server.component.ComponentService;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.search.BaseNormalizer;
import org.sonar.server.source.HtmlSourceDecorator;
import org.sonar.server.source.index.SourceLineDoc;
import org.sonar.server.source.index.SourceLineIndex;
@@ -45,7 +42,6 @@ import org.sonar.server.user.MockUserSession;
import org.sonar.server.ws.WsTester;
import java.util.Date;
-import java.util.Map;
import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
@@ -94,57 +90,67 @@ public class LinesActionTest {
@Test
public void show_source() throws Exception {
+ String projectUuid = "abcd";
String componentUuid = "efgh";
Date updatedAt = new Date();
String scmDate = "2014-01-01T12:34:56.789Z";
- SourceLineDoc line1 = new SourceLineDoc(ImmutableMap.<String, Object>builder()
- .put(SourceLineIndexDefinition.FIELD_PROJECT_UUID, "abcd")
- .put(SourceLineIndexDefinition.FIELD_FILE_UUID, "efgh")
- .put(SourceLineIndexDefinition.FIELD_LINE, 1)
- .put(SourceLineIndexDefinition.FIELD_SCM_REVISION, "cafebabe")
- .put(SourceLineIndexDefinition.FIELD_SCM_DATE, scmDate)
- .put(SourceLineIndexDefinition.FIELD_SCM_AUTHOR, "polop")
- .put(SourceLineIndexDefinition.FIELD_SOURCE, "class Polop {")
- .put(SourceLineIndexDefinition.FIELD_HIGHLIGHTING, "h1")
- .put(SourceLineIndexDefinition.FIELD_SYMBOLS, "palap")
- .put(SourceLineIndexDefinition.FIELD_OVERALL_LINE_HITS, 3)
- .put(SourceLineIndexDefinition.FIELD_OVERALL_CONDITIONS, 2)
- .put(SourceLineIndexDefinition.FIELD_OVERALL_COVERED_CONDITIONS, 1)
- .put(SourceLineIndexDefinition.FIELD_DUPLICATIONS, ImmutableList.of())
- .put(BaseNormalizer.UPDATED_AT_FIELD, updatedAt)
- .build());
- SourceLineDoc line2 = new SourceLineDoc(ImmutableMap.<String, Object>builder()
- .put(SourceLineIndexDefinition.FIELD_PROJECT_UUID, "abcd")
- .put(SourceLineIndexDefinition.FIELD_FILE_UUID, "efgh")
- .put(SourceLineIndexDefinition.FIELD_LINE, 2)
- .put(SourceLineIndexDefinition.FIELD_SCM_REVISION, "cafebabe")
- .put(SourceLineIndexDefinition.FIELD_SCM_DATE, scmDate)
- .put(SourceLineIndexDefinition.FIELD_SCM_AUTHOR, "polop")
- .put(SourceLineIndexDefinition.FIELD_SOURCE, " // Empty")
- .put(SourceLineIndexDefinition.FIELD_HIGHLIGHTING, "h2")
- .put(SourceLineIndexDefinition.FIELD_SYMBOLS, "pulup")
- .put(SourceLineIndexDefinition.FIELD_OVERALL_LINE_HITS, 3)
- .put(SourceLineIndexDefinition.FIELD_OVERALL_CONDITIONS, 2)
- .put(SourceLineIndexDefinition.FIELD_OVERALL_COVERED_CONDITIONS, 1)
- .put(SourceLineIndexDefinition.FIELD_DUPLICATIONS, ImmutableList.of(1))
- .put(BaseNormalizer.UPDATED_AT_FIELD, updatedAt)
- .build());
- SourceLineDoc line3 = new SourceLineDoc(ImmutableMap.<String, Object>builder()
- .put(SourceLineIndexDefinition.FIELD_PROJECT_UUID, "abcd")
- .put(SourceLineIndexDefinition.FIELD_FILE_UUID, "efgh")
- .put(SourceLineIndexDefinition.FIELD_LINE, 3)
- .put(SourceLineIndexDefinition.FIELD_SCM_REVISION, "cafebabe")
- .put(SourceLineIndexDefinition.FIELD_SCM_DATE, scmDate)
- .put(SourceLineIndexDefinition.FIELD_SCM_AUTHOR, "polop")
- .put(SourceLineIndexDefinition.FIELD_SOURCE, "}")
- .put(SourceLineIndexDefinition.FIELD_HIGHLIGHTING, "h3")
- .put(SourceLineIndexDefinition.FIELD_SYMBOLS, "pylyp")
- .put(SourceLineIndexDefinition.FIELD_OVERALL_LINE_HITS, 3)
- .put(SourceLineIndexDefinition.FIELD_OVERALL_CONDITIONS, 2)
- .put(SourceLineIndexDefinition.FIELD_OVERALL_COVERED_CONDITIONS, 1)
- .put(SourceLineIndexDefinition.FIELD_DUPLICATIONS, ImmutableList.of())
- .put(BaseNormalizer.UPDATED_AT_FIELD, updatedAt)
- .build());
+ SourceLineDoc line1 = new SourceLineDoc()
+ .setProjectUuid(projectUuid)
+ .setFileUuid(componentUuid)
+ .setLine(1)
+ .setScmRevision("cafebabe")
+ .setScmAuthor("polop")
+ .setSource("class Polop {")
+ .setHighlighting("h1")
+ .setSymbols("palap")
+ .setUtLineHits(3)
+ .setUtConditions(2)
+ .setUtCoveredConditions(1)
+ .setItLineHits(3)
+ .setItConditions(2)
+ .setItCoveredConditions(1)
+ .setDuplications(ImmutableList.<Integer>of())
+ .setUpdateDate(updatedAt);
+ line1.setField(SourceLineIndexDefinition.FIELD_SCM_DATE, scmDate);
+
+ SourceLineDoc line2 = new SourceLineDoc()
+ .setProjectUuid(projectUuid)
+ .setFileUuid(componentUuid)
+ .setLine(2)
+ .setScmRevision("cafebabe")
+ .setScmAuthor("polop")
+ .setSource(" // Empty")
+ .setHighlighting("h2")
+ .setSymbols("pulup")
+ .setUtLineHits(3)
+ .setUtConditions(2)
+ .setUtCoveredConditions(1)
+ .setItLineHits(null)
+ .setItConditions(null)
+ .setItCoveredConditions(null)
+ .setDuplications(ImmutableList.<Integer>of(1))
+ .setUpdateDate(updatedAt);
+ line2.setField(SourceLineIndexDefinition.FIELD_SCM_DATE, scmDate);
+
+ SourceLineDoc line3 = new SourceLineDoc()
+ .setProjectUuid(projectUuid)
+ .setFileUuid(componentUuid)
+ .setLine(3)
+ .setScmRevision("cafebabe")
+ .setScmAuthor("polop")
+ .setSource("}")
+ .setHighlighting("h3")
+ .setSymbols("pylyp")
+ .setUtLineHits(null)
+ .setUtConditions(null)
+ .setUtCoveredConditions(null)
+ .setItLineHits(3)
+ .setItConditions(2)
+ .setItCoveredConditions(1)
+ .setDuplications(ImmutableList.<Integer>of())
+ .setUpdateDate(updatedAt);
+ line3.setField(SourceLineIndexDefinition.FIELD_SCM_DATE, scmDate);
+
when(sourceLineIndex.getLines(eq(componentUuid), anyInt(), anyInt())).thenReturn(newArrayList(
line1,
line2,
@@ -152,8 +158,8 @@ public class LinesActionTest {
));
String componentKey = "componentKey";
- when(componentService.getByUuid(componentUuid)).thenReturn(new ComponentDto().setKey(componentKey));
- MockUserSession.set().setLogin("login").addComponentPermission(UserRole.CODEVIEWER, "polop", componentKey);
+ when(componentService.getByUuid(componentUuid)).thenReturn(new ComponentDto().setKey(componentKey).setProjectUuid(projectUuid));
+ MockUserSession.set().setLogin("login").addProjectUuidPermissions(UserRole.CODEVIEWER, projectUuid);
WsTester.TestRequest request = tester.newGetRequest("api/sources", "lines").setParam("uuid", componentUuid);
// Using non-strict match b/c of dates
@@ -163,11 +169,12 @@ public class LinesActionTest {
@Test
public void fail_to_show_source_if_no_source_found() throws Exception {
String componentUuid = "abcd";
+ String projectUuid = "efgh";
when(sourceLineIndex.getLines(anyString(), anyInt(), anyInt())).thenReturn(Lists.<SourceLineDoc>newArrayList());
String componentKey = "componentKey";
- when(componentService.getByUuid(componentUuid)).thenReturn(new ComponentDto().setKey(componentKey));
- MockUserSession.set().setLogin("login").addComponentPermission(UserRole.CODEVIEWER, "polop", componentKey);
+ when(componentService.getByUuid(componentUuid)).thenReturn(new ComponentDto().setKey(componentKey).setProjectUuid(projectUuid));
+ MockUserSession.set().setLogin("login").addProjectUuidPermissions(UserRole.CODEVIEWER, projectUuid);
try {
WsTester.TestRequest request = tester.newGetRequest("api/sources", "lines").setParam("uuid", componentUuid);
@@ -180,29 +187,32 @@ public class LinesActionTest {
@Test
public void show_source_with_from_and_to_params() throws Exception {
+ String projectUuid = "abcd";
String fileUuid = "efgh";
- Map<String, Object> fieldMap = Maps.newHashMap();
- fieldMap.put(SourceLineIndexDefinition.FIELD_PROJECT_UUID, "abcd");
- fieldMap.put(SourceLineIndexDefinition.FIELD_FILE_UUID, "efgh");
- fieldMap.put(SourceLineIndexDefinition.FIELD_LINE, 3);
- fieldMap.put(SourceLineIndexDefinition.FIELD_SCM_REVISION, "cafebabe");
- fieldMap.put(SourceLineIndexDefinition.FIELD_SCM_DATE, null);
- fieldMap.put(SourceLineIndexDefinition.FIELD_SCM_AUTHOR, "polop");
- fieldMap.put(SourceLineIndexDefinition.FIELD_SOURCE, "}");
- fieldMap.put(SourceLineIndexDefinition.FIELD_HIGHLIGHTING, "");
- fieldMap.put(SourceLineIndexDefinition.FIELD_SYMBOLS, "");
- fieldMap.put(SourceLineIndexDefinition.FIELD_OVERALL_LINE_HITS, null);
- fieldMap.put(SourceLineIndexDefinition.FIELD_OVERALL_CONDITIONS, null);
- fieldMap.put(SourceLineIndexDefinition.FIELD_OVERALL_COVERED_CONDITIONS, null);
- fieldMap.put(SourceLineIndexDefinition.FIELD_DUPLICATIONS, null);
- fieldMap.put(BaseNormalizer.UPDATED_AT_FIELD, new Date());
String componentKey = "componentKey";
- when(componentService.getByUuid(fileUuid)).thenReturn(new ComponentDto().setKey(componentKey));
- MockUserSession.set().setLogin("login").addComponentPermission(UserRole.CODEVIEWER, "polop", componentKey);
+ when(componentService.getByUuid(fileUuid)).thenReturn(new ComponentDto().setKey(componentKey).setProjectUuid(projectUuid));
+ MockUserSession.set().setLogin("login").addProjectUuidPermissions(UserRole.CODEVIEWER, projectUuid);
when(sourceLineIndex.getLines(fileUuid, 3, 3)).thenReturn(newArrayList(
- new SourceLineDoc(fieldMap)
+ new SourceLineDoc()
+ .setProjectUuid(projectUuid)
+ .setFileUuid(fileUuid)
+ .setLine(3)
+ .setScmRevision("cafebabe")
+ .setScmDate(null)
+ .setScmAuthor("polop")
+ .setSource("}")
+ .setHighlighting("")
+ .setSymbols("")
+ .setUtLineHits(null)
+ .setUtConditions(null)
+ .setUtCoveredConditions(null)
+ .setItLineHits(null)
+ .setItConditions(null)
+ .setItCoveredConditions(null)
+ .setDuplications(null)
+ .setUpdateDate(new Date())
));
WsTester.TestRequest request = tester
.newGetRequest("api/sources", "lines")
diff --git a/server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java b/server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java
index 3d8f2e1ccdd..ea8f9785964 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java
@@ -85,6 +85,7 @@ public class ServerTester extends ExternalResource {
properties.setProperty(ProcessConstants.CLUSTER_NODE_NAME, esServerHolder.getNodeName());
properties.setProperty(ProcessConstants.SEARCH_PORT, String.valueOf(esServerHolder.getPort()));
properties.setProperty(ProcessConstants.PATH_HOME, homeDir.getAbsolutePath());
+ properties.setProperty(ProcessConstants.PATH_DATA, new File(homeDir, "data").getAbsolutePath());
properties.setProperty(DatabaseProperties.PROP_URL, "jdbc:h2:" + homeDir.getAbsolutePath() + "/h2");
for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
String key = entry.getKey().toString();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexerTest.java
index fdbcefb81ac..812b703252a 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexerTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexerTest.java
@@ -74,7 +74,17 @@ public class UserIndexerTest {
assertThat(doc.updatedAt()).isEqualTo(1500000000000L);
}
+ @Test
+ public void do_nothing_if_disabled() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "index.xml");
+
+ createIndexer().setEnabled(false).index();
+ assertThat(esTester.countDocuments("users", "user")).isEqualTo(0);
+ }
+
private UserIndexer createIndexer() {
- return new UserIndexer(new DbClient(dbTester.database(), dbTester.myBatis()), esTester.client());
+ UserIndexer indexer = new UserIndexer(new DbClient(dbTester.database(), dbTester.myBatis()), esTester.client());
+ indexer.setEnabled(true);
+ return indexer;
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java
index 4a0b093b327..259d7473904 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java
@@ -56,7 +56,7 @@ public class UsersWsTest {
assertThat(action.isPost()).isFalse();
assertThat(action.handler()).isInstanceOf(RailsHandler.class);
assertThat(action.responseExampleAsString()).isNotEmpty();
- assertThat(action.params()).hasSize(3);
+ assertThat(action.params()).hasSize(4);
}
@Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java
index b809a46922e..9656c199948 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java
@@ -55,6 +55,7 @@ public class ViewIndexerTest {
dbTester.truncateTables();
esTester.truncateIndices();
indexer = new ViewIndexer(new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao()), esTester.client());
+ indexer.setEnabled(true);
}
@Test
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/activity/index/ActivityResultSetIteratorTest/traverse.xml b/server/sonar-server/src/test/resources/org/sonar/server/activity/index/ActivityResultSetIteratorTest/traverse.xml
new file mode 100644
index 00000000000..f92f7678379
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/activity/index/ActivityResultSetIteratorTest/traverse.xml
@@ -0,0 +1,7 @@
+<dataset>
+ <activities id="1" log_key="UUID1" log_type="ANALYSIS_REPORT" log_action="THE_ACTION" log_message="THE_MSG"
+ created_at="2014-01-01" data_field="foo=bar" user_login="THE_AUTHOR"/>
+
+ <activities id="2" log_key="UUID2" log_type="ANALYSIS_REPORT" log_action="THE_ACTION" log_message="THE_MSG"
+ created_at="2015-01-01" data_field="foo=bar" user_login="THE_AUTHOR"/>
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/ComputationServiceTest/shared.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/ComputationServiceTest/shared.xml
index d01512aa559..66bd86524aa 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/ComputationServiceTest/shared.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/ComputationServiceTest/shared.xml
@@ -1,3 +1,3 @@
<dataset>
- <projects id="10" kee="PROJECT_KEY" qualifier="TRK"/>
+ <projects id="10" kee="P1" qualifier="TRK"/>
</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/any-analysis-reports.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/any-analysis-reports.xml
index b72284f5d10..dba17d047a4 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/any-analysis-reports.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/any-analysis-reports.xml
@@ -1,29 +1,26 @@
<dataset>
<analysis_reports
id="1"
+ uuid="REPORT_1"
project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
report_status="WORKING"
created_at="1411509600000"
updated_at="1411509600000"
/>
<analysis_reports
id="2"
+ uuid="REPORT_2"
project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
report_status="WORKING"
created_at="1411596000000"
updated_at="1411596000000"
/>
<analysis_reports
id="3"
+ uuid="REPORT_3"
project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
report_status="PENDING"
created_at="1411682400000"
updated_at="1411682400000"
/>
-</dataset> \ No newline at end of file
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml
index 26126affff8..ae28befd603 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml
@@ -2,8 +2,7 @@
<analysis_reports
id="1"
project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
+ uuid="REPORT_1"
report_status="PENDING"
created_at="1411509600000"
updated_at="1411596000000"
@@ -11,10 +10,9 @@
<analysis_reports
id="2"
project_key="987654321-123456789"
- snapshot_id="123"
- report_data="data-project"
+ uuid="REPORT_2"
report_status="WORKING"
created_at="1411423200000"
updated_at="1411682400000"
/>
-</dataset> \ No newline at end of file
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/insert-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/insert-result.xml
index a3043ec3238..bc6bbc5b63e 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/insert-result.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/insert-result.xml
@@ -3,8 +3,7 @@
id="1"
project_key="123456789-987654321"
project_name="[null]"
- snapshot_id="123"
- report_data="[null]"
+ uuid="UUID_1"
report_status="PENDING"
started_at="[null]"
finished_at="[null]"
@@ -15,8 +14,7 @@
id="2"
project_key="123456789-987654321"
project_name="[null]"
- snapshot_id="123"
- report_data="[null]"
+ uuid="UUID_2"
report_status="PENDING"
started_at="[null]"
finished_at="[null]"
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_analysis_report.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_analysis_report.xml
index ca3013e2f84..a4e07b73029 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_analysis_report.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_analysis_report.xml
@@ -2,12 +2,11 @@
<analysis_reports
id="1"
project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
+ uuid="REPORT_1"
report_status="WORKING"
created_at="1411509600000"
updated_at="1411596000000"
started_at="1411682400000"
finished_at="1411768800000"
/>
-</dataset> \ No newline at end of file
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_available_analysis.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_available_analysis.xml
deleted file mode 100644
index b26ec14839a..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_available_analysis.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<dataset>
- <analysis_reports
- id="1"
- project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
- report_status="PENDING"
- created_at="1411509600000"
- updated_at="1411596000000"
- />
- <analysis_reports
- id="2"
- project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
- report_status="PENDING"
- created_at="1411509600000"
- updated_at="1411596000000"
- />
-</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_available_analysis_but_another_busy_on_same_project.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_available_analysis_but_another_busy_on_same_project.xml
deleted file mode 100644
index f48e5e111b1..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_available_analysis_but_another_busy_on_same_project.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<dataset>
- <analysis_reports
- id="1"
- project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
- report_status="PENDING"
- created_at="1411509600000"
- updated_at="1411596000000"
- />
- <analysis_reports
- id="2"
- project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
- report_status="WORKING"
- created_at="1411423200000"
- updated_at="1411682400000"
- />
-</dataset> \ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_busy_report_analysis.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_busy_report_analysis.xml
deleted file mode 100644
index f853e443a39..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_busy_report_analysis.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<dataset>
- <analysis_reports
- id="1"
- project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
- report_status="WORKING"
- created_at="1411509600000"
- updated_at="1411596000000"
- />
-</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml
index 21eb7f1fb43..82f93e9fec5 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml
@@ -2,8 +2,7 @@
<analysis_reports
id="1"
project_key="111111111-987654321"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_1"
report_status="WORKING"
created_at="1411596000000"
updated_at="1411682400000"
@@ -11,8 +10,7 @@
<analysis_reports
id="2"
project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_2"
report_status="WORKING"
created_at="1411509600000"
updated_at="1411682400000"
@@ -21,10 +19,9 @@
<analysis_reports
id="3"
project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_3"
report_status="PENDING"
created_at="1411596000000"
updated_at="1411682400000"
/>
-</dataset> \ No newline at end of file
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/pop_oldest_pending.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/pop_oldest_pending.xml
index cae6dec371c..972fde88fd7 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/pop_oldest_pending.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/pop_oldest_pending.xml
@@ -3,8 +3,7 @@
<analysis_reports
id="1"
project_key="P1"
- snapshot_id="1"
- report_data="data-project"
+ uuid="UUID_1"
report_status="WORKING"
created_at="1411596000000"
updated_at="1411682400000"
@@ -14,8 +13,7 @@
<analysis_reports
id="2"
project_key="P1"
- snapshot_id="2"
- report_data="data-project"
+ uuid="UUID_2"
report_status="PENDING"
created_at="1411509600000"
updated_at="1411682400000"
@@ -23,8 +21,7 @@
<analysis_reports
id="3"
project_key="P2"
- snapshot_id="3"
- report_data="data-project"
+ uuid="UUID_3"
report_status="PENDING"
created_at="1411596000000"
updated_at="1411682400000"
@@ -32,8 +29,7 @@
<analysis_reports
id="4"
project_key="P2"
- snapshot_id="4"
- report_data="data-project"
+ uuid="UUID_4"
report_status="PENDING"
created_at="1420066800000"
updated_at="1420066800000"
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select.xml
index 8fff6461280..c1e3284f108 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select.xml
@@ -2,8 +2,7 @@
<analysis_reports
id="1"
project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_1"
report_status="WORKING"
created_at="1411509600000"
updated_at="1411596000000"
@@ -11,8 +10,7 @@
<analysis_reports
id="2"
project_key="987654321-123456789"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_2"
report_status="WORKING"
created_at="1411596000000"
updated_at="1411596000000"
@@ -20,10 +18,9 @@
<analysis_reports
id="3"
project_key="987654321-123456789"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_3"
report_status="PENDING"
created_at="1411682400000"
updated_at="1411682400000"
/>
-</dataset> \ No newline at end of file
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select_oldest_available_report_with_working_reports_older.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select_oldest_available_report_with_working_reports_older.xml
deleted file mode 100644
index 282458ef695..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select_oldest_available_report_with_working_reports_older.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<dataset>
- <analysis_reports
- id="1"
- project_key="111111111-987654321"
- snapshot_id="123"
- report_data="data-project"
- report_status="WORKING"
- created_at="1411423200000"
- updated_at="1411682400000"
- />
- <analysis_reports
- id="2"
- project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
- report_status="PENDING"
- created_at="1411509600000"
- updated_at="1411682400000"
- />
- <analysis_reports
- id="3"
- project_key="333333333-123456789"
- snapshot_id="123"
- report_data="data-project"
- report_status="WORKING"
- created_at="1411596000000"
- updated_at="1411682400000"
- />
-</dataset> \ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/three_analysis_reports.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/three_analysis_reports.xml
index 8fff6461280..c1e3284f108 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/three_analysis_reports.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/three_analysis_reports.xml
@@ -2,8 +2,7 @@
<analysis_reports
id="1"
project_key="123456789-987654321"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_1"
report_status="WORKING"
created_at="1411509600000"
updated_at="1411596000000"
@@ -11,8 +10,7 @@
<analysis_reports
id="2"
project_key="987654321-123456789"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_2"
report_status="WORKING"
created_at="1411596000000"
updated_at="1411596000000"
@@ -20,10 +18,9 @@
<analysis_reports
id="3"
project_key="987654321-123456789"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_3"
report_status="PENDING"
created_at="1411682400000"
updated_at="1411682400000"
/>
-</dataset> \ No newline at end of file
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending-result.xml
index a57c6282dd1..2c240ea4bc4 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending-result.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending-result.xml
@@ -4,8 +4,7 @@
id="1"
project_key="P1"
project_name="Project1"
- snapshot_id="1"
- report_data="data-project"
+ uuid="UUID_1"
report_status="PENDING"
created_at="1411509600000"
updated_at="1411682400000"
@@ -16,8 +15,7 @@
id="2"
project_key="P2"
project_name="Project2"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_2"
report_status="PENDING"
created_at="1411596000000"
updated_at="1411682400000"
@@ -28,8 +26,7 @@
id="3"
project_key="P1"
project_name="Project1"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_3"
report_status="PENDING"
created_at="1411682400000"
updated_at="1411682400000"
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending.xml
index 50edcc5da97..a630cb4ec4b 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending.xml
@@ -3,8 +3,7 @@
id="1"
project_key="P1"
project_name="Project1"
- snapshot_id="1"
- report_data="data-project"
+ uuid="UUID_1"
report_status="WORKING"
created_at="1411509600000"
updated_at="1411509600000"
@@ -15,8 +14,7 @@
id="2"
project_key="P2"
project_name="Project2"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_2"
report_status="WORKING"
created_at="1411596000000"
updated_at="1411596000000"
@@ -27,8 +25,7 @@
id="3"
project_key="P1"
project_name="Project1"
- snapshot_id="123"
- report_data="data-project"
+ uuid="UUID_3"
report_status="PENDING"
created_at="1411682400000"
updated_at="1411682400000"
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryWsActionMediumTest/list_history_reports.json b/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryWsActionMediumTest/list_history_reports.json
index b0ed60a0876..caa180819a4 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryWsActionMediumTest/list_history_reports.json
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryWsActionMediumTest/list_history_reports.json
@@ -2,18 +2,15 @@
"reports": [
{
"status": "SUCCESS",
- "projectName": "DefaultProjectName",
- "projectKey": "DefaultProjectKey"
+ "projectName": "POne",
+ "projectKey": "P1",
+ "projectUuid": "U1"
},
{
- "status": "SUCCESS",
- "projectName": "DefaultProjectName",
- "projectKey": "DefaultProjectKey"
- },
- {
- "status": "SUCCESS",
- "projectName": "DefaultProjectName",
- "projectKey": "DefaultProjectKey"
+ "status": "FAILED",
+ "projectName": "PTwo",
+ "projectKey": "P2",
+ "projectUuid": "U2"
}
]
-} \ No newline at end of file
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/SubmitReportWsActionTest/submit_report.json b/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/SubmitReportWsActionTest/submit_report.json
deleted file mode 100644
index 40062f5b580..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/SubmitReportWsActionTest/submit_report.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "key": "P1"
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/index/IssueIndexerTest/index.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/index/IssueIndexerTest/index.xml
index 4b946cdf306..d7e82dde47c 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/issue/index/IssueIndexerTest/index.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/index/IssueIndexerTest/index.xml
@@ -27,8 +27,8 @@
reporter="[null]"
issue_attributes="JIRA=http://jira.com"
action_plan_key="[null]"
- created_at="1000000000"
- updated_at="2000000000"
+ created_at="1500000000000"
+ updated_at="1550000000000"
issue_creation_date="1115848800000"
issue_update_date="1368828000000"
issue_close_date="[null]"
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rule.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rule.json
index cd218765544..0a2211290ec 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rule.json
+++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rule.json
@@ -27,6 +27,10 @@
{
"val": "HARD_RELIABILITY",
"count": 1
+ },
+ {
+ "val": "NONE",
+ "count": 0
}
]
}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rules_sticky.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rules_sticky.json
index fdd626cfb0e..a7cba30b88e 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rules_sticky.json
+++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rules_sticky.json
@@ -31,6 +31,10 @@
{
"val": "HARD_RELIABILITY",
"count": 1
+ },
+ {
+ "val": "NONE",
+ "count": 2
}
]
}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/source/ws/LinesActionTest/show_source.json b/server/sonar-server/src/test/resources/org/sonar/server/source/ws/LinesActionTest/show_source.json
index 123ccde38e2..7655e20c817 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/source/ws/LinesActionTest/show_source.json
+++ b/server/sonar-server/src/test/resources/org/sonar/server/source/ws/LinesActionTest/show_source.json
@@ -5,18 +5,21 @@
"line": 1,
"scmAuthor": "polop",
"scmRevision": "cafebabe",
- "lineHits": 3,
- "conditions": 2,
- "coveredConditions": 1
+ "utLineHits": 3,
+ "utConditions": 2,
+ "utCoveredConditions": 1,
+ "itLineHits": 3,
+ "itConditions": 2,
+ "itCoveredConditions": 1
},
{
"code": "<span class=\"h2 sym-pulup\"> // Empty</span>",
"line": 2,
"scmAuthor": "polop",
"scmRevision": "cafebabe",
- "lineHits": 3,
- "conditions": 2,
- "coveredConditions": 1,
+ "utLineHits": 3,
+ "utConditions": 2,
+ "utCoveredConditions": 1,
"duplicated": true
},
{
@@ -24,9 +27,9 @@
"line": 3,
"scmAuthor": "polop",
"scmRevision": "cafebabe",
- "lineHits": 3,
- "conditions": 2,
- "coveredConditions": 1
+ "itLineHits": 3,
+ "itConditions": 2,
+ "itCoveredConditions": 1
}
]
}
diff --git a/server/sonar-web/Gruntfile.coffee b/server/sonar-web/Gruntfile.coffee
index 6ddb1e5c2d6..f306c495a9d 100644
--- a/server/sonar-web/Gruntfile.coffee
+++ b/server/sonar-web/Gruntfile.coffee
@@ -1,6 +1,8 @@
module.exports = (grunt) ->
require('jit-grunt')(grunt, {
express: 'grunt-express-server'
+ unzip: 'grunt-zip'
+ replace: 'grunt-text-replace'
});
pkg = grunt.file.readJSON('package.json')
@@ -243,6 +245,10 @@ module.exports = (grunt) ->
name: 'nav/app'
out: '<%= grunt.option("assetsDir") || pkg.assets %>build/js/nav/app.js'
+ issueFilterWidget: options:
+ name: 'widgets/issue-filter'
+ out: '<%= grunt.option("assetsDir") || pkg.assets %>build/js/widgets/issue-filter.js'
+
handlebars:
options:
@@ -296,6 +302,9 @@ module.exports = (grunt) ->
'<%= grunt.option("assetsDir") || pkg.assets %>js/templates/nav.js': [
'<%= pkg.sources %>hbs/nav/**/*.hbs'
]
+ '<%= grunt.option("assetsDir") || pkg.assets %>js/templates/widgets.js': [
+ '<%= pkg.sources %>hbs/widgets/**/*.hbs'
+ ]
'<%= grunt.option("assetsDir") || pkg.assets %>js/templates/workspace.js': [
'<%= pkg.sources %>hbs/workspace/**/*.hbs'
]
@@ -321,12 +330,16 @@ module.exports = (grunt) ->
express:
test:
options:
- script: '<%= pkg.sources %>js/tests/e2e/server.js'
+ script: 'src/test/server.js'
+ port: expressPort
+ testCoverage:
+ options:
+ script: 'src/test/server-coverage.js'
port: expressPort
dev:
options:
background: false
- script: '<%= pkg.sources %>js/tests/e2e/server.js'
+ script: 'src/test/server.js'
casper:
@@ -338,14 +351,29 @@ module.exports = (grunt) ->
concise: true
parallel: true
port: expressPort
- src: ['<%= pkg.sources %>js/tests/e2e/tests/**/*.js']
+ src: ['src/test/js/**/*.js']
+ testCoverage:
+ options:
+ test: true
+ 'no-colors': true
+ 'fail-fast': true
+ concise: true
+ port: expressPort
+ src: ['src/test/js/**/*.js']
+ testCoverageTemp:
+ options:
+ test: true
+ 'fail-fast': true
+ verbose: true
+ port: expressPort
+ src: ['src/test/js/**/*-issue-filter-widget.js']
single:
options:
test: true
verbose: true
'fail-fast': true
port: expressPort
- src: ['<%= pkg.sources %>js/tests/e2e/tests/<%= grunt.option("spec") %>-spec.js']
+ src: ['src/test/js/<%= grunt.option("spec") %>-spec.js']
testfile:
options:
test: true
@@ -366,6 +394,32 @@ module.exports = (grunt) ->
]
+ curl:
+ resetCoverage:
+ src:
+ url: 'http://localhost:' + expressPort + '/coverage/reset'
+ method: 'POST'
+ dest: 'target/reset_coverage.dump'
+
+ downloadCoverage:
+ src: 'http://localhost:' + expressPort + '/coverage/download'
+ dest: 'target/coverage.zip'
+
+
+ unzip:
+ 'target/js-coverage': 'target/coverage.zip'
+
+
+ replace:
+ lcov:
+ src: 'target/js-coverage/lcov.info'
+ dest: 'target/js-coverage/lcov.info'
+ replacements: [{
+ from: '/webapp'
+ to: ''
+ }]
+
+
jshint:
dev:
src: [
@@ -418,6 +472,12 @@ module.exports = (grunt) ->
grunt.registerTask 'test',
['dev', 'express:test', 'casper:test']
+ grunt.registerTask 'testCoverage',
+ ['dev', 'express:testCoverage', 'curl:resetCoverage', 'casper:testCoverage', 'curl:downloadCoverage', 'unzip', 'replace:lcov']
+
+ grunt.registerTask 'testCoverageTemp',
+ ['dev', 'express:testCoverage', 'curl:resetCoverage', 'casper:testCoverageTemp', 'curl:downloadCoverage', 'unzip', 'replace:lcov']
+
grunt.registerTask 'single',
['dev', 'express:test', 'casper:single']
@@ -425,8 +485,11 @@ module.exports = (grunt) ->
['dev', 'express:test', 'casper:testfile']
# tasks used by Maven build (see pom.xml)
- grunt.registerTask 'maven-build-skip-tests-true',
+ grunt.registerTask 'maven-build-skip-tests-true-nocoverage',
['build']
- grunt.registerTask 'maven-build-skip-tests-false',
+ grunt.registerTask 'maven-build-skip-tests-false-nocoverage',
['test', 'build']
+
+ grunt.registerTask 'maven-build-skip-tests-false-coverage',
+ ['testCoverage', 'build']
diff --git a/server/sonar-web/package.json b/server/sonar-web/package.json
index f9beeb0882a..d0150e2b137 100644
--- a/server/sonar-web/package.json
+++ b/server/sonar-web/package.json
@@ -19,8 +19,13 @@
"grunt-contrib-uglify": "0.4.0",
"grunt-contrib-watch": "0.5.3",
"grunt-css-url-rewrite": "0.3.5",
+ "grunt-curl": "2.1.0",
"grunt-express-server": "0.4.17",
+ "grunt-text-replace": "0.4.0",
"grunt-uglify-parallel": "0.0.1",
+ "grunt-zip": "0.16.2",
+ "istanbul": "0.3.5",
+ "istanbul-middleware": "0.2.0",
"jade": "1.4.2",
"jit-grunt": "0.9.1",
"phantomjs": "1.9.7-12",
diff --git a/server/sonar-web/pom.xml b/server/sonar-web/pom.xml
index d5b9865076f..9b7e9ac2ee9 100644
--- a/server/sonar-web/pom.xml
+++ b/server/sonar-web/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>server</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>sonar-web</artifactId>
@@ -15,6 +15,7 @@
<!-- self-analysis -->
<sonar.sources>src/main/js,src/main/coffee,src/main/hbs,src/main/less</sonar.sources>
<sonar.exclusions>src/main/js/third-party/**/*,src/main/js/require.js,src/main/js/tests/**/*</sonar.exclusions>
+ <sonar.javascript.lcov.reportPath>target/js-coverage/lcov.info</sonar.javascript.lcov.reportPath>
</properties>
<build>
@@ -153,7 +154,7 @@
<goal>grunt</goal>
</goals>
<configuration>
- <arguments>maven-build-skip-tests-${skipWebTests} --port=${jsTestPort} --no-color</arguments>
+ <arguments>maven-build-skip-tests-${skipWebTests}-${jsCoverage} --port=${jsTestPort} --no-color</arguments>
</configuration>
</execution>
</executions>
diff --git a/server/sonar-web/src/main/hbs/coding-rules/facets/coding-rules-characteristic-facet.hbs b/server/sonar-web/src/main/hbs/coding-rules/facets/coding-rules-characteristic-facet.hbs
index 1742660c33a..645205b0c5c 100644
--- a/server/sonar-web/src/main/hbs/coding-rules/facets/coding-rules-characteristic-facet.hbs
+++ b/server/sonar-web/src/main/hbs/coding-rules/facets/coding-rules-characteristic-facet.hbs
@@ -2,10 +2,18 @@
<div class="search-navigator-facet-list">
{{#each values}}
- <a class="facet search-navigator-facet {{#if parent}}search-navigator-facet-indent{{/if}} js-facet"
- data-value="{{val}}" title="{{default label val}}">
- <span class="facet-name">{{default label val}}</span>
- <span class="facet-stat">{{numberShort count}}</span>
- </a>
+ {{#eq val 'NONE'}}
+ <a class="facet search-navigator-facet js-facet" data-empty-characteristic
+ title="{{t 'coding_rules.noncharacterized'}}">
+ <span class="facet-name">{{t 'coding_rules.noncharacterized'}}</span>
+ <span class="facet-stat">{{numberShort count}}</span>
+ </a>
+ {{else}}
+ <a class="facet search-navigator-facet {{#if parent}}search-navigator-facet-indent{{/if}} js-facet"
+ data-value="{{val}}" title="{{default label val}}">
+ <span class="facet-name">{{default label val}}</span>
+ <span class="facet-stat">{{numberShort count}}</span>
+ </a>
+ {{/eq}}
{{/each}}
</div>
diff --git a/server/sonar-web/src/main/hbs/coding-rules/rule/coding-rules-rule-issues.hbs b/server/sonar-web/src/main/hbs/coding-rules/rule/coding-rules-rule-issues.hbs
index e60656f4dd0..da9a5336d36 100644
--- a/server/sonar-web/src/main/hbs/coding-rules/rule/coding-rules-rule-issues.hbs
+++ b/server/sonar-web/src/main/hbs/coding-rules/rule/coding-rules-rule-issues.hbs
@@ -1,7 +1,7 @@
<div class="coding-rule-section-separator"></div>
<h3 class="coding-rules-detail-title">
- {{t 'coding_rules.issues'}} (<a class="js-rule-issues" href="{{baseSearchUrl}}" target="_blank">{{total}}</a>)
+ {{t 'coding_rules.issues'}} (<a class="js-rule-issues" href="{{baseSearchUrl}}">{{total}}</a>)
</h3>
{{#notEmpty projects}}
diff --git a/server/sonar-web/src/main/hbs/source-viewer/source-viewer-coverage-popup.hbs b/server/sonar-web/src/main/hbs/source-viewer/source-viewer-coverage-popup.hbs
index 1512a7e0b10..c30e1f500a9 100644
--- a/server/sonar-web/src/main/hbs/source-viewer/source-viewer-coverage-popup.hbs
+++ b/server/sonar-web/src/main/hbs/source-viewer/source-viewer-coverage-popup.hbs
@@ -1,12 +1,12 @@
<div class="bubble-popup-container">
<div class="bubble-popup-title">
{{#if row.lineHits}}
- {{t 'source_viewer.covered'}}
+ {{t 'source_viewer' tests 'covered'}}
{{#if row.conditions}}
({{default row.coveredConditions 0}} of {{row.conditions}} {{t 'source_viewer.conditions'}})
{{/if}}
{{else}}
- {{t 'source_viewer.not_covered'}}
+ {{t 'source_viewer' tests 'not_covered'}}
{{#if row.conditions}}
({{row.conditions}} {{t 'source_viewer.conditions'}})
{{/if}}
diff --git a/server/sonar-web/src/main/hbs/source-viewer/source-viewer-duplication-popup.hbs b/server/sonar-web/src/main/hbs/source-viewer/source-viewer-duplication-popup.hbs
index 673fabdc7d2..d3553ed3e58 100644
--- a/server/sonar-web/src/main/hbs/source-viewer/source-viewer-duplication-popup.hbs
+++ b/server/sonar-web/src/main/hbs/source-viewer/source-viewer-duplication-popup.hbs
@@ -28,7 +28,7 @@
Lines:
{{#joinEach blocks ','}}
<a class="link-action" data-uuid="{{../file.uuid}}" data-line="{{from}}">
- {{from}} – {{sum from size}}
+ {{from}} – {{sum from size -1}}
</a>
{{/joinEach}}
</div>
diff --git a/server/sonar-web/src/main/hbs/source-viewer/source-viewer.hbs b/server/sonar-web/src/main/hbs/source-viewer/source-viewer.hbs
index 0f239f255df..843f5d004c2 100644
--- a/server/sonar-web/src/main/hbs/source-viewer/source-viewer.hbs
+++ b/server/sonar-web/src/main/hbs/source-viewer/source-viewer.hbs
@@ -17,10 +17,21 @@
{{/ifSCMChanged2}}
</td>
- <td class="source-meta source-line-coverage {{#notNull coverageStatus}}source-line-{{coverageStatus}}{{/notNull}}"
- data-line-number="{{line}}" {{#notNull coverageStatus}}title="{{t 'source_viewer.tooltip' coverageStatus}}" data-placement="right" data-toggle="tooltip"{{/notNull}}>
- <div class="source-line-bar"></div>
- </td>
+ {{#if ../hasUTCoverage}}
+ <td class="source-meta source-line-coverage {{#notNull utCoverageStatus}}source-line-{{utCoverageStatus}}{{/notNull}}"
+ data-tests="ut"
+ data-line-number="{{line}}" {{#notNull utCoverageStatus}}title="{{t 'source_viewer.tooltip.ut' utCoverageStatus}}" data-placement="right" data-toggle="tooltip"{{/notNull}}>
+ <div class="source-line-bar"></div>
+ </td>
+ {{/if}}
+
+ {{#if ../hasITCoverage}}
+ <td class="source-meta source-line-coverage {{#notNull itCoverageStatus}}source-line-{{itCoverageStatus}}{{/notNull}}"
+ data-tests="it"
+ data-line-number="{{line}}" {{#notNull itCoverageStatus}}title="{{t 'source_viewer.tooltip.it' itCoverageStatus}}" data-placement="right" data-toggle="tooltip"{{/notNull}}>
+ <div class="source-line-bar"></div>
+ </td>
+ {{/if}}
{{#if ../hasDuplications}}
<td class="source-meta source-line-duplications {{#if duplicated}}source-line-duplicated{{/if}}"
diff --git a/server/sonar-web/src/main/hbs/widgets/_widget-issue-filter-total.hbs b/server/sonar-web/src/main/hbs/widgets/_widget-issue-filter-total.hbs
new file mode 100644
index 00000000000..1619ed5ab8c
--- /dev/null
+++ b/server/sonar-web/src/main/hbs/widgets/_widget-issue-filter-total.hbs
@@ -0,0 +1,11 @@
+<tr>
+ <td>
+ <a href="{{issueFilterTotalLink parsedQuery}}"><strong>{{t 'total'}}</strong></a>
+ </td>
+ <td class="text-right"><strong>{{#notNull periodDate}}+{{/notNull}}{{total}}</strong></td>
+ <td class="barchart">
+ <div class="barchart" style="width: 100%;">
+ <div style="width: 100%;"></div>
+ </div>
+ </td>
+</tr>
diff --git a/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-action-plans.hbs b/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-action-plans.hbs
new file mode 100644
index 00000000000..cec1a9a6748
--- /dev/null
+++ b/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-action-plans.hbs
@@ -0,0 +1,22 @@
+<table class="data zebra">
+ {{> '_widget-issue-filter-total'}}
+ {{#each items}}
+ <tr>
+ <td>
+ {{#eq val ''}}
+ <a href="{{issueFilterItemLink ../../parsedQuery 'planned' 'false'}}">{{t 'issue.unplanned'}}</a>
+ {{else}}
+ <a href="{{issueFilterItemLink ../../parsedQuery 'actionPlans' val}}">{{default label val}}</a>
+ {{/eq}}
+ </td>
+ <td class="text-right nowrap">
+ {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+ </td>
+ <td class="barchart">
+ <div class="barchart" style="width: 100%;">
+ <div style="width: {{percent count ../total}};"></div>
+ </div>
+ </td>
+ </tr>
+ {{/each}}
+</table>
diff --git a/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-assignees.hbs b/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-assignees.hbs
new file mode 100644
index 00000000000..3e1add4abd2
--- /dev/null
+++ b/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-assignees.hbs
@@ -0,0 +1,22 @@
+<table class="data zebra">
+ {{> '_widget-issue-filter-total'}}
+ {{#each items}}
+ <tr>
+ <td>
+ {{#eq val ''}}
+ <a href="{{issueFilterItemLink ../../parsedQuery 'assigned' 'false'}}">{{t 'unassigned'}}</a>
+ {{else}}
+ <a href="{{issueFilterItemLink ../../parsedQuery 'assignees' val}}">{{default label val}}</a>
+ {{/eq}}
+ </td>
+ <td class="text-right nowrap">
+ {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+ </td>
+ <td class="barchart">
+ <div class="barchart" style="width: 100%;">
+ <div style="width: {{percent count ../total}};"></div>
+ </div>
+ </td>
+ </tr>
+ {{/each}}
+</table>
diff --git a/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-resolutions.hbs b/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-resolutions.hbs
new file mode 100644
index 00000000000..8c03461b619
--- /dev/null
+++ b/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-resolutions.hbs
@@ -0,0 +1,22 @@
+<table class="data zebra">
+ {{> '_widget-issue-filter-total'}}
+ {{#each items}}
+ <tr>
+ <td>
+ {{#eq val ''}}
+ <a href="{{issueFilterItemLink ../../parsedQuery 'resolved' 'false'}}">{{t 'unresolved'}}</a>
+ {{else}}
+ <a href="{{issueFilterItemLink ../../parsedQuery 'resolutions' val}}">{{t 'issue.resolution' val}}</a>
+ {{/eq}}
+ </td>
+ <td class="text-right nowrap">
+ {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+ </td>
+ <td class="barchart">
+ <div class="barchart" style="width: 100%;">
+ <div style="width: {{percent count ../total}};"></div>
+ </div>
+ </td>
+ </tr>
+ {{/each}}
+</table>
diff --git a/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-severities.hbs b/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-severities.hbs
new file mode 100644
index 00000000000..98b255ce640
--- /dev/null
+++ b/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-severities.hbs
@@ -0,0 +1,19 @@
+<table class="data zebra">
+ <tr>
+ <td>
+ <a href="{{issueFilterTotalLink parsedQuery}}"><strong>{{t 'total'}}</strong></a>
+ </td>
+ <td class="text-right"><strong>{{#notNull periodDate}}+{{/notNull}}{{total}}</strong></td>
+ </tr>
+ {{#each items}}
+ <tr>
+ <td>
+ {{severityIcon val}}
+ <a href="{{issueFilterItemLink ../parsedQuery ../property val}}">{{t 'severity' val}}</a>
+ </td>
+ <td class="text-right nowrap">
+ {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+ </td>
+ </tr>
+ {{/each}}
+</table>
diff --git a/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-statuses.hbs b/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-statuses.hbs
new file mode 100644
index 00000000000..b27fc32964f
--- /dev/null
+++ b/server/sonar-web/src/main/hbs/widgets/widget-issue-filter-statuses.hbs
@@ -0,0 +1,19 @@
+<table class="data zebra">
+ {{> '_widget-issue-filter-total'}}
+ {{#each items}}
+ <tr>
+ <td>
+ {{statusIcon val}}
+ <a href="{{issueFilterItemLink ../parsedQuery ../property val}}">{{t 'issue.status' val}}</a>
+ </td>
+ <td class="text-right nowrap">
+ {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+ </td>
+ <td class="barchart">
+ <div class="barchart" style="width: 100%;">
+ <div style="width: {{percent count ../total}};"></div>
+ </div>
+ </td>
+ </tr>
+ {{/each}}
+</table>
diff --git a/server/sonar-web/src/main/hbs/widgets/widget-issue-filter.hbs b/server/sonar-web/src/main/hbs/widgets/widget-issue-filter.hbs
new file mode 100644
index 00000000000..ffb3e072557
--- /dev/null
+++ b/server/sonar-web/src/main/hbs/widgets/widget-issue-filter.hbs
@@ -0,0 +1,18 @@
+<table class="data zebra">
+ {{> '_widget-issue-filter-total'}}
+ {{#each items}}
+ <tr>
+ <td>
+ <a href="{{searchLink}}">{{default label val}}</a>
+ </td>
+ <td class="text-right nowrap">
+ {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+ </td>
+ <td class="barchart">
+ <div class="barchart" style="width: 100%;">
+ <div style="width: {{percent count ../total}};"></div>
+ </div>
+ </td>
+ </tr>
+ {{/each}}
+</table>
diff --git a/server/sonar-web/src/main/js/application.js b/server/sonar-web/src/main/js/application.js
index 9362987d90b..de273f721dd 100644
--- a/server/sonar-web/src/main/js/application.js
+++ b/server/sonar-web/src/main/js/application.js
@@ -333,6 +333,39 @@ function openPopup(url, popupId) {
}
+function collapsedDirFromPath (path) {
+ var limit = 30;
+ if (typeof path === 'string') {
+ var tokens = _.initial(path.split('/'));
+ if (tokens.length > 2) {
+ var head = _.first(tokens),
+ tail = _.last(tokens),
+ middle = _.initial(_.rest(tokens)),
+ cut = false;
+ while (middle.join().length > limit && middle.length > 0) {
+ middle.shift();
+ cut = true;
+ }
+ var body = [].concat(head, cut ? ['...'] : [], middle, tail);
+ return body.join('/') + '/';
+ } else {
+ return tokens.join('/') + '/';
+ }
+ } else {
+ return null;
+ }
+}
+
+function fileFromPath (path) {
+ if (typeof path === 'string') {
+ var tokens = path.split('/');
+ return _.last(tokens);
+ } else {
+ return null;
+ }
+}
+
+
jQuery(function () {
// Process login link in order to add the anchor
diff --git a/server/sonar-web/src/main/js/coding-rules/facets/characteristic-facet.js b/server/sonar-web/src/main/js/coding-rules/facets/characteristic-facet.js
index 94a954abc7a..5275d260317 100644
--- a/server/sonar-web/src/main/js/coding-rules/facets/characteristic-facet.js
+++ b/server/sonar-web/src/main/js/coding-rules/facets/characteristic-facet.js
@@ -22,9 +22,44 @@ define([
'templates/coding-rules'
], function (BaseFacet) {
+ var $ = jQuery;
+
return BaseFacet.extend({
template: Templates['coding-rules-characteristic-facet'],
+ onRender: function () {
+ BaseFacet.prototype.onRender.apply(this, arguments);
+ var value = this.options.app.state.get('query').has_debt_characteristic;
+ if (value != null && ('' + value === 'false')) {
+ this.$('.js-facet').filter('[data-empty-characteristic]').addClass('active');
+ }
+ },
+
+ toggleFacet: function (e) {
+ var noneCharacteristic = $(e.currentTarget).is('[data-empty-characteristic]'),
+ property = this.model.get('property'),
+ obj = {};
+ $(e.currentTarget).toggleClass('active');
+ if (noneCharacteristic) {
+ var checked = $(e.currentTarget).is('.active');
+ obj.has_debt_characteristic = checked ? 'false' : null;
+ obj[property] = null;
+ } else {
+ obj.has_debt_characteristic = null;
+ obj[property] = this.getValue();
+ }
+ console.log(obj);
+ this.options.app.state.updateFilter(obj);
+ },
+
+ disable: function () {
+ var property = this.model.get('property'),
+ obj = {};
+ obj.has_debt_characteristic = null;
+ obj[property] = null;
+ this.options.app.state.updateFilter(obj);
+ },
+
getValues: function () {
var values = this.model.getValues(),
characteristics = this.options.app.characteristics;
@@ -32,8 +67,6 @@ define([
var ch = _.findWhere(characteristics, { key: value.val });
if (ch != null) {
_.extend(value, ch, { label: ch.name });
- } else {
- _.extend(value, { label: t('coding_rules.noncharacterized') });
}
return value;
});
diff --git a/server/sonar-web/src/main/js/coding-rules/models/state.js b/server/sonar-web/src/main/js/coding-rules/models/state.js
index 050a7ff58b3..97720d9d5de 100644
--- a/server/sonar-web/src/main/js/coding-rules/models/state.js
+++ b/server/sonar-web/src/main/js/coding-rules/models/state.js
@@ -30,7 +30,9 @@ define([
allFacets: ['q', 'rule_key', 'languages', 'tags', 'repositories', 'debt_characteristics', 'severities',
'statuses', 'available_since', 'is_template', 'qprofile', 'inheritance', 'active_severities'],
facetsFromServer: ['languages', 'repositories', 'tags', 'severities', 'statuses', 'debt_characteristics'],
- transform: {}
+ transform: {
+ 'has_debt_characteristic': 'debt_characteristics'
+ }
}
});
diff --git a/server/sonar-web/src/main/js/common/handlebars-extensions.js b/server/sonar-web/src/main/js/common/handlebars-extensions.js
index 36f89fd0214..260396cc73e 100644
--- a/server/sonar-web/src/main/js/common/handlebars-extensions.js
+++ b/server/sonar-web/src/main/js/common/handlebars-extensions.js
@@ -259,7 +259,10 @@
});
Handlebars.registerHelper('sum', function(a, b) {
- return a + b;
+ var args = Array.prototype.slice.call(arguments, 0, -1);
+ return args.reduce(function (p, c) {
+ return p + +c;
+ }, 0);
});
Handlebars.registerHelper('dashboardUrl', function(componentKey, componentQualifier) {
@@ -473,35 +476,11 @@
});
Handlebars.registerHelper('collapsedDirFromPath', function (path) {
- var limit = 30;
- if (typeof path === 'string') {
- var tokens = _.initial(path.split('/'));
- if (tokens.length > 2) {
- var head = _.first(tokens),
- tail = _.last(tokens),
- middle = _.initial(_.rest(tokens)),
- cut = false;
- while (middle.join().length > limit && middle.length > 0) {
- middle.shift();
- cut = true;
- }
- var body = [].concat(head, cut ? ['...'] : [], middle, tail);
- return body.join('/') + '/';
- } else {
- return tokens.join('/') + '/';
- }
- } else {
- return null;
- }
+ return collapsedDirFromPath(path);
});
Handlebars.registerHelper('fileFromPath', function (path) {
- if (typeof path === 'string') {
- var tokens = path.split('/');
- return _.last(tokens);
- } else {
- return null;
- }
+ return fileFromPath(path);
});
Handlebars.registerHelper('repeat', function (number, options) {
diff --git a/server/sonar-web/src/main/js/nav/search-view.js b/server/sonar-web/src/main/js/nav/search-view.js
index 9c74292b56f..d89942bdbcf 100644
--- a/server/sonar-web/src/main/js/nav/search-view.js
+++ b/server/sonar-web/src/main/js/nav/search-view.js
@@ -129,7 +129,7 @@ define([
url: baseUrl + '/dashboard/index?id=' + encodeURIComponent(historyItem.key) + dashboardParameters(true),
name: historyItem.name,
q: historyItem.icon,
- extra: index === 0 ? t('recent_history') : null
+ extra: index === 0 ? t('browsed_recently') : null
};
}),
qualifiers = this.model.get('qualifiers').map(function (q, index) {
diff --git a/server/sonar-web/src/main/js/source-viewer/popups/coverage-popup.js b/server/sonar-web/src/main/js/source-viewer/popups/coverage-popup.js
index cbc57a1eb0c..34f080e9655 100644
--- a/server/sonar-web/src/main/js/source-viewer/popups/coverage-popup.js
+++ b/server/sonar-web/src/main/js/source-viewer/popups/coverage-popup.js
@@ -46,7 +46,8 @@ define([
},
serializeData: function () {
- var files = this.model.get('files'),
+ var row = this.options.row || {},
+ files = this.model.get('files'),
tests = _.groupBy(this.model.get('tests'), '_ref'),
testFiles = _.map(tests, function (testSet, fileRef) {
return {
@@ -54,9 +55,15 @@ define([
tests: testSet
};
});
+ _.extend(row, {
+ lineHits: row[this.options.tests + 'LineHits'],
+ conditions: row[this.options.tests + 'Conditions'],
+ coveredConditions: row[this.options.tests + 'CoveredConditions']
+ });
return {
testFiles: testFiles,
- row: this.options.row
+ tests: this.options.tests,
+ row: row
};
}
});
diff --git a/server/sonar-web/src/main/js/source-viewer/source.js b/server/sonar-web/src/main/js/source-viewer/source.js
index 3db24bc9fb8..168a86bb9c2 100644
--- a/server/sonar-web/src/main/js/source-viewer/source.js
+++ b/server/sonar-web/src/main/js/source-viewer/source.js
@@ -26,6 +26,7 @@ define(function () {
return {
hasSource: false,
hasCoverage: false,
+ hasITCoverage: false,
hasDuplications: false,
hasSCM: false,
@@ -63,7 +64,7 @@ define(function () {
d.blocks.forEach(function (b) {
if (b._ref === '1') {
var lineFrom = b.from,
- lineTo = b.from + b.size;
+ lineTo = b.from + b.size - 1;
if (line.line >= lineFrom && line.line <= lineTo) {
duplicated = true;
}
@@ -88,6 +89,18 @@ define(function () {
});
}
this.set({ hasDuplications: hasDuplications });
+ },
+
+ hasUTCoverage: function (source) {
+ return _.some(source, function (line) {
+ return line.utCoverageStatus != null;
+ });
+ },
+
+ hasITCoverage: function (source) {
+ return _.some(source, function (line) {
+ return line.itCoverageStatus != null;
+ });
}
});
diff --git a/server/sonar-web/src/main/js/source-viewer/viewer.js b/server/sonar-web/src/main/js/source-viewer/viewer.js
index afa3169941b..d177c92d9a3 100644
--- a/server/sonar-web/src/main/js/source-viewer/viewer.js
+++ b/server/sonar-web/src/main/js/source-viewer/viewer.js
@@ -168,15 +168,29 @@ define([
};
},
- getCoverageStatus: function (row) {
+ getUTCoverageStatus: function (row) {
var status = null;
- if (row.lineHits > 0) {
+ if (row.utLineHits > 0) {
status = 'partially-covered';
}
- if (row.lineHits > 0 && row.conditions === row.coveredConditions) {
+ if (row.utLineHits > 0 && row.utConditions === row.utCoveredConditions) {
status = 'covered';
}
- if (row.lineHits === 0 || row.coveredConditions === 0) {
+ if (row.utLineHits === 0 || row.utCoveredConditions === 0) {
+ status = 'uncovered';
+ }
+ return status;
+ },
+
+ getItCoverageStatus: function (row) {
+ var status = null;
+ if (row.itLineHits > 0) {
+ status = 'partially-covered';
+ }
+ if (row.itLineHits > 0 && row.itConditions === row.itCoveredConditions) {
+ status = 'covered';
+ }
+ if (row.itLineHits === 0 || row.itCoveredConditions === 0) {
status = 'uncovered';
}
return status;
@@ -192,12 +206,17 @@ define([
source.unshift({line: 0});
}
source = source.map(function (row) {
- return _.extend(row, { coverageStatus: that.getCoverageStatus(row) });
+ return _.extend(row, {
+ utCoverageStatus: that.getUTCoverageStatus(row),
+ itCoverageStatus: that.getItCoverageStatus(row)
+ });
});
var firstLine = _.first(source).line,
linesRequested = options.to - options.from + 1;
that.model.set({
source: source,
+ hasUTCoverage: that.model.hasUTCoverage(source),
+ hasITCoverage: that.model.hasITCoverage(source),
hasSourceBefore: firstLine > 1,
hasSourceAfter: data.sources.length === linesRequested
});
@@ -227,7 +246,7 @@ define([
d.blocks.forEach(function (b) {
if (b._ref === '1') {
var lineFrom = b.from,
- lineTo = b.from + b.size;
+ lineTo = b.from + b.size - 1;
for (var j = lineFrom; j <= lineTo; j++) {
duplications[j] = true;
}
@@ -372,7 +391,7 @@ define([
$('body').click();
this.clearTooltips();
var line = $(e.currentTarget).data('line-number'),
- row = _.findWhere(this.model.get('source'), {line: line}),
+ row = _.findWhere(this.model.get('source'), { line: line }),
url = baseUrl + '/api/tests/test_cases',
options = {
uuid: this.model.id,
@@ -382,6 +401,7 @@ define([
var popup = new CoveragePopupView({
model: new Backbone.Model(data),
row: row,
+ tests: $(e.currentTarget).data('tests'),
triggerEl: $(e.currentTarget)
});
popup.render();
@@ -566,10 +586,15 @@ define([
source.unshift({line: 0});
}
source = source.map(function (row) {
- return _.extend(row, { coverageStatus: that.getCoverageStatus(row) });
+ return _.extend(row, {
+ utCoverageStatus: that.getUTCoverageStatus(row),
+ itCoverageStatus: that.getItCoverageStatus(row)
+ });
});
that.model.set({
source: source,
+ hasUTCoverage: that.model.hasUTCoverage(source),
+ hasITCoverage: that.model.hasITCoverage(source),
hasSourceBefore: (data.sources.length === that.LINES_AROUND) && (_.first(source).line > 0)
});
that.addIssuesPerLineMeta(that.issues);
@@ -604,10 +629,15 @@ define([
that.model.set({ hasSourceBefore: true });
}
source = source.map(function (row) {
- return _.extend(row, { coverageStatus: that.getCoverageStatus(row) });
+ return _.extend(row, {
+ utCoverageStatus: that.getUTCoverageStatus(row),
+ itCoverageStatus: that.getItCoverageStatus(row)
+ });
});
that.model.set({
source: source,
+ hasUTCoverage: that.model.hasUTCoverage(source),
+ hasITCoverage: that.model.hasITCoverage(source),
hasSourceAfter: data.sources.length === that.LINES_AROUND
});
that.addIssuesPerLineMeta(that.issues);
diff --git a/server/sonar-web/src/main/js/tests/e2e/views/layouts/main.jade b/server/sonar-web/src/main/js/tests/e2e/views/layouts/main.jade
deleted file mode 100644
index 37b905874c7..00000000000
--- a/server/sonar-web/src/main/js/tests/e2e/views/layouts/main.jade
+++ /dev/null
@@ -1,26 +0,0 @@
-html
- head
- meta(http-equiv='Content-Type', content='text/html; charset=UTF-8')
- link(href='/css/sonar.css', rel='stylesheet', media='all')
- script(src='/js/sonar.js')
- script(src='/js/third-party/jquery.mockjax.js')
- script.
- var baseUrl = '';
- var $j = jQuery.noConflict();
- window.suppressTranslationWarnings = true;
- jQuery.mockjaxSettings.contentType = 'text/json';
- jQuery.mockjaxSettings.responseTime = 50;
- jQuery.mockjaxSettings.throwUnmocked = true;
- $j(document).ready(function () { $j('.open-modal').modal(); });
- window.waitForMocks = function (app) {
- var x = setInterval(function () {
- jQuery.get('/api/l10n/index').done(function () {
- clearInterval(x);
- require([app]);
- });
- }, 500);
- }
- block header
- body
- #body
- block body
diff --git a/server/sonar-web/src/main/js/widgets/bubble-chart.js b/server/sonar-web/src/main/js/widgets/bubble-chart.js
index 1e5860a4f9f..d8f3377dbd6 100644
--- a/server/sonar-web/src/main/js/widgets/bubble-chart.js
+++ b/server/sonar-web/src/main/js/widgets/bubble-chart.js
@@ -208,7 +208,27 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
.style('stroke', function () {
return widget.bubbleColor();
})
- .style('transition', 'all 0.2s ease');
+ .style('transition', 'all 0.2s ease')
+
+ .attr('title', function (d) {
+ var xMetricName = widget.metrics()[widget.xMetric].name,
+ yMetricName = widget.metrics()[widget.yMetric].name,
+ sizeMetricName = widget.metrics()[widget.sizeMetric].name,
+
+ xMetricValue = d.measures[widget.xMetric].fval,
+ yMetricValue = d.measures[widget.yMetric].fval,
+ sizeMetricValue = d.measures[widget.sizeMetric].fval;
+
+ return '<div class="text-left">' +
+ collapsedDirFromPath(d.longName) + '<br>' +
+ fileFromPath(d.longName) + '<br>' + '<br>' +
+ xMetricName + ': ' + xMetricValue + '<br>' +
+ yMetricName + ': ' + yMetricValue + '<br>' +
+ sizeMetricName + ': ' + sizeMetricValue +
+ '</div>';
+ })
+ .attr('data-placement', 'bottom')
+ .attr('data-toggle', 'tooltip');
this.items.exit().remove();
@@ -224,43 +244,13 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
.on('click', function (d) {
window.location = widget.options().baseUrl + '?id=' + encodeURIComponent(d.key);
})
- .on('mouseenter', function (d) {
+ .on('mouseenter', function () {
d3.select(this).select('circle')
.style('fill-opacity', 0.8);
-
- widget.infoDate.text(d.longName);
-
- var metricLineList = [
- {
- metric: widget.metrics()[widget.xMetric].name,
- value: d.measures[widget.xMetric].fval
- },
- {
- metric: widget.metrics()[widget.yMetric].name,
- value: d.measures[widget.yMetric].fval
- },
- {
- metric: widget.metrics()[widget.sizeMetric].name,
- value: (!!d.measures[widget.sizeMetric] ? d.measures[widget.sizeMetric].fval : '–')
- }
- ];
-
- var lastX = 0;
- widget.infoMetrics
- .data(metricLineList)
- .text(function(m) { return m.metric + ': ' + m.value; })
- .attr('transform', function(d2, i) {
- var posX = lastX;
- lastX += widget.infoMetricWidth[i];
- return trans(posX, 20);
- });
})
.on('mouseleave', function () {
d3.select(this).select('circle')
.style('fill-opacity', 0.2);
-
- widget.infoDate.text('');
- widget.infoMetrics.text('');
});
};
@@ -302,26 +292,6 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
this.gGrid.selectAll('line')
.style('stroke', '#000')
.style('stroke-opacity', 0.25);
-
-
- // Configure info placeholders
- this.infoWrap
- .attr('transform', trans(-this.margin().left, -this.margin().top + 20));
-
- this.infoDate
- .style('text-anchor', 'start')
- .style('font-weight', 'bold');
-
- var metricLines = [this.metrics().x, this.metrics().y, this.metrics().size];
- this.infoMetrics = this.infoWrap.selectAll('.metric')
- .data(metricLines);
- this.infoMetrics.enter().append('text').attr('class', 'metric info-text-small')
- .text(function(d) { return d; });
- this.infoMetricWidth = [];
- this.infoMetrics.each(function() {
- widget.infoMetricWidth.push(this.getComputedTextLength() + 140);
- });
- this.infoMetrics.text('');
};
@@ -342,9 +312,10 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
this.initBubbleEvents();
this.initAxes();
this.initGrid();
-
this.update(containerS);
+ jQuery('[data-toggle="tooltip"]').tooltip({ container: 'body', html: true });
+
return this;
};
@@ -542,7 +513,7 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
window.SonarWidgets.BubbleChart.defaults = {
width: 350,
height: 150,
- margin: { top: 60, right: 10, bottom: 50, left: 70 },
+ margin: { top: 10, right: 10, bottom: 50, left: 70 },
xLog: false,
yLog: false,
bubbleColor: '#4b9fd5',
diff --git a/server/sonar-web/src/main/js/widgets/issue-filter.js b/server/sonar-web/src/main/js/widgets/issue-filter.js
new file mode 100644
index 00000000000..c8d27bf5196
--- /dev/null
+++ b/server/sonar-web/src/main/js/widgets/issue-filter.js
@@ -0,0 +1,296 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+define(['templates/widgets'], function () {
+
+ var $ = jQuery,
+ defaultComparator = function (item) {
+ return -item.count;
+ },
+ defaultFilter = function (item) {
+ var items = this.query[this.property];
+ return items == null ||
+ (items != null && items.split(',').indexOf(item.val) !== -1);
+ },
+ defaultLabel = function (item) {
+ return item.val;
+ },
+ defaultLink = function (item, property, query) {
+ var criterion = {};
+ criterion[property] = item.val;
+ var r = _.extend({}, query, criterion);
+ if (r.componentKey != null) {
+ return baseUrl + '/component_issues/index?id=' + encodeURIComponent(r.componentKey) +
+ '#' + getQuery(_.omit(r, 'componentKey'));
+ } else {
+ return baseUrl + '/issues/search#' + getQuery(r);
+ }
+ },
+ byDistributionConf = {
+ 'severities': {
+ template: 'widget-issue-filter-severities',
+ comparator: function (item) {
+ var order = ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO'];
+ return order.indexOf(item.val);
+ }
+ },
+ 'statuses': {
+ template: 'widget-issue-filter-statuses',
+ comparator: function (item) {
+ var order = ['OPEN', 'REOPENED', 'CONFIRMED', 'RESOLVED', 'CLOSED'];
+ return order.indexOf(item.val);
+ }
+ },
+ 'resolutions': {
+ template: 'widget-issue-filter-resolutions',
+ comparator: function (item) {
+ var order = ['', 'FALSE-POSITIVE', 'WONTFIX', 'FIXED', 'REMOVED'];
+ return order.indexOf(item.val);
+ },
+ filter: function (item) {
+ if ('' + this.query.resolved === 'false') {
+ return item.val === '';
+ } else {
+ return defaultFilter.call(this, item);
+ }
+ }
+ },
+ 'rules': {
+ label: function (item, r) {
+ if (_.isArray(r.rules)) {
+ var rule = _.findWhere(r.rules, { key: item.val });
+ if (rule != null) {
+ return rule.name;
+ }
+ }
+ }
+ },
+ 'projectUuids': {
+ label: function (item, r) {
+ if (_.isArray(r.projects)) {
+ var project = _.findWhere(r.projects, { uuid: item.val });
+ if (project != null) {
+ return project.name;
+ }
+ }
+ }
+ },
+ 'assignees': {
+ template: 'widget-issue-filter-assignees',
+ label: function (item, r) {
+ if (_.isArray(r.users)) {
+ var user = _.findWhere(r.users, { login: item.val });
+ if (user != null) {
+ return user.name;
+ }
+ }
+ },
+ filter: function (item) {
+ if ('' + this.query.assigned === 'false') {
+ return item.val === '';
+ } else {
+ return defaultFilter.call(this, item);
+ }
+ }
+ },
+ 'languages': {
+ label: function (item, r) {
+ if (_.isArray(r.languages)) {
+ var lang = _.findWhere(r.languages, { key: item.val });
+ if (lang != null) {
+ return lang.name;
+ }
+ }
+ }
+ },
+ 'actionPlans': {
+ template: 'widget-issue-filter-action-plans',
+ label: function (item, r) {
+ if (_.isArray(r.actionPlans)) {
+ var actionPlan = _.findWhere(r.actionPlans, { key: item.val });
+ if (actionPlan != null) {
+ return actionPlan.name;
+ }
+ }
+ },
+ filter: function (item) {
+ if ('' + this.query.planned === 'false') {
+ return item.val === '';
+ } else {
+ return defaultFilter.call(this, item);
+ }
+ }
+ },
+ 'createdAt': {
+ comparator: function (item) {
+ return moment(item.val).toDate();
+ },
+ label: function (item, r, items, index, query) {
+ var beginning = moment(item.val),
+ endDate = query.createdBefore != null ? moment(query.createdBefore) : moment(),
+ ending = index < items.length - 1 ? moment(items[index + 1].val).subtract(1, 'days') : endDate,
+ isSameDay = ending.diff(beginning, 'days') <= 1;
+ return beginning.format('LL') + (isSameDay ? '' : (' – ' + ending.format('LL')));
+ },
+ link: function (item, property, query, index, items) {
+ var createdAfter = moment(item.val),
+ endDate = query.createdBefore != null ? moment(query.createdBefore) : moment(),
+ createdBefore = index < items.length - 1 ? moment(items[index + 1].val).subtract(1, 'days') : endDate,
+ isSameDay = createdBefore.diff(createdAfter, 'days') <= 1;
+ if (isSameDay) {
+ createdBefore.add(1, 'days');
+ }
+ var r = _.extend({}, query, {
+ createdAfter: createdAfter.format('YYYY-MM-DD'),
+ createdBefore: createdBefore.format('YYYY-MM-DD')
+ });
+ if (r.componentKey != null) {
+ return baseUrl + '/component_issues/index?id=' + encodeURIComponent(r.componentKey) +
+ '#' + getQuery(_.omit(r, 'componentKey'));
+ } else {
+ return baseUrl + '/issues/search#' + getQuery(r);
+ }
+ }
+ }
+ };
+
+ function getQuery (query, separator) {
+ separator = separator || '|';
+ var route = [];
+ _.forEach(query, function (value, property) {
+ route.push('' + property + '=' + encodeURIComponent(value));
+ });
+ return route.join(separator);
+ }
+
+ Handlebars.registerHelper('issueFilterItemLink', function (query, property, value) {
+ var criterion = {};
+ criterion[property] = value;
+ var r = _.extend({}, query, criterion);
+ if (r.componentKey != null) {
+ return baseUrl + '/component_issues/index?id=' + encodeURIComponent(r.componentKey) +
+ '#' + getQuery(_.omit(r, 'componentKey'));
+ } else {
+ return baseUrl + '/issues/search#' + getQuery(r);
+ }
+ });
+
+ Handlebars.registerHelper('issueFilterTotalLink', function (query) {
+ var r = _.extend({}, query);
+ if (r.componentKey != null) {
+ return baseUrl + '/component_issues/index?id=' + encodeURIComponent(r.componentKey) +
+ '#' + getQuery(_.omit(r, 'componentKey'));
+ } else {
+ return baseUrl + '/issues/search#' + getQuery(r);
+ }
+ });
+
+ return Marionette.ItemView.extend({
+
+ getTemplate: function () {
+ var template = this.conf != null && this.conf.template != null ? this.conf.template : 'widget-issue-filter';
+ return Templates[template];
+ },
+
+ initialize: function () {
+ this.model = new Backbone.Model({
+ query: this.options.query,
+ parsedQuery: this.getParsedQuery(),
+ property: this.options.distributionAxis,
+ periodDate: this.options.periodDate
+ });
+ this.listenTo(this.model, 'change', this.render);
+ this.conf = byDistributionConf[this.options.distributionAxis];
+ this.query = this.getParsedQuery();
+ this.requestIssues();
+ },
+
+ getParsedQuery: function () {
+ var queryString = this.options.query || '',
+ query = {};
+ queryString.split('|').forEach(function (criterionString) {
+ var criterion = criterionString.split('=');
+ if (criterion.length === 2) {
+ query[criterion[0]] = criterion[1];
+ }
+ });
+ if (this.options.componentKey != null) {
+ _.extend(query, { componentKey: this.options.componentKey });
+ }
+ if (this.options.periodDate != null) {
+ _.extend(query, { createdAfter: this.options.periodDate });
+ }
+ return query;
+ },
+
+ sortItems: function (items) {
+ var comparator = this.conf != null && this.conf.comparator != null ? this.conf.comparator : defaultComparator;
+ return _.sortBy(items, comparator);
+ },
+
+ filterItems: function (items) {
+ var filter = this.conf != null && this.conf.filter != null ? this.conf.filter : defaultFilter;
+ return _.filter(items, filter, { query: this.query, property: this.options.distributionAxis });
+ },
+
+ withLink: function (items) {
+ var link = this.conf != null && this.conf.link != null ? this.conf.link : defaultLink,
+ property = this.options.distributionAxis,
+ query = this.model.get('parsedQuery');
+ return items.map(function (item, index) {
+ return _.extend(item, { searchLink: link(item, property, query, index, items) });
+ });
+ },
+
+ withLabels: function (items) {
+ var label = this.conf != null && this.conf.label != null ? this.conf.label : defaultLabel,
+ r = this.model.get('rawResponse'),
+ query = this.model.get('parsedQuery');
+ return items.map(function (item, index) {
+ return _.extend(item, { label: label(item, r, items, index, query) });
+ });
+ },
+
+ requestIssues: function () {
+ var that = this,
+ url = baseUrl + '/api/issues/search',
+ options = _.extend({}, this.query, {
+ ps: 1,
+ facets: this.options.distributionAxis
+ });
+ if (this.options.componentUuid != null) {
+ _.extend(options, { componentUuids: this.options.componentUuid });
+ }
+ if (this.options.periodDate != null) {
+ _.extend(options, { createdAfter: this.options.periodDate });
+ }
+ return $.get(url, options).done(function (r) {
+ if (_.isArray(r.facets) && r.facets.length === 1) {
+ // save response object, but do not trigger repaint
+ that.model.set({ rawResponse: r }, { silent: true });
+ that.model.set({
+ items: that.sortItems(that.withLabels(that.withLink(that.filterItems(r.facets[0].values)))),
+ total: r.total
+ });
+ }
+ });
+ }
+ });
+
+});
diff --git a/server/sonar-web/src/main/less/init/misc.less b/server/sonar-web/src/main/less/init/misc.less
index f8b31448f3d..3dc7e5df1ec 100644
--- a/server/sonar-web/src/main/less/init/misc.less
+++ b/server/sonar-web/src/main/less/init/misc.less
@@ -103,3 +103,19 @@ td.spacer-top {
.bordered-top {
border-top: 1px solid @barBorderColor;
}
+
+.zero-font-size {
+ font-size: 0 !important;
+}
+
+.width-100 {
+ width: 100%;
+}
+
+.width-80 {
+ width: 80%;
+}
+
+.width-60 {
+ width: 60%;
+}
diff --git a/server/sonar-web/src/main/less/init/tables.less b/server/sonar-web/src/main/less/init/tables.less
index afca8360a88..aca9725e965 100644
--- a/server/sonar-web/src/main/less/init/tables.less
+++ b/server/sonar-web/src/main/less/init/tables.less
@@ -53,8 +53,9 @@ table.data > tfoot > tr > td {
}
table.data > tbody > tr > td {
- padding: 5px;
+ padding: 4px 5px;
vertical-align: text-top;
+ line-height: 20px;
}
table.data td.small, table.data th.small {
diff --git a/server/sonar-web/src/main/less/pages/dashboard.less b/server/sonar-web/src/main/less/pages/dashboard.less
index 8dc8cfdffe6..84fd6334170 100644
--- a/server/sonar-web/src/main/less/pages/dashboard.less
+++ b/server/sonar-web/src/main/less/pages/dashboard.less
@@ -325,22 +325,6 @@
.widget-span-11 { width: 91.666666666667%; }
.widget-span-12 { width: 100%; }
-@media (max-width: 1279px) {
- .widget-span-1 { width: 50%; }
- .widget-span-2 { width: 50%; }
- .widget-span-3 { width: 50%; }
- .widget-span-3-5 { width: 50%; }
- .widget-span-4 { width: 50%; }
- .widget-span-5 { width: 50%; }
- .widget-span-6 { width: 50%; }
- .widget-span-7 { width: 100%; }
- .widget-span-8 { width: 100%; }
- .widget-span-9 { width: 100%; }
- .widget-span-10 { width: 100%; }
- .widget-span-11 { width: 100%; }
- .widget-span-12 { width: 100%; }
-}
-
.widget-label {
display: block;
font-size: @baseFontSize;
diff --git a/server/sonar-web/src/main/less/style.less b/server/sonar-web/src/main/less/style.less
index 5278454f452..806d57bfc2c 100644
--- a/server/sonar-web/src/main/less/style.less
+++ b/server/sonar-web/src/main/less/style.less
@@ -707,7 +707,8 @@ div.barchart {
}
div.barchart > div {
- background-color: @darkBlue;
+ min-width: 1px;
+ background-color: #c4d6e1;
height: 0.9em;
}
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb
index 3ac6eba4b8d..79b88b22bb0 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb
@@ -268,7 +268,8 @@ class ProfilesController < ApplicationController
require_parameters 'key'
@profile = Internal.qprofile_loader.getByKey(params[:key])
- search = {'profileKeys' => @profile.key().to_s, 'since' => params[:since], 'to' => params[:to], 'p' => params[:p]}
+ not_found('Quality profile does not exist') unless @profile
+ search = {'profileKey' => @profile.key().to_s, 'since' => params[:since], 'to' => params[:to], 'p' => params[:p]}
result = Internal.component(Java::OrgSonarServerActivity::RubyQProfileActivityService.java_class).search(search)
@changes = result.activities
@paging = result.paging
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/helpers/application_helper.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/helpers/application_helper.rb
index 881b85429c9..c1eb79b9028 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/helpers/application_helper.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/helpers/application_helper.rb
@@ -614,7 +614,7 @@ module ApplicationHelper
def select2_tag(name, ws_url, options={})
width=options[:width]||'250px'
- html_id=options[:html_id]||name
+ html_id=options[:html_id]||sanitize_to_id(name).gsub('.', '_')
html_class=options[:html_class]||''
min_length=options[:min_length]
@@ -764,7 +764,7 @@ module ApplicationHelper
if user
# the login is a string so it have to be surrounded by quote to be taken in account by select2
options[:selected_id]="'" + user.login + "'"
- options[:selected_text]=user.name
+ options[:selected_text]=user.name + ' (' + user.login + ')'
end
select2_tag(name, ws_url, options)
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/helpers/properties_helper.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/helpers/properties_helper.rb
index 34fd3326d7e..55c546244d7 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/helpers/properties_helper.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/helpers/properties_helper.rb
@@ -104,6 +104,10 @@ module PropertiesHelper
end
select_tag name, select_options, html_options
+ when PropertyType::TYPE_USER_LOGIN
+ user = User.find_active_by_login(value)
+ user_select_tag name, {:size => options[:size] || 50, :selected_user => user, :allow_empty => true, :include_choices => [ ['', message('none')] ] }.update(html_options)
+
else
hidden_field_tag id, html_options
end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/models/project_measure.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/models/project_measure.rb
index d6aad6e798b..ca542e4b687 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/models/project_measure.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/models/project_measure.rb
@@ -274,7 +274,7 @@ class ProjectMeasure < ActiveRecord::Base
end
def visible?(period)
- ! (value.nil? && variation(period).nil?)
+ !(text_value.nil? && value.nil? && variation(period).nil?)
end
end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/models/property_type.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/models/property_type.rb
index 332096471b3..9c890604ca5 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/models/property_type.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/models/property_type.rb
@@ -32,6 +32,7 @@ class PropertyType
TYPE_FILTER = 'FILTER'
# Since 3.7
TYPE_ISSUE_FILTER = 'ISSUE_FILTER'
+ TYPE_USER_LOGIN = 'USER_LOGIN'
def self.text_to_value(text, type)
case type
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/profiles/changelog.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/profiles/changelog.html.erb
index 035bf52d2d5..f807ae791c2 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/profiles/changelog.html.erb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/profiles/changelog.html.erb
@@ -37,19 +37,19 @@
%>
<tr class="<%= cycle('even', 'odd') -%>">
<%
- action = change.action()
+ action = change.getAction()
action_message = message('quality_profiles.changelog.' + action.downcase) if action
if change.authorName() && !change.authorName().empty?()
author = change.authorName()
- elsif change.login() && !change.login().empty?()
- author = change.login()
+ elsif change.login() && !change.getLogin().empty?()
+ author = change.getLogin()
else
author = 'System'
end
rule = change.ruleName() ? change.ruleName() : change.ruleKey()
%>
- <td valign="top" width="1%" nowrap><%= Internal.i18n.formatDateTime(change.time()) -%></td>
+ <td valign="top" width="1%" nowrap><%= Internal.i18n.formatDateTime(change.getCreatedAt()) -%></td>
<td valign="top" width="1%" nowrap><%= author %></td>
<td valign="top" width="1%" nowrap><%= action_message %></td>
<td valign="top"><%= rule %></td>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/settings/_type_USER_LOGIN.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/settings/_type_USER_LOGIN.html.erb
new file mode 100644
index 00000000000..6f94fa6a651
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/settings/_type_USER_LOGIN.html.erb
@@ -0,0 +1,5 @@
+<%
+ options = {:id => id}
+ options[:size] = (defined? size) ? size : nil
+%>
+<%= property_input_field(name, PropertyType::TYPE_USER_LOGIN, value, PropertiesHelper::SCREEN_SETTINGS, options) %>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/796_add_uuid_to_analysis_reports.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/796_add_uuid_to_analysis_reports.rb
new file mode 100644
index 00000000000..06fba16976d
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/796_add_uuid_to_analysis_reports.rb
@@ -0,0 +1,32 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+
+#
+# SonarQube 5.1
+#
+class AddUuidToAnalysisReports < ActiveRecord::Migration
+
+ def self.up
+ add_column 'analysis_reports', 'uuid', :string, :limit => 50, :null => false
+ remove_column 'analysis_reports', 'report_data'
+ remove_column 'analysis_reports', 'snapshot_id'
+ end
+
+end
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet.js b/server/sonar-web/src/test/js/coding-rules-page-active-severity-facet.js
index bfaebe66cca..a0a1e371875 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-active-severity-facet.js
@@ -78,6 +78,10 @@ casper.test.begin('coding-rules-page-active-severity-facet', 7, function (test)
test.assertExists('.search-navigator-facet-box-forbidden[data-property="active_severities"]');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-available-since.js b/server/sonar-web/src/test/js/coding-rules-page-available-since.js
index e13424e5cfe..e55b457d214 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-available-since.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-available-since.js
@@ -58,6 +58,10 @@ casper.test.begin('coding-rules-page-available-since', 2, function (test) {
test.assertSelectorContains('#coding-rules-total', '101');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet.js b/server/sonar-web/src/test/js/coding-rules-page-inheritance-facet.js
index 6208f9c7d27..64cb89a71ef 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-inheritance-facet.js
@@ -101,6 +101,10 @@ casper.test.begin('coding-rules-page-inheritance-facet', 11, function (test) {
test.assertExists('.search-navigator-facet-box-forbidden[data-property="inheritance"]');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-no-available-profiles-for-activation.js b/server/sonar-web/src/test/js/coding-rules-page-no-available-profiles-for-activation.js
index 5dc7f305251..a7ad36f86f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-no-available-profiles-for-activation.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-no-available-profiles-for-activation.js
@@ -58,6 +58,10 @@ casper.test.begin('coding-rules-page-no-available-profiles-for-activation', 2, f
test.assertExists('.modal .message-notice');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet.js b/server/sonar-web/src/test/js/coding-rules-page-quality-profile-facet.js
index 44c30ebd91d..3d2d55ac40d 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-quality-profile-facet.js
@@ -73,6 +73,10 @@ casper.test.begin('coding-rules-page-quality-profile-facet', 6, function (test)
test.assertSelectorContains('#coding-rules-total', '609');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-query-facet.js b/server/sonar-web/src/test/js/coding-rules-page-query-facet.js
index f0710781f88..e64cf5db6ef 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-query-facet.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-query-facet.js
@@ -63,6 +63,10 @@ casper.test.begin('coding-rules-page-query-facet', 3, function (test) {
test.assertSelectorContains('#coding-rules-total', '609');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-rule-should-have-permalink.js b/server/sonar-web/src/test/js/coding-rules-page-rule-should-have-permalink.js
index 37b89e68bc6..38da7b7afa2 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-rule-should-have-permalink.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-rule-should-have-permalink.js
@@ -51,6 +51,10 @@ casper.test.begin('coding-rules-page-rule-permalink', 1, function (test) {
test.assertExists('a[href="/coding_rules#rule_key=squid%3AS1181"]');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile.js b/server/sonar-web/src/test/js/coding-rules-page-should-activate-profile.js
index d0ac3bd3f29..e354b98f60f 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-activate-profile.js
@@ -69,6 +69,10 @@ casper.test.begin('coding-rules-page-should-activate-profile', 5, function (test
test.assertExists('.coding-rules-detail-quality-profile-deactivate');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules.js b/server/sonar-web/src/test/js/coding-rules-page-should-create-custom-rules.js
index ab36a367844..fac972fa626 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-create-custom-rules.js
@@ -70,6 +70,10 @@ casper.test.begin('coding-rules-page-should-delete-create-rules', 2, function (t
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-manual-rules.js b/server/sonar-web/src/test/js/coding-rules-page-should-create-manual-rules.js
index b725c43e104..590304635df 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-manual-rules.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-create-manual-rules.js
@@ -65,6 +65,10 @@ casper.test.begin('coding-rules-page-should-delete-manual-rules', 3, function (t
test.assertSelectorContains('.coding-rules-detail-description', 'Manual Rule Description');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules.js b/server/sonar-web/src/test/js/coding-rules-page-should-delete-custom-rules.js
index 2c2609c7c7b..623c36e2961 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-delete-custom-rules.js
@@ -60,6 +60,10 @@ casper.test.begin('coding-rules-page-should-delete-custom-rules', 2, function (t
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules.js b/server/sonar-web/src/test/js/coding-rules-page-should-delete-manual-rules.js
index c0efd0bb72a..c4b590bec84 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-delete-manual-rules.js
@@ -65,6 +65,10 @@ casper.test.begin('coding-rules-page-should-delete-manual-rules', 1, function (t
test.assertSelectorContains('#coding-rules-total', 0);
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules.js b/server/sonar-web/src/test/js/coding-rules-page-should-show-custom-rules.js
index 6a17b1ed2d7..bcf5d43980a 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-show-custom-rules.js
@@ -57,6 +57,10 @@ casper.test.begin('coding-rules-page-should-show-custom-rules', 3, function (tes
'Do not use org.h2.util.StringUtils');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-deprecated-label.js b/server/sonar-web/src/test/js/coding-rules-page-should-show-deprecated-label.js
index 51d3be787a2..7c57c1a14dd 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-deprecated-label.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-show-deprecated-label.js
@@ -44,6 +44,10 @@ casper.test.begin('coding-rules-page-should-show-deprecated-label', 1, function
test.assertSelectorContains('.coding-rule.selected', 'DEPRECATED');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-details.js b/server/sonar-web/src/test/js/coding-rules-page-should-show-details.js
index b352b52c4d4..49bac8b4d6c 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-details.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-show-details.js
@@ -76,6 +76,10 @@ casper.test.begin('coding-rules-page-should-show-details', 20, function (test) {
test.assertSelectorContains('.coding-rules-detail-quality-profile-inheritance', 'Default - Top');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-empty-list.js b/server/sonar-web/src/test/js/coding-rules-page-should-show-empty-list.js
index d0e35952e5a..d918aa6d9d4 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-empty-list.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-show-empty-list.js
@@ -46,6 +46,10 @@ casper.test.begin('coding-rules-page-should-show-empty-list', 3, function (test)
test.assertExists('.search-navigator-no-results');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-facets.js b/server/sonar-web/src/test/js/coding-rules-page-should-show-facets.js
index 6f3fc0f889a..5f8b5a782b2 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-facets.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-show-facets.js
@@ -44,6 +44,10 @@ casper.test.begin('coding-rules-page-should-show-facets', 1, function (test) {
test.assertElementCount('.search-navigator-facet-box', 13);
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues.js b/server/sonar-web/src/test/js/coding-rules-page-should-show-rule-issues.js
index 70163ae8544..aa6474fd629 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-show-rule-issues.js
@@ -56,6 +56,10 @@ casper.test.begin('coding-rules-page-should-show-rule-issues', 5, function (test
test.assertSelectorContains('.coding-rules-most-violated-projects', '1');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule.js b/server/sonar-web/src/test/js/coding-rules-page-should-show-rule.js
index 5fa1cf0f220..1b3ab387566 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-show-rule.js
@@ -50,6 +50,10 @@ casper.test.begin('coding-rules-page-should-show-rule', 7, function (test) {
test.assertSelectorContains('.coding-rule.selected', 'custom-tag');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rules.js b/server/sonar-web/src/test/js/coding-rules-page-should-show-rules.js
index 869c03397c1..cde137ac09a 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rules.js
+++ b/server/sonar-web/src/test/js/coding-rules-page-should-show-rules.js
@@ -47,6 +47,10 @@ casper.test.begin('coding-rules-page-should-show-rules', 4, function (test) {
test.assertSelectorContains('#coding-rules-total', '609');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/design-spec.js b/server/sonar-web/src/test/js/design-spec.js
index d9938d4409a..d6989047711 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/design-spec.js
+++ b/server/sonar-web/src/test/js/design-spec.js
@@ -60,6 +60,10 @@ casper.test.begin(testName('Base'), function suite(test) {
test.assertSelectorContains('.dsm-info', 'src/main/java/com/maif/sonar/cobol/metrics/TableMetricsVisitor.java ');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/test/js/global-issue-filter-widget.js b/server/sonar-web/src/test/js/global-issue-filter-widget.js
new file mode 100644
index 00000000000..ac2f5f78acf
--- /dev/null
+++ b/server/sonar-web/src/test/js/global-issue-filter-widget.js
@@ -0,0 +1,853 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+/* globals casper: false */
+
+var lib = require('../lib'),
+ testName = lib.testName('Global Issue Filter Widget');
+
+
+lib.initMessages();
+lib.changeWorkingDirectory('global-issues-filter-widget');
+lib.configureCasper();
+
+
+casper.test.begin(testName('Unresolved Issues By Severity'), 13, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-severity.json',
+ { data: { resolved: 'false' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false',
+ distributionAxis: 'severities'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 6);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '6851');
+ test.assertSelectorContains('tr:nth-child(2)', '1');
+ test.assertSelectorContains('tr:nth-child(3)', '105');
+ test.assertSelectorContains('tr:nth-child(4)', '5027');
+ test.assertSelectorContains('tr:nth-child(5)', '540');
+ test.assertSelectorContains('tr:nth-child(6)', '1178');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|severities=BLOCKER"]');
+ test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|severities=CRITICAL"]');
+ test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|severities=MAJOR"]');
+ test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|severities=MINOR"]');
+ test.assertExists('tr:nth-child(6) a[href="/issues/search#resolved=false|severities=INFO"]');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Red Issues By Severity'), 9, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'red-issues-by-severity.json',
+ { data: { resolved: 'false', severities: 'BLOCKER,CRITICAL,MAJOR' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false|severities=BLOCKER,CRITICAL,MAJOR',
+ distributionAxis: 'severities'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 4);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '6851');
+ test.assertSelectorContains('tr:nth-child(2)', '1');
+ test.assertSelectorContains('tr:nth-child(3)', '105');
+ test.assertSelectorContains('tr:nth-child(4)', '5027');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|severities=BLOCKER%2CCRITICAL%2CMAJOR"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|severities=BLOCKER"]');
+ test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|severities=CRITICAL"]');
+ test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|severities=MAJOR"]');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('All Issues By Status'), 9, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'all-issues-by-status.json');
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: '',
+ distributionAxis: 'statuses'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 6);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '71571');
+ test.assertSelectorContains('tr:nth-child(2)', '238');
+ test.assertSelectorContains('tr:nth-child(3)', '4');
+ test.assertSelectorContains('tr:nth-child(4)', '6609');
+ test.assertSelectorContains('tr:nth-child(5)', '1307');
+ test.assertSelectorContains('tr:nth-child(6)', '63.4k');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#statuses=OPEN"]');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('All Issues By Resolution'), 10, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'all-issues-by-resolution.json');
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: '',
+ distributionAxis: 'resolutions'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 6);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '71571');
+ test.assertSelectorContains('tr:nth-child(2)', '6851');
+ test.assertSelectorContains('tr:nth-child(3)', '752');
+ test.assertSelectorContains('tr:nth-child(4)', '550');
+ test.assertSelectorContains('tr:nth-child(5)', '47.1k');
+ test.assertSelectorContains('tr:nth-child(6)', '16.3k');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false"]');
+ test.assertExists('tr:nth-child(3) a[href="/issues/search#resolutions=FALSE-POSITIVE"]');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Resolution'), 5, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-resolution.json',
+ { data: { resolved: 'false' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false',
+ distributionAxis: 'resolutions'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 2);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '6851');
+ test.assertSelectorContains('tr:nth-child(2)', '6851');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false"]');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Rule'), 15, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-rule.json',
+ { data: { resolved: 'false' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false',
+ distributionAxis: 'rules'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 16);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '6851');
+ test.assertSelectorContains('tr:nth-child(2)', '879');
+ test.assertSelectorContains('tr:nth-child(3)', '571');
+ test.assertSelectorContains('tr:nth-child(15)', '113');
+ test.assertSelectorContains('tr:nth-child(16)', '111');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|rules=squid%3AS1161"]');
+ test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|rules=squid%3AS1135"]');
+ test.assertExists('tr:nth-child(15) a[href="/issues/search#resolved=false|rules=squid%3AS1134"]');
+ test.assertExists('tr:nth-child(16) a[href="/issues/search#resolved=false|rules=squid%3AS1192"]');
+
+ // check labels
+ test.assertSelectorContains('tr:nth-child(2)', '@Override" annotation should be used');
+ test.assertSelectorContains('tr:nth-child(3)', 'TODO tags should be handled');
+ test.assertSelectorContains('tr:nth-child(15)', 'FIXME tags should be handled');
+ test.assertSelectorContains('tr:nth-child(16)', 'String literals should not be duplicated');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Project'), 15, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-project.json',
+ { data: { resolved: 'false' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false',
+ distributionAxis: 'projectUuids'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 5);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '2598');
+ test.assertSelectorContains('tr:nth-child(2)', '1766');
+ test.assertSelectorContains('tr:nth-child(3)', '442');
+ test.assertSelectorContains('tr:nth-child(4)', '283');
+ test.assertSelectorContains('tr:nth-child(5)', '107');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|projectUuids=69e57151-be0d-4157-adff-c06741d88879"]');
+ test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|projectUuids=dd7c3556-ce3f-42d0-a348-914a582dc944"]');
+ test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|projectUuids=5eab015a-1f76-4ba4-bd89-bf547132d673"]');
+ test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|projectUuids=c156940b-e3ec-43f6-9589-e3b75aa9ca32"]');
+
+ // check labels
+ test.assertSelectorContains('tr:nth-child(2)', 'SonarQube');
+ test.assertSelectorContains('tr:nth-child(3)', 'SonarQube Java');
+ test.assertSelectorContains('tr:nth-child(4)', 'JavaScript');
+ test.assertSelectorContains('tr:nth-child(5)', 'Python');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Assignee'), 15, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-assignee.json',
+ { data: { resolved: 'false' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false',
+ distributionAxis: 'assignees'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 5);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '6851');
+ test.assertSelectorContains('tr:nth-child(2)', '4134');
+ test.assertSelectorContains('tr:nth-child(3)', '698');
+ test.assertSelectorContains('tr:nth-child(4)', '504');
+ test.assertSelectorContains('tr:nth-child(5)', '426');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|assigned=false"]');
+ test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|assignees=first.user"]');
+ test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|assignees=second.user"]');
+ test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|assignees=third.user"]');
+
+ // check labels
+ test.assertSelectorContains('tr:nth-child(2)', 'unassigned');
+ test.assertSelectorContains('tr:nth-child(3)', 'First User');
+ test.assertSelectorContains('tr:nth-child(4)', 'Second User');
+ test.assertSelectorContains('tr:nth-child(5)', 'Third User');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Unresolved Unassigned Issues By Assignee'), 6, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-unassigned-issues-by-assignee.json',
+ { data: { resolved: 'false', assigned: 'false' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false|assigned=false',
+ distributionAxis: 'assignees'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 2);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '4134');
+ test.assertSelectorContains('tr:nth-child(2)', '4134');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|assigned=false"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|assigned=false"]');
+
+ // check labels
+ test.assertSelectorContains('tr:nth-child(2)', 'unassigned');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Language'), 15, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-language.json',
+ { data: { resolved: 'false' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false',
+ distributionAxis: 'languages'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 5);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '6851');
+ test.assertSelectorContains('tr:nth-child(2)', '6336');
+ test.assertSelectorContains('tr:nth-child(3)', '444');
+ test.assertSelectorContains('tr:nth-child(4)', '22');
+ test.assertSelectorContains('tr:nth-child(5)', '15');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|languages=java"]');
+ test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|languages=py"]');
+ test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|languages=php"]');
+ test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|languages=js"]');
+
+ // check labels
+ test.assertSelectorContains('tr:nth-child(2)', 'Java');
+ test.assertSelectorContains('tr:nth-child(3)', 'Python');
+ test.assertSelectorContains('tr:nth-child(4)', 'PHP');
+ test.assertSelectorContains('tr:nth-child(5)', 'JavaScript');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Action Plan'), 15, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-action-plan.json',
+ { data: { resolved: 'false' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false',
+ distributionAxis: 'actionPlans'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 5);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '6851');
+ test.assertSelectorContains('tr:nth-child(2)', '5877');
+ test.assertSelectorContains('tr:nth-child(3)', '532');
+ test.assertSelectorContains('tr:nth-child(4)', '56');
+ test.assertSelectorContains('tr:nth-child(5)', '52');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|planned=false"]');
+ test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|actionPlans=0cf48508-2fcd-4cb8-a50b-c5cd7c3decc0"]');
+ test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|actionPlans=1b9e7e52-ff58-40c1-80bf-f68429a3275e"]');
+ test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|actionPlans=8c1d5d01-948e-4670-a0d9-17c512979486"]');
+
+ // check labels
+ test.assertSelectorContains('tr:nth-child(2)', 'unplanned');
+ test.assertSelectorContains('tr:nth-child(3)', 'First Action Plan');
+ test.assertSelectorContains('tr:nth-child(4)', 'Second Action Plan');
+ test.assertSelectorContains('tr:nth-child(5)', 'Third Action Plan');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Unresolved Unplanned Issues By Action Plan'), 6, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-unplanned-issues-by-action-plan.json',
+ { data: { resolved: 'false', planned: 'false' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false|planned=false',
+ distributionAxis: 'actionPlans'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 2);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '5877');
+ test.assertSelectorContains('tr:nth-child(2)', '5877');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|planned=false"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|planned=false"]');
+
+ // check labels
+ test.assertSelectorContains('tr:nth-child(2)', 'unplanned');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Date'), 18, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-date.json',
+ { data: { resolved: 'false' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false',
+ distributionAxis: 'createdAt'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 6);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '6851');
+ test.assertSelectorContains('tr:nth-child(2)', '72');
+ test.assertSelectorContains('tr:nth-child(3)', '64');
+ test.assertSelectorContains('tr:nth-child(4)', '1262');
+ test.assertSelectorContains('tr:nth-child(5)', '3729');
+ test.assertSelectorContains('tr:nth-child(6)', '1724');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|createdAfter=2011-01-01|createdBefore=2011-12-31"]');
+ test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|createdAfter=2012-01-01|createdBefore=2012-12-31"]');
+ test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|createdAfter=2013-01-01|createdBefore=2013-12-31"]');
+ test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|createdAfter=2014-01-01|createdBefore=2014-12-31"]');
+ // do not check createdBefore value, because it is set dynamically to *now*
+ test.assertExists('tr:nth-child(6) a[href^="/issues/search#resolved=false|createdAfter=2015-01-01|createdBefore="]');
+
+ // check labels
+ test.assertSelectorContains('tr:nth-child(2)', 'January 1 2011 – December 31 2011');
+ test.assertSelectorContains('tr:nth-child(3)', 'January 1 2012 – December 31 2012');
+ test.assertSelectorContains('tr:nth-child(4)', 'January 1 2013 – December 31 2013');
+ test.assertSelectorContains('tr:nth-child(5)', 'January 1 2014 – December 31 2014');
+ // do not check label fully, because it is set dynamically using *now*
+ test.assertSelectorContains('tr:nth-child(6)', 'January 1 2015 – ');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Unresolved Issues on a Limited Period By Date'), 12, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-date-limited.json',
+ { data: { resolved: 'false', createdAfter: '2015-02-16', createdBefore: '2015-02-18' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false|createdAfter=2015-02-16|createdBefore=2015-02-18',
+ distributionAxis: 'createdAt'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 4);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '6851');
+ test.assertSelectorContains('tr:nth-child(2)', '49');
+ test.assertSelectorContains('tr:nth-child(3)', '48');
+ test.assertSelectorContains('tr:nth-child(4)', '47');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|createdAfter=2015-02-16|createdBefore=2015-02-18"]');
+ test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|createdAfter=2015-02-16|createdBefore=2015-02-17"]');
+ test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|createdAfter=2015-02-17|createdBefore=2015-02-18"]');
+ test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|createdAfter=2015-02-18|createdBefore=2015-02-19"]');
+
+ // check labels
+ test.assertSelectorContains('tr:nth-child(2)', 'February 16 2015');
+ test.assertSelectorContains('tr:nth-child(3)', 'February 17 2015');
+ test.assertSelectorContains('tr:nth-child(4)', 'February 18 2015');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink.js b/server/sonar-web/src/test/js/issues-page-should-open-issue-permalink.js
index 0eb6587f442..64b10e69251 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink.js
+++ b/server/sonar-web/src/test/js/issues-page-should-open-issue-permalink.js
@@ -51,6 +51,10 @@ casper.test.begin('issues-page-should-open-issue-permalink', 3, function (test)
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-page-spec.js b/server/sonar-web/src/test/js/issues-page-spec.js
index 5abab8e9f94..7dfb1916039 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-page-spec.js
+++ b/server/sonar-web/src/test/js/issues-page-spec.js
@@ -77,6 +77,10 @@ casper.test.begin(testName('Base'), function (test) {
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
@@ -115,6 +119,10 @@ casper.test.begin(testName('Issue Box', 'Check Elements'), function (test) {
test.assertExists('.issue.selected .js-issue-show-changelog');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
@@ -156,6 +164,10 @@ casper.test.begin(testName('Issue Box', 'Tags'), function (test) {
test.assertSelectorContains('.issue.selected .js-issue-tags', 'security, design');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
@@ -189,6 +201,10 @@ casper.test.begin(testName('Issue Box', 'Transitions'), function (test) {
test.assertExists('.issue-action-option[data-value=falsepositive]');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
@@ -222,6 +238,10 @@ casper.test.begin(testName('File-Level Issues'), function (test) {
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
@@ -251,6 +271,10 @@ casper.test.begin(testName('Severity Facet'), function (test) {
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
@@ -282,6 +306,10 @@ casper.test.begin(testName('Bulk Change'), function (test) {
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/test/js/project-issue-filter-widget.js b/server/sonar-web/src/test/js/project-issue-filter-widget.js
new file mode 100644
index 00000000000..25e69cdeff8
--- /dev/null
+++ b/server/sonar-web/src/test/js/project-issue-filter-widget.js
@@ -0,0 +1,221 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+/* globals casper: false */
+
+var lib = require('../lib'),
+ testName = lib.testName('Project Issue Filter Widget');
+
+
+lib.initMessages();
+lib.changeWorkingDirectory('project-issues-filter-widget');
+lib.configureCasper();
+
+
+casper.test.begin(testName('Unresolved Issues By Severity'), 13, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-severity.json',
+ { data: { resolved: 'false' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false',
+ distributionAxis: 'severities',
+ componentUuid: '69e57151-be0d-4157-adff-c06741d88879',
+ componentKey: 'org.codehaus.sonar:sonar'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 6);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '6851');
+ test.assertSelectorContains('tr:nth-child(2)', '1');
+ test.assertSelectorContains('tr:nth-child(3)', '105');
+ test.assertSelectorContains('tr:nth-child(4)', '5027');
+ test.assertSelectorContains('tr:nth-child(5)', '540');
+ test.assertSelectorContains('tr:nth-child(6)', '1178');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false"]');
+ test.assertExists('tr:nth-child(2) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|severities=BLOCKER"]');
+ test.assertExists('tr:nth-child(3) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|severities=CRITICAL"]');
+ test.assertExists('tr:nth-child(4) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|severities=MAJOR"]');
+ test.assertExists('tr:nth-child(5) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|severities=MINOR"]');
+ test.assertExists('tr:nth-child(6) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|severities=INFO"]');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Date'), 18, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-date.json',
+ { data: { resolved: 'false' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false',
+ distributionAxis: 'createdAt',
+ componentUuid: '69e57151-be0d-4157-adff-c06741d88879',
+ componentKey: 'org.codehaus.sonar:sonar'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 6);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '6851');
+ test.assertSelectorContains('tr:nth-child(2)', '72');
+ test.assertSelectorContains('tr:nth-child(3)', '64');
+ test.assertSelectorContains('tr:nth-child(4)', '1262');
+ test.assertSelectorContains('tr:nth-child(5)', '3729');
+ test.assertSelectorContains('tr:nth-child(6)', '1724');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false"]');
+ test.assertExists('tr:nth-child(2) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2011-01-01|createdBefore=2011-12-31"]');
+ test.assertExists('tr:nth-child(3) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2012-01-01|createdBefore=2012-12-31"]');
+ test.assertExists('tr:nth-child(4) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2013-01-01|createdBefore=2013-12-31"]');
+ test.assertExists('tr:nth-child(5) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-01-01|createdBefore=2014-12-31"]');
+ // do not check createdBefore value, because it is set dynamically to *now*
+ test.assertExists('tr:nth-child(6) a[href^="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2015-01-01|createdBefore="]');
+
+ // check labels
+ test.assertSelectorContains('tr:nth-child(2)', 'January 1 2011 – December 31 2011');
+ test.assertSelectorContains('tr:nth-child(3)', 'January 1 2012 – December 31 2012');
+ test.assertSelectorContains('tr:nth-child(4)', 'January 1 2013 – December 31 2013');
+ test.assertSelectorContains('tr:nth-child(5)', 'January 1 2014 – December 31 2014');
+ // do not check label fully, because it is set dynamically using *now*
+ test.assertSelectorContains('tr:nth-child(6)', 'January 1 2015 – ');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Severity With Differential Period'), 13, function (test) {
+ casper
+ .start(lib.buildUrl('issue-filter-widget'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-severity-with-differential-period.json',
+ { data: { resolved: 'false', createdAfter: '2014-12-09T17:12:38+0100' } });
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+ window.requestMessages().done(function () {
+ new IssueFilter({
+ el: '#issue-filter-widget',
+ query: 'resolved=false',
+ distributionAxis: 'severities',
+ periodDate: '2014-12-09T17:12:38+0100',
+ componentUuid: '69e57151-be0d-4157-adff-c06741d88879',
+ componentKey: 'org.codehaus.sonar:sonar'
+ });
+ });
+ });
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('#issue-filter-widget > table');
+ })
+
+ .then(function () {
+ // check count
+ test.assertElementCount('tr', 6);
+
+ // check order and values
+ test.assertSelectorContains('tr:nth-child(1)', '+549');
+ test.assertSelectorContains('tr:nth-child(2)', '+0');
+ test.assertSelectorContains('tr:nth-child(3)', '+59');
+ test.assertSelectorContains('tr:nth-child(4)', '+306');
+ test.assertSelectorContains('tr:nth-child(5)', '+135');
+ test.assertSelectorContains('tr:nth-child(6)', '+49');
+
+ // check links
+ test.assertExists('tr:nth-child(1) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-12-09T17%3A12%3A38%2B0100"]');
+ test.assertExists('tr:nth-child(2) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-12-09T17%3A12%3A38%2B0100|severities=BLOCKER"]');
+ test.assertExists('tr:nth-child(3) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-12-09T17%3A12%3A38%2B0100|severities=CRITICAL"]');
+ test.assertExists('tr:nth-child(4) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-12-09T17%3A12%3A38%2B0100|severities=MAJOR"]');
+ test.assertExists('tr:nth-child(5) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-12-09T17%3A12%3A38%2B0100|severities=MINOR"]');
+ test.assertExists('tr:nth-child(6) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-12-09T17%3A12%3A38%2B0100|severities=INFO"]');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec.js b/server/sonar-web/src/test/js/quality-gates-spec.js
index 8de770ca65f..2b2c7ef8ac2 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec.js
+++ b/server/sonar-web/src/test/js/quality-gates-spec.js
@@ -56,6 +56,10 @@ casper.test.begin('Quality Gates', function suite (test) {
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/test/js/source-viewer-coverage.js b/server/sonar-web/src/test/js/source-viewer-coverage.js
new file mode 100644
index 00000000000..434300129f3
--- /dev/null
+++ b/server/sonar-web/src/test/js/source-viewer-coverage.js
@@ -0,0 +1,66 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+/* global casper:false */
+
+
+var lib = require('../lib'),
+ testName = lib.testName('Source Viewer');
+
+lib.initMessages();
+lib.changeWorkingDirectory('source-viewer-coverage');
+lib.configureCasper();
+
+
+casper.test.begin(testName('Coverage'), 4, function (test) {
+ casper
+ .start(lib.buildUrl('source-viewer'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/components/app', 'app.json');
+ lib.mockRequestFromFile('/api/sources/lines', 'lines.json');
+ lib.mockRequestFromFile('/api/issues/search', 'issues.json');
+ lib.mockRequestFromFile('/api/tests/test_cases', 'test-cases.json');
+ })
+
+ .then(function () {
+ casper.waitForSelector('.source-line');
+ })
+
+ .then(function () {
+ test.assertElementCount('.source-line-covered', 1);
+ casper.click('.source-line-covered');
+ casper.waitForSelector('.bubble-popup');
+ })
+
+ .then(function () {
+ test.assertSelectorContains('.bubble-popup', 'SampleTest');
+ test.assertSelectorContains('.bubble-popup', '2ms');
+ test.assertExists('.bubble-popup .icon-test-status-ok');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue.js b/server/sonar-web/src/test/js/source-viewer-create-manual-issue.js
index 794947f744f..2cc0a798b83 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue.js
+++ b/server/sonar-web/src/test/js/source-viewer-create-manual-issue.js
@@ -68,6 +68,10 @@ casper.test.begin(testName('source-viewer-create-manual-issue'), function (test)
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/test/js/source-viewer-duplications.js b/server/sonar-web/src/test/js/source-viewer-duplications.js
new file mode 100644
index 00000000000..bff158991b5
--- /dev/null
+++ b/server/sonar-web/src/test/js/source-viewer-duplications.js
@@ -0,0 +1,70 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+/* global casper:false */
+
+
+var lib = require('../lib'),
+ testName = lib.testName('Source Viewer');
+
+lib.initMessages();
+lib.changeWorkingDirectory('source-viewer-duplications');
+lib.configureCasper();
+
+
+casper.test.begin(testName('Duplications'), 4, function (test) {
+ casper
+ .start(lib.buildUrl('source-viewer'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/components/app', 'app.json');
+ lib.mockRequestFromFile('/api/sources/lines', 'lines.json');
+ lib.mockRequestFromFile('/api/issues/search', 'issues.json');
+ lib.mockRequestFromFile('/api/duplications/show', 'duplications.json');
+ })
+
+ .then(function () {
+ casper.waitForSelector('.source-line');
+ })
+
+ .then(function () {
+ test.assertElementCount('.source-line-duplications.source-line-duplicated', 5);
+ casper.click('.source-line-duplicated');
+ lib.waitForElementCount('.source-line-duplications-extra.source-line-duplicated', 5);
+ })
+
+ .then(function () {
+ casper.waitForSelector('.bubble-popup');
+ })
+
+ .then(function () {
+ test.assertSelectorContains('.bubble-popup', 'Duplicated');
+ test.assertSelectorContains('.bubble-popup', '12');
+ test.assertSelectorContains('.bubble-popup', '16');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-favorite-spec.js b/server/sonar-web/src/test/js/source-viewer-favorite-spec.js
index 6a4398704bb..91eeedc5952 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-favorite-spec.js
+++ b/server/sonar-web/src/test/js/source-viewer-favorite-spec.js
@@ -56,6 +56,10 @@ casper.test.begin(testName('Mark as Favorite'), function (test) {
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
@@ -82,6 +86,10 @@ casper.test.begin(testName('Don\'t Show Favorite If Not Logged In'), function (t
test.assertDoesntExist('.icon-not-favorite');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-link-to-raw-spec.js b/server/sonar-web/src/test/js/source-viewer-link-to-raw-spec.js
index 3c9f83f5ed1..8942a7cffc5 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-link-to-raw-spec.js
+++ b/server/sonar-web/src/test/js/source-viewer-link-to-raw-spec.js
@@ -54,6 +54,10 @@ casper.test.begin(testName('Link to Raw'), function (test) {
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/test/js/source-viewer-scm.js b/server/sonar-web/src/test/js/source-viewer-scm.js
new file mode 100644
index 00000000000..abf5102cf46
--- /dev/null
+++ b/server/sonar-web/src/test/js/source-viewer-scm.js
@@ -0,0 +1,71 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+/* global casper:false */
+
+
+var lib = require('../lib'),
+ testName = lib.testName('Source Viewer');
+
+lib.initMessages();
+lib.changeWorkingDirectory('source-viewer-scm');
+lib.configureCasper();
+
+
+casper.test.begin(testName('SCM'), 4, function (test) {
+ casper
+ .start(lib.buildUrl('source-viewer'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/components/app', 'app.json');
+ lib.mockRequestFromFile('/api/sources/lines', 'lines.json');
+ lib.mockRequestFromFile('/api/issues/search', 'issues.json');
+ })
+
+ .then(function () {
+ casper.waitForSelector('.source-line');
+ })
+
+ .then(function () {
+ casper.click('.source-line-scm[data-line-number="1"]');
+ casper.waitForSelector('.bubble-popup');
+ })
+
+ .then(function () {
+ test.assertSelectorContains('.bubble-popup', 'sample-author');
+ test.assertSelectorContains('.bubble-popup', 'January 1 2015 1:00 AM');
+ test.assertSelectorContains('.bubble-popup', 'samplerevision');
+ })
+
+ // do not hide popup on click
+ // to allow selecting text by mouse
+ .then(function () {
+ casper.click('.bubble-popup');
+ test.assertExists('.bubble-popup');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-not-show-source-if-no-permission.js b/server/sonar-web/src/test/js/source-viewer-should-not-show-source-if-no-permission.js
index 51786db106f..ec29cb5af96 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-not-show-source-if-no-permission.js
+++ b/server/sonar-web/src/test/js/source-viewer-should-not-show-source-if-no-permission.js
@@ -44,6 +44,10 @@ casper.test.begin(testName('source-viewer-should-not-show-source-if-no-permissio
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window-with-line.js b/server/sonar-web/src/test/js/source-viewer-should-open-in-new-window-with-line.js
index fd5f81785b2..f1c622890fa 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window-with-line.js
+++ b/server/sonar-web/src/test/js/source-viewer-should-open-in-new-window-with-line.js
@@ -61,6 +61,10 @@ casper.test.begin(testName('source-viewer-should-open-in-new-window-with-line'),
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window.js b/server/sonar-web/src/test/js/source-viewer-should-open-in-new-window.js
index 35188e28bb8..200932f5f22 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window.js
+++ b/server/sonar-web/src/test/js/source-viewer-should-open-in-new-window.js
@@ -55,6 +55,10 @@ casper.test.begin(testName('source-viewer-should-open-in-new-window'), function
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec.js b/server/sonar-web/src/test/js/source-viewer-spec.js
index d70789490a0..7adcee1a280 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec.js
+++ b/server/sonar-web/src/test/js/source-viewer-spec.js
@@ -65,6 +65,10 @@ casper.test.begin(testName('Base'), function (test) {
});
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
@@ -110,6 +114,10 @@ casper.test.begin(testName('Decoration'), function (test) {
test.assertExists('.source-line-scm-inner[data-author="julien.henry@sonarsource.com"]');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
@@ -135,6 +143,10 @@ casper.test.begin(testName('Test File'), function (test) {
test.assertSelectorContains('.source-viewer-header-measure', '6');
})
+ .then(function () {
+ lib.sendCoverage();
+ })
+
.run(function () {
test.done();
});
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/treemap-spec.js b/server/sonar-web/src/test/js/treemap-spec.js
index 2cf0496144a..43100cf6107 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/treemap-spec.js
+++ b/server/sonar-web/src/test/js/treemap-spec.js
@@ -69,6 +69,9 @@ casper.test.begin('Treemap', function (test) {
test.assertSelectorHasText('.treemap-cell', 'Server');
test.assertElementCount('.treemap-cell', 25);
});
+ })
+ .then(function () {
+ lib.sendCoverage();
});
casper.run(function() {
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet/app.json b/server/sonar-web/src/test/json/coding-rules-page-active-severity-facet/app.json
index 0eb43bc39f7..0eb43bc39f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-active-severity-facet/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet/search-BLOCKER.json b/server/sonar-web/src/test/json/coding-rules-page-active-severity-facet/search-BLOCKER.json
index 3dc49f0bca3..3dc49f0bca3 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet/search-BLOCKER.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-active-severity-facet/search-BLOCKER.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet/search-qprofile.json b/server/sonar-web/src/test/json/coding-rules-page-active-severity-facet/search-qprofile.json
index cbbb2722ae9..cbbb2722ae9 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet/search-qprofile.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-active-severity-facet/search-qprofile.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet/search.json b/server/sonar-web/src/test/json/coding-rules-page-active-severity-facet/search.json
index c17c58d2b42..c17c58d2b42 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-active-severity-facet/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-active-severity-facet/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-available-since/app.json b/server/sonar-web/src/test/json/coding-rules-page-available-since/app.json
index 0eb43bc39f7..0eb43bc39f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-available-since/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-available-since/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-available-since/search-limited.json b/server/sonar-web/src/test/json/coding-rules-page-available-since/search-limited.json
index ca5b3316b7c..ca5b3316b7c 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-available-since/search-limited.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-available-since/search-limited.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-available-since/search.json b/server/sonar-web/src/test/json/coding-rules-page-available-since/search.json
index c17c58d2b42..c17c58d2b42 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-available-since/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-available-since/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/app.json b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/app.json
index 0eb43bc39f7..0eb43bc39f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-inherited.json b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-inherited.json
index ca5b3316b7c..ca5b3316b7c 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-inherited.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-inherited.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-not-inherited.json b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-not-inherited.json
index c49bff75f1c..c49bff75f1c 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-not-inherited.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-not-inherited.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-overriden.json b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-overriden.json
index 60bb4a7796e..60bb4a7796e 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-overriden.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-overriden.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-qprofile.json b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-qprofile.json
index cbbb2722ae9..cbbb2722ae9 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-qprofile.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-qprofile.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-qprofile2.json b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-qprofile2.json
index 63dd5c45733..63dd5c45733 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search-qprofile2.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search-qprofile2.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search.json b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search.json
index c17c58d2b42..c17c58d2b42 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-inheritance-facet/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-inheritance-facet/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-no-available-profiles-for-activation/app.json b/server/sonar-web/src/test/json/coding-rules-page-no-available-profiles-for-activation/app.json
index 4e69bdee31a..4e69bdee31a 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-no-available-profiles-for-activation/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-no-available-profiles-for-activation/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-no-available-profiles-for-activation/search.json b/server/sonar-web/src/test/json/coding-rules-page-no-available-profiles-for-activation/search.json
index b5a6bc269b9..b5a6bc269b9 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-no-available-profiles-for-activation/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-no-available-profiles-for-activation/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-no-available-profiles-for-activation/show.json b/server/sonar-web/src/test/json/coding-rules-page-no-available-profiles-for-activation/show.json
index 1fddeb6a632..1fddeb6a632 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-no-available-profiles-for-activation/show.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-no-available-profiles-for-activation/show.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet/app.json b/server/sonar-web/src/test/json/coding-rules-page-quality-profile-facet/app.json
index 0eb43bc39f7..0eb43bc39f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-quality-profile-facet/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet/search-qprofile-active.json b/server/sonar-web/src/test/json/coding-rules-page-quality-profile-facet/search-qprofile-active.json
index cbbb2722ae9..cbbb2722ae9 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet/search-qprofile-active.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-quality-profile-facet/search-qprofile-active.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet/search-qprofile-inactive.json b/server/sonar-web/src/test/json/coding-rules-page-quality-profile-facet/search-qprofile-inactive.json
index 63dd5c45733..63dd5c45733 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet/search-qprofile-inactive.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-quality-profile-facet/search-qprofile-inactive.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet/search.json b/server/sonar-web/src/test/json/coding-rules-page-quality-profile-facet/search.json
index c17c58d2b42..c17c58d2b42 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-quality-profile-facet/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-quality-profile-facet/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-query-facet/app.json b/server/sonar-web/src/test/json/coding-rules-page-query-facet/app.json
index 0eb43bc39f7..0eb43bc39f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-query-facet/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-query-facet/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-query-facet/search-query.json b/server/sonar-web/src/test/json/coding-rules-page-query-facet/search-query.json
index 3dc49f0bca3..3dc49f0bca3 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-query-facet/search-query.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-query-facet/search-query.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-query-facet/search.json b/server/sonar-web/src/test/json/coding-rules-page-query-facet/search.json
index c17c58d2b42..c17c58d2b42 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-query-facet/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-query-facet/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-rule-permalink/app.json b/server/sonar-web/src/test/json/coding-rules-page-rule-permalink/app.json
index 0eb43bc39f7..0eb43bc39f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-rule-permalink/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-rule-permalink/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-rule-permalink/search.json b/server/sonar-web/src/test/json/coding-rules-page-rule-permalink/search.json
index b5a6bc269b9..b5a6bc269b9 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-rule-permalink/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-rule-permalink/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-rule-permalink/show.json b/server/sonar-web/src/test/json/coding-rules-page-rule-permalink/show.json
index 274b587bfb2..274b587bfb2 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-rule-permalink/show.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-rule-permalink/show.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile/app.json b/server/sonar-web/src/test/json/coding-rules-page-should-activate-profile/app.json
index 50148bb1b6e..50148bb1b6e 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-activate-profile/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile/search.json b/server/sonar-web/src/test/json/coding-rules-page-should-activate-profile/search.json
index b5a6bc269b9..b5a6bc269b9 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-activate-profile/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile/show-with-profile.json b/server/sonar-web/src/test/json/coding-rules-page-should-activate-profile/show-with-profile.json
index 1fddeb6a632..1fddeb6a632 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile/show-with-profile.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-activate-profile/show-with-profile.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile/show.json b/server/sonar-web/src/test/json/coding-rules-page-should-activate-profile/show.json
index cf4b206221e..cf4b206221e 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-activate-profile/show.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-activate-profile/show.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/app.json b/server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/app.json
index 50148bb1b6e..50148bb1b6e 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/search-custom-rules.json b/server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/search-custom-rules.json
index db83a85fbd6..db83a85fbd6 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/search-custom-rules.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/search-custom-rules.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/search-custom-rules2.json b/server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/search-custom-rules2.json
index 0e4184e48a9..0e4184e48a9 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/search-custom-rules2.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/search-custom-rules2.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/search.json b/server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/search.json
index 40ab6ae953a..40ab6ae953a 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/show.json b/server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/show.json
index 517c5f6e754..517c5f6e754 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-custom-rules/show.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-create-custom-rules/show.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-manual-rules/app.json b/server/sonar-web/src/test/json/coding-rules-page-should-create-manual-rules/app.json
index 50148bb1b6e..50148bb1b6e 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-manual-rules/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-create-manual-rules/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-manual-rules/search.json b/server/sonar-web/src/test/json/coding-rules-page-should-create-manual-rules/search.json
index f43d117c569..f43d117c569 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-manual-rules/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-create-manual-rules/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-manual-rules/show.json b/server/sonar-web/src/test/json/coding-rules-page-should-create-manual-rules/show.json
index 38190c28abb..38190c28abb 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-create-manual-rules/show.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-create-manual-rules/show.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules/app.json b/server/sonar-web/src/test/json/coding-rules-page-should-delete-custom-rules/app.json
index 50148bb1b6e..50148bb1b6e 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-delete-custom-rules/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules/search-custom-rules.json b/server/sonar-web/src/test/json/coding-rules-page-should-delete-custom-rules/search-custom-rules.json
index 0e4184e48a9..0e4184e48a9 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules/search-custom-rules.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-delete-custom-rules/search-custom-rules.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules/search.json b/server/sonar-web/src/test/json/coding-rules-page-should-delete-custom-rules/search.json
index 40ab6ae953a..40ab6ae953a 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-delete-custom-rules/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules/show.json b/server/sonar-web/src/test/json/coding-rules-page-should-delete-custom-rules/show.json
index 517c5f6e754..517c5f6e754 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-custom-rules/show.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-delete-custom-rules/show.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules/app.json b/server/sonar-web/src/test/json/coding-rules-page-should-delete-manual-rules/app.json
index 50148bb1b6e..50148bb1b6e 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-delete-manual-rules/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules/search-after.json b/server/sonar-web/src/test/json/coding-rules-page-should-delete-manual-rules/search-after.json
index f43d117c569..f43d117c569 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules/search-after.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-delete-manual-rules/search-after.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules/search-before.json b/server/sonar-web/src/test/json/coding-rules-page-should-delete-manual-rules/search-before.json
index 1f19e1d27c2..1f19e1d27c2 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules/search-before.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-delete-manual-rules/search-before.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules/show.json b/server/sonar-web/src/test/json/coding-rules-page-should-delete-manual-rules/show.json
index 38190c28abb..38190c28abb 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-delete-manual-rules/show.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-delete-manual-rules/show.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules/app.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-custom-rules/app.json
index 0eb43bc39f7..0eb43bc39f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-custom-rules/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules/search-custom-rules.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-custom-rules/search-custom-rules.json
index 0e4184e48a9..0e4184e48a9 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules/search-custom-rules.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-custom-rules/search-custom-rules.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules/search.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-custom-rules/search.json
index 40ab6ae953a..40ab6ae953a 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-custom-rules/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules/show.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-custom-rules/show.json
index 517c5f6e754..517c5f6e754 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-custom-rules/show.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-custom-rules/show.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-deprecated-label/app.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-deprecated-label/app.json
index 0eb43bc39f7..0eb43bc39f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-deprecated-label/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-deprecated-label/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-deprecated-label/search.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-deprecated-label/search.json
index ddeb1cb7984..ddeb1cb7984 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-deprecated-label/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-deprecated-label/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-details/app.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-details/app.json
index 0eb43bc39f7..0eb43bc39f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-details/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-details/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-details/search.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-details/search.json
index b5a6bc269b9..b5a6bc269b9 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-details/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-details/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-details/show.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-details/show.json
index 274b587bfb2..274b587bfb2 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-details/show.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-details/show.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-empty-list/app.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-empty-list/app.json
index 0eb43bc39f7..0eb43bc39f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-empty-list/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-empty-list/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-empty-list/search.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-empty-list/search.json
index f43d117c569..f43d117c569 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-empty-list/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-empty-list/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues/app.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-rule-issues/app.json
index 0eb43bc39f7..0eb43bc39f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues/app.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-rule-issues/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues/issues-search.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-rule-issues/issues-search.json
index 511b9288285..511b9288285 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues/issues-search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-rule-issues/issues-search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues/search.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-rule-issues/search.json
index 558be10513e..558be10513e 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues/search.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-rule-issues/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues/show.json b/server/sonar-web/src/test/json/coding-rules-page-should-show-rule-issues/show.json
index 274b587bfb2..274b587bfb2 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules-page-should-show-rule-issues/show.json
+++ b/server/sonar-web/src/test/json/coding-rules-page-should-show-rule-issues/show.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules/app.json b/server/sonar-web/src/test/json/coding-rules/app.json
index 0eb43bc39f7..0eb43bc39f7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules/app.json
+++ b/server/sonar-web/src/test/json/coding-rules/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules/search.json b/server/sonar-web/src/test/json/coding-rules/search.json
index c17c58d2b42..c17c58d2b42 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/coding-rules/search.json
+++ b/server/sonar-web/src/test/json/coding-rules/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/design-spec/dependencies.json b/server/sonar-web/src/test/json/design-spec/dependencies.json
index 7f23c19b8d5..7f23c19b8d5 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/design-spec/dependencies.json
+++ b/server/sonar-web/src/test/json/design-spec/dependencies.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/design-spec/resources.json b/server/sonar-web/src/test/json/design-spec/resources.json
index 3d06975ac57..3d06975ac57 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/design-spec/resources.json
+++ b/server/sonar-web/src/test/json/design-spec/resources.json
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-resolution.json b/server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-resolution.json
new file mode 100644
index 00000000000..6751605092f
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-resolution.json
@@ -0,0 +1,32 @@
+{
+ "total": 71571,
+ "p": 1,
+ "ps": 1,
+ "facets": [
+ {
+ "property": "resolutions",
+ "values": [
+ {
+ "val": "",
+ "count": 6851
+ },
+ {
+ "val": "FIXED",
+ "count": 47092
+ },
+ {
+ "val": "REMOVED",
+ "count": 16326
+ },
+ {
+ "val": "FALSE-POSITIVE",
+ "count": 752
+ },
+ {
+ "val": "WONTFIX",
+ "count": 550
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-status.json b/server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-status.json
new file mode 100644
index 00000000000..99fe9461067
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-status.json
@@ -0,0 +1,32 @@
+{
+ "total": 71571,
+ "p": 1,
+ "ps": 1,
+ "facets": [
+ {
+ "property": "statuses",
+ "values": [
+ {
+ "val": "CLOSED",
+ "count": 63413
+ },
+ {
+ "val": "CONFIRMED",
+ "count": 6609
+ },
+ {
+ "val": "RESOLVED",
+ "count": 1307
+ },
+ {
+ "val": "OPEN",
+ "count": 238
+ },
+ {
+ "val": "REOPENED",
+ "count": 4
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/red-issues-by-severity.json b/server/sonar-web/src/test/json/global-issues-filter-widget/red-issues-by-severity.json
new file mode 100644
index 00000000000..f261766748c
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/red-issues-by-severity.json
@@ -0,0 +1,32 @@
+{
+ "total": 6851,
+ "p": 1,
+ "ps": 1,
+ "facets": [
+ {
+ "property": "severities",
+ "values": [
+ {
+ "val": "MAJOR",
+ "count": 5027
+ },
+ {
+ "val": "INFO",
+ "count": 1178
+ },
+ {
+ "val": "MINOR",
+ "count": 540
+ },
+ {
+ "val": "CRITICAL",
+ "count": 105
+ },
+ {
+ "val": "BLOCKER",
+ "count": 1
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-action-plan.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-action-plan.json
new file mode 100644
index 00000000000..7589fe0737c
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-action-plan.json
@@ -0,0 +1,63 @@
+{
+ "total": 6851,
+ "p": 1,
+ "ps": 1,
+ "actionPlans": [
+ {
+ "key": "0cf48508-2fcd-4cb8-a50b-c5cd7c3decc0",
+ "name": "First Action Plan",
+ "status": "OPEN",
+ "project": "example:project",
+ "userLogin": "example.login",
+ "createdAt": "2014-04-03T12:28:05+0200",
+ "fCreatedAt": "Apr 3, 2014 12:28 PM",
+ "updatedAt": "2014-04-03T12:28:05+0200",
+ "fUpdatedAt": "Apr 3, 2014 12:28 PM"
+ },
+ {
+ "key": "1b9e7e52-ff58-40c1-80bf-f68429a3275e",
+ "name": "Second Action Plan",
+ "status": "OPEN",
+ "project": "example:project",
+ "userLogin": "example.login",
+ "createdAt": "2014-04-03T12:28:05+0200",
+ "fCreatedAt": "Apr 3, 2014 12:28 PM",
+ "updatedAt": "2014-04-03T12:28:05+0200",
+ "fUpdatedAt": "Apr 3, 2014 12:28 PM"
+ },
+ {
+ "key": "8c1d5d01-948e-4670-a0d9-17c512979486",
+ "name": "Third Action Plan",
+ "status": "OPEN",
+ "project": "example:project",
+ "userLogin": "example.login",
+ "createdAt": "2014-04-03T12:28:05+0200",
+ "fCreatedAt": "Apr 3, 2014 12:28 PM",
+ "updatedAt": "2014-04-03T12:28:05+0200",
+ "fUpdatedAt": "Apr 3, 2014 12:28 PM"
+ }
+ ],
+ "facets": [
+ {
+ "property": "actionPlans",
+ "values": [
+ {
+ "val": "",
+ "count": 5877
+ },
+ {
+ "val": "0cf48508-2fcd-4cb8-a50b-c5cd7c3decc0",
+ "count": 532
+ },
+ {
+ "val": "1b9e7e52-ff58-40c1-80bf-f68429a3275e",
+ "count": 56
+ },
+ {
+ "val": "8c1d5d01-948e-4670-a0d9-17c512979486",
+ "count": 52
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-assignee.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-assignee.json
new file mode 100644
index 00000000000..350327879fc
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-assignee.json
@@ -0,0 +1,48 @@
+{
+ "total": 6851,
+ "p": 1,
+ "ps": 1,
+ "users": [
+ {
+ "login": "second.user",
+ "name": "Second User",
+ "active": true,
+ "email": "second.user@example.com"
+ },
+ {
+ "login": "third.user",
+ "name": "Third User",
+ "active": true,
+ "email": "third.user@example .com"
+ },
+ {
+ "login": "first.user",
+ "name": "First User",
+ "active": true,
+ "email": "first.user@example.com"
+ }
+ ],
+ "facets": [
+ {
+ "property": "assignees",
+ "values": [
+ {
+ "val": "",
+ "count": 4134
+ },
+ {
+ "val": "first.user",
+ "count": 698
+ },
+ {
+ "val": "second.user",
+ "count": 504
+ },
+ {
+ "val": "third.user",
+ "count": 426
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date-limited.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date-limited.json
new file mode 100644
index 00000000000..5c2f0182f9a
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date-limited.json
@@ -0,0 +1,24 @@
+{
+ "total": 6851,
+ "p": 1,
+ "ps": 1,
+ "facets": [
+ {
+ "property": "createdAt",
+ "values": [
+ {
+ "val": "2015-02-16T01:00:00+0000",
+ "count": 49
+ },
+ {
+ "val": "2015-02-17T01:00:00+0000",
+ "count": 48
+ },
+ {
+ "val": "2015-02-18T01:00:00+0000",
+ "count": 47
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date.json
new file mode 100644
index 00000000000..54153d9897b
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date.json
@@ -0,0 +1,32 @@
+{
+ "total": 6851,
+ "p": 1,
+ "ps": 1,
+ "facets": [
+ {
+ "property": "createdAt",
+ "values": [
+ {
+ "val": "2011-01-01T01:00:00+0000",
+ "count": 72
+ },
+ {
+ "val": "2012-01-01T01:00:00+0000",
+ "count": 64
+ },
+ {
+ "val": "2013-01-01T01:00:00+0000",
+ "count": 1262
+ },
+ {
+ "val": "2014-01-01T01:00:00+0000",
+ "count": 3729
+ },
+ {
+ "val": "2015-01-01T01:00:00+0000",
+ "count": 1724
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-language.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-language.json
new file mode 100644
index 00000000000..de5e4c9be3a
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-language.json
@@ -0,0 +1,46 @@
+{
+ "total": 6851,
+ "p": 1,
+ "ps": 1,
+ "languages": [
+ {
+ "key": "py",
+ "name": "Python"
+ },
+ {
+ "key": "js",
+ "name": "JavaScript"
+ },
+ {
+ "key": "php",
+ "name": "PHP"
+ },
+ {
+ "key": "java",
+ "name": "Java"
+ }
+ ],
+ "facets": [
+ {
+ "property": "languages",
+ "values": [
+ {
+ "val": "java",
+ "count": 6336
+ },
+ {
+ "val": "py",
+ "count": 444
+ },
+ {
+ "val": "php",
+ "count": 22
+ },
+ {
+ "val": "js",
+ "count": 15
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-project.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-project.json
new file mode 100644
index 00000000000..e53991f61ab
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-project.json
@@ -0,0 +1,62 @@
+{
+ "total": 2598,
+ "p": 1,
+ "ps": 1,
+ "projects": [
+ {
+ "uuid": "5eab015a-1f76-4ba4-bd89-bf547132d673",
+ "key": "org.codehaus.sonar-plugins.javascript:javascript",
+ "id": 10159,
+ "qualifier": "TRK",
+ "name": "JavaScript",
+ "longName": "JavaScript"
+ },
+ {
+ "uuid": "c156940b-e3ec-43f6-9589-e3b75aa9ca32",
+ "key": "org.codehaus.sonar-plugins.python:python",
+ "id": 11752,
+ "qualifier": "TRK",
+ "name": "Python",
+ "longName": "Python"
+ },
+ {
+ "uuid": "dd7c3556-ce3f-42d0-a348-914a582dc944",
+ "key": "org.codehaus.sonar-plugins.java:java",
+ "id": 13265,
+ "qualifier": "TRK",
+ "name": "SonarQube Java",
+ "longName": "SonarQube Java"
+ },
+ {
+ "uuid": "69e57151-be0d-4157-adff-c06741d88879",
+ "key": "org.codehaus.sonar:sonar",
+ "id": 2865,
+ "qualifier": "TRK",
+ "name": "SonarQube",
+ "longName": "SonarQube"
+ }
+ ],
+ "facets": [
+ {
+ "property": "projectUuids",
+ "values": [
+ {
+ "val": "69e57151-be0d-4157-adff-c06741d88879",
+ "count": 1766
+ },
+ {
+ "val": "dd7c3556-ce3f-42d0-a348-914a582dc944",
+ "count": 442
+ },
+ {
+ "val": "5eab015a-1f76-4ba4-bd89-bf547132d673",
+ "count": 283
+ },
+ {
+ "val": "c156940b-e3ec-43f6-9589-e3b75aa9ca32",
+ "count": 107
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-resolution.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-resolution.json
new file mode 100644
index 00000000000..146920688ff
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-resolution.json
@@ -0,0 +1,32 @@
+{
+ "total": 6851,
+ "p": 1,
+ "ps": 1,
+ "facets": [
+ {
+ "property": "resolutions",
+ "values": [
+ {
+ "val": "",
+ "count": 6851
+ },
+ {
+ "val": "FIXED",
+ "count": 47092
+ },
+ {
+ "val": "REMOVED",
+ "count": 16326
+ },
+ {
+ "val": "FALSE-POSITIVE",
+ "count": 752
+ },
+ {
+ "val": "WONTFIX",
+ "count": 550
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-rule.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-rule.json
new file mode 100644
index 00000000000..aa70a9bfc71
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-rule.json
@@ -0,0 +1,186 @@
+{
+ "total": 6851,
+ "p": 1,
+ "ps": 1,
+ "rules": [
+ {
+ "key": "squid:S1698",
+ "name": "Objects should be compared with \"equals()\"",
+ "lang": "java",
+ "desc": "<p>Using the equality (<code>==</code>) and inequality (<code>!=</code>) operators to compare two objects does not check to see if they have the same values. Rather it checks to see if both object references point to exactly the same object in memory. The vast majority of the time, this is not what you want to do. Use the .equals() method to compare the values of two objects or to compare a string object to a string literal.</p>\n\n<h2>Noncompliant Code Sample</h2>\n<pre>\nString str1 = \"blue\";\nString str2 = \"blue\";\nString str3 = str1;\n\nif (str1 == str2)\n{\n System.out.println(\"they're both 'blue'\"); // this doesn't print because the objects are different\n}\n\nif (str1 == \"blue\")\n{\n System.out.println(\"they're both 'blue'\"); // this doesn't print because the objects are different\n}\n\nif (str1 == str3)\n{\n System.out.println(\"they're the same object\"); // this prints\n}\n</pre>\n\n<h2>Compliant Solution</h2>\n<pre>\nString str1 = \"blue\";\nString str2 = \"blue\";\nString str3 = str1;\n\nif (str1.equals(str2))\n{\n System.out.println(\"they're both 'blue'\"); // this prints\n}\n\nif (str1.equals(\"blue\"))\n{\n System.out.println(\"they're both 'blue'\"); // this prints\n}\n\nif (str1 == str3)\n{\n System.out.println(\"they're the same object\"); // this still prints, but it's probably not what you meant to do\n}\n</pre>\n\n<h2>Exception</h2>\nComparing two instances of the <code>Class</code> object will not raise an issue.\n<pre>\nClass c;\nif(c == Integer.class) { //No issue raised\n}\n</pre>\n\n<h2>See</h2>\n <ul>\n <li><a href=\"http://cwe.mitre.org/data/definitions/595.html\">MITRE, CWE-595</a> - Comparison of Object References Instead of Object Contents</li>\n </ul>",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "squid:AstNode_SSLR_class_should_not_be_used",
+ "name": "AstNode SSLR class should not be used",
+ "lang": "java",
+ "desc": "Once strongly typed AST is in place on a language plugin, the AstNode class should not be used anymore. ",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "squid:IndentationCheck",
+ "name": "Source code should be correctly indented",
+ "lang": "java",
+ "desc": "<p>\nProper indentation is a simple and effective way to improve the code's readability.\nConsistent indentation among developers also reduces the differences that are committed to source control systems, making code reviews easier.\n</p>\n\n<p>The following code illustrates this rule with an indentation level of 2:</p>\n\n<pre>\nclass Foo {\n public int a; // Compliant\npublic int b; // Non-Compliant\n}\n</pre>",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "squid:S1161",
+ "name": "\"@Override\" annotation should be used on any method overriding (since Java 5) or implementing (since Java 6) another one",
+ "lang": "java",
+ "desc": "<p>Using the <code>@Override</code> annotation is useful for two reasons :</p>\n<ul>\n <li>It elicits a warning from the compiler if the annotated method doesn't actually override anything, as in the case of a misspelling.</li>\n <li>It improves the readability of the source code by making it obvious that methods are overridden.</li>\n</ul>\n<h2>Noncompliant Code Example</h2>\n<pre>\nclass ParentClass {\n public boolean doSomething(){...}\n}\nclass FirstChildClass extends ParentClass {\n public boolean doSomething(){...} //Non-Compliant\n}\n</pre>\n\n<h2>Compliant Solution</h2>\n<pre>\nclass ParentClass {\n public boolean doSomething(){...}\n}\nclass FirstChildClass extends ParentClass {\n @Override\n public boolean doSomething(){...} //Compliant\n}\n</pre>",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "common-java:DuplicatedBlocks",
+ "name": "Duplicated blocks",
+ "lang": "java",
+ "desc": "<p>An issue is created on a file as soon as there is a block of duplicated code on this file. It gives the number of blocks in the file.</p>",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "squid:S1192",
+ "name": "String literals should not be duplicated",
+ "lang": "java",
+ "desc": "<p>\n Duplicated string literals make the process of refactoring error-prone, since you must be sure to update all occurrences.\n On the other hand, constants can be referenced from many places, but only need to be updated in a single place.\n</p>\n\n<h2>Non Compliant Code Example</h2>\n\n<pre>\npublic void run() {\n prepare(\"action1\"); // Non-Compliant - \"action1\" is duplicated 3 times\n execute(\"action1\");\n release(\"action1\");\n}\n\n@SuppressWarning(\"all\") // Compliant - annotations are excluded\nprivate void method1() { /* ... */ }\n@SuppressWarning(\"all\")\nprivate void method2() { /* ... */ }\n\npublic String method3(String a) {\n System.out.println(\"'\" + a + \"'\"); // Compliant - literal \"'\" has less than 5 characters and is excluded\n return \"\"; // Compliant - literal \"\" has less than 5 characters and is excluded\n}\n</pre>\n\n<h2>Compliant Code Example</h2>\n\n<pre>\nprivate static final String ACTION_1 = \"action1\"; // Compliant\n\npublic void run() {\n prepare(ACTION_1); // Compliant\n execute(ACTION_1);\n release(ACTION_1);\n}\n</pre>\n\n<h2>Exceptions</h2>\n<p>To prevent generating some false-positives, literals having less than 5 characters are excluded.</p>",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "squid:MethodCyclomaticComplexity",
+ "name": "Methods should not be too complex",
+ "lang": "java",
+ "desc": "<p>The Cyclomatic Complexity is measured by the number of\n\t(&amp;&amp;, ||) operators and (if, while, do, for, ?:, catch, switch,\n\tcase, return, throw) statements in the body of a class plus one for\n\teach constructor, method (but not getter/setter), static initializer,\n\tor instance initializer in the class. The last return statement in\n\tmethod, if exists, is not taken into account.</p>\n<p>\n\tEven when the Cyclomatic Complexity of a class is very high, this\n\tcomplexity might be well distributed among all methods. Nevertheless,\n\tmost of the time, a very complex class is a class which breaks the <a\n\t\thref=\"http://en.wikipedia.org/wiki/Single_responsibility_principle\">Single\n\t\tResponsibility Principle</a> and which should be re-factored to be split\n\tin several classes.\n</p>",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "squid:S1135",
+ "name": "TODO tags should be handled",
+ "lang": "java",
+ "desc": "<p>\n<code>TODO</code> tags are commonly used to mark places where some more code is required, but which the developer wants to implement later.\nSometimes the developer will not have the time or will simply forget to get back to that tag.\nThis rule is meant to track those tags, and ensure that they do not go unnoticed.\n</p>\n\n<p>The following code illustrates this rule:</p>\n\n<pre>\nvoid doSomething() {\n // TODO\n}\n</pre>",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "common-java:InsufficientBranchCoverage",
+ "name": "Insufficient branch coverage by unit tests",
+ "lang": "java",
+ "desc": "<p>An issue is created on a file as soon as the branch coverage on this file is less than the required threshold.It gives the number of branches to be covered in order to reach the required threshold.</p>",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "squid:S00115",
+ "name": "Constant names should comply with a naming convention",
+ "lang": "java",
+ "desc": "<p>\nSharing some naming conventions is a key point to make it possible for a team to efficiently collaborate. This rule allows to check that all constant names match a provided regular expression.\n</p>\n\n<p>\nThe following code snippet illustrates this rule when the regular expression value is \"^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$\":\n</p>\n<pre>\npublic class MyClass {\n public static final int first = 1; // Non-Compliant\n public static final int SECOND = 2; // Compliant\n}\n\npublic enum MyEnum {\n first, // Non-Compliant\n SECOND; // Compliant\n}\n</pre>",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "squid:S1134",
+ "name": "FIXME tags should be handled",
+ "lang": "java",
+ "desc": "<p>\n<code>FIXME</code> tags are commonly used to mark places where a bug is suspected, but which the developer wants to deal with later.\nSometimes the developer will not have the time or will simply forget to get back to that tag.\nThis rule is meant to track those tags, and ensure that they do not go unnoticed.\n</p>\n\n<p>The following code illustrates this rule:</p>\n\n<pre>\nint divide(int numerator, int denominator) {\n return numerator / denominator; // FIXME denominator = 0, Non-Compliant\n}\n</pre>",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "squid:S1133",
+ "name": "Deprecated code should be removed eventually",
+ "lang": "java",
+ "desc": "<p>\nThis rule is meant to be used as a way to track code which is marked as being deprecated.\nDeprecated code should eventually be removed.\n</p>\n\n<p>\nThe following code illustrates this rule:\n</p>\n\n<pre>\nclass Foo {\n /**\n * @deprecated\n */\n public void foo() { // Non-Compliant\n }\n\n @Deprecated // Non-Compliant\n public void bar() {\n }\n\n public void baz() { // Compliant\n }\n}\n</pre>",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "squid:CallToDeprecatedMethod",
+ "name": "Avoid use of deprecated method",
+ "lang": "java",
+ "desc": "<p>Once deprecated, a method should no longer be used as it means\n\tthat the method might be removed sooner or later.</p>",
+ "status": "READY",
+ "langName": "Java"
+ },
+ {
+ "key": "squid:S1228",
+ "name": "Packages should have a javadoc file 'package-info.java'",
+ "lang": "java",
+ "desc": "<p>Each package in a Java project should include a <code>package-info.java</code> file. The purpose of this file is to document the Java package using javadoc and declare package annotations.</p>\n\n<h2>Compliant Solution</h2>\n<pre>\n/**\n* This package has non null parameters and is documented.\n**/\n@ParametersAreNonnullByDefault\npackage org.foo.bar;\n</pre>",
+ "status": "READY",
+ "langName": "Java"
+ }
+ ],
+ "facets": [
+ {
+ "property": "rules",
+ "values": [
+ {
+ "val": "squid:S1161",
+ "count": 879
+ },
+ {
+ "val": "squid:S1135",
+ "count": 571
+ },
+ {
+ "val": "squid:S1133",
+ "count": 558
+ },
+ {
+ "val": "common-java:InsufficientBranchCoverage",
+ "count": 550
+ },
+ {
+ "val": "common-java:DuplicatedBlocks",
+ "count": 408
+ },
+ {
+ "val": "squid:AstNode_SSLR_class_should_not_be_used",
+ "count": 265
+ },
+ {
+ "val": "squid:IndentationCheck",
+ "count": 264
+ },
+ {
+ "val": "squid:CallToDeprecatedMethod",
+ "count": 237
+ },
+ {
+ "val": "squid:MethodCyclomaticComplexity",
+ "count": 233
+ },
+ {
+ "val": "squid:S00115",
+ "count": 212
+ },
+ {
+ "val": "resharper-cs:RedundantUsingDirective",
+ "count": 175
+ },
+ {
+ "val": "squid:S1228",
+ "count": 174
+ },
+ {
+ "val": "squid:S1698",
+ "count": 139
+ },
+ {
+ "val": "squid:S1134",
+ "count": 113
+ },
+ {
+ "val": "squid:S1192",
+ "count": 111
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-severity.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-severity.json
new file mode 100644
index 00000000000..f261766748c
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-severity.json
@@ -0,0 +1,32 @@
+{
+ "total": 6851,
+ "p": 1,
+ "ps": 1,
+ "facets": [
+ {
+ "property": "severities",
+ "values": [
+ {
+ "val": "MAJOR",
+ "count": 5027
+ },
+ {
+ "val": "INFO",
+ "count": 1178
+ },
+ {
+ "val": "MINOR",
+ "count": 540
+ },
+ {
+ "val": "CRITICAL",
+ "count": 105
+ },
+ {
+ "val": "BLOCKER",
+ "count": 1
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unassigned-issues-by-assignee.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unassigned-issues-by-assignee.json
new file mode 100644
index 00000000000..eec6932ed8c
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unassigned-issues-by-assignee.json
@@ -0,0 +1,48 @@
+{
+ "total": 4134,
+ "p": 1,
+ "ps": 1,
+ "users": [
+ {
+ "login": "second.user",
+ "name": "Second User",
+ "active": true,
+ "email": "second.user@example.com"
+ },
+ {
+ "login": "third.user",
+ "name": "Third User",
+ "active": true,
+ "email": "third.user@example .com"
+ },
+ {
+ "login": "first.user",
+ "name": "First User",
+ "active": true,
+ "email": "first.user@example.com"
+ }
+ ],
+ "facets": [
+ {
+ "property": "assignees",
+ "values": [
+ {
+ "val": "",
+ "count": 4134
+ },
+ {
+ "val": "first.user",
+ "count": 698
+ },
+ {
+ "val": "second.user",
+ "count": 504
+ },
+ {
+ "val": "third.user",
+ "count": 426
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unplanned-issues-by-action-plan.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unplanned-issues-by-action-plan.json
new file mode 100644
index 00000000000..94eba943db2
--- /dev/null
+++ b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unplanned-issues-by-action-plan.json
@@ -0,0 +1,63 @@
+{
+ "total": 5877,
+ "p": 1,
+ "ps": 1,
+ "actionPlans": [
+ {
+ "key": "0cf48508-2fcd-4cb8-a50b-c5cd7c3decc0",
+ "name": "First Action Plan",
+ "status": "OPEN",
+ "project": "example:project",
+ "userLogin": "example.login",
+ "createdAt": "2014-04-03T12:28:05+0200",
+ "fCreatedAt": "Apr 3, 2014 12:28 PM",
+ "updatedAt": "2014-04-03T12:28:05+0200",
+ "fUpdatedAt": "Apr 3, 2014 12:28 PM"
+ },
+ {
+ "key": "1b9e7e52-ff58-40c1-80bf-f68429a3275e",
+ "name": "Second Action Plan",
+ "status": "OPEN",
+ "project": "example:project",
+ "userLogin": "example.login",
+ "createdAt": "2014-04-03T12:28:05+0200",
+ "fCreatedAt": "Apr 3, 2014 12:28 PM",
+ "updatedAt": "2014-04-03T12:28:05+0200",
+ "fUpdatedAt": "Apr 3, 2014 12:28 PM"
+ },
+ {
+ "key": "8c1d5d01-948e-4670-a0d9-17c512979486",
+ "name": "Third Action Plan",
+ "status": "OPEN",
+ "project": "example:project",
+ "userLogin": "example.login",
+ "createdAt": "2014-04-03T12:28:05+0200",
+ "fCreatedAt": "Apr 3, 2014 12:28 PM",
+ "updatedAt": "2014-04-03T12:28:05+0200",
+ "fUpdatedAt": "Apr 3, 2014 12:28 PM"
+ }
+ ],
+ "facets": [
+ {
+ "property": "actionPlans",
+ "values": [
+ {
+ "val": "",
+ "count": 5877
+ },
+ {
+ "val": "0cf48508-2fcd-4cb8-a50b-c5cd7c3decc0",
+ "count": 532
+ },
+ {
+ "val": "1b9e7e52-ff58-40c1-80bf-f68429a3275e",
+ "count": 56
+ },
+ {
+ "val": "8c1d5d01-948e-4670-a0d9-17c512979486",
+ "count": 52
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink/app.json b/server/sonar-web/src/test/json/issues-page-should-open-issue-permalink/app.json
index 1006684e0c9..1006684e0c9 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink/app.json
+++ b/server/sonar-web/src/test/json/issues-page-should-open-issue-permalink/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink/components-app.json b/server/sonar-web/src/test/json/issues-page-should-open-issue-permalink/components-app.json
index 61afe8a34c8..61afe8a34c8 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink/components-app.json
+++ b/server/sonar-web/src/test/json/issues-page-should-open-issue-permalink/components-app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink/lines.json b/server/sonar-web/src/test/json/issues-page-should-open-issue-permalink/lines.json
index cd2053d91d6..cd2053d91d6 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink/lines.json
+++ b/server/sonar-web/src/test/json/issues-page-should-open-issue-permalink/lines.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink/search.json b/server/sonar-web/src/test/json/issues-page-should-open-issue-permalink/search.json
index 655e7492bd7..655e7492bd7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-page-should-open-issue-permalink/search.json
+++ b/server/sonar-web/src/test/json/issues-page-should-open-issue-permalink/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/app.json b/server/sonar-web/src/test/json/issues-spec/app.json
index 604ef7c79f1..604ef7c79f1 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/app.json
+++ b/server/sonar-web/src/test/json/issues-spec/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/file-level/components-app.json b/server/sonar-web/src/test/json/issues-spec/file-level/components-app.json
index 537dd0787a8..537dd0787a8 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/file-level/components-app.json
+++ b/server/sonar-web/src/test/json/issues-spec/file-level/components-app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/file-level/lines.json b/server/sonar-web/src/test/json/issues-spec/file-level/lines.json
index 18a670b8522..18a670b8522 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/file-level/lines.json
+++ b/server/sonar-web/src/test/json/issues-spec/file-level/lines.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/file-level/search.json b/server/sonar-web/src/test/json/issues-spec/file-level/search.json
index 5ea06f0c717..5ea06f0c717 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/file-level/search.json
+++ b/server/sonar-web/src/test/json/issues-spec/file-level/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/search-reopened.json b/server/sonar-web/src/test/json/issues-spec/search-reopened.json
index efd73bce04a..efd73bce04a 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/search-reopened.json
+++ b/server/sonar-web/src/test/json/issues-spec/search-reopened.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/search-with-tags.json b/server/sonar-web/src/test/json/issues-spec/search-with-tags.json
index 442b1de359a..442b1de359a 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/search-with-tags.json
+++ b/server/sonar-web/src/test/json/issues-spec/search-with-tags.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/search.json b/server/sonar-web/src/test/json/issues-spec/search.json
index 3dbc631468b..3dbc631468b 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/search.json
+++ b/server/sonar-web/src/test/json/issues-spec/search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/show-open.json b/server/sonar-web/src/test/json/issues-spec/show-open.json
index 071d6bde7c4..071d6bde7c4 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/show-open.json
+++ b/server/sonar-web/src/test/json/issues-spec/show-open.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/show-resolved.json b/server/sonar-web/src/test/json/issues-spec/show-resolved.json
index f4eab749601..f4eab749601 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/show-resolved.json
+++ b/server/sonar-web/src/test/json/issues-spec/show-resolved.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/show-with-tags.json b/server/sonar-web/src/test/json/issues-spec/show-with-tags.json
index 6eb9475a066..6eb9475a066 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/show-with-tags.json
+++ b/server/sonar-web/src/test/json/issues-spec/show-with-tags.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/show.json b/server/sonar-web/src/test/json/issues-spec/show.json
index c125f5f96c2..c125f5f96c2 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/show.json
+++ b/server/sonar-web/src/test/json/issues-spec/show.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/tags-modified.json b/server/sonar-web/src/test/json/issues-spec/tags-modified.json
index d1b53890ee3..d1b53890ee3 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/tags-modified.json
+++ b/server/sonar-web/src/test/json/issues-spec/tags-modified.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/tags.json b/server/sonar-web/src/test/json/issues-spec/tags.json
index af6bc92e0b4..af6bc92e0b4 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/issues-spec/tags.json
+++ b/server/sonar-web/src/test/json/issues-spec/tags.json
diff --git a/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-date.json b/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-date.json
new file mode 100644
index 00000000000..54153d9897b
--- /dev/null
+++ b/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-date.json
@@ -0,0 +1,32 @@
+{
+ "total": 6851,
+ "p": 1,
+ "ps": 1,
+ "facets": [
+ {
+ "property": "createdAt",
+ "values": [
+ {
+ "val": "2011-01-01T01:00:00+0000",
+ "count": 72
+ },
+ {
+ "val": "2012-01-01T01:00:00+0000",
+ "count": 64
+ },
+ {
+ "val": "2013-01-01T01:00:00+0000",
+ "count": 1262
+ },
+ {
+ "val": "2014-01-01T01:00:00+0000",
+ "count": 3729
+ },
+ {
+ "val": "2015-01-01T01:00:00+0000",
+ "count": 1724
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity-with-differential-period.json b/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity-with-differential-period.json
new file mode 100644
index 00000000000..afa5ed4f5cc
--- /dev/null
+++ b/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity-with-differential-period.json
@@ -0,0 +1,32 @@
+{
+ "total": 549,
+ "p": 1,
+ "ps": 1,
+ "facets": [
+ {
+ "property": "severities",
+ "values": [
+ {
+ "val": "MAJOR",
+ "count": 306
+ },
+ {
+ "val": "MINOR",
+ "count": 135
+ },
+ {
+ "val": "CRITICAL",
+ "count": 59
+ },
+ {
+ "val": "INFO",
+ "count": 49
+ },
+ {
+ "val": "BLOCKER",
+ "count": 0
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity.json b/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity.json
new file mode 100644
index 00000000000..f261766748c
--- /dev/null
+++ b/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity.json
@@ -0,0 +1,32 @@
+{
+ "total": 6851,
+ "p": 1,
+ "ps": 1,
+ "facets": [
+ {
+ "property": "severities",
+ "values": [
+ {
+ "val": "MAJOR",
+ "count": 5027
+ },
+ {
+ "val": "INFO",
+ "count": 1178
+ },
+ {
+ "val": "MINOR",
+ "count": 540
+ },
+ {
+ "val": "CRITICAL",
+ "count": 105
+ },
+ {
+ "val": "BLOCKER",
+ "count": 1
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec/app.json b/server/sonar-web/src/test/json/quality-gates-spec/app.json
index 6a38a3ed8b5..6a38a3ed8b5 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec/app.json
+++ b/server/sonar-web/src/test/json/quality-gates-spec/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec/list.json b/server/sonar-web/src/test/json/quality-gates-spec/list.json
index 9d7ac911b05..9d7ac911b05 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec/list.json
+++ b/server/sonar-web/src/test/json/quality-gates-spec/list.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec/show.json b/server/sonar-web/src/test/json/quality-gates-spec/show.json
index bc36acb897e..bc36acb897e 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec/show.json
+++ b/server/sonar-web/src/test/json/quality-gates-spec/show.json
diff --git a/server/sonar-web/src/test/json/source-viewer-coverage/app.json b/server/sonar-web/src/test/json/source-viewer-coverage/app.json
new file mode 100644
index 00000000000..bfee785a15c
--- /dev/null
+++ b/server/sonar-web/src/test/json/source-viewer-coverage/app.json
@@ -0,0 +1,19 @@
+{
+ "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaaa",
+ "key": "sample:sample",
+ "path": "sample/path",
+ "name": "Sample",
+ "longName": "Sample",
+ "q": "FIL",
+ "subProject": "sample:subproject",
+ "subProjectName": "Sample Sub-Project",
+ "project": "sample:project",
+ "projectName": "Sample Project",
+ "fav": false,
+ "canMarkAsFavourite": true,
+ "canCreateManualIssue": true,
+ "measures": {
+ "lines": "20",
+ "duplicationDensity": "25%"
+ }
+}
diff --git a/server/sonar-web/src/test/json/source-viewer-coverage/issues.json b/server/sonar-web/src/test/json/source-viewer-coverage/issues.json
new file mode 100644
index 00000000000..40edd884b11
--- /dev/null
+++ b/server/sonar-web/src/test/json/source-viewer-coverage/issues.json
@@ -0,0 +1,14 @@
+{
+ "total": 0,
+ "p": 1,
+ "ps": 100,
+ "issues": [],
+ "maxResultsReached": false,
+ "paging": {
+ "pageIndex": 1,
+ "pageSize": 100,
+ "total": 0,
+ "fTotal": "0",
+ "pages": 1
+ }
+}
diff --git a/server/sonar-web/src/test/json/source-viewer-coverage/lines.json b/server/sonar-web/src/test/json/source-viewer-coverage/lines.json
new file mode 100644
index 00000000000..3b0947ab08b
--- /dev/null
+++ b/server/sonar-web/src/test/json/source-viewer-coverage/lines.json
@@ -0,0 +1,18 @@
+{"sources": [
+ { "line": 1, "code": "line 1" },
+ { "line": 2, "code": "line 2" },
+ { "line": 3, "code": "line 3" },
+ { "line": 4, "code": "line 4" },
+ { "line": 5, "code": "line 5" },
+ { "line": 6, "code": "line 6" },
+ { "line": 7, "code": "line 7" },
+ { "line": 8, "code": "line 8" },
+ { "line": 9, "code": "line 9" },
+ { "line": 10, "code": "line 10" },
+ { "line": 11, "code": "line 11", "utLineHits": 3 },
+ { "line": 16, "code": "line 16" },
+ { "line": 17, "code": "line 17" },
+ { "line": 18, "code": "line 18" },
+ { "line": 19, "code": "line 19" },
+ { "line": 20, "code": "line 20" }
+]}
diff --git a/server/sonar-web/src/test/json/source-viewer-coverage/test-cases.json b/server/sonar-web/src/test/json/source-viewer-coverage/test-cases.json
new file mode 100644
index 00000000000..db0ef3fb827
--- /dev/null
+++ b/server/sonar-web/src/test/json/source-viewer-coverage/test-cases.json
@@ -0,0 +1,17 @@
+{
+ "tests": [
+ {
+ "name": "sampleTest",
+ "status": "OK",
+ "durationInMs": 2,
+ "_ref": "1"
+ }
+ ],
+ "files": {
+ "1": {
+ "uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbbb",
+ "key": "test:sample",
+ "longName": "SampleTest"
+ }
+ }
+}
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/api-rules-search.json b/server/sonar-web/src/test/json/source-viewer-create-manual-issue/api-rules-search.json
index 9a176d3e06a..9a176d3e06a 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/api-rules-search.json
+++ b/server/sonar-web/src/test/json/source-viewer-create-manual-issue/api-rules-search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/app.json b/server/sonar-web/src/test/json/source-viewer-create-manual-issue/app.json
index dd6a3fb900f..dd6a3fb900f 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/app.json
+++ b/server/sonar-web/src/test/json/source-viewer-create-manual-issue/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/create-issue.json b/server/sonar-web/src/test/json/source-viewer-create-manual-issue/create-issue.json
index db69ef34a93..db69ef34a93 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/create-issue.json
+++ b/server/sonar-web/src/test/json/source-viewer-create-manual-issue/create-issue.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/issues.json b/server/sonar-web/src/test/json/source-viewer-create-manual-issue/issues.json
index 0b1601191ef..0b1601191ef 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/issues.json
+++ b/server/sonar-web/src/test/json/source-viewer-create-manual-issue/issues.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/lines.json b/server/sonar-web/src/test/json/source-viewer-create-manual-issue/lines.json
index e33d02b2465..2983d8e4728 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-create-manual-issue/lines.json
+++ b/server/sonar-web/src/test/json/source-viewer-create-manual-issue/lines.json
@@ -313,7 +313,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 46,
@@ -321,7 +321,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 47,
@@ -329,7 +329,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 48,
@@ -337,7 +337,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 49,
@@ -359,7 +359,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 52,
@@ -367,7 +367,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 53,
@@ -396,7 +396,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 57,
@@ -404,7 +404,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 58,
@@ -433,7 +433,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 62,
@@ -441,7 +441,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 63,
@@ -470,7 +470,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 67,
@@ -478,7 +478,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 68,
@@ -514,7 +514,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 73,
@@ -522,7 +522,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 74,
@@ -530,7 +530,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 75,
@@ -538,7 +538,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 76,
@@ -546,7 +546,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 77,
@@ -603,7 +603,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 85,
@@ -611,7 +611,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 86,
@@ -668,7 +668,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 94,
@@ -676,7 +676,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 95,
@@ -733,7 +733,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 103,
@@ -741,7 +741,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 104,
@@ -798,7 +798,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 112,
@@ -806,7 +806,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 113,
@@ -856,7 +856,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 120,
@@ -864,9 +864,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 2
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 2
},
{
"line": 121,
@@ -874,7 +874,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 122,
@@ -889,7 +889,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 124,
@@ -897,7 +897,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 125,
@@ -912,7 +912,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 127,
@@ -948,7 +948,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 132,
@@ -956,7 +956,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 133,
@@ -985,7 +985,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 137,
@@ -993,7 +993,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 138,
@@ -1022,7 +1022,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 142,
@@ -1030,7 +1030,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 143,
@@ -1059,7 +1059,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 147,
@@ -1067,7 +1067,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 148,
@@ -1103,7 +1103,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e108f5de333cf36aff978aa03940590f9caca9fc",
"scmDate": "2013-10-10T12:18:02+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 153,
@@ -1111,7 +1111,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e108f5de333cf36aff978aa03940590f9caca9fc",
"scmDate": "2013-10-10T12:18:02+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 154,
@@ -1119,7 +1119,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e108f5de333cf36aff978aa03940590f9caca9fc",
"scmDate": "2013-10-10T12:18:02+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 155,
@@ -1134,7 +1134,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e108f5de333cf36aff978aa03940590f9caca9fc",
"scmDate": "2013-10-10T12:18:02+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 157,
@@ -1170,7 +1170,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 162,
@@ -1178,7 +1178,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 163,
@@ -1207,7 +1207,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 167,
@@ -1215,7 +1215,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 168,
@@ -1244,7 +1244,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 172,
@@ -1252,7 +1252,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 173,
@@ -1281,7 +1281,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 177,
@@ -1289,7 +1289,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 178,
@@ -1325,7 +1325,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "6f1161efb92298ace498df544e38f6f97216ec36",
"scmDate": "2013-04-26T15:19:16+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 183,
@@ -1333,7 +1333,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 184,
@@ -1348,7 +1348,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 186,
@@ -1419,7 +1419,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 196,
@@ -1427,7 +1427,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 197,
@@ -1456,7 +1456,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 201,
@@ -1464,7 +1464,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 202,
@@ -1493,7 +1493,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 206,
@@ -1501,7 +1501,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 207,
@@ -1530,7 +1530,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 211,
@@ -1538,7 +1538,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 212,
@@ -1574,7 +1574,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 217,
@@ -1582,7 +1582,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 218,
@@ -1590,7 +1590,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 219,
@@ -1598,7 +1598,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 220,
@@ -1606,7 +1606,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 221,
@@ -1614,7 +1614,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 222,
@@ -1678,7 +1678,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 231,
@@ -1686,7 +1686,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 232,
@@ -1694,7 +1694,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 233,
@@ -1702,7 +1702,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 234,
@@ -1710,7 +1710,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 235,
@@ -1718,7 +1718,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 236,
@@ -1803,7 +1803,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 248,
@@ -1811,7 +1811,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 249,
@@ -1819,7 +1819,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 250,
@@ -1827,7 +1827,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 251,
@@ -1835,7 +1835,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 252,
@@ -1843,9 +1843,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 2
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 2
},
{
"line": 253,
@@ -1853,7 +1853,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 254,
@@ -1868,7 +1868,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 256,
@@ -1876,7 +1876,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 257,
@@ -1884,7 +1884,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 258,
@@ -1934,7 +1934,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 265,
@@ -1942,7 +1942,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 266,
@@ -1950,7 +1950,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 267,
@@ -1958,7 +1958,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 268,
@@ -1966,7 +1966,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 269,
@@ -1974,7 +1974,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 270,
@@ -1982,9 +1982,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 2
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 2
},
{
"line": 271,
@@ -1992,7 +1992,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 272,
@@ -2007,7 +2007,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 274,
@@ -2015,7 +2015,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 275,
@@ -2023,7 +2023,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 276,
@@ -2101,7 +2101,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 287,
@@ -2109,7 +2109,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 288,
@@ -2117,7 +2117,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 289,
@@ -2125,7 +2125,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 290,
@@ -2133,9 +2133,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 2
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 2
},
{
"line": 291,
@@ -2143,7 +2143,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 292,
@@ -2158,7 +2158,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 294,
@@ -2166,7 +2166,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 295,
@@ -2174,7 +2174,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 296,
@@ -2238,7 +2238,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "171cd79c0b5152461434951ed5d6e5e58849a7b7",
"scmDate": "2014-04-23T14:41:32+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 305,
@@ -2246,7 +2246,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "171cd79c0b5152461434951ed5d6e5e58849a7b7",
"scmDate": "2014-04-23T14:41:32+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 306,
@@ -2254,7 +2254,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "171cd79c0b5152461434951ed5d6e5e58849a7b7",
"scmDate": "2014-04-23T14:41:32+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 307,
@@ -2262,7 +2262,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 308,
@@ -2270,7 +2270,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 309,
@@ -2278,7 +2278,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "171cd79c0b5152461434951ed5d6e5e58849a7b7",
"scmDate": "2014-04-23T14:41:32+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 310,
@@ -2286,7 +2286,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "904b462c56317b1fb5a616534bd58aa9c9097d0b",
"scmDate": "2014-06-20T14:13:01+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 311,
@@ -2322,7 +2322,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "904b462c56317b1fb5a616534bd58aa9c9097d0b",
"scmDate": "2014-06-20T14:13:01+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 316,
@@ -2379,7 +2379,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 324,
@@ -2387,7 +2387,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 325,
@@ -2395,7 +2395,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 326,
@@ -2403,7 +2403,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 327,
@@ -2411,7 +2411,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 328,
@@ -2419,7 +2419,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "46395126b184c343df5471a147cdb48133f59f6f",
"scmDate": "2014-04-23T14:41:32+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 329,
@@ -2427,7 +2427,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "904b462c56317b1fb5a616534bd58aa9c9097d0b",
"scmDate": "2014-06-20T14:13:01+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 330,
@@ -2491,7 +2491,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 339,
@@ -2499,7 +2499,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 340,
@@ -2507,7 +2507,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 341,
@@ -2515,7 +2515,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 342,
@@ -2523,7 +2523,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 343,
@@ -2531,7 +2531,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "904b462c56317b1fb5a616534bd58aa9c9097d0b",
"scmDate": "2014-06-20T14:13:01+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 344,
@@ -2567,7 +2567,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 349,
@@ -2575,7 +2575,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 350,
@@ -2583,7 +2583,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 351,
@@ -2612,7 +2612,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 355,
@@ -2620,7 +2620,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 356,
@@ -2628,7 +2628,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 357,
@@ -2657,7 +2657,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 361,
@@ -2665,7 +2665,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 362,
@@ -2673,7 +2673,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 363,
@@ -2695,7 +2695,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 366,
@@ -2703,7 +2703,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 367,
@@ -2711,7 +2711,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 368,
@@ -2733,7 +2733,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 371,
@@ -2741,7 +2741,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 372,
@@ -2749,7 +2749,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 373,
@@ -2771,7 +2771,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 376,
@@ -2779,9 +2779,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0,
- "conditions": 2,
- "coveredConditions": 0
+ "utLineHits": 0,
+ "utConditions": 2,
+ "utCoveredConditions": 0
},
{
"line": 377,
@@ -2789,7 +2789,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 378,
@@ -2804,7 +2804,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 380,
@@ -2868,7 +2868,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 389,
@@ -2876,7 +2876,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 390,
@@ -2884,7 +2884,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 391,
@@ -2913,7 +2913,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 395,
@@ -2970,7 +2970,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 403,
@@ -2978,7 +2978,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -2987,7 +2987,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -2996,7 +2996,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -3037,7 +3037,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -3046,7 +3046,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 0,
+ "utLineHits": 0,
"duplicated": true
},
{
@@ -3055,7 +3055,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 0,
+ "utLineHits": 0,
"duplicated": true
},
{
@@ -3118,7 +3118,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 421,
@@ -3126,7 +3126,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 422,
@@ -3134,7 +3134,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 423,
@@ -3142,7 +3142,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 424,
@@ -3150,9 +3150,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 1
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 1
},
{
"line": 425,
@@ -3160,7 +3160,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 426,
@@ -3175,7 +3175,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 428,
@@ -3211,7 +3211,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "34cce8e330192c56a159a856ebd8072d38299087",
"scmDate": "2014-02-24T14:21:50+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 433,
@@ -3261,7 +3261,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 440,
@@ -3269,7 +3269,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 441,
@@ -3277,7 +3277,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 442,
@@ -3306,7 +3306,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 446,
@@ -3363,7 +3363,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 454,
@@ -3371,7 +3371,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -3380,7 +3380,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -3389,7 +3389,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -3430,7 +3430,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -3439,7 +3439,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 0,
+ "utLineHits": 0,
"duplicated": true
},
{
@@ -3448,7 +3448,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 0,
+ "utLineHits": 0,
"duplicated": true
},
{
@@ -3511,7 +3511,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 472,
@@ -3519,7 +3519,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 473,
@@ -3527,7 +3527,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 474,
@@ -3535,7 +3535,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 475,
@@ -3543,9 +3543,9 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 1
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 1
},
{
"line": 476,
@@ -3553,7 +3553,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 477,
@@ -3561,7 +3561,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 478,
@@ -3569,7 +3569,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 479,
@@ -3577,9 +3577,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 2
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 2
},
{
"line": 480,
@@ -3587,7 +3587,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 481,
@@ -3602,7 +3602,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 483,
@@ -3617,7 +3617,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 485,
@@ -3653,7 +3653,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "34cce8e330192c56a159a856ebd8072d38299087",
"scmDate": "2014-02-24T14:21:50+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 490,
@@ -3710,7 +3710,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 498,
@@ -3718,7 +3718,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 499,
@@ -3726,7 +3726,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 500,
@@ -3734,7 +3734,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 501,
@@ -3756,7 +3756,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 504,
@@ -3792,7 +3792,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 509,
@@ -3828,7 +3828,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 514,
diff --git a/server/sonar-web/src/test/json/source-viewer-duplications/app.json b/server/sonar-web/src/test/json/source-viewer-duplications/app.json
new file mode 100644
index 00000000000..bfee785a15c
--- /dev/null
+++ b/server/sonar-web/src/test/json/source-viewer-duplications/app.json
@@ -0,0 +1,19 @@
+{
+ "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaaa",
+ "key": "sample:sample",
+ "path": "sample/path",
+ "name": "Sample",
+ "longName": "Sample",
+ "q": "FIL",
+ "subProject": "sample:subproject",
+ "subProjectName": "Sample Sub-Project",
+ "project": "sample:project",
+ "projectName": "Sample Project",
+ "fav": false,
+ "canMarkAsFavourite": true,
+ "canCreateManualIssue": true,
+ "measures": {
+ "lines": "20",
+ "duplicationDensity": "25%"
+ }
+}
diff --git a/server/sonar-web/src/test/json/source-viewer-duplications/duplications.json b/server/sonar-web/src/test/json/source-viewer-duplications/duplications.json
new file mode 100644
index 00000000000..7da4385b3a5
--- /dev/null
+++ b/server/sonar-web/src/test/json/source-viewer-duplications/duplications.json
@@ -0,0 +1,41 @@
+{
+ "duplications": [
+ {
+ "blocks": [
+ {
+ "from": 11,
+ "size": 5,
+ "_ref": "1"
+ },
+ {
+ "from": 12,
+ "size": 5,
+ "_ref": "2"
+ }
+ ]
+ }
+ ],
+ "files": {
+ "2": {
+ "uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbbb",
+ "key": "duplicated:duplicated",
+ "name": "Duplicated",
+ "q": "FIL",
+ "subProject": "duplicated:subproject",
+ "subProjectName": "Duplicated Sub-Project",
+ "project": "duplicated:project",
+ "projectName": "Duplicated Project"
+ },
+ "1": {
+ "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaaa",
+ "key": "sample:sample",
+ "name": "Sample",
+ "longName": "Sample",
+ "q": "FIL",
+ "subProject": "sample:subproject",
+ "subProjectName": "Sample Sub-Project",
+ "project": "sample:project",
+ "projectName": "Sample Project"
+ }
+ }
+}
diff --git a/server/sonar-web/src/test/json/source-viewer-duplications/issues.json b/server/sonar-web/src/test/json/source-viewer-duplications/issues.json
new file mode 100644
index 00000000000..40edd884b11
--- /dev/null
+++ b/server/sonar-web/src/test/json/source-viewer-duplications/issues.json
@@ -0,0 +1,14 @@
+{
+ "total": 0,
+ "p": 1,
+ "ps": 100,
+ "issues": [],
+ "maxResultsReached": false,
+ "paging": {
+ "pageIndex": 1,
+ "pageSize": 100,
+ "total": 0,
+ "fTotal": "0",
+ "pages": 1
+ }
+}
diff --git a/server/sonar-web/src/test/json/source-viewer-duplications/lines.json b/server/sonar-web/src/test/json/source-viewer-duplications/lines.json
new file mode 100644
index 00000000000..5fc7b0cb4de
--- /dev/null
+++ b/server/sonar-web/src/test/json/source-viewer-duplications/lines.json
@@ -0,0 +1,22 @@
+{"sources": [
+ { "line": 1, "code": "line 1" },
+ { "line": 2, "code": "line 2" },
+ { "line": 3, "code": "line 3" },
+ { "line": 4, "code": "line 4" },
+ { "line": 5, "code": "line 5" },
+ { "line": 6, "code": "line 6" },
+ { "line": 7, "code": "line 7" },
+ { "line": 8, "code": "line 8" },
+ { "line": 9, "code": "line 9" },
+ { "line": 10, "code": "line 10" },
+ { "line": 11, "code": "line 11", "duplicated": true },
+ { "line": 12, "code": "line 12", "duplicated": true },
+ { "line": 13, "code": "line 13", "duplicated": true },
+ { "line": 14, "code": "line 14", "duplicated": true },
+ { "line": 15, "code": "line 15", "duplicated": true },
+ { "line": 16, "code": "line 16" },
+ { "line": 17, "code": "line 17" },
+ { "line": 18, "code": "line 18" },
+ { "line": 19, "code": "line 19" },
+ { "line": 20, "code": "line 20" }
+]}
diff --git a/server/sonar-web/src/test/json/source-viewer-scm/app.json b/server/sonar-web/src/test/json/source-viewer-scm/app.json
new file mode 100644
index 00000000000..bfee785a15c
--- /dev/null
+++ b/server/sonar-web/src/test/json/source-viewer-scm/app.json
@@ -0,0 +1,19 @@
+{
+ "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaaa",
+ "key": "sample:sample",
+ "path": "sample/path",
+ "name": "Sample",
+ "longName": "Sample",
+ "q": "FIL",
+ "subProject": "sample:subproject",
+ "subProjectName": "Sample Sub-Project",
+ "project": "sample:project",
+ "projectName": "Sample Project",
+ "fav": false,
+ "canMarkAsFavourite": true,
+ "canCreateManualIssue": true,
+ "measures": {
+ "lines": "20",
+ "duplicationDensity": "25%"
+ }
+}
diff --git a/server/sonar-web/src/test/json/source-viewer-scm/issues.json b/server/sonar-web/src/test/json/source-viewer-scm/issues.json
new file mode 100644
index 00000000000..40edd884b11
--- /dev/null
+++ b/server/sonar-web/src/test/json/source-viewer-scm/issues.json
@@ -0,0 +1,14 @@
+{
+ "total": 0,
+ "p": 1,
+ "ps": 100,
+ "issues": [],
+ "maxResultsReached": false,
+ "paging": {
+ "pageIndex": 1,
+ "pageSize": 100,
+ "total": 0,
+ "fTotal": "0",
+ "pages": 1
+ }
+}
diff --git a/server/sonar-web/src/test/json/source-viewer-scm/lines.json b/server/sonar-web/src/test/json/source-viewer-scm/lines.json
new file mode 100644
index 00000000000..c934ddd0e0a
--- /dev/null
+++ b/server/sonar-web/src/test/json/source-viewer-scm/lines.json
@@ -0,0 +1,11 @@
+{
+ "sources": [
+ {
+ "line": 1,
+ "code": "line 1",
+ "scmAuthor": "sample-author",
+ "scmDate": "2015-01-01T00:00:00+0000",
+ "scmRevision": "samplerevision"
+ }
+ ]
+}
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-not-show-source-if-no-permission/api-components-app.json b/server/sonar-web/src/test/json/source-viewer-should-not-show-source-if-no-permission/api-components-app.json
index db4620fbc23..db4620fbc23 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-not-show-source-if-no-permission/api-components-app.json
+++ b/server/sonar-web/src/test/json/source-viewer-should-not-show-source-if-no-permission/api-components-app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-not-show-source-if-no-permission/api-issues-search.json b/server/sonar-web/src/test/json/source-viewer-should-not-show-source-if-no-permission/api-issues-search.json
index 73d6a9fcf3d..73d6a9fcf3d 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-not-show-source-if-no-permission/api-issues-search.json
+++ b/server/sonar-web/src/test/json/source-viewer-should-not-show-source-if-no-permission/api-issues-search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-components-app.json b/server/sonar-web/src/test/json/source-viewer-should-open-in-new-window/api-components-app.json
index 5af670f2d91..5af670f2d91 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-components-app.json
+++ b/server/sonar-web/src/test/json/source-viewer-should-open-in-new-window/api-components-app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-issues-search.json b/server/sonar-web/src/test/json/source-viewer-should-open-in-new-window/api-issues-search.json
index 73d6a9fcf3d..73d6a9fcf3d 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-issues-search.json
+++ b/server/sonar-web/src/test/json/source-viewer-should-open-in-new-window/api-issues-search.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-sources-lines.json b/server/sonar-web/src/test/json/source-viewer-should-open-in-new-window/api-sources-lines.json
index b095d82408f..b095d82408f 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-sources-lines.json
+++ b/server/sonar-web/src/test/json/source-viewer-should-open-in-new-window/api-sources-lines.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/app-not-logged-in.json b/server/sonar-web/src/test/json/source-viewer-spec/app-not-logged-in.json
index e8b7516ee3c..e8b7516ee3c 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/app-not-logged-in.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/app-not-logged-in.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/app.json b/server/sonar-web/src/test/json/source-viewer-spec/app.json
index dd6a3fb900f..dd6a3fb900f 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/app.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/coverage.json b/server/sonar-web/src/test/json/source-viewer-spec/coverage.json
index ace41da645e..ace41da645e 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/coverage.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/coverage.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/cross-project-duplications.json b/server/sonar-web/src/test/json/source-viewer-spec/cross-project-duplications.json
index cd445d5f5b2..cd445d5f5b2 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/cross-project-duplications.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/cross-project-duplications.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/duplications-in-deleted-files.json b/server/sonar-web/src/test/json/source-viewer-spec/duplications-in-deleted-files.json
index 9de23d1ce7d..9de23d1ce7d 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/duplications-in-deleted-files.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/duplications-in-deleted-files.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/duplications.json b/server/sonar-web/src/test/json/source-viewer-spec/duplications.json
index f77e92bef26..f77e92bef26 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/duplications.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/duplications.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/issues.json b/server/sonar-web/src/test/json/source-viewer-spec/issues.json
index 0b1601191ef..0b1601191ef 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/issues.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/issues.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/lines.json b/server/sonar-web/src/test/json/source-viewer-spec/lines.json
index e33d02b2465..2983d8e4728 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/lines.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/lines.json
@@ -313,7 +313,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 46,
@@ -321,7 +321,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 47,
@@ -329,7 +329,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 48,
@@ -337,7 +337,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 49,
@@ -359,7 +359,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 52,
@@ -367,7 +367,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 53,
@@ -396,7 +396,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 57,
@@ -404,7 +404,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 58,
@@ -433,7 +433,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 62,
@@ -441,7 +441,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 63,
@@ -470,7 +470,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 67,
@@ -478,7 +478,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 68,
@@ -514,7 +514,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 73,
@@ -522,7 +522,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 74,
@@ -530,7 +530,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 75,
@@ -538,7 +538,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 76,
@@ -546,7 +546,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 77,
@@ -603,7 +603,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 85,
@@ -611,7 +611,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 86,
@@ -668,7 +668,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 94,
@@ -676,7 +676,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 95,
@@ -733,7 +733,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 103,
@@ -741,7 +741,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 104,
@@ -798,7 +798,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 112,
@@ -806,7 +806,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 113,
@@ -856,7 +856,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 120,
@@ -864,9 +864,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 2
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 2
},
{
"line": 121,
@@ -874,7 +874,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 122,
@@ -889,7 +889,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 124,
@@ -897,7 +897,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 125,
@@ -912,7 +912,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 127,
@@ -948,7 +948,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 132,
@@ -956,7 +956,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 133,
@@ -985,7 +985,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 137,
@@ -993,7 +993,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 138,
@@ -1022,7 +1022,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 142,
@@ -1030,7 +1030,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 143,
@@ -1059,7 +1059,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 147,
@@ -1067,7 +1067,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 148,
@@ -1103,7 +1103,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e108f5de333cf36aff978aa03940590f9caca9fc",
"scmDate": "2013-10-10T12:18:02+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 153,
@@ -1111,7 +1111,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e108f5de333cf36aff978aa03940590f9caca9fc",
"scmDate": "2013-10-10T12:18:02+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 154,
@@ -1119,7 +1119,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e108f5de333cf36aff978aa03940590f9caca9fc",
"scmDate": "2013-10-10T12:18:02+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 155,
@@ -1134,7 +1134,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e108f5de333cf36aff978aa03940590f9caca9fc",
"scmDate": "2013-10-10T12:18:02+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 157,
@@ -1170,7 +1170,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 162,
@@ -1178,7 +1178,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 163,
@@ -1207,7 +1207,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 167,
@@ -1215,7 +1215,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 168,
@@ -1244,7 +1244,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 172,
@@ -1252,7 +1252,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 173,
@@ -1281,7 +1281,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 177,
@@ -1289,7 +1289,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 178,
@@ -1325,7 +1325,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "6f1161efb92298ace498df544e38f6f97216ec36",
"scmDate": "2013-04-26T15:19:16+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 183,
@@ -1333,7 +1333,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 184,
@@ -1348,7 +1348,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 186,
@@ -1419,7 +1419,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 196,
@@ -1427,7 +1427,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 197,
@@ -1456,7 +1456,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 201,
@@ -1464,7 +1464,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 202,
@@ -1493,7 +1493,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 206,
@@ -1501,7 +1501,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 207,
@@ -1530,7 +1530,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 211,
@@ -1538,7 +1538,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 212,
@@ -1574,7 +1574,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 217,
@@ -1582,7 +1582,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 218,
@@ -1590,7 +1590,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 219,
@@ -1598,7 +1598,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 220,
@@ -1606,7 +1606,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 221,
@@ -1614,7 +1614,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 222,
@@ -1678,7 +1678,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 231,
@@ -1686,7 +1686,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 232,
@@ -1694,7 +1694,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 233,
@@ -1702,7 +1702,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 234,
@@ -1710,7 +1710,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 235,
@@ -1718,7 +1718,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 236,
@@ -1803,7 +1803,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 248,
@@ -1811,7 +1811,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 249,
@@ -1819,7 +1819,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 250,
@@ -1827,7 +1827,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 251,
@@ -1835,7 +1835,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 252,
@@ -1843,9 +1843,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 2
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 2
},
{
"line": 253,
@@ -1853,7 +1853,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 254,
@@ -1868,7 +1868,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 256,
@@ -1876,7 +1876,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 257,
@@ -1884,7 +1884,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 258,
@@ -1934,7 +1934,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 265,
@@ -1942,7 +1942,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 266,
@@ -1950,7 +1950,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 267,
@@ -1958,7 +1958,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 268,
@@ -1966,7 +1966,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 269,
@@ -1974,7 +1974,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 270,
@@ -1982,9 +1982,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 2
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 2
},
{
"line": 271,
@@ -1992,7 +1992,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 272,
@@ -2007,7 +2007,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 274,
@@ -2015,7 +2015,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 275,
@@ -2023,7 +2023,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 276,
@@ -2101,7 +2101,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 287,
@@ -2109,7 +2109,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 288,
@@ -2117,7 +2117,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 289,
@@ -2125,7 +2125,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 290,
@@ -2133,9 +2133,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 2
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 2
},
{
"line": 291,
@@ -2143,7 +2143,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 292,
@@ -2158,7 +2158,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 294,
@@ -2166,7 +2166,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 295,
@@ -2174,7 +2174,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 296,
@@ -2238,7 +2238,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "171cd79c0b5152461434951ed5d6e5e58849a7b7",
"scmDate": "2014-04-23T14:41:32+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 305,
@@ -2246,7 +2246,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "171cd79c0b5152461434951ed5d6e5e58849a7b7",
"scmDate": "2014-04-23T14:41:32+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 306,
@@ -2254,7 +2254,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "171cd79c0b5152461434951ed5d6e5e58849a7b7",
"scmDate": "2014-04-23T14:41:32+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 307,
@@ -2262,7 +2262,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 308,
@@ -2270,7 +2270,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 309,
@@ -2278,7 +2278,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "171cd79c0b5152461434951ed5d6e5e58849a7b7",
"scmDate": "2014-04-23T14:41:32+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 310,
@@ -2286,7 +2286,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "904b462c56317b1fb5a616534bd58aa9c9097d0b",
"scmDate": "2014-06-20T14:13:01+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 311,
@@ -2322,7 +2322,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "904b462c56317b1fb5a616534bd58aa9c9097d0b",
"scmDate": "2014-06-20T14:13:01+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 316,
@@ -2379,7 +2379,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 324,
@@ -2387,7 +2387,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 325,
@@ -2395,7 +2395,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 326,
@@ -2403,7 +2403,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 327,
@@ -2411,7 +2411,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 328,
@@ -2419,7 +2419,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "46395126b184c343df5471a147cdb48133f59f6f",
"scmDate": "2014-04-23T14:41:32+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 329,
@@ -2427,7 +2427,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "904b462c56317b1fb5a616534bd58aa9c9097d0b",
"scmDate": "2014-06-20T14:13:01+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 330,
@@ -2491,7 +2491,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 339,
@@ -2499,7 +2499,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 340,
@@ -2507,7 +2507,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 341,
@@ -2515,7 +2515,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 342,
@@ -2523,7 +2523,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "26edff10d133e29e7013f803e7ef0d69ff593aeb",
"scmDate": "2013-04-16T17:26:34+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 343,
@@ -2531,7 +2531,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "904b462c56317b1fb5a616534bd58aa9c9097d0b",
"scmDate": "2014-06-20T14:13:01+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 344,
@@ -2567,7 +2567,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 349,
@@ -2575,7 +2575,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 350,
@@ -2583,7 +2583,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 351,
@@ -2612,7 +2612,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 355,
@@ -2620,7 +2620,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 356,
@@ -2628,7 +2628,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 357,
@@ -2657,7 +2657,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 361,
@@ -2665,7 +2665,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 362,
@@ -2673,7 +2673,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 363,
@@ -2695,7 +2695,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 366,
@@ -2703,7 +2703,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 367,
@@ -2711,7 +2711,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 368,
@@ -2733,7 +2733,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 371,
@@ -2741,7 +2741,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 372,
@@ -2749,7 +2749,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 373,
@@ -2771,7 +2771,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 376,
@@ -2779,9 +2779,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0,
- "conditions": 2,
- "coveredConditions": 0
+ "utLineHits": 0,
+ "utConditions": 2,
+ "utCoveredConditions": 0
},
{
"line": 377,
@@ -2789,7 +2789,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 378,
@@ -2804,7 +2804,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 380,
@@ -2868,7 +2868,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 389,
@@ -2876,7 +2876,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 390,
@@ -2884,7 +2884,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 391,
@@ -2913,7 +2913,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 395,
@@ -2970,7 +2970,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 403,
@@ -2978,7 +2978,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -2987,7 +2987,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -2996,7 +2996,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -3037,7 +3037,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -3046,7 +3046,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 0,
+ "utLineHits": 0,
"duplicated": true
},
{
@@ -3055,7 +3055,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 0,
+ "utLineHits": 0,
"duplicated": true
},
{
@@ -3118,7 +3118,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 421,
@@ -3126,7 +3126,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 422,
@@ -3134,7 +3134,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 423,
@@ -3142,7 +3142,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 424,
@@ -3150,9 +3150,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "babb50a4f143c312df1ba45955d3d589ecb2845f",
"scmDate": "2013-05-29T14:27:38+0200",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 1
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 1
},
{
"line": 425,
@@ -3160,7 +3160,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 426,
@@ -3175,7 +3175,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 428,
@@ -3211,7 +3211,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "34cce8e330192c56a159a856ebd8072d38299087",
"scmDate": "2014-02-24T14:21:50+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 433,
@@ -3261,7 +3261,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 440,
@@ -3269,7 +3269,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 441,
@@ -3277,7 +3277,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 442,
@@ -3306,7 +3306,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 446,
@@ -3363,7 +3363,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 454,
@@ -3371,7 +3371,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -3380,7 +3380,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -3389,7 +3389,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -3430,7 +3430,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1,
+ "utLineHits": 1,
"duplicated": true
},
{
@@ -3439,7 +3439,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 0,
+ "utLineHits": 0,
"duplicated": true
},
{
@@ -3448,7 +3448,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 0,
+ "utLineHits": 0,
"duplicated": true
},
{
@@ -3511,7 +3511,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 472,
@@ -3519,7 +3519,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 473,
@@ -3527,7 +3527,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 474,
@@ -3535,7 +3535,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 475,
@@ -3543,9 +3543,9 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 1
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 1
},
{
"line": 476,
@@ -3553,7 +3553,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 477,
@@ -3561,7 +3561,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 478,
@@ -3569,7 +3569,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 479,
@@ -3577,9 +3577,9 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1,
- "conditions": 2,
- "coveredConditions": 2
+ "utLineHits": 1,
+ "utConditions": 2,
+ "utCoveredConditions": 2
},
{
"line": 480,
@@ -3587,7 +3587,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 481,
@@ -3602,7 +3602,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 483,
@@ -3617,7 +3617,7 @@
"scmAuthor": "julien.henry@sonarsource.com",
"scmRevision": "cc071cc29e8c4d4592282313a3ca2ec376fd7f71",
"scmDate": "2014-05-01T00:00:12+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 485,
@@ -3653,7 +3653,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "34cce8e330192c56a159a856ebd8072d38299087",
"scmDate": "2014-02-24T14:21:50+0100",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 490,
@@ -3710,7 +3710,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "e486fe02a0a38d3d9fb70690f7870c77e2265254",
"scmDate": "2014-02-20T07:23:08+0100",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 498,
@@ -3718,7 +3718,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 499,
@@ -3726,7 +3726,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 500,
@@ -3734,7 +3734,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 501,
@@ -3756,7 +3756,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 504,
@@ -3792,7 +3792,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 1
+ "utLineHits": 1
},
{
"line": 509,
@@ -3828,7 +3828,7 @@
"scmAuthor": "simon.brandhof@gmail.com",
"scmRevision": "b5eb47872b34aa9d017dca62abfe49b2fd7af61b",
"scmDate": "2013-04-17T10:35:23+0200",
- "lineHits": 0
+ "utLineHits": 0
},
{
"line": 514,
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/resources-without-ncloc-data.json b/server/sonar-web/src/test/json/source-viewer-spec/resources-without-ncloc-data.json
index dfbacdf7b28..dfbacdf7b28 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/resources-without-ncloc-data.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/resources-without-ncloc-data.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/resources.json b/server/sonar-web/src/test/json/source-viewer-spec/resources.json
index 415718c7cd5..415718c7cd5 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/resources.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/resources.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/scm.json b/server/sonar-web/src/test/json/source-viewer-spec/scm.json
index ff89c9856ca..ff89c9856ca 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/scm.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/scm.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/source.json b/server/sonar-web/src/test/json/source-viewer-spec/source.json
index 1b32224e6a7..1b32224e6a7 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/source.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/source.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/test-cases.json b/server/sonar-web/src/test/json/source-viewer-spec/test-cases.json
index 233229a803b..233229a803b 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/test-cases.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/test-cases.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/tests/app.json b/server/sonar-web/src/test/json/source-viewer-spec/tests/app.json
index 873632ffd3b..873632ffd3b 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/tests/app.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/tests/app.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/tests/lines.json b/server/sonar-web/src/test/json/source-viewer-spec/tests/lines.json
index becc8c92f69..becc8c92f69 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/tests/lines.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/tests/lines.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/tests/tests.json b/server/sonar-web/src/test/json/source-viewer-spec/tests/tests.json
index 421cbb391b1..421cbb391b1 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-spec/tests/tests.json
+++ b/server/sonar-web/src/test/json/source-viewer-spec/tests/tests.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/treemap-spec/treemap-resources.json b/server/sonar-web/src/test/json/treemap-spec/treemap-resources.json
index bc1c20845fa..bc1c20845fa 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/treemap-spec/treemap-resources.json
+++ b/server/sonar-web/src/test/json/treemap-spec/treemap-resources.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/treemap-spec/treemap.json b/server/sonar-web/src/test/json/treemap-spec/treemap.json
index 1125b3a7cf4..1125b3a7cf4 100644
--- a/server/sonar-web/src/main/js/tests/e2e/tests/treemap-spec/treemap.json
+++ b/server/sonar-web/src/test/json/treemap-spec/treemap.json
diff --git a/server/sonar-web/src/main/js/tests/e2e/lib.js b/server/sonar-web/src/test/lib.js
index 2c66e0e618a..82204cdacfe 100644
--- a/server/sonar-web/src/main/js/tests/e2e/lib.js
+++ b/server/sonar-web/src/test/lib.js
@@ -26,6 +26,7 @@ var getPort = function () {
};
var BASE_URL = 'http://localhost:' + getPort() + '/pages/',
+ BASE_ROOT_URL = 'http://localhost:' + getPort(),
WINDOW_WIDTH = 1200,
WINDOW_HEIGHT = 800;
@@ -54,7 +55,9 @@ exports.changeWorkingDirectory = function (dir) {
var currentFile = commandLineArgs[4];
var curFilePath = fs.absolute(currentFile).split(fs.separator);
if (curFilePath.length > 1) {
- curFilePath.pop(); // PhantomJS does not have an equivalent path.baseName()-like method
+ curFilePath.pop(); // test name
+ curFilePath.pop(); // "js" dir
+ curFilePath.push('json');
curFilePath.push(dir);
fs.changeWorkingDirectory(curFilePath.join(fs.separator));
}
@@ -118,6 +121,11 @@ exports.buildUrl = function (urlTail) {
};
+exports.buildRootUrl = function (urlTail) {
+ return patchWithTimestamp(BASE_ROOT_URL + urlTail);
+};
+
+
exports.setDefaultViewport = function () {
casper.viewport(WINDOW_WIDTH, WINDOW_HEIGHT);
};
@@ -156,3 +164,16 @@ exports.assertLinkHref = function assertElementCount(selector, href, message) {
}
});
};
+
+
+exports.sendCoverage = function () {
+ return casper.evaluate(function () {
+ jQuery.ajax({
+ type: 'POST',
+ url: '/coverage/client',
+ data: JSON.stringify(window.__coverage__),
+ processData: false,
+ contentType: 'application/json; charset=UTF-8'
+ });
+ });
+};
diff --git a/server/sonar-web/src/test/server-coverage.js b/server/sonar-web/src/test/server-coverage.js
new file mode 100644
index 00000000000..99394a28421
--- /dev/null
+++ b/server/sonar-web/src/test/server-coverage.js
@@ -0,0 +1,30 @@
+var express = require('express'),
+ path = require('path'),
+ errorhandler = require('errorhandler'),
+ serveStatic = require('serve-static'),
+ im = require('istanbul-middleware');
+
+var staticPath = path.join(__dirname, '../main/webapp');
+im.hookLoader(staticPath);
+
+var app = express();
+
+app.set('views', __dirname + '/views');
+app.set('view engine', 'jade');
+
+app.use(errorhandler({ dumpExceptions: true, showStack: true }));
+
+app.use(im.createClientHandler(staticPath));
+app.use('/coverage', im.createHandler());
+app.use('/', serveStatic(staticPath));
+
+app.get('/pages/:page', function (req, res) {
+ res.render(req.param('page'));
+});
+
+// Get the port from environment variables
+var port = process.env.PORT || 8000;
+
+app.listen(port);
+
+console.log('Server running on port %d', port);
diff --git a/server/sonar-web/src/main/js/tests/e2e/server.js b/server/sonar-web/src/test/server.js
index 14acf2fc602..fc0caa73758 100644
--- a/server/sonar-web/src/main/js/tests/e2e/server.js
+++ b/server/sonar-web/src/test/server.js
@@ -20,16 +20,18 @@
var express = require('express'),
path = require('path'),
errorhandler = require('errorhandler'),
- serveStatic = require('serve-static'),
- app = express();
+ serveStatic = require('serve-static');
+
+var staticPath = path.join(__dirname, '../main/webapp');
+
+var app = express();
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(errorhandler({ dumpExceptions: true, showStack: true }));
-// Serve static files
-app.use('/', serveStatic(path.join(__dirname, '../../../webapp')));
+app.use('/', serveStatic(staticPath));
app.get('/pages/:page', function (req, res) {
res.render(req.param('page'));
diff --git a/server/sonar-web/src/main/js/tests/e2e/views/coding-rules.jade b/server/sonar-web/src/test/views/coding-rules.jade
index a56d076e719..f5c7ef3adb8 100644
--- a/server/sonar-web/src/main/js/tests/e2e/views/coding-rules.jade
+++ b/server/sonar-web/src/test/views/coding-rules.jade
@@ -1,4 +1,4 @@
-extends ./layouts/main
+extends layouts/main
block header
script(src='../js/require.js')
diff --git a/server/sonar-web/src/main/js/tests/e2e/views/design.jade b/server/sonar-web/src/test/views/design.jade
index 9132d07e7e4..ab71d7af887 100644
--- a/server/sonar-web/src/main/js/tests/e2e/views/design.jade
+++ b/server/sonar-web/src/test/views/design.jade
@@ -1,4 +1,4 @@
-extends ./layouts/main
+extends layouts/main
block header
script(src='../js/require.js')
diff --git a/server/sonar-web/src/test/views/issue-filter-widget.jade b/server/sonar-web/src/test/views/issue-filter-widget.jade
new file mode 100644
index 00000000000..97a22c3de73
--- /dev/null
+++ b/server/sonar-web/src/test/views/issue-filter-widget.jade
@@ -0,0 +1,9 @@
+extends layouts/main
+
+block header
+ script(src='../js/require.js')
+ script.
+ requirejs.config({ baseUrl: '/js' });
+
+block body
+ #issue-filter-widget
diff --git a/server/sonar-web/src/main/js/tests/e2e/views/issues.jade b/server/sonar-web/src/test/views/issues.jade
index c23c98a54f9..4a9ba14f681 100644
--- a/server/sonar-web/src/main/js/tests/e2e/views/issues.jade
+++ b/server/sonar-web/src/test/views/issues.jade
@@ -1,4 +1,4 @@
-extends ./layouts/main
+extends layouts/main
block header
script(src='../js/require.js')
diff --git a/server/sonar-web/src/test/views/layouts/main.jade b/server/sonar-web/src/test/views/layouts/main.jade
new file mode 100644
index 00000000000..59aafece770
--- /dev/null
+++ b/server/sonar-web/src/test/views/layouts/main.jade
@@ -0,0 +1,67 @@
+html
+ head
+ meta(http-equiv='Content-Type', content='text/html; charset=UTF-8')
+ link(href='/css/sonar.css', rel='stylesheet', media='all')
+
+ script(src='/js/translate.js')
+ script(src='/js/third-party/jquery.js')
+ script(src='/js/third-party/jquery-ui.js')
+ script(src='/js/third-party/d3.js')
+ script(src='/js/third-party/latinize.js')
+ script(src='/js/third-party/underscore.js')
+ script(src='/js/third-party/backbone.js')
+ script(src='/js/third-party/backbone.marionette.js')
+ script(src='/js/third-party/handlebars.js')
+ script(src='/js/third-party/underscore.js')
+ script(src='/js/third-party/select2.js')
+ script(src='/js/third-party/keymaster.js')
+ script(src='/js/third-party/moment.js')
+ script(src='/js/third-party/numeral.js')
+ script(src='/js/third-party/numeral-languages.js')
+ script(src='/js/third-party/bootstrap/tooltip.js')
+ script(src='/js/third-party/bootstrap/dropdown.js')
+ script(src='/js/select2-jquery-ui-fix.js')
+ script(src='/js/widgets/base.js')
+ script(src='/js/widgets/widget.js')
+ script(src='/js/widgets/bubble-chart.js')
+ script(src='/js/widgets/timeline.js')
+ script(src='/js/widgets/stack-area.js')
+ script(src='/js/widgets/pie-chart.js')
+ script(src='/js/widgets/histogram.js')
+ script(src='/js/widgets/word-cloud.js')
+ script(src='/js/widgets/tag-cloud.js')
+ script(src='/js/widgets/treemap.js')
+ script(src='/js/graphics/pie-chart.js')
+ script(src='/js/graphics/timeline.js')
+ script(src='/js/graphics/barchart.js')
+ script(src='/js/sortable.js')
+ script(src='/js/common/inputs.js')
+ script(src='/js/common/dialogs.js')
+ script(src='/js/common/processes.js')
+ script(src='/js/common/jquery-isolated-scroll.js')
+ script(src='/js/common/handlebars-extensions.js')
+ script(src='/js/application.js')
+ script(src='/js/csv.js')
+ script(src='/js/dashboard.js')
+ script(src='/js/recent-history.js')
+
+ script(src='/js/third-party/jquery.mockjax.js')
+ script.
+ var baseUrl = '';
+ var $j = jQuery.noConflict();
+ window.suppressTranslationWarnings = true;
+ jQuery.mockjaxSettings.contentType = 'text/json';
+ jQuery.mockjaxSettings.responseTime = 50;
+ $j(document).ready(function () { $j('.open-modal').modal(); });
+ window.waitForMocks = function (app) {
+ var x = setInterval(function () {
+ jQuery.get('/api/l10n/index').done(function () {
+ clearInterval(x);
+ require([app]);
+ });
+ }, 500);
+ }
+ block header
+ body
+ #body
+ block body
diff --git a/server/sonar-web/src/main/js/tests/e2e/views/quality-gates.jade b/server/sonar-web/src/test/views/quality-gates.jade
index ac1a4871c1b..ccee40be0d0 100644
--- a/server/sonar-web/src/main/js/tests/e2e/views/quality-gates.jade
+++ b/server/sonar-web/src/test/views/quality-gates.jade
@@ -1,4 +1,4 @@
-extends ./layouts/main
+extends layouts/main
block header
script(src='../js/require.js')
diff --git a/server/sonar-web/src/main/js/tests/e2e/views/source-viewer.jade b/server/sonar-web/src/test/views/source-viewer.jade
index 03903d8f854..9e2c62c3a1d 100644
--- a/server/sonar-web/src/main/js/tests/e2e/views/source-viewer.jade
+++ b/server/sonar-web/src/test/views/source-viewer.jade
@@ -1,4 +1,4 @@
-extends ./layouts/main
+extends layouts/main
block header
script(src='../js/require.js')
diff --git a/server/sonar-web/src/main/js/tests/e2e/views/treemap.jade b/server/sonar-web/src/test/views/treemap.jade
index 3f6fbac8ae9..09dc4fb950b 100644
--- a/server/sonar-web/src/main/js/tests/e2e/views/treemap.jade
+++ b/server/sonar-web/src/test/views/treemap.jade
@@ -1,4 +1,4 @@
-extends ./layouts/main
+extends layouts/main
block body
#container
diff --git a/server/sonar-ws-client/pom.xml b/server/sonar-ws-client/pom.xml
index ca2fa7225b0..7f66d5e21c4 100644
--- a/server/sonar-ws-client/pom.xml
+++ b/server/sonar-ws-client/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>server</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>sonar-ws-client</artifactId>
diff --git a/sonar-application/pom.xml b/sonar-application/pom.xml
index 44133ea12a0..dbf50534e4d 100644
--- a/sonar-application/pom.xml
+++ b/sonar-application/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-application</artifactId>
@@ -97,12 +97,6 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.codehaus.sonar-plugins.java</groupId>
- <artifactId>sonar-findbugs-plugin</artifactId>
- <type>sonar-plugin</type>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>org.codehaus.sonar.plugins</groupId>
<artifactId>sonar-l10n-en-plugin</artifactId>
<version>${project.version}</version>
diff --git a/sonar-batch-maven-compat/pom.xml b/sonar-batch-maven-compat/pom.xml
index b79d22382eb..dc5c18efd3a 100644
--- a/sonar-batch-maven-compat/pom.xml
+++ b/sonar-batch-maven-compat/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-batch-maven-compat</artifactId>
diff --git a/sonar-batch-protocol/pom.xml b/sonar-batch-protocol/pom.xml
index 343d707f094..6dc19b488e3 100644
--- a/sonar-batch-protocol/pom.xml
+++ b/sonar-batch-protocol/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-batch-protocol</artifactId>
diff --git a/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/input/BatchInput.java b/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/input/BatchInput.java
index 5e35e980038..6ecbcc83d31 100644
--- a/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/input/BatchInput.java
+++ b/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/input/BatchInput.java
@@ -4,212 +4,198 @@
package org.sonar.batch.protocol.input;
public final class BatchInput {
- private BatchInput() {
- }
-
+ private BatchInput() {}
public static void registerAllExtensions(
- com.google.protobuf.ExtensionRegistry registry) {
+ com.google.protobuf.ExtensionRegistry registry) {
}
+ public interface ServerIssueOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
- public interface ServerIssueOrBuilder extends
- // @@protoc_insertion_point(interface_extends:ServerIssue)
- com.google.protobuf.MessageOrBuilder {
-
+ // optional string key = 1;
/**
* <code>optional string key = 1;</code>
*/
boolean hasKey();
-
/**
* <code>optional string key = 1;</code>
*/
java.lang.String getKey();
-
/**
* <code>optional string key = 1;</code>
*/
com.google.protobuf.ByteString
- getKeyBytes();
+ getKeyBytes();
+ // optional string module_key = 2;
/**
* <code>optional string module_key = 2;</code>
*/
boolean hasModuleKey();
-
/**
* <code>optional string module_key = 2;</code>
*/
java.lang.String getModuleKey();
-
/**
* <code>optional string module_key = 2;</code>
*/
com.google.protobuf.ByteString
- getModuleKeyBytes();
+ getModuleKeyBytes();
+ // optional string path = 3;
/**
* <code>optional string path = 3;</code>
*/
boolean hasPath();
-
/**
* <code>optional string path = 3;</code>
*/
java.lang.String getPath();
-
/**
* <code>optional string path = 3;</code>
*/
com.google.protobuf.ByteString
- getPathBytes();
+ getPathBytes();
+ // optional string rule_repository = 4;
/**
* <code>optional string rule_repository = 4;</code>
*/
boolean hasRuleRepository();
-
/**
* <code>optional string rule_repository = 4;</code>
*/
java.lang.String getRuleRepository();
-
/**
* <code>optional string rule_repository = 4;</code>
*/
com.google.protobuf.ByteString
- getRuleRepositoryBytes();
+ getRuleRepositoryBytes();
+ // optional string rule_key = 5;
/**
* <code>optional string rule_key = 5;</code>
*/
boolean hasRuleKey();
-
/**
* <code>optional string rule_key = 5;</code>
*/
java.lang.String getRuleKey();
-
/**
* <code>optional string rule_key = 5;</code>
*/
com.google.protobuf.ByteString
- getRuleKeyBytes();
+ getRuleKeyBytes();
+ // optional int32 line = 6;
/**
* <code>optional int32 line = 6;</code>
*/
boolean hasLine();
-
/**
* <code>optional int32 line = 6;</code>
*/
int getLine();
+ // optional string msg = 7;
/**
* <code>optional string msg = 7;</code>
*/
boolean hasMsg();
-
/**
* <code>optional string msg = 7;</code>
*/
java.lang.String getMsg();
-
/**
* <code>optional string msg = 7;</code>
*/
com.google.protobuf.ByteString
- getMsgBytes();
+ getMsgBytes();
+ // optional .Severity severity = 8;
/**
* <code>optional .Severity severity = 8;</code>
*/
boolean hasSeverity();
-
/**
* <code>optional .Severity severity = 8;</code>
*/
org.sonar.batch.protocol.Constants.Severity getSeverity();
+ // optional bool manual_severity = 9;
/**
* <code>optional bool manual_severity = 9;</code>
*/
boolean hasManualSeverity();
-
/**
* <code>optional bool manual_severity = 9;</code>
*/
boolean getManualSeverity();
+ // optional string resolution = 10;
/**
* <code>optional string resolution = 10;</code>
*/
boolean hasResolution();
-
/**
* <code>optional string resolution = 10;</code>
*/
java.lang.String getResolution();
-
/**
* <code>optional string resolution = 10;</code>
*/
com.google.protobuf.ByteString
- getResolutionBytes();
+ getResolutionBytes();
+ // optional string status = 11;
/**
* <code>optional string status = 11;</code>
*/
boolean hasStatus();
-
/**
* <code>optional string status = 11;</code>
*/
java.lang.String getStatus();
-
/**
* <code>optional string status = 11;</code>
*/
com.google.protobuf.ByteString
- getStatusBytes();
+ getStatusBytes();
+ // optional string checksum = 12;
/**
* <code>optional string checksum = 12;</code>
*/
boolean hasChecksum();
-
/**
* <code>optional string checksum = 12;</code>
*/
java.lang.String getChecksum();
-
/**
* <code>optional string checksum = 12;</code>
*/
com.google.protobuf.ByteString
- getChecksumBytes();
+ getChecksumBytes();
+ // optional string assignee_login = 13;
/**
* <code>optional string assignee_login = 13;</code>
*/
boolean hasAssigneeLogin();
-
/**
* <code>optional string assignee_login = 13;</code>
*/
java.lang.String getAssigneeLogin();
-
/**
* <code>optional string assignee_login = 13;</code>
*/
com.google.protobuf.ByteString
- getAssigneeLoginBytes();
+ getAssigneeLoginBytes();
+ // optional int64 creation_date = 14;
/**
* <code>optional int64 creation_date = 14;</code>
*/
boolean hasCreationDate();
-
/**
* <code>optional int64 creation_date = 14;</code>
*/
@@ -219,21 +205,16 @@ public final class BatchInput {
* Protobuf type {@code ServerIssue}
*/
public static final class ServerIssue extends
- com.google.protobuf.GeneratedMessage implements
- // @@protoc_insertion_point(message_implements:ServerIssue)
- ServerIssueOrBuilder {
+ com.google.protobuf.GeneratedMessage
+ implements ServerIssueOrBuilder {
// Use ServerIssue.newBuilder() to construct.
private ServerIssue(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
super(builder);
this.unknownFields = builder.getUnknownFields();
}
-
- private ServerIssue(boolean noInit) {
- this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance();
- }
+ private ServerIssue(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
private static final ServerIssue defaultInstance;
-
public static ServerIssue getDefaultInstance() {
return defaultInstance;
}
@@ -243,21 +224,19 @@ public final class BatchInput {
}
private final com.google.protobuf.UnknownFieldSet unknownFields;
-
@java.lang.Override
public final com.google.protobuf.UnknownFieldSet
- getUnknownFields() {
+ getUnknownFields() {
return this.unknownFields;
}
-
private ServerIssue(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
initFields();
int mutable_bitField0_ = 0;
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
- com.google.protobuf.UnknownFieldSet.newBuilder();
+ com.google.protobuf.UnknownFieldSet.newBuilder();
try {
boolean done = false;
while (!done) {
@@ -268,39 +247,34 @@ public final class BatchInput {
break;
default: {
if (!parseUnknownField(input, unknownFields,
- extensionRegistry, tag)) {
+ extensionRegistry, tag)) {
done = true;
}
break;
}
case 10: {
- com.google.protobuf.ByteString bs = input.readBytes();
bitField0_ |= 0x00000001;
- key_ = bs;
+ key_ = input.readBytes();
break;
}
case 18: {
- com.google.protobuf.ByteString bs = input.readBytes();
bitField0_ |= 0x00000002;
- moduleKey_ = bs;
+ moduleKey_ = input.readBytes();
break;
}
case 26: {
- com.google.protobuf.ByteString bs = input.readBytes();
bitField0_ |= 0x00000004;
- path_ = bs;
+ path_ = input.readBytes();
break;
}
case 34: {
- com.google.protobuf.ByteString bs = input.readBytes();
bitField0_ |= 0x00000008;
- ruleRepository_ = bs;
+ ruleRepository_ = input.readBytes();
break;
}
case 42: {
- com.google.protobuf.ByteString bs = input.readBytes();
bitField0_ |= 0x00000010;
- ruleKey_ = bs;
+ ruleKey_ = input.readBytes();
break;
}
case 48: {
@@ -309,9 +283,8 @@ public final class BatchInput {
break;
}
case 58: {
- com.google.protobuf.ByteString bs = input.readBytes();
bitField0_ |= 0x00000040;
- msg_ = bs;
+ msg_ = input.readBytes();
break;
}
case 64: {
@@ -331,27 +304,23 @@ public final class BatchInput {
break;
}
case 82: {
- com.google.protobuf.ByteString bs = input.readBytes();
bitField0_ |= 0x00000200;
- resolution_ = bs;
+ resolution_ = input.readBytes();
break;
}
case 90: {
- com.google.protobuf.ByteString bs = input.readBytes();
bitField0_ |= 0x00000400;
- status_ = bs;
+ status_ = input.readBytes();
break;
}
case 98: {
- com.google.protobuf.ByteString bs = input.readBytes();
bitField0_ |= 0x00000800;
- checksum_ = bs;
+ checksum_ = input.readBytes();
break;
}
case 106: {
- com.google.protobuf.ByteString bs = input.readBytes();
bitField0_ |= 0x00001000;
- assigneeLogin_ = bs;
+ assigneeLogin_ = input.readBytes();
break;
}
case 112: {
@@ -365,34 +334,33 @@ public final class BatchInput {
throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
- e.getMessage()).setUnfinishedMessage(this);
+ e.getMessage()).setUnfinishedMessage(this);
} finally {
this.unknownFields = unknownFields.build();
makeExtensionsImmutable();
}
}
-
public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
+ getDescriptor() {
return org.sonar.batch.protocol.input.BatchInput.internal_static_ServerIssue_descriptor;
}
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
+ internalGetFieldAccessorTable() {
return org.sonar.batch.protocol.input.BatchInput.internal_static_ServerIssue_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.sonar.batch.protocol.input.BatchInput.ServerIssue.class, org.sonar.batch.protocol.input.BatchInput.ServerIssue.Builder.class);
+ .ensureFieldAccessorsInitialized(
+ org.sonar.batch.protocol.input.BatchInput.ServerIssue.class, org.sonar.batch.protocol.input.BatchInput.ServerIssue.Builder.class);
}
public static com.google.protobuf.Parser<ServerIssue> PARSER =
- new com.google.protobuf.AbstractParser<ServerIssue>() {
- public ServerIssue parsePartialFrom(
+ new com.google.protobuf.AbstractParser<ServerIssue>() {
+ public ServerIssue parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
- return new ServerIssue(input, extensionRegistry);
- }
- };
+ return new ServerIssue(input, extensionRegistry);
+ }
+ };
@java.lang.Override
public com.google.protobuf.Parser<ServerIssue> getParserForType() {
@@ -400,16 +368,15 @@ public final class BatchInput {
}
private int bitField0_;
+ // optional string key = 1;
public static final int KEY_FIELD_NUMBER = 1;
private java.lang.Object key_;
-
/**
* <code>optional string key = 1;</code>
*/
public boolean hasKey() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
-
/**
* <code>optional string key = 1;</code>
*/
@@ -418,8 +385,8 @@ public final class BatchInput {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
key_ = s;
@@ -427,17 +394,16 @@ public final class BatchInput {
return s;
}
}
-
/**
* <code>optional string key = 1;</code>
*/
public com.google.protobuf.ByteString
- getKeyBytes() {
+ getKeyBytes() {
java.lang.Object ref = key_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
key_ = b;
return b;
} else {
@@ -445,16 +411,15 @@ public final class BatchInput {
}
}
+ // optional string module_key = 2;
public static final int MODULE_KEY_FIELD_NUMBER = 2;
private java.lang.Object moduleKey_;
-
/**
* <code>optional string module_key = 2;</code>
*/
public boolean hasModuleKey() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
-
/**
* <code>optional string module_key = 2;</code>
*/
@@ -463,8 +428,8 @@ public final class BatchInput {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
moduleKey_ = s;
@@ -472,17 +437,16 @@ public final class BatchInput {
return s;
}
}
-
/**
* <code>optional string module_key = 2;</code>
*/
public com.google.protobuf.ByteString
- getModuleKeyBytes() {
+ getModuleKeyBytes() {
java.lang.Object ref = moduleKey_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
moduleKey_ = b;
return b;
} else {
@@ -490,16 +454,15 @@ public final class BatchInput {
}
}
+ // optional string path = 3;
public static final int PATH_FIELD_NUMBER = 3;
private java.lang.Object path_;
-
/**
* <code>optional string path = 3;</code>
*/
public boolean hasPath() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
-
/**
* <code>optional string path = 3;</code>
*/
@@ -508,8 +471,8 @@ public final class BatchInput {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
path_ = s;
@@ -517,17 +480,16 @@ public final class BatchInput {
return s;
}
}
-
/**
* <code>optional string path = 3;</code>
*/
public com.google.protobuf.ByteString
- getPathBytes() {
+ getPathBytes() {
java.lang.Object ref = path_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
path_ = b;
return b;
} else {
@@ -535,16 +497,15 @@ public final class BatchInput {
}
}
+ // optional string rule_repository = 4;
public static final int RULE_REPOSITORY_FIELD_NUMBER = 4;
private java.lang.Object ruleRepository_;
-
/**
* <code>optional string rule_repository = 4;</code>
*/
public boolean hasRuleRepository() {
return ((bitField0_ & 0x00000008) == 0x00000008);
}
-
/**
* <code>optional string rule_repository = 4;</code>
*/
@@ -553,8 +514,8 @@ public final class BatchInput {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
ruleRepository_ = s;
@@ -562,17 +523,16 @@ public final class BatchInput {
return s;
}
}
-
/**
* <code>optional string rule_repository = 4;</code>
*/
public com.google.protobuf.ByteString
- getRuleRepositoryBytes() {
+ getRuleRepositoryBytes() {
java.lang.Object ref = ruleRepository_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
ruleRepository_ = b;
return b;
} else {
@@ -580,16 +540,15 @@ public final class BatchInput {
}
}
+ // optional string rule_key = 5;
public static final int RULE_KEY_FIELD_NUMBER = 5;
private java.lang.Object ruleKey_;
-
/**
* <code>optional string rule_key = 5;</code>
*/
public boolean hasRuleKey() {
return ((bitField0_ & 0x00000010) == 0x00000010);
}
-
/**
* <code>optional string rule_key = 5;</code>
*/
@@ -598,8 +557,8 @@ public final class BatchInput {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
ruleKey_ = s;
@@ -607,17 +566,16 @@ public final class BatchInput {
return s;
}
}
-
/**
* <code>optional string rule_key = 5;</code>
*/
public com.google.protobuf.ByteString
- getRuleKeyBytes() {
+ getRuleKeyBytes() {
java.lang.Object ref = ruleKey_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
ruleKey_ = b;
return b;
} else {
@@ -625,16 +583,15 @@ public final class BatchInput {
}
}
+ // optional int32 line = 6;
public static final int LINE_FIELD_NUMBER = 6;
private int line_;
-
/**
* <code>optional int32 line = 6;</code>
*/
public boolean hasLine() {
return ((bitField0_ & 0x00000020) == 0x00000020);
}
-
/**
* <code>optional int32 line = 6;</code>
*/
@@ -642,16 +599,15 @@ public final class BatchInput {
return line_;
}
+ // optional string msg = 7;
public static final int MSG_FIELD_NUMBER = 7;
private java.lang.Object msg_;
-
/**
* <code>optional string msg = 7;</code>
*/
public boolean hasMsg() {
return ((bitField0_ & 0x00000040) == 0x00000040);
}
-
/**
* <code>optional string msg = 7;</code>
*/
@@ -660,8 +616,8 @@ public final class BatchInput {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
msg_ = s;
@@ -669,17 +625,16 @@ public final class BatchInput {
return s;
}
}
-
/**
* <code>optional string msg = 7;</code>
*/
public com.google.protobuf.ByteString
- getMsgBytes() {
+ getMsgBytes() {
java.lang.Object ref = msg_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
msg_ = b;
return b;
} else {
@@ -687,16 +642,15 @@ public final class BatchInput {
}
}
+ // optional .Severity severity = 8;
public static final int SEVERITY_FIELD_NUMBER = 8;
private org.sonar.batch.protocol.Constants.Severity severity_;
-
/**
* <code>optional .Severity severity = 8;</code>
*/
public boolean hasSeverity() {
return ((bitField0_ & 0x00000080) == 0x00000080);
}
-
/**
* <code>optional .Severity severity = 8;</code>
*/
@@ -704,16 +658,15 @@ public final class BatchInput {
return severity_;
}
+ // optional bool manual_severity = 9;
public static final int MANUAL_SEVERITY_FIELD_NUMBER = 9;
private boolean manualSeverity_;
-
/**
* <code>optional bool manual_severity = 9;</code>
*/
public boolean hasManualSeverity() {
return ((bitField0_ & 0x00000100) == 0x00000100);
}
-
/**
* <code>optional bool manual_severity = 9;</code>
*/
@@ -721,16 +674,15 @@ public final class BatchInput {
return manualSeverity_;
}
+ // optional string resolution = 10;
public static final int RESOLUTION_FIELD_NUMBER = 10;
private java.lang.Object resolution_;
-
/**
* <code>optional string resolution = 10;</code>
*/
public boolean hasResolution() {
return ((bitField0_ & 0x00000200) == 0x00000200);
}
-
/**
* <code>optional string resolution = 10;</code>
*/
@@ -739,8 +691,8 @@ public final class BatchInput {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
resolution_ = s;
@@ -748,17 +700,16 @@ public final class BatchInput {
return s;
}
}
-
/**
* <code>optional string resolution = 10;</code>
*/
public com.google.protobuf.ByteString
- getResolutionBytes() {
+ getResolutionBytes() {
java.lang.Object ref = resolution_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
resolution_ = b;
return b;
} else {
@@ -766,16 +717,15 @@ public final class BatchInput {
}
}
+ // optional string status = 11;
public static final int STATUS_FIELD_NUMBER = 11;
private java.lang.Object status_;
-
/**
* <code>optional string status = 11;</code>
*/
public boolean hasStatus() {
return ((bitField0_ & 0x00000400) == 0x00000400);
}
-
/**
* <code>optional string status = 11;</code>
*/
@@ -784,8 +734,8 @@ public final class BatchInput {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
status_ = s;
@@ -793,17 +743,16 @@ public final class BatchInput {
return s;
}
}
-
/**
* <code>optional string status = 11;</code>
*/
public com.google.protobuf.ByteString
- getStatusBytes() {
+ getStatusBytes() {
java.lang.Object ref = status_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
status_ = b;
return b;
} else {
@@ -811,16 +760,15 @@ public final class BatchInput {
}
}
+ // optional string checksum = 12;
public static final int CHECKSUM_FIELD_NUMBER = 12;
private java.lang.Object checksum_;
-
/**
* <code>optional string checksum = 12;</code>
*/
public boolean hasChecksum() {
return ((bitField0_ & 0x00000800) == 0x00000800);
}
-
/**
* <code>optional string checksum = 12;</code>
*/
@@ -829,8 +777,8 @@ public final class BatchInput {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
checksum_ = s;
@@ -838,17 +786,16 @@ public final class BatchInput {
return s;
}
}
-
/**
* <code>optional string checksum = 12;</code>
*/
public com.google.protobuf.ByteString
- getChecksumBytes() {
+ getChecksumBytes() {
java.lang.Object ref = checksum_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
checksum_ = b;
return b;
} else {
@@ -856,16 +803,15 @@ public final class BatchInput {
}
}
+ // optional string assignee_login = 13;
public static final int ASSIGNEE_LOGIN_FIELD_NUMBER = 13;
private java.lang.Object assigneeLogin_;
-
/**
* <code>optional string assignee_login = 13;</code>
*/
public boolean hasAssigneeLogin() {
return ((bitField0_ & 0x00001000) == 0x00001000);
}
-
/**
* <code>optional string assignee_login = 13;</code>
*/
@@ -874,8 +820,8 @@ public final class BatchInput {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
assigneeLogin_ = s;
@@ -883,17 +829,16 @@ public final class BatchInput {
return s;
}
}
-
/**
* <code>optional string assignee_login = 13;</code>
*/
public com.google.protobuf.ByteString
- getAssigneeLoginBytes() {
+ getAssigneeLoginBytes() {
java.lang.Object ref = assigneeLogin_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
assigneeLogin_ = b;
return b;
} else {
@@ -901,16 +846,15 @@ public final class BatchInput {
}
}
+ // optional int64 creation_date = 14;
public static final int CREATION_DATE_FIELD_NUMBER = 14;
private long creationDate_;
-
/**
* <code>optional int64 creation_date = 14;</code>
*/
public boolean hasCreationDate() {
return ((bitField0_ & 0x00002000) == 0x00002000);
}
-
/**
* <code>optional int64 creation_date = 14;</code>
*/
@@ -934,22 +878,17 @@ public final class BatchInput {
assigneeLogin_ = "";
creationDate_ = 0L;
}
-
private byte memoizedIsInitialized = -1;
-
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
- if (isInitialized == 1)
- return true;
- if (isInitialized == 0)
- return false;
+ if (isInitialized != -1) return isInitialized == 1;
memoizedIsInitialized = 1;
return true;
}
public void writeTo(com.google.protobuf.CodedOutputStream output)
- throws java.io.IOException {
+ throws java.io.IOException {
getSerializedSize();
if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeBytes(1, getKeyBytes());
@@ -997,11 +936,9 @@ public final class BatchInput {
}
private int memoizedSerializedSize = -1;
-
public int getSerializedSize() {
int size = memoizedSerializedSize;
- if (size != -1)
- return size;
+ if (size != -1) return size;
size = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) {
@@ -1066,115 +1003,94 @@ public final class BatchInput {
}
private static final long serialVersionUID = 0L;
-
@java.lang.Override
protected java.lang.Object writeReplace()
- throws java.io.ObjectStreamException {
+ throws java.io.ObjectStreamException {
return super.writeReplace();
}
public static org.sonar.batch.protocol.input.BatchInput.ServerIssue parseFrom(
- com.google.protobuf.ByteString data)
- throws com.google.protobuf.InvalidProtocolBufferException {
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
-
public static org.sonar.batch.protocol.input.BatchInput.ServerIssue parseFrom(
- com.google.protobuf.ByteString data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
-
public static org.sonar.batch.protocol.input.BatchInput.ServerIssue parseFrom(byte[] data)
- throws com.google.protobuf.InvalidProtocolBufferException {
+ throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
-
public static org.sonar.batch.protocol.input.BatchInput.ServerIssue parseFrom(
- byte[] data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
-
public static org.sonar.batch.protocol.input.BatchInput.ServerIssue parseFrom(java.io.InputStream input)
- throws java.io.IOException {
+ throws java.io.IOException {
return PARSER.parseFrom(input);
}
-
public static org.sonar.batch.protocol.input.BatchInput.ServerIssue parseFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
return PARSER.parseFrom(input, extensionRegistry);
}
-
public static org.sonar.batch.protocol.input.BatchInput.ServerIssue parseDelimitedFrom(java.io.InputStream input)
- throws java.io.IOException {
+ throws java.io.IOException {
return PARSER.parseDelimitedFrom(input);
}
-
public static org.sonar.batch.protocol.input.BatchInput.ServerIssue parseDelimitedFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
return PARSER.parseDelimitedFrom(input, extensionRegistry);
}
-
public static org.sonar.batch.protocol.input.BatchInput.ServerIssue parseFrom(
- com.google.protobuf.CodedInputStream input)
- throws java.io.IOException {
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
return PARSER.parseFrom(input);
}
-
public static org.sonar.batch.protocol.input.BatchInput.ServerIssue parseFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
return PARSER.parseFrom(input, extensionRegistry);
}
- public static Builder newBuilder() {
- return Builder.create();
- }
-
- public Builder newBuilderForType() {
- return newBuilder();
- }
-
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder(org.sonar.batch.protocol.input.BatchInput.ServerIssue prototype) {
return newBuilder().mergeFrom(prototype);
}
-
- public Builder toBuilder() {
- return newBuilder(this);
- }
+ public Builder toBuilder() { return newBuilder(this); }
@java.lang.Override
protected Builder newBuilderForType(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
-
/**
* Protobuf type {@code ServerIssue}
*/
public static final class Builder extends
- com.google.protobuf.GeneratedMessage.Builder<Builder> implements
- // @@protoc_insertion_point(builder_implements:ServerIssue)
- org.sonar.batch.protocol.input.BatchInput.ServerIssueOrBuilder {
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.sonar.batch.protocol.input.BatchInput.ServerIssueOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
+ getDescriptor() {
return org.sonar.batch.protocol.input.BatchInput.internal_static_ServerIssue_descriptor;
}
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
+ internalGetFieldAccessorTable() {
return org.sonar.batch.protocol.input.BatchInput.internal_static_ServerIssue_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.sonar.batch.protocol.input.BatchInput.ServerIssue.class, org.sonar.batch.protocol.input.BatchInput.ServerIssue.Builder.class);
+ .ensureFieldAccessorsInitialized(
+ org.sonar.batch.protocol.input.BatchInput.ServerIssue.class, org.sonar.batch.protocol.input.BatchInput.ServerIssue.Builder.class);
}
// Construct using org.sonar.batch.protocol.input.BatchInput.ServerIssue.newBuilder()
@@ -1183,16 +1099,14 @@ public final class BatchInput {
}
private Builder(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
-
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
}
}
-
private static Builder create() {
return new Builder();
}
@@ -1235,7 +1149,7 @@ public final class BatchInput {
}
public com.google.protobuf.Descriptors.Descriptor
- getDescriptorForType() {
+ getDescriptorForType() {
return org.sonar.batch.protocol.input.BatchInput.internal_static_ServerIssue_descriptor;
}
@@ -1318,7 +1232,7 @@ public final class BatchInput {
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof org.sonar.batch.protocol.input.BatchInput.ServerIssue) {
- return mergeFrom((org.sonar.batch.protocol.input.BatchInput.ServerIssue) other);
+ return mergeFrom((org.sonar.batch.protocol.input.BatchInput.ServerIssue)other);
} else {
super.mergeFrom(other);
return this;
@@ -1326,8 +1240,7 @@ public final class BatchInput {
}
public Builder mergeFrom(org.sonar.batch.protocol.input.BatchInput.ServerIssue other) {
- if (other == org.sonar.batch.protocol.input.BatchInput.ServerIssue.getDefaultInstance())
- return this;
+ if (other == org.sonar.batch.protocol.input.BatchInput.ServerIssue.getDefaultInstance()) return this;
if (other.hasKey()) {
bitField0_ |= 0x00000001;
key_ = other.key_;
@@ -1399,9 +1312,9 @@ public final class BatchInput {
}
public Builder mergeFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
org.sonar.batch.protocol.input.BatchInput.ServerIssue parsedMessage = null;
try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
@@ -1415,67 +1328,59 @@ public final class BatchInput {
}
return this;
}
-
private int bitField0_;
+ // optional string key = 1;
private java.lang.Object key_ = "";
-
/**
* <code>optional string key = 1;</code>
*/
public boolean hasKey() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
-
/**
* <code>optional string key = 1;</code>
*/
public java.lang.String getKey() {
java.lang.Object ref = key_;
if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- key_ = s;
- }
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ key_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
-
/**
* <code>optional string key = 1;</code>
*/
public com.google.protobuf.ByteString
- getKeyBytes() {
+ getKeyBytes() {
java.lang.Object ref = key_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
key_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
-
/**
* <code>optional string key = 1;</code>
*/
public Builder setKey(
- java.lang.String value) {
+ java.lang.String value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000001;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
key_ = value;
onChanged();
return this;
}
-
/**
* <code>optional string key = 1;</code>
*/
@@ -1485,79 +1390,71 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional string key = 1;</code>
*/
public Builder setKeyBytes(
- com.google.protobuf.ByteString value) {
+ com.google.protobuf.ByteString value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000001;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
key_ = value;
onChanged();
return this;
}
+ // optional string module_key = 2;
private java.lang.Object moduleKey_ = "";
-
/**
* <code>optional string module_key = 2;</code>
*/
public boolean hasModuleKey() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
-
/**
* <code>optional string module_key = 2;</code>
*/
public java.lang.String getModuleKey() {
java.lang.Object ref = moduleKey_;
if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- moduleKey_ = s;
- }
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ moduleKey_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
-
/**
* <code>optional string module_key = 2;</code>
*/
public com.google.protobuf.ByteString
- getModuleKeyBytes() {
+ getModuleKeyBytes() {
java.lang.Object ref = moduleKey_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
moduleKey_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
-
/**
* <code>optional string module_key = 2;</code>
*/
public Builder setModuleKey(
- java.lang.String value) {
+ java.lang.String value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000002;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
moduleKey_ = value;
onChanged();
return this;
}
-
/**
* <code>optional string module_key = 2;</code>
*/
@@ -1567,79 +1464,71 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional string module_key = 2;</code>
*/
public Builder setModuleKeyBytes(
- com.google.protobuf.ByteString value) {
+ com.google.protobuf.ByteString value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000002;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
moduleKey_ = value;
onChanged();
return this;
}
+ // optional string path = 3;
private java.lang.Object path_ = "";
-
/**
* <code>optional string path = 3;</code>
*/
public boolean hasPath() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
-
/**
* <code>optional string path = 3;</code>
*/
public java.lang.String getPath() {
java.lang.Object ref = path_;
if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- path_ = s;
- }
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ path_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
-
/**
* <code>optional string path = 3;</code>
*/
public com.google.protobuf.ByteString
- getPathBytes() {
+ getPathBytes() {
java.lang.Object ref = path_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
path_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
-
/**
* <code>optional string path = 3;</code>
*/
public Builder setPath(
- java.lang.String value) {
+ java.lang.String value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000004;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
path_ = value;
onChanged();
return this;
}
-
/**
* <code>optional string path = 3;</code>
*/
@@ -1649,79 +1538,71 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional string path = 3;</code>
*/
public Builder setPathBytes(
- com.google.protobuf.ByteString value) {
+ com.google.protobuf.ByteString value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000004;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
path_ = value;
onChanged();
return this;
}
+ // optional string rule_repository = 4;
private java.lang.Object ruleRepository_ = "";
-
/**
* <code>optional string rule_repository = 4;</code>
*/
public boolean hasRuleRepository() {
return ((bitField0_ & 0x00000008) == 0x00000008);
}
-
/**
* <code>optional string rule_repository = 4;</code>
*/
public java.lang.String getRuleRepository() {
java.lang.Object ref = ruleRepository_;
if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- ruleRepository_ = s;
- }
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ ruleRepository_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
-
/**
* <code>optional string rule_repository = 4;</code>
*/
public com.google.protobuf.ByteString
- getRuleRepositoryBytes() {
+ getRuleRepositoryBytes() {
java.lang.Object ref = ruleRepository_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
ruleRepository_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
-
/**
* <code>optional string rule_repository = 4;</code>
*/
public Builder setRuleRepository(
- java.lang.String value) {
+ java.lang.String value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000008;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000008;
ruleRepository_ = value;
onChanged();
return this;
}
-
/**
* <code>optional string rule_repository = 4;</code>
*/
@@ -1731,79 +1612,71 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional string rule_repository = 4;</code>
*/
public Builder setRuleRepositoryBytes(
- com.google.protobuf.ByteString value) {
+ com.google.protobuf.ByteString value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000008;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000008;
ruleRepository_ = value;
onChanged();
return this;
}
+ // optional string rule_key = 5;
private java.lang.Object ruleKey_ = "";
-
/**
* <code>optional string rule_key = 5;</code>
*/
public boolean hasRuleKey() {
return ((bitField0_ & 0x00000010) == 0x00000010);
}
-
/**
* <code>optional string rule_key = 5;</code>
*/
public java.lang.String getRuleKey() {
java.lang.Object ref = ruleKey_;
if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- ruleKey_ = s;
- }
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ ruleKey_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
-
/**
* <code>optional string rule_key = 5;</code>
*/
public com.google.protobuf.ByteString
- getRuleKeyBytes() {
+ getRuleKeyBytes() {
java.lang.Object ref = ruleKey_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
ruleKey_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
-
/**
* <code>optional string rule_key = 5;</code>
*/
public Builder setRuleKey(
- java.lang.String value) {
+ java.lang.String value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000010;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000010;
ruleKey_ = value;
onChanged();
return this;
}
-
/**
* <code>optional string rule_key = 5;</code>
*/
@@ -1813,37 +1686,34 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional string rule_key = 5;</code>
*/
public Builder setRuleKeyBytes(
- com.google.protobuf.ByteString value) {
+ com.google.protobuf.ByteString value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000010;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000010;
ruleKey_ = value;
onChanged();
return this;
}
- private int line_;
-
+ // optional int32 line = 6;
+ private int line_ ;
/**
* <code>optional int32 line = 6;</code>
*/
public boolean hasLine() {
return ((bitField0_ & 0x00000020) == 0x00000020);
}
-
/**
* <code>optional int32 line = 6;</code>
*/
public int getLine() {
return line_;
}
-
/**
* <code>optional int32 line = 6;</code>
*/
@@ -1853,7 +1723,6 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional int32 line = 6;</code>
*/
@@ -1864,64 +1733,57 @@ public final class BatchInput {
return this;
}
+ // optional string msg = 7;
private java.lang.Object msg_ = "";
-
/**
* <code>optional string msg = 7;</code>
*/
public boolean hasMsg() {
return ((bitField0_ & 0x00000040) == 0x00000040);
}
-
/**
* <code>optional string msg = 7;</code>
*/
public java.lang.String getMsg() {
java.lang.Object ref = msg_;
if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- msg_ = s;
- }
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ msg_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
-
/**
* <code>optional string msg = 7;</code>
*/
public com.google.protobuf.ByteString
- getMsgBytes() {
+ getMsgBytes() {
java.lang.Object ref = msg_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
msg_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
-
/**
* <code>optional string msg = 7;</code>
*/
public Builder setMsg(
- java.lang.String value) {
+ java.lang.String value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000040;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000040;
msg_ = value;
onChanged();
return this;
}
-
/**
* <code>optional string msg = 7;</code>
*/
@@ -1931,37 +1793,34 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional string msg = 7;</code>
*/
public Builder setMsgBytes(
- com.google.protobuf.ByteString value) {
+ com.google.protobuf.ByteString value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000040;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000040;
msg_ = value;
onChanged();
return this;
}
+ // optional .Severity severity = 8;
private org.sonar.batch.protocol.Constants.Severity severity_ = org.sonar.batch.protocol.Constants.Severity.INFO;
-
/**
* <code>optional .Severity severity = 8;</code>
*/
public boolean hasSeverity() {
return ((bitField0_ & 0x00000080) == 0x00000080);
}
-
/**
* <code>optional .Severity severity = 8;</code>
*/
public org.sonar.batch.protocol.Constants.Severity getSeverity() {
return severity_;
}
-
/**
* <code>optional .Severity severity = 8;</code>
*/
@@ -1974,7 +1833,6 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional .Severity severity = 8;</code>
*/
@@ -1985,22 +1843,20 @@ public final class BatchInput {
return this;
}
- private boolean manualSeverity_;
-
+ // optional bool manual_severity = 9;
+ private boolean manualSeverity_ ;
/**
* <code>optional bool manual_severity = 9;</code>
*/
public boolean hasManualSeverity() {
return ((bitField0_ & 0x00000100) == 0x00000100);
}
-
/**
* <code>optional bool manual_severity = 9;</code>
*/
public boolean getManualSeverity() {
return manualSeverity_;
}
-
/**
* <code>optional bool manual_severity = 9;</code>
*/
@@ -2010,7 +1866,6 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional bool manual_severity = 9;</code>
*/
@@ -2021,64 +1876,57 @@ public final class BatchInput {
return this;
}
+ // optional string resolution = 10;
private java.lang.Object resolution_ = "";
-
/**
* <code>optional string resolution = 10;</code>
*/
public boolean hasResolution() {
return ((bitField0_ & 0x00000200) == 0x00000200);
}
-
/**
* <code>optional string resolution = 10;</code>
*/
public java.lang.String getResolution() {
java.lang.Object ref = resolution_;
if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- resolution_ = s;
- }
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ resolution_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
-
/**
* <code>optional string resolution = 10;</code>
*/
public com.google.protobuf.ByteString
- getResolutionBytes() {
+ getResolutionBytes() {
java.lang.Object ref = resolution_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
resolution_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
-
/**
* <code>optional string resolution = 10;</code>
*/
public Builder setResolution(
- java.lang.String value) {
+ java.lang.String value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000200;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000200;
resolution_ = value;
onChanged();
return this;
}
-
/**
* <code>optional string resolution = 10;</code>
*/
@@ -2088,79 +1936,71 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional string resolution = 10;</code>
*/
public Builder setResolutionBytes(
- com.google.protobuf.ByteString value) {
+ com.google.protobuf.ByteString value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000200;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000200;
resolution_ = value;
onChanged();
return this;
}
+ // optional string status = 11;
private java.lang.Object status_ = "";
-
/**
* <code>optional string status = 11;</code>
*/
public boolean hasStatus() {
return ((bitField0_ & 0x00000400) == 0x00000400);
}
-
/**
* <code>optional string status = 11;</code>
*/
public java.lang.String getStatus() {
java.lang.Object ref = status_;
if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- status_ = s;
- }
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ status_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
-
/**
* <code>optional string status = 11;</code>
*/
public com.google.protobuf.ByteString
- getStatusBytes() {
+ getStatusBytes() {
java.lang.Object ref = status_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
status_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
-
/**
* <code>optional string status = 11;</code>
*/
public Builder setStatus(
- java.lang.String value) {
+ java.lang.String value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000400;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000400;
status_ = value;
onChanged();
return this;
}
-
/**
* <code>optional string status = 11;</code>
*/
@@ -2170,79 +2010,71 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional string status = 11;</code>
*/
public Builder setStatusBytes(
- com.google.protobuf.ByteString value) {
+ com.google.protobuf.ByteString value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000400;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000400;
status_ = value;
onChanged();
return this;
}
+ // optional string checksum = 12;
private java.lang.Object checksum_ = "";
-
/**
* <code>optional string checksum = 12;</code>
*/
public boolean hasChecksum() {
return ((bitField0_ & 0x00000800) == 0x00000800);
}
-
/**
* <code>optional string checksum = 12;</code>
*/
public java.lang.String getChecksum() {
java.lang.Object ref = checksum_;
if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- checksum_ = s;
- }
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ checksum_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
-
/**
* <code>optional string checksum = 12;</code>
*/
public com.google.protobuf.ByteString
- getChecksumBytes() {
+ getChecksumBytes() {
java.lang.Object ref = checksum_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
checksum_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
-
/**
* <code>optional string checksum = 12;</code>
*/
public Builder setChecksum(
- java.lang.String value) {
+ java.lang.String value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000800;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000800;
checksum_ = value;
onChanged();
return this;
}
-
/**
* <code>optional string checksum = 12;</code>
*/
@@ -2252,79 +2084,71 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional string checksum = 12;</code>
*/
public Builder setChecksumBytes(
- com.google.protobuf.ByteString value) {
+ com.google.protobuf.ByteString value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000800;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000800;
checksum_ = value;
onChanged();
return this;
}
+ // optional string assignee_login = 13;
private java.lang.Object assigneeLogin_ = "";
-
/**
* <code>optional string assignee_login = 13;</code>
*/
public boolean hasAssigneeLogin() {
return ((bitField0_ & 0x00001000) == 0x00001000);
}
-
/**
* <code>optional string assignee_login = 13;</code>
*/
public java.lang.String getAssigneeLogin() {
java.lang.Object ref = assigneeLogin_;
if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- assigneeLogin_ = s;
- }
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ assigneeLogin_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
-
/**
* <code>optional string assignee_login = 13;</code>
*/
public com.google.protobuf.ByteString
- getAssigneeLoginBytes() {
+ getAssigneeLoginBytes() {
java.lang.Object ref = assigneeLogin_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
assigneeLogin_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
-
/**
* <code>optional string assignee_login = 13;</code>
*/
public Builder setAssigneeLogin(
- java.lang.String value) {
+ java.lang.String value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00001000;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00001000;
assigneeLogin_ = value;
onChanged();
return this;
}
-
/**
* <code>optional string assignee_login = 13;</code>
*/
@@ -2334,37 +2158,34 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional string assignee_login = 13;</code>
*/
public Builder setAssigneeLoginBytes(
- com.google.protobuf.ByteString value) {
+ com.google.protobuf.ByteString value) {
if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00001000;
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00001000;
assigneeLogin_ = value;
onChanged();
return this;
}
- private long creationDate_;
-
+ // optional int64 creation_date = 14;
+ private long creationDate_ ;
/**
* <code>optional int64 creation_date = 14;</code>
*/
public boolean hasCreationDate() {
return ((bitField0_ & 0x00002000) == 0x00002000);
}
-
/**
* <code>optional int64 creation_date = 14;</code>
*/
public long getCreationDate() {
return creationDate_;
}
-
/**
* <code>optional int64 creation_date = 14;</code>
*/
@@ -2374,7 +2195,6 @@ public final class BatchInput {
onChanged();
return this;
}
-
/**
* <code>optional int64 creation_date = 14;</code>
*/
@@ -2396,48 +2216,49 @@ public final class BatchInput {
// @@protoc_insertion_point(class_scope:ServerIssue)
}
- private static final com.google.protobuf.Descriptors.Descriptor internal_static_ServerIssue_descriptor;
- private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_ServerIssue_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_ServerIssue_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_ServerIssue_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
- getDescriptor() {
+ getDescriptor() {
return descriptor;
}
-
- private static com.google.protobuf.Descriptors.FileDescriptor descriptor;
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
static {
java.lang.String[] descriptorData = {
"\n\021batch_input.proto\032\017constants.proto\"\235\002\n" +
- "\013ServerIssue\022\013\n\003key\030\001 \001(\t\022\022\n\nmodule_key\030" +
- "\002 \001(\t\022\014\n\004path\030\003 \001(\t\022\027\n\017rule_repository\030\004" +
- " \001(\t\022\020\n\010rule_key\030\005 \001(\t\022\014\n\004line\030\006 \001(\005\022\013\n\003" +
- "msg\030\007 \001(\t\022\033\n\010severity\030\010 \001(\0162\t.Severity\022\027" +
- "\n\017manual_severity\030\t \001(\010\022\022\n\nresolution\030\n " +
- "\001(\t\022\016\n\006status\030\013 \001(\t\022\020\n\010checksum\030\014 \001(\t\022\026\n" +
- "\016assignee_login\030\r \001(\t\022\025\n\rcreation_date\030\016" +
- " \001(\003B\"\n\036org.sonar.batch.protocol.inputH\001"
+ "\013ServerIssue\022\013\n\003key\030\001 \001(\t\022\022\n\nmodule_key\030" +
+ "\002 \001(\t\022\014\n\004path\030\003 \001(\t\022\027\n\017rule_repository\030\004" +
+ " \001(\t\022\020\n\010rule_key\030\005 \001(\t\022\014\n\004line\030\006 \001(\005\022\013\n\003" +
+ "msg\030\007 \001(\t\022\033\n\010severity\030\010 \001(\0162\t.Severity\022\027" +
+ "\n\017manual_severity\030\t \001(\010\022\022\n\nresolution\030\n " +
+ "\001(\t\022\016\n\006status\030\013 \001(\t\022\020\n\010checksum\030\014 \001(\t\022\026\n" +
+ "\016assignee_login\030\r \001(\t\022\025\n\rcreation_date\030\016" +
+ " \001(\003B\"\n\036org.sonar.batch.protocol.inputH\001"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
public com.google.protobuf.ExtensionRegistry assignDescriptors(
- com.google.protobuf.Descriptors.FileDescriptor root) {
+ com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root;
+ internal_static_ServerIssue_descriptor =
+ getDescriptor().getMessageTypes().get(0);
+ internal_static_ServerIssue_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_ServerIssue_descriptor,
+ new java.lang.String[] { "Key", "ModuleKey", "Path", "RuleRepository", "RuleKey", "Line", "Msg", "Severity", "ManualSeverity", "Resolution", "Status", "Checksum", "AssigneeLogin", "CreationDate", });
return null;
}
};
com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
- org.sonar.batch.protocol.Constants.getDescriptor(),
+ org.sonar.batch.protocol.Constants.getDescriptor(),
}, assigner);
- internal_static_ServerIssue_descriptor =
- getDescriptor().getMessageTypes().get(0);
- internal_static_ServerIssue_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_ServerIssue_descriptor,
- new java.lang.String[] {"Key", "ModuleKey", "Path", "RuleRepository", "RuleKey", "Line", "Msg", "Severity", "ManualSeverity", "Resolution", "Status", "Checksum",
- "AssigneeLogin", "CreationDate",});
- org.sonar.batch.protocol.Constants.getDescriptor();
}
// @@protoc_insertion_point(outer_class_scope)
diff --git a/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchReport.java b/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchReport.java
index 8e5ca2c921c..c2d7821b918 100644
--- a/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchReport.java
+++ b/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchReport.java
@@ -45,6 +45,34 @@ public final class BatchReport {
* <code>optional int32 root_component_ref = 3;</code>
*/
int getRootComponentRef();
+
+ // optional int64 snapshot_id = 4;
+ /**
+ * <code>optional int64 snapshot_id = 4;</code>
+ *
+ * <pre>
+ * temporary fields used during development of computation stack
+ * </pre>
+ */
+ boolean hasSnapshotId();
+ /**
+ * <code>optional int64 snapshot_id = 4;</code>
+ *
+ * <pre>
+ * temporary fields used during development of computation stack
+ * </pre>
+ */
+ long getSnapshotId();
+
+ // optional int32 deleted_components_count = 5;
+ /**
+ * <code>optional int32 deleted_components_count = 5;</code>
+ */
+ boolean hasDeletedComponentsCount();
+ /**
+ * <code>optional int32 deleted_components_count = 5;</code>
+ */
+ int getDeletedComponentsCount();
}
/**
* Protobuf type {@code Metadata}
@@ -112,6 +140,16 @@ public final class BatchReport {
rootComponentRef_ = input.readInt32();
break;
}
+ case 32: {
+ bitField0_ |= 0x00000008;
+ snapshotId_ = input.readInt64();
+ break;
+ }
+ case 40: {
+ bitField0_ |= 0x00000010;
+ deletedComponentsCount_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -227,10 +265,52 @@ public final class BatchReport {
return rootComponentRef_;
}
+ // optional int64 snapshot_id = 4;
+ public static final int SNAPSHOT_ID_FIELD_NUMBER = 4;
+ private long snapshotId_;
+ /**
+ * <code>optional int64 snapshot_id = 4;</code>
+ *
+ * <pre>
+ * temporary fields used during development of computation stack
+ * </pre>
+ */
+ public boolean hasSnapshotId() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional int64 snapshot_id = 4;</code>
+ *
+ * <pre>
+ * temporary fields used during development of computation stack
+ * </pre>
+ */
+ public long getSnapshotId() {
+ return snapshotId_;
+ }
+
+ // optional int32 deleted_components_count = 5;
+ public static final int DELETED_COMPONENTS_COUNT_FIELD_NUMBER = 5;
+ private int deletedComponentsCount_;
+ /**
+ * <code>optional int32 deleted_components_count = 5;</code>
+ */
+ public boolean hasDeletedComponentsCount() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional int32 deleted_components_count = 5;</code>
+ */
+ public int getDeletedComponentsCount() {
+ return deletedComponentsCount_;
+ }
+
private void initFields() {
analysisDate_ = 0L;
projectKey_ = "";
rootComponentRef_ = 0;
+ snapshotId_ = 0L;
+ deletedComponentsCount_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -253,6 +333,12 @@ public final class BatchReport {
if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeInt32(3, rootComponentRef_);
}
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeInt64(4, snapshotId_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeInt32(5, deletedComponentsCount_);
+ }
getUnknownFields().writeTo(output);
}
@@ -274,6 +360,14 @@ public final class BatchReport {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(3, rootComponentRef_);
}
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt64Size(4, snapshotId_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(5, deletedComponentsCount_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -396,6 +490,10 @@ public final class BatchReport {
bitField0_ = (bitField0_ & ~0x00000002);
rootComponentRef_ = 0;
bitField0_ = (bitField0_ & ~0x00000004);
+ snapshotId_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ deletedComponentsCount_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
@@ -436,6 +534,14 @@ public final class BatchReport {
to_bitField0_ |= 0x00000004;
}
result.rootComponentRef_ = rootComponentRef_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.snapshotId_ = snapshotId_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.deletedComponentsCount_ = deletedComponentsCount_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -463,6 +569,12 @@ public final class BatchReport {
if (other.hasRootComponentRef()) {
setRootComponentRef(other.getRootComponentRef());
}
+ if (other.hasSnapshotId()) {
+ setSnapshotId(other.getSnapshotId());
+ }
+ if (other.hasDeletedComponentsCount()) {
+ setDeletedComponentsCount(other.getDeletedComponentsCount());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -630,6 +742,88 @@ public final class BatchReport {
return this;
}
+ // optional int64 snapshot_id = 4;
+ private long snapshotId_ ;
+ /**
+ * <code>optional int64 snapshot_id = 4;</code>
+ *
+ * <pre>
+ * temporary fields used during development of computation stack
+ * </pre>
+ */
+ public boolean hasSnapshotId() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional int64 snapshot_id = 4;</code>
+ *
+ * <pre>
+ * temporary fields used during development of computation stack
+ * </pre>
+ */
+ public long getSnapshotId() {
+ return snapshotId_;
+ }
+ /**
+ * <code>optional int64 snapshot_id = 4;</code>
+ *
+ * <pre>
+ * temporary fields used during development of computation stack
+ * </pre>
+ */
+ public Builder setSnapshotId(long value) {
+ bitField0_ |= 0x00000008;
+ snapshotId_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int64 snapshot_id = 4;</code>
+ *
+ * <pre>
+ * temporary fields used during development of computation stack
+ * </pre>
+ */
+ public Builder clearSnapshotId() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ snapshotId_ = 0L;
+ onChanged();
+ return this;
+ }
+
+ // optional int32 deleted_components_count = 5;
+ private int deletedComponentsCount_ ;
+ /**
+ * <code>optional int32 deleted_components_count = 5;</code>
+ */
+ public boolean hasDeletedComponentsCount() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional int32 deleted_components_count = 5;</code>
+ */
+ public int getDeletedComponentsCount() {
+ return deletedComponentsCount_;
+ }
+ /**
+ * <code>optional int32 deleted_components_count = 5;</code>
+ */
+ public Builder setDeletedComponentsCount(int value) {
+ bitField0_ |= 0x00000010;
+ deletedComponentsCount_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 deleted_components_count = 5;</code>
+ */
+ public Builder clearDeletedComponentsCount() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ deletedComponentsCount_ = 0;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:Metadata)
}
@@ -5690,6 +5884,33 @@ public final class BatchReport {
*/
org.sonar.batch.protocol.output.BatchReport.IssueOrBuilder getListOrBuilder(
int index);
+
+ // optional string component_uuid = 3;
+ /**
+ * <code>optional string component_uuid = 3;</code>
+ *
+ * <pre>
+ * Temporary field for issues on deleted components
+ * </pre>
+ */
+ boolean hasComponentUuid();
+ /**
+ * <code>optional string component_uuid = 3;</code>
+ *
+ * <pre>
+ * Temporary field for issues on deleted components
+ * </pre>
+ */
+ java.lang.String getComponentUuid();
+ /**
+ * <code>optional string component_uuid = 3;</code>
+ *
+ * <pre>
+ * Temporary field for issues on deleted components
+ * </pre>
+ */
+ com.google.protobuf.ByteString
+ getComponentUuidBytes();
}
/**
* Protobuf type {@code Issues}
@@ -5755,6 +5976,11 @@ public final class BatchReport {
list_.add(input.readMessage(org.sonar.batch.protocol.output.BatchReport.Issue.PARSER, extensionRegistry));
break;
}
+ case 26: {
+ bitField0_ |= 0x00000002;
+ componentUuid_ = input.readBytes();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -5850,9 +6076,65 @@ public final class BatchReport {
return list_.get(index);
}
+ // optional string component_uuid = 3;
+ public static final int COMPONENT_UUID_FIELD_NUMBER = 3;
+ private java.lang.Object componentUuid_;
+ /**
+ * <code>optional string component_uuid = 3;</code>
+ *
+ * <pre>
+ * Temporary field for issues on deleted components
+ * </pre>
+ */
+ public boolean hasComponentUuid() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional string component_uuid = 3;</code>
+ *
+ * <pre>
+ * Temporary field for issues on deleted components
+ * </pre>
+ */
+ public java.lang.String getComponentUuid() {
+ java.lang.Object ref = componentUuid_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ if (bs.isValidUtf8()) {
+ componentUuid_ = s;
+ }
+ return s;
+ }
+ }
+ /**
+ * <code>optional string component_uuid = 3;</code>
+ *
+ * <pre>
+ * Temporary field for issues on deleted components
+ * </pre>
+ */
+ public com.google.protobuf.ByteString
+ getComponentUuidBytes() {
+ java.lang.Object ref = componentUuid_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ componentUuid_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
private void initFields() {
componentRef_ = 0;
list_ = java.util.Collections.emptyList();
+ componentUuid_ = "";
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -5872,6 +6154,9 @@ public final class BatchReport {
for (int i = 0; i < list_.size(); i++) {
output.writeMessage(2, list_.get(i));
}
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(3, getComponentUuidBytes());
+ }
getUnknownFields().writeTo(output);
}
@@ -5889,6 +6174,10 @@ public final class BatchReport {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(2, list_.get(i));
}
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, getComponentUuidBytes());
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -6014,6 +6303,8 @@ public final class BatchReport {
} else {
listBuilder_.clear();
}
+ componentUuid_ = "";
+ bitField0_ = (bitField0_ & ~0x00000004);
return this;
}
@@ -6055,6 +6346,10 @@ public final class BatchReport {
} else {
result.list_ = listBuilder_.build();
}
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.componentUuid_ = componentUuid_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -6100,6 +6395,11 @@ public final class BatchReport {
}
}
}
+ if (other.hasComponentUuid()) {
+ bitField0_ |= 0x00000004;
+ componentUuid_ = other.componentUuid_;
+ onChanged();
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -6400,6 +6700,104 @@ public final class BatchReport {
return listBuilder_;
}
+ // optional string component_uuid = 3;
+ private java.lang.Object componentUuid_ = "";
+ /**
+ * <code>optional string component_uuid = 3;</code>
+ *
+ * <pre>
+ * Temporary field for issues on deleted components
+ * </pre>
+ */
+ public boolean hasComponentUuid() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional string component_uuid = 3;</code>
+ *
+ * <pre>
+ * Temporary field for issues on deleted components
+ * </pre>
+ */
+ public java.lang.String getComponentUuid() {
+ java.lang.Object ref = componentUuid_;
+ if (!(ref instanceof java.lang.String)) {
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ componentUuid_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ * <code>optional string component_uuid = 3;</code>
+ *
+ * <pre>
+ * Temporary field for issues on deleted components
+ * </pre>
+ */
+ public com.google.protobuf.ByteString
+ getComponentUuidBytes() {
+ java.lang.Object ref = componentUuid_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ componentUuid_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ * <code>optional string component_uuid = 3;</code>
+ *
+ * <pre>
+ * Temporary field for issues on deleted components
+ * </pre>
+ */
+ public Builder setComponentUuid(
+ java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ componentUuid_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional string component_uuid = 3;</code>
+ *
+ * <pre>
+ * Temporary field for issues on deleted components
+ * </pre>
+ */
+ public Builder clearComponentUuid() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ componentUuid_ = getDefaultInstance().getComponentUuid();
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional string component_uuid = 3;</code>
+ *
+ * <pre>
+ * Temporary field for issues on deleted components
+ * </pre>
+ */
+ public Builder setComponentUuidBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ componentUuid_ = value;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:Issues)
}
@@ -6440,29 +6838,31 @@ public final class BatchReport {
descriptor;
static {
java.lang.String[] descriptorData = {
- "\n\022batch_report.proto\032\017constants.proto\"R\n" +
- "\010Metadata\022\025\n\ranalysis_date\030\001 \001(\003\022\023\n\013proj" +
- "ect_key\030\002 \001(\t\022\032\n\022root_component_ref\030\003 \001(" +
- "\005\"\260\001\n\tComponent\022\013\n\003ref\030\001 \001(\005\022\014\n\004path\030\002 \001" +
- "(\t\022\014\n\004name\030\003 \001(\t\022\034\n\004type\030\004 \001(\0162\016.Compone" +
- "ntType\022\017\n\007is_test\030\005 \001(\010\022\020\n\010language\030\006 \001(" +
- "\t\022\026\n\nchild_refs\030\007 \003(\005B\002\020\001\022\023\n\013snapshot_id" +
- "\030\010 \001(\005\022\014\n\004uuid\030\t \001(\t\"\232\004\n\005Issue\022\027\n\017rule_r" +
- "epository\030\001 \001(\t\022\020\n\010rule_key\030\002 \001(\t\022\014\n\004lin" +
- "e\030\003 \001(\005\022\013\n\003msg\030\004 \001(\t\022\033\n\010severity\030\005 \001(\0162\t",
- ".Severity\022\014\n\004tags\030\006 \003(\t\022\025\n\reffort_to_fix" +
- "\030\007 \001(\001\022\016\n\006is_new\030\010 \001(\010\022\014\n\004uuid\030\t \001(\t\022\027\n\017" +
- "debt_in_minutes\030\n \001(\003\022\022\n\nresolution\030\013 \001(" +
- "\t\022\016\n\006status\030\014 \001(\t\022\020\n\010checksum\030\r \001(\t\022\027\n\017m" +
- "anual_severity\030\016 \001(\010\022\020\n\010reporter\030\017 \001(\t\022\020" +
- "\n\010assignee\030\020 \001(\t\022\027\n\017action_plan_key\030\021 \001(" +
- "\t\022\022\n\nattributes\030\022 \001(\t\022\024\n\014author_login\030\023 " +
- "\001(\t\022\025\n\rcreation_date\030\024 \001(\003\022\022\n\nclose_date" +
- "\030\025 \001(\003\022\023\n\013update_date\030\026 \001(\003\022\023\n\013selected_" +
- "at\030\027 \001(\003\022\023\n\013diff_fields\030\030 \001(\t\022\022\n\nis_chan",
- "ged\030\031 \001(\010\022\036\n\026must_send_notification\030\032 \001(" +
- "\010\"5\n\006Issues\022\025\n\rcomponent_ref\030\001 \001(\005\022\024\n\004li" +
- "st\030\002 \003(\0132\006.IssueB#\n\037org.sonar.batch.prot" +
+ "\n\022batch_report.proto\032\017constants.proto\"\211\001" +
+ "\n\010Metadata\022\025\n\ranalysis_date\030\001 \001(\003\022\023\n\013pro" +
+ "ject_key\030\002 \001(\t\022\032\n\022root_component_ref\030\003 \001" +
+ "(\005\022\023\n\013snapshot_id\030\004 \001(\003\022 \n\030deleted_compo" +
+ "nents_count\030\005 \001(\005\"\260\001\n\tComponent\022\013\n\003ref\030\001" +
+ " \001(\005\022\014\n\004path\030\002 \001(\t\022\014\n\004name\030\003 \001(\t\022\034\n\004type" +
+ "\030\004 \001(\0162\016.ComponentType\022\017\n\007is_test\030\005 \001(\010\022" +
+ "\020\n\010language\030\006 \001(\t\022\026\n\nchild_refs\030\007 \003(\005B\002\020" +
+ "\001\022\023\n\013snapshot_id\030\010 \001(\005\022\014\n\004uuid\030\t \001(\t\"\232\004\n" +
+ "\005Issue\022\027\n\017rule_repository\030\001 \001(\t\022\020\n\010rule_",
+ "key\030\002 \001(\t\022\014\n\004line\030\003 \001(\005\022\013\n\003msg\030\004 \001(\t\022\033\n\010" +
+ "severity\030\005 \001(\0162\t.Severity\022\014\n\004tags\030\006 \003(\t\022" +
+ "\025\n\reffort_to_fix\030\007 \001(\001\022\016\n\006is_new\030\010 \001(\010\022\014" +
+ "\n\004uuid\030\t \001(\t\022\027\n\017debt_in_minutes\030\n \001(\003\022\022\n" +
+ "\nresolution\030\013 \001(\t\022\016\n\006status\030\014 \001(\t\022\020\n\010che" +
+ "cksum\030\r \001(\t\022\027\n\017manual_severity\030\016 \001(\010\022\020\n\010" +
+ "reporter\030\017 \001(\t\022\020\n\010assignee\030\020 \001(\t\022\027\n\017acti" +
+ "on_plan_key\030\021 \001(\t\022\022\n\nattributes\030\022 \001(\t\022\024\n" +
+ "\014author_login\030\023 \001(\t\022\025\n\rcreation_date\030\024 \001" +
+ "(\003\022\022\n\nclose_date\030\025 \001(\003\022\023\n\013update_date\030\026 ",
+ "\001(\003\022\023\n\013selected_at\030\027 \001(\003\022\023\n\013diff_fields\030" +
+ "\030 \001(\t\022\022\n\nis_changed\030\031 \001(\010\022\036\n\026must_send_n" +
+ "otification\030\032 \001(\010\"M\n\006Issues\022\025\n\rcomponent" +
+ "_ref\030\001 \001(\005\022\024\n\004list\030\002 \003(\0132\006.Issue\022\026\n\016comp" +
+ "onent_uuid\030\003 \001(\tB#\n\037org.sonar.batch.prot" +
"ocol.outputH\001"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
@@ -6475,7 +6875,7 @@ public final class BatchReport {
internal_static_Metadata_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_Metadata_descriptor,
- new java.lang.String[] { "AnalysisDate", "ProjectKey", "RootComponentRef", });
+ new java.lang.String[] { "AnalysisDate", "ProjectKey", "RootComponentRef", "SnapshotId", "DeletedComponentsCount", });
internal_static_Component_descriptor =
getDescriptor().getMessageTypes().get(1);
internal_static_Component_fieldAccessorTable = new
@@ -6493,7 +6893,7 @@ public final class BatchReport {
internal_static_Issues_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_Issues_descriptor,
- new java.lang.String[] { "ComponentRef", "List", });
+ new java.lang.String[] { "ComponentRef", "List", "ComponentUuid", });
return null;
}
};
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchOutputReader.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportReader.java
index 28c50041c82..a2cee3bd75f 100644
--- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchOutputReader.java
+++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportReader.java
@@ -20,16 +20,17 @@
package org.sonar.batch.protocol.output;
import org.sonar.batch.protocol.ProtobufUtil;
+import org.sonar.batch.protocol.output.BatchReport.Issues;
-import javax.annotation.CheckForNull;
import java.io.File;
import java.util.Collections;
+import java.util.List;
-public class BatchOutputReader {
+public class BatchReportReader {
private final FileStructure fileStructure;
- public BatchOutputReader(File dir) {
+ public BatchReportReader(File dir) {
this.fileStructure = new FileStructure(dir);
}
@@ -41,16 +42,15 @@ public class BatchOutputReader {
return ProtobufUtil.readFile(file, BatchReport.Metadata.PARSER);
}
- @CheckForNull
public BatchReport.Component readComponent(int componentRef) {
File file = fileStructure.fileFor(FileStructure.Domain.COMPONENT, componentRef);
- if (file.exists() && file.isFile()) {
- return ProtobufUtil.readFile(file, BatchReport.Component.PARSER);
+ if (!file.exists() || !file.isFile()) {
+ throw new IllegalStateException("Unable to find report for component #" + componentRef + ". File does not exist: " + file);
}
- return null;
+ return ProtobufUtil.readFile(file, BatchReport.Component.PARSER);
}
- public Iterable<BatchReport.Issue> readComponentIssues(int componentRef) {
+ public List<BatchReport.Issue> readComponentIssues(int componentRef) {
File file = fileStructure.fileFor(FileStructure.Domain.ISSUES, componentRef);
if (file.exists() && file.isFile()) {
// all the issues are loaded in memory
@@ -59,4 +59,13 @@ public class BatchOutputReader {
}
return Collections.emptyList();
}
+
+ public Issues readDeletedComponentIssues(int deletedComponentRef) {
+ File file = fileStructure.fileFor(FileStructure.Domain.ISSUES_ON_DELETED, deletedComponentRef);
+ if (!file.exists() || !file.isFile()) {
+ throw new IllegalStateException("Unable to find report for deleted component #" + deletedComponentRef);
+ }
+ // all the issues are loaded in memory
+ return ProtobufUtil.readFile(file, Issues.PARSER);
+ }
}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchOutputWriter.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java
index 2e12a297e1e..55ced1fa354 100644
--- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchOutputWriter.java
+++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java
@@ -23,11 +23,11 @@ import org.sonar.batch.protocol.ProtobufUtil;
import java.io.File;
-public class BatchOutputWriter {
+public class BatchReportWriter {
private final FileStructure fileStructure;
- public BatchOutputWriter(File dir) {
+ public BatchReportWriter(File dir) {
if (!dir.exists() && !dir.mkdirs()) {
throw new IllegalStateException("Unable to create directory: " + dir);
}
@@ -62,4 +62,18 @@ public class BatchOutputWriter {
File file = fileStructure.fileFor(FileStructure.Domain.ISSUES, componentRef);
ProtobufUtil.writeToFile(issuesBuilder.build(), file);
}
+
+ /**
+ * Issues on components which have been deleted are stored in another location.
+ * Temporary hack, waiting for computation stack
+ */
+ public void writeDeletedComponentIssues(int componentRef, String componentUuid, Iterable<BatchReport.Issue> issues) {
+ BatchReport.Issues.Builder issuesBuilder = BatchReport.Issues.newBuilder();
+ issuesBuilder.setComponentRef(componentRef);
+ issuesBuilder.setComponentUuid(componentUuid);
+ issuesBuilder.addAllList(issues);
+ File file = fileStructure.fileFor(FileStructure.Domain.ISSUES_ON_DELETED, componentRef);
+ ProtobufUtil.writeToFile(issuesBuilder.build(), file);
+ }
+
}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java
index 5e2d51b26ce..4f9529d2c3b 100644
--- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java
+++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java
@@ -27,7 +27,7 @@ import java.io.File;
public class FileStructure {
public static enum Domain {
- ISSUES("issues-"), COMPONENT("component-");
+ ISSUES("issues-"), ISSUES_ON_DELETED("issues-deleted-"), COMPONENT("component-");
private final String filePrefix;
diff --git a/sonar-batch-protocol/src/main/protobuf/batch_report.proto b/sonar-batch-protocol/src/main/protobuf/batch_report.proto
index d1acbfe00a3..546f33f86fb 100644
--- a/sonar-batch-protocol/src/main/protobuf/batch_report.proto
+++ b/sonar-batch-protocol/src/main/protobuf/batch_report.proto
@@ -42,6 +42,10 @@ message Metadata {
optional int64 analysis_date = 1;
optional string project_key = 2;
optional int32 root_component_ref = 3;
+
+ // temporary fields used during development of computation stack
+ optional int64 snapshot_id = 4;
+ optional int32 deleted_components_count = 5;
}
message Component {
@@ -92,4 +96,7 @@ message Issue {
message Issues {
optional int32 component_ref = 1;
repeated Issue list = 2;
+
+ // Temporary field for issues on deleted components
+ optional string component_uuid = 3;
}
diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchOutputReaderTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportReaderTest.java
index c9fc72df6c7..cee15cf1c65 100644
--- a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchOutputReaderTest.java
+++ b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportReaderTest.java
@@ -22,13 +22,15 @@ package org.sonar.batch.protocol.output;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.sonar.batch.protocol.output.BatchReport.Issues;
+import org.sonar.batch.protocol.output.BatchReport.Metadata;
import java.io.File;
import java.util.Arrays;
import static org.assertj.core.api.Assertions.assertThat;
-public class BatchOutputReaderTest {
+public class BatchReportReaderTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@@ -39,22 +41,61 @@ public class BatchOutputReaderTest {
initFiles(dir);
- BatchOutputReader reader = new BatchOutputReader(dir);
- assertThat(reader.readMetadata().getAnalysisDate()).isEqualTo(15000000L);
+ BatchReportReader reader = new BatchReportReader(dir);
+ Metadata readMetadata = reader.readMetadata();
+ assertThat(readMetadata.getAnalysisDate()).isEqualTo(15000000L);
+ assertThat(readMetadata.getDeletedComponentsCount()).isEqualTo(1);
assertThat(reader.readComponentIssues(1)).hasSize(1);
assertThat(reader.readComponentIssues(200)).isEmpty();
assertThat(reader.readComponent(1).getUuid()).isEqualTo("UUID_A");
- assertThat(reader.readComponent(200)).isNull();
+ Issues deletedComponentIssues = reader.readDeletedComponentIssues(1);
+ assertThat(deletedComponentIssues.getComponentUuid()).isEqualTo("compUuid");
+ assertThat(deletedComponentIssues.getListList()).hasSize(1);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void fail_if_missing_metadata_file() throws Exception {
+ File dir = temp.newFolder();
+
+ BatchReportReader reader = new BatchReportReader(dir);
+ reader.readMetadata();
+ }
+ @Test(expected = IllegalStateException.class)
+ public void fail_if_missing_file_on_deleted_component() throws Exception {
+ File dir = temp.newFolder();
+
+ BatchReportReader reader = new BatchReportReader(dir);
+ reader.readDeletedComponentIssues(666);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void fail_if_missing_file_on_component() throws Exception {
+ File dir = temp.newFolder();
+
+ BatchReportReader reader = new BatchReportReader(dir);
+ reader.readComponent(666);
+ }
+
+ /**
+ * no file if no issues
+ */
+ @Test
+ public void ignore_missing_file_on_component_issues() throws Exception {
+ File dir = temp.newFolder();
+
+ BatchReportReader reader = new BatchReportReader(dir);
+ assertThat(reader.readComponentIssues(666)).isEmpty();
}
private void initFiles(File dir) {
- BatchOutputWriter writer = new BatchOutputWriter(dir);
+ BatchReportWriter writer = new BatchReportWriter(dir);
BatchReport.Metadata.Builder metadata = BatchReport.Metadata.newBuilder()
.setAnalysisDate(15000000L)
.setProjectKey("PROJECT_A")
- .setRootComponentRef(1);
+ .setRootComponentRef(1)
+ .setDeletedComponentsCount(1);
writer.writeMetadata(metadata.build());
BatchReport.Component.Builder component = BatchReport.Component.newBuilder()
@@ -68,10 +109,7 @@ public class BatchOutputReaderTest {
.build();
writer.writeComponentIssues(1, Arrays.asList(issue));
- }
-
- @Test
- public void readMetadata() throws Exception {
+ writer.writeDeletedComponentIssues(1, "compUuid", Arrays.asList(issue));
}
}
diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchOutputWriterTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportWriterTest.java
index ed1d4362048..a26ba76d58d 100644
--- a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchOutputWriterTest.java
+++ b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportWriterTest.java
@@ -31,7 +31,7 @@ import java.util.Arrays;
import static org.assertj.core.api.Assertions.assertThat;
-public class BatchOutputWriterTest {
+public class BatchReportWriterTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@@ -41,7 +41,7 @@ public class BatchOutputWriterTest {
File dir = temp.newFolder();
FileUtils.deleteQuietly(dir);
- new BatchOutputWriter(dir);
+ new BatchReportWriter(dir);
assertThat(dir).isDirectory().exists();
}
@@ -49,7 +49,7 @@ public class BatchOutputWriterTest {
@Test
public void write_metadata() throws Exception {
File dir = temp.newFolder();
- BatchOutputWriter writer = new BatchOutputWriter(dir);
+ BatchReportWriter writer = new BatchReportWriter(dir);
BatchReport.Metadata.Builder metadata = BatchReport.Metadata.newBuilder()
.setAnalysisDate(15000000L)
.setProjectKey("PROJECT_A")
@@ -65,7 +65,7 @@ public class BatchOutputWriterTest {
@Test
public void write_component() throws Exception {
File dir = temp.newFolder();
- BatchOutputWriter writer = new BatchOutputWriter(dir);
+ BatchReportWriter writer = new BatchReportWriter(dir);
// no data yet
assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 1)).isFalse();
@@ -96,7 +96,7 @@ public class BatchOutputWriterTest {
@Test
public void write_issues() throws Exception {
File dir = temp.newFolder();
- BatchOutputWriter writer = new BatchOutputWriter(dir);
+ BatchReportWriter writer = new BatchReportWriter(dir);
// no data yet
assertThat(writer.hasComponentData(FileStructure.Domain.ISSUES, 1)).isFalse();
@@ -115,6 +115,33 @@ public class BatchOutputWriterTest {
assertThat(file).exists().isFile();
BatchReport.Issues read = ProtobufUtil.readFile(file, BatchReport.Issues.PARSER);
assertThat(read.getComponentRef()).isEqualTo(1);
+ assertThat(read.hasComponentUuid()).isFalse();
+ assertThat(read.getListCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void write_issues_of_deleted_component() throws Exception {
+ File dir = temp.newFolder();
+ BatchReportWriter writer = new BatchReportWriter(dir);
+
+ // no data yet
+ assertThat(writer.hasComponentData(FileStructure.Domain.ISSUES_ON_DELETED, 1)).isFalse();
+
+ // write data
+ BatchReport.Issue issue = BatchReport.Issue.newBuilder()
+ .setUuid("ISSUE_A")
+ .setLine(50)
+ .setMsg("the message")
+ .build();
+
+ writer.writeDeletedComponentIssues(1, "componentUuid", Arrays.asList(issue));
+
+ assertThat(writer.hasComponentData(FileStructure.Domain.ISSUES_ON_DELETED, 1)).isTrue();
+ File file = writer.getFileStructure().fileFor(FileStructure.Domain.ISSUES_ON_DELETED, 1);
+ assertThat(file).exists().isFile();
+ BatchReport.Issues read = ProtobufUtil.readFile(file, BatchReport.Issues.PARSER);
+ assertThat(read.getComponentRef()).isEqualTo(1);
+ assertThat(read.getComponentUuid()).isEqualTo("componentUuid");
assertThat(read.getListCount()).isEqualTo(1);
}
}
diff --git a/sonar-batch/pom.xml b/sonar-batch/pom.xml
index 7d1559266c3..f199b70343a 100644
--- a/sonar-batch/pom.xml
+++ b/sonar-batch/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-batch</artifactId>
diff --git a/sonar-batch/src/main/java/org/sonar/batch/design/DsmDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/design/DsmDecorator.java
index 0fdae1a037b..8dafbe0cbd0 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/design/DsmDecorator.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/design/DsmDecorator.java
@@ -74,7 +74,6 @@ public abstract class DsmDecorator implements Decorator {
return;
}
Dsm<Resource> dsm = getDsm(children, feedbackEdges);
- // Optimization, don't save DSM if there is no dependency at all
saveDsm(context, dsm);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
index 0e2c128b185..0bec73c2c3e 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
@@ -188,11 +188,6 @@ public class DefaultIndex extends SonarIndex {
}
}
- // store dependencies
- for (Dependency dep : dependencies) {
- dependencyPersister.saveDependency(currentProject, dep);
- }
-
// Keep only inter module dependencies
Set<Dependency> projectDependencies = getDependenciesBetweenProjects();
dependencies.clear();
@@ -242,7 +237,7 @@ public class DefaultIndex extends SonarIndex {
if (metric == null) {
throw new SonarException("Unknown metric: " + measure.getMetricKey());
}
- if (!isTechnicalProjectCopy(resource) && !measure.isFromCore() && INTERNAL_METRICS.contains(metric)) {
+ if (!isViewResource(resource) && !measure.isFromCore() && INTERNAL_METRICS.contains(metric)) {
LOG.debug("Metric " + metric.key() + " is an internal metric computed by SonarQube. Provided value is ignored.");
return measure;
}
@@ -257,8 +252,9 @@ public class DefaultIndex extends SonarIndex {
/**
* Views plugin creates copy of technical projects and should be allowed to copy all measures even internal ones
*/
- private boolean isTechnicalProjectCopy(Resource resource) {
- return Scopes.FILE.equals(resource.getScope()) && Qualifiers.PROJECT.equals(resource.getQualifier());
+ private boolean isViewResource(Resource resource) {
+ boolean isTechnicalProject = Scopes.FILE.equals(resource.getScope()) && Qualifiers.PROJECT.equals(resource.getQualifier());
+ return isTechnicalProject || ResourceUtils.isView(resource) || ResourceUtils.isSubview(resource);
}
//
@@ -289,6 +285,7 @@ public class DefaultIndex extends SonarIndex {
addDependency(parentDependency);
}
registerDependency(dependency);
+ dependencyPersister.saveDependency(currentProject, dependency);
return dependency;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java b/sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java
index f804fc62efd..f0c1cfb1fbd 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java
@@ -24,6 +24,8 @@ import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.batch.index.Cache;
import org.sonar.batch.index.Caches;
+import java.util.Collection;
+
/**
* Shared issues among all project modules
*/
@@ -44,6 +46,10 @@ public class IssueCache implements BatchComponent {
return cache.values();
}
+ public Collection<Object> componentKeys() {
+ return cache.keySet();
+ }
+
public IssueCache put(DefaultIssue issue) {
cache.put(issue.componentKey(), issue.key(), issue);
return this;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/language/LanguageDistributionDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/language/LanguageDistributionDecorator.java
index cc246cfc793..ab9fb78b8ff 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/language/LanguageDistributionDecorator.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/language/LanguageDistributionDecorator.java
@@ -35,6 +35,8 @@ import org.sonar.api.resources.ResourceUtils;
public class LanguageDistributionDecorator implements Decorator {
+ private static final String UNKNOWN_LANGUAGE_KEY = "<null>";
+
@Override
public boolean shouldExecuteOnProject(Project project) {
return true;
@@ -56,8 +58,8 @@ public class LanguageDistributionDecorator implements Decorator {
if (ResourceUtils.isFile(resource)) {
Language language = resource.getLanguage();
Measure ncloc = context.getMeasure(CoreMetrics.NCLOC);
- if (language != null && ncloc != null) {
- nclocDistribution.add(language.getKey(), ncloc.getIntValue());
+ if (ncloc != null) {
+ nclocDistribution.add(language != null ? language.getKey() : UNKNOWN_LANGUAGE_KEY, ncloc.getIntValue());
}
} else {
for (Measure measure : context.getChildrenMeasures(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION)) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java
index 3604685d66f..d075a9a6300 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java
@@ -21,13 +21,12 @@ package org.sonar.batch.report;
import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
import org.sonar.batch.index.BatchResource;
import org.sonar.batch.index.ResourceCache;
import org.sonar.batch.protocol.Constants;
-import org.sonar.batch.protocol.output.BatchOutputWriter;
+import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.batch.protocol.output.BatchReport;
import javax.annotation.CheckForNull;
@@ -46,18 +45,12 @@ public class ComponentsPublisher implements ReportPublisher {
}
@Override
- public void publish(BatchOutputWriter writer) {
+ public void publish(BatchReportWriter writer) {
BatchResource rootProject = resourceCache.get(reactor.getRoot().getKeyWithBranch());
- BatchReport.Metadata metadata = BatchReport.Metadata.newBuilder()
- .setAnalysisDate(((Project) rootProject.resource()).getAnalysisDate().getTime())
- .setProjectKey(((Project) rootProject.resource()).key())
- .setRootComponentRef(rootProject.batchId())
- .build();
- writer.writeMetadata(metadata);
recursiveWriteComponent(rootProject, writer);
}
- private void recursiveWriteComponent(BatchResource batchResource, BatchOutputWriter writer) {
+ private void recursiveWriteComponent(BatchResource batchResource, BatchReportWriter writer) {
Resource r = batchResource.resource();
BatchReport.Component.Builder builder = BatchReport.Component.newBuilder();
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java
index 8be01240274..0cefc7d25db 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java
@@ -21,41 +21,87 @@ package org.sonar.batch.report;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.resources.Project;
import org.sonar.api.utils.KeyValueFormat;
import org.sonar.batch.index.BatchResource;
import org.sonar.batch.index.ResourceCache;
import org.sonar.batch.issue.IssueCache;
import org.sonar.batch.protocol.Constants;
-import org.sonar.batch.protocol.output.BatchOutputWriter;
+import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.batch.protocol.output.BatchReport;
import javax.annotation.Nullable;
+import java.util.Collection;
import java.util.Date;
+import java.util.Iterator;
public class IssuesPublisher implements ReportPublisher {
private final ResourceCache resourceCache;
private final IssueCache issueCache;
+ private final ProjectReactor reactor;
- public IssuesPublisher(ResourceCache resourceCache, IssueCache issueCache) {
+ public IssuesPublisher(ProjectReactor reactor, ResourceCache resourceCache, IssueCache issueCache) {
+ this.reactor = reactor;
this.resourceCache = resourceCache;
this.issueCache = issueCache;
}
@Override
- public void publish(BatchOutputWriter writer) {
+ public void publish(BatchReportWriter writer) {
+ Collection<Object> deletedComponentKeys = issueCache.componentKeys();
for (BatchResource resource : resourceCache.all()) {
- Iterable<DefaultIssue> issues = issueCache.byComponent(resource.resource().getEffectiveKey());
+ String componentKey = resource.resource().getEffectiveKey();
+ Iterable<DefaultIssue> issues = issueCache.byComponent(componentKey);
writer.writeComponentIssues(resource.batchId(), Iterables.transform(issues, new Function<DefaultIssue, BatchReport.Issue>() {
@Override
public BatchReport.Issue apply(DefaultIssue input) {
return toReportIssue(input);
}
}));
+ deletedComponentKeys.remove(componentKey);
}
+
+ int count = exportIssuesOfDeletedComponents(deletedComponentKeys, writer);
+
+ exportMetadata(writer, count);
+ }
+
+ private void exportMetadata(BatchReportWriter writer, int count) {
+ BatchResource rootProject = resourceCache.get(reactor.getRoot().getKeyWithBranch());
+ BatchReport.Metadata.Builder builder = BatchReport.Metadata.newBuilder()
+ .setAnalysisDate(((Project) rootProject.resource()).getAnalysisDate().getTime())
+ .setProjectKey(((Project) rootProject.resource()).key())
+ .setRootComponentRef(rootProject.batchId())
+ .setDeletedComponentsCount(count);
+ Integer sid = rootProject.snapshotId();
+ if (sid != null) {
+ builder.setSnapshotId(sid);
+ }
+ writer.writeMetadata(builder.build());
+ }
+
+ private int exportIssuesOfDeletedComponents(Collection<Object> deletedComponentKeys, BatchReportWriter writer) {
+ int deletedComponentCount = 0;
+ for (Object componentKey : deletedComponentKeys) {
+ deletedComponentCount++;
+ Iterable<DefaultIssue> issues = issueCache.byComponent(componentKey.toString());
+ Iterator<DefaultIssue> iterator = issues.iterator();
+ if (iterator.hasNext()) {
+ String componentUuid = iterator.next().componentUuid();
+ writer.writeDeletedComponentIssues(deletedComponentCount, componentUuid, Iterables.transform(issues, new Function<DefaultIssue, BatchReport.Issue>() {
+ @Override
+ public BatchReport.Issue apply(DefaultIssue input) {
+ return toReportIssue(input);
+ }
+ }));
+ }
+ }
+ return deletedComponentCount;
}
private BatchReport.Issue toReportIssue(DefaultIssue issue) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java b/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java
index 17a8c7e4c32..3a70259bede 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java
@@ -33,8 +33,7 @@ import org.sonar.api.utils.TempFolder;
import org.sonar.api.utils.ZipUtils;
import org.sonar.batch.bootstrap.DefaultAnalysisMode;
import org.sonar.batch.bootstrap.ServerClient;
-import org.sonar.batch.index.ResourceCache;
-import org.sonar.batch.protocol.output.BatchOutputWriter;
+import org.sonar.batch.protocol.output.BatchReportWriter;
import java.io.File;
import java.io.IOException;
@@ -50,26 +49,24 @@ public class PublishReportJob implements BatchComponent {
private final Settings settings;
private final Project project;
private final DefaultAnalysisMode analysisMode;
- private final ResourceCache resourceCache;
private final TempFolder temp;
private ReportPublisher[] publishers;
public PublishReportJob(Settings settings, ServerClient serverClient, Server server,
- Project project, DefaultAnalysisMode analysisMode, TempFolder temp, ResourceCache resourceCache, ReportPublisher[] publishers) {
+ Project project, DefaultAnalysisMode analysisMode, TempFolder temp, ReportPublisher[] publishers) {
this.serverClient = serverClient;
this.server = server;
this.project = project;
this.settings = settings;
this.analysisMode = analysisMode;
this.temp = temp;
- this.resourceCache = resourceCache;
this.publishers = publishers;
}
public PublishReportJob(Settings settings, ServerClient serverClient, Server server,
- Project project, DefaultAnalysisMode analysisMode, TempFolder temp, ResourceCache resourceCache) {
- this(settings, serverClient, server, project, analysisMode, temp, resourceCache, new ReportPublisher[0]);
+ Project project, DefaultAnalysisMode analysisMode, TempFolder temp) {
+ this(settings, serverClient, server, project, analysisMode, temp, new ReportPublisher[0]);
}
public void execute() {
@@ -87,7 +84,7 @@ public class PublishReportJob implements BatchComponent {
try {
long startTime = System.currentTimeMillis();
File reportDir = temp.newDir("batch-report");
- BatchOutputWriter writer = new BatchOutputWriter(reportDir);
+ BatchReportWriter writer = new BatchReportWriter(reportDir);
for (ReportPublisher publisher : publishers) {
publisher.publish(writer);
}
@@ -112,8 +109,7 @@ public class PublishReportJob implements BatchComponent {
long startTime = System.currentTimeMillis();
URL url;
try {
- int snapshotId = resourceCache.get(project.getEffectiveKey()).snapshotId();
- url = new URL(serverClient.getURL() + "/api/computation/submit_report?projectKey=" + project.getEffectiveKey() + "&snapshot=" + snapshotId);
+ url = new URL(serverClient.getURL() + "/api/computation/submit_report?projectKey=" + project.getEffectiveKey());
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Invalid URL", e);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java
index 6fe18f50889..07aa03fccbe 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java
@@ -19,13 +19,13 @@
*/
package org.sonar.batch.report;
-import org.sonar.batch.protocol.output.BatchOutputWriter;
+import org.sonar.batch.protocol.output.BatchReportWriter;
/**
* Adds a sub-part of data to output report
*/
public interface ReportPublisher {
- void publish(BatchOutputWriter writer);
+ void publish(BatchReportWriter writer);
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/language/LanguageDistributionDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/language/LanguageDistributionDecoratorTest.java
index cb9d52bae9e..155b9cd4910 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/language/LanguageDistributionDecoratorTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/language/LanguageDistributionDecoratorTest.java
@@ -93,6 +93,21 @@ public class LanguageDistributionDecoratorTest {
}
@Test
+ public void save_ncloc_language_distribution_on_file_without_language() {
+
+ when(resource.getScope()).thenReturn(Scopes.FILE);
+ when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 200.0));
+
+ decorator.decorate(resource, context);
+
+ verify(context).saveMeasure(measureCaptor.capture());
+
+ Measure result = measureCaptor.getValue();
+ assertThat(result.getMetric()).isEqualTo(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION);
+ assertThat(result.getData()).isEqualTo("<null>=200");
+ }
+
+ @Test
public void save_ncloc_language_distribution_on_project() {
when(resource.getScope()).thenReturn(Scopes.PROJECT);
when(context.getChildrenMeasures(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION)).thenReturn(newArrayList(
diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java
index 30f56d3a46e..5bcc75aa6db 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java
@@ -30,7 +30,7 @@ import org.sonar.api.resources.Java;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.DateUtils;
import org.sonar.batch.index.ResourceCache;
-import org.sonar.batch.protocol.output.BatchOutputWriter;
+import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.batch.protocol.output.FileStructure;
import static org.assertj.core.api.Assertions.assertThat;
@@ -77,7 +77,7 @@ public class ComponentsPublisherTest {
testFile.setId(6).setUuid("TEST_FILE_UUID");
resourceCache.add(testFile, dir).setSnapshot(new Snapshot().setId(16));
- BatchOutputWriter writer = new BatchOutputWriter(temp.newFolder());
+ BatchReportWriter writer = new BatchReportWriter(temp.newFolder());
publisher.publish(writer);
assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 1)).isTrue();
diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/IssuesPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/IssuesPublisherTest.java
new file mode 100644
index 00000000000..9a020765298
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/report/IssuesPublisherTest.java
@@ -0,0 +1,166 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.report;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.resources.Project;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.Duration;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.issue.IssueCache;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+import org.sonar.batch.protocol.output.BatchReport.Metadata;
+import org.sonar.batch.protocol.output.BatchReportReader;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class IssuesPublisherTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ private IssueCache issueCache;
+ private IssuesPublisher publisher;
+
+ @Before
+ public void prepare() {
+ ProjectDefinition root = ProjectDefinition.create().setKey("foo");
+ Project p = new Project("foo").setAnalysisDate(new Date(1234567L));
+ ResourceCache resourceCache = new ResourceCache();
+ org.sonar.api.resources.Resource sampleFile = org.sonar.api.resources.File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php");
+ resourceCache.add(p, null).setSnapshot(new Snapshot().setId(2));
+ resourceCache.add(sampleFile, null);
+ issueCache = mock(IssueCache.class);
+ when(issueCache.byComponent(anyString())).thenReturn(Collections.<DefaultIssue>emptyList());
+ publisher = new IssuesPublisher(new ProjectReactor(root), resourceCache, issueCache);
+ }
+
+ @Test
+ public void publishIssuesAndMetadata() throws Exception {
+
+ DefaultIssue issue1 = new DefaultIssue();
+ issue1.setKey("uuid");
+ issue1.setSeverity("MAJOR");
+ issue1.setRuleKey(RuleKey.of("repo", "rule"));
+ DefaultIssue issue2 = new DefaultIssue();
+ issue2.setKey("uuid2");
+ issue2.setSeverity("MAJOR");
+ issue2.setRuleKey(RuleKey.of("repo", "rule"));
+ issue2.setLine(2);
+ issue2.setMessage("msg");
+ issue2.setEffortToFix(2d);
+ issue2.setDebt(Duration.create(2));
+ issue2.setResolution("FIXED");
+ issue2.setStatus("RESOLVED");
+ issue2.setChecksum("checksum");
+ issue2.setReporter("reporter");
+ issue2.setAssignee("assignee");
+ issue2.setActionPlanKey("action");
+ issue2.setAuthorLogin("author");
+ issue2.setCurrentChange(new FieldDiffs().setUserLogin("foo"));
+ issue2.setCreationDate(new Date());
+ issue2.setUpdateDate(new Date());
+ issue2.setCloseDate(new Date());
+ issue2.setSelectedAt(1234L);
+ when(issueCache.byComponent("foo:src/Foo.php")).thenReturn(Arrays.asList(issue1, issue2));
+
+ File outputDir = temp.newFolder();
+ BatchReportWriter writer = new BatchReportWriter(outputDir);
+
+ publisher.publish(writer);
+
+ BatchReportReader reader = new BatchReportReader(outputDir);
+ Metadata metadata = reader.readMetadata();
+ assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L);
+ assertThat(metadata.getProjectKey()).isEqualTo("foo");
+ assertThat(metadata.getDeletedComponentsCount()).isEqualTo(0);
+ assertThat(metadata.getSnapshotId()).isEqualTo(2);
+
+ assertThat(reader.readComponentIssues(1)).hasSize(0);
+ assertThat(reader.readComponentIssues(2)).hasSize(2);
+
+ }
+
+ @Test
+ public void publishIssuesOfDeletedComponents() throws Exception {
+
+ DefaultIssue issue1 = new DefaultIssue();
+ issue1.setKey("uuid");
+ issue1.setComponentUuid("deletedUuid");
+ issue1.setSeverity("MAJOR");
+ issue1.setRuleKey(RuleKey.of("repo", "rule"));
+ DefaultIssue issue2 = new DefaultIssue();
+ issue2.setKey("uuid2");
+ issue2.setComponentUuid("deletedUuid");
+ issue2.setSeverity("MAJOR");
+ issue2.setRuleKey(RuleKey.of("repo", "rule"));
+ issue2.setLine(2);
+ issue2.setMessage("msg");
+ issue2.setEffortToFix(2d);
+ issue2.setDebt(Duration.create(2));
+ issue2.setResolution("FIXED");
+ issue2.setStatus("RESOLVED");
+ issue2.setChecksum("checksum");
+ issue2.setReporter("reporter");
+ issue2.setAssignee("assignee");
+ issue2.setActionPlanKey("action");
+ issue2.setAuthorLogin("author");
+ issue2.setCurrentChange(new FieldDiffs().setUserLogin("foo"));
+ issue2.setCreationDate(new Date());
+ issue2.setUpdateDate(new Date());
+ issue2.setCloseDate(new Date());
+ issue2.setSelectedAt(1234L);
+
+ when(issueCache.byComponent("foo:deleted.php")).thenReturn(Arrays.asList(issue1, issue2));
+
+ when(issueCache.componentKeys()).thenReturn(Arrays.<Object>asList("foo:deleted.php"));
+
+ File outputDir = temp.newFolder();
+ BatchReportWriter writer = new BatchReportWriter(outputDir);
+
+ publisher.publish(writer);
+
+ BatchReportReader reader = new BatchReportReader(outputDir);
+ Metadata metadata = reader.readMetadata();
+ assertThat(metadata.getDeletedComponentsCount()).isEqualTo(1);
+
+ assertThat(reader.readComponentIssues(1)).hasSize(0);
+ assertThat(reader.readComponentIssues(2)).hasSize(0);
+ assertThat(reader.readDeletedComponentIssues(1).getComponentUuid()).isEqualTo("deletedUuid");
+ assertThat(reader.readDeletedComponentIssues(1).getListList()).hasSize(2);
+
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java
index 924f05d25f2..2da52bd2f3d 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java
@@ -32,9 +32,7 @@ import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.batch.index.ResourceCache;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
public class PublishReportJobTest extends AbstractDbUnitTestCase {
@@ -52,7 +50,7 @@ public class PublishReportJobTest extends AbstractDbUnitTestCase {
Settings settings = new Settings();
settings.setProperty(CoreProperties.SERVER_BASE_URL, "http://myserver/");
Project project = new Project("struts");
- PublishReportJob job = new PublishReportJob(settings, mock(ServerClient.class), mock(Server.class), project, mode, mock(TempFolder.class), mock(ResourceCache.class));
+ PublishReportJob job = new PublishReportJob(settings, mock(ServerClient.class), mock(Server.class), project, mode, mock(TempFolder.class));
Logger logger = mock(Logger.class);
job.logSuccess(logger);
@@ -66,7 +64,7 @@ public class PublishReportJobTest extends AbstractDbUnitTestCase {
Settings settings = new Settings();
when(mode.isPreview()).thenReturn(true);
Project project = new Project("struts");
- PublishReportJob job = new PublishReportJob(settings, mock(ServerClient.class), mock(Server.class), project, mode, mock(TempFolder.class), mock(ResourceCache.class));
+ PublishReportJob job = new PublishReportJob(settings, mock(ServerClient.class), mock(Server.class), project, mode, mock(TempFolder.class));
Logger logger = mock(Logger.class);
job.logSuccess(logger);
diff --git a/sonar-check-api/pom.xml b/sonar-check-api/pom.xml
index 8fa9d2d9b62..af8aae840d0 100644
--- a/sonar-check-api/pom.xml
+++ b/sonar-check-api/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>sonar-check-api</artifactId>
diff --git a/sonar-colorizer/pom.xml b/sonar-colorizer/pom.xml
index e5ced4532a2..19ff87b1503 100644
--- a/sonar-colorizer/pom.xml
+++ b/sonar-colorizer/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
diff --git a/sonar-core/pom.xml b/sonar-core/pom.xml
index 3682bc1fb64..98cc5cb0017 100644
--- a/sonar-core/pom.xml
+++ b/sonar-core/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-core</artifactId>
diff --git a/sonar-core/src/main/java/org/sonar/core/activity/db/ActivityDto.java b/sonar-core/src/main/java/org/sonar/core/activity/db/ActivityDto.java
index 517f0e998a7..81454b05421 100644
--- a/sonar-core/src/main/java/org/sonar/core/activity/db/ActivityDto.java
+++ b/sonar-core/src/main/java/org/sonar/core/activity/db/ActivityDto.java
@@ -21,44 +21,44 @@ package org.sonar.core.activity.db;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
-import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.api.utils.internal.Uuids;
-import org.sonar.core.activity.Activity;
-import org.sonar.core.activity.ActivityLog;
-import org.sonar.core.persistence.Dto;
-
-/**
- * @since 4.4
- */
-public final class ActivityDto extends Dto<String> {
+
+import javax.annotation.Nullable;
+
+import java.util.Date;
+
+public class ActivityDto {
private String key;
private String message;
- private Activity.Type type;
+ private String type;
private String action;
private String author;
-
private String data;
+ private Date createdAt;
- protected ActivityDto() {
- this.key = Uuids.create();
+ public ActivityDto setKey(String key) {
+ this.key = key;
+ return this;
}
- @Override
public String getKey() {
return key;
}
- @Override
- public String toString() {
- return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
+ public Date getCreatedAt() {
+ return createdAt;
}
- public Activity.Type getType() {
+ public ActivityDto setCreatedAt(Date createdAt) {
+ this.createdAt = createdAt;
+ return this;
+ }
+
+ public String getType() {
return type;
}
- public ActivityDto setType(Activity.Type type) {
+ public ActivityDto setType(String type) {
this.type = type;
return this;
}
@@ -67,7 +67,7 @@ public final class ActivityDto extends Dto<String> {
return author;
}
- public ActivityDto setAuthor(String author) {
+ public ActivityDto setAuthor(@Nullable String author) {
this.author = author;
return this;
}
@@ -85,7 +85,7 @@ public final class ActivityDto extends Dto<String> {
return message;
}
- public ActivityDto setMessage(String message) {
+ public ActivityDto setMessage(@Nullable String message) {
this.message = message;
return this;
}
@@ -99,21 +99,8 @@ public final class ActivityDto extends Dto<String> {
return this;
}
- public static ActivityDto createFor(String message) {
- return new ActivityDto()
- .setMessage(message);
- }
-
- public static ActivityDto createFor(String action, String message) {
- return new ActivityDto()
- .setAction(action)
- .setMessage(message);
- }
-
- public static ActivityDto createFor(ActivityLog activityLog) {
- return new ActivityDto()
- .setAction(activityLog.getAction())
- .setData(KeyValueFormat.format(activityLog.getDetails()));
-
+ @Override
+ public String toString() {
+ return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}
diff --git a/sonar-core/src/main/java/org/sonar/core/activity/db/ActivityMapper.java b/sonar-core/src/main/java/org/sonar/core/activity/db/ActivityMapper.java
index d7f5959c422..175bef8bc30 100644
--- a/sonar-core/src/main/java/org/sonar/core/activity/db/ActivityMapper.java
+++ b/sonar-core/src/main/java/org/sonar/core/activity/db/ActivityMapper.java
@@ -19,21 +19,8 @@
*/
package org.sonar.core.activity.db;
-import org.apache.ibatis.annotations.Param;
-
-import javax.annotation.Nullable;
-
-import java.sql.Timestamp;
-import java.util.List;
-
-/**
- * @since 4.4
- */
public interface ActivityMapper {
- void insert(ActivityDto rule);
-
- List<ActivityDto> selectAll();
+ void insert(ActivityDto dto);
- List<ActivityDto> selectAfterDate(@Nullable @Param("date") Timestamp timestamp);
}
diff --git a/sonar-core/src/main/java/org/sonar/core/activity/package-info.java b/sonar-core/src/main/java/org/sonar/core/activity/package-info.java
deleted file mode 100644
index 8c6baa92aa2..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/activity/package-info.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-@ParametersAreNonnullByDefault
-package org.sonar.core.activity;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-core/src/main/java/org/sonar/core/component/ComponentDto.java b/sonar-core/src/main/java/org/sonar/core/component/ComponentDto.java
index fe72cc88037..b528ac47aec 100644
--- a/sonar-core/src/main/java/org/sonar/core/component/ComponentDto.java
+++ b/sonar-core/src/main/java/org/sonar/core/component/ComponentDto.java
@@ -19,6 +19,7 @@
*/
package org.sonar.core.component;
+import org.apache.commons.lang.builder.ToStringBuilder;
import org.sonar.api.component.Component;
import org.sonar.api.resources.Scopes;
import org.sonar.core.persistence.Dto;
@@ -238,6 +239,7 @@ public class ComponentDto extends Dto<String> implements Component {
return moduleUuid == null && Scopes.PROJECT.equals(scope);
}
+ // FIXME equals/hashCode mean nothing on DTOs, especially when on id
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -246,19 +248,40 @@ public class ComponentDto extends Dto<String> implements Component {
if (o == null || getClass() != o.getClass()) {
return false;
}
-
ComponentDto that = (ComponentDto) o;
-
- if (!id.equals(that.id)) {
+ if (id != null ? !id.equals(that.id) : that.id != null) {
return false;
}
-
return true;
}
+ // FIXME equals/hashCode mean nothing on DTOs, especially when on id
@Override
public int hashCode() {
- return id.hashCode();
+ return id != null ? id.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("id", id)
+ .append("uuid", uuid)
+ .append("kee", kee)
+ .append("scope", scope)
+ .append("qualifier", qualifier)
+ .append("projectUuid", projectUuid)
+ .append("moduleUuid", moduleUuid)
+ .append("moduleUuidPath", moduleUuidPath)
+ .append("parentProjectId", parentProjectId)
+ .append("copyResourceId", copyResourceId)
+ .append("path", path)
+ .append("deprecatedKey", deprecatedKey)
+ .append("name", name)
+ .append("longName", longName)
+ .append("language", language)
+ .append("enabled", enabled)
+ .append("authorizationUpdatedAt", authorizationUpdatedAt)
+ .toString();
}
@Override
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportDto.java b/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportDto.java
index 4987652b89d..d5cfc718ccf 100644
--- a/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportDto.java
+++ b/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportDto.java
@@ -23,16 +23,12 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import java.io.InputStream;
public class AnalysisReportDto {
private Long id;
private String projectKey;
private Status status;
- private InputStream data;
- private Long snapshotId;
+ private String uuid;
private Long createdAt;
private Long updatedAt;
private Long startedAt;
@@ -76,19 +72,15 @@ public class AnalysisReportDto {
this.status = Status.SUCCESS;
}
- public InputStream getData() {
- return data;
+ public String getUuid() {
+ return uuid;
}
- public AnalysisReportDto setData(@Nullable InputStream data) {
- this.data = data;
+ public AnalysisReportDto setUuid(String s) {
+ this.uuid = s;
return this;
}
- public String getKey() {
- return String.valueOf(getId());
- }
-
public Long getId() {
return id;
}
@@ -98,7 +90,7 @@ public class AnalysisReportDto {
return Objects.toStringHelper(this)
.add("id", getId())
.add("projectKey", getProjectKey())
- .add("snapshotId", getSnapshotId())
+ .add("uuid", getUuid())
.add("status", getStatus())
.add("createdAt", getCreatedAt())
.add("startedAt", getStartedAt())
@@ -106,15 +98,6 @@ public class AnalysisReportDto {
.toString();
}
- public Long getSnapshotId() {
- return snapshotId;
- }
-
- public AnalysisReportDto setSnapshotId(Long snapshotId) {
- this.snapshotId = snapshotId;
- return this;
- }
-
@CheckForNull
public Long getStartedAt() {
return startedAt;
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportMapper.java b/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportMapper.java
index 223eacbe69e..f9995986a24 100644
--- a/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportMapper.java
+++ b/sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportMapper.java
@@ -34,6 +34,8 @@ public interface AnalysisReportMapper {
void truncate();
+ void insert(AnalysisReportDto reportDto);
+
int update(AnalysisReportDto report);
int updateWithBookingReport(@Param("id") Long id, @Param("startedAt") long startedAt,
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleaner.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleaner.java
index e87214d4e0e..5b003323855 100644
--- a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleaner.java
+++ b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleaner.java
@@ -21,12 +21,12 @@
package org.sonar.core.computation.dbcleaner.period;
import com.google.common.annotations.VisibleForTesting;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.sonar.api.ServerExtension;
import org.sonar.api.config.Settings;
import org.sonar.api.task.TaskExtension;
import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.core.purge.PurgeDao;
@@ -37,7 +37,7 @@ import java.util.List;
public class DefaultPeriodCleaner implements TaskExtension, ServerExtension {
- private static final Logger LOG = LoggerFactory.getLogger(DefaultPeriodCleaner.class);
+ private static final Logger LOG = Loggers.get(DefaultPeriodCleaner.class);
private PurgeDao purgeDao;
private Settings settings;
private MyBatis mybatis;
@@ -76,7 +76,7 @@ public class DefaultPeriodCleaner implements TaskExtension, ServerExtension {
private void delete(List<PurgeableSnapshotDto> snapshots, DbSession session) {
for (PurgeableSnapshotDto snapshot : snapshots) {
- LOG.info("<- Delete snapshot: " + DateUtils.formatDateTime(snapshot.getDate()) + " [" + snapshot.getSnapshotId() + "]");
+ LOG.debug("<- Delete snapshot: {} [{}]", DateUtils.formatDateTime(snapshot.getDate()), snapshot.getSnapshotId());
purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setRootSnapshotId(snapshot.getSnapshotId()), session);
purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setId(snapshot.getSnapshotId()), session);
}
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DeleteAllFilter.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DeleteAllFilter.java
index 25dcb409ea1..0b6d34cbfb9 100644
--- a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DeleteAllFilter.java
+++ b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DeleteAllFilter.java
@@ -21,8 +21,8 @@
package org.sonar.core.computation.dbcleaner.period;
import com.google.common.collect.Lists;
-import org.slf4j.LoggerFactory;
import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.core.purge.PurgeableSnapshotDto;
import java.util.Date;
@@ -48,6 +48,6 @@ class DeleteAllFilter implements Filter {
@Override
public void log() {
- LoggerFactory.getLogger(getClass()).info("-> Delete data prior to: " + DateUtils.formatDate(before));
+ Loggers.get(getClass()).debug("-> Delete data prior to: {}", DateUtils.formatDate(before));
}
}
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/KeepOneFilter.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/KeepOneFilter.java
index 419add8383f..b1087066243 100644
--- a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/KeepOneFilter.java
+++ b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/KeepOneFilter.java
@@ -22,8 +22,8 @@ package org.sonar.core.computation.dbcleaner.period;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
-import org.slf4j.LoggerFactory;
import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.core.purge.PurgeableSnapshotDto;
import java.util.Date;
@@ -56,7 +56,7 @@ class KeepOneFilter implements Filter {
@Override
public void log() {
- LoggerFactory.getLogger(getClass()).info("-> Keep one snapshot per " + label + " between " + DateUtils.formatDate(start) + " and " + DateUtils.formatDate(end));
+ Loggers.get(getClass()).debug("-> Keep one snapshot per {} between {} and {}", label, DateUtils.formatDate(start), DateUtils.formatDate(end));
}
private void appendSnapshotsToDelete(Interval interval, List<PurgeableSnapshotDto> toDelete) {
diff --git a/sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java b/sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java
index 97977cd2162..3d635b3f207 100644
--- a/sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java
+++ b/sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java
@@ -60,6 +60,16 @@ public class CorePropertyDefinitions {
.subCategory(CoreProperties.SUBCATEGORY_LOOKNFEEL)
.build(),
+ // ISSUES
+ PropertyDefinition.builder(CoreProperties.DEFAULT_ISSUE_ASSIGNEE)
+ .name("Default Assignee")
+ .description("Login assigned to a new issue if an assignee has not been found.")
+ .category(CoreProperties.CATEGORY_GENERAL)
+ .subCategory(CoreProperties.SUBCATEGORY_ISSUES)
+ .onQualifiers(Qualifiers.PROJECT)
+ .type(PropertyType.USER_LOGIN)
+ .build(),
+
// BATCH
PropertyDefinition.builder(CoreProperties.CORE_VIOLATION_LOCALE_PROPERTY)
@@ -153,7 +163,7 @@ public class CorePropertyDefinitions {
.subCategory(CoreProperties.SUBCATEGORY_DUPLICATIONS_EXCLUSIONS)
.multiValues(true)
.build()
- ));
+ ));
return defs;
}
}
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
index 0ab6f186cd4..48459ea8fc6 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
@@ -33,7 +33,7 @@ import java.util.List;
*/
public class DatabaseVersion implements BatchComponent, ServerComponent {
- public static final int LAST_VERSION = 795;
+ public static final int LAST_VERSION = 796;
/**
* List of all the tables.n
diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java
index 6af3a526fcd..a294dce2a6b 100644
--- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java
+++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java
@@ -32,7 +32,11 @@ import org.sonar.core.persistence.MyBatis;
import org.sonar.core.resource.ResourceDao;
import org.sonar.core.resource.ResourceDto;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
import static org.sonar.api.utils.DateUtils.dateToLong;
@@ -69,7 +73,7 @@ public class PurgeDao {
PurgeCommands commands = new PurgeCommands(session, mapper, profiler);
List<ResourceDto> projects = getProjects(conf.rootProjectIdUuid().getId(), session);
for (ResourceDto project : projects) {
- LOG.info("-> Clean " + project.getLongName() + " [id=" + project.getId() + "]");
+ LOG.debug("-> Clean " + project.getLongName() + " [id=" + project.getId() + "]");
deleteAbortedBuilds(project, commands);
purge(project, conf.scopesWithoutHistoricalData(), commands);
}
@@ -87,7 +91,7 @@ public class PurgeDao {
private void deleteAbortedBuilds(ResourceDto project, PurgeCommands commands) {
if (hasAbortedBuilds(project.getId(), commands)) {
- LOG.info("<- Delete aborted builds");
+ LOG.debug("<- Delete aborted builds");
PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
.setIslast(false)
.setStatus(new String[] {"U"})
@@ -112,7 +116,7 @@ public class PurgeDao {
.setNotPurged(true)
);
for (final Long projectSnapshotId : projectSnapshotIds) {
- LOG.info("<- Clean snapshot " + projectSnapshotId);
+ LOG.debug("<- Clean snapshot " + projectSnapshotId);
if (!ArrayUtils.isEmpty(scopesWithoutHistoricalData)) {
PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
.setIslast(false)
diff --git a/sonar-core/src/main/java/org/sonar/core/user/UserDao.java b/sonar-core/src/main/java/org/sonar/core/user/UserDao.java
index 0cff129eb8a..97f7e6a26cd 100644
--- a/sonar-core/src/main/java/org/sonar/core/user/UserDao.java
+++ b/sonar-core/src/main/java/org/sonar/core/user/UserDao.java
@@ -68,20 +68,21 @@ public class UserDao implements BatchComponent, ServerComponent, DaoComponent {
public UserDto selectActiveUserByLogin(String login) {
DbSession session = mybatis.openSession(false);
try {
- return selectActiveUserByLogin(login, session);
+ return selectActiveUserByLogin(session, login);
} finally {
MyBatis.closeQuietly(session);
}
}
- public UserDto selectActiveUserByLogin(String login, DbSession session) {
+ @CheckForNull
+ public UserDto selectActiveUserByLogin(DbSession session, String login) {
UserMapper mapper = session.getMapper(UserMapper.class);
return mapper.selectUserByLogin(login);
}
public List<UserDto> selectUsersByLogins(List<String> logins) {
List<UserDto> users = Lists.newArrayList();
- SqlSession session = mybatis.openSession(false);
+ DbSession session = mybatis.openSession(false);
try {
users.addAll(selectUsersByLogins(session, logins));
} finally {
@@ -90,7 +91,7 @@ public class UserDao implements BatchComponent, ServerComponent, DaoComponent {
return users;
}
- public List<UserDto> selectUsersByLogins(SqlSession session, List<String> logins) {
+ public List<UserDto> selectUsersByLogins(DbSession session, List<String> logins) {
List<UserDto> users = Lists.newArrayList();
if (!logins.isEmpty()) {
UserMapper mapper = session.getMapper(UserMapper.class);
diff --git a/sonar-core/src/main/java/org/sonar/core/util/MultiSets.java b/sonar-core/src/main/java/org/sonar/core/util/MultiSets.java
new file mode 100644
index 00000000000..05c93b572b2
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/util/MultiSets.java
@@ -0,0 +1,62 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.core.util;
+
+import com.google.common.collect.Multiset;
+import com.google.common.collect.Ordering;
+import com.google.common.primitives.Ints;
+
+import java.util.List;
+
+/**
+ * Utility class heavily inspired by Guava
+ */
+public class MultiSets {
+
+ private static final Ordering<Multiset.Entry<?>> DECREASING_COUNT_ORDERING = new NonNullOrdering<Multiset.Entry<?>>() {
+ @Override
+ public int doCompare(Multiset.Entry<?> entry1, Multiset.Entry<?> entry2) {
+ return Ints.compare(entry2.getCount(), entry1.getCount());
+ }
+ };
+
+ private MultiSets() {
+
+ }
+
+ /**
+ * Returns a copy of {@code multiset} as a {@link List} whose iteration order is
+ * highest count first, with ties broken by the iteration order of the original multiset.
+ */
+ public static <E> List<Multiset.Entry<E>> listOrderedByHighestCounts(Multiset<E> multiset) {
+ return DECREASING_COUNT_ORDERING.sortedCopy(multiset.entrySet());
+ }
+
+ private abstract static class NonNullOrdering<T> extends Ordering<T> {
+
+ @Override
+ public int compare(T left, T right) {
+ return doCompare(left, right);
+ }
+
+ public abstract int doCompare(T left, T right);
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/util/NonNullInputFunction.java b/sonar-core/src/main/java/org/sonar/core/util/NonNullInputFunction.java
index a99652beb58..9ec5fbb4ec2 100644
--- a/sonar-core/src/main/java/org/sonar/core/util/NonNullInputFunction.java
+++ b/sonar-core/src/main/java/org/sonar/core/util/NonNullInputFunction.java
@@ -20,10 +20,11 @@
package org.sonar.core.util;
import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
import javax.annotation.Nullable;
+import static com.google.common.base.Preconditions.checkArgument;
+
/**
* Guava Function that does not accept null input elements
* @since 5.1
@@ -32,7 +33,7 @@ public abstract class NonNullInputFunction<F,T> implements Function<F, T> {
@Override
public final T apply(@Nullable F input) {
- Preconditions.checkArgument(input != null, "Null inputs are not allowed in this function");
+ checkArgument(input != null, "Null inputs are not allowed in this function");
return doApply(input);
}
diff --git a/sonar-core/src/main/resources/org/sonar/core/activity/db/ActivityMapper.xml b/sonar-core/src/main/resources/org/sonar/core/activity/db/ActivityMapper.xml
index fecd0b0210f..c3de19773b6 100644
--- a/sonar-core/src/main/resources/org/sonar/core/activity/db/ActivityMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/activity/db/ActivityMapper.xml
@@ -3,40 +3,13 @@
<mapper namespace="org.sonar.core.activity.db.ActivityMapper">
- <insert id="insert" parameterType="Activity" useGeneratedKeys="false" >
+ <insert id="insert" parameterType="Activity" useGeneratedKeys="false">
insert into activities
(created_at, log_key, log_type, log_action, user_login, data_field, log_message)
- values (#{createdAt}, #{key}, #{type}, #{action}, #{author}, #{data}, #{message})
+ values (#{createdAt,jdbcType=TIMESTAMP}, #{key,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR},
+ #{action,jdbcType=VARCHAR},
+ #{author,jdbcType=VARCHAR}, #{data,jdbcType=VARCHAR}, #{message,jdbcType=VARCHAR})
</insert>
- <select id="selectAll" parameterType="map" resultType="Activity" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
- SELECT
- created_at as "createdAt",
- log_type as "type",
- user_login as "author",
- data_field as "data",
- log_message as "message",
- log_key as "key",
- log_action as "action"
- FROM activities
- </select>
-
-
- <select id="selectAfterDate" parameterType="map" resultType="Activity" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
- SELECT
- created_at as "createdAt",
- log_type as "type",
- user_login as "author",
- data_field as "data",
- log_message as "message",
- log_key as "key",
- log_action as "action"
- FROM activities
- <where>
- <if test="date != null">
- created_at &gt;= #{date}
- </if>
- </where>
- </select>
</mapper>
diff --git a/sonar-core/src/main/resources/org/sonar/core/computation/db/AnalysisReportMapper.xml b/sonar-core/src/main/resources/org/sonar/core/computation/db/AnalysisReportMapper.xml
index bcaf5eea10e..7e37e574d99 100644
--- a/sonar-core/src/main/resources/org/sonar/core/computation/db/AnalysisReportMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/computation/db/AnalysisReportMapper.xml
@@ -7,22 +7,32 @@
ar.id,
ar.project_key as projectKey,
ar.report_status as status,
- ar.snapshot_id as snapshotId,
+ ar.uuid as uuid,
ar.created_at as createdAt,
ar.updated_at as updatedAt,
ar.started_at as startedAt,
ar.finished_at as finishedAt
</sql>
+ <insert id="insert" parameterType="AnalysisReport" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+ insert into analysis_reports
+ (project_key, uuid, report_status, created_at, updated_at, started_at, finished_at)
+ values (
+ #{projectKey,jdbcType=VARCHAR}, #{uuid,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
+ #{createdAt,jdbcType=BIGINT}, #{updatedAt,jdbcType=BIGINT}, #{startedAt,jdbcType=BIGINT},
+ #{finishedAt,jdbcType=BIGINT}
+ )
+ </insert>
+
<update id="resetAllToPendingStatus" parameterType="map">
update analysis_reports
- set report_status='PENDING', updated_at=#{updatedAt}, started_at=NULL
+ set report_status='PENDING', updated_at=#{updatedAt,jdbcType=BIGINT}, started_at=NULL
</update>
<update id="updateWithBookingReport" parameterType="map">
update analysis_reports
- set report_status=#{busyStatus},
- started_at=#{startedAt}
+ set report_status=#{busyStatus,jdbcType=VARCHAR},
+ started_at=#{startedAt,jdbcType=BIGINT}
where id=#{id} and report_status=#{availableStatus}
</update>
@@ -59,7 +69,7 @@
where ar.project_key = ar2.project_key
and ar2.report_status=#{busyStatus}
)
- order by created_at asc
+ order by ar.created_at asc, ar.id asc
</select>
<select id="selectAll" resultType="AnalysisReport">
diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
index c8a2417dba7..a410243e678 100644
--- a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
+++ b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
@@ -322,6 +322,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('792');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('793');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('794');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('795');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('796');
INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '1418215735482', '1418215735482', null, null);
ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl
index 092477c188c..a722b4673ae 100644
--- a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl
+++ b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl
@@ -541,11 +541,10 @@ CREATE TABLE "ANALYSIS_REPORTS" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"PROJECT_KEY" VARCHAR(400) NOT NULL,
"PROJECT_NAME" VARCHAR(256) NULL,
- "SNAPSHOT_ID" INTEGER NOT NULL,
"REPORT_STATUS" VARCHAR(20) NOT NULL,
- "REPORT_DATA" BLOB(2147483647),
- "CREATED_AT" BIGINT,
- "UPDATED_AT" BIGINT,
+ "UUID" VARCHAR(50) NOT NULL,
+ "CREATED_AT" BIGINT NOT NULL,
+ "UPDATED_AT" BIGINT NOT NULL,
"STARTED_AT" BIGINT,
"FINISHED_AT" BIGINT
);
diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
index b6f5b4a4cef..13e651e836c 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -26,6 +26,7 @@ backup_verb=Back up
blocker=Blocker
bold=Bold
branch=Branch
+browsed_recently=Browsed Recently
build_date=Build date
build_time=Build time
calendar=Calendar
@@ -104,6 +105,7 @@ open_verb=Open
operations=Operations
optional=Optional
order=Order
+other=Other
owner=Owner
package=Package
packages=Packages
@@ -155,6 +157,7 @@ template=Template
title=Title
to=To
to.downcase=to
+total=Total
treemap=Treemap
true=True
type=Type
@@ -978,6 +981,7 @@ property.category.general.differentialViews=Differential Views
property.category.general.localization=Localization
property.category.general.databaseCleaner=Database Cleaner
property.category.general.looknfeel=Look & Feel
+property.category.general.issues=Issues
property.category.security=Security
property.category.security.encryption=Encryption
property.category.java=Java
@@ -1069,8 +1073,8 @@ shortcuts.section.issue.comment=comment issue
shortcuts.section.issue.change_tags=change tags of issue
shortcuts.section.rules=Rules Page
-shortcuts.section.rules.navigate_between_rules=navigate between rules
-shortcuts.section.rules.open_details=go from the list of rules to the rule details
+shortcuts.section.rules.navigate_between_rules=navigate between items in a list
+shortcuts.section.rules.open_details=go from the list of items to the rule details
shortcuts.section.rules.return_to_list=return back to the list
@@ -1186,7 +1190,7 @@ widget.events.description=Reports events on the project life cycle such as versi
widget.events.title=Events
widget.events.all=All
widget.events.no_event=No event
-widget.events.show_more=Show more
+widget.events.show_all=Show All
widget.rules.name=Issues and Technical Debt
widget.rules.description=Reports issues and technical debt.
@@ -1319,32 +1323,6 @@ widget.hotspot_metric.property.title.name=Title
widget.hotspot_metric.property.metric.name=Metric
widget.hotspot_metric.property.numberOfLines.name=Number of lines
-widget.hotspot_most_violated_rules.name=Most Violated Rules
-widget.hotspot_most_violated_rules.name_when_period=Most new violated rules
-widget.hotspot_most_violated_rules.description=Shows the rules that are the most violated.
-widget.hotspot_most_violated_rules.no_violation_for_severity=No result
-widget.hotspot_most_violated_rules.any_severity=Any severity
-widget.hotspot_most_violated_rules.property.numberOfLines.name=Number of lines
-widget.hotspot_most_violated_rules.property.defaultSeverity.name=Default severity
-widget.hotspot_most_violated_rules.property.defaultSeverity.desc=If selected, severity used to initialize the dropdown list of widget
-
-widget.my_reviews.name=My Unresolved Issues
-widget.my_reviews.description=Shows unresolved issues assigned to the current user.
-widget.my_reviews.property.numberOfLines.name=Number of lines
-widget.my_reviews.property.numberOfLines.desc=Maximum number of issues displayed at the same time.
-
-widget.false_positive_reviews.name=False Positives Issues
-widget.false_positive_reviews.description=Shows all the false positives found on the project.
-widget.false_positive_reviews.property.numberOfLines.name=Number of lines
-widget.false_positive_reviews.property.numberOfLines.desc=Maximum number of issues displayed at the same time.
-
-widget.reviews_per_developer.name=Unresolved Issues per Assignee
-widget.reviews_per_developer.description=Shows the number of unresolved issues per assignee.
-widget.reviews_per_developer.not_assigned=Not assigned
-
-widget.unresolved_issues_statuses.name=Unresolved Issues by Status
-widget.unresolved_issues_statuses.description=Displays the number of unresolved issues according to their status: Open, Reopened and Confirmed.
-
widget.action_plans.name=Action Plans
widget.action_plans.description=Shows all the open action plans of the project.
widget.action_plans.property.showResolvedIssues.name=Show Resolved Issues
@@ -1355,9 +1333,41 @@ widget.action_plans.x_unresolved_issues={0} unresolved issues
widget.issue_filter.name=Issue Filter
widget.issue_filter.description=Displays the result of a pre-configured issue filter.
widget.issue_filter.property.filter.name=Filter
-widget.issue_filter.property.numberOfLines.name=Page size
+widget.issue_filter.property.distributionAxis.name=Distribution Axis
widget.issue_filter.property.displayFilterDescription.name=Display Filter Description
widget.issue_filter.unknown_filter_warning=This widget is configured to display an issue filter that doesn't exist anymore.
+widget.issue_filter.insufficient_privileges_warning=Widget cannot be displayed: insufficient privileges.
+widget.issue_filter.property.distributionAxis.option.severities.name=By Severity
+widget.issue_filter.property.distributionAxis.option.projectUuids.name=By Project
+widget.issue_filter.property.distributionAxis.option.statuses.name=By Status
+widget.issue_filter.property.distributionAxis.option.createdAt.name=New Issues
+widget.issue_filter.property.distributionAxis.option.actionPlans.name=By Action Plan
+widget.issue_filter.property.distributionAxis.option.assignees.name=By Assignee
+widget.issue_filter.property.distributionAxis.option.tags.name=By Tag
+widget.issue_filter.property.distributionAxis.option.rules.name=By Rule
+widget.issue_filter.property.distributionAxis.option.resolutions.name=By Resolution
+widget.issue_filter.property.distributionAxis.option.languages.name=By Language
+widget.issue_filter.property.distributionAxis.option.reporters.name=By Reporter
+widget.issue_filter.property.distributionAxis.option.authors.name=By Author
+
+widget.project_issue_filter.name=Project Issue Filter
+widget.project_issue_filter.description=Displays the result of a pre-configured issue filter applied to the project.
+widget.project_issue_filter.property.filter.name=Filter
+widget.project_issue_filter.property.distributionAxis.name=Distribution Axis
+widget.project_issue_filter.property.displayFilterDescription.name=Display Filter Description
+widget.project_issue_filter.unknown_filter_warning=This widget is configured to display an issue filter that doesn't exist anymore.
+widget.project_issue_filter.insufficient_privileges_warning=Widget cannot be displayed: insufficient privileges.
+widget.project_issue_filter.property.distributionAxis.option.severities.name=By Severity
+widget.project_issue_filter.property.distributionAxis.option.statuses.name=By Status
+widget.project_issue_filter.property.distributionAxis.option.createdAt.name=New Issues
+widget.project_issue_filter.property.distributionAxis.option.actionPlans.name=By Action Plan
+widget.project_issue_filter.property.distributionAxis.option.assignees.name=By Assignee
+widget.project_issue_filter.property.distributionAxis.option.tags.name=By Tag
+widget.project_issue_filter.property.distributionAxis.option.rules.name=By Rule
+widget.project_issue_filter.property.distributionAxis.option.resolutions.name=By Resolution
+widget.project_issue_filter.property.distributionAxis.option.languages.name=By Language
+widget.project_issue_filter.property.distributionAxis.option.reporters.name=By Reporter
+widget.project_issue_filter.property.distributionAxis.option.authors.name=By Author
widget.issue_tag_cloud.name=Project Issue Tag Cloud
widget.issue_tag_cloud.title=Issue Tag Cloud
@@ -1893,7 +1903,7 @@ coding_rules.rule_template.title=This rule can be used as a template to create c
coding_rules._rules=rules
coding_rules.select_tag=Select Tag
coding_rules.show_template=Show Template
-coding_rules.noncharacterized=Noncharacterized
+coding_rules.noncharacterized=Uncharacterized
coding_rules.update_custom_rule=Update Custom Rule
coding_rules.update_manual_rule=Update Manual Rule
@@ -2748,7 +2758,7 @@ projects_role.groups=Groups
projects_role.admin=Administer
projects_role.admin.desc=Ability to access project settings and perform administration tasks. (Users will also need "Browse" permission)
projects_role.issueadmin=Administer Issues
-projects_role.issueadmin.desc=Grants the permission to perform advanced editing on issues: marking an issue False Positive or changing an Issue's severity. (Users will also need "Browse" permission)
+projects_role.issueadmin.desc=Grants the permission to perform advanced editing on issues: marking an issue False Positive / Won't Fix or changing an Issue's severity. (Users will also need "Browse" permission)
projects_role.user=Browse
projects_role.user.desc=Ability to access a project, browse its measures, and create/edit issues for it.
projects_role.codeviewer=See Source Code
@@ -2798,7 +2808,6 @@ errors.type.notInteger=Value '{0}' must be an integer.
errors.type.notFloat=Value '{0}' must be an floating point number.
errors.type.notInOptions=Value '{0}' must be one of : {1}.
-
#------------------------------------------------------------------------------
#
# HELP
@@ -2894,15 +2903,20 @@ component_viewer.workspace.tooltip=Keeps track of history of navigation
component_viewer.workspace.show_workspace=Show workspace
component_viewer.workspace.hide_workspace=Hide workspace
-source_viewer.covered=Covered
-source_viewer.not_covered=Not covered
+source_viewer.ut.covered=Covered by unit tests
+source_viewer.ut.not_covered=Not covered by unit tests
+source_viewer.it.covered=Covered by integration tests
+source_viewer.it.not_covered=Not covered by integration tests
source_viewer.conditions=conditions
source_viewer.tooltip.duplicated_line=This line is duplicated. Click to see duplicated blocks.
source_viewer.tooltip.duplicated_block=Duplicated block. Click for details.
-source_viewer.tooltip.covered=Fully covered by tests. Click for details.
-source_viewer.tooltip.partially-covered=Partially covered by tests. Click for details.
-source_viewer.tooltip.uncovered=Not covered by tests.
+source_viewer.tooltip.ut.covered=Fully covered by unit tests. Click for details.
+source_viewer.tooltip.ut.partially-covered=Partially covered by unit tests. Click for details.
+source_viewer.tooltip.ut.uncovered=Not covered by unit tests.
+source_viewer.tooltip.it.covered=Fully covered by integration tests. Click for details.
+source_viewer.tooltip.it.partially-covered=Partially covered by integration tests. Click for details.
+source_viewer.tooltip.it.uncovered=Not covered by integration tests.
source_viewer.tooltip.new_code=New {0}.
diff --git a/sonar-core/src/test/java/org/sonar/core/component/ComponentDtoTest.java b/sonar-core/src/test/java/org/sonar/core/component/ComponentDtoTest.java
index 172164cb1c2..ddc26aaa064 100644
--- a/sonar-core/src/test/java/org/sonar/core/component/ComponentDtoTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/component/ComponentDtoTest.java
@@ -74,6 +74,12 @@ public class ComponentDtoTest {
}
@Test
+ public void toString_does_not_fail_if_empty() throws Exception {
+ ComponentDto dto = new ComponentDto();
+ assertThat(dto.toString()).isNotEmpty();
+ }
+
+ @Test
public void is_root_project() throws Exception {
assertThat(new ComponentDto().setModuleUuid("ABCD").isRootProject()).isFalse();
assertThat(new ComponentDto().setModuleUuid("ABCD").setScope(Scopes.DIRECTORY).isRootProject()).isFalse();
diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/DbTester.java b/sonar-core/src/test/java/org/sonar/core/persistence/DbTester.java
index b838a10f452..48470d92f36 100644
--- a/sonar-core/src/test/java/org/sonar/core/persistence/DbTester.java
+++ b/sonar-core/src/test/java/org/sonar/core/persistence/DbTester.java
@@ -56,6 +56,7 @@ import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
+import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -220,14 +221,18 @@ public class DbTester extends ExternalResource {
return rows.get(0);
}
- private static List<Map<String, Object>> getHashMap(ResultSet resultSet) throws SQLException {
+ private static List<Map<String, Object>> getHashMap(ResultSet resultSet) throws Exception {
ResultSetMetaData metaData = resultSet.getMetaData();
int colCount = metaData.getColumnCount();
List<Map<String, Object>> rows = newArrayList();
while (resultSet.next()) {
Map<String, Object> columns = newHashMap();
for (int i = 1; i <= colCount; i++) {
- columns.put(metaData.getColumnLabel(i), resultSet.getObject(i));
+ Object value = resultSet.getObject(i);
+ if (value instanceof Clob) {
+ value = IOUtils.toString(((Clob)value).getAsciiStream());
+ }
+ columns.put(metaData.getColumnLabel(i), value);
}
rows.add(columns);
}
diff --git a/sonar-core/src/test/java/org/sonar/core/util/MultiSetsTest.java b/sonar-core/src/test/java/org/sonar/core/util/MultiSetsTest.java
new file mode 100644
index 00000000000..c7f40b0c83b
--- /dev/null
+++ b/sonar-core/src/test/java/org/sonar/core/util/MultiSetsTest.java
@@ -0,0 +1,49 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.core.util;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class MultiSetsTest {
+ @Test
+ public void order_with_highest_count_first() throws Exception {
+ Multiset<String> multiset = HashMultiset.create();
+ add(multiset, "seneca", 10);
+ add(multiset, "plato", 5);
+ add(multiset, "confucius", 3);
+
+ List<Multiset.Entry<String>> orderedEntries = MultiSets.listOrderedByHighestCounts(multiset);
+
+ assertThat(orderedEntries).extracting("element").containsExactly("seneca", "plato", "confucius");
+ }
+
+ private void add(Multiset<String> multiset, String element, int times) {
+ for (int i = 0; i < times; i++) {
+ multiset.add(element);
+ }
+ }
+}
diff --git a/sonar-deprecated/pom.xml b/sonar-deprecated/pom.xml
index 9b856c20605..d6d933204ac 100644
--- a/sonar-deprecated/pom.xml
+++ b/sonar-deprecated/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-deprecated</artifactId>
<name>SonarQube :: Deprecated</name>
diff --git a/sonar-deprecated/src/main/java/org/sonar/api/rules/XMLRuleParser.java b/sonar-deprecated/src/main/java/org/sonar/api/rules/XMLRuleParser.java
index 58cb60046e5..479d2a93402 100644
--- a/sonar-deprecated/src/main/java/org/sonar/api/rules/XMLRuleParser.java
+++ b/sonar-deprecated/src/main/java/org/sonar/api/rules/XMLRuleParser.java
@@ -38,18 +38,14 @@ import org.sonar.check.Cardinality;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
+import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @since 2.3
- * @deprecated in 4.2. Replaced by org.sonar.api.rule.RuleDefinitions#loadXml()
+ * @deprecated in 4.2. Replaced by org.sonar.api.server.rule.RulesDefinition and org.sonar.api.server.rule.RulesDefinitionXmlLoader
*/
@Deprecated
public final class XMLRuleParser implements ServerComponent {
diff --git a/sonar-duplications/pom.xml b/sonar-duplications/pom.xml
index 66aac795498..56dc0fec83b 100644
--- a/sonar-duplications/pom.xml
+++ b/sonar-duplications/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-duplications</artifactId>
diff --git a/sonar-graph/pom.xml b/sonar-graph/pom.xml
index 18c8612f3c8..1acc1c390be 100644
--- a/sonar-graph/pom.xml
+++ b/sonar-graph/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>sonar-graph</artifactId>
diff --git a/sonar-home/pom.xml b/sonar-home/pom.xml
index 55127f8dd4f..4acab99b362 100644
--- a/sonar-home/pom.xml
+++ b/sonar-home/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-home</artifactId>
diff --git a/sonar-java-api/pom.xml b/sonar-java-api/pom.xml
index 4a3647c8938..c250188556e 100644
--- a/sonar-java-api/pom.xml
+++ b/sonar-java-api/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-java-api</artifactId>
<name>SonarQube :: Java API</name>
diff --git a/sonar-markdown/pom.xml b/sonar-markdown/pom.xml
index 8883090bc1a..c653230d96e 100644
--- a/sonar-markdown/pom.xml
+++ b/sonar-markdown/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
diff --git a/sonar-maven-plugin/pom.xml b/sonar-maven-plugin/pom.xml
index 49ee7be17e7..95781fcdb63 100644
--- a/sonar-maven-plugin/pom.xml
+++ b/sonar-maven-plugin/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
diff --git a/sonar-maven3-plugin/pom.xml b/sonar-maven3-plugin/pom.xml
index fb3083f24b6..fe3fca77dff 100644
--- a/sonar-maven3-plugin/pom.xml
+++ b/sonar-maven3-plugin/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-maven3-plugin</artifactId>
<packaging>pom</packaging>
diff --git a/sonar-plugin-api/pom.xml b/sonar-plugin-api/pom.xml
index 3bb3de8f2e1..c8ad930e776 100644
--- a/sonar-plugin-api/pom.xml
+++ b/sonar-plugin-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-plugin-api</artifactId>
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java
index 1df01833ae5..39d28c1b8cc 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java
@@ -60,6 +60,11 @@ public interface CoreProperties {
String SUBCATEGORY_LOOKNFEEL = "looknfeel";
/**
+ * @since 5.1
+ */
+ String SUBCATEGORY_ISSUES = "issues";
+
+ /**
* @since 4.0
*/
String SUBCATEGORY_L10N = "localization";
@@ -564,4 +569,9 @@ public interface CoreProperties {
*/
String IMPORT_UNKNOWN_FILES_KEY = "sonar.import_unknown_files";
+ /**
+ * @since 5.1
+ */
+ String DEFAULT_ISSUE_ASSIGNEE = "sonar.issues.defaultAssigneeLogin";
+
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/PropertyType.java b/sonar-plugin-api/src/main/java/org/sonar/api/PropertyType.java
index 7462b0a6ba8..292a298c7e2 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/PropertyType.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/PropertyType.java
@@ -80,5 +80,11 @@ public enum PropertyType {
*
* @since 3.3
*/
- PROPERTY_SET
+ PROPERTY_SET,
+
+ /**
+ * User login
+ * @since 5.1
+ */
+ USER_LOGIN
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java
index 7648dac9e8e..823155b2d0a 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java
@@ -35,47 +35,12 @@ import java.util.SortedMap;
public final class CoverageMeasuresBuilder {
/**
- * @since 5.1
- */
- public static enum CoverageType {
- UNIT(CoreMetrics.LINES_TO_COVER, CoreMetrics.UNCOVERED_LINES, CoreMetrics.COVERAGE_LINE_HITS_DATA,
- CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS, CoreMetrics.CONDITIONS_BY_LINE,
- CoreMetrics.COVERED_CONDITIONS_BY_LINE),
- IT(CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.IT_COVERAGE_LINE_HITS_DATA,
- CoreMetrics.IT_CONDITIONS_TO_COVER, CoreMetrics.IT_UNCOVERED_CONDITIONS, CoreMetrics.IT_CONDITIONS_BY_LINE,
- CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE),
- OVERALL(CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA,
- CoreMetrics.OVERALL_CONDITIONS_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, CoreMetrics.OVERALL_CONDITIONS_BY_LINE,
- CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE);
-
- private final Metric<Integer> linesToCover;
- private final Metric<Integer> uncoveredLines;
- private final Metric<String> lineHits;
- private final Metric<Integer> conditionsToCover;
- private final Metric<Integer> uncoveredConditions;
- private final Metric<String> conditionsByLine;
- private final Metric<String> coveredConditionsByLine;
-
- private CoverageType(Metric<Integer> linesToCover, Metric<Integer> uncoveredLines, Metric<String> lineHits, Metric<Integer> conditionsToCover,
- Metric<Integer> uncoveredConditions, Metric<String> conditionsByLine, Metric<String> coveredConditionsByLine) {
- this.linesToCover = linesToCover;
- this.uncoveredLines = uncoveredLines;
- this.lineHits = lineHits;
- this.conditionsToCover = conditionsToCover;
- this.uncoveredConditions = uncoveredConditions;
- this.conditionsByLine = conditionsByLine;
- this.coveredConditionsByLine = coveredConditionsByLine;
- }
-
- public List<Metric> all() {
- return Arrays.<Metric>asList(linesToCover, uncoveredLines, lineHits, conditionsToCover, uncoveredConditions, conditionsByLine, coveredConditionsByLine);
- }
- }
-
- /**
* Metrics of generated measures
*/
- public static final List<Metric> METRICS = CoverageType.UNIT.all();
+ public static final List<Metric> METRICS = Arrays.<Metric>asList(
+ CoreMetrics.LINES_TO_COVER, CoreMetrics.UNCOVERED_LINES, CoreMetrics.COVERAGE_LINE_HITS_DATA,
+ CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS, CoreMetrics.CONDITIONS_BY_LINE,
+ CoreMetrics.COVERED_CONDITIONS_BY_LINE);
private int totalCoveredLines = 0, totalConditions = 0, totalCoveredConditions = 0;
private SortedMap<Integer, Integer> hitsByLine = Maps.newTreeMap();
@@ -145,33 +110,29 @@ public final class CoverageMeasuresBuilder {
}
public Collection<Measure> createMeasures() {
- return createMeasures(CoverageType.UNIT);
- }
-
- public Collection<Measure> createMeasures(CoverageType type) {
Collection<Measure> measures = Lists.newArrayList();
if (getLinesToCover() > 0) {
- measures.add(new Measure(type.linesToCover, (double) getLinesToCover()));
- measures.add(new Measure(type.uncoveredLines, (double) (getLinesToCover() - getCoveredLines())));
- measures.add(new Measure(type.lineHits).setData(KeyValueFormat.format(hitsByLine)).setPersistenceMode(PersistenceMode.DATABASE));
+ measures.add(new Measure(CoreMetrics.LINES_TO_COVER, (double) getLinesToCover()));
+ measures.add(new Measure(CoreMetrics.UNCOVERED_LINES, (double) (getLinesToCover() - getCoveredLines())));
+ measures.add(new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA).setData(KeyValueFormat.format(hitsByLine)).setPersistenceMode(PersistenceMode.DATABASE));
}
if (getConditions() > 0) {
- measures.add(new Measure(type.conditionsToCover, (double) getConditions()));
- measures.add(new Measure(type.uncoveredConditions, (double) (getConditions() - getCoveredConditions())));
- measures.add(createConditionsByLine(type));
- measures.add(createCoveredConditionsByLine(type));
+ measures.add(new Measure(CoreMetrics.CONDITIONS_TO_COVER, (double) getConditions()));
+ measures.add(new Measure(CoreMetrics.UNCOVERED_CONDITIONS, (double) (getConditions() - getCoveredConditions())));
+ measures.add(createConditionsByLine());
+ measures.add(createCoveredConditionsByLine());
}
return measures;
}
- private Measure createCoveredConditionsByLine(CoverageType type) {
- return new Measure(type.coveredConditionsByLine)
+ private Measure createCoveredConditionsByLine() {
+ return new Measure(CoreMetrics.COVERED_CONDITIONS_BY_LINE)
.setData(KeyValueFormat.format(coveredConditionsByLine))
.setPersistenceMode(PersistenceMode.DATABASE);
}
- private Measure createConditionsByLine(CoverageType type) {
- return new Measure(type.conditionsByLine)
+ private Measure createConditionsByLine() {
+ return new Measure(CoreMetrics.CONDITIONS_BY_LINE)
.setData(KeyValueFormat.format(conditionsByLine))
.setPersistenceMode(PersistenceMode.DATABASE);
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java
index 72e2b545f06..55612d860aa 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java
@@ -19,7 +19,6 @@
*/
package org.sonar.api.server.rule;
-import com.google.common.io.Closeables;
import org.apache.commons.lang.StringUtils;
import org.codehaus.staxmate.SMInputFactory;
import org.codehaus.staxmate.in.SMHierarchicCursor;
@@ -31,10 +30,12 @@ import org.sonar.check.Cardinality;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
+import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
@@ -57,10 +58,10 @@ import java.util.List;
* &lt;severity&gt;BLOCKER&lt;/severity&gt;
* &lt;cardinality&gt;MULTIPLE&lt;/cardinality&gt;
* &lt;status&gt;BETA&lt;/status&gt;
+ * &lt;tag&gt;style&lt;/tag&gt;
+ * &lt;tag&gt;security&lt;/tag&gt;
* &lt;param&gt;
* &lt;key&gt;the-param-key&lt;/key&gt;
- * &lt;tag&gt;style&lt;/tag&gt;
- * &lt;tag&gt;security&lt;/tag&gt;
* &lt;description&gt;
* &lt;![CDATA[the param-description]]&gt;
* &lt;/description&gt;
@@ -83,16 +84,17 @@ import java.util.List;
public class RulesDefinitionXmlLoader implements ServerComponent {
public void load(RulesDefinition.NewRepository repo, InputStream input, String encoding) {
- Reader reader = null;
- try {
- reader = new InputStreamReader(input, encoding);
- load(repo, reader);
+ load(repo, input, Charset.forName(encoding));
+ }
+ /**
+ * @since 5.1
+ */
+ public void load(RulesDefinition.NewRepository repo, InputStream input, Charset charset) {
+ try (Reader reader = new InputStreamReader(input, charset)) {
+ load(repo, reader);
} catch (IOException e) {
- throw new IllegalStateException("Fail to load XML file", e);
-
- } finally {
- Closeables.closeQuietly(reader);
+ throw new IllegalStateException("Error while reading XML rules definition for repository " + repo.key(), e);
}
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java
new file mode 100644
index 00000000000..3a8c15bf474
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java
@@ -0,0 +1,108 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.utils.internal;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.rules.ExternalResource;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import org.sonar.api.utils.TempFolder;
+
+import javax.annotation.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Implementation of {@link org.sonar.api.utils.TempFolder} to be used
+ * only in JUnit tests. It wraps {@link org.junit.rules.TemporaryFolder}.
+ * <p/>
+ * Example:
+ * <pre>
+ * public class MyTest {
+ * &#064;@org.junit.Rule
+ * public JUnitTempFolder temp = new JUnitTempFolder();
+ *
+ * &#064;@org.junit.Test
+ * public void myTest() throws Exception {
+ * File dir = temp.newDir();
+ * // ...
+ * }
+ * }
+ * </pre>
+ *
+ * @since 5.1
+ */
+public class JUnitTempFolder extends ExternalResource implements TempFolder {
+
+ private final TemporaryFolder junit = new TemporaryFolder();
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return junit.apply(base, description);
+ }
+
+ @Override
+ protected void before() throws Throwable {
+ junit.create();
+ }
+
+ @Override
+ protected void after() {
+ junit.delete();
+ }
+
+ @Override
+ public File newDir() {
+ try {
+ return junit.newFolder();
+ } catch (IOException e) {
+ throw new IllegalStateException("Fail to create temp dir", e);
+ }
+ }
+
+ @Override
+ public File newDir(String name) {
+ try {
+ return junit.newFolder(name);
+ } catch (IOException e) {
+ throw new IllegalStateException("Fail to create temp dir", e);
+ }
+ }
+
+ @Override
+ public File newFile() {
+ try {
+ return junit.newFile();
+ } catch (IOException e) {
+ throw new IllegalStateException("Fail to create temp file", e);
+ }
+ }
+
+ @Override
+ public File newFile(@Nullable String prefix, @Nullable String suffix) {
+ try {
+ return junit.newFile(StringUtils.defaultString(prefix) + "-" + StringUtils.defaultString(suffix));
+ } catch (IOException e) {
+ throw new IllegalStateException("Fail to create temp file", e);
+ }
+ }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/BaseLogger.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/BaseLogger.java
index fec49378945..8b33cf19f05 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/BaseLogger.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/BaseLogger.java
@@ -24,127 +24,127 @@ import javax.annotation.Nullable;
abstract class BaseLogger implements Logger {
@Override
public void trace(String msg) {
- LogInterceptors.get().log(msg);
+ LogInterceptors.get().log(LoggerLevel.TRACE, msg);
doTrace(msg);
}
@Override
public void trace(String pattern, @Nullable Object arg) {
- LogInterceptors.get().log(pattern, arg);
+ LogInterceptors.get().log(LoggerLevel.TRACE, pattern, arg);
doTrace(pattern, arg);
}
@Override
public void trace(String msg, @Nullable Object arg1, @Nullable Object arg2) {
- LogInterceptors.get().log(msg, arg1, arg2);
+ LogInterceptors.get().log(LoggerLevel.TRACE, msg, arg1, arg2);
doTrace(msg, arg1, arg2);
}
@Override
public void trace(String msg, Object... args) {
- LogInterceptors.get().log(msg, args);
+ LogInterceptors.get().log(LoggerLevel.TRACE, msg, args);
doTrace(msg, args);
}
@Override
public void debug(String msg) {
- LogInterceptors.get().log(msg);
+ LogInterceptors.get().log(LoggerLevel.DEBUG, msg);
doDebug(msg);
}
@Override
public void debug(String pattern, @Nullable Object arg) {
- LogInterceptors.get().log(pattern, arg);
+ LogInterceptors.get().log(LoggerLevel.DEBUG, pattern, arg);
doDebug(pattern, arg);
}
@Override
public void debug(String msg, @Nullable Object arg1, @Nullable Object arg2) {
- LogInterceptors.get().log(msg, arg1, arg2);
+ LogInterceptors.get().log(LoggerLevel.DEBUG, msg, arg1, arg2);
doDebug(msg, arg1, arg2);
}
@Override
public void debug(String msg, Object... args) {
- LogInterceptors.get().log(msg, args);
+ LogInterceptors.get().log(LoggerLevel.DEBUG, msg, args);
doDebug(msg, args);
}
@Override
public void info(String msg) {
- LogInterceptors.get().log(msg);
+ LogInterceptors.get().log(LoggerLevel.INFO, msg);
doInfo(msg);
}
@Override
public void info(String msg, @Nullable Object arg) {
- LogInterceptors.get().log(msg, arg);
+ LogInterceptors.get().log(LoggerLevel.INFO, msg, arg);
doInfo(msg, arg);
}
@Override
public void info(String msg, @Nullable Object arg1, @Nullable Object arg2) {
- LogInterceptors.get().log(msg, arg1, arg2);
+ LogInterceptors.get().log(LoggerLevel.INFO, msg, arg1, arg2);
doInfo(msg, arg1, arg2);
}
@Override
public void info(String msg, Object... args) {
- LogInterceptors.get().log(msg, args);
+ LogInterceptors.get().log(LoggerLevel.INFO, msg, args);
doInfo(msg, args);
}
@Override
public void warn(String msg) {
- LogInterceptors.get().log(msg);
+ LogInterceptors.get().log(LoggerLevel.WARN, msg);
doWarn(msg);
}
@Override
public void warn(String msg, @Nullable Object arg) {
- LogInterceptors.get().log(msg, arg);
+ LogInterceptors.get().log(LoggerLevel.WARN, msg, arg);
doWarn(msg, arg);
}
@Override
public void warn(String msg, @Nullable Object arg1, @Nullable Object arg2) {
- LogInterceptors.get().log(msg, arg1, arg2);
+ LogInterceptors.get().log(LoggerLevel.WARN, msg, arg1, arg2);
doWarn(msg, arg1, arg2);
}
@Override
public void warn(String msg, Object... args) {
- LogInterceptors.get().log(msg, args);
+ LogInterceptors.get().log(LoggerLevel.WARN, msg, args);
doWarn(msg, args);
}
@Override
public void error(String msg) {
- LogInterceptors.get().log(msg);
+ LogInterceptors.get().log(LoggerLevel.ERROR, msg);
doError(msg);
}
@Override
public void error(String msg, @Nullable Object arg) {
- LogInterceptors.get().log(msg, arg);
+ LogInterceptors.get().log(LoggerLevel.ERROR, msg, arg);
doError(msg, arg);
}
@Override
public void error(String msg, @Nullable Object arg1, @Nullable Object arg2) {
- LogInterceptors.get().log(msg, arg1, arg2);
+ LogInterceptors.get().log(LoggerLevel.ERROR, msg, arg1, arg2);
doError(msg, arg1, arg2);
}
@Override
public void error(String msg, Object... args) {
- LogInterceptors.get().log(msg, args);
+ LogInterceptors.get().log(LoggerLevel.ERROR, msg, args);
doError(msg, args);
}
@Override
public void error(String msg, Throwable thrown) {
- LogInterceptors.get().log(msg, thrown);
+ LogInterceptors.get().log(LoggerLevel.ERROR, msg, thrown);
doError(msg, thrown);
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/ListInterceptor.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/ListInterceptor.java
index 76e3c444829..67869605d9a 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/ListInterceptor.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/ListInterceptor.java
@@ -19,6 +19,9 @@
*/
package org.sonar.api.utils.log;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
+
import javax.annotation.Nullable;
import java.util.ArrayList;
@@ -27,37 +30,51 @@ import java.util.List;
class ListInterceptor extends LogInterceptor {
private final List<String> logs = new ArrayList<>();
+ private final ListMultimap<LoggerLevel, String> logsByLevel = ArrayListMultimap.create();
@Override
- public void log(String msg) {
+ public void log(LoggerLevel level, String msg) {
logs.add(msg);
+ logsByLevel.put(level, msg);
}
@Override
- public void log(String msg, @Nullable Object arg) {
- logs.add(ConsoleFormatter.format(msg, arg));
+ public void log(LoggerLevel level, String msg, @Nullable Object arg) {
+ String s = ConsoleFormatter.format(msg, arg);
+ logs.add(s);
+ logsByLevel.put(level, s);
}
@Override
- public void log(String msg, @Nullable Object arg1, @Nullable Object arg2) {
- logs.add(ConsoleFormatter.format(msg, arg1, arg2));
+ public void log(LoggerLevel level, String msg, @Nullable Object arg1, @Nullable Object arg2) {
+ String s = ConsoleFormatter.format(msg, arg1, arg2);
+ logs.add(s);
+ logsByLevel.put(level, s);
}
@Override
- public void log(String msg, Object... args) {
- logs.add(ConsoleFormatter.format(msg, args));
+ public void log(LoggerLevel level, String msg, Object... args) {
+ String s = ConsoleFormatter.format(msg, args);
+ logs.add(s);
+ logsByLevel.put(level, s);
}
@Override
- public void log(String msg, Throwable thrown) {
+ public void log(LoggerLevel level, String msg, Throwable thrown) {
logs.add(msg);
+ logsByLevel.put(level, msg);
}
public List<String> logs() {
return logs;
}
+ public List<String> logs(LoggerLevel level) {
+ return logsByLevel.get(level);
+ }
+
public void clear() {
logs.clear();
+ logsByLevel.clear();
}
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogInterceptor.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogInterceptor.java
index bccd7e9797a..556b1644130 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogInterceptor.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogInterceptor.java
@@ -23,13 +23,13 @@ import javax.annotation.Nullable;
abstract class LogInterceptor {
- abstract void log(String msg);
+ abstract void log(LoggerLevel level, String msg);
- abstract void log(String msg, @Nullable Object arg);
+ abstract void log(LoggerLevel level, String msg, @Nullable Object arg);
- abstract void log(String msg, @Nullable Object arg1, @Nullable Object arg2);
+ abstract void log(LoggerLevel level, String msg, @Nullable Object arg1, @Nullable Object arg2);
- abstract void log(String msg, Object... args);
+ abstract void log(LoggerLevel level, String msg, Object... args);
- abstract void log(String msg, Throwable thrown);
+ abstract void log(LoggerLevel level, String msg, Throwable thrown);
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTester.java
index cdc112fbbf7..ab2fe4a3fa5 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTester.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTester.java
@@ -42,10 +42,10 @@ import java.util.List;
* }
*
* public class MyTest {
- * &#064;Rule
+ * &#064;org.junit.Rule
* public LogTester logTester = new LogTester();
*
- * &#064;Test
+ * &#064;org.junit.Test
* public void test_log() {
* new MyClass().doSomething();
*
@@ -95,6 +95,14 @@ public class LogTester extends ExternalResource {
return ((ListInterceptor) LogInterceptors.get()).logs();
}
+ /**
+ * Logs in chronological order (item at index 0 is the oldest one) for
+ * a given level
+ */
+ public List<String> logs(LoggerLevel level) {
+ return ((ListInterceptor) LogInterceptors.get()).logs(level);
+ }
+
public LogTester clear() {
((ListInterceptor) LogInterceptors.get()).clear();
return this;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/NullInterceptor.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/NullInterceptor.java
index 63e0d9ab847..6614e01bf31 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/NullInterceptor.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/NullInterceptor.java
@@ -30,27 +30,27 @@ class NullInterceptor extends LogInterceptor {
}
@Override
- void log(String msg) {
+ void log(LoggerLevel level, String msg) {
// nothing
}
@Override
- void log(String msg, Object arg) {
+ void log(LoggerLevel level, String msg, Object arg) {
// nothing
}
@Override
- void log(String msg, Object arg1, Object arg2) {
+ void log(LoggerLevel level, String msg, Object arg1, Object arg2) {
// nothing
}
@Override
- void log(String msg, Object... args) {
+ void log(LoggerLevel level, String msg, Object... args) {
// nothing
}
@Override
- void log(String msg, Throwable thrown) {
+ void log(LoggerLevel level, String msg, Throwable thrown) {
// nothing
}
}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/HotspotMostViolatedRulesWidget.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/JUnitTempFolderTest.java
index 27b382155a7..c2086e05c36 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/HotspotMostViolatedRulesWidget.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/JUnitTempFolderTest.java
@@ -17,21 +17,37 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.plugins.core.widgets;
-
-import org.sonar.api.web.WidgetCategory;
-import org.sonar.api.web.WidgetProperties;
-import org.sonar.api.web.WidgetProperty;
-import org.sonar.api.web.WidgetPropertyType;
-
-@WidgetCategory("Hotspots")
-@WidgetProperties(
-{
- @WidgetProperty(key = "numberOfLines", type = WidgetPropertyType.INTEGER, defaultValue = "5"),
- @WidgetProperty(key = "defaultSeverity", type = WidgetPropertyType.SINGLE_SELECT_LIST, defaultValue = "", options = {"INFO", "MINOR", "MAJOR", "CRITICAL", "BLOCKER"})
-})
-public class HotspotMostViolatedRulesWidget extends CoreWidget {
- public HotspotMostViolatedRulesWidget() {
- super("hotspot_most_violated_rules", "Most violated rules", "/org/sonar/plugins/core/widgets/hotspots/hotspot_most_violated_rules.html.erb");
+package org.sonar.api.utils.internal;
+
+import org.junit.Test;
+
+import java.io.File;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class JUnitTempFolderTest {
+
+ @Test
+ public void apply() throws Throwable {
+ JUnitTempFolder temp = new JUnitTempFolder();
+ temp.before();
+ File dir1 = temp.newDir();
+ assertThat(dir1).isDirectory().exists();
+
+ File dir2 = temp.newDir("foo");
+ assertThat(dir2).isDirectory().exists();
+
+ File file1 = temp.newFile();
+ assertThat(file1).isFile().exists();
+
+ File file2 = temp.newFile("foo", "txt");
+ assertThat(file2).isFile().exists();
+
+ temp.after();
+ assertThat(dir1).doesNotExist();
+ assertThat(dir2).doesNotExist();
+ assertThat(file1).doesNotExist();
+ assertThat(file2).doesNotExist();
}
+
}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterTest.java
index 9fd01343f34..9880b1ef13a 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterTest.java
@@ -54,9 +54,13 @@ public class LogTesterTest {
Loggers.get("logger2").warn("warning: {}", 42);
assertThat(sut.logs()).containsExactly("an information", "warning: 42");
+ assertThat(sut.logs(LoggerLevel.ERROR)).isEmpty();
+ assertThat(sut.logs(LoggerLevel.INFO)).containsOnly("an information");
+ assertThat(sut.logs(LoggerLevel.WARN)).containsOnly("warning: 42");
sut.clear();
assertThat(sut.logs()).isEmpty();
+ assertThat(sut.logs(LoggerLevel.INFO)).isEmpty();
sut.after();
assertThat(LogInterceptors.get()).isSameAs(NullInterceptor.NULL_INSTANCE);
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/NullInterceptorTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/NullInterceptorTest.java
index ca4d14e4890..f410fcd80ae 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/NullInterceptorTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/NullInterceptorTest.java
@@ -28,10 +28,10 @@ public class NullInterceptorTest {
@Test
public void do_not_throws_exception() throws Exception {
// verify that... it does nothing
- NullInterceptor.NULL_INSTANCE.log("foo");
- NullInterceptor.NULL_INSTANCE.log("foo {}", 42);
- NullInterceptor.NULL_INSTANCE.log("foo {} {}", 42, 66);
- NullInterceptor.NULL_INSTANCE.log("foo {} {} {}", 42, 66, 84);
- NullInterceptor.NULL_INSTANCE.log("foo", mock(Exception.class));
+ NullInterceptor.NULL_INSTANCE.log(LoggerLevel.INFO, "foo");
+ NullInterceptor.NULL_INSTANCE.log(LoggerLevel.INFO, "foo {}", 42);
+ NullInterceptor.NULL_INSTANCE.log(LoggerLevel.INFO, "foo {} {}", 42, 66);
+ NullInterceptor.NULL_INSTANCE.log(LoggerLevel.INFO, "foo {} {} {}", 42, 66, 84);
+ NullInterceptor.NULL_INSTANCE.log(LoggerLevel.INFO, "foo", mock(Exception.class));
}
}
diff --git a/sonar-testing-harness/pom.xml b/sonar-testing-harness/pom.xml
index e646ec13a93..a0af4198337 100644
--- a/sonar-testing-harness/pom.xml
+++ b/sonar-testing-harness/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
- <version>5.1-SNAPSHOT</version>
+ <version>5.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-testing-harness</artifactId>
<packaging>jar</packaging>