| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.brooklyn.test.framework; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| |
| import com.google.common.base.Joiner; |
| import com.google.common.base.Supplier; |
| import com.google.common.reflect.TypeToken; |
| |
| import org.apache.brooklyn.api.entity.Entity; |
| import org.apache.brooklyn.config.ConfigKey; |
| import org.apache.brooklyn.test.Asserts; |
| import org.apache.brooklyn.util.core.flags.TypeCoercions; |
| import org.apache.brooklyn.util.exceptions.CompoundRuntimeException; |
| import org.apache.brooklyn.util.exceptions.FatalConfigurationRuntimeException; |
| import org.apache.brooklyn.util.guava.Maybe; |
| import org.apache.brooklyn.util.text.Strings; |
| |
| |
| /** |
| * Utility class to evaluate test-framework assertions |
| * |
| * @author m4rkmckenna on 11/11/2015. |
| */ |
| public class TestFrameworkAssertions { |
| |
| public static final String IS_NULL = "isNull"; |
| public static final String NOT_NULL = "notNull"; |
| public static final String IS_EQUAL_TO = "isEqualTo"; |
| public static final String EQUAL_TO = "equalTo"; |
| public static final String EQUALS = "equals"; |
| public static final String MATCHES = "matches"; |
| public static final String CONTAINS = "contains"; |
| public static final String IS_EMPTY = "isEmpty"; |
| public static final String NOT_EMPTY = "notEmpty"; |
| public static final String HAS_TRUTH_VALUE = "hasTruthValue"; |
| public static final String UNKNOWN_CONDITION = "unknown condition"; |
| |
| |
| private TestFrameworkAssertions() { |
| } |
| |
| |
| /** |
| * Get assertions tolerantly from a configuration key. |
| * This supports either a simple map of assertions, such as |
| * |
| <pre> |
| assertOut: |
| contains: 2 users |
| matches: .*[\d]* days.* |
| </pre> |
| * or a list of such maps, (which allows you to repeat keys): |
| <pre> |
| assertOut: |
| - contains: 2 users |
| - contains: 2 days |
| </pre> |
| or |
| private static List<Map<String,Object>> getAssertions(ConfigKey<Object> key) { |
| } |
| */ |
| public static List<Map<String, Object>> getAssertions(Entity entity, ConfigKey<Object> key) { |
| Object config = entity.getConfig(key); |
| Maybe<Map<String, Object>> maybeMap = TypeCoercions.tryCoerce(config, new TypeToken<Map<String, Object>>() {}); |
| if (maybeMap.isPresent()) { |
| return Collections.singletonList(maybeMap.get()); |
| } |
| |
| Maybe<List<Map<String, Object>>> maybeList = TypeCoercions.tryCoerce(config, |
| new TypeToken<List<Map<String, Object>>>() {}); |
| if (maybeList.isPresent()) { |
| return maybeList.get(); |
| } |
| |
| throw new FatalConfigurationRuntimeException(key.getDescription() + " is not a map or list of maps"); |
| } |
| |
| |
| public static <T> void checkAssertions(Map<String,?> flags, |
| Map<String, Object> assertions, |
| String target, |
| final Supplier<T> actualSupplier) { |
| |
| AssertionSupport support = new AssertionSupport(); |
| checkAssertions(support, flags, assertions, target, actualSupplier); |
| support.validate(); |
| } |
| |
| |
| public static <T> void checkAssertions(Map<String,?> flags, |
| List<Map<String, Object>> assertions, |
| String target, |
| final Supplier<T> actualSupplier) { |
| |
| AssertionSupport support = new AssertionSupport(); |
| for (Map<String, Object> assertionMap : assertions) { |
| checkAssertions(support, flags, assertionMap, target, actualSupplier); |
| } |
| support.validate(); |
| } |
| |
| public static <T> void checkAssertions(final AssertionSupport support, |
| Map<String,?> flags, |
| final List<Map<String, Object>> assertions, |
| final String target, |
| final Supplier<T> actualSupplier) { |
| |
| for (Map<String, Object> assertionMap : assertions) { |
| checkAssertions(support, flags, assertionMap, target, actualSupplier); |
| } |
| } |
| |
| public static <T> void checkAssertions(final AssertionSupport support, |
| Map<String,?> flags, |
| final Map<String, Object> assertions, |
| final String target, |
| final Supplier<T> actualSupplier) { |
| |
| if (null == assertions) { |
| return; |
| } |
| try { |
| Asserts.succeedsEventually(flags, new Runnable() { |
| @Override |
| public void run() { |
| T actual = actualSupplier.get(); |
| checkActualAgainstAssertions(assertions, target, actual); |
| } |
| }); |
| } catch (Throwable t) { |
| support.fail(t); |
| } |
| } |
| |
| private static <T> void checkActualAgainstAssertions(Map<String, Object> assertions, |
| String target, T actual) { |
| for (Map.Entry<String, Object> assertion : assertions.entrySet()) { |
| String condition = assertion.getKey().toString(); |
| Object expected = assertion.getValue(); |
| switch (condition) { |
| |
| case IS_EQUAL_TO : |
| case EQUAL_TO : |
| case EQUALS : |
| if (null == actual || !actual.equals(expected)) { |
| failAssertion(target, EQUALS, expected); |
| } |
| break; |
| |
| case IS_NULL : |
| if (isTrue(expected) != (null == actual)) { |
| failAssertion(target, IS_NULL, expected); |
| } |
| break; |
| |
| case NOT_NULL : |
| if (isTrue(expected) != (null != actual)) { |
| failAssertion(target, NOT_NULL, expected); |
| } |
| break; |
| |
| case CONTAINS : |
| if (null == actual || !actual.toString().contains(expected.toString())) { |
| failAssertion(target, CONTAINS, expected); |
| } |
| break; |
| |
| case IS_EMPTY : |
| if (isTrue(expected) != (null == actual || Strings.isEmpty(actual.toString()))) { |
| failAssertion(target, IS_EMPTY, expected); |
| } |
| break; |
| |
| case NOT_EMPTY : |
| if (isTrue(expected) != ((null != actual && Strings.isNonEmpty(actual.toString())))) { |
| failAssertion(target, NOT_EMPTY, expected); |
| } |
| break; |
| |
| case MATCHES : |
| if (null == actual || !actual.toString().matches(expected.toString())) { |
| failAssertion(target, MATCHES, expected); |
| } |
| break; |
| |
| case HAS_TRUTH_VALUE : |
| if (isTrue(expected) != isTrue(actual)) { |
| failAssertion(target, HAS_TRUTH_VALUE, expected); |
| } |
| break; |
| |
| default: |
| failAssertion(target, UNKNOWN_CONDITION, condition); |
| } |
| } |
| } |
| |
| static void failAssertion(String target, String assertion, Object expected) { |
| throw new AssertionError(Joiner.on(' ').join( |
| null != target ? target : "null", |
| null != assertion ? assertion : "null", |
| null != expected ? expected : "null")); |
| } |
| |
| private static boolean isTrue(Object object) { |
| return null != object && Boolean.valueOf(object.toString()); |
| } |
| |
| /** |
| * A convenience to collect multiple assertion failures. |
| */ |
| public static class AssertionSupport { |
| private List<AssertionError> failures = new ArrayList<>(); |
| |
| public void fail(String target, String assertion, Object expected) { |
| failures.add(new AssertionError(Joiner.on(' ').join( |
| null != target ? target : "null", |
| null != assertion ? assertion : "null", |
| null != expected ? expected : "null"))); |
| } |
| |
| public void fail(Throwable throwable) { |
| failures.add(new AssertionError(throwable.getMessage(), throwable)); |
| } |
| |
| /** |
| * @throws AssertionError if any failures were collected. |
| */ |
| public void validate() { |
| if (0 < failures.size()) { |
| |
| if (1 == failures.size()) { |
| throw failures.get(0); |
| } |
| |
| StringBuilder builder = new StringBuilder(); |
| for (AssertionError assertionError : failures) { |
| builder.append(assertionError.getMessage()).append("\n"); |
| } |
| throw new AssertionError("Assertions failed:\n" + builder, new CompoundRuntimeException("Assertions", failures)); |
| } |
| } |
| } |
| } |