'''
Testing for revert - for IOCs and HLA apps
Revert relies on hist, runReleaseScript and upgradeRelease so some of the testing of the subfunctions is done there.
This tests the revert itself.
'''

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 revertRelease

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


class TestIOCRevert(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 createPushAndUpgrade(self, testPushVersionName, testupgradeargs):
        ''' Creates, pushes and upgrade the specified IOCs to this release'''
        testPushPkgName = "testPkg"
        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')
        upgradeargs.extend(testupgradeargs)
        upgradeRelease.execute(upgradeargs)
        
    def revert(self, testrevertargs):
        revertargs = []
        if globals.verbose:
            revertargs.append('-v')
        revertargs.extend(testrevertargs)
        revertRelease.execute(revertargs)
        testUtils.cd(startingDir)

    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'''
        testPushPkgName = "testPkg"
        testPushVersionName = "testPush_V9"
        self.createPushAndUpgrade(testPushVersionName, ['--ioc', 'sioc-test1-001', '--facility', 'test1', testPushVersionName])
        
        iocVersionsBefore = self.getIOCVersionsInAllFacilities()

        testPushVersionName = "testPush_V10"
        self.createPushAndUpgrade(testPushVersionName, ['--ioc', 'sioc-test1-001', '--facility', 'test1', testPushVersionName])

        self.revert(['--ioc', 'sioc-test1-001', '--facility', 'test1'])
        iocVersionsAfter = self.getIOCVersionsInAllFacilities()

        self.makeSureIOCVersionsAreTheSame(iocVersionsBefore, iocVersionsAfter, [])
 
        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')
        self.assertTrue(hist['test1']['sioc-test1-001'][1]['release'] == 'testPush_V10')
        self.assertTrue(hist['test1']['sioc-test1-001'][2]['release'] == 'testPush_V9')
        

    def testUpgradeTwoIOCsButRevertOnlyOne(self):
        '''Test upgrading two IOCs in one facility but revert only one'''
        testPushPkgName = "testPkg"
        testPushVersionName = "testPush_V9"
        self.createPushAndUpgrade(testPushVersionName, ['--ioc', 'sioc-test1-001,sioc-test1-002', '--facility', 'test1', testPushVersionName])
        
        iocVersionsBefore = self.getIOCVersionsInAllFacilities()

        testPushVersionName = "testPush_V10"
        self.createPushAndUpgrade(testPushVersionName, ['--ioc', 'sioc-test1-001,sioc-test1-002', '--facility', 'test1', testPushVersionName])

        self.revert(['--ioc', 'sioc-test1-001', '--facility', 'test1'])
        iocVersionsAfter = self.getIOCVersionsInAllFacilities()

        self.makeSureIOCVersionsAreTheSame(iocVersionsBefore, iocVersionsAfter, ['sioc-test1-002'])
 
        hist = self.getHist()
        if globals.verbose:
            print "History", hist
        self.assertTrue('sioc-test1-001' in hist['test1'])
        self.assertTrue('sioc-test1-002' in hist['test1'])
        self.assertTrue(hist['test1']['sioc-test1-001'][0]['release'] == 'testPush_V9')
        self.assertTrue(hist['test1']['sioc-test1-001'][1]['release'] == 'testPush_V10')
        self.assertTrue(hist['test1']['sioc-test1-001'][2]['release'] == 'testPush_V9')

        self.assertTrue(hist['test1']['sioc-test1-002'][0]['release'] == 'testPush_V10')
        

    def testRevertTwoIOCsToDifferentVersions(self):
        '''Test reverting two IOCs in one facility but they each go back to different versions'''
        testPushPkgName = "testPkg"
        testPushVersionName = "testPush_V9"
        self.createPushAndUpgrade(testPushVersionName, ['--ioc', 'sioc-test1-001,sioc-test1-002', '--facility', 'test1', testPushVersionName])
        
        iocVersionsBefore = self.getIOCVersionsInAllFacilities()

        testPushVersionName = "testPush_V10"
        self.createPushAndUpgrade(testPushVersionName, ['--ioc', 'sioc-test1-001,sioc-test1-002', '--facility', 'test1', testPushVersionName])

        testPushVersionName = "testPush_V11"
        self.createPushAndUpgrade(testPushVersionName, ['--ioc', 'sioc-test1-001', '--facility', 'test1', testPushVersionName])

        self.revert(['--ioc', 'sioc-test1-001,sioc-test1-002', '--facility', 'test1'])
        iocVersionsAfter = self.getIOCVersionsInAllFacilities()

        self.makeSureIOCVersionsAreTheSame(iocVersionsBefore, iocVersionsAfter, ['sioc-test1-001','sioc-test1-002'])
 
        hist = self.getHist()
        if globals.verbose:
            print "History", hist
        self.assertTrue('sioc-test1-001' in hist['test1'])
        self.assertTrue('sioc-test1-002' in hist['test1'])
        self.assertTrue(hist['test1']['sioc-test1-001'][0]['release'] == 'testPush_V10')
        self.assertTrue(hist['test1']['sioc-test1-001'][1]['release'] == 'testPush_V11')
        self.assertTrue(hist['test1']['sioc-test1-001'][2]['release'] == 'testPush_V10')
        self.assertTrue(hist['test1']['sioc-test1-001'][3]['release'] == 'testPush_V9')

        self.assertTrue(hist['test1']['sioc-test1-002'][0]['release'] == 'testPush_V9')
        self.assertTrue(hist['test1']['sioc-test1-002'][1]['release'] == 'testPush_V10')
        self.assertTrue(hist['test1']['sioc-test1-002'][2]['release'] == 'testPush_V9')
        
        # Add a display hist here
        showHistory.execute(['--name', 'testPkg', '--type', 'SIOC'])


class TestHLARevert(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 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 createPushAndUpgrade(self, testPushVersionName, testupgradeargs):
        '''Create, push and upgrade a HLA application'''
        testPushPkgName = "testPkg"
        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)
 
        upgradeargs = []
        if globals.verbose:
            upgradeargs.append('-v')
        upgradeargs.extend(testupgradeargs)
        upgradeRelease.execute(upgradeargs)
 
    def revert(self, testrevertargs):
        revertargs = []
        if globals.verbose:
            revertargs.append('-v')
        revertargs.extend(testrevertargs)
        revertRelease.execute(revertargs)
        testUtils.cd(startingDir)


    def testHLAInOneFacility(self):
        '''Test reverting HLA in one facility '''
        self.createPushAndUpgrade('testPush_V9', ['--facility', 'test1', 'testPush_V9'])

        HLAVersionsBefore = self.getHLAVersionsInAllFacilities()

        self.createPushAndUpgrade('testPush_V10', ['--facility', 'test1', 'testPush_V10'])
        self.revert(['--facility', 'test1'])

        HLAVersionsAfter = self.getHLAVersionsInAllFacilities()

        hist = self.getHist()
        if globals.verbose:
            print "History", hist
        self.assertTrue('MASTER' in hist['test1'])
        self.assertTrue(hist['test1']['MASTER'][0]['release'] == 'testPush_V9')
        self.assertTrue(hist['test1']['MASTER'][1]['release'] == 'testPush_V10')
        self.assertTrue(hist['test1']['MASTER'][2]['release'] == 'testPush_V9')
        
        # Add a display hist here
        showHistory.execute(['--name', 'testPkg', '--type', 'SIOC'])


