/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.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 General Public License for more details.
*
*
* Copyright 2006 - 2016 Pentaho Corporation. All rights reserved.
*/
package org.pentaho.platform.web.http.api.resources.operations;
import org.junit.Before;
import org.junit.Test;
import org.pentaho.platform.api.repository2.unified.IRepositoryFileData;
import org.pentaho.platform.api.repository2.unified.IUnifiedRepository;
import org.pentaho.platform.api.repository2.unified.RepositoryFile;
import org.pentaho.platform.api.repository2.unified.RepositoryFileAcl;
import org.pentaho.platform.api.repository2.unified.RepositoryRequest;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import static org.mockito.Mockito.*;
/**
* @author Ivan Nikolaichuk
*/
/**
* Goals of this test are:
* 1. verify, that recursion ends.
* 2. verify, that accurate number of files and folders were created.
*
* <p/>
* Tests are called N_LevelDeepness, where by deepness meant folders-hierarchy deepness.
* <p/>
* Example:
* <p/>
* 1 level deepness: -folder
* -file
* -file
* <p/>
* 3 level deepness: -folder
* -folder
* -file
* -folder
* -folder
*/
public class CopyFilesOperation_DeepFolderCopyTest {
private static IUnifiedRepository repo;
private static CopyFilesOperation operation;
private RepositoryFile from;
private RepositoryFile to;
@Before
public void init() {
repo = mock( IUnifiedRepository.class );
operation = mock( CopyFilesOperation.class );
doReturn( repo ).when( operation ).getRepository();
from = mockFolder();
to = mockFolder();
doReturn( mockFolder() ).when( repo )
.createFolder( any( Serializable.class ), any( RepositoryFile.class ), any(
RepositoryFileAcl.class ), anyString() );
doCallRealMethod().when( operation ).performFolderDeepCopy( any( RepositoryFile.class ),
any( RepositoryFile.class ), anyInt() );
}
@Test( expected = IllegalArgumentException.class )
public void deepCopyOfFile_Fails() {
RepositoryFile file1 = mockFile();
RepositoryFile file2 = mockFile();
doCallRealMethod().when( operation ).performFolderDeepCopy( file1, file2, null );
operation.performFolderDeepCopy( file1, file2, null );
}
@Test
public void one_LevelDeepness() {
List<RepositoryFile> files = listOfMockedFiles( 3 );
mockRequest( from, files );
operation.performFolderDeepCopy( from, to, CopyFilesOperation.DEFAULT_DEEPNESS );
performVerification( 0, files.size() );
}
@Test
public void two_LevelDeepness() {
int numberOfFolders = 3;
int filesInEachFolder = 3;
List<RepositoryFile> folders = listOfMockedFolders( numberOfFolders );
mockRequest( from, folders );
for ( RepositoryFile folder : folders ) {
mockRequest( folder, listOfMockedFiles( filesInEachFolder ) );
}
operation.performFolderDeepCopy( from, to, CopyFilesOperation.DEFAULT_DEEPNESS );
// one stands for root folder.
performVerification( numberOfFolders, numberOfFolders * filesInEachFolder );
}
@Test
public void six_LevelDeepness_Folders() {
int expectedFolders = 62;
int foldersInEachFolderNotLastLevel = 2;
List<RepositoryFile> foldersSecondLevel = listOfMockedFolders( foldersInEachFolderNotLastLevel );
List<RepositoryFile> foldersThirdLevel = listOfMockedFolders( foldersInEachFolderNotLastLevel );
List<RepositoryFile> foldersForthLevel = listOfMockedFolders( foldersInEachFolderNotLastLevel );
List<RepositoryFile> foldersFiveLevel = listOfMockedFolders( foldersInEachFolderNotLastLevel );
List<RepositoryFile> foldersSixLevel = listOfMockedFolders( foldersInEachFolderNotLastLevel );
mockRequest( from, foldersSecondLevel );
for ( RepositoryFile folder : foldersSecondLevel ) {
mockRequest( folder, foldersThirdLevel );
}
for ( RepositoryFile folder : foldersThirdLevel ) {
mockRequest( folder, foldersForthLevel );
}
for ( RepositoryFile folder : foldersForthLevel ) {
mockRequest( folder, foldersFiveLevel );
}
for ( RepositoryFile folder : foldersFiveLevel ) {
mockRequest( folder, foldersSixLevel );
}
operation.performFolderDeepCopy( from, to, CopyFilesOperation.DEFAULT_DEEPNESS );
performVerification( expectedFolders, 0 );
}
/**
* Verifies: - performFolderDeepCopy method was called {@code newFolders + 1} times, where 1 performs as the first
* method call.
* <p/>
* - there were created {@code numberOfFiles} files. - there were created {@code newFolders} folders.
*/
private void performVerification( int newFolders, int newFiles ) {
// 1 stands for first method-call
verify( operation, times( newFolders + 1 ) )
.performFolderDeepCopy( any( RepositoryFile.class ), any( RepositoryFile.class ), anyInt() );
verify( repo, times( newFolders ) )
.createFolder( any( Serializable.class ), any( RepositoryFile.class ), any( RepositoryFileAcl.class ),
anyString() );
verify( repo, times( newFiles ) ).createFile( any( RepositoryFile.class ), any( RepositoryFile.class ), any(
IRepositoryFileData.class ), anyString() );
}
/**
* Enforces to return provided {@code children}, when making a RepositoryRequest to know {@code folder} content.
*/
private void mockRequest( RepositoryFile folder, List<RepositoryFile> children ) {
RepositoryRequest mockedRequest = mock( RepositoryRequest.class );
doReturn( mockedRequest ).when( operation ).createRepoRequest( eq( folder ), anyInt() );
doReturn( children ).when( repo ).getChildren( mockedRequest );
}
private List<RepositoryFile> listOfMockedFiles( final int files ) {
return listOfMockedRepoFiles( files, false );
}
private List<RepositoryFile> listOfMockedFolders( final int files ) {
return listOfMockedRepoFiles( files, true );
}
private List<RepositoryFile> listOfMockedRepoFiles( final int files, final boolean isFolder ) {
return new ArrayList<RepositoryFile>() { {
for ( int i = 0; i < files; i++ ) {
if ( isFolder ) {
add( mockFolder() );
} else {
add( mockFile() );
}
}
}
};
}
public static RepositoryFile mockFile( String id ) {
RepositoryFile file = mock( RepositoryFile.class );
doReturn( id ).when( file ).getId();
doReturn( false ).when( file ).isFolder();
return file;
}
public static RepositoryFile mockFile() {
return mockFile( generateID() );
}
public static RepositoryFile mockFolder( String id ) {
RepositoryFile folder = mock( RepositoryFile.class );
doReturn( id ).when( folder ).getId();
doReturn( true ).when( folder ).isFolder();
return folder;
}
public static RepositoryFile mockFolder() {
return mockFolder( generateID() );
}
private static String generateID() {
return UUID.randomUUID().toString();
}
}