blob: 8f2b3da81ad97f425fe4634a5b14b6e077e0fcb3 [file] [log] [blame]
// 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);
}
}
}