#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import unittest
import copy

from pytest import raises
from pystachio import Choice

from gen.apache.aurora.api.ttypes import (
  JobUpdateSettings,
  JobUpdateStrategy,
  VariableBatchJobUpdateStrategy,
  BatchJobUpdateStrategy,
  QueueJobUpdateStrategy
)
from apache.aurora.client.api import UpdaterConfig
from apache.aurora.config.schema.base import UpdateConfig
from apache.aurora.config.schema.base import (
  BatchUpdateStrategy as PystachioBatchUpdateStrategy,
  QueueUpdateStrategy as PystachioQueueUpdateStrategy,
  VariableBatchUpdateStrategy as PystachioVariableBatchUpdateStrategy
)

from gen.apache.aurora.api.ttypes import Range


class TestUpdaterUtil(unittest.TestCase):

  EXPECTED_JOB_UPDATE_SETTINGS = JobUpdateSettings(
    blockIfNoPulsesAfterMs=None,
    updateOnlyTheseInstances=None,
    slaAware=False,
    maxPerInstanceFailures=0,
    waitForBatchCompletion=False,
    rollbackOnFailure=True,
    minWaitInInstanceRunningMs=45000,
    updateGroupSize=1,
    maxFailedInstances=0)

  UPDATE_STRATEGIES = Choice([PystachioQueueUpdateStrategy,
                            PystachioBatchUpdateStrategy,
                            PystachioVariableBatchUpdateStrategy])

  def test_multiple_ranges(self):
    """Test multiple ranges."""
    ranges = [repr(e) for e in UpdaterConfig.instances_to_ranges([1, 2, 3, 5, 7, 8])]
    assert 3 == len(ranges), "Wrong number of ranges:%s" % len(ranges)
    assert repr(Range(first=1, last=3)) in ranges, "Missing range [1,3]"
    assert repr(Range(first=5, last=5)) in ranges, "Missing range [5,5]"
    assert repr(Range(first=7, last=8)) in ranges, "Missing range [7,8]"

  def test_one_element(self):
    """Test one ID in the list."""
    ranges = [repr(e) for e in UpdaterConfig.instances_to_ranges([1])]
    assert 1 == len(ranges), "Wrong number of ranges:%s" % len(ranges)
    assert repr(Range(first=1, last=1)) in ranges, "Missing range [1,1]"

  def test_none_list(self):
    """Test None list produces None result."""
    assert UpdaterConfig.instances_to_ranges(None) is None, "Result must be None."

  def test_empty_list(self):
    """Test empty list produces None result."""
    assert UpdaterConfig.instances_to_ranges([]) is None, "Result must be None."

  def test_pulse_interval_secs(self):
    config = UpdaterConfig(
      UpdateConfig(batch_size=1,
                   watch_secs=1,
                   max_per_shard_failures=1,
                   max_total_failures=1,
                   pulse_interval_secs=60))
    assert 60000 == config.to_thrift_update_settings().blockIfNoPulsesAfterMs

  def test_pulse_interval_unset(self):
    config = UpdaterConfig(
      UpdateConfig(batch_size=1, watch_secs=1, max_per_shard_failures=1, max_total_failures=1))
    assert config.to_thrift_update_settings().blockIfNoPulsesAfterMs is None

  def test_pulse_interval_too_low(self):
    threshold = UpdaterConfig.MIN_PULSE_INTERVAL_SECONDS
    with raises(ValueError) as e:
      UpdaterConfig(UpdateConfig(batch_size=1,
                                 watch_secs=1,
                                 max_per_shard_failures=1,
                                 max_total_failures=1,
                                 pulse_interval_secs=threshold - 1))
    assert 'Pulse interval seconds must be at least %s seconds.' % threshold in e.value.message

  def test_to_thrift_update_settings_strategy(self):

    """Test to_thrift produces an expected thrift update settings configuration
       from a Pystachio update object.
    """

    config = UpdaterConfig(
      UpdateConfig(
        update_strategy=self.UPDATE_STRATEGIES(
          PystachioVariableBatchUpdateStrategy(batch_sizes=[1, 2, 3, 4]))))

    thrift_update_config = config.to_thrift_update_settings()

    update_settings = copy.deepcopy(self.EXPECTED_JOB_UPDATE_SETTINGS)

    update_settings.updateStrategy = JobUpdateStrategy(
      batchStrategy=None,
      queueStrategy=None,
      varBatchStrategy=VariableBatchJobUpdateStrategy(groupSizes=(1, 2, 3, 4)))

    assert thrift_update_config == update_settings

  def test_to_thrift_update_settings_no_strategy_queue(self):

    """Test to_thrift produces an expected thrift update settings configuration
       from a Pystachio update object that doesn't include an update strategy.

       The configuration in this test should be converted to a
       QueueJobUpdateStrategy.
    """

    config = UpdaterConfig(UpdateConfig())

    thrift_update_config = config.to_thrift_update_settings()

    update_settings = copy.deepcopy(self.EXPECTED_JOB_UPDATE_SETTINGS)
    update_settings.updateStrategy = JobUpdateStrategy(
        batchStrategy=None,
        queueStrategy=QueueJobUpdateStrategy(groupSize=1),
        varBatchStrategy=None)

    assert thrift_update_config == update_settings

  def test_to_thrift_update_settings_no_strategy_batch(self):

    """Test to_thrift produces an expected thrift update settings configuration
       from a Pystachio update object that doesn't include an update strategy.

       The configuration in this test should be converted to a
       BatchJobUpdateStrategy.
    """

    config = UpdaterConfig(UpdateConfig(wait_for_batch_completion=True))

    thrift_update_config = config.to_thrift_update_settings()

    update_settings = copy.deepcopy(self.EXPECTED_JOB_UPDATE_SETTINGS)
    update_settings.updateStrategy = JobUpdateStrategy(
        batchStrategy=BatchJobUpdateStrategy(groupSize=1),
        queueStrategy=None,
        varBatchStrategy=None)
    update_settings.waitForBatchCompletion = True

    assert thrift_update_config == update_settings

  def test_wait_for_batch_completion_and_update_strategy(self):

    """Test setting wait_for_batch_completion along with an update strategy.
       This combination should result in a fast fail.
    """

    with raises(ValueError) as e:
      UpdaterConfig(UpdateConfig(wait_for_batch_completion=True,
                                 update_strategy=self.UPDATE_STRATEGIES(
                                     PystachioBatchUpdateStrategy(
                                         batch_size=3))))

    assert ('Ambiguous update configuration. Cannot combine '
            'wait_batch_completion with an '
            'explicit update strategy.' in e.value.message)

  def test_batch_size_and_update_strategy(self):

    """Test setting a batch size along with an update strategy.
       This combination should result in a fast fail.
    """

    with raises(ValueError) as e:
      UpdaterConfig(UpdateConfig(batch_size=2,
                                 update_strategy=self.UPDATE_STRATEGIES(
                                     PystachioBatchUpdateStrategy(
                                         batch_size=3))))

    assert ('Ambiguous update configuration. Cannot combine '
            'update strategy with batch size. Please set batch'
            'size inside of update strategy instead.' in e.value.message)
