#! /usr/bin/env python

# FIXME: if it requires a dirac.cfg it is not a unit test and should be moved to tests directory


from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
import unittest
import time
import os
import shutil
import sys
import six

from DIRAC.Core.Base.Script import parseCommandLine, getPositionalArgs

parseCommandLine()

from DIRAC.Resources.Storage.StorageFactory import StorageFactory
from DIRAC.Core.Utilities.File import getSize

positionalArgs = getPositionalArgs()

__RCSID__ = "$Id$"

if len(positionalArgs) < 2:
    print("Usage: TestStoragePlugIn.py StorageElement plugin")
    sys.exit()
else:
    storageElementToTest = positionalArgs[0]
    plugin = positionalArgs[1]


class StoragePlugInTestCase(unittest.TestCase):
    """Base class for the StoragePlugin test cases"""

    def setUp(self):

        factory = StorageFactory("lhcb")
        res = factory.getStorages(storageElementToTest, [plugin])
        self.assertTrue(res["OK"])
        storageDetails = res["Value"]
        self.storage = storageDetails["StorageObjects"][0]
        self.storage.changeDirectory("lhcb/test/unit-test/TestStoragePlugIn")
        destDir = self.storage.getCurrentURL("")["Value"]
        res = self.storage.createDirectory(destDir)
        self.assertTrue(res["OK"])
        self.assertTrue(destDir in res["Value"]["Successful"])
        self.assertTrue(res["Value"]["Successful"][destDir])
        self.numberOfFiles = 1

    def tearDown(self):
        remoteDir = self.storage.getCurrentURL("")["Value"]
        _ = self.storage.removeDirectory(remoteDir, True)


