/**
* 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.sqoop.model;
import org.testng.annotations.Test;
import org.testng.Assert;
import org.testng.AssertJUnit;
import static org.testng.AssertJUnit.assertNull;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.sqoop.common.SqoopException;
/**
* Test config utils
*/
public class TestConfigUtils {
@Test
public void testConfigs() {
TestConfiguration config = new TestConfiguration();
config.aConfig.a1 = "value";
List<MConfig> configsByInstance = ConfigUtils.toConfigs(config);
AssertJUnit.assertEquals(getConfigs(), configsByInstance);
AssertJUnit.assertEquals("value", configsByInstance.get(0).getInputs().get(0).getValue());
List<MConfig> configsByClass = ConfigUtils.toConfigs(TestConfiguration.class);
AssertJUnit.assertEquals(getConfigs(), configsByClass);
List<MConfig> configsByBoth = ConfigUtils.toConfigs(TestConfiguration.class, config);
AssertJUnit.assertEquals(getConfigs(), configsByBoth);
AssertJUnit.assertEquals("value", configsByBoth.get(0).getInputs().get(0).getValue());
}
@Test(expectedExceptions = SqoopException.class)
public void testBadConfigInputsWithNonExisitingOverride() {
TestBadConfiguration config = new TestBadConfiguration();
config.aBadConfig.a1 = "value";
ConfigUtils.toConfigs(config);
}
@Test(expectedExceptions = SqoopException.class)
public void testBadConfigInputsWithBadOverride() {
TestBadConfiguration1 config = new TestBadConfiguration1();
config.aBadConfig1.a1 = "value";
ConfigUtils.toConfigs(config);
}
@Test(expectedExceptions = SqoopException.class)
public void testBadConfigInputsWithSelfOverride() {
TestBadConfiguration2 config = new TestBadConfiguration2();
config.aBadConfig2.a1 = "value";
ConfigUtils.toConfigs(config);
}
@Test
public void testConfigsMissingAnnotation() {
try {
ConfigUtils.toConfigs(ConfigWithoutAnnotation.class);
} catch (SqoopException ex) {
AssertJUnit.assertEquals(ModelError.MODEL_003, ex.getErrorCode());
return;
}
Assert.fail("Correct exception wasn't thrown");
}
@Test
public void testNonUniqueConfigNameAttributes() {
try {
ConfigUtils.toConfigs(ConfigurationWithNonUniqueConfigNameAttribute.class);
} catch (SqoopException ex) {
AssertJUnit.assertEquals(ModelError.MODEL_012, ex.getErrorCode());
return;
}
Assert.fail("Correct exception wasn't thrown");
}
@Test
public void testInvalidConfigNameAttribute() {
try {
ConfigUtils.toConfigs(ConfigurationWithInvalidConfigNameAttribute.class);
} catch (SqoopException ex) {
AssertJUnit.assertEquals(ModelError.MODEL_013, ex.getErrorCode());
return;
}
Assert.fail("Correct exception wasn't thrown");
}
@Test
public void testInvalidConfigNameAttributeLength() {
try {
ConfigUtils.toConfigs(ConfigurationWithInvalidConfigNameAttributeLength.class);
} catch (SqoopException ex) {
AssertJUnit.assertEquals(ModelError.MODEL_014, ex.getErrorCode());
return;
}
Assert.fail("Correct exception wasn't thrown");
}
@Test
public void testFailureOnPrimitiveType() {
PrimitiveConfig config = new PrimitiveConfig();
try {
ConfigUtils.toConfigs(config);
Assert.fail("We were expecting exception for unsupported type.");
} catch (SqoopException ex) {
AssertJUnit.assertEquals(ModelError.MODEL_007, ex.getErrorCode());
}
}
@Test
public void testFillValues() {
List<MConfig> configs = getConfigs();
((MStringInput) configs.get(0).getInputs().get(0)).setValue("value");
TestConfiguration config = new TestConfiguration();
ConfigUtils.fromConfigs(configs, config);
AssertJUnit.assertEquals("value", config.aConfig.a1);
}
@Test
public void testFromConfigWithClass() {
List<MConfig> configs = getConfigs();
((MStringInput) configs.get(0).getInputs().get(0)).setValue("value");
TestConfiguration config = (TestConfiguration) ConfigUtils.fromConfigs(configs,
TestConfiguration.class);
AssertJUnit.assertEquals("value", config.aConfig.a1);
}
@Test
public void testFillValuesObjectReuse() {
List<MConfig> configs = getConfigs();
((MStringInput) configs.get(0).getInputs().get(0)).setValue("value");
TestConfiguration config = new TestConfiguration();
config.aConfig.a2 = "x";
config.bConfig.b1 = "y";
ConfigUtils.fromConfigs(configs, config);
AssertJUnit.assertEquals("value", config.aConfig.a1);
assertNull(config.aConfig.a2);
assertNull(config.bConfig.b2);
assertNull(config.bConfig.b2);
}
@Test
public void testJson() {
TestConfiguration config = new TestConfiguration();
config.aConfig.a1 = "A";
config.bConfig.b2 = "B";
config.cConfig.longValue = 4L;
config.cConfig.map.put("C", "D");
config.cConfig.enumeration = Enumeration.X;
String json = ConfigUtils.toJson(config);
TestConfiguration targetConfig = new TestConfiguration();
// Old values from should be always removed
targetConfig.aConfig.a2 = "X";
targetConfig.bConfig.b1 = "Y";
// Nulls in configs shouldn't be an issue either
targetConfig.cConfig = null;
ConfigUtils.fillValues(json, targetConfig);
AssertJUnit.assertEquals("A", targetConfig.aConfig.a1);
assertNull(targetConfig.aConfig.a2);
assertNull(targetConfig.bConfig.b1);
AssertJUnit.assertEquals("B", targetConfig.bConfig.b2);
AssertJUnit.assertEquals((Long) 4L, targetConfig.cConfig.longValue);
AssertJUnit.assertEquals(1, targetConfig.cConfig.map.size());
AssertJUnit.assertTrue(targetConfig.cConfig.map.containsKey("C"));
AssertJUnit.assertEquals("D", targetConfig.cConfig.map.get("C"));
AssertJUnit.assertEquals(Enumeration.X, targetConfig.cConfig.enumeration);
}
/**
* Config structure that corresponds to Config class declared below
* @return Config structure
*/
protected List<MConfig> getConfigs() {
List<MConfig> ret = new LinkedList<MConfig>();
List<MInput<?>> inputs;
// Config A
inputs = new LinkedList<MInput<?>>();
inputs.add(new MStringInput("aConfig.a1", false, InputEditable.ANY, StringUtils.EMPTY,
(short) 30));
inputs.add(new MStringInput("aConfig.a2", true, InputEditable.ANY, StringUtils.EMPTY,
(short) -1));
ret.add(new MConfig("aConfig", inputs));
// Config B
inputs = new LinkedList<MInput<?>>();
inputs.add(new MStringInput("bConfig.b1", false, InputEditable.ANY, StringUtils.EMPTY,
(short) 2));
inputs.add(new MStringInput("bConfig.b2", false, InputEditable.ANY, StringUtils.EMPTY,
(short) 3));
ret.add(new MConfig("bConfig", inputs));
// Config C
inputs = new LinkedList<MInput<?>>();
inputs.add(new MLongInput("cConfig.longValue", false, InputEditable.ANY, StringUtils.EMPTY));
inputs.add(new MMapInput("cConfig.map", false, InputEditable.ANY, StringUtils.EMPTY));
inputs.add(new MEnumInput("cConfig.enumeration", false, InputEditable.ANY, StringUtils.EMPTY,
new String[] { "X", "Y" }));
ret.add(new MConfig("cConfig", inputs));
return ret;
}
protected List<MConfig> getBadConfigWithSelfOverrideInputs() {
List<MConfig> ret = new LinkedList<MConfig>();
List<MInput<?>> inputs;
// Config A
inputs = new LinkedList<MInput<?>>();
inputs.add(new MStringInput("aConfig.a1", false, InputEditable.ANY, "aConfig.a1", (short) 30));
inputs.add(new MStringInput("aConfig.a2", true, InputEditable.ANY, StringUtils.EMPTY,
(short) -1));
ret.add(new MConfig("aConfig", inputs));
return ret;
}
protected List<MConfig> getBadConfigWithNonExistingOverrideInputs() {
List<MConfig> ret = new LinkedList<MConfig>();
List<MInput<?>> inputs;
// Config A
inputs = new LinkedList<MInput<?>>();
inputs.add(new MStringInput("aConfig.a1", false, InputEditable.ANY, "aConfig.a3", (short) 30));
inputs.add(new MStringInput("aConfig.a2", true, InputEditable.ANY, StringUtils.EMPTY,
(short) -1));
ret.add(new MConfig("aConfig", inputs));
return ret;
}
protected List<MConfig> getBadConfigWithUserEditableOverrideInputs() {
List<MConfig> ret = new LinkedList<MConfig>();
List<MInput<?>> inputs;
// Config A
inputs = new LinkedList<MInput<?>>();
inputs.add(new MStringInput("aConfig.a1", false, InputEditable.ANY, "aConfig.a2", (short) 30));
inputs.add(new MStringInput("aConfig.a2", true, InputEditable.USER_ONLY, StringUtils.EMPTY,
(short) -1));
ret.add(new MConfig("aConfig", inputs));
return ret;
}
@ConfigurationClass
public static class ConfigurationWithNonUniqueConfigNameAttribute {
public ConfigurationWithNonUniqueConfigNameAttribute() {
aConfig = new InvalidConfig();
bConfig = new InvalidConfig();
}
@Config(name = "sameName")
InvalidConfig aConfig;
@Config(name = "sameName")
InvalidConfig bConfig;
}
@ConfigurationClass
public static class ConfigurationWithInvalidConfigNameAttribute {
public ConfigurationWithInvalidConfigNameAttribute() {
invalidConfig = new InvalidConfig();
}
@Config(name = "#_config")
InvalidConfig invalidConfig;
}
@ConfigurationClass
public static class ConfigurationWithInvalidConfigNameAttributeLength {
public ConfigurationWithInvalidConfigNameAttributeLength() {
invalidLengthConfig = new InvalidConfig();
}
@Config(name = "longest_config_more_than_30_characers")
InvalidConfig invalidLengthConfig;
}
@ConfigurationClass
public static class TestBadConfiguration {
public TestBadConfiguration() {
aBadConfig = new ABadConfig();
}
@Config
ABadConfig aBadConfig;
}
@ConfigurationClass
public static class TestBadConfiguration1 {
public TestBadConfiguration1() {
aBadConfig1 = new ABadConfig1();
}
@Config
ABadConfig1 aBadConfig1;
}
@ConfigurationClass
public static class TestBadConfiguration2 {
public TestBadConfiguration2() {
aBadConfig2 = new ABadConfig2();
}
@Config
ABadConfig2 aBadConfig2;
}
@ConfigurationClass
public static class TestConfiguration {
public TestConfiguration() {
aConfig = new AConfig();
bConfig = new BConfig();
cConfig = new CConfig();
}
@Config
AConfig aConfig;
@Config
BConfig bConfig;
@Config
CConfig cConfig;
}
@ConfigurationClass
public static class PrimitiveConfig {
@Config
DConfig dConfig;
}
@ConfigClass
public static class AConfig {
@Input(size = 30)
String a1;
@Input(sensitive = true)
String a2;
}
@ConfigClass
public static class ABadConfig {
@Input(size = 30, editable = InputEditable.USER_ONLY, overrides = "a5")
String a1;
@Input(sensitive = true)
String a2;
}
@ConfigClass
public static class ABadConfig1 {
@Input(size = 30, editable = InputEditable.USER_ONLY, overrides = "a2")
String a1;
@Input(sensitive = true, editable = InputEditable.USER_ONLY, overrides = "a1")
String a2;
}
@ConfigClass
public static class ABadConfig2 {
@Input(size = 30, editable = InputEditable.USER_ONLY, overrides = "a1")
String a1;
@Input(sensitive = true, editable = InputEditable.USER_ONLY, overrides = "a2")
String a2;
}
@ConfigClass
public static class BConfig {
@Input(size = 2)
String b1;
@Input(size = 3)
String b2;
}
@ConfigClass
public static class CConfig {
@Input
Long longValue;
@Input
Map<String, String> map;
@Input
Enumeration enumeration;
public CConfig() {
map = new HashMap<String, String>();
}
}
@ConfigClass
public static class InvalidConfig {
}
@ConfigClass
public static class DConfig {
@Input
int value;
}
public static class ConfigWithoutAnnotation {
}
enum Enumeration {
X, Y,
}
}