bigtop-master/bigtop-test-framework/src/main/groovy/org/apache/bigtop/itest/ParameterSetter.java
/**
 * 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
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * 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.bigtop.itest;

import java.lang.reflect.Field;

import static org.junit.Assert.assertNotNull;

/**
 * Class containing utility methods for test classes to use (in a static
 * setup method) for obtaining the values of parameters passed in via
 * environment variables or system properties. The parameters are obtained
 * by introspecting the {@link org.apache.bigtop.itest.Contract Contract}
 * annotation of the test class.
 */
public class ParameterSetter {

  /**
   * Sets the values of parameters passed in via environment variables, using
   * convention.
   * Assumes the presence in the target class of static fields (the parameters)
   * with the same names as the environment variables.
   * (Unix/Linux environment variable names shall consist solely of uppercase
   * letters, digits, and the '_' (underscore) character, and shall not begin
   * with a digit.)
   * If an environment variable is required and it is not set, an
   * AssertionError is thrown.
   *
   * @param target the test class
   * @throws NoSuchFieldException
   * @throws IllegalAccessException
   */
  public static void setEnv(Class target)
      throws NoSuchFieldException, IllegalAccessException {
    Contract contract = (Contract) target.getAnnotation(Contract.class);
    Variable[] vars = contract.env();
    for (int i = 0; i < vars.length; i++) {
      Variable var = vars[i];
      String name = var.name();
      Field field = target.getDeclaredField(name);
      String value = System.getenv(name);
      if (value == null && var.required()) {
        assertNotNull(name + " is not set", value);
      }
      field.setAccessible(true);
      field.set(target, value);
    }
  }

  /**
   * Sets the values of parameters passed in via environment variables.
   * Assumes the presence in the target class of static fields with the given
   * names.
   * If an environment variable is required and it is not set, an
   * AssertionError is thrown.
   *
   * @param target     the test class
   * @param fieldNames the names of the static fields corresponding to the
   *                   environment variables; the number of names must match the number of
   *                   environment variables
   * @throws NoSuchFieldException
   * @throws IllegalAccessException
   */
  public static void setEnv(Class target, String[] fieldNames)
      throws NoSuchFieldException, IllegalAccessException {
    Contract contract = (Contract) target.getAnnotation(Contract.class);
    Variable[] vars = contract.env();
    assert vars.length == fieldNames.length;
    for (int i = 0; i < vars.length; i++) {
      Variable var = vars[i];
      String name = var.name();
      Field field = target.getDeclaredField(fieldNames[i]);
      String value = System.getenv(name);
      if (value == null && var.required()) {
        assertNotNull(name + " is not set", value);
      }
      field.setAccessible(true);
      field.set(target, value);
    }
  }

  /**
   * Sets the values of parameters passed in via system properties, using
   * convention.
   * Assumes the presence in the target class of static fields (the parameters)
   * with the same names as the system properties, except with '.' replaced by
   * '_'. (The names of the system properties shall be chosen so that the
   * corresponding field names are valid Java identifiers.)
   * If a system property is not set, the parameter is set to a default value.
   * Therefore usable default values must be provided in the annotation or else
   * test logic must be written to handle the lack thereof.
   *
   * @param target the test class
   * @throws NoSuchFieldException
   * @throws IllegalAccessException
   */
  public static void setProperties(Class target)
      throws NoSuchFieldException, IllegalAccessException {
    Contract contract = (Contract) target.getAnnotation(Contract.class);
    Property[] props = contract.properties();
    for (int i = 0; i < props.length; i++) {
      Property prop = props[i];
      String name = prop.name();
      Field field = target.getDeclaredField(name.replace('.', '_'));
      Object value = null;
      switch (prop.type()) {
        case STRING:
          value = System.getProperty(name, prop.defaultValue());
          break;
        case INT:
          value = Integer.getInteger(name, prop.intValue());
          break;
        case LONG:
          value = Long.getLong(name, prop.longValue());
          break;
        case BOOLEAN:
          value = Boolean.getBoolean(name);
      }
      field.setAccessible(true);
      field.set(target, value);
    }
  }

  /**
   * Sets the values of parameters passed in via system properties.
   * Assumes the presence in the target class of static fields with the given
   * names.
   * If a system property is not set, the parameter is set to a default value.
   * Therefore usable default values must be provided in the annotation or else
   * test logic must be written to handle the lack thereof.
   *
   * @param target     the test class
   * @param fieldNames the names of the static fields corresponding to the
   *                   system properties; the number of names must match the number of
   *                   system properties
   * @throws NoSuchFieldException
   * @throws IllegalAccessException
   */
  public static void setProperties(Class target, String[] fieldNames)
      throws NoSuchFieldException, IllegalAccessException {
    Contract contract = (Contract) target.getAnnotation(Contract.class);
    Property[] props = contract.properties();
    assert props.length == fieldNames.length;
    for (int i = 0; i < props.length; i++) {
      Property prop = props[i];
      String name = prop.name();
      Field field = target.getDeclaredField(fieldNames[i]);
      Object value = null;
      switch (prop.type()) {
        case STRING:
          value = System.getProperty(name, prop.defaultValue());
          break;
        case INT:
          value = Integer.getInteger(name, prop.intValue());
          break;
        case LONG:
          value = Long.getLong(name, prop.longValue());
          break;
        case BOOLEAN:
          value = Boolean.getBoolean(name);
      }
      field.setAccessible(true);
      field.set(target, value);
    }
  }
}
