class DBReporting(Plugin):
    """
    The plugin for test reporting to the database.
    """
    name = 'db_reporting'
    
    def __init__(self):
        """initialize some variables"""
        Plugin.__init__(self)
        self.testcase_guid = None
        self.execution_start_time = 0
        self.case_start_time = 0
        self.application = None
        self.testcase_manager = None

        self.error_handled = False

    def options(self, parser, env):
        super(DBReporting, self).options(parser, env=env)
        parser.add_option('--database_environment', action='store', 
                          dest='database_env',
                          choices=('prod', 'qa'),
                          default='qa',
                          help=SUPPRESS_HELP)
        
    #Plugin methods
    def configure(self, options, conf):
        """get the options"""
        super(DBReporting, self).configure(options, conf)
        self.options = options
        self.testcase_manager = TestcaseManager(self.options.database_env)

    def begin(self):
        """At the start of the run, we want to record the 
        execution information to the database."""
        self.execution_guid = os.environ['test_execution_guid']
        exec_payload = ExecutionQueryPayload()
        exec_payload.execution_start_time = int(time.time() * 1000)
        self.execution_start_time = exec_payload.execution_start_time
        exec_payload.guid = self.execution_guid
        exec_payload.username = getpass.getuser()
        self.testcase_manager.insert_execution_data(exec_payload)

    def startTest(self, test):
        """at the start of the test, set the test case details"""
        data_payload = TestcaseDataPayload()
        self.testcase_guid = test.testcase_guid
        data_payload.guid = self.testcase_guid
        data_payload.execution_guid = self.execution_guid
        if hasattr(test, "browser"):
            data_payload.browser = test.browser
        else:
            data_payload.browser = "N/A"
        data_payload.sauceJobID = test.sauce_job_id
        data_payload.testcaseAddress = test.id()
        data_payload.application = \
            ApplicationManager.generate_application_string(test)
        data_payload.state = constants.State.NOTRUN
        data_payload.startTime = int(time.time() * 1000)
        self.testcase_manager.insert_testcase_data(data_payload)
        self.case_start_time = int(time.time() * 1000)  #more accurate
        #make the testcase and execution guids available to other plugins
        test.execution_guid = self.execution_guid

    def finalize(self, result):
        """At the end of the run, we want to 
        update that row with the execution time."""
        runtime = int(time.time() * 1000) - self.execution_start_time
        self.testcase_manager.update_execution_data(self.execution_guid, 
                                                    runtime)

    def addSuccess(self, test, capt):
        """
        After sucess of a test, we want to record the testcase run information.
        """
        self.__insert_test_result(constants.State.PASS, test)
    
    def addError(self, test, err, capt=None):
        """
        After error of a test, we want to record the testcase run information.
        """
        self.__insert_test_result(constants.State.ERROR, test, err)

    def handleError(self, test, err, capt=None):
        """
        After error of a test, we want to record the testcase run information.
        "Error" also encompasses any states other than Pass or Fail, so we
        check for those first.
        """
        if err[0] == errors.BlockedTest:
            self.__insert_test_result(constants.State.BLOCKED, test, err)
            self.error_handled = True
            raise SkipTest(err[1])
            return True
            
        elif err[0] == errors.DeprecatedTest:
            self.__insert_test_result(constants.State.DEPRECATED, test, err)
            self.error_handled = True
            raise SkipTest(err[1])
            return True
            
        elif err[0] == errors.SkipTest:
            self.__insert_test_result(constants.State.SKIP, test, err)
            self.error_handled = True
            raise SkipTest(err[1])
            return True
            

    def addFailure(self, test, err, capt=None, tbinfo=None):
        """
        After failure of a test, we want to record the testcase run information.
        """
        self.__insert_test_result(constants.State.FAILURE, test, err)  

    def __insert_test_result(self, state, test, err=None):
        data_payload = TestcaseDataPayload()
        data_payload.runtime = int(time.time() * 1000) - self.case_start_time
        data_payload.guid = self.testcase_guid
        data_payload.execution_guid = self.execution_guid
        data_payload.state = state
        if err is not None:
            data_payload.message = err[1].__str__().split('-------------------- >> begin captured logging << --------------------', 1)[0]
        self.testcase_manager.update_testcase_data(data_payload)
