'''
Tests the upgrade for IOC and HLA applications
Test cases

IOC's
1) Upgrade one IOC in one facility
2) Upgrade two IOC's in one facility
3) Upgrade ALL IOC's in one facility
4) Upgrade two IOC's in two different facilities
5) Upgrade three IOC's in two different facilities
6) Upgrade ALL IOC's in two different facilities
7) Upgrade ALL IOC's in ALL facilities
8) Exception is generated when we specify invalid IOC
9) Exception is generated when we specify invalid facility

HLA
1) Upgrade one facility
2) Upgrade two facilities
3) Upgrade ALL facilities

Misc
1) Test preDeploy and postDeploy
'''

import os
import unittest
import shutil
import subprocess
import json
import multi_facility_process_helper
import multi_facility_process_helper_client
import globals
import toolconfig
import testUtils
import pushRelease
import upgradeRelease
import showHistory
import envPathsParser
from globals import UserParamsException

class TestUpgradeSubFunctions(unittest.TestCase):
    '''Test the upgrade subfunctions'''
    testDataFolder = "/tmp"
    
    def setUp(self):
        self.testDataFolder = testUtils.getTestFolder()
        testUtils.createStdIOCFolders()
        testUtils.createStdHLAFolders()
  
         
    def tearDown(self):
        shutil.rmtree(os.path.join(self.testDataFolder, testUtils.iocTestFolder))
        shutil.rmtree(os.path.join(self.testDataFolder, testUtils.HLATestFolder))

    def test_doWeNeedToSwitchTheMasterLink(self):
        versionsAndReleases = upgradeRelease.determineExistingVersionsAndAvailableReleases('testPkg', 'SIOC')
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test1', 'testPkg', 'SIOC', 'v1', versionsAndReleases) == False)
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test2', 'testPkg', 'SIOC', 'v1', versionsAndReleases) == False)
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test1', 'testPkg', 'SIOC', 'v2', versionsAndReleases) == True)
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test2', 'testPkg', 'SIOC', 'v2', versionsAndReleases) == True)
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test1', 'testPkg', 'SIOC', 'vOther', versionsAndReleases) == True)
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test2', 'testPkg', 'SIOC', 'vOther', versionsAndReleases) == True)

        versionsAndReleases = upgradeRelease.determineExistingVersionsAndAvailableReleases('otherPkg', 'SIOC')
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test1', 'otherPkg', 'SIOC', 'v2', versionsAndReleases) == False)
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test2', 'otherPkg', 'SIOC', 'v2', versionsAndReleases) == False)

        versionsAndReleases = upgradeRelease.determineExistingVersionsAndAvailableReleases('testPkg', 'HLA')
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test1', 'testPkg', 'HLA', 'v1', versionsAndReleases) == False)
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test2', 'testPkg', 'HLA', 'v1', versionsAndReleases) == False)
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test1', 'testPkg', 'HLA', 'v2', versionsAndReleases) == True)
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test2', 'testPkg', 'HLA', 'v2', versionsAndReleases) == True)
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test1', 'testPkg', 'HLA', 'vOther', versionsAndReleases) == True)
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test2', 'testPkg', 'HLA', 'vOther', versionsAndReleases) == True)

        versionsAndReleases = upgradeRelease.determineExistingVersionsAndAvailableReleases('otherPkg', 'HLA')
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test1', 'otherPkg', 'HLA', 'v2', versionsAndReleases) == False)
        self.assertTrue(upgradeRelease.doWeNeedToSwitchTheMasterLink('test2', 'otherPkg', 'HLA', 'v2', versionsAndReleases) == False)
        
    def test_determineIOCLinksThatNeedToChangeBecauseTheMasterLinkIsChanging(self):
        versionsAndReleases = upgradeRelease.determineExistingVersionsAndAvailableReleases('testPkg', 'SIOC')
        iocs = upgradeRelease.determineIOCLinksThatNeedToChangeBecauseTheMasterLinkIsChanging('test1', 'testPkg', 'SIOC', 'v2', versionsAndReleases)
        if globals.verbose:
            print "IOCs that need upgrading", iocs
        self.assertTrue(('test1', 'sioc-test1-001') in iocs)
        self.assertTrue(('test1', 'sioc-test1-002') in iocs)
        self.assertTrue(('test1', 'sioc-test1-003') in iocs)
        self.assertTrue(('test1', 'sioc-test1-004') in iocs)
        self.assertTrue(('test1', 'sioc-test1-005') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-001') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-002') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-003') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-004') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-005') not in iocs)

        iocs = upgradeRelease.determineIOCLinksThatNeedToChangeBecauseTheMasterLinkIsChanging('test1', 'testPkg', 'SIOC', 'v1', versionsAndReleases)
        if globals.verbose:
            print "IOCs that need upgrading", iocs
        self.assertTrue(('test1', 'sioc-test1-001') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-002') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-003') in iocs)
        self.assertTrue(('test1', 'sioc-test1-004') in iocs)
        self.assertTrue(('test1', 'sioc-test1-005') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-001') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-002') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-003') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-004') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-005') not in iocs)
        
    def test_determineFacilityIOCCombos(self):
        versionsAndReleases = upgradeRelease.determineExistingVersionsAndAvailableReleases('testPkg', 'SIOC')
        iocs = upgradeRelease.determineFacilityIOCCombos(None, 'sioc-test1-001', 'testPkg', 'SIOC', 'v2', versionsAndReleases)
        if globals.verbose:
            print json.dumps(versionsAndReleases)
            print "IOCs that need upgrading", iocs
        self.assertTrue(('test1', 'MASTER') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-001') in iocs)
        self.assertTrue(('test1', 'sioc-test1-002') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-003') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-004') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-005') not in iocs)
        self.assertTrue(('test2', 'MASTER') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-001') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-002') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-003') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-004') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-005') not in iocs)
        iocs = upgradeRelease.determineFacilityIOCCombos(None, 'sioc-test1-001,sioc-test1-002', 'testPkg', 'SIOC', 'v2', versionsAndReleases)
        if globals.verbose:
            print json.dumps(versionsAndReleases)
            print "IOCs that need upgrading", iocs
        self.assertTrue(('test1', 'MASTER') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-001') in iocs)
        self.assertTrue(('test1', 'sioc-test1-002') in iocs)
        self.assertTrue(('test1', 'sioc-test1-003') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-004') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-005') not in iocs)
        self.assertTrue(('test2', 'MASTER') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-001') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-002') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-003') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-004') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-005') not in iocs)
        # Make sure we do not include IOCS from other packages.
        self.assertRaises(Exception, upgradeRelease.determineFacilityIOCCombos, None, 'sioc-test1-001,sioc-test1-002,sioc-test1-005', 'testPkg', 'SIOC', 'v2', versionsAndReleases)

        # Pass in an IOC and a facility. The facility should be ignored...
        iocs = upgradeRelease.determineFacilityIOCCombos('test1', 'sioc-test1-001', 'testPkg', 'SIOC', 'v2', versionsAndReleases)
        if globals.verbose:
            print json.dumps(versionsAndReleases)
            print "IOCs that need upgrading", iocs
        self.assertTrue(('test1', 'MASTER') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-001') in iocs)
        self.assertTrue(('test1', 'sioc-test1-002') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-003') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-004') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-005') not in iocs)
        self.assertTrue(('test2', 'MASTER') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-001') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-002') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-003') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-004') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-005') not in iocs)

        iocs = upgradeRelease.determineFacilityIOCCombos('test1', 'ALL', 'testPkg', 'SIOC', 'v2', versionsAndReleases)
        if globals.verbose:
            print json.dumps(versionsAndReleases)
            print "IOCs that need upgrading", iocs
        self.assertTrue(('test1', 'MASTER') in iocs)
        self.assertTrue(('test1', 'sioc-test1-001') in iocs)
        self.assertTrue(('test1', 'sioc-test1-002') in iocs)
        self.assertTrue(('test1', 'sioc-test1-003') in iocs)
        self.assertTrue(('test1', 'sioc-test1-004') in iocs)
        self.assertTrue(('test1', 'sioc-test1-005') not in iocs)
        self.assertTrue(('test2', 'MASTER') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-001') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-002') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-003') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-004') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-005') not in iocs)
        
        iocs = upgradeRelease.determineFacilityIOCCombos('test1,test2', 'ALL', 'testPkg', 'SIOC', 'v2', versionsAndReleases)
        if globals.verbose:
            print json.dumps(versionsAndReleases)
            print "IOCs that need upgrading", iocs
        self.assertTrue(('test1', 'MASTER') in iocs)
        self.assertTrue(('test1', 'sioc-test1-001') in iocs)
        self.assertTrue(('test1', 'sioc-test1-002') in iocs)
        self.assertTrue(('test1', 'sioc-test1-003') in iocs)
        self.assertTrue(('test1', 'sioc-test1-004') in iocs)
        self.assertTrue(('test1', 'sioc-test1-005') not in iocs)
        self.assertTrue(('test2', 'MASTER') in iocs)
        self.assertTrue(('test2', 'sioc-test2-001') in iocs)
        self.assertTrue(('test2', 'sioc-test2-002') in iocs)
        self.assertTrue(('test2', 'sioc-test2-003') in iocs)
        self.assertTrue(('test2', 'sioc-test2-004') in iocs)
        self.assertTrue(('test2', 'sioc-test2-005') not in iocs)
        
        iocs = upgradeRelease.determineFacilityIOCCombos('ALL', 'ALL', 'testPkg', 'SIOC', 'v2', versionsAndReleases)
        if globals.verbose:
            print json.dumps(versionsAndReleases)
            print "IOCs that need upgrading", iocs
        self.assertTrue(('test1', 'MASTER') in iocs)
        self.assertTrue(('test1', 'sioc-test1-001') in iocs)
        self.assertTrue(('test1', 'sioc-test1-002') in iocs)
        self.assertTrue(('test1', 'sioc-test1-003') in iocs)
        self.assertTrue(('test1', 'sioc-test1-004') in iocs)
        self.assertTrue(('test1', 'sioc-test1-005') not in iocs)
        self.assertTrue(('test2', 'MASTER') in iocs)
        self.assertTrue(('test2', 'sioc-test2-001') in iocs)
        self.assertTrue(('test2', 'sioc-test2-002') in iocs)
        self.assertTrue(('test2', 'sioc-test2-003') in iocs)
        self.assertTrue(('test2', 'sioc-test2-004') in iocs)
        self.assertTrue(('test2', 'sioc-test2-005') not in iocs)

        # For IOCs with the same name across multiple facilities, we expect to get an exception        
        self.assertRaises(Exception, upgradeRelease.determineFacilityIOCCombos, None, 'sioc-same-name', 'testPkg', 'SIOC', 'v2', versionsAndReleases)
        
        iocs = upgradeRelease.determineFacilityIOCCombos('test1', 'sioc-same-name', 'testPkg', 'SIOC', 'v2', versionsAndReleases)
        if globals.verbose:
            print json.dumps(versionsAndReleases)
            print "IOCs that need upgrading", iocs
        self.assertTrue(('test1', 'sioc-same-name') in iocs)
        self.assertTrue(('test2', 'sioc-same-name') not in iocs)
        self.assertTrue(('test1', 'MASTER') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-001') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-002') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-003') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-004') not in iocs)
        self.assertTrue(('test1', 'sioc-test1-005') not in iocs)
        self.assertTrue(('test2', 'MASTER') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-001') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-002') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-003') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-004') not in iocs)
        self.assertTrue(('test2', 'sioc-test2-005') not in iocs)
        
        
    def test_makeSureReleaseFolderExistsOnFacilities(self):
        versionsAndReleases = upgradeRelease.determineExistingVersionsAndAvailableReleases('testPkg', 'SIOC')
        iocFacilityCombos = upgradeRelease.determineFacilityIOCCombos('ALL', 'ALL', 'testPkg', 'SIOC', 'v2', versionsAndReleases)
        upgradeRelease.makeSureReleaseFolderExistsOnFacilities('testPkg', 'SIOC', 'v2', iocFacilityCombos, versionsAndReleases)
        iocFacilityCombos = upgradeRelease.determineFacilityIOCCombos('ALL', 'ALL', 'testPkg', 'SIOC', 'Development', versionsAndReleases)
        devpath = os.path.join(self.testDataFolder, testUtils.iocTestFolder, 'test2', "iocTop", "testPkg", "Development")
        self.assertTrue(os.path.exists(devpath))
        os.rmdir(devpath)
        self.assertTrue(not os.path.exists(devpath))
        versionsAndReleases = upgradeRelease.determineExistingVersionsAndAvailableReleases('testPkg', 'SIOC')
        self.assertRaises(Exception, upgradeRelease.makeSureReleaseFolderExistsOnFacilities, 'testPkg', 'SIOC', 'Development', iocFacilityCombos, versionsAndReleases)
        

