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 runReleaseScript
import upgradeRelease
import pushRelease

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

class TestRun(unittest.TestCase):
    '''Test the run command'''
    testDataFolder = "/tmp"
    
    def setUp(self):
        self.testDataFolder = testUtils.getTestFolder()
        testUtils.createStdIOCFolders()
        testUtils.createStdHLAFolders()
        testUtils.createStdPyDMFolders()

         
    def tearDown(self):
        shutil.rmtree(os.path.join(self.testDataFolder, testUtils.iocTestFolder), ignore_errors=True)
        shutil.rmtree(os.path.join(self.testDataFolder, testUtils.HLATestFolder), ignore_errors=True)
        shutil.rmtree(os.path.join(self.testDataFolder, testUtils.PyDMTestFolder), ignore_errors=True)
        shutil.rmtree(os.path.join(self.testDataFolder, testUtils.IOCWorkspaceFolder), ignore_errors=True)
        shutil.rmtree(os.path.join(self.testDataFolder, testUtils.HLAWorkspaceFolder), ignore_errors=True)
        shutil.rmtree(os.path.join(self.testDataFolder, testUtils.PyDMWorkspaceFolder), ignore_errors=True)

    def test_determineIOCFacilityCombos(self):
        versionsAndReleases = upgradeRelease.determineExistingVersionsAndAvailableReleases('testPkg', 'SIOC')
        iocFacilityCombos = runReleaseScript.determineIOCFacilityCombos('testPkg', 'SIOC', None, 'sioc-test1-001', versionsAndReleases)
        self.assertTrue(('test1', 'sioc-test1-001', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-002', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-003', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-004', 'v2') not in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-005', 'v2') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-001', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-002', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-003', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-004', 'v2') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-005', 'v2') not in iocFacilityCombos)
        iocFacilityCombos = runReleaseScript.determineIOCFacilityCombos('testPkg', 'SIOC', None, 'sioc-test1-001,sioc-test2-002', versionsAndReleases)
        self.assertTrue(('test1', 'sioc-test1-001', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-002', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-003', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-004', 'v2') not in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-005', 'v2') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-001', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-002', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-003', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-004', 'v2') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-005', 'v2') not in iocFacilityCombos)
        iocFacilityCombos = runReleaseScript.determineIOCFacilityCombos('testPkg', 'SIOC', 'test1', 'sioc-test1-*', versionsAndReleases)
        self.assertTrue(('test1', 'sioc-test1-001', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-002', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-003', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-004', 'v2') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-005', 'v2') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-001', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-002', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-003', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-004', 'v2') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-005', 'v2') not in iocFacilityCombos)
        iocFacilityCombos = runReleaseScript.determineIOCFacilityCombos('testPkg', 'SIOC', 'test1', 'ALL', versionsAndReleases)
        self.assertTrue(('test1', 'sioc-test1-001', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-002', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-003', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-004', 'v2') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-005', 'v2') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-001', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-002', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-003', 'v1') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-004', 'v2') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-005', 'v2') not in iocFacilityCombos)
        iocFacilityCombos = runReleaseScript.determineIOCFacilityCombos('testPkg', 'SIOC', 'test1,test2', 'ALL', versionsAndReleases)
        self.assertTrue(('test1', 'sioc-test1-001', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-002', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-003', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-004', 'v2') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-005', 'v2') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-001', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-002', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-003', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-004', 'v2') in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-005', 'v2') not in iocFacilityCombos)
        iocFacilityCombos = runReleaseScript.determineIOCFacilityCombos('testPkg', 'SIOC', 'ALL', 'ALL', versionsAndReleases)
        self.assertTrue(('test1', 'sioc-test1-001', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-002', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-003', 'v1') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-004', 'v2') in iocFacilityCombos)
        self.assertTrue(('test1', 'sioc-test1-005', 'v2') not in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-001', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-002', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-003', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-004', 'v2') in iocFacilityCombos)
        self.assertTrue(('test2', 'sioc-test2-005', 'v2') not in iocFacilityCombos)
        self.assertRaises(Exception, runReleaseScript.determineIOCFacilityCombos, 'testPkg', 'SIOC', None, 'ALL', versionsAndReleases)
        self.assertRaises(Exception, runReleaseScript.determineIOCFacilityCombos, 'testPkg', 'SIOC', None, 'unknownIOC', versionsAndReleases)
        self.assertRaises(Exception, runReleaseScript.determineIOCFacilityCombos, 'testPkg', 'SIOC', None, 'wild?card', versionsAndReleases)
        self.assertRaises(Exception, runReleaseScript.determineIOCFacilityCombos, 'testPkg', 'SIOC', 'DummyFacility', 'ALL', versionsAndReleases)

    def test_determineHLAFacilityCombos(self):
        versionsAndReleases = upgradeRelease.determineExistingVersionsAndAvailableReleases('testPkg', 'HLA')
        iocFacilityCombos = runReleaseScript.determineIOCFacilityCombos('testPkg', 'HLA', 'test1', None, versionsAndReleases)
        self.assertTrue(('test1', 'MASTER', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'MASTER', 'v1') not in iocFacilityCombos)
        iocFacilityCombos = runReleaseScript.determineIOCFacilityCombos('testPkg', 'HLA', 'test1,test2', None, versionsAndReleases)
        self.assertTrue(('test1', 'MASTER', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'MASTER', 'v1') in iocFacilityCombos)
        iocFacilityCombos = runReleaseScript.determineIOCFacilityCombos('testPkg', 'HLA', 'ALL', None, versionsAndReleases)
        self.assertTrue(('test1', 'MASTER', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'MASTER', 'v1') in iocFacilityCombos)
        self.assertRaises(Exception, runReleaseScript.determineIOCFacilityCombos, 'testPkg', 'HLA', 'DummyFacility', None, versionsAndReleases)

    def test_determinePyDMFacilityCombos(self):
        versionsAndReleases = upgradeRelease.determineExistingVersionsAndAvailableReleases('pydm-testSubsys', 'PyDM')
        iocFacilityCombos = runReleaseScript.determineIOCFacilityCombos('pydm-testSubsys', 'PyDM', 'test1', None, versionsAndReleases)
        self.assertTrue(('test1', 'MASTER', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'MASTER', 'v1') not in iocFacilityCombos)
        iocFacilityCombos = runReleaseScript.determineIOCFacilityCombos('pydm-testSubsys', 'PyDM', 'test1,test2', None, versionsAndReleases)
        self.assertTrue(('test1', 'MASTER', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'MASTER', 'v1') in iocFacilityCombos)
        iocFacilityCombos = runReleaseScript.determineIOCFacilityCombos('pydm-testSubsys', 'PyDM', 'ALL', None, versionsAndReleases)
        self.assertTrue(('test1', 'MASTER', 'v1') in iocFacilityCombos)
        self.assertTrue(('test2', 'MASTER', 'v1') in iocFacilityCombos)
        self.assertRaises(Exception, runReleaseScript.determineIOCFacilityCombos, 'pydm-testSubsys', 'PyDM', 'DummyFacility', None, versionsAndReleases)

    def test_RunIOCs(self):
        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", "runTest"))
        os.chmod(os.path.join(self.testDataFolder, testUtils.IOCWorkspaceFolder, testPushPkgName, testPushVersionName, "bin", "runTest"), 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', 'ALL', '--facility', 'ALL', 'testPush_V9'])
        upgradeRelease.execute(upgradeargs)
        testUtils.cd(startingDir)
        
        runargs = []
        if globals.verbose:
            runargs.append('-v')
        runargs.extend(['--name', 'testPkg', '--type', 'SIOC', '--ioc', 'sioc-test1-001', '--facility', 'ALL', 'bin/runTest'])
        runReleaseScript.execute(runargs)
        
        with open(os.path.join(self.testDataFolder, testUtils.iocTestFolder, 'test1', 'iocTop', testPushPkgName, testPushVersionName, 'bin', 'runTest_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)
                
    def test_RunIOCsWithInvalidRunScript(self):
        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", "postDeploy"))
        os.chmod(os.path.join(self.testDataFolder, testUtils.IOCWorkspaceFolder, testPushPkgName, testPushVersionName, "bin", "postDeploy"), 0444)
        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', 'ALL', '--facility', 'ALL', 'testPush_V9'])
        self.assertRaises(Exception, upgradeRelease.execute, upgradeargs)
        testUtils.cd(startingDir)

