All Downloads are FREE. Search and download functionalities are using the official Maven repository.

reactor.test.MessageFormatter Maven / Gradle / Ivy

There is a newer version: 3.7.0
Show newest version
/*
 * Copyright (c) 2018-2021 VMware Inc. or its affiliates, All Rights Reserved.
 *
 * 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
 *
 *   https://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 reactor.test;

import java.util.Collection;
import java.util.Optional;
import java.util.function.Function;

import reactor.util.annotation.Nullable;

/**
 * A utility class to format error messages in all of the default implementation of {@link StepVerifier}.
 * Formats events and is capable of prepending messages with a {@link StepVerifierOptions#scenarioName(String) scenario name}.
 *
 * @author Simon Baslé
 */
final class MessageFormatter {

	private static final String                            EMPTY = "";

	final String scenarioPrefix;
	@Nullable
	final ValueFormatters.ToStringConverter valueFormatter;
	@Nullable
	final Collection> extractors;

	MessageFormatter(@Nullable final String scenarioName,
			@Nullable ValueFormatters.ToStringConverter valueFormatter,
			@Nullable Collection> extractors) {
		if (scenarioName == null || scenarioName.isEmpty()) {
			scenarioPrefix = EMPTY;
		}
		else {
			scenarioPrefix = "[" + scenarioName + "] ";
		}
		this.valueFormatter =  valueFormatter;
		this.extractors = extractors;
	}

	/**
	 * Format an event, message with argument placeholders (in the style of {@link String#format(String, Object...)})
	 * and produce an {@link AssertionError}.
	 *
	 * @param event the event that caused an expectation failure
	 * @param msg the message, possibly with {@link String#format(String, Object...)} style placeholders
	 * @param args the optional values for the placeholders in msg
	 * @return an {@link AssertionError} with a standardized message potentially prefixed with the associated scenario name
	 */
	AssertionError fail(@Nullable DefaultStepVerifierBuilder.Event event, String msg, Object... args) {
		String prefix;
		if (event != null && event.getDescription()
		                          .length() > 0) {
			prefix = String.format("expectation \"%s\" failed (", event.getDescription());
		}
		else {
			prefix = "expectation failed (";
		}

		return failPrefix(prefix, msg, args);
	}

	/**
	 * Format an event, message with argument placeholders (in the style of {@link String#format(String, Object...)})
	 * and produce an {@link AssertionError} wrapped in an {@link Optional}.
	 *
	 * @param event the event that caused an expectation failure
	 * @param msg the message, possibly with {@link String#format(String, Object...)} style placeholders
	 * @param args the optional values for the placeholders in msg
	 * @return an {@link AssertionError} with a standardized message potentially prefixed with the associated scenario name,
	 * wrapped in an {@link Optional}
	 */
	Optional failOptional(@Nullable DefaultStepVerifierBuilder.Event event, String msg,
			Object... args) {
		return Optional.of(fail(event, msg, args));
	}

	/**
	 * Formats a two-part message: a prefix that should end in an opening parenthesis and
	 * a second part with argument placeholders (in the style of {@link String#format(String, Object...)}).
	 * This method adds the closing parenthesis after that second part, and then produces
	 * an {@link AssertionError} out of the formatted message.
	 *
	 * @param prefix the first part of the message, should en with an opening parenthesis
	 * @param msg the second part (detail) of the message, possibly with {@link String#format(String, Object...)} style placeholders
	 * @param args the optional values for the placeholders in msg
	 * @return an {@link AssertionError} with a standardized message potentially prefixed with the associated scenario name
	 */
	AssertionError failPrefix(String prefix, String msg, Object... args) {
		String formattedMessage = format(msg, args);
		return assertionError(prefix + formattedMessage + ")");
	}

	/**
	 * Produce an {@link AssertionError} out of a given plain message, potentially prefixing
	 * it with the associated scenario name.
	 *
	 * @param msg the plain message
	 * @return an {@link AssertionError} with a standardized message potentially prefixed with the associated scenario name
	 */
	AssertionError assertionError(String msg) {
		return new AssertionError(scenarioPrefix + msg);
	}

	/**
	 * Produce an {@link AssertionError} out of a given plain message and a cause,
	 * potentially prefixing it with the associated scenario name.
	 *
	 * @param msg the plain message
	 * @param cause the cause to add to the {@link AssertionError}
	 * @return an {@link AssertionError} with a cause and a standardized message
	 * potentially prefixed with the associated scenario name
	 */
	AssertionError assertionError(String msg, @Nullable Throwable cause) {
		return new AssertionError(scenarioPrefix + msg, cause); //null cause is ok
	}

	/**
	 * Produce an arbitrary {@link Throwable} with a standardized message comprised of
	 * the given plain message and an optional prefix if the associated scenario is named.
	 *
	 * @param errorProducer the error producer (usually an Exception constructor method reference)
	 * @param message the plain message
	 * @param  the type of the {@link Exception}
	 * @return a {@link T} with a message potentially prefixed with the associated scenario name
	 */
	 T error(Function errorProducer, String message) {
		return errorProducer.apply(scenarioPrefix + message);
	}

	/**
	 * Format a message with placeholders (in the {@link String#format(String, Object...)}
	 * style), with a potential customization of each argument's {@link Object#toString() toString}.
	 *
	 * @param msg the message base, with placeholders for arguments
	 * @param args the arguments
	 * @return the formatted message
	 */
	String format(String msg, Object... args) {
		if (valueFormatter != null) {
			return String.format(msg, ValueFormatters.convertVarArgs(valueFormatter, extractors, args));
		}
		return String.format(msg, args);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy