/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2016 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.di.repository; import org.apache.commons.io.IOUtils; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; import org.pentaho.di.core.Const; import org.pentaho.di.core.KettleEnvironment; import org.pentaho.di.core.database.DatabaseMeta; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.logging.LogChannel; import org.pentaho.test.util.XXEUtils; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import static org.junit.Assert.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class RepositoriesMetaTest { private RepositoriesMeta repoMeta; @BeforeClass public static void setUpClass() throws Exception { if ( !KettleEnvironment.isInitialized() ) { KettleEnvironment.init(); } } @Before public void setUp() { repoMeta = new RepositoriesMeta(); repoMeta = Mockito.spy( repoMeta ); LogChannel log = mock( LogChannel.class ); when( repoMeta.newLogChannel() ).thenReturn( log ); } @Test public void testToString() throws Exception { RepositoriesMeta repositoriesMeta = new RepositoriesMeta(); assertEquals( "RepositoriesMeta", repositoriesMeta.toString() ); } @Test public void testReadData() throws Exception { LogChannel log = mock( LogChannel.class ); when( repoMeta.getKettleUserRepositoriesFile() ).thenReturn( getClass().getResource( "repositories.xml" ).getPath() ); when( repoMeta.newLogChannel() ).thenReturn( log ); repoMeta.readData(); String repositoriesXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + Const.CR + "<repositories>" + Const.CR + " <connection>" + Const.CR + " <name>local postgres</name>" + Const.CR + " <server>localhost</server>" + Const.CR + " <type>POSTGRESQL</type>" + Const.CR + " <access>Native</access>" + Const.CR + " <database>hibernate</database>" + Const.CR + " <port>5432</port>" + Const.CR + " <username>auser</username>" + Const.CR + " <password>Encrypted 2be98afc86aa7f285bb18bd63c99dbdde</password>" + Const.CR + " <servername/>" + Const.CR + " <data_tablespace/>" + Const.CR + " <index_tablespace/>" + Const.CR + " <attributes>" + Const.CR + " <attribute><code>FORCE_IDENTIFIERS_TO_LOWERCASE</code><attribute>N</attribute></attribute>" + Const.CR + " <attribute><code>FORCE_IDENTIFIERS_TO_UPPERCASE</code><attribute>N</attribute></attribute>" + Const.CR + " <attribute><code>IS_CLUSTERED</code><attribute>N</attribute></attribute>" + Const.CR + " <attribute><code>PORT_NUMBER</code><attribute>5432</attribute></attribute>" + Const.CR + " <attribute><code>PRESERVE_RESERVED_WORD_CASE</code><attribute>N</attribute></attribute>" + Const.CR + " <attribute><code>QUOTE_ALL_FIELDS</code><attribute>N</attribute></attribute>" + Const.CR + " <attribute><code>SUPPORTS_BOOLEAN_DATA_TYPE</code><attribute>Y</attribute></attribute>" + Const.CR + " <attribute><code>SUPPORTS_TIMESTAMP_DATA_TYPE</code><attribute>Y</attribute></attribute>" + Const.CR + " <attribute><code>USE_POOLING</code><attribute>N</attribute></attribute>" + Const.CR + " </attributes>" + Const.CR + " </connection>" + Const.CR + " <repository> <id>KettleFileRepository</id>" + Const.CR + " <name>Test Repository</name>" + Const.CR + " <description>Test Repository Description</description>" + Const.CR + " <is_default>false</is_default>" + Const.CR + " <base_directory>test-repository</base_directory>" + Const.CR + " <read_only>N</read_only>" + Const.CR + " <hides_hidden_files>N</hides_hidden_files>" + Const.CR + " </repository> </repositories>" + Const.CR; assertEquals( repositoriesXml, repoMeta.getXML() ); RepositoriesMeta clone = repoMeta.clone(); assertEquals( repositoriesXml, repoMeta.getXML() ); assertNotSame( clone, repoMeta ); assertEquals( 1, repoMeta.nrRepositories() ); RepositoryMeta repository = repoMeta.getRepository( 0 ); assertEquals( "Test Repository", repository.getName() ); assertEquals( "Test Repository Description", repository.getDescription() ); assertEquals( " <repository> <id>KettleFileRepository</id>" + Const.CR + " <name>Test Repository</name>" + Const.CR + " <description>Test Repository Description</description>" + Const.CR + " <is_default>false</is_default>" + Const.CR + " <base_directory>test-repository</base_directory>" + Const.CR + " <read_only>N</read_only>" + Const.CR + " <hides_hidden_files>N</hides_hidden_files>" + Const.CR + " </repository>", repository.getXML() ); assertSame( repository, repoMeta.searchRepository( "Test Repository" ) ); assertSame( repository, repoMeta.findRepositoryById( "KettleFileRepository" ) ); assertSame( repository, repoMeta.findRepository( "Test Repository" ) ); assertNull( repoMeta.findRepository( "not found" ) ); assertNull( repoMeta.findRepositoryById( "not found" ) ); assertEquals( 0, repoMeta.indexOfRepository( repository ) ); repoMeta.removeRepository( 0 ); assertEquals( 0, repoMeta.nrRepositories() ); assertNull( repoMeta.searchRepository( "Test Repository" ) ); repoMeta.addRepository( 0, repository ); assertEquals( 1, repoMeta.nrRepositories() ); repoMeta.removeRepository( 1 ); assertEquals( 1, repoMeta.nrRepositories() ); assertEquals( 1, repoMeta.nrDatabases() ); assertEquals( "local postgres", repoMeta.getDatabase( 0 ).getName() ); DatabaseMeta searchDatabase = repoMeta.searchDatabase( "local postgres" ); assertSame( searchDatabase, repoMeta.getDatabase( 0 ) ); assertEquals( 0, repoMeta.indexOfDatabase( searchDatabase ) ); repoMeta.removeDatabase( 0 ); assertEquals( 0, repoMeta.nrDatabases() ); assertNull( repoMeta.searchDatabase( "local postgres" ) ); repoMeta.addDatabase( 0, searchDatabase ); assertEquals( 1, repoMeta.nrDatabases() ); repoMeta.removeDatabase( 1 ); assertEquals( 1, repoMeta.nrDatabases() ); assertEquals( "Unable to read repository with id [junk]. RepositoryMeta is not available.", repoMeta.getErrorMessage() ); } @Test public void testNothingToRead() throws Exception { when( repoMeta.getKettleUserRepositoriesFile() ).thenReturn( "filedoesnotexist.xml" ); assertTrue( repoMeta.readData() ); assertEquals( 0, repoMeta.nrDatabases() ); assertEquals( 0, repoMeta.nrRepositories() ); } @Test public void testReadDataFromInputStream() throws Exception { InputStream inputStream = getClass().getResourceAsStream( "repositories.xml" ); repoMeta.readDataFromInputStream( inputStream ); assertEquals( 1, repoMeta.nrDatabases() ); assertEquals( 1, repoMeta.nrRepositories() ); } @Test public void testErrorReadingInputStream() throws Exception { try { repoMeta.readDataFromInputStream( getClass().getResourceAsStream( "filedoesnotexist.xml" ) ); } catch ( KettleException e ) { assertEquals( Const.CR + "Error reading information from file:" + Const.CR + "InputStream cannot be null" + Const.CR, e.getMessage() ); } } @Test public void testErrorReadingFile() throws Exception { when( repoMeta.getKettleUserRepositoriesFile() ).thenReturn( getClass().getResource( "bad-repositories.xml" ).getPath() ); try { repoMeta.readData(); } catch ( KettleException e ) { assertEquals( Const.CR + "Error reading information from file:" + Const.CR + "The element type \"repositories\" must be terminated by the matching end-tag \"</repositories>\"." + Const.CR, e.getMessage() ); } } @Test public void testWriteFile() throws Exception { String path = getClass().getResource( "repositories.xml" ).getPath().replace( "repositories.xml", "new-repositories.xml" ); when( repoMeta.getKettleUserRepositoriesFile() ).thenReturn( path ); repoMeta.writeData(); InputStream resourceAsStream = getClass().getResourceAsStream( "new-repositories.xml" ); assertEquals( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + Const.CR + "<repositories>" + Const.CR + " </repositories>" + Const.CR, IOUtils.toString( resourceAsStream ) ); new File( path ).delete(); } @Test public void testErrorWritingFile() throws Exception { when( repoMeta.getKettleUserRepositoriesFile() ).thenReturn( null ); try { repoMeta.writeData(); } catch ( KettleException e ) { assertTrue( e.getMessage().startsWith( Const.CR + "Error writing repositories metadata" ) ); } } @Test( expected = KettleException.class ) public void exceptionThrownWhenParsingXmlWithBigAmountOfExternalEntitiesFromInputStream() throws Exception { repoMeta.readDataFromInputStream( new ByteArrayInputStream( XXEUtils.MALICIOUS_XML.getBytes() ) ); } }