###############################################################################
# (c) Copyright 2019 CERN for the benefit of the LHCb Collaboration           #
#                                                                             #
# This software is distributed under the terms of the GNU General Public      #
# Licence version 3 (GPL Version 3), copied verbatim in the file "LICENSE".   #
#                                                                             #
# In applying this licence, CERN does not waive the privileges and immunities #
# granted to it by virtue of its status as an Intergovernmental Organization  #
# or submit itself to any jurisdiction.                                       #
###############################################################################
"""Unittest for: LHCbDIRAC.AccountingSystem.private.Plotters.JobStepPlotter.

JobStepPlotter.__bases__:
  DIRAC.AccountingSystem.private.Plotters.BaseReporter

We are assuming there is a solid test of __bases__, we are not testing them
here and assuming they work fine.

IMPORTANT: the test MUST be pylint compliant !
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import mock
import unittest


class JobStepPlotterTestCase(unittest.TestCase):
  """JobStepPlotterTestCase."""

  moduleTested = None
  classsTested = None

  def mockModuleTested(self, moduleTested):
    """Used to not redo the mocking done on the parent class ( if any )"""

    # Tries to get the mocks of the parent TestCases ( if any )
    for baseClass in self.__class__.__bases__:
      try:
        # pylint: disable=no-member
        moduleTested = baseClass.mockModuleTested(moduleTested)
      except TypeError:
        continue

    # And then makes its own mock
    class MockJobStep:
      # pylint: disable=missing-docstring,no-init
      definitionKeyFields = ('JobGroup', 'RunNumber', 'EventType', 'ProcessingType',
                             'ProcessingStep', 'Site', 'FinalStepState')

    moduleTested.JobStep = mock.Mock(return_value=MockJobStep())

    return moduleTested

  def setUp(self):
    """Setup the test case."""

    import LHCbDIRAC.AccountingSystem.private.Plotters.JobStepPlotter as moduleTested

    self.moduleTested = self.mockModuleTested(moduleTested)
    self.classsTested = self.moduleTested.JobStepPlotter

  def tearDown(self):
    """Tear down the test case."""

    del self.moduleTested
    del self.classsTested

# ...............................................................................


class JobStepPlotterUnitTest(JobStepPlotterTestCase):
  """JobStepPlotterUnitTest.

  <constructor>
   - test_instantiate
  <class variables>
   - test_typeName
   - test_typeKeyFields
   - test_reportCPUEfficiencyName
   - test_reportCPUUsageName
   - test_reportPieCPUTimeName
   - test_reportCumulativeCPUTimeName
   - test_reportNormCPUTimeName
   - test_reportCumulativeNormCPUTimeName
   - test_reportPieNormCPUTimeName
   - test_reportInputDataName
   - test_reportCumulativeInputDataName
   - test_reportPieInputDataName
   - test_reportOutputDataName
   - test_reportCumulativeOutputDataName
   - test_reportPieOutputDataName
   - test_reportInputEventsName
   - test_reportCumulativeInputEventsName
   - test_reportPieInputEventsName
   - test_reportOutputEventsName
   - test_reportCumulativeOutputEventsName
   - test_reportPieOutputEventsName
   - test_reportInputEventsPerOutputEventsName
   - test_reportCPUTimePerOutputEventsName
   - test_reportCPUTimePerInputEventsName
  <methods>
  """

  def test_instantiate(self):
    """tests that we can instantiate one object of the tested class."""
    obj = self.classsTested(None, None)
    self.assertEqual('JobStepPlotter', obj.__class__.__name__,
                     msg='Expected JobStepPlotter object')

  def test_typeName(self):
    """test the class variable "_typeName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._typeName, "JobStep",
                     msg='Expected JobStep as value')

  def test_typeKeyFields(self):
    """test the class variable "_typeKeyFields"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._typeKeyFields, ['JobGroup', 'RunNumber', 'EventType',
                                          'ProcessingType', 'ProcessingStep',
                                          'Site', 'FinalStepState'],
                     msg='Expected keys from MockJobStep')

  def test_reportCPUEfficiencyName(self):
    """test the class variable "_reportCPUEfficiencyName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportCPUEfficiencyName, "CPU efficiency",
                     msg='Expected CPU efficiency as value')

  def test_reportCPUUsageName(self):
    """test the class variable "_reportCPUUsageName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportCPUUsageName, "CPU time",
                     msg='Expected CPU time as value')

  def test_reportPieCPUTimeName(self):
    """test the class variable "_reportPieCPUTimeName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportPieCPUTimeName, "Pie plot of CPU time",
                     msg='Expected Pie plot of CPU time as value')

  def test_reportCumulativeCPUTimeName(self):
    """test the class variable "_reportCumulativeCPUTimeName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportCumulativeCPUTimeName, "Cumulative CPU time",
                     msg='Expected Cumulative CPU time as value')

  def test_reportNormCPUTimeName(self):
    """test the class variable "_reportNormCPUTimeName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportNormCPUTimeName, "NormCPU time",
                     msg='Expected NormCPU time as value')

  def test_reportCumulativeNormCPUTimeName(self):
    """test the class variable "_reportCumulativeNormCPUTimeName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportCumulativeNormCPUTimeName, "Cumulative normalized CPU time",
                     msg='Expected Cumulative normalized CPU time as value')

  def test_reportPieNormCPUTimeName(self):
    """test the class variable "_reportPieNormCPUTimeName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportPieNormCPUTimeName, "Pie plot of NormCPU time",
                     msg='Expected Pie plot of NormCPU time as value')

  def test_reportInputDataName(self):
    """test the class variable "_reportInputDataName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportInputDataName, "Input Data",
                     msg='Expected Input Data as value')

  def test_reportCumulativeInputDataName(self):
    """test the class variable "_reportCumulativeInputDataName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportCumulativeInputDataName, "Cumulative Input Data",
                     msg='Expected Cumulative Input Data as value')

  def test_reportPieInputDataName(self):
    """test the class variable "_reportPieInputDataName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportPieInputDataName, "Pie plot of Input Data",
                     msg='Expected Pie plot of Input Data as value')

  def test_reportOutputDataName(self):
    """test the class variable "_reportOutputDataName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportOutputDataName, "Output Data",
                     msg='Expected Output Data as value')

  def test_reportCumulativeOutputDataName(self):
    """test the class variable "_reportCumulativeOutputDataName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportCumulativeOutputDataName, "Cumulative OutputData",
                     msg='Expected Cumulative OutputData as value')

  def test_reportPieOutputDataName(self):
    """test the class variable "_reportPieOutputDataName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportPieOutputDataName, "Pie plot of Output Data",
                     msg='Expected Pie plot of Output Data as value')

  def test_reportInputEventsName(self):
    """test the class variable "_reportInputEventsName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportInputEventsName, "Input Events",
                     msg='Expected Input Events as value')

  def test_reportCumulativeInputEventsName(self):
    """test the class variable "_reportCumulativeInputEventsName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportCumulativeInputEventsName, "Cumulative Input Events",
                     msg='Expected Cumulative Input Events as value')

  def test_reportPieInputEventsName(self):
    """test the class variable "_reportPieInputEventsName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportPieInputEventsName, "Pie plot of Input Events",
                     msg='Expected Pie plot of Input Events as value')

  def test_reportOutputEventsName(self):
    """test the class variable "_reportOutputEventsName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportOutputEventsName, "Output Events",
                     msg='Expected Output Events as value')

  def test_reportCumulativeOutputEventsName(self):
    """test the class variable "_reportCumulativeOutputEventsName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportCumulativeOutputEventsName, "Cumulative Output Events",
                     msg='Expected Cumulative Output Events as value')

  def test_reportPieOutputEventsName(self):
    """test the class variable "_reportPieOutputEventsName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportPieOutputEventsName, "Pie plot of Output Events",
                     msg='Expected Pie plot of Output Events as value')

  def test_reportInputEventsPerOutputEventsName(self):
    """test the class variable "_reportInputEventsPerOutputEventsName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportInputEventsPerOutputEventsName, "Input/Output Events",
                     msg='Expected Input/Output Events as value')

  def test_reportCPUTimePerOutputEventsName(self):
    """test the class variable "_reportCPUTimePerOutputEventsName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportCPUTimePerOutputEventsName, "CPUTime/Output Events",
                     msg='Expected CPUTime/Output Events as value')

  def test_reportCPUTimePerInputEventsName(self):
    """test the class variable "_reportCPUTimePerInputEventsName"."""
    obj = self.classsTested(None, None)
    self.assertEqual(obj._reportCPUTimePerInputEventsName, "CPUTime/Input Events",
                     msg='Expected CPUTime/Input Events as value')

  # FIXME: add crashes !

################################################################################


if __name__ == '__main__':
  suite = unittest.defaultTestLoader.loadTestsFromTestCase(JobStepPlotterTestCase)
  suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(JobStepPlotterUnitTest))
  testResult = unittest.TextTestRunner(verbosity=2).run(suite)
