001/* 002 * SonarQube 003 * Copyright (C) 2009-2016 SonarSource SA 004 * mailto:contact AT sonarsource DOT com 005 * 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public License 017 * along with this program; if not, write to the Free Software Foundation, 018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 */ 020package org.sonar.api.ce.posttask; 021 022import com.google.common.annotations.Beta; 023import java.util.ArrayList; 024import java.util.Collection; 025import java.util.Date; 026import java.util.List; 027import javax.annotation.CheckForNull; 028import javax.annotation.Nullable; 029 030import static com.google.common.base.Preconditions.checkArgument; 031import static com.google.common.base.Preconditions.checkState; 032import static java.util.Objects.requireNonNull; 033 034/** 035 * This class can be used to test {@link PostProjectAnalysisTask} implementations, see example below: 036 * <pre> 037 * import static org.assertj.core.api.Assertions.assertThat; 038 * import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newCeTaskBuilder; 039 * import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newConditionBuilder; 040 * import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newProjectBuilder; 041 * import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newQualityGateBuilder; 042 * 043 * public class CaptorPostProjectAnalysisTaskTest { 044 * private class CaptorPostProjectAnalysisTask implements PostProjectAnalysisTask { 045 * private ProjectAnalysis projectAnalysis; 046 * 047 * {@literal @}Override 048 * public void finished(ProjectAnalysis analysis) { 049 * this.projectAnalysis = analysis; 050 * } 051 * } 052 * 053 * {@literal @}Test 054 * public void execute_is_passed_a_non_null_ProjectAnalysis_object() { 055 * CaptorPostProjectAnalysisTask postProjectAnalysisTask = new CaptorPostProjectAnalysisTask(); 056 * 057 * PostProjectAnalysisTaskTester.of(postProjectAnalysisTask) 058 * .withCeTask( 059 * newCeTaskBuilder() 060 * .setId("id") 061 * .setStatus(CeTask.Status.SUCCESS) 062 * .build()) 063 * .withProject( 064 * PostProjectAnalysisTaskTester.newProjectBuilder() 065 * .setUuid("uuid") 066 * .setKey("key") 067 * .setName("name") 068 * .build()) 069 * .at(new Date()) 070 * .withQualityGate( 071 * newQualityGateBuilder() 072 * .setId("id") 073 * .setName("name") 074 * .setStatus(QualityGate.Status.OK) 075 * .add( 076 * newConditionBuilder() 077 * .setMetricKey("metric key") 078 * .setOperator(QualityGate.Operator.GREATER_THAN) 079 * .setErrorThreshold("12") 080 * .setOnLeakPeriod(true) 081 * .build(QualityGate.EvaluationStatus.OK, "value")) 082 * .build()) 083 * .execute(); 084 * 085 * assertThat(postProjectAnalysisTask.projectAnalysis).isNotNull(); 086 * } 087 * } 088 * </pre> 089 * 090 * @since 5.5 091 */ 092@Beta 093public class PostProjectAnalysisTaskTester { 094 private static final String DATE_CAN_NOT_BE_NULL = "date cannot be null"; 095 private static final String PROJECT_CAN_NOT_BE_NULL = "project cannot be null"; 096 private static final String CE_TASK_CAN_NOT_BE_NULL = "ceTask cannot be null"; 097 private static final String STATUS_CAN_NOT_BE_NULL = "status cannot be null"; 098 099 private final PostProjectAnalysisTask underTest; 100 @CheckForNull 101 private CeTask ceTask; 102 @CheckForNull 103 private Project project; 104 @CheckForNull 105 private Date date; 106 @CheckForNull 107 private QualityGate qualityGate; 108 109 private PostProjectAnalysisTaskTester(PostProjectAnalysisTask underTest) { 110 this.underTest = requireNonNull(underTest, "PostProjectAnalysisTask instance cannot be null"); 111 } 112 113 public static PostProjectAnalysisTaskTester of(PostProjectAnalysisTask underTest) { 114 return new PostProjectAnalysisTaskTester(underTest); 115 } 116 117 public static CeTaskBuilder newCeTaskBuilder() { 118 return new CeTaskBuilder(); 119 } 120 121 public static ProjectBuilder newProjectBuilder() { 122 return new ProjectBuilder(); 123 } 124 125 public static QualityGateBuilder newQualityGateBuilder() { 126 return new QualityGateBuilder(); 127 } 128 129 public static ConditionBuilder newConditionBuilder() { 130 return new ConditionBuilder(); 131 } 132 133 public PostProjectAnalysisTaskTester withCeTask(CeTask ceTask) { 134 this.ceTask = requireNonNull(ceTask, CE_TASK_CAN_NOT_BE_NULL); 135 return this; 136 } 137 138 public PostProjectAnalysisTaskTester withProject(Project project) { 139 this.project = requireNonNull(project, PROJECT_CAN_NOT_BE_NULL); 140 return this; 141 } 142 143 public PostProjectAnalysisTaskTester at(Date date) { 144 this.date = requireNonNull(date, DATE_CAN_NOT_BE_NULL); 145 return this; 146 } 147 148 public PostProjectAnalysisTaskTester withQualityGate(@Nullable QualityGate qualityGate) { 149 this.qualityGate = qualityGate; 150 return this; 151 } 152 153 public void execute() { 154 this.ceTask = requireNonNull(ceTask, CE_TASK_CAN_NOT_BE_NULL); 155 this.project = requireNonNull(project, PROJECT_CAN_NOT_BE_NULL); 156 this.date = requireNonNull(date, DATE_CAN_NOT_BE_NULL); 157 158 this.underTest.finished( 159 new PostProjectAnalysisTask.ProjectAnalysis() { 160 @Override 161 public CeTask getCeTask() { 162 return ceTask; 163 } 164 165 @Override 166 public Project getProject() { 167 return project; 168 } 169 170 @Override 171 public QualityGate getQualityGate() { 172 return qualityGate; 173 } 174 175 @Override 176 public Date getDate() { 177 return date; 178 } 179 180 @Override 181 public String toString() { 182 return "ProjectAnalysis{" + 183 "ceTask=" + ceTask + 184 ", project=" + project + 185 ", date=" + date.getTime() + 186 ", qualityGate=" + qualityGate + 187 '}'; 188 } 189 }); 190 191 } 192 193 @Beta 194 public static final class CeTaskBuilder { 195 private static final String ID_CAN_NOT_BE_NULL = "id cannot be null"; 196 197 @CheckForNull 198 private String id; 199 @CheckForNull 200 private CeTask.Status status; 201 202 private CeTaskBuilder() { 203 // prevents instantiation outside PostProjectAnalysisTaskTester 204 } 205 206 public CeTaskBuilder setId(String id) { 207 this.id = requireNonNull(id, ID_CAN_NOT_BE_NULL); 208 return this; 209 } 210 211 public CeTaskBuilder setStatus(CeTask.Status status) { 212 this.status = requireNonNull(status, STATUS_CAN_NOT_BE_NULL); 213 return this; 214 } 215 216 public CeTask build() { 217 requireNonNull(id, ID_CAN_NOT_BE_NULL); 218 requireNonNull(status, STATUS_CAN_NOT_BE_NULL); 219 return new CeTask() { 220 @Override 221 public String getId() { 222 return id; 223 } 224 225 @Override 226 public Status getStatus() { 227 return status; 228 } 229 230 @Override 231 public String toString() { 232 return "CeTask{" + 233 "id='" + id + '\'' + 234 ", status=" + status + 235 '}'; 236 } 237 }; 238 } 239 } 240 241 @Beta 242 public static final class ProjectBuilder { 243 private static final String UUID_CAN_NOT_BE_NULL = "uuid cannot be null"; 244 private static final String KEY_CAN_NOT_BE_NULL = "key cannot be null"; 245 private static final String NAME_CAN_NOT_BE_NULL = "name cannot be null"; 246 private String uuid; 247 private String key; 248 private String name; 249 250 private ProjectBuilder() { 251 // prevents instantiation outside PostProjectAnalysisTaskTester 252 } 253 254 public ProjectBuilder setUuid(String uuid) { 255 this.uuid = requireNonNull(uuid, UUID_CAN_NOT_BE_NULL); 256 return this; 257 } 258 259 public ProjectBuilder setKey(String key) { 260 this.key = requireNonNull(key, KEY_CAN_NOT_BE_NULL); 261 return this; 262 } 263 264 public ProjectBuilder setName(String name) { 265 this.name = requireNonNull(name, NAME_CAN_NOT_BE_NULL); 266 return this; 267 } 268 269 public Project build() { 270 requireNonNull(uuid, UUID_CAN_NOT_BE_NULL); 271 requireNonNull(key, KEY_CAN_NOT_BE_NULL); 272 requireNonNull(name, NAME_CAN_NOT_BE_NULL); 273 return new Project() { 274 @Override 275 public String getUuid() { 276 return uuid; 277 } 278 279 @Override 280 public String getKey() { 281 return key; 282 } 283 284 @Override 285 public String getName() { 286 return name; 287 } 288 289 @Override 290 public String toString() { 291 return "Project{" + 292 "uuid='" + uuid + '\'' + 293 ", key='" + key + '\'' + 294 ", name='" + name + '\'' + 295 '}'; 296 } 297 298 }; 299 } 300 } 301 302 @Beta 303 public static final class QualityGateBuilder { 304 private static final String ID_CAN_NOT_BE_NULL = "id cannot be null"; 305 private static final String NAME_CAN_NOT_BE_NULL = "name cannot be null"; 306 307 private String id; 308 private String name; 309 private QualityGate.Status status; 310 private final List<QualityGate.Condition> conditions = new ArrayList<>(); 311 312 private QualityGateBuilder() { 313 // prevents instantiation outside PostProjectAnalysisTaskTester 314 } 315 316 public QualityGateBuilder setId(String id) { 317 this.id = requireNonNull(id, ID_CAN_NOT_BE_NULL); 318 return this; 319 } 320 321 public QualityGateBuilder setName(String name) { 322 this.name = requireNonNull(name, NAME_CAN_NOT_BE_NULL); 323 return this; 324 } 325 326 public QualityGateBuilder setStatus(QualityGate.Status status) { 327 this.status = requireNonNull(status, STATUS_CAN_NOT_BE_NULL); 328 return this; 329 } 330 331 public QualityGateBuilder add(QualityGate.Condition condition) { 332 conditions.add(requireNonNull(condition, "condition cannot be null")); 333 return this; 334 } 335 336 public QualityGateBuilder clearConditions() { 337 this.conditions.clear(); 338 return this; 339 } 340 341 public QualityGate build() { 342 requireNonNull(id, ID_CAN_NOT_BE_NULL); 343 requireNonNull(name, NAME_CAN_NOT_BE_NULL); 344 requireNonNull(status, STATUS_CAN_NOT_BE_NULL); 345 346 return new QualityGate() { 347 @Override 348 public String getId() { 349 return id; 350 } 351 352 @Override 353 public String getName() { 354 return name; 355 } 356 357 @Override 358 public Status getStatus() { 359 return status; 360 } 361 362 @Override 363 public Collection<Condition> getConditions() { 364 return conditions; 365 } 366 367 @Override 368 public String toString() { 369 return "QualityGate{" + 370 "id='" + id + '\'' + 371 ", name='" + name + '\'' + 372 ", status=" + status + 373 ", conditions=" + conditions + 374 '}'; 375 } 376 }; 377 } 378 } 379 380 @Beta 381 public static final class ConditionBuilder { 382 private static final String METRIC_KEY_CAN_NOT_BE_NULL = "metricKey cannot be null"; 383 private static final String OPERATOR_CAN_NOT_BE_NULL = "operator cannot be null"; 384 385 private String metricKey; 386 private QualityGate.Operator operator; 387 private String errorThreshold; 388 private String warningThreshold; 389 private boolean onLeakPeriod; 390 391 private ConditionBuilder() { 392 // prevents instantiation outside PostProjectAnalysisTaskTester 393 } 394 395 public ConditionBuilder setMetricKey(String metricKey) { 396 this.metricKey = requireNonNull(metricKey, METRIC_KEY_CAN_NOT_BE_NULL); 397 return this; 398 } 399 400 public ConditionBuilder setOperator(QualityGate.Operator operator) { 401 this.operator = requireNonNull(operator, OPERATOR_CAN_NOT_BE_NULL); 402 return this; 403 } 404 405 public ConditionBuilder setErrorThreshold(@Nullable String errorThreshold) { 406 this.errorThreshold = errorThreshold; 407 return this; 408 } 409 410 public ConditionBuilder setWarningThreshold(@Nullable String warningThreshold) { 411 this.warningThreshold = warningThreshold; 412 return this; 413 } 414 415 public ConditionBuilder setOnLeakPeriod(boolean onLeakPeriod) { 416 this.onLeakPeriod = onLeakPeriod; 417 return this; 418 } 419 420 public QualityGate.Condition buildNoValue() { 421 checkCommonProperties(); 422 return new QualityGate.Condition() { 423 @Override 424 public QualityGate.EvaluationStatus getStatus() { 425 return QualityGate.EvaluationStatus.NO_VALUE; 426 } 427 428 @Override 429 public String getMetricKey() { 430 return metricKey; 431 } 432 433 @Override 434 public QualityGate.Operator getOperator() { 435 return operator; 436 } 437 438 @Override 439 public String getErrorThreshold() { 440 return errorThreshold; 441 } 442 443 @Override 444 public String getWarningThreshold() { 445 return warningThreshold; 446 } 447 448 @Override 449 public boolean isOnLeakPeriod() { 450 return onLeakPeriod; 451 } 452 453 @Override 454 public String getValue() { 455 throw new IllegalStateException("There is no value when status is NO_VALUE"); 456 } 457 458 @Override 459 public String toString() { 460 return "Condition{" + 461 "status=" + QualityGate.EvaluationStatus.NO_VALUE + 462 ", metricKey='" + metricKey + '\'' + 463 ", operator=" + operator + 464 ", errorThreshold='" + errorThreshold + '\'' + 465 ", warningThreshold='" + warningThreshold + '\'' + 466 ", onLeakPeriod=" + onLeakPeriod + 467 '}'; 468 } 469 }; 470 } 471 472 public QualityGate.Condition build(final QualityGate.EvaluationStatus status, final String value) { 473 checkCommonProperties(); 474 requireNonNull(status, STATUS_CAN_NOT_BE_NULL); 475 checkArgument(status != QualityGate.EvaluationStatus.NO_VALUE, "status cannot be NO_VALUE, use method buildNoValue() instead"); 476 requireNonNull(value, "value cannot be null, use method buildNoValue() instead"); 477 return new QualityGate.Condition() { 478 @Override 479 public QualityGate.EvaluationStatus getStatus() { 480 return status; 481 } 482 483 @Override 484 public String getMetricKey() { 485 return metricKey; 486 } 487 488 @Override 489 public QualityGate.Operator getOperator() { 490 return operator; 491 } 492 493 @Override 494 public String getErrorThreshold() { 495 return errorThreshold; 496 } 497 498 @Override 499 public String getWarningThreshold() { 500 return warningThreshold; 501 } 502 503 @Override 504 public boolean isOnLeakPeriod() { 505 return onLeakPeriod; 506 } 507 508 @Override 509 public String getValue() { 510 return value; 511 } 512 513 @Override 514 public String toString() { 515 return "Condition{" + 516 "status=" + status + 517 ", metricKey='" + metricKey + '\'' + 518 ", operator=" + operator + 519 ", errorThreshold='" + errorThreshold + '\'' + 520 ", warningThreshold='" + warningThreshold + '\'' + 521 ", onLeakPeriod=" + onLeakPeriod + 522 ", value='" + value + '\'' + 523 '}'; 524 } 525 }; 526 } 527 528 private void checkCommonProperties() { 529 requireNonNull(metricKey, METRIC_KEY_CAN_NOT_BE_NULL); 530 requireNonNull(operator, OPERATOR_CAN_NOT_BE_NULL); 531 checkState(errorThreshold != null || warningThreshold != null, "At least one of errorThreshold and warningThreshold must be non null"); 532 } 533 } 534}