diff --git a/shell/src/main/java/org/apache/sqoop/shell/CloneJobFunction.java b/shell/src/main/java/org/apache/sqoop/shell/CloneJobFunction.java index b28ece28..ecea579e 100644 --- a/shell/src/main/java/org/apache/sqoop/shell/CloneJobFunction.java +++ b/shell/src/main/java/org/apache/sqoop/shell/CloneJobFunction.java @@ -60,7 +60,7 @@ public Object executeFunction(CommandLine line, boolean isInteractive) throws IO private Status cloneJob(String jobArg, List args, boolean isInteractive) throws IOException { printlnResource(Constants.RES_CLONE_CLONING_JOB, jobArg); - ConsoleReader reader = new ConsoleReader(); + ConsoleReader reader = getConsoleReader(); MJob job = client.getJob(jobArg); job.setPersistenceId(MPersistableEntity.PERSISTANCE_ID_DEFAULT); diff --git a/shell/src/main/java/org/apache/sqoop/shell/CloneLinkFunction.java b/shell/src/main/java/org/apache/sqoop/shell/CloneLinkFunction.java index b76346b4..b46a19f9 100644 --- a/shell/src/main/java/org/apache/sqoop/shell/CloneLinkFunction.java +++ b/shell/src/main/java/org/apache/sqoop/shell/CloneLinkFunction.java @@ -61,15 +61,15 @@ public Object executeFunction(CommandLine line, boolean isInteractive) throws IO private Status cloneLink(String linkArg, List args, boolean isInteractive) throws IOException { printlnResource(Constants.RES_CLONE_CLONING_LINK, linkArg); - ConsoleReader reader = new ConsoleReader(); + ConsoleReader reader = getConsoleReader(); - MLink connection = client.getLink(linkArg); + MLink link = client.getLink(linkArg); // Remove persistent id as we're making a clone - connection.setPersistenceId(MPersistableEntity.PERSISTANCE_ID_DEFAULT); + link.setPersistenceId(MPersistableEntity.PERSISTANCE_ID_DEFAULT); Status status = Status.OK; - ResourceBundle linkConfigBundle = client.getConnectorConfigBundle(connection.getConnectorId()); + ResourceBundle linkConfigBundle = client.getConnectorConfigBundle(link.getConnectorId()); if (isInteractive) { printlnResource(Constants.RES_PROMPT_UPDATE_LINK_CONFIG); @@ -81,29 +81,29 @@ private Status cloneLink(String linkArg, List args, boolean isInteractiv } // Fill in data from user - if(!fillLinkWithBundle(reader, connection, linkConfigBundle)) { + if(!fillLinkWithBundle(reader, link, linkConfigBundle)) { return null; } - status = client.saveLink(connection); + status = client.saveLink(link); } while(!status.canProceed()); } else { LinkDynamicConfigOptions options = new LinkDynamicConfigOptions(); - options.prepareOptions(connection); + options.prepareOptions(link); CommandLine line = ConfigOptions.parseOptions(options, 0, args, false); - if (fillLink(line, connection)) { - status = client.saveLink(connection); + if (fillLink(line, link)) { + status = client.saveLink(link); if (!status.canProceed()) { - printLinkValidationMessages(connection); + printLinkValidationMessages(link); return null; } } else { - printLinkValidationMessages(connection); + printLinkValidationMessages(link); return null; } } - printlnResource(Constants.RES_CLONE_LINK_SUCCESSFUL, status.name(), connection.getPersistenceId()); + printlnResource(Constants.RES_CLONE_LINK_SUCCESSFUL, status.name(), link.getPersistenceId()); return status; } diff --git a/shell/src/main/java/org/apache/sqoop/shell/CreateJobFunction.java b/shell/src/main/java/org/apache/sqoop/shell/CreateJobFunction.java index 4a520d75..03ceaba7 100644 --- a/shell/src/main/java/org/apache/sqoop/shell/CreateJobFunction.java +++ b/shell/src/main/java/org/apache/sqoop/shell/CreateJobFunction.java @@ -73,7 +73,7 @@ public Object executeFunction(CommandLine line, boolean isInteractive) throws IO private Status createJob(String fromLinkArg, String toLinkArg, List args, boolean isInteractive) throws IOException { printlnResource(Constants.RES_CREATE_CREATING_JOB, fromLinkArg, toLinkArg); - ConsoleReader reader = new ConsoleReader(); + ConsoleReader reader = getConsoleReader(); MJob job = getClient().createJob(fromLinkArg, toLinkArg); MConnector fromConnector = getClient().getConnector(job.getFromConnectorId()); diff --git a/shell/src/main/java/org/apache/sqoop/shell/CreateLinkFunction.java b/shell/src/main/java/org/apache/sqoop/shell/CreateLinkFunction.java index 224f8444..e3928463 100644 --- a/shell/src/main/java/org/apache/sqoop/shell/CreateLinkFunction.java +++ b/shell/src/main/java/org/apache/sqoop/shell/CreateLinkFunction.java @@ -86,7 +86,7 @@ private Status createLink(CommandLine line, List args, boolean isInterac printlnResource(Constants.RES_CREATE_CREATING_LINK, connectorName); } - ConsoleReader reader = new ConsoleReader(); + ConsoleReader reader = getConsoleReader(); ResourceBundle connectorConfigBundle = getClient().getConnectorConfigBundle(cid); diff --git a/shell/src/main/java/org/apache/sqoop/shell/ShellEnvironment.java b/shell/src/main/java/org/apache/sqoop/shell/ShellEnvironment.java index b08fdcf8..55a0f279 100644 --- a/shell/src/main/java/org/apache/sqoop/shell/ShellEnvironment.java +++ b/shell/src/main/java/org/apache/sqoop/shell/ShellEnvironment.java @@ -23,12 +23,15 @@ import org.apache.sqoop.shell.core.Constants; import org.codehaus.groovy.tools.shell.IO; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.text.MessageFormat; import java.util.Locale; import java.util.ResourceBundle; +import jline.ConsoleReader; + /** * Static internal environment of the shell shared across all commands and * functions. @@ -56,6 +59,7 @@ private ShellEnvironment() { static ResourceBundle resource = ResourceBundle.getBundle(Constants.RESOURCE_NAME, Locale.getDefault()); static SqoopClient client = new SqoopClient(getServerUrl()); static IO io; + static ConsoleReader consoleReader; public static String getEnv(String variable, String defaultValue) { String value = System.getenv(variable); @@ -169,6 +173,18 @@ public static long getPollTimeout() { return pollTimeout; } + public static void setConsoleReader(ConsoleReader reader) { + consoleReader = reader; + } + + @edu.umd.cs.findbugs.annotations.SuppressWarnings({"LI_LAZY_INIT_STATIC"}) + public static ConsoleReader getConsoleReader() throws IOException { + if (consoleReader == null) { + consoleReader = new ConsoleReader(); + } + return consoleReader; + } + public static String resourceString(String resourceName) { return resource.getString(resourceName); } diff --git a/shell/src/main/java/org/apache/sqoop/shell/UpdateJobFunction.java b/shell/src/main/java/org/apache/sqoop/shell/UpdateJobFunction.java index ba85d636..fe6a1557 100644 --- a/shell/src/main/java/org/apache/sqoop/shell/UpdateJobFunction.java +++ b/shell/src/main/java/org/apache/sqoop/shell/UpdateJobFunction.java @@ -61,7 +61,7 @@ public Object executeFunction(CommandLine line, boolean isInteractive) throws IO private Status updateJob(String jobArg, List args, boolean isInteractive) throws IOException { printlnResource(Constants.RES_SQOOP_UPDATING_JOB, jobArg); - ConsoleReader reader = new ConsoleReader(); + ConsoleReader reader = getConsoleReader(); // TODO(SQOOP-1634): using from/to and driver config id, this call can be avoided MJob job = client.getJob(jobArg); diff --git a/shell/src/main/java/org/apache/sqoop/shell/UpdateLinkFunction.java b/shell/src/main/java/org/apache/sqoop/shell/UpdateLinkFunction.java index e815220f..c5359ce4 100644 --- a/shell/src/main/java/org/apache/sqoop/shell/UpdateLinkFunction.java +++ b/shell/src/main/java/org/apache/sqoop/shell/UpdateLinkFunction.java @@ -60,7 +60,7 @@ public Object executeFunction(CommandLine line, boolean isInteractive) throws IO private Status updateLink(String linkArg, List args, boolean isInteractive) throws IOException { printlnResource(Constants.RES_SQOOP_UPDATING_LINK, linkArg); - ConsoleReader reader = new ConsoleReader(); + ConsoleReader reader = getConsoleReader(); // TODO(SQOOP-1634): using link config id, this call can be avoided MLink link = client.getLink(linkArg); diff --git a/shell/src/test/java/org/apache/sqoop/shell/TestCloneCommand.java b/shell/src/test/java/org/apache/sqoop/shell/TestCloneCommand.java index f7f44a5a..c45501c9 100644 --- a/shell/src/test/java/org/apache/sqoop/shell/TestCloneCommand.java +++ b/shell/src/test/java/org/apache/sqoop/shell/TestCloneCommand.java @@ -21,19 +21,43 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; import java.util.HashMap; +import java.util.List; +import java.util.ResourceBundle; +import jline.ConsoleReader; + +import org.apache.commons.lang.StringUtils; import org.apache.sqoop.client.SqoopClient; import org.apache.sqoop.common.SqoopException; +import org.apache.sqoop.model.InputEditable; +import org.apache.sqoop.model.MBooleanInput; import org.apache.sqoop.model.MConfig; +import org.apache.sqoop.model.MDateTimeInput; import org.apache.sqoop.model.MDriverConfig; +import org.apache.sqoop.model.MEnumInput; import org.apache.sqoop.model.MFromConfig; +import org.apache.sqoop.model.MInput; +import org.apache.sqoop.model.MIntegerInput; import org.apache.sqoop.model.MJob; import org.apache.sqoop.model.MLink; import org.apache.sqoop.model.MLinkConfig; +import org.apache.sqoop.model.MListInput; +import org.apache.sqoop.model.MLongInput; +import org.apache.sqoop.model.MMapInput; +import org.apache.sqoop.model.MStringInput; import org.apache.sqoop.model.MToConfig; import org.apache.sqoop.model.MValidator; import org.apache.sqoop.shell.core.Constants; @@ -41,22 +65,41 @@ import org.apache.sqoop.utils.MapResourceBundle; import org.apache.sqoop.validation.Status; import org.codehaus.groovy.tools.shell.Groovysh; -import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class TestCloneCommand { CloneCommand cloneCmd; SqoopClient client; + ConsoleReader reader; + ResourceBundle resourceBundle; + ByteArrayInputStream in; + byte[] data; @BeforeTest(alwaysRun = true) - public void setup() { + public void setup() throws IOException { Groovysh shell = new Groovysh(); cloneCmd = new CloneCommand(shell); ShellEnvironment.setInteractive(false); ShellEnvironment.setIo(shell.getIo()); client = mock(SqoopClient.class); ShellEnvironment.setClient(client); + + data = new byte[1000]; + in = new ByteArrayInputStream(data); + reader = new ConsoleReader(in, new OutputStreamWriter(System.out)); + ShellEnvironment.setConsoleReader(reader); + resourceBundle = new ResourceBundle() { + @Override + protected Object handleGetObject(String key) { + return "fake_translated_value"; + } + + @Override + public Enumeration getKeys() { + return Collections.emptyEnumeration(); + } + }; } @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -69,27 +112,62 @@ public void testCloneLink() { // clone link -lid link_test Status status = (Status) cloneCmd.execute(Arrays.asList(Constants.FN_LINK, "-lid", "link_test")); - Assert.assertTrue(status != null && status == Status.OK); + assertTrue(status != null && status == Status.OK); // Missing argument for option lid try { cloneCmd.execute(Arrays.asList(Constants.FN_LINK, "-lid")); - Assert.fail("Update link should fail as parameters aren't complete!"); + fail("Update link should fail as parameters aren't complete!"); } catch (SqoopException e) { - Assert.assertEquals(ShellError.SHELL_0003, e.getErrorCode()); - Assert.assertTrue(e.getMessage().contains("Missing argument for option")); + assertEquals(ShellError.SHELL_0003, e.getErrorCode()); + assertTrue(e.getMessage().contains("Missing argument for option")); } // Missing option lid try { cloneCmd.execute(Arrays.asList(Constants.FN_LINK)); - Assert.fail("Update link should fail as option lid is missing"); + fail("Update link should fail as option lid is missing"); } catch (SqoopException e) { - Assert.assertEquals(ShellError.SHELL_0003, e.getErrorCode()); - Assert.assertTrue(e.getMessage().contains("Missing required option")); + assertEquals(ShellError.SHELL_0003, e.getErrorCode()); + assertTrue(e.getMessage().contains("Missing required option")); } } + @Test + public void testCloneLinkInteractive() { + ShellEnvironment.setInteractive(true); + initEnv(); + MLink link = new MLink(1, new MLinkConfig(getConfig("CONFIGFROMNAME"), new ArrayList())); + when(client.getLink("link_test")).thenReturn(link); + when(client.getConnectorConfigBundle(1L)).thenReturn(resourceBundle); + when(client.saveLink(link)).thenReturn(Status.OK); + + // clone link -lid link_test + initData("linkname\r" + // link name + "abc\r" + // for input with name "String" + "12345\r" + // for input with name "Integer" + "56789\r" + // for input with name "Long" + "true\r" + // for input with name "Boolean" + "k1=v1\rk2=v2\r\r" + // for input with name "Map" + "0\r" + // for input with name "Enum" + "l1\rl2\rl3\r\r" + // for input with name "List" + "12345678\r"); // for input with name "DateTime" + Status status = (Status) cloneCmd.execute(Arrays.asList(Constants.FN_LINK, "-lid", "link_test")); + assertTrue(status != null && status == Status.OK); + assertEquals(link.getName(), "linkname"); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getStringInput("CONFIGFROMNAME.String").getValue(), "abc"); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getIntegerInput("CONFIGFROMNAME.Integer").getValue().intValue(), 12345); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getLongInput("CONFIGFROMNAME.Long").getValue().longValue(), 56789); + assertTrue((link.getConnectorLinkConfig("CONFIGFROMNAME").getBooleanInput("CONFIGFROMNAME.Boolean").getValue())); + HashMap map = new HashMap(); + map.put("k1", "v1"); + map.put("k2", "v2"); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getMapInput("CONFIGFROMNAME.Map").getValue(), map); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getEnumInput("CONFIGFROMNAME.Enum").getValue(), "YES"); + assertEquals(StringUtils.join(link.getConnectorLinkConfig("CONFIGFROMNAME").getListInput("CONFIGFROMNAME.List").getValue(), "&"), "l1&l2&l3"); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getDateTimeInput("CONFIGFROMNAME.DateTime").getValue().getMillis(), 12345678); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void testCloneJob() { @@ -102,26 +180,141 @@ public void testCloneJob() { when(client.getDriverConfigBundle()).thenReturn(new MapResourceBundle(new HashMap())); when(client.saveJob(job)).thenReturn(Status.OK); - // update job -jid job_test + // clone job -jid job_test Status status = (Status) cloneCmd.execute(Arrays.asList(Constants.FN_JOB, "-jid", "job_test")); - Assert.assertTrue(status != null && status == Status.OK); + assertTrue(status != null && status == Status.OK); // Missing argument for option jid try { cloneCmd.execute(Arrays.asList(Constants.FN_JOB, "-jid")); - Assert.fail("Update job should fail as parameters aren't complete!"); + fail("Update job should fail as parameters aren't complete!"); } catch (SqoopException e) { - Assert.assertEquals(ShellError.SHELL_0003, e.getErrorCode()); - Assert.assertTrue(e.getMessage().contains("Missing argument for option")); + assertEquals(ShellError.SHELL_0003, e.getErrorCode()); + assertTrue(e.getMessage().contains("Missing argument for option")); } // Missing option jid try { cloneCmd.execute(Arrays.asList(Constants.FN_JOB)); - Assert.fail("Update job should fail as option jid is missing"); + fail("Update job should fail as option jid is missing"); } catch (SqoopException e) { - Assert.assertEquals(ShellError.SHELL_0003, e.getErrorCode()); - Assert.assertTrue(e.getMessage().contains("Missing required option")); + assertEquals(ShellError.SHELL_0003, e.getErrorCode()); + assertTrue(e.getMessage().contains("Missing required option")); + } + } + + @Test + public void testCloneJobInteractive() { + ShellEnvironment.setInteractive(true); + initEnv(); + MJob job = new MJob(1, 2, 1, 2, new MFromConfig(getConfig("fromJobConfig"), new ArrayList()), + new MToConfig(getConfig("toJobConfig"), new ArrayList()), + new MDriverConfig(getConfig("driverConfig"), new ArrayList())); + when(client.getJob("job_test")).thenReturn(job); + when(client.getConnectorConfigBundle(any(Long.class))).thenReturn(resourceBundle); + when(client.getDriverConfigBundle()).thenReturn(resourceBundle); + when(client.saveJob(job)).thenReturn(Status.OK); + + // clone job -jid job_test + initData("jobname\r" + // job name + // From job config + "abc\r" + // for input with name "String" + "12345\r" + // for input with name "Integer" + "56789\r" + // for input with name "Long" + "true\r" + // for input with name "Boolean" + "k1=v1\rk2=v2\r\r" + // for input with name "Map" + "0\r" + // for input with name "Enum" + "l1\rl2\rl3\r\r" + // for input with name "List" + "12345678\r" + // for input with name "DateTime" + + // To job config + "def\r" + // for input with name "String" + "11111\r" + // for input with name "Integer" + "22222\r" + // for input with name "Long" + "false\r" + // for input with name "Boolean" + "k3=v3\rk4=v4\r\r" + // for input with name "Map" + "1\r" + // for input with name "Enum" + "l4\rl5\rl6\r\r" + // for input with name "List" + "1234567\r" + // for input with name "DateTime" + + // Driver config + "hij\r" + // for input with name "String" + "33333\r" + // for input with name "Integer" + "44444\r" + // for input with name "Long" + "true\r" + // for input with name "Boolean" + "k1=v1\r\r" + // for input with name "Map" + "0\r" + // for input with name "Enum" + "l1\rl2\rl3\r\r" + // for input with name "List" + "7654321\r"); // for input with name "DateTime" + Status status = (Status) cloneCmd.execute(Arrays.asList(Constants.FN_JOB, "-jid", "job_test")); + assertTrue(status != null && status == Status.OK); + assertEquals(job.getName(), "jobname"); + // check from job config + assertEquals(job.getFromJobConfig().getStringInput("fromJobConfig.String").getValue(), "abc"); + assertEquals(job.getFromJobConfig().getIntegerInput("fromJobConfig.Integer").getValue().intValue(), 12345); + assertEquals((job.getFromJobConfig().getLongInput("fromJobConfig.Long").getValue()).longValue(), 56789); + assertTrue((job.getFromJobConfig().getBooleanInput("fromJobConfig.Boolean").getValue())); + HashMap map = new HashMap(); + map.put("k1", "v1"); + map.put("k2", "v2"); + assertEquals(job.getFromJobConfig().getMapInput("fromJobConfig.Map").getValue(), map); + assertEquals(job.getFromJobConfig().getEnumInput("fromJobConfig.Enum").getValue(), "YES"); + assertEquals(StringUtils.join(job.getFromJobConfig().getListInput("fromJobConfig.List").getValue(), "&"), "l1&l2&l3"); + assertEquals(job.getFromJobConfig().getDateTimeInput("fromJobConfig.DateTime").getValue().getMillis(), 12345678); + + // check to job config + assertEquals(job.getToJobConfig().getStringInput("toJobConfig.String").getValue(), "def"); + assertEquals(job.getToJobConfig().getIntegerInput("toJobConfig.Integer").getValue().intValue(), 11111); + assertEquals(job.getToJobConfig().getLongInput("toJobConfig.Long").getValue().longValue(), 22222); + assertFalse(job.getToJobConfig().getBooleanInput("toJobConfig.Boolean").getValue()); + map = new HashMap(); + map.put("k3", "v3"); + map.put("k4", "v4"); + assertEquals(job.getToJobConfig().getMapInput("toJobConfig.Map").getValue(), map); + assertEquals(job.getToJobConfig().getEnumInput("toJobConfig.Enum").getValue(), "NO"); + assertEquals(StringUtils.join(job.getToJobConfig().getListInput("toJobConfig.List").getValue(), "&"), "l4&l5&l6"); + assertEquals(job.getToJobConfig().getDateTimeInput("toJobConfig.DateTime").getValue().getMillis(), 1234567); + + // check driver config + assertEquals(job.getDriverConfig().getStringInput("driverConfig.String").getValue(), "hij"); + assertEquals(job.getDriverConfig().getIntegerInput("driverConfig.Integer").getValue().intValue(), 33333); + assertEquals(job.getDriverConfig().getLongInput("driverConfig.Long").getValue().longValue(), 44444); + assertTrue(job.getDriverConfig().getBooleanInput("driverConfig.Boolean").getValue()); + map = new HashMap(); + map.put("k1", "v1"); + assertEquals(job.getDriverConfig().getMapInput("driverConfig.Map").getValue(), map); + assertEquals(job.getDriverConfig().getEnumInput("driverConfig.Enum").getValue(), "YES"); + assertEquals(StringUtils.join(job.getDriverConfig().getListInput("driverConfig.List").getValue(), "&"), "l1&l2&l3"); + assertEquals(job.getDriverConfig().getDateTimeInput("driverConfig.DateTime").getValue().getMillis(), 7654321); + } + + @SuppressWarnings("unchecked") + private List getConfig(String configName) { + List> list = new ArrayList>(); + list.add(new MStringInput(configName + "." + "String", false, InputEditable.ANY, StringUtils.EMPTY, (short)30, Collections.EMPTY_LIST)); + list.add(new MIntegerInput(configName + "." + "Integer", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MLongInput(configName + "." + "Long", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MBooleanInput(configName + "." + "Boolean", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MMapInput(configName + "." + "Map", false, InputEditable.ANY, StringUtils.EMPTY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MEnumInput(configName + "." + "Enum", false, InputEditable.ANY, StringUtils.EMPTY, new String[] {"YES", "NO"}, Collections.EMPTY_LIST)); + list.add(new MListInput(configName + "." + "List", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MDateTimeInput(configName + "." + "DateTime", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + + List configs = new ArrayList(); + configs.add(new MConfig(configName, list, Collections.EMPTY_LIST)); + return configs; + } + + private void initData(String destData) { + byte[] destDataBytes = destData.getBytes(); + System.arraycopy(destDataBytes, 0, data, 0, destDataBytes.length); + in.reset(); + } + + private void initEnv() { + in.reset(); + for (int i = 0; i < data.length; i++) { + data[i] = '\0'; } } } diff --git a/shell/src/test/java/org/apache/sqoop/shell/TestCreateCommand.java b/shell/src/test/java/org/apache/sqoop/shell/TestCreateCommand.java index e0788ccb..2f91897f 100644 --- a/shell/src/test/java/org/apache/sqoop/shell/TestCreateCommand.java +++ b/shell/src/test/java/org/apache/sqoop/shell/TestCreateCommand.java @@ -18,44 +18,88 @@ package org.apache.sqoop.shell; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.ResourceBundle; +import jline.ConsoleReader; + +import org.apache.commons.lang.StringUtils; import org.apache.sqoop.client.SqoopClient; import org.apache.sqoop.common.SqoopException; +import org.apache.sqoop.model.InputEditable; +import org.apache.sqoop.model.MBooleanInput; import org.apache.sqoop.model.MConfig; import org.apache.sqoop.model.MConnector; +import org.apache.sqoop.model.MDateTimeInput; import org.apache.sqoop.model.MDriverConfig; +import org.apache.sqoop.model.MEnumInput; import org.apache.sqoop.model.MFromConfig; +import org.apache.sqoop.model.MInput; +import org.apache.sqoop.model.MIntegerInput; import org.apache.sqoop.model.MJob; import org.apache.sqoop.model.MLink; import org.apache.sqoop.model.MLinkConfig; +import org.apache.sqoop.model.MListInput; +import org.apache.sqoop.model.MLongInput; +import org.apache.sqoop.model.MMapInput; +import org.apache.sqoop.model.MStringInput; import org.apache.sqoop.model.MToConfig; import org.apache.sqoop.model.MValidator; import org.apache.sqoop.shell.core.Constants; import org.apache.sqoop.shell.core.ShellError; import org.apache.sqoop.validation.Status; import org.codehaus.groovy.tools.shell.Groovysh; -import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class TestCreateCommand { CreateCommand createCmd; SqoopClient client; + ConsoleReader reader; + ResourceBundle resourceBundle; + ByteArrayInputStream in; + byte[] data; @BeforeTest(alwaysRun = true) - public void setup() { + public void setup() throws IOException { Groovysh shell = new Groovysh(); createCmd = new CreateCommand(shell); ShellEnvironment.setInteractive(false); ShellEnvironment.setIo(shell.getIo()); client = mock(SqoopClient.class); ShellEnvironment.setClient(client); + + data = new byte[1000]; + in = new ByteArrayInputStream(data); + reader = new ConsoleReader(in, new OutputStreamWriter(System.out)); + ShellEnvironment.setConsoleReader(reader); + resourceBundle = new ResourceBundle() { + @Override + protected Object handleGetObject(String key) { + return "fake_translated_value"; + } + + @Override + public Enumeration getKeys() { + return Collections.emptyEnumeration(); + } + }; } @Test @@ -66,19 +110,19 @@ public void testCreateLink() { // create link -c connector_test Status status = (Status) createCmd.execute(Arrays.asList(Constants.FN_LINK, "-c", "connector_test")); - Assert.assertTrue(status != null && status == Status.OK); + assertTrue(status != null && status == Status.OK); // create link -cid connector_test status = (Status) createCmd.execute(Arrays.asList(Constants.FN_LINK, "-cid", "connector_test")); - Assert.assertTrue(status != null && status == Status.OK); + assertTrue(status != null && status == Status.OK); // incorrect command: create link -c try { status = (Status) createCmd.execute(Arrays.asList(Constants.FN_LINK, "-c")); - Assert.fail("Create link should fail as connector id/name is missing!"); + fail("Create link should fail as connector id/name is missing!"); } catch (SqoopException e) { - Assert.assertEquals(ShellError.SHELL_0003, e.getErrorCode()); - Assert.assertTrue(e.getMessage().contains("Missing argument for option")); + assertEquals(ShellError.SHELL_0003, e.getErrorCode()); + assertTrue(e.getMessage().contains("Missing argument for option")); } } @@ -89,12 +133,48 @@ public void testCreateLinkWithNonExistingConnector() { try { createCmd.execute(Arrays.asList(Constants.FN_LINK, "-c", "connector_test")); - Assert.fail("Create link should fail as requested connector doesn't exist!"); + fail("Create link should fail as requested connector doesn't exist!"); } catch (SqoopException e) { - Assert.assertEquals(TestShellError.TEST_SHELL_0000, e.getErrorCode()); + assertEquals(TestShellError.TEST_SHELL_0000, e.getErrorCode()); } } + @Test + public void testCreateLinkInteractive() { + ShellEnvironment.setInteractive(true); + initEnv(); + when(client.getConnector("connector_test")).thenReturn(new MConnector("", "", "", null, null, null)); + MLink link = new MLink(1, new MLinkConfig(getConfig("CONFIGFROMNAME"), new ArrayList())); + when(client.createLink("connector_test")).thenReturn(link); + when(client.saveLink(any(MLink.class))).thenReturn(Status.OK); + when(client.getConnectorConfigBundle(any(Long.class))).thenReturn(resourceBundle); + + // create link -c connector_test + initData("linkname\r" + // link name + "abc\r" + // for input with name "String" + "12345\r" + // for input with name "Integer" + "56789\r" + // for input with name "Long" + "true\r" + // for input with name "Boolean" + "k1=v1\rk2=v2\r\r" + // for input with name "Map" + "0\r" + // for input with name "Enum" + "l1\rl2\rl3\r\r" + // for input with name "List" + "12345678\r"); // for input with name "DateTime" + Status status = (Status) createCmd.execute(Arrays.asList(Constants.FN_LINK, "-c", "connector_test")); + assertTrue(status != null && status == Status.OK); + assertEquals(link.getName(), "linkname"); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getStringInput("CONFIGFROMNAME.String").getValue(), "abc"); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getIntegerInput("CONFIGFROMNAME.Integer").getValue().intValue(), 12345); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getLongInput("CONFIGFROMNAME.Long").getValue().longValue(), 56789); + assertTrue((link.getConnectorLinkConfig("CONFIGFROMNAME").getBooleanInput("CONFIGFROMNAME.Boolean").getValue())); + HashMap map = new HashMap(); + map.put("k1", "v1"); + map.put("k2", "v2"); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getMapInput("CONFIGFROMNAME.Map").getValue(), map); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getEnumInput("CONFIGFROMNAME.Enum").getValue(), "YES"); + assertEquals(StringUtils.join(link.getConnectorLinkConfig("CONFIGFROMNAME").getListInput("CONFIGFROMNAME.List").getValue(), "&"), "l1&l2&l3"); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getDateTimeInput("CONFIGFROMNAME.DateTime").getValue().getMillis(), 12345678); + } + @Test public void testCreateJob() { MConnector fromConnector = new MConnector("connector_from", "", "", null, new MFromConfig(new ArrayList(), new ArrayList()), null); @@ -109,15 +189,15 @@ public void testCreateJob() { // create job -f link_from -to link_to Status status = (Status) createCmd.execute(Arrays.asList(Constants.FN_JOB, "-f", "link_from", "-to", "link_to")); - Assert.assertTrue(status != null && status == Status.OK); + assertTrue(status != null && status == Status.OK); // incorrect command: create job -f link_from try { status = (Status) createCmd.execute(Arrays.asList(Constants.FN_JOB, "-f", "link_from")); - Assert.fail("Create Job should fail as the to link id/name is missing!"); + fail("Create Job should fail as the to link id/name is missing!"); } catch (SqoopException e) { - Assert.assertEquals(ShellError.SHELL_0003, e.getErrorCode()); - Assert.assertTrue(e.getMessage().contains("Missing required option")); + assertEquals(ShellError.SHELL_0003, e.getErrorCode()); + assertTrue(e.getMessage().contains("Missing required option")); } } @@ -127,16 +207,135 @@ public void testCreateJobWithNonExistingLink() { try { createCmd.execute(Arrays.asList(Constants.FN_JOB, "-f", "link_from", "-to", "link_to")); - Assert.fail("Create Job should fail as from link doesn't exist!"); + fail("Create Job should fail as from link doesn't exist!"); } catch (SqoopException e) { - Assert.assertEquals(TestShellError.TEST_SHELL_0000, e.getErrorCode()); + assertEquals(TestShellError.TEST_SHELL_0000, e.getErrorCode()); } } + @Test + public void testCreateJobInteractive() { + ShellEnvironment.setInteractive(true); + initEnv(); + MConnector fromConnector = new MConnector("connector_from", "", "", null, new MFromConfig(new ArrayList(), new ArrayList()), null); + MConnector toConnector = new MConnector("connector_to", "", "", null, null, new MToConfig(new ArrayList(), new ArrayList())); + MJob job = new MJob(1, 2, 1, 2, new MFromConfig(getConfig("fromJobConfig"), new ArrayList()), + new MToConfig(getConfig("toJobConfig"), new ArrayList()), + new MDriverConfig(getConfig("driverConfig"), new ArrayList())); + when(client.createJob("link_from", "link_to")).thenReturn(job); + when(client.getConnector(1)).thenReturn(fromConnector); + when(client.getConnector(2)).thenReturn(toConnector); + when(client.saveJob(any(MJob.class))).thenReturn(Status.OK); + when(client.getConnectorConfigBundle(any(Long.class))).thenReturn(resourceBundle); + when(client.getDriverConfigBundle()).thenReturn(resourceBundle); + + // create job -f link_from -to link_to + initData("jobname\r" + // job name + // From job config + "abc\r" + // for input with name "String" + "12345\r" + // for input with name "Integer" + "56789\r" + // for input with name "Long" + "true\r" + // for input with name "Boolean" + "k1=v1\rk2=v2\r\r" + // for input with name "Map" + "0\r" + // for input with name "Enum" + "l1\rl2\rl3\r\r" + // for input with name "List" + "12345678\r" + // for input with name "DateTime" + + // To job config + "def\r" + // for input with name "String" + "11111\r" + // for input with name "Integer" + "22222\r" + // for input with name "Long" + "false\r" + // for input with name "Boolean" + "k3=v3\rk4=v4\r\r" + // for input with name "Map" + "1\r" + // for input with name "Enum" + "l4\rl5\rl6\r\r" + // for input with name "List" + "1234567\r" + // for input with name "DateTime" + + // Driver config + "hij\r" + // for input with name "String" + "33333\r" + // for input with name "Integer" + "44444\r" + // for input with name "Long" + "true\r" + // for input with name "Boolean" + "k1=v1\r\r" + // for input with name "Map" + "0\r" + // for input with name "Enum" + "l1\rl2\rl3\r\r" + // for input with name "List" + "7654321\r"); // for input with name "DateTime" + Status status = (Status) createCmd.execute(Arrays.asList(Constants.FN_JOB, "-f", "link_from", "-to", "link_to")); + assertTrue(status != null && status == Status.OK); + assertEquals(job.getName(), "jobname"); + // check from job config + assertEquals(job.getFromJobConfig().getStringInput("fromJobConfig.String").getValue(), "abc"); + assertEquals(job.getFromJobConfig().getIntegerInput("fromJobConfig.Integer").getValue().intValue(), 12345); + assertEquals((job.getFromJobConfig().getLongInput("fromJobConfig.Long").getValue()).longValue(), 56789); + assertTrue((job.getFromJobConfig().getBooleanInput("fromJobConfig.Boolean").getValue())); + HashMap map = new HashMap(); + map.put("k1", "v1"); + map.put("k2", "v2"); + assertEquals(job.getFromJobConfig().getMapInput("fromJobConfig.Map").getValue(), map); + assertEquals(job.getFromJobConfig().getEnumInput("fromJobConfig.Enum").getValue(), "YES"); + assertEquals(StringUtils.join(job.getFromJobConfig().getListInput("fromJobConfig.List").getValue(), "&"), "l1&l2&l3"); + assertEquals(job.getFromJobConfig().getDateTimeInput("fromJobConfig.DateTime").getValue().getMillis(), 12345678); + + // check to job config + assertEquals(job.getToJobConfig().getStringInput("toJobConfig.String").getValue(), "def"); + assertEquals(job.getToJobConfig().getIntegerInput("toJobConfig.Integer").getValue().intValue(), 11111); + assertEquals(job.getToJobConfig().getLongInput("toJobConfig.Long").getValue().longValue(), 22222); + assertFalse(job.getToJobConfig().getBooleanInput("toJobConfig.Boolean").getValue()); + map = new HashMap(); + map.put("k3", "v3"); + map.put("k4", "v4"); + assertEquals(job.getToJobConfig().getMapInput("toJobConfig.Map").getValue(), map); + assertEquals(job.getToJobConfig().getEnumInput("toJobConfig.Enum").getValue(), "NO"); + assertEquals(StringUtils.join(job.getToJobConfig().getListInput("toJobConfig.List").getValue(), "&"), "l4&l5&l6"); + assertEquals(job.getToJobConfig().getDateTimeInput("toJobConfig.DateTime").getValue().getMillis(), 1234567); + + // check driver config + assertEquals(job.getDriverConfig().getStringInput("driverConfig.String").getValue(), "hij"); + assertEquals(job.getDriverConfig().getIntegerInput("driverConfig.Integer").getValue().intValue(), 33333); + assertEquals(job.getDriverConfig().getLongInput("driverConfig.Long").getValue().longValue(), 44444); + assertTrue(job.getDriverConfig().getBooleanInput("driverConfig.Boolean").getValue()); + map = new HashMap(); + map.put("k1", "v1"); + assertEquals(job.getDriverConfig().getMapInput("driverConfig.Map").getValue(), map); + assertEquals(job.getDriverConfig().getEnumInput("driverConfig.Enum").getValue(), "YES"); + assertEquals(StringUtils.join(job.getDriverConfig().getListInput("driverConfig.List").getValue(), "&"), "l1&l2&l3"); + assertEquals(job.getDriverConfig().getDateTimeInput("driverConfig.DateTime").getValue().getMillis(), 7654321); + } + @Test public void testCreateRole() { // create role -r role_test Status status = (Status) createCmd.execute(Arrays.asList(Constants.FN_ROLE, "-r", "role_test")); - Assert.assertTrue(status != null && status == Status.OK); + assertTrue(status != null && status == Status.OK); + } + + @SuppressWarnings("unchecked") + private List getConfig(String configName) { + List> list = new ArrayList>(); + list.add(new MStringInput(configName + "." + "String", false, InputEditable.ANY, StringUtils.EMPTY, (short)30, Collections.EMPTY_LIST)); + list.add(new MIntegerInput(configName + "." + "Integer", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MLongInput(configName + "." + "Long", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MBooleanInput(configName + "." + "Boolean", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MMapInput(configName + "." + "Map", false, InputEditable.ANY, StringUtils.EMPTY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MEnumInput(configName + "." + "Enum", false, InputEditable.ANY, StringUtils.EMPTY, new String[] {"YES", "NO"}, Collections.EMPTY_LIST)); + list.add(new MListInput(configName + "." + "List", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MDateTimeInput(configName + "." + "DateTime", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + + List configs = new ArrayList(); + configs.add(new MConfig(configName, list, Collections.EMPTY_LIST)); + return configs; + } + + private void initData(String destData) { + byte[] destDataBytes = destData.getBytes(); + System.arraycopy(destDataBytes, 0, data, 0, destDataBytes.length); + in.reset(); + } + + private void initEnv() { + in.reset(); + for (int i = 0; i < data.length; i++) { + data[i] = '\0'; + } } } diff --git a/shell/src/test/java/org/apache/sqoop/shell/TestUpdateCommand.java b/shell/src/test/java/org/apache/sqoop/shell/TestUpdateCommand.java index d9618ac3..d5df497f 100644 --- a/shell/src/test/java/org/apache/sqoop/shell/TestUpdateCommand.java +++ b/shell/src/test/java/org/apache/sqoop/shell/TestUpdateCommand.java @@ -21,19 +21,44 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; import java.util.HashMap; +import java.util.List; +import java.util.ResourceBundle; +import jline.ConsoleReader; + +import org.apache.commons.lang.StringUtils; import org.apache.sqoop.client.SqoopClient; import org.apache.sqoop.common.SqoopException; +import org.apache.sqoop.model.InputEditable; +import org.apache.sqoop.model.MBooleanInput; import org.apache.sqoop.model.MConfig; +import org.apache.sqoop.model.MConnector; +import org.apache.sqoop.model.MDateTimeInput; import org.apache.sqoop.model.MDriverConfig; +import org.apache.sqoop.model.MEnumInput; import org.apache.sqoop.model.MFromConfig; +import org.apache.sqoop.model.MInput; +import org.apache.sqoop.model.MIntegerInput; import org.apache.sqoop.model.MJob; import org.apache.sqoop.model.MLink; import org.apache.sqoop.model.MLinkConfig; +import org.apache.sqoop.model.MListInput; +import org.apache.sqoop.model.MLongInput; +import org.apache.sqoop.model.MMapInput; +import org.apache.sqoop.model.MStringInput; import org.apache.sqoop.model.MToConfig; import org.apache.sqoop.model.MValidator; import org.apache.sqoop.shell.core.Constants; @@ -41,22 +66,41 @@ import org.apache.sqoop.utils.MapResourceBundle; import org.apache.sqoop.validation.Status; import org.codehaus.groovy.tools.shell.Groovysh; -import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class TestUpdateCommand { UpdateCommand updateCmd; SqoopClient client; + ConsoleReader reader; + ResourceBundle resourceBundle; + ByteArrayInputStream in; + byte[] data; @BeforeTest(alwaysRun = true) - public void setup() { + public void setup() throws IOException { Groovysh shell = new Groovysh(); updateCmd = new UpdateCommand(shell); ShellEnvironment.setInteractive(false); ShellEnvironment.setIo(shell.getIo()); client = mock(SqoopClient.class); ShellEnvironment.setClient(client); + + data = new byte[1000]; + in = new ByteArrayInputStream(data); + reader = new ConsoleReader(in, new OutputStreamWriter(System.out)); + ShellEnvironment.setConsoleReader(reader); + resourceBundle = new ResourceBundle() { + @Override + protected Object handleGetObject(String key) { + return "fake_translated_value"; + } + + @Override + public Enumeration getKeys() { + return Collections.emptyEnumeration(); + } + }; } @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -69,27 +113,63 @@ public void testUpdateLink() throws InterruptedException { // update link -lid link_test Status status = (Status) updateCmd.execute(Arrays.asList(Constants.FN_LINK, "-lid", "link_test")); - Assert.assertTrue(status != null && status == Status.OK); + assertTrue(status != null && status == Status.OK); // Missing argument for option lid try { updateCmd.execute(Arrays.asList(Constants.FN_LINK, "-lid")); - Assert.fail("Update link should fail as parameters aren't complete!"); + fail("Update link should fail as parameters aren't complete!"); } catch (SqoopException e) { - Assert.assertEquals(ShellError.SHELL_0003, e.getErrorCode()); - Assert.assertTrue(e.getMessage().contains("Missing argument for option")); + assertEquals(ShellError.SHELL_0003, e.getErrorCode()); + assertTrue(e.getMessage().contains("Missing argument for option")); } // Missing option lid try { updateCmd.execute(Arrays.asList(Constants.FN_LINK)); - Assert.fail("Update link should fail as option lid is missing"); + fail("Update link should fail as option lid is missing"); } catch (SqoopException e) { - Assert.assertEquals(ShellError.SHELL_0003, e.getErrorCode()); - Assert.assertTrue(e.getMessage().contains("Missing required option")); + assertEquals(ShellError.SHELL_0003, e.getErrorCode()); + assertTrue(e.getMessage().contains("Missing required option")); } } + @Test + public void testUpdateLinkInteractive() { + ShellEnvironment.setInteractive(true); + initEnv(); + when(client.getConnector("connector_test")).thenReturn(new MConnector("", "", "", null, null, null)); + MLink link = new MLink(1, new MLinkConfig(getConfig("CONFIGFROMNAME"), new ArrayList())); + when(client.getLink("link_test")).thenReturn(link); + when(client.updateLink(link)).thenReturn(Status.OK); + when(client.getConnectorConfigBundle(any(Long.class))).thenReturn(resourceBundle); + + // update link -lid link_test + initData("linkname\r" + // link name + "abc\r" + // for input with name "String" + "12345\r" + // for input with name "Integer" + "56789\r" + // for input with name "Long" + "true\r" + // for input with name "Boolean" + "k1=v1\rk2=v2\r\r" + // for input with name "Map" + "0\r" + // for input with name "Enum" + "l1\rl2\rl3\r\r" + // for input with name "List" + "12345678\r"); // for input with name "DateTime" + Status status = (Status) updateCmd.execute(Arrays.asList(Constants.FN_LINK, "-lid", "link_test")); + assertTrue(status != null && status == Status.OK); + assertEquals(link.getName(), "linkname"); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getStringInput("CONFIGFROMNAME.String").getValue(), "abc"); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getIntegerInput("CONFIGFROMNAME.Integer").getValue().intValue(), 12345); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getLongInput("CONFIGFROMNAME.Long").getValue().longValue(), 56789); + assertTrue((link.getConnectorLinkConfig("CONFIGFROMNAME").getBooleanInput("CONFIGFROMNAME.Boolean").getValue())); + HashMap map = new HashMap(); + map.put("k1", "v1"); + map.put("k2", "v2"); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getMapInput("CONFIGFROMNAME.Map").getValue(), map); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getEnumInput("CONFIGFROMNAME.Enum").getValue(), "YES"); + assertEquals(StringUtils.join(link.getConnectorLinkConfig("CONFIGFROMNAME").getListInput("CONFIGFROMNAME.List").getValue(), "&"), "l1&l2&l3"); + assertEquals(link.getConnectorLinkConfig("CONFIGFROMNAME").getDateTimeInput("CONFIGFROMNAME.DateTime").getValue().getMillis(), 12345678); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void testUpdateJob() throws InterruptedException { @@ -104,24 +184,139 @@ public void testUpdateJob() throws InterruptedException { // update job -jid job_test Status status = (Status) updateCmd.execute(Arrays.asList(Constants.FN_JOB, "-jid", "job_test")); - Assert.assertTrue(status != null && status == Status.OK); + assertTrue(status != null && status == Status.OK); // Missing argument for option jid try { updateCmd.execute(Arrays.asList(Constants.FN_JOB, "-jid")); - Assert.fail("Update job should fail as parameters aren't complete!"); + fail("Update job should fail as parameters aren't complete!"); } catch (SqoopException e) { - Assert.assertEquals(ShellError.SHELL_0003, e.getErrorCode()); - Assert.assertTrue(e.getMessage().contains("Missing argument for option")); + assertEquals(ShellError.SHELL_0003, e.getErrorCode()); + assertTrue(e.getMessage().contains("Missing argument for option")); } // Missing option jid try { updateCmd.execute(Arrays.asList(Constants.FN_JOB)); - Assert.fail("Update job should fail as option jid is missing"); + fail("Update job should fail as option jid is missing"); } catch (SqoopException e) { - Assert.assertEquals(ShellError.SHELL_0003, e.getErrorCode()); - Assert.assertTrue(e.getMessage().contains("Missing required option")); + assertEquals(ShellError.SHELL_0003, e.getErrorCode()); + assertTrue(e.getMessage().contains("Missing required option")); + } + } + + @Test + public void testUpdateJobInteractive() { + ShellEnvironment.setInteractive(true); + initEnv(); + MJob job = new MJob(1, 2, 1, 2, new MFromConfig(getConfig("fromJobConfig"), new ArrayList()), + new MToConfig(getConfig("toJobConfig"), new ArrayList()), + new MDriverConfig(getConfig("driverConfig"), new ArrayList())); + when(client.getJob("job_test")).thenReturn(job); + when(client.getConnectorConfigBundle(any(Long.class))).thenReturn(resourceBundle); + when(client.getDriverConfigBundle()).thenReturn(resourceBundle); + when(client.updateJob(job)).thenReturn(Status.OK); + + // update job -jid job_test + initData("jobname\r" + // job name + // From job config + "abc\r" + // for input with name "String" + "12345\r" + // for input with name "Integer" + "56789\r" + // for input with name "Long" + "true\r" + // for input with name "Boolean" + "k1=v1\rk2=v2\r\r" + // for input with name "Map" + "0\r" + // for input with name "Enum" + "l1\rl2\rl3\r\r" + // for input with name "List" + "12345678\r" + // for input with name "DateTime" + + // To job config + "def\r" + // for input with name "String" + "11111\r" + // for input with name "Integer" + "22222\r" + // for input with name "Long" + "false\r" + // for input with name "Boolean" + "k3=v3\rk4=v4\r\r" + // for input with name "Map" + "1\r" + // for input with name "Enum" + "l4\rl5\rl6\r\r" + // for input with name "List" + "1234567\r" + // for input with name "DateTime" + + // Driver config + "hij\r" + // for input with name "String" + "33333\r" + // for input with name "Integer" + "44444\r" + // for input with name "Long" + "true\r" + // for input with name "Boolean" + "k1=v1\r\r" + // for input with name "Map" + "0\r" + // for input with name "Enum" + "l1\rl2\rl3\r\r" + // for input with name "List" + "7654321\r"); // for input with name "DateTime" + Status status = (Status) updateCmd.execute(Arrays.asList(Constants.FN_JOB, "-jid", "job_test")); + assertTrue(status != null && status == Status.OK); + assertEquals(job.getName(), "jobname"); + // check from job config + assertEquals(job.getFromJobConfig().getStringInput("fromJobConfig.String").getValue(), "abc"); + assertEquals(job.getFromJobConfig().getIntegerInput("fromJobConfig.Integer").getValue().intValue(), 12345); + assertEquals((job.getFromJobConfig().getLongInput("fromJobConfig.Long").getValue()).longValue(), 56789); + assertTrue((job.getFromJobConfig().getBooleanInput("fromJobConfig.Boolean").getValue())); + HashMap map = new HashMap(); + map.put("k1", "v1"); + map.put("k2", "v2"); + assertEquals(job.getFromJobConfig().getMapInput("fromJobConfig.Map").getValue(), map); + assertEquals(job.getFromJobConfig().getEnumInput("fromJobConfig.Enum").getValue(), "YES"); + assertEquals(StringUtils.join(job.getFromJobConfig().getListInput("fromJobConfig.List").getValue(), "&"), "l1&l2&l3"); + assertEquals(job.getFromJobConfig().getDateTimeInput("fromJobConfig.DateTime").getValue().getMillis(), 12345678); + + // check to job config + assertEquals(job.getToJobConfig().getStringInput("toJobConfig.String").getValue(), "def"); + assertEquals(job.getToJobConfig().getIntegerInput("toJobConfig.Integer").getValue().intValue(), 11111); + assertEquals(job.getToJobConfig().getLongInput("toJobConfig.Long").getValue().longValue(), 22222); + assertFalse(job.getToJobConfig().getBooleanInput("toJobConfig.Boolean").getValue()); + map = new HashMap(); + map.put("k3", "v3"); + map.put("k4", "v4"); + assertEquals(job.getToJobConfig().getMapInput("toJobConfig.Map").getValue(), map); + assertEquals(job.getToJobConfig().getEnumInput("toJobConfig.Enum").getValue(), "NO"); + assertEquals(StringUtils.join(job.getToJobConfig().getListInput("toJobConfig.List").getValue(), "&"), "l4&l5&l6"); + assertEquals(job.getToJobConfig().getDateTimeInput("toJobConfig.DateTime").getValue().getMillis(), 1234567); + + // check driver config + assertEquals(job.getDriverConfig().getStringInput("driverConfig.String").getValue(), "hij"); + assertEquals(job.getDriverConfig().getIntegerInput("driverConfig.Integer").getValue().intValue(), 33333); + assertEquals(job.getDriverConfig().getLongInput("driverConfig.Long").getValue().longValue(), 44444); + assertTrue(job.getDriverConfig().getBooleanInput("driverConfig.Boolean").getValue()); + map = new HashMap(); + map.put("k1", "v1"); + assertEquals(job.getDriverConfig().getMapInput("driverConfig.Map").getValue(), map); + assertEquals(job.getDriverConfig().getEnumInput("driverConfig.Enum").getValue(), "YES"); + assertEquals(StringUtils.join(job.getDriverConfig().getListInput("driverConfig.List").getValue(), "&"), "l1&l2&l3"); + assertEquals(job.getDriverConfig().getDateTimeInput("driverConfig.DateTime").getValue().getMillis(), 7654321); + } + + @SuppressWarnings("unchecked") + private List getConfig(String configName) { + List> list = new ArrayList>(); + list.add(new MStringInput(configName + "." + "String", false, InputEditable.ANY, StringUtils.EMPTY, (short)30, Collections.EMPTY_LIST)); + list.add(new MIntegerInput(configName + "." + "Integer", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MLongInput(configName + "." + "Long", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MBooleanInput(configName + "." + "Boolean", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MMapInput(configName + "." + "Map", false, InputEditable.ANY, StringUtils.EMPTY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MEnumInput(configName + "." + "Enum", false, InputEditable.ANY, StringUtils.EMPTY, new String[] {"YES", "NO"}, Collections.EMPTY_LIST)); + list.add(new MListInput(configName + "." + "List", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + list.add(new MDateTimeInput(configName + "." + "DateTime", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST)); + + List configs = new ArrayList(); + configs.add(new MConfig(configName, list, Collections.EMPTY_LIST)); + return configs; + } + + private void initData(String destData) { + byte[] destDataBytes = destData.getBytes(); + System.arraycopy(destDataBytes, 0, data, 0, destDataBytes.length); + in.reset(); + } + + private void initEnv() { + in.reset(); + for (int i = 0; i < data.length; i++) { + data[i] = '\0'; } } }