| // Copyright 2011 The Bazel Authors. 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 |
| // |
| // 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.testing.junit.runner.util; |
| |
| import static com.google.testing.junit.runner.util.TestPropertyRunnerIntegration.getCallbackForThread; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| /** |
| * Exports test properties to the test XML. |
| */ |
| public class TestPropertyExporter { |
| /* |
| * The global {@code TestPropertyExporter}, which writes the properties into |
| * the test XML if the test is running from the command line.<p> |
| * |
| * If you have test infrastructure that needs to export properties, consider |
| * injecting an instance of {@code TestPropertyExporter}. Your tests can |
| * use one of the static methods in this class to create a fake instance. |
| */ |
| public static final TestPropertyExporter INSTANCE = new TestPropertyExporter( |
| new DefaultCallback()); |
| |
| // Set to 1000 so that it will play nice with code that doesn't use exportRepeatedProperty |
| // yet. |
| public static final int INITIAL_INDEX_FOR_REPEATED_PROPERTY = 1000; |
| |
| private final Callback callback; |
| |
| /** |
| * Creates a fake {@code TestPropertyExporter} instance, storing values |
| * in the passed-in map. |
| * |
| * @param backingMap Map to use to store values |
| * @return exporter instance |
| */ |
| public static TestPropertyExporter createFake(final Map<String, String> backingMap) { |
| return createFake(new Callback() { |
| |
| private final Map<String, Integer> repeatedPropertyNamesToRepetitions = new HashMap<>(); |
| |
| @Override public void exportProperty(String name, String value) { |
| backingMap.put(name, value); |
| } |
| |
| @Override |
| public String exportRepeatedProperty(String name, String value) { |
| String propertyName = getRepeatedPropertyName(name); |
| backingMap.put(propertyName, value); |
| return propertyName; |
| } |
| |
| private String getRepeatedPropertyName(String name) { |
| int index = addNameToRepeatedPropertyNamesAndGetRepetitionsNr(name) |
| + INITIAL_INDEX_FOR_REPEATED_PROPERTY; |
| return name + index; |
| } |
| |
| private synchronized int addNameToRepeatedPropertyNamesAndGetRepetitionsNr(String name) { |
| Integer previousRepetitionsNr = repeatedPropertyNamesToRepetitions.get(name); |
| if (previousRepetitionsNr == null) { |
| previousRepetitionsNr = 0; |
| } |
| repeatedPropertyNamesToRepetitions.put(name, previousRepetitionsNr + 1); |
| return previousRepetitionsNr; |
| } |
| }); |
| } |
| |
| /** |
| * Creates a fake {@code TestPropertyExporter} instance, passing values |
| * to the passed-in callback. |
| * |
| * @param callback Callback to use when values are exported |
| * @return exporter instance |
| */ |
| public static TestPropertyExporter createFake(final Callback callback) { |
| return new TestPropertyExporter(callback); |
| } |
| |
| protected TestPropertyExporter(Callback callback) { |
| this.callback = callback; |
| } |
| |
| /** |
| * Exports a property to the test runner. This method is a no-op unless called |
| * by the thread running the current test. |
| * |
| * @param name The property name. |
| * @param value The property value. |
| * @throws IllegalArgumentException if the name is not a valid name |
| */ |
| public void exportProperty(String name, String value) { |
| callback.exportProperty(name, value); |
| } |
| |
| /** |
| * Exports a property to the test runner by adding the value to the list of values for the |
| * given property name. |
| * When the properties get written to the XML, each name will have a numeric value appended to it |
| * that is guaranteed to be unique for the given test case. |
| * This method is a no-op unless called by the thread running the current test. |
| * |
| * @param name The property name. |
| * @param value The property value. |
| * @return the name of the property that was exported |
| * @throws IllegalArgumentException if the name is not a valid name |
| */ |
| public String exportRepeatedProperty(String name, String value) { |
| return callback.exportRepeatedProperty(name, value); |
| } |
| |
| /** |
| * Callback that is used to store test properties. |
| */ |
| public interface Callback { |
| |
| /** |
| * Export the property. |
| * |
| * @param name The property name. |
| * @param value The property value. |
| */ |
| void exportProperty(String name, String value); |
| |
| /** |
| * Export the property with an incrementing numeric suffix. |
| * |
| * @param name The property name. |
| * @param value The property value. |
| * @return the name of the property that was exported |
| */ |
| String exportRepeatedProperty(String name, String value); |
| } |
| |
| |
| /** |
| * Default callback implementation. |
| * Calls the test runner to write the property to the XML. |
| */ |
| private static class DefaultCallback implements Callback { |
| |
| @Override |
| public void exportProperty(String name, String value) { |
| getCallbackForThread().exportProperty(name, value); |
| } |
| |
| @Override |
| public String exportRepeatedProperty(String name, String value) { |
| return getCallbackForThread().exportRepeatedProperty(name, value); |
| } |
| } |
| } |