| /* |
| * 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.openjpa.persistence.test; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.BitSet; |
| import java.util.List; |
| |
| import org.apache.openjpa.persistence.jdbc.update.TestParentChild; |
| |
| /** |
| * Aids to run a single test under different combination of configuration |
| * parameters. |
| * |
| * Each configurable property can be registered to this receiver with all its |
| * possible values. This class generates all combinations of all the possible |
| * property values as configuration and invokes the same test with each |
| * configuration combination. |
| * The properties can be designated as <em>runtime</code> to be included in |
| * combination for execution but excluded from configuration. |
| * |
| * For example, |
| * @see TestParentChild |
| * |
| * @author Pinaki Poddar |
| * |
| */ |
| public class CombinatorialTestHelper { |
| private CombinationGenerator geneartor; |
| private List<String> propertyKeys; |
| private List currentOption; |
| private BitSet runtimeKeys = new BitSet(); |
| |
| private List[] combos; |
| private int cursor; |
| |
| public CombinatorialTestHelper() { |
| geneartor = new CombinationGenerator(); |
| propertyKeys = new ArrayList<>(); |
| currentOption = null; |
| runtimeKeys = new BitSet(); |
| combos = null; |
| cursor = 0; |
| } |
| |
| /** |
| * Generates the key-value property array as expected by its superclass |
| * by appending the current combinatorially generated properties. |
| * |
| * The important side effect of this method is to set the current |
| * configuration options. |
| * |
| * If no property is configured for combinatorial generation then returns |
| * the given list as it is. |
| * |
| */ |
| Object[] setCombinatorialOption(Object[] props) { |
| if (propertyKeys.isEmpty() || |
| propertyKeys.size() == runtimeKeys.cardinality()) |
| return props; |
| |
| if (combos == null) { |
| combos = geneartor.generate(); |
| cursor = 0; |
| } |
| // Each non-runtime property contributes a key-value pair |
| Object[] options = new Object[2*(propertyKeys.size()- |
| runtimeKeys.cardinality())]; |
| currentOption = combos[cursor++]; |
| int k = 0; |
| for (int i = 0; i < propertyKeys.size(); i++) { |
| if (runtimeKeys.get(i)) |
| continue; |
| options[k++] = propertyKeys.get(i); |
| options[k++] = currentOption.get(i); |
| } |
| if (props == null || props.length == 0) |
| return options; |
| |
| Object[] newProps = new Object[props.length + options.length]; |
| System.arraycopy(props, 0, newProps, 0, props.length); |
| System.arraycopy(options, 0, newProps, props.length, options.length); |
| return newProps; |
| } |
| |
| /** |
| * Adds options for the given configuration property. |
| */ |
| public void addOption(String property, Object[] options) { |
| addOption(property, options, false); |
| } |
| |
| /** |
| * Adds options for the given configuration property. |
| */ |
| public void addOption(String property, List options) { |
| addOption(property, options, false); |
| } |
| |
| /** |
| * Adds options for the given property. |
| * If runtime is true then this property is not added to configuration. |
| */ |
| public void addOption(String property, Object[] options, boolean runtime) { |
| addOption(property, Arrays.asList(options), runtime); |
| } |
| |
| /** |
| * Adds options for the given property. |
| * If runtime is true then this property is not added to configuration. |
| */ |
| public void addOption(String property, List options, boolean runtime) { |
| if (geneartor == null) { |
| geneartor = new CombinationGenerator(); |
| } |
| if (propertyKeys == null) { |
| propertyKeys = new ArrayList<>(); |
| } |
| if (!propertyKeys.contains(property)) { |
| geneartor.addDimension(options); |
| propertyKeys.add(property); |
| if (runtime) runtimeKeys.set(propertyKeys.size()-1); |
| } |
| } |
| |
| /** |
| * Gets the value of current option for the given key. |
| * Raises exception if the given key is not an option. |
| */ |
| public Object getOption(String key) { |
| int index = propertyKeys.indexOf(key); |
| if (index == -1) |
| throw new IllegalArgumentException("Unknown option " + key); |
| return currentOption.get(index); |
| } |
| |
| /** |
| * Gets the string value of current option for the given key. |
| * Raises exception if the given key is not an option. |
| */ |
| public String getOptionAsString(String key) { |
| return getOption(key).toString(); |
| } |
| |
| /** |
| * Gets the values of the current options. |
| */ |
| public List getOptions() { |
| return currentOption; |
| } |
| |
| /** |
| * Gets the key and values of the current options as printable string. |
| */ |
| public String getOptionsAsString() { |
| StringBuilder buf = new StringBuilder(); |
| for (int i = 0; i <propertyKeys.size(); i++) { |
| String key = propertyKeys.get(i); |
| if (!runtimeKeys.get(i)) |
| buf.append(key + " : " + getOption(key)).append("\r\n"); |
| } |
| for (int i = 0; i <propertyKeys.size(); i++) { |
| String key = propertyKeys.get(i); |
| if (runtimeKeys.get(i)) |
| buf.append("* " + key + " : " + getOption(key)).append("\r\n"); |
| } |
| return buf.toString(); |
| } |
| |
| /** |
| * Affirms if this receiver has more combinations. |
| */ |
| public boolean hasMoreCombination() { |
| return cursor < combos.length; |
| } |
| |
| /** |
| * Gets total number of combinations. |
| */ |
| public int getCombinationSize() { |
| return geneartor == null ? 0 : geneartor.getSize(); |
| } |
| } |