startingDir = os.path.realpath(os.curdir)


class TestIOCUpgrade(unittest.TestCase):
 
    testDataFolder = "/tmp"
 
    def setUp(self):
        self.testDataFolder = testUtils.getTestFolder()
        testUtils.createStdIOCFolders()
  
         
    def tearDown(self):
        shutil.rmtree(os.path.join(self.testDataFolder, testUtils.iocTestFolder))
        shutil.rmtree(os.path.join(self.testDataFolder, testUtils.IOCWorkspaceFolder))
 
    def getIOCVersionsInAllFacilities(self):
        '''Get the versions of all IOCs in all facilities as a dict
        The  master release for each facility is added as a facility_name_MASTER key
        IOCs themselves are tuples - version and whether they point to the master release or not'''
        iocVersions = {}
        for facility in toolconfig.getListOfFacilities():
            arg = {}
            arg['name'] = 'testPkg'
            arg['releaseFolder'] = os.path.join(self.testDataFolder, testUtils.iocTestFolder, facility, "iocTop")
            arg['linkFolder'] = os.path.join(self.testDataFolder, testUtils.iocTestFolder, facility, "iocCommon")
            ret = multi_facility_process_helper.determineIOCVersions(arg)
            iocVersions[facility + "_MASTER"] = (ret['master'], True)
            for ioc in ret['iocs']:
                iocVersions[ioc['ioc']] = (ioc['release'], ioc['isMaster'])
        return iocVersions
 
    def makeSureIOCVersionsAreTheSame(self, iocVersionsBefore, iocVersionsAfter, upgradedIOCs):
        '''Make sure that the versions before and after are the same with the exceptions of the IOCs in the upgradedIOCs list.'''
        for (iocName, versionMasterTuple) in iocVersionsBefore.iteritems():
            self.assertTrue(iocName in iocVersionsAfter)
            if iocName not in upgradedIOCs:
                if globals.verbose:
                    print iocName, versionMasterTuple, iocVersionsAfter[iocName]
                self.assertTrue(versionMasterTuple == iocVersionsAfter[iocName], msg="Failure in " + iocName +  str(versionMasterTuple) +  str(iocVersionsAfter[iocName]))
        for (iocName, versionMasterTuple) in iocVersionsAfter.iteritems():
            self.assertTrue(iocName in iocVersionsBefore)
            if iocName not in upgradedIOCs:
                if globals.verbose:
                    print iocName, versionMasterTuple, iocVersionsBefore[iocName]
                self.assertTrue(versionMasterTuple == iocVersionsBefore[iocName], msg="Failure in " + iocName +  str(versionMasterTuple) +  str(iocVersionsAfter[iocName]))
                
    def checkEnvPaths(self, facility, name, release, ioc):
        '''Quick ckeck on envPaths to make sure TOP etc are replaced'''
        envPathsPath = os.path.join(self.testDataFolder, testUtils.iocTestFolder, facility, 'iocTop', name, release, 'iocBoot', ioc, 'envPaths')
        envPaths = envPathsParser.parseAndReplaceEnvPathsFile(envPathsPath, {})
        self.assertTrue('TOP' in envPaths)
        self.assertTrue('ARCH' in envPaths)
        self.assertTrue('IOC' in envPaths)
        self.assertTrue('EPICS_SITE_TOP' in envPaths)
        self.assertTrue('BASE_SITE_TOP' in envPaths)
        self.assertTrue('EPICS_BASE' in envPaths)
        self.assertTrue('MODULES_SITE_TOP' in envPaths)

        self.assertTrue(envPaths['TOP'] == os.path.join(self.testDataFolder, testUtils.iocTestFolder, facility, 'iocTop', name, release))
        self.assertTrue(envPaths['ARCH'] == 'RTEMS-beatnik')
             
    def IOCTestHelper(self, testupgradeargs):
        '''Boilerplate for IOC tests'''
        testPushPkgName = "testPkg"
        testPushVersionName = "testPush_V9"
        testUtils.createNewIOCRelease(testPushPkgName, testPushVersionName)
        testUtils.cd(os.path.join(self.testDataFolder, testUtils.IOCWorkspaceFolder, testPushPkgName, testPushVersionName))
        pushargs = []
        if globals.verbose:
            pushargs.append('-v')
        pushRelease.execute(pushargs)
 
        iocVersionsBefore = self.getIOCVersionsInAllFacilities()
        upgradeargs = []
        if globals.verbose:
            upgradeargs.append('-v')
        upgradeargs.extend(testupgradeargs)
        upgradeRelease.execute(upgradeargs)
        testUtils.cd(startingDir)
        iocVersionsAfter = self.getIOCVersionsInAllFacilities()
 
        return (iocVersionsBefore, iocVersionsAfter)
    
    def getHist(self):
        ''' Gets the history for this package'''
        ret = {}
        for facility in toolconfig.getListOfFacilities():
            arg = {}
            arg['name'] = 'testPkg'
            arg['type'] = 'SIOC'
            arg['releaseFolder'] = toolconfig.getConfigForFacility(facility)['SIOC']['releaseFolder']
            ret[facility] = multi_facility_process_helper.hist(arg)
        return ret
         
    def testOneIOCInOneFacility(self):
        '''Test upgrading one IOC in one facility. We also test that the remaining IOCs are unaffected'''
        (iocVersionsBefore, iocVersionsAfter) = self.IOCTestHelper(['--ioc', 'sioc-test1-001', '--facility', 'test1', 'testPush_V9'])
        self.makeSureIOCVersionsAreTheSame(iocVersionsBefore, iocVersionsAfter, ['sioc-test1-001'])
 
        self.assertTrue(iocVersionsAfter['sioc-test1-001'][0] == 'testPush_V9')
        # Check to see that we are indeed not pointing to the master
        self.assertTrue(iocVersionsAfter['sioc-test1-001'][1] == False)
        
        hist = self.getHist()
        if globals.verbose:
            print "History", hist
        self.assertTrue('sioc-test1-001' in hist['test1'])
        self.assertTrue(hist['test1']['sioc-test1-001'][0]['release'] == 'testPush_V9')
        
        

    def testTwoIOCsInOneFacility(self):
        '''Test upgrading two IOCs in one facility. We also test that the remaining IOCs are unaffected'''
        (iocVersionsBefore, iocVersionsAfter) = self.IOCTestHelper(['--ioc', 'sioc-test1-001,sioc-test1-002', '--facility', 'test1', 'testPush_V9'])
        self.makeSureIOCVersionsAreTheSame(iocVersionsBefore, iocVersionsAfter, ['sioc-test1-001', 'sioc-test1-002'])
 
        self.assertTrue(iocVersionsAfter['sioc-test1-001'][0] == 'testPush_V9')
        # Check to see that we are indeed not pointing to the master
        self.assertTrue(iocVersionsAfter['sioc-test1-001'][1] == False)

        self.assertTrue(iocVersionsAfter['sioc-test1-002'][0] == 'testPush_V9')
        # Check to see that we are indeed not pointing to the master
        self.assertTrue(iocVersionsAfter['sioc-test1-002'][1] == False)

    def testAllIOCsInOneFacility(self):
        '''Test upgrading ALL IOCs in one facility. We also test that the remaining IOCs are unaffected'''
        (iocVersionsBefore, iocVersionsAfter) = self.IOCTestHelper(['--ioc', 'ALL', '--facility', 'test1', 'testPush_V9'])
        self.makeSureIOCVersionsAreTheSame(iocVersionsBefore, iocVersionsAfter, ['test1_MASTER', 'sioc-test1-001', 'sioc-test1-002', 'sioc-test1-003', 'sioc-test1-004'])
 
        self.assertTrue(iocVersionsAfter['sioc-test1-001'][0] == 'testPush_V9')
        self.assertTrue(iocVersionsAfter['sioc-test1-001'][1] == True)
        
        self.assertTrue(iocVersionsAfter['sioc-test1-002'][0] == 'testPush_V9')
        self.assertTrue(iocVersionsAfter['sioc-test1-002'][1] == True)

        self.assertTrue(iocVersionsAfter['sioc-test1-003'][0] == 'testPush_V9')
        self.assertTrue(iocVersionsAfter['sioc-test1-003'][1] == True)

        self.assertTrue(iocVersionsAfter['sioc-test1-004'][0] == 'testPush_V9')
        self.assertTrue(iocVersionsAfter['sioc-test1-004'][1] == True)

        self.assertTrue(iocVersionsAfter['test1_MASTER'][0] == 'testPush_V9')
        
    def testTwoIOCsInDifferentFacilities(self):
        '''Test upgrading two IOC's in two different facilities'''
        (iocVersionsBefore, iocVersionsAfter) = self.IOCTestHelper(['--ioc', 'sioc-test1-001,sioc-test2-001', 'testPush_V9'])
        self.makeSureIOCVersionsAreTheSame(iocVersionsBefore, iocVersionsAfter, ['sioc-test1-001', 'sioc-test2-001'])
 
        self.assertTrue(iocVersionsAfter['sioc-test1-001'][0] == 'testPush_V9')
        self.assertTrue(iocVersionsAfter['sioc-test1-001'][1] == False)
        
        self.assertTrue(iocVersionsAfter['sioc-test2-001'][0] == 'testPush_V9')
        self.assertTrue(iocVersionsAfter['sioc-test2-001'][1] == False)
        
        hist = self.getHist()
        if globals.verbose:
            print "History", hist
        self.assertTrue('sioc-test1-001' in hist['test1'])
        self.assertTrue('sioc-test2-001' in hist['test2'])
        self.assertTrue(hist['test1']['sioc-test1-001'][0]['release'] == 'testPush_V9')
        self.assertTrue(hist['test2']['sioc-test2-001'][0]['release'] == 'testPush_V9')
        
        
    def testThreeIOCsInDifferentFacilities(self):
        '''Test upgrading three IOC's in two different facilities'''
        (iocVersionsBefore, iocVersionsAfter) = self.IOCTestHelper(['--ioc', 'sioc-test1-001,sioc-test2-001,sioc-test2-002', 'testPush_V9'])
        self.makeSureIOCVersionsAreTheSame(iocVersionsBefore, iocVersionsAfter, ['sioc-test1-001', 'sioc-test2-001', 'sioc-test2-002'])
 
        self.assertTrue(iocVersionsAfter['sioc-test1-001'][0] == 'testPush_V9')
        self.assertTrue(iocVersionsAfter['sioc-test1-001'][1] == False)
        
        self.assertTrue(iocVersionsAfter['sioc-test2-001'][0] == 'testPush_V9')
        self.assertTrue(iocVersionsAfter['sioc-test2-001'][1] == False)
        
        self.assertTrue(iocVersionsAfter['sioc-test2-002'][0] == 'testPush_V9')
        self.assertTrue(iocVersionsAfter['sioc-test2-002'][1] == False)
        
    def testAllIOCsInDifferentFacilities(self):
        '''Test upgrading ALL IOC's in two different facilities'''
        (iocVersionsBefore, iocVersionsAfter) = self.IOCTestHelper(['--ioc', 'ALL', '--facility', 'test1,test2', 'testPush_V9'])

        # Everybody should be upgraded
        for ioc,versionTuple in iocVersionsAfter.iteritems():
            self.assertTrue(versionTuple[0] == 'testPush_V9')
            self.assertTrue(versionTuple[1] == True)

    def testAllIOCsInAllFacilities(self):
        '''Test upgrading ALL IOC's in ALL facilities'''
        (iocVersionsBefore, iocVersionsAfter) = self.IOCTestHelper(['--ioc', 'ALL', '--facility', 'ALL', 'testPush_V9'])

        # Everybody should be upgraded
        for ioc,versionTuple in iocVersionsAfter.iteritems():
            self.assertTrue(versionTuple[0] == 'testPush_V9')
            self.assertTrue(versionTuple[1] == True)
            
        hist = self.getHist()
        if globals.verbose:
            print "History", hist
            
        self.assertTrue('MASTER' in hist['test1'])
        self.assertTrue('MASTER' in hist['test2'])
        self.assertTrue(hist['test1']['MASTER'][0]['release'] == 'testPush_V9')
        self.assertTrue(hist['test2']['MASTER'][0]['release'] == 'testPush_V9')
        
        for facility in toolconfig.getListOfFacilities():
            for suf in ['-001', '-002', '-003', '-004']:
                self.assertTrue(hist[facility]['sioc-' + facility + suf][0]['release'] == 'testPush_V9')

        for facility in toolconfig.getListOfFacilities():
            for suf in ['-001', '-002', '-003', '-004']:
                self.checkEnvPaths(facility, 'testPkg', 'testPush_V9', 'sioc-' + facility + suf)
                
        # Add a display hist here
        showHistory.execute(['--name', 'testPkg', '--type', 'SIOC'])
            

    def testExceptions(self):
        '''Exception is generated when we specify invalid IOC
        Exception is generated when we specify invalid facility
        Exception is generated when we specify valid IOC but in a facility that it does not belong to'''
        testPushPkgName = "testPkg"
        testPushVersionName = "testPush_V9"
        testUtils.createNewIOCRelease(testPushPkgName, testPushVersionName)
        testUtils.cd(os.path.join(self.testDataFolder, testUtils.IOCWorkspaceFolder, testPushPkgName, testPushVersionName))
        pushargs = []
        if globals.verbose:
            pushargs.append('-v')
        pushRelease.execute(pushargs)
 
        upgradeargs = []
        if globals.verbose:
            upgradeargs.append('-v')
        
        self.assertRaises(UserParamsException, upgradeRelease.execute, upgradeargs + ['--ioc', 'sioc-test1-010', '--facility', 'test1', 'testPush_V9'])
        self.assertRaises(Exception, upgradeRelease.execute, upgradeargs + ['--ioc', 'ALL', '--facility', 'test10', 'testPush_V9'])
        testUtils.cd(startingDir)

    def testPreAndPostDeploy(self):
        '''Test the execution of pre and post deploy scripts'''
        testPushPkgName = "testPkg"
        testPushVersionName = "testPush_V9"
        testUtils.createNewIOCRelease(testPushPkgName, testPushVersionName)
        os.mkdir(os.path.join(self.testDataFolder, testUtils.IOCWorkspaceFolder, testPushPkgName, testPushVersionName, "bin"))
        shutil.copy('prePostDeployTemplate.py', os.path.join(self.testDataFolder, testUtils.IOCWorkspaceFolder, testPushPkgName, testPushVersionName, "bin", "preDeploy"))
        shutil.copy('prePostDeployTemplate.py', os.path.join(self.testDataFolder, testUtils.IOCWorkspaceFolder, testPushPkgName, testPushVersionName, "bin", "postDeploy"))
        os.chmod(os.path.join(self.testDataFolder, testUtils.IOCWorkspaceFolder, testPushPkgName, testPushVersionName, "bin", "preDeploy"), 0754)
        os.chmod(os.path.join(self.testDataFolder, testUtils.IOCWorkspaceFolder, testPushPkgName, testPushVersionName, "bin", "postDeploy"), 0754)
        testUtils.cd(os.path.join(self.testDataFolder, testUtils.IOCWorkspaceFolder, testPushPkgName, testPushVersionName))
        pushargs = []
        if globals.verbose:
            pushargs.append('-v')
        pushRelease.execute(pushargs)
 
        upgradeargs = []
        if globals.verbose:
            upgradeargs.append('-v')
        upgradeargs.extend(['--ioc', 'sioc-test1-001', '--facility', 'test1', 'testPush_V9'])
        upgradeRelease.execute(upgradeargs)
        testUtils.cd(startingDir)
        
        with open(os.path.join(self.testDataFolder, testUtils.iocTestFolder, 'test1', 'iocTop', testPushPkgName, testPushVersionName, 'bin', 'preDeploy_output.json'), 'r') as f:
            envs = json.load(f)
            for envvar in ['CRAM_SCRIPT', 'CRAM_PACKAGENAME', 'CRAM_PACKAGETYPE', 'CRAM_RELEASEFOLDER', 'CRAM_RELEASE', 'CRAM_LINKFOLDER', 'CRAM_ISMASTER', 'CRAM_FACILITY', 'CRAM_IOC']:
                self.assertTrue(envvar in envs)

        with open(os.path.join(self.testDataFolder, testUtils.iocTestFolder, 'test1', 'iocTop', testPushPkgName, testPushVersionName, 'bin', 'postDeploy_output.json'), 'r') as f:
            envs = json.load(f)
            for envvar in ['CRAM_SCRIPT', 'CRAM_PACKAGENAME', 'CRAM_PACKAGETYPE', 'CRAM_RELEASEFOLDER', 'CRAM_RELEASE', 'CRAM_LINKFOLDER', 'CRAM_ISMASTER', 'CRAM_FACILITY', 'CRAM_IOC']:
                self.assertTrue(envvar in envs)


