/** * 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 org.apache.hadoop.hive.ql.session; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.conf.HiveConf.ConfVars; import org.apache.hadoop.hive.metastore.MetaStoreUtils; import org.apache.hive.common.util.HiveTestUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import com.google.common.io.Files; /** * Test SessionState */ @RunWith(value = Parameterized.class) public class TestSessionState { private final boolean prewarm; private final static String clazzDistFileName = "RefreshedJarClass.jar.V1"; private final static String clazzV2FileName = "RefreshedJarClass.jar.V2"; private final static String reloadClazzFileName = "RefreshedJarClass.jar"; private final static String versionMethodName = "version"; private final static String RELOADED_CLAZZ_PREFIX_NAME = "RefreshedJarClass"; private final static String V1 = "V1"; private final static String V2 = "V2"; private static String hiveReloadPath; private File reloadFolder; public static final Logger LOG = LoggerFactory.getLogger(TestSessionState.class); public TestSessionState(Boolean mode) { this.prewarm = mode.booleanValue(); } @Parameters public static Collection<Boolean[]> data() { return Arrays.asList(new Boolean[][] { {false}, {true}}); } @Before public void setUp() { HiveConf conf = new HiveConf(); String tmp = System.getProperty("java.io.tmpdir"); File tmpDir = new File(tmp); if (!tmpDir.exists()) { tmpDir.mkdir(); } hiveReloadPath = Files.createTempDir().getAbsolutePath(); // create the reloading folder to place jar files if not exist reloadFolder = new File(hiveReloadPath); if (!reloadFolder.exists()) { reloadFolder.mkdir(); } try { generateRefreshJarFiles(V2); generateRefreshJarFiles(V1); } catch (Throwable e) { Assert.fail("fail to generate refresh jar file due to the error " + e); } if (prewarm) { HiveConf.setBoolVar(conf, ConfVars.HIVE_PREWARM_ENABLED, true); HiveConf.setIntVar(conf, ConfVars.HIVE_PREWARM_NUM_CONTAINERS, 1); } SessionState.start(conf); } @After public void tearDown(){ FileUtils.deleteQuietly(reloadFolder); } /** * test set and get db */ @Test public void testgetDbName() throws Exception { //check that we start with default db assertEquals(MetaStoreUtils.DEFAULT_DATABASE_NAME, SessionState.get().getCurrentDatabase()); final String newdb = "DB_2"; //set new db and verify get SessionState.get().setCurrentDatabase(newdb); assertEquals(newdb, SessionState.get().getCurrentDatabase()); //verify that a new sessionstate has default db SessionState.start(new HiveConf()); assertEquals(MetaStoreUtils.DEFAULT_DATABASE_NAME, SessionState.get().getCurrentDatabase()); } @Test public void testClose() throws Exception { SessionState ss = SessionState.get(); assertNull(ss.getTezSession()); ss.close(); assertNull(ss.getTezSession()); } class RegisterJarRunnable implements Runnable { String jar; ClassLoader loader; SessionState ss; public RegisterJarRunnable(String jar, SessionState ss) { this.jar = jar; this.ss = ss; } public void run() { SessionState.start(ss); SessionState.registerJars(Arrays.asList(jar)); loader = Thread.currentThread().getContextClassLoader(); } } @Test public void testClassLoaderEquality() throws Exception { HiveConf conf = new HiveConf(); final SessionState ss1 = new SessionState(conf); RegisterJarRunnable otherThread = new RegisterJarRunnable("./build/contrib/test/test-udfs.jar", ss1); Thread th1 = new Thread(otherThread); th1.start(); th1.join(); // set state in current thread SessionState.start(ss1); SessionState ss2 = SessionState.get(); ClassLoader loader2 = ss2.getConf().getClassLoader(); System.out.println("Loader1:(Set in other thread) " + otherThread.loader); System.out.println("Loader2:(Set in SessionState.conf) " + loader2); System.out.println("Loader3:(CurrentThread.getContextClassLoader()) " + Thread.currentThread().getContextClassLoader()); assertEquals("Other thread loader and session state loader", otherThread.loader, loader2); assertEquals("Other thread loader and current thread loader", otherThread.loader, Thread.currentThread().getContextClassLoader()); } private String getReloadedClazzVersion(ClassLoader cl) throws Exception { Class addedClazz = Class.forName(RELOADED_CLAZZ_PREFIX_NAME, true, cl); Method versionMethod = addedClazz.getMethod(versionMethodName); return (String) versionMethod.invoke(addedClazz.newInstance()); } private void generateRefreshJarFiles(String version) throws IOException, InterruptedException { String u = HiveTestUtils .getFileFromClasspath(RELOADED_CLAZZ_PREFIX_NAME + version + HiveTestUtils.TXT_FILE_EXT); File jarFile = HiveTestUtils.genLocalJarForTest(u, RELOADED_CLAZZ_PREFIX_NAME); Files.move(jarFile, new File(jarFile.getAbsolutePath() + "." + version)); } @Test public void testReloadAuxJars2() { HiveConf conf = new HiveConf(); HiveConf.setVar(conf, ConfVars.HIVERELOADABLEJARS, hiveReloadPath); SessionState ss = new SessionState(conf); SessionState.start(ss); ss = SessionState.get(); File dist = null; try { dist = new File(reloadFolder.getAbsolutePath() + File.separator + reloadClazzFileName); Files.copy(new File(HiveTestUtils.getFileFromClasspath(clazzDistFileName)), dist); ss.loadReloadableAuxJars(); Assert.assertEquals("version1", getReloadedClazzVersion(ss.getConf().getClassLoader())); } catch (Exception e) { LOG.error("Reload auxiliary jar test fail with message: ", e); Assert.fail(e.getMessage()); } finally { FileUtils.deleteQuietly(dist); try { ss.close(); } catch (IOException ioException) { Assert.fail(ioException.getMessage()); LOG.error("Fail to close the created session: ", ioException); } } } @Test public void testReloadExistingAuxJars2() { HiveConf conf = new HiveConf(); HiveConf.setVar(conf, ConfVars.HIVERELOADABLEJARS, hiveReloadPath); SessionState ss = new SessionState(conf); SessionState.start(ss); File dist = null; try { ss = SessionState.get(); LOG.info("copy jar file 1"); dist = new File(reloadFolder.getAbsolutePath() + File.separator + reloadClazzFileName); Files.copy(new File(HiveTestUtils.getFileFromClasspath(clazzDistFileName)), dist); ss.loadReloadableAuxJars(); Assert.assertEquals("version1", getReloadedClazzVersion(ss.getConf().getClassLoader())); LOG.info("copy jar file 2"); FileUtils.deleteQuietly(dist); Files.copy(new File(HiveTestUtils.getFileFromClasspath(clazzV2FileName)), dist); ss.loadReloadableAuxJars(); Assert.assertEquals("version2", getReloadedClazzVersion(ss.getConf().getClassLoader())); FileUtils.deleteQuietly(dist); ss.loadReloadableAuxJars(); } catch (Exception e) { LOG.error("refresh existing jar file case failed with message: ", e); Assert.fail(e.getMessage()); } finally { FileUtils.deleteQuietly(dist); try { ss.close(); } catch (IOException ioException) { Assert.fail(ioException.getMessage()); LOG.error("Fail to close the created session: ", ioException); } } } }