/** * 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.metastore; import java.sql.SQLException; import java.sql.Statement; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.apache.hadoop.conf.Configuration; import com.cloudera.sqoop.SqoopOptions; import com.cloudera.sqoop.manager.HsqldbManager; import com.cloudera.sqoop.metastore.hsqldb.AutoHsqldbStorage; import com.cloudera.sqoop.tool.VersionTool; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import java.io.IOException; import java.sql.Connection; import static org.junit.Assert.assertEquals; /** * Test the metastore and job-handling features. * * These all make use of the auto-connect hsqldb-based metastore. * The metastore URL is configured to be in-memory, and drop all * state between individual tests. */ public class TestSavedJobs { public static final String TEST_AUTOCONNECT_URL = "jdbc:hsqldb:mem:sqoopmetastore"; public static final String TEST_AUTOCONNECT_USER = "SA"; public static final String TEST_AUTOCONNECT_PASS = ""; @Rule public ExpectedException thrown = ExpectedException.none(); @Before public void setUp() throws Exception { // Delete db state between tests. resetJobSchema(); } public static void resetJobSchema() throws SQLException { SqoopOptions options = new SqoopOptions(); options.setConnectString(TEST_AUTOCONNECT_URL); options.setUsername(TEST_AUTOCONNECT_USER); options.setPassword(TEST_AUTOCONNECT_PASS); resetSchema(options); } /** * Drop all tables in the configured HSQLDB-based schema/user/pass. */ public static void resetSchema(SqoopOptions options) throws SQLException { HsqldbManager manager = new HsqldbManager(options); Connection c = manager.getConnection(); Statement s = c.createStatement(); try { String [] tables = manager.listTables(); for (String table : tables) { s.executeUpdate("DROP TABLE " + manager.escapeTableName(table)); } c.commit(); } finally { s.close(); } } public static Configuration newConf() { Configuration conf = new Configuration(); conf.set(AutoHsqldbStorage.AUTO_STORAGE_USER_KEY, TEST_AUTOCONNECT_USER); conf.set(AutoHsqldbStorage.AUTO_STORAGE_PASS_KEY, TEST_AUTOCONNECT_PASS); conf.set(AutoHsqldbStorage.AUTO_STORAGE_CONNECT_STRING_KEY, TEST_AUTOCONNECT_URL); return conf; } @Test public void testAutoConnect() throws IOException { // By default, we should be able to auto-connect with an // empty connection descriptor. We should see an empty // job set. Configuration conf = newConf(); JobStorageFactory ssf = new JobStorageFactory(conf); Map<String, String> descriptor = new TreeMap<String, String>(); JobStorage storage = ssf.getJobStorage(descriptor); storage.open(descriptor); List<String> jobs = storage.list(); assertEquals(0, jobs.size()); storage.close(); } @Test public void testCreateSameJob() throws IOException { Configuration conf = newConf(); JobStorageFactory ssf = new JobStorageFactory(conf); Map<String, String> descriptor = new TreeMap<String, String>(); JobStorage storage = ssf.getJobStorage(descriptor); storage.open(descriptor); // Job list should start out empty. List<String> jobs = storage.list(); assertEquals(0, jobs.size()); // Create a job that displays the version. JobData data = new JobData(new SqoopOptions(), new VersionTool()); storage.create("versionJob", data); jobs = storage.list(); assertEquals(1, jobs.size()); assertEquals("versionJob", jobs.get(0)); try { // Try to create that same job name again. This should fail. thrown.expect(IOException.class); thrown.reportMissingExceptionWithMessage("Expected IOException since job already exists"); storage.create("versionJob", data); } finally { jobs = storage.list(); assertEquals(1, jobs.size()); // Restore our job, check that it exists. JobData outData = storage.read("versionJob"); assertEquals(new VersionTool().getToolName(), outData.getSqoopTool().getToolName()); storage.close(); } } @Test public void testDeleteJob() throws IOException { Configuration conf = newConf(); JobStorageFactory ssf = new JobStorageFactory(conf); Map<String, String> descriptor = new TreeMap<String, String>(); JobStorage storage = ssf.getJobStorage(descriptor); storage.open(descriptor); // Job list should start out empty. List<String> jobs = storage.list(); assertEquals(0, jobs.size()); // Create a job that displays the version. JobData data = new JobData(new SqoopOptions(), new VersionTool()); storage.create("versionJob", data); jobs = storage.list(); assertEquals(1, jobs.size()); assertEquals("versionJob", jobs.get(0)); // Now delete the job. storage.delete("versionJob"); // After delete, we should have no jobs. jobs = storage.list(); assertEquals(0, jobs.size()); storage.close(); } @Test public void testRestoreNonExistingJob() throws IOException { Configuration conf = newConf(); JobStorageFactory ssf = new JobStorageFactory(conf); Map<String, String> descriptor = new TreeMap<String, String>(); JobStorage storage = ssf.getJobStorage(descriptor); storage.open(descriptor); try { // Try to restore a job that doesn't exist. Watch it fail. thrown.expect(IOException.class); thrown.reportMissingExceptionWithMessage("Expected IOException since job doesn't exist"); storage.read("DoesNotExist"); } finally { storage.close(); } } @Test public void testCreateJobWithExtraArgs() throws IOException { Configuration conf = newConf(); JobStorageFactory ssf = new JobStorageFactory(conf); Map<String, String> descriptor = new TreeMap<String, String>(); JobStorage storage = ssf.getJobStorage(descriptor); storage.open(descriptor); // Job list should start out empty. List<String> jobs = storage.list(); assertEquals(0, jobs.size()); // Create a job with extra args com.cloudera.sqoop.SqoopOptions opts = new SqoopOptions(); String[] args = {"-schema", "test"}; opts.setExtraArgs(args); JobData data = new JobData(opts, new VersionTool()); storage.create("versionJob", data); jobs = storage.list(); assertEquals(1, jobs.size()); assertEquals("versionJob", jobs.get(0)); // Restore our job, check that it exists. JobData outData = storage.read("versionJob"); assertEquals(new VersionTool().getToolName(), outData.getSqoopTool().getToolName()); String[] storedArgs = outData.getSqoopOptions().getExtraArgs(); for(int index = 0; index < args.length; ++index) { assertEquals(args[index], storedArgs[index]); } // Now delete the job. storage.delete("versionJob"); storage.close(); } @Test public void testMultiConnections() throws IOException { // Ensure that a job can be retrieved when the storage is // closed and reopened. Configuration conf = newConf(); JobStorageFactory ssf = new JobStorageFactory(conf); Map<String, String> descriptor = new TreeMap<String, String>(); JobStorage storage = ssf.getJobStorage(descriptor); storage.open(descriptor); // Job list should start out empty. List<String> jobs = storage.list(); assertEquals(0, jobs.size()); // Create a job that displays the version. JobData data = new JobData(new SqoopOptions(), new VersionTool()); storage.create("versionJob", data); jobs = storage.list(); assertEquals(1, jobs.size()); assertEquals("versionJob", jobs.get(0)); storage.close(); // Close the existing connection // Now re-open the storage. ssf = new JobStorageFactory(newConf()); storage = ssf.getJobStorage(descriptor); storage.open(descriptor); jobs = storage.list(); assertEquals(1, jobs.size()); assertEquals("versionJob", jobs.get(0)); // Restore our job, check that it exists. JobData outData = storage.read("versionJob"); assertEquals(new VersionTool().getToolName(), outData.getSqoopTool().getToolName()); storage.close(); } }