class TestHLAUpgrade(unittest.TestCase):
 
    testDataFolder = "/tmp"
    startingDir = os.path.realpath(os.curdir)
 
    def setUp(self):
        self.testDataFolder = testUtils.getTestFolder()
        testUtils.createStdHLAFolders()
  
         
    def tearDown(self):
        shutil.rmtree(os.path.join(self.testDataFolder, testUtils.HLATestFolder))
        shutil.rmtree(os.path.join(self.testDataFolder, testUtils.HLAWorkspaceFolder))


    def getHLAVersionsInAllFacilities(self):
        '''Get the versions of the HLA applications in all facilities as a dict'''
        HLAVersions = {}
        for facility in toolconfig.getListOfFacilities():
            arg = {}
            arg['name'] = 'testPkg'
            arg['releaseFolder'] = os.path.join(self.testDataFolder, testUtils.HLATestFolder, facility, "physicsTop", "release")
            arg['linkFolder'] = os.path.join(self.testDataFolder, testUtils.HLATestFolder, facility, "physicsTop")
            ret = multi_facility_process_helper.determineHLAVersion(arg)
            HLAVersions[facility] = ret
        return HLAVersions

    def HLATestHelper(self, testupgradeargs):
        '''Boilerplate for HLA tests'''
        testPushPkgName = "testPkg"
        testPushVersionName = "testPush_V9"
        testUtils.createNewHLARelease(testPushPkgName, testPushVersionName)
        testUtils.cd(os.path.join(self.testDataFolder, testUtils.HLAWorkspaceFolder, testPushPkgName, testPushVersionName))
        pushargs = []
        if globals.verbose:
            pushargs.append('-v')
        pushRelease.execute(pushargs)
 
        HLAVersionsBefore = self.getHLAVersionsInAllFacilities()
        upgradeargs = []
        if globals.verbose:
            upgradeargs.append('-v')
        upgradeargs.extend(testupgradeargs)
        upgradeRelease.execute(upgradeargs)
        HLAVersionsAfter = self.getHLAVersionsInAllFacilities()
        testUtils.cd(startingDir)
 
        return (HLAVersionsBefore, HLAVersionsAfter)

    def getHist(self):
        ''' Gets the history for this package'''
        ret = {}
        for facility in toolconfig.getListOfFacilities():
            arg = {}
            arg['name'] = 'testPkg'
            arg['type'] = 'HLA'
            arg['releaseFolder'] = toolconfig.getConfigForFacility(facility)['HLA']['releaseFolder']
            ret[facility] = multi_facility_process_helper.hist(arg)
        return ret

    def testHLAInOneFacility(self):
        '''Test upgrading HLA in one facility '''
        (HLAVersionsBefore, HLAVersionsAfter) = self.HLATestHelper(['--facility', 'test1', 'testPush_V9'])

        self.assertTrue(HLAVersionsAfter['test1'] == 'testPush_V9')
        self.assertTrue(HLAVersionsAfter['test1'] != HLAVersionsBefore['test1'])
        self.assertTrue(HLAVersionsAfter['test2'] == HLAVersionsBefore['test2'])
        
    def testHLAInTwoFacilities(self):
        '''Test upgrading HLA in two facilities '''
        (HLAVersionsBefore, HLAVersionsAfter) = self.HLATestHelper(['--facility', 'test1,test2', 'testPush_V9'])

        self.assertTrue(HLAVersionsAfter['test1'] == 'testPush_V9')
        self.assertTrue(HLAVersionsAfter['test1'] != HLAVersionsBefore['test1'])
        self.assertTrue(HLAVersionsAfter['test2'] == 'testPush_V9')
        self.assertTrue(HLAVersionsAfter['test2'] != HLAVersionsBefore['test2'])
        
        
    def testHLAInAllFacilities(self):
        '''Test upgrading HLA in all facilities '''
        (HLAVersionsBefore, HLAVersionsAfter) = self.HLATestHelper(['--facility', 'ALL', 'testPush_V9'])

        self.assertTrue(HLAVersionsAfter['test1'] == 'testPush_V9')
        self.assertTrue(HLAVersionsAfter['test1'] != HLAVersionsBefore['test1'])
        self.assertTrue(HLAVersionsAfter['test2'] == 'testPush_V9')
        self.assertTrue(HLAVersionsAfter['test2'] != HLAVersionsBefore['test2'])
        
        hist = self.getHist()
        if globals.verbose:
            print "History", hist
            
        self.assertTrue('MASTER' in hist['test1'])
        self.assertTrue('MASTER' in hist['test2'])
        self.assertTrue(hist['test1']['MASTER'][0]['release'] == 'testPush_V9')
        self.assertTrue(hist['test2']['MASTER'][0]['release'] == 'testPush_V9')

        # Add a display hist here
        showHistory.execute(['--name', 'testPkg', '--type', 'HLA'])

        
