blob: 2919c0206da52620e7268035075ac4125e478379 [file] [log] [blame]
// Copyright (C) 2019 The Android Open Source Project
//
// 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.google.gerrit.plugins.checks.api;
import com.google.common.collect.ImmutableListMultimap;
import java.util.Map;
/**
* Combined state of multiple checks on a change.
*
* <p>This state combines multiple {@link CheckState}s together with the required/optional bit
* associated with each check.
*
* <p>Ordering is not significant in this class, but for consistency's sake the ordering matches
* {@code CheckState} where applicable.
*/
public enum CombinedCheckState {
/** At least one required check failed; other checks may have passed, or still be running. */
FAILED(false),
/**
* All relevant checks terminated, and at least one optional check failed, but no required checks
* failed.
*
* <p>This state is considered {@link #isPassing() passing}, as in "checks passed with warnings."
*/
WARNING(true),
/**
* At least one relevant check is in a non-terminated state ({@link CheckState#NOT_STARTED},
* {@link CheckState#SCHEDULED}, {@link CheckState#RUNNING}), and no required checks failed. Some
* optional checks may have failed.
*/
IN_PROGRESS(false),
/** All relevant checks terminated successfully. */
SUCCESSFUL(true),
/** No checks are relevant to this change. */
NOT_RELEVANT(true);
/**
* Combines multiple per-check states into a single combined state.
*
* <p>See documentation of specific enum values for precise semantics.
*
* @param statesAndRequired map of state to a list of booleans, one per check, indicating whether
* that particular check is required in the context of a particular change.
* @return combined state.
*/
public static CombinedCheckState combine(
ImmutableListMultimap<CheckState, Boolean> statesAndRequired) {
int inProgressCount = 0;
int failedOptionalCount = 0;
int successfulCount = 0;
for (Map.Entry<CheckState, Boolean> e : statesAndRequired.entries()) {
CheckState state = e.getKey();
if (state.isInProgress()) {
inProgressCount++;
} else if (state == CheckState.FAILED) {
if (e.getValue()) {
return CombinedCheckState.FAILED;
}
failedOptionalCount++;
} else if (state == CheckState.SUCCESSFUL) {
successfulCount++;
} else if (state == CheckState.NOT_RELEVANT) {
continue;
} else {
throw new IllegalStateException("invalid state: " + state);
}
}
if (inProgressCount > 0) {
return IN_PROGRESS;
}
if (failedOptionalCount > 0) {
return WARNING;
}
if (successfulCount > 0) {
return SUCCESSFUL;
}
return NOT_RELEVANT;
}
private final boolean passing;
CombinedCheckState(boolean passing) {
this.passing = passing;
}
/**
* Returns whether the state represents a passing state.
*
* <p>A passing state is one that is either completed successfully with or without warnings
* ({@link #WARNING} or {@link #SUCCESSFUL}), or is simply {@link #NOT_RELEVANT}.
*
* @return whether the state represents a passing state.
*/
public boolean isPassing() {
return passing;
}
}