| /** |
| * 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 com.cloudera.sqoop.orm; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.sql.Connection; |
| import java.sql.Statement; |
| import java.sql.SQLException; |
| import java.util.Random; |
| import java.util.jar.JarEntry; |
| import java.util.jar.JarInputStream; |
| |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.hadoop.util.Shell; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import com.cloudera.sqoop.SqoopOptions; |
| import com.cloudera.sqoop.TestConnFactory.DummyManager; |
| import com.cloudera.sqoop.manager.ConnManager; |
| import com.cloudera.sqoop.testutil.DirUtil; |
| import com.cloudera.sqoop.testutil.HsqldbTestServer; |
| import com.cloudera.sqoop.testutil.ImportJobTestCase; |
| import com.cloudera.sqoop.tool.ImportTool; |
| import com.cloudera.sqoop.util.ClassLoaderStack; |
| |
| import java.lang.reflect.Field; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| /** |
| * Test that the ClassWriter generates Java classes based on the given table, |
| * which compile. |
| */ |
| public class TestClassWriter { |
| |
| public static final Log LOG = |
| LogFactory.getLog(TestClassWriter.class.getName()); |
| private static final String WIDE_TABLE_NAME = "WIDETABLE"; |
| private static final int WIDE_TABLE_COLUMN_COUNT = 800; |
| private static final int WIDE_TABLE_ROW_COUNT = 20_000; |
| |
| // instance variables populated during setUp, used during tests |
| private HsqldbTestServer testServer; |
| private ConnManager manager; |
| private SqoopOptions options; |
| |
| @Before |
| public void setUp() { |
| testServer = new HsqldbTestServer(); |
| org.apache.log4j.Logger root = org.apache.log4j.Logger.getRootLogger(); |
| root.setLevel(org.apache.log4j.Level.DEBUG); |
| try { |
| testServer.resetServer(); |
| } catch (SQLException sqlE) { |
| LOG.error("Got SQLException: " + sqlE.toString()); |
| fail("Got SQLException: " + sqlE.toString()); |
| } catch (ClassNotFoundException cnfe) { |
| LOG.error("Could not find class for db driver: " + cnfe.toString()); |
| fail("Could not find class for db driver: " + cnfe.toString()); |
| } |
| |
| manager = testServer.getManager(); |
| options = testServer.getSqoopOptions(); |
| |
| // sanity check: make sure we're in a tmp dir before we blow anything away. |
| assertTrue("Test generates code in non-tmp dir!", |
| CODE_GEN_DIR.startsWith(ImportJobTestCase.TEMP_BASE_DIR)); |
| assertTrue("Test generates jars in non-tmp dir!", |
| JAR_GEN_DIR.startsWith(ImportJobTestCase.TEMP_BASE_DIR)); |
| |
| // start out by removing these directories ahead of time |
| // to ensure that this is truly generating the code. |
| File codeGenDirFile = new File(CODE_GEN_DIR); |
| File classGenDirFile = new File(JAR_GEN_DIR); |
| |
| if (codeGenDirFile.exists()) { |
| LOG.debug("Removing code gen dir: " + codeGenDirFile); |
| if (!DirUtil.deleteDir(codeGenDirFile)) { |
| LOG.warn("Could not delete " + codeGenDirFile + " prior to test"); |
| } |
| } |
| |
| if (classGenDirFile.exists()) { |
| LOG.debug("Removing class gen dir: " + classGenDirFile); |
| if (!DirUtil.deleteDir(classGenDirFile)) { |
| LOG.warn("Could not delete " + classGenDirFile + " prior to test"); |
| } |
| } |
| } |
| |
| @After |
| public void tearDown() { |
| try { |
| manager.close(); |
| } catch (SQLException sqlE) { |
| LOG.error("Got SQLException: " + sqlE.toString()); |
| fail("Got SQLException: " + sqlE.toString()); |
| } |
| } |
| |
| static final String CODE_GEN_DIR = ImportJobTestCase.TEMP_BASE_DIR |
| + "sqoop/test/codegen"; |
| static final String JAR_GEN_DIR = ImportJobTestCase.TEMP_BASE_DIR |
| + "sqoop/test/jargen"; |
| |
| private File runGenerationTest(String[] argv, String classNameToCheck) { |
| return runGenerationTest(argv, classNameToCheck, HsqldbTestServer.getTableName()); |
| } |
| |
| /** |
| * Run a test to verify that we can generate code and it emits the output |
| * files where we expect them. |
| * @return |
| */ |
| private File runGenerationTest(String[] argv, String classNameToCheck, String tableName) { |
| File codeGenDirFile = new File(CODE_GEN_DIR); |
| File classGenDirFile = new File(JAR_GEN_DIR); |
| |
| try { |
| options = new ImportTool().parseArguments(argv, |
| null, options, true); |
| } catch (Exception e) { |
| LOG.error("Could not parse options: " + e.toString()); |
| } |
| |
| CompilationManager compileMgr = new CompilationManager(options); |
| ClassWriter writer = new ClassWriter(options, manager, |
| tableName, compileMgr); |
| |
| try { |
| writer.generate(); |
| compileMgr.compile(); |
| compileMgr.jar(); |
| } catch (IOException ioe) { |
| LOG.error("Got IOException: " + ioe.toString()); |
| fail("Got IOException: " + ioe.toString()); |
| } |
| |
| String classFileNameToCheck = classNameToCheck.replace('.', |
| File.separatorChar); |
| LOG.debug("Class file to check for: " + classFileNameToCheck); |
| |
| // Check that all the files we expected to generate (.java, .class, .jar) |
| // exist. |
| File tableFile = new File(codeGenDirFile, classFileNameToCheck + ".java"); |
| assertTrue("Cannot find generated source file for table!", |
| tableFile.exists()); |
| LOG.debug("Found generated source: " + tableFile); |
| |
| File tableClassFile = new File(classGenDirFile, classFileNameToCheck |
| + ".class"); |
| assertTrue("Cannot find generated class file for table!", |
| tableClassFile.exists()); |
| LOG.debug("Found generated class: " + tableClassFile); |
| |
| File jarFile = new File(compileMgr.getJarFilename()); |
| assertTrue("Cannot find compiled jar", jarFile.exists()); |
| LOG.debug("Found generated jar: " + jarFile); |
| |
| // check that the .class file made it into the .jar by enumerating |
| // available entries in the jar file. |
| boolean foundCompiledClass = false; |
| if (Shell.WINDOWS) { |
| // In Windows OS, elements in jar files still need to have a path |
| // separator of '/' rather than the default File.separator which is '\' |
| classFileNameToCheck = classFileNameToCheck.replace(File.separator, "/"); |
| } |
| try { |
| JarInputStream jis = new JarInputStream(new FileInputStream(jarFile)); |
| |
| LOG.debug("Jar file has entries:"); |
| while (true) { |
| JarEntry entry = jis.getNextJarEntry(); |
| if (null == entry) { |
| // no more entries. |
| break; |
| } |
| |
| if (entry.getName().equals(classFileNameToCheck + ".class")) { |
| foundCompiledClass = true; |
| LOG.debug(" * " + entry.getName()); |
| } else { |
| LOG.debug(" " + entry.getName()); |
| } |
| } |
| |
| jis.close(); |
| } catch (IOException ioe) { |
| fail("Got IOException iterating over Jar file: " + ioe.toString()); |
| } |
| |
| assertTrue("Cannot find .class file " + classFileNameToCheck |
| + ".class in jar file", foundCompiledClass); |
| |
| LOG.debug("Found class in jar - test success!"); |
| return jarFile; |
| } |
| |
| /** |
| * Test that we can generate code. Test that we can redirect the --outdir |
| * and --bindir too. |
| */ |
| @Test |
| public void testCodeGen() { |
| |
| // Set the option strings in an "argv" to redirect our srcdir and bindir. |
| String [] argv = { |
| "--bindir", |
| JAR_GEN_DIR, |
| "--outdir", |
| CODE_GEN_DIR, |
| }; |
| |
| runGenerationTest(argv, HsqldbTestServer.getTableName()); |
| } |
| |
| private static final String OVERRIDE_CLASS_NAME = "override"; |
| |
| /** |
| * Test that we can generate code with a custom class name. |
| */ |
| @Test |
| public void testSetClassName() { |
| |
| // Set the option strings in an "argv" to redirect our srcdir and bindir |
| String [] argv = { |
| "--bindir", |
| JAR_GEN_DIR, |
| "--outdir", |
| CODE_GEN_DIR, |
| "--class-name", |
| OVERRIDE_CLASS_NAME, |
| }; |
| |
| runGenerationTest(argv, OVERRIDE_CLASS_NAME); |
| } |
| |
| private static final String OVERRIDE_CLASS_AND_PACKAGE_NAME = |
| "override.pkg.prefix.classname"; |
| |
| /** |
| * Test that we can generate code with a custom class name that includes a |
| * package. |
| */ |
| @Test |
| public void testSetClassAndPackageName() { |
| |
| // Set the option strings in an "argv" to redirect our srcdir and bindir |
| String [] argv = { |
| "--bindir", |
| JAR_GEN_DIR, |
| "--outdir", |
| CODE_GEN_DIR, |
| "--class-name", |
| OVERRIDE_CLASS_AND_PACKAGE_NAME, |
| }; |
| |
| runGenerationTest(argv, OVERRIDE_CLASS_AND_PACKAGE_NAME); |
| } |
| |
| private static final String OVERRIDE_PACKAGE_NAME = |
| "special.userpackage.name"; |
| |
| /** |
| * Test that we can generate code with a custom class name that includes a |
| * package. |
| */ |
| @Test |
| public void testSetPackageName() { |
| |
| // Set the option strings in an "argv" to redirect our srcdir and bindir |
| String [] argv = { |
| "--bindir", |
| JAR_GEN_DIR, |
| "--outdir", |
| CODE_GEN_DIR, |
| "--package-name", |
| OVERRIDE_PACKAGE_NAME, |
| }; |
| |
| runGenerationTest(argv, OVERRIDE_PACKAGE_NAME + "." |
| + HsqldbTestServer.getTableName()); |
| } |
| |
| |
| // Test the SQL identifier -> Java identifier conversion. |
| @Test |
| public void testJavaIdentifierConversion() { |
| assertNull(ClassWriter.getIdentifierStrForChar(' ')); |
| assertNull(ClassWriter.getIdentifierStrForChar('\t')); |
| assertNull(ClassWriter.getIdentifierStrForChar('\r')); |
| assertNull(ClassWriter.getIdentifierStrForChar('\n')); |
| assertEquals("x", ClassWriter.getIdentifierStrForChar('x')); |
| assertEquals("_", ClassWriter.getIdentifierStrForChar('-')); |
| assertEquals("_", ClassWriter.getIdentifierStrForChar('_')); |
| |
| assertEquals("foo", ClassWriter.toJavaIdentifier("foo")); |
| |
| assertEquals("_abstract", ClassWriter.toJavaIdentifier("abstract")); |
| assertEquals("_assert", ClassWriter.toJavaIdentifier("assert")); |
| assertEquals("_boolean", ClassWriter.toJavaIdentifier("boolean")); |
| assertEquals("_break", ClassWriter.toJavaIdentifier("break")); |
| assertEquals("_byte", ClassWriter.toJavaIdentifier("byte")); |
| assertEquals("_case", ClassWriter.toJavaIdentifier("case")); |
| assertEquals("_catch", ClassWriter.toJavaIdentifier("catch")); |
| assertEquals("_char", ClassWriter.toJavaIdentifier("char")); |
| assertEquals("_class", ClassWriter.toJavaIdentifier("class")); |
| assertEquals("_const", ClassWriter.toJavaIdentifier("const")); |
| assertEquals("_continue", ClassWriter.toJavaIdentifier("continue")); |
| assertEquals("_default", ClassWriter.toJavaIdentifier("default")); |
| assertEquals("_do", ClassWriter.toJavaIdentifier("do")); |
| assertEquals("_double", ClassWriter.toJavaIdentifier("double")); |
| assertEquals("_else", ClassWriter.toJavaIdentifier("else")); |
| assertEquals("_enum", ClassWriter.toJavaIdentifier("enum")); |
| assertEquals("_extends", ClassWriter.toJavaIdentifier("extends")); |
| assertEquals("_false", ClassWriter.toJavaIdentifier("false")); |
| assertEquals("_final", ClassWriter.toJavaIdentifier("final")); |
| assertEquals("_finally", ClassWriter.toJavaIdentifier("finally")); |
| assertEquals("_float", ClassWriter.toJavaIdentifier("float")); |
| assertEquals("_for", ClassWriter.toJavaIdentifier("for")); |
| assertEquals("_goto", ClassWriter.toJavaIdentifier("goto")); |
| assertEquals("_if", ClassWriter.toJavaIdentifier("if")); |
| assertEquals("_implements", ClassWriter.toJavaIdentifier("implements")); |
| assertEquals("_import", ClassWriter.toJavaIdentifier("import")); |
| assertEquals("_instanceof", ClassWriter.toJavaIdentifier("instanceof")); |
| assertEquals("_int", ClassWriter.toJavaIdentifier("int")); |
| assertEquals("_interface", ClassWriter.toJavaIdentifier("interface")); |
| assertEquals("_long", ClassWriter.toJavaIdentifier("long")); |
| assertEquals("_native", ClassWriter.toJavaIdentifier("native")); |
| assertEquals("_new", ClassWriter.toJavaIdentifier("new")); |
| assertEquals("_null", ClassWriter.toJavaIdentifier("null")); |
| assertEquals("_package", ClassWriter.toJavaIdentifier("package")); |
| assertEquals("_private", ClassWriter.toJavaIdentifier("private")); |
| assertEquals("_protected", ClassWriter.toJavaIdentifier("protected")); |
| assertEquals("_public", ClassWriter.toJavaIdentifier("public")); |
| assertEquals("_return", ClassWriter.toJavaIdentifier("return")); |
| assertEquals("_short", ClassWriter.toJavaIdentifier("short")); |
| assertEquals("_static", ClassWriter.toJavaIdentifier("static")); |
| assertEquals("_strictfp", ClassWriter.toJavaIdentifier("strictfp")); |
| assertEquals("_super", ClassWriter.toJavaIdentifier("super")); |
| assertEquals("_switch", ClassWriter.toJavaIdentifier("switch")); |
| assertEquals("_synchronized", ClassWriter.toJavaIdentifier("synchronized")); |
| assertEquals("_this", ClassWriter.toJavaIdentifier("this")); |
| assertEquals("_throw", ClassWriter.toJavaIdentifier("throw")); |
| assertEquals("_throws", ClassWriter.toJavaIdentifier("throws")); |
| assertEquals("_transient", ClassWriter.toJavaIdentifier("transient")); |
| assertEquals("_true", ClassWriter.toJavaIdentifier("true")); |
| assertEquals("_try", ClassWriter.toJavaIdentifier("try")); |
| assertEquals("_void", ClassWriter.toJavaIdentifier("void")); |
| assertEquals("_volatile", ClassWriter.toJavaIdentifier("volatile")); |
| assertEquals("_while", ClassWriter.toJavaIdentifier("while")); |
| |
| assertEquals("_class", ClassWriter.toJavaIdentifier("cla ss")); |
| assertEquals("_int", ClassWriter.toJavaIdentifier("int")); |
| assertEquals("thisismanywords", ClassWriter.toJavaIdentifier( |
| "this is many words")); |
| assertEquals("_9isLegalInSql", ClassWriter.toJavaIdentifier( |
| "9isLegalInSql")); |
| assertEquals("____", ClassWriter.toJavaIdentifier("___")); |
| assertEquals("__class", ClassWriter.toJavaIdentifier("_class")); |
| //Checking Java identifier for Constant PROTOCOL_VERSION |
| assertEquals("_PROTOCOL_VERSION", ClassWriter.toJavaIdentifier("PROTOCOL_VERSION")); |
| } |
| |
| @Test |
| public void testWeirdColumnNames() throws SQLException { |
| // Recreate the table with column names that aren't legal Java identifiers. |
| String tableName = HsqldbTestServer.getTableName(); |
| Connection connection = testServer.getConnection(); |
| Statement st = connection.createStatement(); |
| try { |
| st.executeUpdate("DROP TABLE " + tableName + " IF EXISTS"); |
| st.executeUpdate("CREATE TABLE " + tableName |
| + " (class INT, \"9field\" INT)"); |
| st.executeUpdate("INSERT INTO " + tableName + " VALUES(42, 41)"); |
| connection.commit(); |
| } finally { |
| st.close(); |
| connection.close(); |
| } |
| |
| String [] argv = { |
| "--bindir", |
| JAR_GEN_DIR, |
| "--outdir", |
| CODE_GEN_DIR, |
| "--package-name", |
| OVERRIDE_PACKAGE_NAME, |
| }; |
| |
| runGenerationTest(argv, OVERRIDE_PACKAGE_NAME + "." |
| + HsqldbTestServer.getTableName()); |
| } |
| |
| // Test For checking Codegneration perfroming successfully |
| // in case of Table with Column name as PROTOCOL_VERSION |
| @Test |
| public void testColumnNameAsProtocolVersion() throws SQLException { |
| // Recreate the table with column name as PROTOCOL_VERSION. |
| String tableName = HsqldbTestServer.getTableName(); |
| Connection connection = testServer.getConnection(); |
| Statement st = connection.createStatement(); |
| try { |
| st.executeUpdate("DROP TABLE " + tableName + " IF EXISTS"); |
| st.executeUpdate("CREATE TABLE " + tableName |
| + " (PROTOCOL_VERSION INT)"); |
| st.executeUpdate("INSERT INTO " + tableName + " VALUES(42)"); |
| connection.commit(); |
| } finally { |
| st.close(); |
| connection.close(); |
| } |
| |
| String [] argv = { |
| "--bindir", |
| JAR_GEN_DIR, |
| "--outdir", |
| CODE_GEN_DIR, |
| "--package-name", |
| OVERRIDE_PACKAGE_NAME, |
| }; |
| |
| runGenerationTest(argv, OVERRIDE_PACKAGE_NAME + "." |
| + HsqldbTestServer.getTableName()); |
| } |
| |
| @Test |
| public void testCloningTableWithVarbinaryDoesNotThrowNPE() throws SQLException, |
| IOException, ClassNotFoundException, NoSuchMethodException, |
| SecurityException, InstantiationException, IllegalAccessException, |
| IllegalArgumentException, InvocationTargetException { |
| String tableName = HsqldbTestServer.getTableName(); |
| Connection connection = testServer.getConnection(); |
| Statement st = connection.createStatement(); |
| try { |
| st.executeUpdate("DROP TABLE " + tableName + " IF EXISTS"); |
| st.executeUpdate("CREATE TABLE " + tableName |
| + " (id INT, test VARBINARY(10))"); |
| connection.commit(); |
| } finally { |
| st.close(); |
| connection.close(); |
| } |
| |
| String [] argv = { |
| "--bindir", |
| JAR_GEN_DIR, |
| "--outdir", |
| CODE_GEN_DIR, |
| "--package-name", |
| OVERRIDE_PACKAGE_NAME, |
| }; |
| |
| String className = OVERRIDE_PACKAGE_NAME + "." |
| + HsqldbTestServer.getTableName(); |
| File ormJarFile = runGenerationTest(argv, className); |
| |
| ClassLoader prevClassLoader = ClassLoaderStack.addJarFile( |
| ormJarFile.getCanonicalPath(), className); |
| Class tableClass = Class.forName(className, true, |
| Thread.currentThread().getContextClassLoader()); |
| Method cloneImplementation = tableClass.getMethod("clone"); |
| |
| Object instance = tableClass.newInstance(); |
| |
| assertTrue(cloneImplementation.invoke(instance).getClass(). |
| getCanonicalName().equals(className)); |
| |
| if (null != prevClassLoader) { |
| ClassLoaderStack.setCurrentClassLoader(prevClassLoader); |
| } |
| } |
| |
| /** |
| * Test the generated equals method. |
| * @throws IOException |
| * @throws ClassNotFoundException |
| * @throws IllegalAccessException |
| * @throws InstantiationException |
| * @throws NoSuchMethodException |
| * @throws SecurityException |
| * @throws InvocationTargetException |
| * @throws IllegalArgumentException |
| */ |
| @Test |
| public void testEqualsMethod() throws IOException, ClassNotFoundException, |
| InstantiationException, IllegalAccessException, NoSuchMethodException, |
| InvocationTargetException { |
| |
| // Set the option strings in an "argv" to redirect our srcdir and bindir |
| String [] argv = { |
| "--bindir", |
| JAR_GEN_DIR, |
| "--outdir", |
| CODE_GEN_DIR, |
| "--class-name", |
| OVERRIDE_CLASS_AND_PACKAGE_NAME, |
| }; |
| |
| File ormJarFile = runGenerationTest(argv, OVERRIDE_CLASS_AND_PACKAGE_NAME); |
| ClassLoader prevClassLoader = ClassLoaderStack.addJarFile( |
| ormJarFile.getCanonicalPath(), |
| OVERRIDE_CLASS_AND_PACKAGE_NAME); |
| Class tableClass = Class.forName( |
| OVERRIDE_CLASS_AND_PACKAGE_NAME, |
| true, |
| Thread.currentThread().getContextClassLoader()); |
| Method setterIntField1 = |
| tableClass.getMethod("set_INTFIELD1", Integer.class); |
| Method setterIntField2 = |
| tableClass.getMethod("set_INTFIELD2", Integer.class); |
| Method equalsImplementation = tableClass.getMethod("equals", Object.class); |
| |
| Object instance1 = tableClass.newInstance(); |
| Object instance2 = tableClass.newInstance(); |
| |
| // test reflexivity |
| assertTrue((Boolean) equalsImplementation.invoke(instance1, instance1)); |
| |
| // test equality for uninitialized fields |
| assertTrue((Boolean) equalsImplementation.invoke(instance1, instance2)); |
| |
| // test symmetry |
| assertTrue((Boolean) equalsImplementation.invoke(instance2, instance1)); |
| |
| // test reflexivity with initialized fields |
| setterIntField1.invoke(instance1, new Integer(1)); |
| setterIntField2.invoke(instance1, new Integer(2)); |
| assertTrue((Boolean) equalsImplementation.invoke(instance1, instance1)); |
| |
| // test difference in both fields |
| setterIntField1.invoke(instance2, new Integer(3)); |
| setterIntField2.invoke(instance2, new Integer(4)); |
| assertFalse((Boolean) equalsImplementation.invoke(instance1, instance2)); |
| |
| // test difference in second field |
| setterIntField1.invoke(instance2, new Integer(1)); |
| setterIntField2.invoke(instance2, new Integer(3)); |
| assertFalse((Boolean) equalsImplementation.invoke(instance1, instance2)); |
| |
| // test difference in first field |
| setterIntField1.invoke(instance2, new Integer(3)); |
| setterIntField2.invoke(instance2, new Integer(2)); |
| assertFalse((Boolean) equalsImplementation.invoke(instance1, instance2)); |
| |
| // test equality for initialized fields |
| setterIntField1.invoke(instance2, new Integer(1)); |
| setterIntField2.invoke(instance2, new Integer(2)); |
| assertTrue((Boolean) equalsImplementation.invoke(instance1, instance2)); |
| |
| if (null != prevClassLoader) { |
| ClassLoaderStack.setCurrentClassLoader(prevClassLoader); |
| } |
| } |
| |
| private static final String USERMAPPING_CLASS_AND_PACKAGE_NAME = |
| "usermapping.pkg.prefix.classname"; |
| |
| @Test |
| public void testUserMapping() throws IOException, ClassNotFoundException, |
| InstantiationException, IllegalAccessException, NoSuchMethodException, |
| InvocationTargetException { |
| |
| // Set the option strings in an "argv" to redirect our srcdir and bindir |
| String [] argv = { |
| "--bindir", JAR_GEN_DIR, |
| "--outdir", CODE_GEN_DIR, |
| "--class-name", USERMAPPING_CLASS_AND_PACKAGE_NAME, |
| "--map-column-java", "INTFIELD1=String", |
| }; |
| |
| File ormJarFile = runGenerationTest(argv, |
| USERMAPPING_CLASS_AND_PACKAGE_NAME); |
| ClassLoader prevClassLoader = ClassLoaderStack.addJarFile( |
| ormJarFile.getCanonicalPath(), |
| USERMAPPING_CLASS_AND_PACKAGE_NAME); |
| Class tableClass = Class.forName( |
| USERMAPPING_CLASS_AND_PACKAGE_NAME, |
| true, |
| Thread.currentThread().getContextClassLoader()); |
| |
| try { |
| Field intfield = tableClass.getDeclaredField("INTFIELD1"); |
| |
| assertEquals(String.class, intfield.getType()); |
| } catch (NoSuchFieldException ex) { |
| fail("Can't find field for INTFIELD1"); |
| } catch (SecurityException ex) { |
| fail("Can't find field for INTFIELD1"); |
| } |
| |
| if (null != prevClassLoader) { |
| ClassLoaderStack.setCurrentClassLoader(prevClassLoader); |
| } |
| } |
| |
| @Test |
| public void testBrokenUserMapping() throws Exception { |
| |
| String [] argv = { |
| "--bindir", JAR_GEN_DIR, |
| "--outdir", CODE_GEN_DIR, |
| "--class-name", USERMAPPING_CLASS_AND_PACKAGE_NAME, |
| "--map-column-java", "INTFIELD1=NotARealClass", |
| }; |
| |
| try { |
| runGenerationTest( |
| argv, |
| USERMAPPING_CLASS_AND_PACKAGE_NAME); |
| } catch(IllegalArgumentException e) { |
| return; |
| } |
| fail("we shouldn't successfully generate code"); |
| } |
| |
| private void runFailedGenerationTest(String [] argv, |
| String classNameToCheck) { |
| File codeGenDirFile = new File(CODE_GEN_DIR); |
| File classGenDirFile = new File(JAR_GEN_DIR); |
| |
| try { |
| options = new ImportTool().parseArguments(argv, |
| null, options, true); |
| } catch (Exception e) { |
| LOG.error("Could not parse options: " + e.toString()); |
| } |
| |
| CompilationManager compileMgr = new CompilationManager(options); |
| ClassWriter writer = new ClassWriter(options, manager, |
| HsqldbTestServer.getTableName(), compileMgr); |
| |
| try { |
| writer.generate(); |
| compileMgr.compile(); |
| fail("ORM class file generation succeeded when it was expected to fail"); |
| } catch (Exception ioe) { |
| LOG.error("Got Exception from ORM generation as expected : " |
| + ioe.toString()); |
| } |
| } |
| /** |
| * A dummy manager that declares that it ORM is self managed. |
| */ |
| public static class DummyDirectManager extends DummyManager { |
| @Override |
| public boolean isORMFacilitySelfManaged() { |
| return true; |
| } |
| } |
| |
| @Test |
| public void testNoClassGeneration() throws Exception { |
| manager = new DummyDirectManager(); |
| String [] argv = { |
| "--bindir", |
| JAR_GEN_DIR, |
| "--outdir", |
| CODE_GEN_DIR, |
| }; |
| runFailedGenerationTest(argv, HsqldbTestServer.getTableName()); |
| } |
| |
| @Test(timeout = 25000) |
| public void testWideTableClassGeneration() throws Exception { |
| createWideTable(); |
| options = new SqoopOptions(HsqldbTestServer.getDbUrl(), WIDE_TABLE_NAME); |
| |
| // Set the option strings in an "argv" to redirect our srcdir and bindir. |
| String [] argv = { |
| "--bindir", |
| JAR_GEN_DIR, |
| "--outdir", |
| CODE_GEN_DIR, |
| }; |
| |
| File ormJarFile = runGenerationTest(argv, WIDE_TABLE_NAME, WIDE_TABLE_NAME); |
| |
| ClassLoader prevClassLoader = ClassLoaderStack.addJarFile(ormJarFile.getCanonicalPath(), |
| WIDE_TABLE_NAME); |
| Class tableClass = Class.forName(WIDE_TABLE_NAME, true, |
| Thread.currentThread().getContextClassLoader()); |
| |
| Object instance = tableClass.newInstance(); |
| Method setterMethod = tableClass.getMethod("setField", String.class, Object.class); |
| Random random = new Random(0); |
| for (int j = 0; j < WIDE_TABLE_ROW_COUNT; ++j) { |
| for (int i = 0; i < WIDE_TABLE_COLUMN_COUNT; ++i) { |
| setterMethod.invoke(instance, "INTFIELD" + i, random.nextInt()); |
| } |
| } |
| |
| if (null != prevClassLoader) { |
| ClassLoaderStack.setCurrentClassLoader(prevClassLoader); |
| } |
| } |
| |
| private void createWideTable() throws Exception { |
| try (Connection conn = testServer.getConnection(); Statement stmt = conn.createStatement();) { |
| stmt.executeUpdate("DROP TABLE \"" + WIDE_TABLE_NAME + "\" IF EXISTS"); |
| StringBuilder sb = new StringBuilder("CREATE TABLE \"" + WIDE_TABLE_NAME + "\" ("); |
| for (int i = 0; i < WIDE_TABLE_COLUMN_COUNT; ++i) { |
| sb.append("intField" + i + " INT"); |
| if (i < WIDE_TABLE_COLUMN_COUNT - 1) { |
| sb.append(","); |
| } else { |
| sb.append(")"); |
| } |
| } |
| stmt.executeUpdate(sb.toString()); |
| conn.commit(); |
| } |
| } |
| } |