#!/usr/bin/python

# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Unittests for lab status."""

import constants
from mock import Mock
import sys
import time
import urllib

sys.path.insert(0, constants.SOURCE_ROOT)
from chromite.cbuildbot import lab_status
from chromite.lib import cros_test_lib


class TestLabStatus(cros_test_lib.MockTestCase):
  """Class that tests GetLabStatus and CheckLabStatus."""

  def setUp(self):
    self.PatchObject(time, 'sleep')
    self.PatchObject(urllib, 'urlopen')

  def _LabStatusFile(self, message, general_state):
    """Returns a file-like object with the status message written in it."""
    my_response = Mock()
    my_response.json = '{"message": "%s", "general_state": "%s"}' % (
        message, general_state)
    return my_response

  def _TestGetLabStatusHelper(self, lab_message, general_state, expected_return,
                              max_attempts=5, failed_attempts=0):
    """Tests whether we get correct lab status.

    Args:
      lab_message: A message describing lab status and
                   disabled boards, e.g. "Lab is Up [stumpy, kiev]"
      general_state: Current lab state, e.g. 'open'.
      expected_return: The expected return of GetLabStatus,
                       e.g. {'lab_is_up': True, 'message': 'Lab is up'}.
      max_attempts: Max attempts GetLabStatus will make to get lab status.
      failed_attempts: Number of failed attempts we want to mock.
    """
    return_status = self._LabStatusFile(lab_message, general_state)
    urlopen_side_effect = [500 for _ in range(failed_attempts)]
    if failed_attempts < max_attempts:
      urlopen_side_effect.append(200)
      call_count = failed_attempts + 1
    else:
      call_count = max_attempts
    return_status.getcode.side_effect = urlopen_side_effect
    urllib.urlopen.return_value = return_status
    return_status.read.return_value = return_status.json
    self.assertEqual(lab_status.GetLabStatus(max_attempts), expected_return)
    # pylint: disable=E1101
    self.assertEqual(urllib.urlopen.call_count, call_count)

  def testGetLabStatusWithOneAttempt(self):
    """Tests that GetLabStatus succeeds with one attempt."""
    expected_return = {'lab_is_up': True, 'message': 'Lab is up'}
    self._TestGetLabStatusHelper('Lab is up', 'open', expected_return)

  def testGetLabStatusWithMultipleAttempts(self):
    """Tests that GetLabStatus succeeds after multiple tries."""
    expected_return = {'lab_is_up': True, 'message': 'Lab is up'}
    self._TestGetLabStatusHelper('Lab is up', 'open', expected_return,
                              max_attempts=5, failed_attempts=3)

  def testGetLabStatusFailsWithMultipleAttempts(self):
    """Tests that GetLabStatus fails after multiple tries."""
    expected_return = {'lab_is_up': True, 'message': ''}
    self._TestGetLabStatusHelper('dummy_msg', 'dummy_state', expected_return,
                              max_attempts=5, failed_attempts=5)

  def _BuildLabStatus(self, lab_is_up, disabled_boards=None):
    """Build a dictionary representing the lab status."""
    if lab_is_up:
      message = 'Lab is Open'
      if disabled_boards:
        message += '[%s]' % (', '.join(disabled_boards))
    else:
      message = 'Lab is Down (For some reason it is down.)'

    status = {'lab_is_up': lab_is_up, 'message': message}
    return status

  def _TestCheckLabStatusHelper(self, lab_is_up):
    """Tests CheckLabStatus runs properly."""
    self.PatchObject(lab_status, 'GetLabStatus')
    status = self._BuildLabStatus(lab_is_up)
    lab_status.GetLabStatus.return_value = status
    if lab_is_up:
      lab_status.CheckLabStatus()
    else:
      self.assertRaises(lab_status.LabIsDownException,
                        lab_status.CheckLabStatus)

  def testCheckLabStatusWhenLabUp(self):
    """Tests CheckLabStatus runs properly when lab is up."""
    self._TestCheckLabStatusHelper(True)

  def testCheckLabStatusWhenLabDown(self):
    """Tests CheckLabStatus runs properly when lab is down."""
    self._TestCheckLabStatusHelper(False)

  def testCheckLabStatusWhenBoardsDisabled(self):
    """Tests CheckLabStatus runs properly when some boards are disabled."""
    self.PatchObject(lab_status, 'GetLabStatus')
    status = self._BuildLabStatus(True, ['stumpy', 'kiev', 'x85-alex'])
    lab_status.GetLabStatus.return_value = status
    lab_status.CheckLabStatus('lumpy')
    self.assertRaises(lab_status.BoardIsDisabledException,
                      lab_status.CheckLabStatus,
                      'stumpy')


if __name__ == '__main__':
  cros_test_lib.main()