class DirectoryTestCase(StoragePlugInTestCase):
    def test_putRemoveDirectory(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tPut Directory test\n"
        )
        # First clean the remote directory incase something was left there
        remoteDir = self.storage.getCurrentURL("")["Value"]
        _ = self.storage.removeDirectory(remoteDir, True)

        # Create a local directory to upload
        localDir = "/tmp/unit-test"
        srcFile = "/etc/group"
        sizeOfLocalFile = getSize(srcFile)
        if not os.path.exists(localDir):
            os.mkdir(localDir)
        for i in range(self.numberOfFiles):
            shutil.copy(srcFile, "%s/testFile.%s" % (localDir, time.time()))
            time.sleep(1)

        # Check that we can successfully upload the directory to the storage element
        dirDict = {remoteDir: localDir}
        putDirRes = self.storage.putDirectory(dirDict)
        # Now remove the remove directory
        removeDirRes = self.storage.removeDirectory(remoteDir, True)
        # Clean up the locally created directory
        shutil.rmtree(localDir)

        # Perform the checks for the put dir operation
        self.assertTrue(putDirRes["OK"])
        self.assertTrue(remoteDir in putDirRes["Value"]["Successful"])
        if putDirRes["Value"]["Successful"][remoteDir]["Files"]:
            self.assertEqual(putDirRes["Value"]["Successful"][remoteDir]["Files"], self.numberOfFiles)
            self.assertEqual(putDirRes["Value"]["Successful"][remoteDir]["Size"], self.numberOfFiles * sizeOfLocalFile)
        self.assertTrue(isinstance(putDirRes["Value"]["Successful"][remoteDir]["Files"], int))
        self.assertTrue(type(putDirRes["Value"]["Successful"][remoteDir]["Size"]) in six.integer_types)
        # Perform the checks for the remove dir operation
        self.assertTrue(removeDirRes["OK"])
        self.assertTrue(remoteDir in removeDirRes["Value"]["Successful"])
        if removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"]:
            self.assertEqual(removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"], self.numberOfFiles)
            self.assertEqual(
                removeDirRes["Value"]["Successful"][remoteDir]["SizeRemoved"], self.numberOfFiles * sizeOfLocalFile
            )
        self.assertTrue(isinstance(removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"], int))
        self.assertTrue(type(removeDirRes["Value"]["Successful"][remoteDir]["SizeRemoved"]) in six.integer_types)

    def test_isDirectory(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tIs Directory test\n"
        )
        # Test that we can determine what is a directory
        destDir = self.storage.getCurrentURL("")["Value"]
        isDirRes = self.storage.isDirectory(destDir)
        # Test that we can determine that a directory is not a directory
        dummyDir = self.storage.getCurrentURL("NonExistantFile")["Value"]
        nonExistantDirRes = self.storage.isDirectory(dummyDir)

        # Check the is directory operation
        self.assertTrue(isDirRes["OK"])
        self.assertTrue(destDir in isDirRes["Value"]["Successful"])
        self.assertTrue(isDirRes["Value"]["Successful"][destDir])
        # Check the non existant directory operation
        self.assertTrue(nonExistantDirRes["OK"])
        self.assertTrue(dummyDir in nonExistantDirRes["Value"]["Failed"])
        expectedError = "Path does not exist"
        self.assertTrue(expectedError in nonExistantDirRes["Value"]["Failed"][dummyDir])

    def test_putGetDirectoryMetadata(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tGet Directory Metadata test\n"
        )
        # First clean the remote directory incase something was left there
        remoteDir = self.storage.getCurrentURL("")["Value"]
        _ = self.storage.removeDirectory(remoteDir, True)

        # Create a local directory to upload
        localDir = "/tmp/unit-test"
        srcFile = "/etc/group"
        sizeOfLocalFile = getSize(srcFile)
        if not os.path.exists(localDir):
            os.mkdir(localDir)
        for i in range(self.numberOfFiles):
            shutil.copy(srcFile, "%s/testFile.%s" % (localDir, time.time()))
            time.sleep(1)

        # Check that we can successfully upload the directory to the storage element
        dirDict = {remoteDir: localDir}
        putDirRes = self.storage.putDirectory(dirDict)

        # Get the directory metadata
        getMetadataRes = self.storage.getDirectoryMetadata(remoteDir)
        # Now remove the remove directory
        removeDirRes = self.storage.removeDirectory(remoteDir, True)
        # Clean up the locally created directory
        shutil.rmtree(localDir)

        # Perform the checks for the put dir operation
        self.assertTrue(putDirRes["OK"])
        self.assertTrue(remoteDir in putDirRes["Value"]["Successful"])
        if putDirRes["Value"]["Successful"][remoteDir]["Files"]:
            self.assertEqual(putDirRes["Value"]["Successful"][remoteDir]["Files"], self.numberOfFiles)
            self.assertEqual(putDirRes["Value"]["Successful"][remoteDir]["Size"], self.numberOfFiles * sizeOfLocalFile)
        self.assertTrue(isinstance(putDirRes["Value"]["Successful"][remoteDir]["Files"], int))
        self.assertTrue(type(putDirRes["Value"]["Successful"][remoteDir]["Size"]) in six.integer_types)
        # Perform the checks for the get metadata operation
        self.assertTrue(getMetadataRes["OK"])
        self.assertTrue(remoteDir in getMetadataRes["Value"]["Successful"])
        resDict = getMetadataRes["Value"]["Successful"][remoteDir]
        self.assertTrue("Mode" in resDict)
        self.assertTrue(isinstance(resDict["Mode"], int))
        # Perform the checks for the remove directory operation
        if removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"]:
            self.assertEqual(removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"], self.numberOfFiles)
            self.assertEqual(
                removeDirRes["Value"]["Successful"][remoteDir]["SizeRemoved"], self.numberOfFiles * sizeOfLocalFile
            )
        self.assertTrue(isinstance(removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"], int))
        self.assertTrue(type(removeDirRes["Value"]["Successful"][remoteDir]["SizeRemoved"]) in six.integer_types)

    def test_putGetDirectorySize(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tGet Directory Size test\n"
        )
        # First clean the remote directory incase something was left there
        remoteDir = self.storage.getCurrentURL("")["Value"]
        _ = self.storage.removeDirectory(remoteDir, True)

        # Create a local directory to upload
        localDir = "/tmp/unit-test"
        srcFile = "/etc/group"
        sizeOfLocalFile = getSize(srcFile)
        if not os.path.exists(localDir):
            os.mkdir(localDir)
        for i in range(self.numberOfFiles):
            shutil.copy(srcFile, "%s/testFile.%s" % (localDir, time.time()))
            time.sleep(1)
        # Check that we can successfully upload the directory to the storage element
        dirDict = {remoteDir: localDir}
        putDirRes = self.storage.putDirectory(dirDict)
        # Now get the directory size
        getDirSizeRes = self.storage.getDirectorySize(remoteDir)
        # Now remove the remove directory
        removeDirRes = self.storage.removeDirectory(remoteDir, True)
        # Clean up the locally created directory
        shutil.rmtree(localDir)

        # Perform the checks for the put dir operation
        self.assertTrue(putDirRes["OK"])
        self.assertTrue(remoteDir in putDirRes["Value"]["Successful"])
        if putDirRes["Value"]["Successful"][remoteDir]["Files"]:
            self.assertEqual(putDirRes["Value"]["Successful"][remoteDir]["Files"], self.numberOfFiles)
            self.assertEqual(putDirRes["Value"]["Successful"][remoteDir]["Size"], self.numberOfFiles * sizeOfLocalFile)
        self.assertTrue(isinstance(putDirRes["Value"]["Successful"][remoteDir]["Files"], int))
        self.assertTrue(type(putDirRes["Value"]["Successful"][remoteDir]["Size"]) in six.integer_types)
        # Now perform the checks for the get directory size operation
        self.assertTrue(getDirSizeRes["OK"])
        self.assertTrue(remoteDir in getDirSizeRes["Value"]["Successful"])
        resDict = getDirSizeRes["Value"]["Successful"][remoteDir]
        self.assertTrue(type(resDict["Size"]) in six.integer_types)
        self.assertTrue(isinstance(resDict["Files"], int))
        # Perform the checks for the remove directory operation
        self.assertTrue(removeDirRes["OK"])
        self.assertTrue(remoteDir in removeDirRes["Value"]["Successful"])
        if removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"]:
            self.assertEqual(removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"], self.numberOfFiles)
            self.assertEqual(
                removeDirRes["Value"]["Successful"][remoteDir]["SizeRemoved"], self.numberOfFiles * sizeOfLocalFile
            )
        self.assertTrue(isinstance(removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"], int))
        self.assertTrue(type(removeDirRes["Value"]["Successful"][remoteDir]["SizeRemoved"]) in six.integer_types)

    def test_putListDirectory(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tList Directory test\n"
        )
        # First clean the remote directory incase something was left there
        remoteDir = self.storage.getCurrentURL("")["Value"]
        _ = self.storage.removeDirectory(remoteDir, True)

        # Create a local directory to upload
        localDir = "/tmp/unit-test"
        srcFile = "/etc/group"
        sizeOfLocalFile = getSize(srcFile)
        if not os.path.exists(localDir):
            os.mkdir(localDir)
        for i in range(self.numberOfFiles):
            shutil.copy(srcFile, "%s/testFile.%s" % (localDir, time.time()))
            time.sleep(1)
        # Check that we can successfully upload the directory to the storage element
        dirDict = {remoteDir: localDir}
        putDirRes = self.storage.putDirectory(dirDict)
        # List the remote directory
        listDirRes = self.storage.listDirectory(remoteDir)
        # Now remove the remove directory
        removeDirRes = self.storage.removeDirectory(remoteDir, True)
        # Clean up the locally created directory
        shutil.rmtree(localDir)

        # Perform the checks for the put dir operation
        self.assertTrue(putDirRes["OK"])
        self.assertTrue(remoteDir in putDirRes["Value"]["Successful"])
        if putDirRes["Value"]["Successful"][remoteDir]["Files"]:
            self.assertEqual(putDirRes["Value"]["Successful"][remoteDir]["Files"], self.numberOfFiles)
            self.assertEqual(putDirRes["Value"]["Successful"][remoteDir]["Size"], self.numberOfFiles * sizeOfLocalFile)
        self.assertTrue(isinstance(putDirRes["Value"]["Successful"][remoteDir]["Files"], int))
        self.assertTrue(type(putDirRes["Value"]["Successful"][remoteDir]["Size"]) in six.integer_types)
        # Perform the checks for the list dir operation
        self.assertTrue(listDirRes["OK"])
        self.assertTrue(remoteDir in listDirRes["Value"]["Successful"])
        resDict = listDirRes["Value"]["Successful"][remoteDir]
        self.assertTrue("SubDirs" in resDict)
        self.assertTrue("Files" in resDict)
        self.assertEqual(len(resDict["Files"]), self.numberOfFiles)
        # Perform the checks for the remove directory operation
        self.assertTrue(removeDirRes["OK"])
        self.assertTrue(remoteDir in removeDirRes["Value"]["Successful"])
        if removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"]:
            self.assertEqual(removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"], self.numberOfFiles)
            self.assertEqual(
                removeDirRes["Value"]["Successful"][remoteDir]["SizeRemoved"], self.numberOfFiles * sizeOfLocalFile
            )
        self.assertTrue(isinstance(removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"], int))
        self.assertTrue(type(removeDirRes["Value"]["Successful"][remoteDir]["SizeRemoved"]) in six.integer_types)

    def test_putGetDirectory(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tGet Directory test\n"
        )
        # First clean the remote directory incase something was left there
        remoteDir = self.storage.getCurrentURL("")["Value"]
        _ = self.storage.removeDirectory(remoteDir, True)

        # Create a local directory to upload
        localDir = "/tmp/unit-test"
        srcFile = "/etc/group"
        sizeOfLocalFile = getSize(srcFile)
        if not os.path.exists(localDir):
            os.mkdir(localDir)
        for i in range(self.numberOfFiles):
            shutil.copy(srcFile, "%s/testFile.%s" % (localDir, time.time()))
            time.sleep(1)
        # Check that we can successfully upload the directory to the storage element
        dirDict = {remoteDir: localDir}
        putDirRes = self.storage.putDirectory(dirDict)
        # Clean up the locally created directory
        shutil.rmtree(localDir)
        # Check that we can get directories from the storage element
        getDirRes = self.storage.getDirectory(remoteDir, localPath=localDir)
        # Now remove the remove directory
        removeDirRes = self.storage.removeDirectory(remoteDir, True)
        # Clean up the locally created directory
        shutil.rmtree(localDir)

        # Perform the checks for the put dir operation
        self.assertTrue(putDirRes["OK"])
        self.assertTrue(remoteDir in putDirRes["Value"]["Successful"])
        if putDirRes["Value"]["Successful"][remoteDir]["Files"]:
            self.assertEqual(putDirRes["Value"]["Successful"][remoteDir]["Files"], self.numberOfFiles)
            self.assertEqual(putDirRes["Value"]["Successful"][remoteDir]["Size"], self.numberOfFiles * sizeOfLocalFile)
        self.assertTrue(isinstance(putDirRes["Value"]["Successful"][remoteDir]["Files"], int))
        self.assertTrue(type(putDirRes["Value"]["Successful"][remoteDir]["Size"]) in six.integer_types)
        # Perform the checks for the get dir operation
        self.assertTrue(getDirRes["OK"])
        self.assertTrue(remoteDir in getDirRes["Value"]["Successful"])
        resDict = getDirRes["Value"]["Successful"][remoteDir]
        if resDict["Files"]:
            self.assertEqual(resDict["Files"], self.numberOfFiles)
            self.assertEqual(resDict["Size"], self.numberOfFiles * sizeOfLocalFile)
        self.assertTrue(isinstance(resDict["Files"], int))
        self.assertTrue(type(resDict["Size"]) in six.integer_types)
        # Perform the checks for the remove directory operation
        self.assertTrue(removeDirRes["OK"])
        self.assertTrue(remoteDir in removeDirRes["Value"]["Successful"])
        if removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"]:
            self.assertEqual(removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"], self.numberOfFiles)
            self.assertEqual(
                removeDirRes["Value"]["Successful"][remoteDir]["SizeRemoved"], self.numberOfFiles * sizeOfLocalFile
            )
        self.assertTrue(isinstance(removeDirRes["Value"]["Successful"][remoteDir]["FilesRemoved"], int))
        self.assertTrue(type(removeDirRes["Value"]["Successful"][remoteDir]["SizeRemoved"]) in six.integer_types)


class FileTestCase(StoragePlugInTestCase):
    def test_putRemoveFile(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tPut and Remove test\n"
        )

        # Make sure that we can actually upload a file properly
        srcFile = "/etc/group"
        srcFileSize = getSize(srcFile)
        testFileName = "testFile.%s" % time.time()
        destFile = self.storage.getCurrentURL(testFileName)["Value"]
        fileDict = {destFile: srcFile}
        putFileRes = self.storage.putFile(fileDict)
        # Make sure we are able to remove the file
        removeFileRes = self.storage.removeFile(destFile)

        # Check the successful put file operation
        self.assertTrue(putFileRes["OK"])
        self.assertTrue(destFile in putFileRes["Value"]["Successful"])
        self.assertEqual(putFileRes["Value"]["Successful"][destFile], srcFileSize)
        # Check the remove file operation
        self.assertTrue(removeFileRes["OK"])
        self.assertTrue(destFile in removeFileRes["Value"]["Successful"])
        self.assertTrue(removeFileRes["Value"]["Successful"][destFile])

    def test_putGetFile(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tPut and Get test\n"
        )

        # First upload a file to the storage
        srcFile = "/etc/group"
        srcFileSize = getSize(srcFile)
        testFileName = "testFile.%s" % time.time()
        remoteFile = self.storage.getCurrentURL(testFileName)["Value"]
        fileDict = {remoteFile: srcFile}
        putFileRes = self.storage.putFile(fileDict)

        # Then make sure we can get a local copy of the file
        getFileRes = self.storage.getFile(remoteFile)
        # Cleanup the remote mess
        removeFileRes = self.storage.removeFile(remoteFile)
        # Cleanup the mess locally
        os.remove(testFileName)

        # Check the put operation
        self.assertTrue(putFileRes["OK"])
        self.assertTrue(remoteFile in putFileRes["Value"]["Successful"])
        self.assertEqual(putFileRes["Value"]["Successful"][remoteFile], srcFileSize)
        # Check the get operation
        self.assertTrue(getFileRes["OK"])
        self.assertTrue(remoteFile in getFileRes["Value"]["Successful"])
        self.assertEqual(getFileRes["Value"]["Successful"][remoteFile], srcFileSize)
        # Check the remove operation
        self.assertTrue(removeFileRes["OK"])
        self.assertTrue(remoteFile in removeFileRes["Value"]["Successful"])
        self.assertTrue(removeFileRes["Value"]["Successful"][remoteFile])

    def test_putExistsFile(self):
        print("\n\n#########################################################" "################\n\n\t\t\tExists test\n")
        # First upload a file to the storage
        srcFile = "/etc/group"
        srcFileSize = getSize(srcFile)
        testFileName = "testFile.%s" % time.time()
        remoteFile = self.storage.getCurrentURL(testFileName)["Value"]
        fileDict = {remoteFile: srcFile}
        putFileRes = self.storage.putFile(fileDict)
        # Then get the file's existance
        existsFileRes = self.storage.exists(remoteFile)
        # Now remove the file
        removeFileRes = self.storage.removeFile(remoteFile)
        # Check  again that the file exists
        failedExistRes = self.storage.exists(remoteFile)

        # Check the put file operation
        self.assertTrue(putFileRes["OK"])
        self.assertTrue(remoteFile in putFileRes["Value"]["Successful"])
        self.assertEqual(putFileRes["Value"]["Successful"][remoteFile], srcFileSize)
        # Check the exists operation
        self.assertTrue(existsFileRes["OK"])
        self.assertTrue(remoteFile in existsFileRes["Value"]["Successful"])
        self.assertTrue(existsFileRes["Value"]["Successful"][remoteFile])
        # Check the removal operation
        self.assertTrue(removeFileRes["OK"])
        self.assertTrue(remoteFile in removeFileRes["Value"]["Successful"])
        # Check the failed exists operation
        self.assertTrue(failedExistRes["OK"])
        self.assertTrue(remoteFile in failedExistRes["Value"]["Successful"])
        self.assertFalse(failedExistRes["Value"]["Successful"][remoteFile])

    def test_putIsFile(self):
        print(
            "\n\n#########################################################" "################\n\n\t\t\tIs file test\n"
        )
        # First upload a file to the storage
        srcFile = "/etc/group"
        srcFileSize = getSize(srcFile)
        testFileName = "testFile.%s" % time.time()
        remoteFile = self.storage.getCurrentURL(testFileName)["Value"]
        fileDict = {remoteFile: srcFile}
        putFileRes = self.storage.putFile(fileDict)
        # Check we are able to determine that it is a file
        isFileRes = self.storage.isFile(remoteFile)
        # Clean up the remote mess
        removeFileRes = self.storage.removeFile(remoteFile)
        # Check that everything isn't a file
        remoteDir = os.path.dirname(remoteFile)
        failedIsFileRes = self.storage.isFile(remoteDir)

        # Check the put file operation
        self.assertTrue(putFileRes["OK"])
        self.assertTrue(remoteFile in putFileRes["Value"]["Successful"])
        self.assertTrue(putFileRes["Value"]["Successful"][remoteFile])
        self.assertEqual(putFileRes["Value"]["Successful"][remoteFile], srcFileSize)
        # Check the is file operation
        self.assertTrue(isFileRes["OK"])
        self.assertTrue(remoteFile in isFileRes["Value"]["Successful"])
        self.assertTrue(isFileRes["Value"]["Successful"][remoteFile])
        # check the remove file operation
        self.assertTrue(removeFileRes["OK"])
        self.assertTrue(remoteFile in removeFileRes["Value"]["Successful"])
        # Check that the directory is not a file
        self.assertTrue(failedIsFileRes["OK"])
        self.assertTrue(remoteDir in failedIsFileRes["Value"]["Successful"])
        self.assertFalse(failedIsFileRes["Value"]["Successful"][remoteDir])

    def test_putGetFileMetaData(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tGet file metadata test\n"
        )
        # First upload a file to the storage
        srcFile = "/etc/group"
        srcFileSize = getSize(srcFile)
        testFileName = "testFile.%s" % time.time()
        remoteFile = self.storage.getCurrentURL(testFileName)["Value"]
        fileDict = {remoteFile: srcFile}
        putFileRes = self.storage.putFile(fileDict)
        # Check that we can get the file metadata
        getMetadataRes = self.storage.getFileMetadata(remoteFile)
        # Clean up the remote mess
        removeFileRes = self.storage.removeFile(remoteFile)
        # See what happens with non existant files
        failedMetadataRes = self.storage.getFileMetadata(remoteFile)
        # Check directories are handled properly
        remoteDir = os.path.dirname(remoteFile)
        directoryMetadataRes = self.storage.getFileMetadata(remoteDir)

        # Check the put file operation
        self.assertTrue(putFileRes["OK"])
        self.assertTrue(remoteFile in putFileRes["Value"]["Successful"])
        self.assertTrue(putFileRes["Value"]["Successful"][remoteFile])
        self.assertEqual(putFileRes["Value"]["Successful"][remoteFile], srcFileSize)
        # Check the get metadata operation
        self.assertTrue(getMetadataRes["OK"])
        self.assertTrue(remoteFile in getMetadataRes["Value"]["Successful"])
        fileMetaData = getMetadataRes["Value"]["Successful"][remoteFile]
        self.assertTrue(fileMetaData["Cached"])
        self.assertFalse(fileMetaData["Migrated"])
        self.assertEqual(fileMetaData["Size"], srcFileSize)
        # check the remove file operation
        self.assertTrue(removeFileRes["OK"])
        self.assertTrue(remoteFile in removeFileRes["Value"]["Successful"])
        # Check the get metadata for non existant file
        self.assertTrue(failedMetadataRes["OK"])
        self.assertTrue(remoteFile in failedMetadataRes["Value"]["Failed"])
        expectedError = "File does not exist"
        self.assertTrue(expectedError in failedMetadataRes["Value"]["Failed"][remoteFile])
        # Check that metadata operation with a directory
        self.assertTrue(directoryMetadataRes["OK"])
        self.assertTrue(remoteDir in directoryMetadataRes["Value"]["Failed"])
        expectedError = "Supplied path is not a file"
        self.assertTrue(expectedError in directoryMetadataRes["Value"]["Failed"][remoteDir])

    def test_putGetFileSize(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tGet file size test\n"
        )
        # First upload a file to the storage
        srcFile = "/etc/group"
        srcFileSize = getSize(srcFile)
        testFileName = "testFile.%s" % time.time()
        remoteFile = self.storage.getCurrentURL(testFileName)["Value"]
        fileDict = {remoteFile: srcFile}
        putFileRes = self.storage.putFile(fileDict)
        # Check that we can get the file size
        getSizeRes = self.storage.getFileSize(remoteFile)
        # Clean up the remote mess
        removeFileRes = self.storage.removeFile(remoteFile)
        # Check non existant files
        failedSizeRes = self.storage.getFileMetadata(remoteFile)
        # Check directories are handled properly
        remoteDir = os.path.dirname(remoteFile)
        directorySizeRes = self.storage.getFileSize(remoteDir)

        # Check the put file operation
        self.assertTrue(putFileRes["OK"])
        self.assertTrue(remoteFile in putFileRes["Value"]["Successful"])
        self.assertTrue(putFileRes["Value"]["Successful"][remoteFile])
        self.assertEqual(putFileRes["Value"]["Successful"][remoteFile], srcFileSize)
        # Check that we got the file size correctly
        self.assertTrue(getSizeRes["OK"])
        self.assertTrue(remoteFile in getSizeRes["Value"]["Successful"])
        self.assertEqual(getSizeRes["Value"]["Successful"][remoteFile], srcFileSize)
        # check the remove file operation
        self.assertTrue(removeFileRes["OK"])
        self.assertTrue(remoteFile in removeFileRes["Value"]["Successful"])
        # Check the get size with non existant file works properly
        self.assertTrue(failedSizeRes["OK"])
        self.assertTrue(remoteFile in failedSizeRes["Value"]["Failed"])
        expectedError = "File does not exist"
        self.assertTrue(expectedError in failedSizeRes["Value"]["Failed"][remoteFile])
        # Check that the passing a directory is handled correctly
        self.assertTrue(directorySizeRes["OK"])
        self.assertTrue(remoteDir in directorySizeRes["Value"]["Failed"])
        expectedError = "Supplied path is not a file"
        self.assertTrue(expectedError in directorySizeRes["Value"]["Failed"][remoteDir])

    def test_putPrestageFile(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tFile prestage test\n"
        )
        # First upload a file to the storage
        srcFile = "/etc/group"
        srcFileSize = getSize(srcFile)
        testFileName = "testFile.%s" % time.time()
        remoteFile = self.storage.getCurrentURL(testFileName)["Value"]
        fileDict = {remoteFile: srcFile}
        putFileRes = self.storage.putFile(fileDict)
        # Check that we can issue a stage request
        prestageRes = self.storage.prestageFile(remoteFile)
        # Clean up the remote mess
        removeFileRes = self.storage.removeFile(remoteFile)
        # Check what happens with deleted files
        deletedPrestageRes = self.storage.prestageFile(remoteFile)

        # Check the put file operation
        self.assertTrue(putFileRes["OK"])
        self.assertTrue(remoteFile in putFileRes["Value"]["Successful"])
        self.assertTrue(putFileRes["Value"]["Successful"][remoteFile])
        self.assertEqual(putFileRes["Value"]["Successful"][remoteFile], srcFileSize)
        # Check the prestage file operation
        self.assertTrue(prestageRes["OK"])
        self.assertTrue(remoteFile in prestageRes["Value"]["Successful"])
        self.assertTrue(prestageRes["Value"]["Successful"][remoteFile])
        # Check the remove file operation
        self.assertTrue(removeFileRes["OK"])
        self.assertTrue(remoteFile in removeFileRes["Value"]["Successful"])
        # Check that pre-staging non-existant file fails
        self.assertTrue(deletedPrestageRes["OK"])
        self.assertTrue(remoteFile in deletedPrestageRes["Value"]["Failed"])
        expectedError = "No such file or directory"
        self.assertTrue(expectedError in deletedPrestageRes["Value"]["Failed"][remoteFile])

    def test_putFilegetTransportURL(self):
        print(
            "\n\n#########################################################" "################\n\n\t\t\tGet tURL test\n"
        )
        # First upload a file to the storage
        srcFile = "/etc/group"
        srcFileSize = getSize(srcFile)
        testFileName = "testFile.%s" % time.time()
        remoteFile = self.storage.getCurrentURL(testFileName)["Value"]
        fileDict = {remoteFile: srcFile}
        putFileRes = self.storage.putFile(fileDict)
        # Check that we can get a turl
        getTurlRes = self.storage.getTransportURL(remoteFile)
        # Clean up the remote mess
        removeFileRes = self.storage.removeFile(remoteFile)
        # Try and get a turl for a non existant file
        failedGetTurlRes = self.storage.getTransportURL(remoteFile)

        # Check the put file operation
        self.assertTrue(putFileRes["OK"])
        self.assertTrue(remoteFile in putFileRes["Value"]["Successful"])
        self.assertTrue(putFileRes["Value"]["Successful"][remoteFile])
        self.assertEqual(putFileRes["Value"]["Successful"][remoteFile], srcFileSize)
        # check the get turl operation
        self.assertTrue(getTurlRes["OK"])
        self.assertTrue(remoteFile in getTurlRes["Value"]["Successful"])
        # check the remove file operation
        self.assertTrue(removeFileRes["OK"])
        self.assertTrue(remoteFile in removeFileRes["Value"]["Successful"])
        # Check the get turl with non existant file operation
        self.assertTrue(failedGetTurlRes["OK"])
        self.assertTrue(remoteFile in failedGetTurlRes["Value"]["Failed"])
        expectedError = "File does not exist"
        self.assertTrue(expectedError in failedGetTurlRes["Value"]["Failed"][remoteFile])

    def test_putPinRelease(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tPin and Release test\n"
        )
        # First upload a file to the storage
        srcFile = "/etc/group"
        srcFileSize = getSize(srcFile)
        testFileName = "testFile.%s" % time.time()
        remoteFile = self.storage.getCurrentURL(testFileName)["Value"]
        fileDict = {remoteFile: srcFile}
        putFileRes = self.storage.putFile(fileDict)
        # Check that we can pin the file
        pinFileRes = self.storage.pinFile(remoteFile)
        srmID = ""
        if pinFileRes["OK"]:
            if remoteFile in pinFileRes["Value"]["Successful"]:
                srmID = pinFileRes["Value"]["Successful"][remoteFile]
        # Check that we can release the file
        releaseFileRes = self.storage.releaseFile({remoteFile: srmID})
        # Clean up the mess
        removeFileRes = self.storage.removeFile(remoteFile)

        # Check the put file operation
        self.assertTrue(putFileRes["OK"])
        self.assertTrue(remoteFile in putFileRes["Value"]["Successful"])
        self.assertTrue(putFileRes["Value"]["Successful"][remoteFile])
        self.assertEqual(putFileRes["Value"]["Successful"][remoteFile], srcFileSize)
        # Check the pin file operation
        self.assertTrue(pinFileRes["OK"])
        self.assertTrue(remoteFile in pinFileRes["Value"]["Successful"])
        self.assertTrue(type(pinFileRes["Value"]["Successful"][remoteFile]) in six.string_types)
        # Check the release file operation
        self.assertTrue(releaseFileRes["OK"])
        self.assertTrue(remoteFile in releaseFileRes["Value"]["Successful"])
        # check the remove file operation
        self.assertTrue(removeFileRes["OK"])
        self.assertTrue(remoteFile in removeFileRes["Value"]["Successful"])

    def test_putPrestageStatus(self):
        print(
            "\n\n#########################################################"
            "################\n\n\t\t\tPrestage status test\n"
        )
        # First upload a file to the storage
        srcFile = "/etc/group"
        srcFileSize = getSize(srcFile)
        testFileName = "testFile.%s" % time.time()
        remoteFile = self.storage.getCurrentURL(testFileName)["Value"]
        fileDict = {remoteFile: srcFile}
        putFileRes = self.storage.putFile(fileDict)
        # Check that we can issue a stage request
        prestageRes = self.storage.prestageFile(remoteFile)
        srmID = ""
        if prestageRes["OK"]:
            if remoteFile in prestageRes["Value"]["Successful"]:
                srmID = prestageRes["Value"]["Successful"][remoteFile]
        # Take a quick break to allow the SRM to realise the file is available
        sleepTime = 10
        print("Sleeping for %s seconds" % sleepTime)
        time.sleep(sleepTime)
        # Check that we can monitor the stage request
        prestageStatusRes = self.storage.prestageFileStatus({remoteFile: srmID})
        # Clean up the remote mess
        removeFileRes = self.storage.removeFile(remoteFile)

        # Check the put file operation
        self.assertTrue(putFileRes["OK"])
        self.assertTrue(remoteFile in putFileRes["Value"]["Successful"])
        self.assertTrue(putFileRes["Value"]["Successful"][remoteFile])
        self.assertEqual(putFileRes["Value"]["Successful"][remoteFile], srcFileSize)
        # Check the prestage file operation
        self.assertTrue(prestageRes["OK"])
        self.assertTrue(remoteFile in prestageRes["Value"]["Successful"])
        self.assertTrue(prestageRes["Value"]["Successful"][remoteFile])
        self.assertTrue(type(prestageRes["Value"]["Successful"][remoteFile]) in six.string_types)
        # Check the prestage status operation
        self.assertTrue(prestageStatusRes["OK"])
        self.assertTrue(remoteFile in prestageStatusRes["Value"]["Successful"])
        self.assertTrue(prestageStatusRes["Value"]["Successful"][remoteFile])
        # Check the remove file operation
        self.assertTrue(removeFileRes["OK"])
        self.assertTrue(remoteFile in removeFileRes["Value"]["Successful"])


if __name__ == "__main__":
    suite = unittest.defaultTestLoader.loadTestsFromTestCase(FileTestCase)
    suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(DirectoryTestCase))
    testResult = unittest.TextTestRunner(verbosity=2).run(suite)
