Java tutorial
/** * Licensed to Cloudera, Inc. under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. Cloudera, Inc. 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.sql.Connection; import java.sql.Statement; import java.sql.SQLException; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; import junit.framework.TestCase; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.cloudera.sqoop.SqoopOptions; 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; /** * Test that the ClassWriter generates Java classes based on the given table, * which compile. */ public class TestClassWriter extends TestCase { public static final Log LOG = LogFactory.getLog(TestClassWriter.class.getName()); // 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"; /** * Run a test to verify that we can generate code and it emits the output * files where we expect them. */ private void runGenerationTest(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(); 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; 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!"); } /** * 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 testIdentifierConversion() { 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.toIdentifier("foo")); assertEquals("_class", ClassWriter.toIdentifier("class")); assertEquals("_class", ClassWriter.toIdentifier("cla ss")); assertEquals("_int", ClassWriter.toIdentifier("int")); assertEquals("thisismanywords", ClassWriter.toIdentifier("this is many words")); assertEquals("_9isLegalInSql", ClassWriter.toIdentifier("9isLegalInSql")); assertEquals("___", ClassWriter.toIdentifier("___")); } @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()); } }