/******************************************************************************* * * Pentaho Big Data * * Copyright (C) 2002-2017 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * Licensed 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.pentaho.hadoop.shim; import org.apache.commons.vfs2.AllFileSelector; import org.apache.commons.vfs2.FileObject; import org.apache.commons.vfs2.FileSystemException; import org.apache.commons.vfs2.FileType; import org.apache.commons.vfs2.VFS; import org.apache.commons.vfs2.impl.DefaultFileSystemManager; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.pentaho.hadoop.shim.api.ShimProperties; import org.pentaho.hadoop.shim.spi.HadoopShim; import org.pentaho.hadoop.shim.spi.MockHadoopShim; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.net.URL; import java.util.Arrays; import java.util.List; import java.util.Properties; import static org.junit.Assert.*; public class HadoopConfigurationLocatorTest { private static String HADOOP_CONFIGURATIONS_PATH = System.getProperty( "java.io.tmpdir" ) + "/hadoop-configurations"; private static FileObject configFile; @BeforeClass public static void setup() throws Exception { // Create a test hadoop configuration "a" FileObject ramRoot = VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH ); FileObject aConfigFolder = ramRoot.resolveFile( "a" ); if ( aConfigFolder.exists() ) { aConfigFolder.delete( new AllFileSelector() ); } aConfigFolder.createFolder(); assertEquals( FileType.FOLDER, aConfigFolder.getType() ); // Create the properties file for the configuration as hadoop-configurations/a/config.properties configFile = aConfigFolder.resolveFile( "config.properties" ); Properties p = new Properties(); p.setProperty( "name", "Test Configuration A" ); p.setProperty( "classpath", "" ); p.setProperty( "ignore.classes", "" ); p.setProperty( "library.path", "" ); p.setProperty( "required.classes", HadoopConfigurationLocatorTest.class.getName() ); p.store( configFile.getContent().getOutputStream(), "Test Configuration A" ); configFile.close(); // Create the implementation jar FileObject implJar = aConfigFolder.resolveFile( "a-config.jar" ); implJar.createFile(); // Use ShrinkWrap to create the jar and write it out to VFS JavaArchive archive = ShrinkWrap.create( JavaArchive.class, "a-configuration.jar" ).addAsServiceProvider( HadoopShim.class, MockHadoopShim.class ) .addClass( MockHadoopShim.class ); archive.as( ZipExporter.class ).exportTo( implJar.getContent().getOutputStream() ); } @Test( expected = ConfigurationException.class ) public void init_invalidDirectory() throws FileSystemException, ConfigurationException { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.init( VFS.getManager().resolveFile( "ram://bogus-path" ), new MockActiveHadoopConfigurationLocator(), new DefaultFileSystemManager() ); } @Test( expected = NullPointerException.class ) public void init_null_basedir() throws FileSystemException, ConfigurationException { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.init( null, new MockActiveHadoopConfigurationLocator(), new DefaultFileSystemManager() ); } @Test( expected = NullPointerException.class ) public void init_null_activeLocator() throws FileSystemException, ConfigurationException { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.init( VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH ), null, new DefaultFileSystemManager() ); } @Test( expected = NullPointerException.class ) public void init_null_fsm() throws FileSystemException, ConfigurationException { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.init( VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH ), new MockActiveHadoopConfigurationLocator(), null ); } @Test public void init_MissingRequiredClasses() throws IOException { Properties properties = new Properties(); InputStream inputStream = configFile.getContent().getInputStream(); properties.load( inputStream ); inputStream.close(); properties.setProperty( "required.classes", "this.class.does.not.Exist" ); properties.store( configFile.getContent().getOutputStream(), "Test Configuration A" ); configFile.close(); HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); try { locator.init( VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH ), new MockActiveHadoopConfigurationLocator( "a" ), new DefaultFileSystemManager() ); Assert.fail( "Should have got exception " ); } catch ( ConfigurationException e ) { assertEquals( "Unable to load class this.class.does.not.Exist that is required to start the Test Configuration A Hadoop Shim", e.getCause().getMessage() ); } finally { properties.setProperty( "required.classes", HadoopConfigurationLocator.class.getName() ); properties.store( configFile.getContent().getOutputStream(), "Test Configuration A" ); configFile.close(); } } public void init() throws FileSystemException, ConfigurationException { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.init( VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH ), new MockActiveHadoopConfigurationLocator( "a" ), new DefaultFileSystemManager() ); assertEquals( 1, locator.getConfigurations().size() ); assertEquals( VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH ).resolveFile( "a" ), locator.getConfiguration( "a" ).getLocation() ); } @Test public void hasConfiguration() throws Exception { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.init( VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH ), new MockActiveHadoopConfigurationLocator( "a" ), new DefaultFileSystemManager() ); assertTrue( locator.hasConfiguration( "a" ) ); } @Test( expected = RuntimeException.class ) public void hasConfiguration_not_intialized() { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.hasConfiguration( null ); } @Test public void getConfiguration() throws Exception { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.init( VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH ), new MockActiveHadoopConfigurationLocator( "a" ), new DefaultFileSystemManager() ); HadoopConfiguration a = locator.getConfiguration( "a" ); assertNotNull( a ); assertEquals( "a", a.getIdentifier() ); assertEquals( "Test Configuration A", a.getName() ); } @Test( expected = ConfigurationException.class ) public void getConfiguration_unknown_id() throws Exception { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.init( VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH ), new MockActiveHadoopConfigurationLocator(), new DefaultFileSystemManager() ); locator.getConfiguration( "unknown" ); } @Test( expected = RuntimeException.class ) public void getConfiguration_not_intialized() throws ConfigurationException { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.getConfiguration( null ); } @Test( expected = RuntimeException.class ) public void getConfigurations_not_intialized() { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.getConfigurations(); } @Test public void getActiveConfiguration() throws Exception { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.init( VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH ), new MockActiveHadoopConfigurationLocator( "a" ), new DefaultFileSystemManager() ); HadoopConfiguration a = locator.getActiveConfiguration(); assertNotNull( a ); } @Test( expected = RuntimeException.class ) public void getActiveConfiguration_not_intialized() throws ConfigurationException { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.getActiveConfiguration(); } @Test( expected = NullPointerException.class ) public void registerNativeLibraryPath_null_path() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.registerNativeLibraryPath( null ); } @Test public void registerNativeLibraryPaths() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.registerNativeLibraryPaths( "test,ing" ); Field f = ClassLoader.class.getDeclaredField( "usr_paths" ); boolean accessible = f.isAccessible(); f.setAccessible( true ); try { String[] usrPaths = (String[]) f.get( null ); assertTrue( Arrays.asList( usrPaths ).contains( "test" ) ); assertTrue( Arrays.asList( usrPaths ).contains( "ing" ) ); } finally { f.setAccessible( accessible ); } } @Test public void registerNativeLibraryPaths_no_duplicates() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.registerNativeLibraryPaths( "test,ing" ); Field f = ClassLoader.class.getDeclaredField( "usr_paths" ); boolean accessible = f.isAccessible(); f.setAccessible( true ); try { String[] usrPaths = (String[]) f.get( null ); int pathCount = usrPaths.length; locator.registerNativeLibraryPaths( "ing" ); usrPaths = (String[]) f.get( null ); assertTrue( Arrays.asList( usrPaths ).contains( "test" ) ); assertTrue( Arrays.asList( usrPaths ).contains( "ing" ) ); assertEquals( pathCount, usrPaths.length ); } finally { f.setAccessible( accessible ); } } @Test( expected = ConfigurationException.class ) public void createConfigurationLoader_null_root() throws ConfigurationException { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); locator.createConfigurationLoader( null, null, null, new ShimProperties() ); } @Test( expected = ConfigurationException.class ) public void createConfigurationLoader_root_not_a_folder() throws Exception { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); // Try to create a configuration based on a file, not a folder FileObject buildProperties = VFS.getManager().resolveFile( "ram:///test.file" ); buildProperties.createFile(); assertEquals( FileType.FILE, buildProperties.getType() ); locator.createConfigurationLoader( buildProperties, null, null, new ShimProperties() ); } @Test public void loadHadoopConfiguration_with_ignore_classes() throws Exception { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); FileObject root = VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH + "/a" ); HadoopConfiguration configuration = locator.loadHadoopConfiguration( root ); assertNotNull( configuration ); } @Test public void createConfigurationLoader() throws Exception { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); FileObject root = VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH + "/a" ); ClassLoader cl = locator.createConfigurationLoader( root, getClass().getClassLoader(), null, new ShimProperties() ); assertNotNull( cl.getResource( "config.properties" ) ); } @Test( expected = ConfigurationException.class ) public void findHadoopConfigurations_errorLoadingHadoopConfig() throws Exception { FileObject root = VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH ); HadoopConfigurationLocator locator = new HadoopConfigurationLocator() { protected HadoopConfiguration loadHadoopConfiguration( FileObject folder ) throws ConfigurationException { throw new ConfigurationException( "test" ); } }; locator.init( root, new MockActiveHadoopConfigurationLocator( "a" ), new DefaultFileSystemManager() ); } @Test public void parseURLs() throws Exception { HadoopConfigurationLocator locator = new HadoopConfigurationLocator(); FileObject root = VFS.getManager().resolveFile( HADOOP_CONFIGURATIONS_PATH ); List<URL> urls = locator.parseURLs( root, "a,b" ); assertEquals( 2, urls.size() ); assertEquals( root.getURL().toURI().resolve( "hadoop-configurations/a/" ), urls.get( 0 ).toURI() ); assertEquals( root.getURL().toURI().resolve( "hadoop-configurations/a/a-config.jar" ), urls.get( 1 ).toURI() ); } }