/**
 * 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.Rule;
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 org.junit.rules.ExpectedException;

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;

  @Rule
  public ExpectedException thrown = ExpectedException.none();

  @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");
  }

  /**
   * 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,
    };

    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);

    writer.generate();

    thrown.expect(Exception.class);
    compileMgr.compile();
  }

  @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();
    }
  }
}
