/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2016 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.platform.plugin.services.exporter;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.pentaho.database.model.DatabaseConnection;
import org.pentaho.database.model.IDatabaseConnection;
import org.pentaho.metadata.repository.IMetadataDomainRepository;
import org.pentaho.metastore.api.IMetaStore;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.engine.IUserRoleListService;
import org.pentaho.platform.api.mt.ITenant;
import org.pentaho.platform.api.repository.datasource.IDatasourceMgmtService;
import org.pentaho.platform.api.repository2.unified.IUnifiedRepository;
import org.pentaho.platform.api.scheduler2.ComplexJobTrigger;
import org.pentaho.platform.api.scheduler2.IScheduler;
import org.pentaho.platform.api.scheduler2.Job;
import org.pentaho.platform.api.scheduler2.JobTrigger;
import org.pentaho.platform.api.scheduler2.SchedulerException;
import org.pentaho.platform.api.usersettings.IAnyUserSettingService;
import org.pentaho.platform.api.usersettings.pojo.IUserSetting;
import org.pentaho.platform.engine.core.system.PentahoSessionHolder;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.plugin.action.mondrian.catalog.IMondrianCatalogService;
import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianCatalog;
import org.pentaho.platform.plugin.services.importexport.ExportManifestUserSetting;
import org.pentaho.platform.plugin.services.importexport.RoleExport;
import org.pentaho.platform.plugin.services.importexport.UserExport;
import org.pentaho.platform.plugin.services.importexport.exportManifest.ExportManifest;
import org.pentaho.platform.plugin.services.importexport.exportManifest.bindings.ExportManifestMetaStore;
import org.pentaho.platform.plugin.services.importexport.exportManifest.bindings.ExportManifestMondrian;
import org.pentaho.platform.plugin.services.importexport.legacy.MondrianCatalogRepositoryHelper;
import org.pentaho.platform.scheduler2.versionchecker.EmbeddedVersionCheckSystemListener;
import org.pentaho.platform.security.policy.rolebased.IRoleAuthorizationPolicyRoleBindingDao;
import org.pentaho.platform.security.policy.rolebased.RoleBindingStruct;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import java.io.InputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.anyBoolean;
public class PentahoPlatformExporterTest {
PentahoPlatformExporter exporterSpy;
PentahoPlatformExporter exporter;
IUnifiedRepository repo;
IScheduler scheduler;
IPentahoSession session;
IMondrianCatalogService mondrianCatalogService;
MondrianCatalogRepositoryHelper mondrianCatalogRepositoryHelper;
ExportManifest exportManifest;
@Before
public void setUp() throws Exception {
repo = mock( IUnifiedRepository.class );
scheduler = mock( IScheduler.class );
session = mock( IPentahoSession.class );
mondrianCatalogService = mock( IMondrianCatalogService.class );
mondrianCatalogRepositoryHelper = mock( MondrianCatalogRepositoryHelper.class );
exportManifest = spy( new ExportManifest() );
PentahoSessionHolder.setSession( session );
exporterSpy = spy( new PentahoPlatformExporter( repo ) );
exporterSpy.setScheduler( scheduler );
exporterSpy.setExportManifest( exportManifest );
doReturn( "session name" ).when( session ).getName();
exporter = new PentahoPlatformExporter( repo );
}
@After
public void tearDown() {
PentahoSystem.clearObjectFactory();
}
@Test
public void testExportSchedules() throws Exception {
List<Job> jobs = new ArrayList<>();
ComplexJobTrigger trigger = mock( ComplexJobTrigger.class );
JobTrigger unknownTrigger = mock( JobTrigger.class );
Job job1 = mock( Job.class );
Job job2 = mock( Job.class );
Job job3 = mock( Job.class );
jobs.add( job1 );
jobs.add( job2 );
jobs.add( job3 );
when( scheduler.getJobs( null ) ).thenReturn( jobs );
when( job1.getJobName() ).thenReturn( EmbeddedVersionCheckSystemListener.VERSION_CHECK_JOBNAME );
when( job2.getJobName() ).thenReturn( "job 2" );
when( job2.getJobTrigger() ).thenReturn( trigger );
when( job3.getJobName() ).thenReturn( "job 3" );
when( job3.getJobTrigger() ).thenReturn( unknownTrigger );
exporterSpy.exportSchedules();
verify( scheduler ).getJobs( null );
assertEquals( 1, exporterSpy.getExportManifest().getScheduleList().size() );
}
@Test
public void testExportSchedules_SchedulereThrowsException() throws Exception {
when( scheduler.getJobs( null ) ).thenThrow( new SchedulerException( "bad" ) );
exporterSpy.exportSchedules();
verify( scheduler ).getJobs( null );
assertEquals( 0, exporterSpy.getExportManifest().getScheduleList().size() );
}
@Test
public void testExportUsersAndRoles() {
IUserRoleListService mockDao = mock( IUserRoleListService.class );
IAnyUserSettingService userSettingService = mock( IAnyUserSettingService.class );
UserDetailsService userDetailsService = mock( UserDetailsService.class );
PentahoSystem.registerObject( mockDao );
PentahoSystem.registerObject( userSettingService );
PentahoSystem.registerObject( userDetailsService );
IRoleAuthorizationPolicyRoleBindingDao roleBindingDao = mock( IRoleAuthorizationPolicyRoleBindingDao.class );
PentahoSystem.registerObject( roleBindingDao );
String tenantPath = "path";
when( session.getAttribute( IPentahoSession.TENANT_ID_KEY ) ).thenReturn( tenantPath );
List<String> userList = new ArrayList<String>();
String user = "testUser";
String role = "testRole";
userList.add( user );
when( mockDao.getAllUsers( any( ITenant.class ) ) ).thenReturn( userList );
List<String> roleList = new ArrayList<String>();
roleList.add( role );
when( mockDao.getAllRoles() ).thenReturn( roleList );
Map<String, List<String>> map = new HashMap<String, List<String>>();
List<String> permissions = new ArrayList<String>();
permissions.add( "read" );
map.put( "testRole", permissions );
RoleBindingStruct struct = mock( RoleBindingStruct.class );
struct.bindingMap = map;
when( roleBindingDao.getRoleBindingStruct( anyString() ) ).thenReturn( struct );
ArgumentCaptor<UserExport> userCaptor = ArgumentCaptor.forClass( UserExport.class );
ArgumentCaptor<RoleExport> roleCaptor = ArgumentCaptor.forClass( RoleExport.class );
ExportManifest manifest = mock( ExportManifest.class );
exporter.setExportManifest( manifest );
List<IUserSetting> settings = new ArrayList<>();
IUserSetting setting = mock( IUserSetting.class );
settings.add( setting );
when( userSettingService.getUserSettings( user ) ).thenReturn( settings );
when( userSettingService.getGlobalUserSettings() ).thenReturn( settings );
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
UserDetails userDetails = new User( "testUser", "testPassword", true, true, true, true, authList );
when( userDetailsService.loadUserByUsername( anyString() ) ).thenReturn( userDetails );
exporter.exportUsersAndRoles();
verify( manifest ).addUserExport( userCaptor.capture() );
verify( manifest ).addRoleExport( roleCaptor.capture() );
verify( userSettingService ).getGlobalUserSettings();
verify( manifest ).addGlobalUserSetting( any( ExportManifestUserSetting.class ) );
assertEquals( settings.size(), userCaptor.getValue().getUserSettings().size() );
UserExport userExport = userCaptor.getValue();
assertEquals( "testUser", userExport.getUsername() );
RoleExport roleExport = roleCaptor.getValue();
assertEquals( "testRole", roleExport.getRolename() );
}
@Test
public void testExportMetadata_noModels() throws Exception {
IMetadataDomainRepository mdr = mock( IMetadataDomainRepository.class );
exporter.setMetadataDomainRepository( mdr );
exporter.exportMetadataModels();
assertEquals( 0, exporter.getExportManifest().getMetadataList().size() );
}
@Test
public void testExportMetadata() throws Exception {
IMetadataDomainRepository mdr = mock( IMetadataDomainRepository.class );
Set<String> domainIds = new HashSet<>();
domainIds.add( "test1" );
when( mdr.getDomainIds() ).thenReturn( domainIds );
exporterSpy.setMetadataDomainRepository( mdr );
exporterSpy.zos = mock( ZipOutputStream.class );
Map<String, InputStream> inputMap = new HashMap<>();
InputStream is = mock( InputStream.class );
when( is.read( any( ( new byte[] {} ).getClass() ) ) ).thenReturn( -1 );
inputMap.put( "test1", is );
doReturn( inputMap ).when( exporterSpy ).getDomainFilesData( "test1" );
exporterSpy.exportMetadataModels();
assertEquals( 1, exporterSpy.getExportManifest().getMetadataList().size() );
assertEquals( "test1", exporterSpy.getExportManifest().getMetadataList().get( 0 ).getDomainId() );
assertEquals( PentahoPlatformExporter.METADATA_PATH_IN_ZIP + "test1.xmi",
exporterSpy.getExportManifest().getMetadataList().get( 0 ).getFile() );
}
@Test
public void testExportDatasources() throws Exception {
IDatasourceMgmtService svc = mock( IDatasourceMgmtService.class );
exporterSpy.setDatasourceMgmtService( svc );
List<IDatabaseConnection> datasources = new ArrayList<>();
IDatabaseConnection conn = mock( DatabaseConnection.class );
IDatabaseConnection icon = mock( IDatabaseConnection.class );
datasources.add( conn );
datasources.add( icon );
when( svc.getDatasources() ).thenReturn( datasources );
exporterSpy.exportDatasources();
assertEquals( 1, exporterSpy.getExportManifest().getDatasourceList().size() );
assertEquals( conn, exporterSpy.getExportManifest().getDatasourceList().get( 0 ) );
}
@Test
public void testParseXmlaEnabled() throws Exception {
String dsInfo = "DataSource=SampleData;Provider=mondrian;EnableXmla=\"false\"";
assertFalse( exporterSpy.parseXmlaEnabled( dsInfo ) );
dsInfo = "DataSource=SampleData;Provider=mondrian;EnableXmla=\"true\"";
assertTrue( exporterSpy.parseXmlaEnabled( dsInfo ) );
dsInfo = "DataSource=SampleData;Provider=mondrian";
assertFalse( exporterSpy.parseXmlaEnabled( dsInfo ) );
dsInfo = "DataSource=SampleData;EnableXmla=\"true\";Provider=mondrian";
assertTrue( exporterSpy.parseXmlaEnabled( dsInfo ) );
}
@Test
public void testExportMondrianSchemas_noCatalogs() throws Exception {
PentahoSystem.registerObject( mondrianCatalogService );
exporterSpy.setMondrianCatalogRepositoryHelper( mondrianCatalogRepositoryHelper );
exporterSpy.exportMondrianSchemas();
verify( exportManifest, never() ).addMondrian( any( ExportManifestMondrian.class ) );
verify( mondrianCatalogRepositoryHelper, never() ).getModrianSchemaFiles( anyString() );
}
@Test
public void testExportMondrianSchemas() throws Exception {
final String catalogName = "test";
String dataSourceInfo = "EnableXmla=\"true\"";
executeExportMondrianSchemasForDataSourceInfo( catalogName, dataSourceInfo );
verify( exportManifest ).addMondrian( any( ExportManifestMondrian.class ) );
verify( mondrianCatalogRepositoryHelper ).getModrianSchemaFiles( anyString() );
assertEquals( catalogName, exportManifest.getMondrianList().get( 0 ).getCatalogName() );
assertTrue( exportManifest.getMondrianList().get( 0 ).isXmlaEnabled() );
verify( exporterSpy.zos ).putNextEntry( any( ZipEntry.class ) );
}
@Test
public void testExportMondrianSchemas_AdditionalParametersSaved() throws Exception {
final String parameterName = "AdditionalParameter";
final String parameterValue = "TestValue";
final String expectedParameterValue = "TestValue";
final String dataSourceInfo = "EnableXmla=\"true\";" + parameterName + "=" + parameterValue;
String catalogName = "test";
executeExportMondrianSchemasForDataSourceInfo( catalogName, dataSourceInfo );
String returnedParameterValue = exportManifest.getMondrianList().get( 0 ).getParameters().get( parameterName );
assertNotNull( returnedParameterValue );
assertEquals( returnedParameterValue, expectedParameterValue );
}
@Test
public void testPerformExportMondrianSchemas_XmlUnsafeDataSourceInfoSaved() throws IOException {
final String dataSourceInfo = "DataSource=\""DS "Test's" & <Fun>"\";"
+ "DynamicSchemaProcessor=\""DSP's & "Other" <stuff>"\";";
final String dataSourceExpectedValue = "\"DS \"Test's\" & <Fun>\"";
final String dynamicSchemaProcessorExpectedValue = "\"DSP's & \"Other\" <stuff>\"";
executeExportMondrianSchemasForDataSourceInfo( "", dataSourceInfo );
String returnedParameterValue = exportManifest.getMondrianList().get( 0 ).getParameters().get( "DataSource" );
assertNotNull( returnedParameterValue );
assertEquals( returnedParameterValue, dataSourceExpectedValue );
returnedParameterValue = exportManifest.getMondrianList().get( 0 ).getParameters().get( "DynamicSchemaProcessor" );
assertNotNull( returnedParameterValue );
assertEquals( returnedParameterValue, dynamicSchemaProcessorExpectedValue );
}
private void executeExportMondrianSchemasForDataSourceInfo( String catalogName, String dataSourceInfo ) throws IOException {
PentahoSystem.registerObject( mondrianCatalogService );
exporterSpy.setMondrianCatalogRepositoryHelper( mondrianCatalogRepositoryHelper );
List<MondrianCatalog> catalogs = new ArrayList<>();
MondrianCatalog catalog = new MondrianCatalog( catalogName, dataSourceInfo, null, null );
catalogs.add( catalog );
when( mondrianCatalogService.listCatalogs( any( IPentahoSession.class ), anyBoolean() ) ).thenReturn( catalogs );
Map<String, InputStream> inputMap = new HashMap<>();
InputStream is = mock( InputStream.class );
when( is.read( any( ( new byte[] {} ).getClass() ) ) ).thenReturn( -1 );
inputMap.put( catalogName, is );
when( mondrianCatalogRepositoryHelper.getModrianSchemaFiles( catalogName ) ).thenReturn( inputMap );
exporterSpy.zos = mock( ZipOutputStream.class );
exporterSpy.exportMondrianSchemas();
}
@Test
public void testExportMetaStore() throws Exception {
exporterSpy.zos = mock( ZipOutputStream.class );
IMetaStore metastore = mock( IMetaStore.class );
exporterSpy.setRepoMetaStore( metastore );
ExportManifest manifest = mock( ExportManifest.class );
exporterSpy.setExportManifest( manifest );
exporterSpy.exportMetastore();
verify( exporterSpy.zos ).putNextEntry( any( ZipEntry.class ) );
verify( manifest ).setMetaStore( any( ExportManifestMetaStore.class ) );
}
@Test
public void testIsExportCandidate() throws Exception {
assertTrue( exporter.isExportCandidate( "/etc" ) );
assertTrue( exporter.isExportCandidate( "/etc/operations_mart" ) );
assertTrue( exporter.isExportCandidate( "/etc/operations_mart/someSubFolder" ) );
assertTrue( exporter.isExportCandidate( "/public" ) );
assertTrue( exporter.isExportCandidate( "/home" ) );
assertFalse( exporter.isExportCandidate( "/etc/someRandomFolder" ) );
assertFalse( exporter.isExportCandidate( "/etc/someRandomFolder/someSubFOlder" ) );
assertFalse( exporter.isExportCandidate( "/etc/mondrian" ) );
assertFalse( exporter.isExportCandidate( "/etc/metadata" ) );
assertFalse( exporter.isExportCandidate( "/etc/metastore" ) );
assertFalse( exporter.isExportCandidate( "/etc/olap-servers" ) );
assertFalse( exporter.isExportCandidate( "/etc/models" ) );
assertFalse( exporter.isExportCandidate( "/etc/pdi" ) );
}
}