/* * Copyright 2012-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.test; import com.facebook.buck.event.external.elements.TestCaseSummaryExternalInterface; import com.facebook.buck.util.Ansi; import com.facebook.buck.util.TimeFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import com.google.common.collect.ImmutableList; import java.util.List; import java.util.Locale; public class TestCaseSummary implements TestCaseSummaryExternalInterface<TestResultSummary> { private static final int MAX_STATUS_WIDTH = 7; private final String testCaseName; private final ImmutableList<TestResultSummary> testResults; private final boolean isDryRun; private final boolean hasAssumptionViolations; private final int skippedCount; private final int passCount; private final int failureCount; private final long totalTime; public TestCaseSummary(String testCaseName, List<TestResultSummary> testResults) { this.testCaseName = testCaseName; this.testResults = ImmutableList.copyOf(testResults); boolean isDryRun = false; boolean hasAssumptionViolations = false; int skippedCount = 0; int failureCount = 0; int passCount = 0; long totalTime = 0L; for (TestResultSummary result : testResults) { totalTime += result.getTime(); switch (result.getType()) { case SUCCESS: ++passCount; break; case DRY_RUN: isDryRun = true; ++passCount; // "pass" in the sense that it confirms the class can be loaded break; case DISABLED: ++skippedCount; break; case EXCLUDED: break; case ASSUMPTION_VIOLATION: hasAssumptionViolations = true; ++skippedCount; break; case FAILURE: ++failureCount; break; } } this.isDryRun = isDryRun; this.hasAssumptionViolations = hasAssumptionViolations; this.skippedCount = skippedCount; this.failureCount = failureCount; this.passCount = passCount; this.totalTime = totalTime; } @JsonIgnore public boolean isDryRun() { return isDryRun; } @Override public boolean isSuccess() { return failureCount == 0; } @Override public boolean hasAssumptionViolations() { return hasAssumptionViolations; } @Override public String getTestCaseName() { return testCaseName; } /** @return the total time to run all of the tests in this test case, in milliseconds */ @Override public long getTotalTime() { return totalTime; } /** @return a one-line, printable summary */ public String getOneLineSummary(Locale locale, boolean hasPassingDependencies, Ansi ansi) { String statusText; Ansi.SeverityLevel severityLevel; if (isDryRun) { severityLevel = Ansi.SeverityLevel.WARNING; statusText = "DRYRUN"; } else if (!isSuccess()) { if (hasPassingDependencies) { severityLevel = Ansi.SeverityLevel.ERROR; statusText = "FAIL"; } else { severityLevel = Ansi.SeverityLevel.WARNING; statusText = "DROP"; } } else { if (hasAssumptionViolations) { severityLevel = Ansi.SeverityLevel.WARNING; statusText = "ASSUME"; } else { if (passCount == 0) { severityLevel = Ansi.SeverityLevel.WARNING; statusText = "NOTESTS"; } else { severityLevel = Ansi.SeverityLevel.OK; statusText = "PASS"; } } } String status = ansi.asHighlightedStatusText(severityLevel, statusText); int paddingWidth = MAX_STATUS_WIDTH - statusText.length(); String padding = ""; for (int position = 0; position < paddingWidth; position++) { padding += ' '; } return String.format( locale, "%s%s %s %2d Passed %2d Skipped %2d Failed %s", status, padding, TimeFormat.formatForConsole(locale, totalTime, ansi), getPassedCount(), skippedCount, failureCount, testCaseName); } @Override public ImmutableList<TestResultSummary> getTestResults() { return testResults; } @JsonIgnore public int getPassedCount() { return passCount; } @Override public int getSkippedCount() { return skippedCount; } @Override public int getFailureCount() { return failureCount; } @Override public String toString() { return String.format(Locale.US, "%s %s", getShortStatusSummaryString(), testCaseName); } private String getShortStatusSummaryString() { if (isDryRun) { return "DRYRUN"; } if (failureCount > 0) { return "FAIL"; } if (passCount > 0) { return "PASS"; } if (skippedCount > 0) { if (hasAssumptionViolations) { return "ASSUME"; } else { return "SKIPPED"; } } return "NOTESTS"; } }