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