def testGenerateReportWithEmptyMetricsField(self):
        # Make sure that an empty metrics field
        # does not cause failure on subsequent
        # callhome generation calls. First
        # handle None value for metrics
        self.dmd.callHome = PersistentCallHomeData()
        self.dmd.callHome.metrics = None

        # call callhome scripting
        chd = CallHomeData(self.dmd, True)
        data = chd.getData()  # noqa F841

        # Then handle empty string value
        self.dmd.callHome.metrics = ""

        # call callhome scripting
        chd = CallHomeData(self.dmd, True)
        data = chd.getData()  # noqa F841

        # Then handle whitespace-only string value
        self.dmd.callHome.metrics = "   "

        # call callhome scripting
        chd = CallHomeData(self.dmd, True)
        data = chd.getData()  # noqa F841
    def testPayloadGeneration(self):
        # check current version of report (should be empty)
        self.checkForExistingCallHomeData()

        # call callhome scripting
        beforeReportGeneration = datetime.utcnow()
        chd = CallHomeData(self.dmd, True)
        data = chd.getData()
        afterReportGeneration = datetime.utcnow()

        time.sleep(1)

        # Unfortunately the cycler code can't be disentagled
        # from itself for testability so we have to mimic it
        # for this test case.
        # What happens is that CallHomeCycler
        # kicks off the callhome script (callhome.py)
        # and takes the process output as a string
        # and stores it in the callhome object
        # in zodb (dmd.callHome). In callhome.py you can
        # see that the Main class spits out the
        # json.dumps of the output of CallHomeData.getData.
        self.dmd.callHome = PersistentCallHomeData()
        self.dmd.callHome.metrics = json.dumps(data)

        # create the actual payload that will be sent
        beforePayloadGeneration = datetime.utcnow()
        payloadGenerator = CallHome(self.dmd)
        payload = payloadGenerator.get_payload(doEncrypt=False)
        afterPayloadGeneration = datetime.utcnow()

        # decrypt payload and reconstitute object
        payloadObj = json.loads(payload)

        # make sure payload has the required fields
        self.assertTrue('product' in payloadObj)
        self.assertTrue('uuid' in payloadObj)
        self.assertTrue('symkey' in payloadObj)
        self.assertTrue('metrics' in payloadObj)

        # reconstitute metrics obj & make sure send date is present
        # and has a valid time
        metricsObj = json.loads(payloadObj['metrics'])
        self.assertTrue('Send Date' in metricsObj)
        sendDateDT = datetime.strptime(metricsObj['Send Date'],
                                       DATETIME_ISOFORMAT)
        reportDateDT = datetime.strptime(metricsObj['Report Date'],
                                         DATETIME_ISOFORMAT)
        self.assertTrue(reportDateDT < sendDateDT)
        self.assertTrue(
            beforeReportGeneration <= reportDateDT <= afterReportGeneration)
        self.assertTrue(
            beforePayloadGeneration <= sendDateDT <= afterPayloadGeneration)
    def testSavedVersionHistory(self):
        # check current version of report (should be empty)
        self.checkForExistingCallHomeData()

        # set up test version history collector
        zcml.load_string(TEST_VERSION_HISTORY_COLLECTOR)

        # generate callhome
        chd = CallHomeData(self.dmd, True)
        data = chd.getData()
        firstReportDate = data[REPORT_DATE_KEY]

        time.sleep(1)

        # make sure version history record is present and correct
        self.assertTrue(VERSION_HISTORIES_KEY in data)
        versionHistories = data[VERSION_HISTORIES_KEY]
        self.assertTrue(TEST_VERSION_HISTORY_ENTITY in versionHistories)
        versionHistory = versionHistories[TEST_VERSION_HISTORY_ENTITY]
        self.assertTrue(TEST_VERSION_1 in versionHistory)
        historyRecord = versionHistory[TEST_VERSION_1]
        self.assertTrue(VERSION_START_KEY in historyRecord)
        self.assertEquals(firstReportDate, historyRecord[VERSION_START_KEY])

        # The cycler code is where the saving of
        # callhome data in ZODB occurs. We'll have
        # to mimic that again here.
        self.dmd.callHome = PersistentCallHomeData()
        self.dmd.callHome.metrics = json.dumps(data)

        # update the version history
        global TEST_CURRENT_VERSION
        TEST_CURRENT_VERSION = TEST_VERSION_2

        # generate callhome again
        chd = CallHomeData(self.dmd, True)
        data = chd.getData()
        secondReportDate = data[REPORT_DATE_KEY]

        # make sure a second version history record exists
        self.assertTrue(VERSION_HISTORIES_KEY in data)
        versionHistories = data[VERSION_HISTORIES_KEY]
        self.assertTrue(TEST_VERSION_HISTORY_ENTITY in versionHistories)
        versionHistory = versionHistories[TEST_VERSION_HISTORY_ENTITY]
        self.assertTrue(TEST_VERSION_1 in versionHistory)
        historyRecord = versionHistory[TEST_VERSION_1]
        self.assertTrue(VERSION_START_KEY in historyRecord)
        self.assertEquals(firstReportDate, historyRecord[VERSION_START_KEY])
        self.assertTrue(TEST_VERSION_2 in versionHistory)
        historyRecord = versionHistory[TEST_VERSION_2]
        self.assertTrue(VERSION_START_KEY in historyRecord)
        self.assertEquals(secondReportDate, historyRecord[VERSION_START_KEY])
    def testSendMethod(self):
        # check current version of report (should be empty)
        self.checkForExistingCallHomeData()

        # call callhome scripting
        chd = CallHomeData(self.dmd, True)
        data = chd.getData()

        # Unfortunately the cycler code can't be disentagled
        # from itself for testability so we have to mimic it
        # for this test case.
        # What happens is that CallHomeCycler
        # kicks off the callhome script (callhome.py)
        # and takes the process output as a string
        # and stores it in the callhome object
        # in zodb (dmd.callHome). In callhome.py you can
        # see that the Main class spits out the
        # json.dumps of the output of CallHomeData.getData.
        self.dmd.callHome = PersistentCallHomeData()
        self.dmd.callHome.metrics = json.dumps(data)

        # create the actual payload that will be sent
        payloadGenerator = CallHome(self.dmd)
        payload = payloadGenerator.get_payload(doEncrypt=False)

        # reconstitute object
        payloadObj = json.loads(payload)

        # reconstitute metrics obj & make sure send date is present
        # and has a valid time
        metricsObj = json.loads(payloadObj['metrics'])
        self.assertTrue('Send Method' in metricsObj)
        self.assertEquals('directpost', metricsObj['Send Method'])

        # Fetch the payload the browserjs way
        payloadGenerator = CallHome(self.dmd)
        payload = payloadGenerator.get_payload(method='browserjs',
                                               doEncrypt=False)

        # reconstitute object
        payloadObj = json.loads(payload)

        # reconstitute metrics obj & make sure send date is present
        # and has a valid time
        metricsObj = json.loads(payloadObj['metrics'])
        self.assertTrue('Send Method' in metricsObj)
        self.assertEquals('browserjs', metricsObj['Send Method'])