class TestTestcaseManager(unittest.TestCase):
	
    def setUp(self):
        self.manager = TCM('qa')

    def tearDown(self):
        query = """DELETE FROM execution WHERE guid = %(guid)s"""
        DatabaseManager('qa').execute_query_and_close(query,
                                                  {"guid":"anexecutionguid"})

        query = """DELETE FROM testcaseRunData WHERE guid = %(guid)s"""
        DatabaseManager('qa').execute_query_and_close(query,
                                                  {"guid":'antestcaseguid'})

    def test_insert_execution_data(self):
        payload = ExecutionQueryPayload()
        payload.guid = "anexecutionguid"
        payload.execution_start_time = 1234567890
        payload.username = "******"
        self.manager.insert_execution_data(payload)

        query = """SELECT * FROM execution WHERE guid = %(guid)s"""
        results = DatabaseManager('qa').fetchone_query_and_close(query, {"guid":'anexecutionguid'})

        self.assertTrue(results[0] == 'anexecutionguid')
        self.assertTrue(results[1] == -1)
        self.assertTrue(results[2] == 'myself')
        self.assertTrue(results[3] == 1234567890)
	
    def test_update_execution_data(self):
        payload = ExecutionQueryPayload()
        payload.guid = "anexecutionguid"
        payload.execution_start_time = 1234
        payload.username = "******"
        self.manager.insert_execution_data(payload)
        self.manager.update_execution_data("anexecutionguid", 60)

        query = """SELECT * FROM execution WHERE guid = %(guid)s"""
        results = DatabaseManager('qa').fetchone_query_and_close(query, {"guid":'anexecutionguid'})

        self.assertTrue(results[0] == 'anexecutionguid')
        self.assertTrue(results[1] == 60)
        self.assertTrue(results[2] == 'myself')
        self.assertTrue(results[3] == 1234)

    def test_insert_test_case_data(self):
        payload = TestcaseDataPayload()
        payload.guid = "antestcaseguid"
        payload.testcaseAddress = self.id()
        payload.application = "python unittest"
        payload.execution_guid = "executionmachine"
        payload.runtime = 55
        payload.state = "Massachusetts"
        payload.browser = "SeaMonkey"
        self.manager.insert_testcase_data(payload)

        query = """SELECT * FROM testcaseRunData WHERE guid = %(guid)s"""
        results = DatabaseManager('qa').\
            fetchone_query_and_close(query, {"guid":'antestcaseguid'})

        self.assertTrue(results[0] == 'antestcaseguid')
        self.assertTrue(results[1] == self.id())
        self.assertTrue(results[2] == "python unittest")
        self.assertTrue(results[3] == "executionmachine")
        self.assertTrue(results[4] == 55)
        self.assertTrue(results[5] == 'Massachusetts')
        self.assertTrue(results[6] == 'SeaMonkey')
		
    def test_update_test_case_data(self):
        payload = TestcaseDataPayload()
        payload.guid = "antestcaseguid"
        payload.testcaseAddress = self.id()
        payload.application = "python unittest"
        payload.execution_guid = "executionmachine"
        payload.runtime = 55
        payload.state = "Massachusetts"
        payload.browser = "SeaMonkey"
        self.manager.insert_testcase_data(payload)

        new_payload = TestcaseDataPayload()
        new_payload.runtime = 300
        new_payload.state = "Ohio"
        new_payload.retry_count = 82
        new_payload.guid = "antestcaseguid"
        self.manager.update_testcase_data(new_payload)

        query = """
                        SELECT * FROM testcaseRunData WHERE guid = %(guid)s
                """
        results = DatabaseManager('qa').\
            fetchone_query_and_close(query, {"guid":'antestcaseguid'})

        self.assertTrue(results[0] == 'antestcaseguid')
        self.assertTrue(results[1] == self.id())
        self.assertTrue(results[2] == "python unittest")
        self.assertTrue(results[3] == "executionmachine")
        self.assertTrue(results[4] == 300)
        self.assertTrue(results[5] == 'Ohio')
        self.assertTrue(results[6] == 'SeaMonkey')
        self.assertTrue(results[8] == 82)