blob: 8a178692f3db5cbffa6675eba75f860a3c71b721 [file] [log] [blame]
#!/usr/bin/python
# Copyright (c) 2014 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 the retry_stats.py module."""
from __future__ import print_function
import os
import StringIO
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(
os.path.abspath(__file__)))))
from chromite.lib import cros_test_lib
from chromite.lib import retry_stats
# We access internal members to help with testing.
# pylint: disable=W0212
class TestRetryException(Exception):
"""Used when testing failure cases."""
class TestRetryStats(cros_test_lib.TestCase):
"""This contains test cases for the retry_stats module."""
CAT = 'Test Service A'
CAT_B = 'Test Service B'
SUCCESS_RESULT = 'success result'
def setUp(self):
retry_stats._ResetStatsForUnittests()
def handlerNoRetry(self, _e):
return False
def handlerRetry(self, _e):
return True
def callSuccess(self):
return self.SUCCESS_RESULT
def callFailure(self):
raise TestRetryException()
def _verifyStats(self, category, success=0, failure=0, retry=0):
"""Verify that the given category has the specified values collected."""
stats = retry_stats._STATS_COLLECTION[category]
self.assertEqual(stats.success.value, success)
self.assertEqual(stats.failure.value, failure)
self.assertEqual(stats.retry.value, retry)
def testSetupStats(self):
"""Verify that we do something when we setup a new stats category."""
# We start out empty.
self.assertEqual(retry_stats._STATS_COLLECTION, {})
# We add something else
retry_stats.SetupStats()
self.assertItemsEqual(
retry_stats._STATS_COLLECTION.keys(),
retry_stats.CATEGORIES)
for category in retry_stats.CATEGORIES:
self._verifyStats(category)
def testSetupStatsExplicit(self):
"""Verify that we do something when we setup a new stats category."""
# We start out empty.
self.assertEqual(retry_stats._STATS_COLLECTION, {})
# We add something else
retry_stats.SetupStats([self.CAT, self.CAT_B])
self.assertEqual(len(retry_stats._STATS_COLLECTION), 2)
self.assertTrue(self.CAT_B in retry_stats._STATS_COLLECTION)
self._verifyStats(self.CAT)
self._verifyStats(self.CAT_B)
def testReportStatsEmpty(self):
retry_stats.SetupStats([self.CAT])
out = StringIO.StringIO()
retry_stats.ReportStats(out)
expected = """************************************************************
** Performance Statistics for Test Service A
**
** Success: 0
** Failure: 0
** Retries: 0
** Total: 0
************************************************************
"""
self.assertEqual(out.getvalue(), expected)
def testSuccessNoSetup(self):
self.assertEqual(retry_stats._STATS_COLLECTION, {})
result = retry_stats.RetryWithStats(
self.CAT, self.handlerNoRetry, 3, self.callSuccess)
self.assertEqual(result, self.SUCCESS_RESULT)
result = retry_stats.RetryWithStats(
self.CAT, self.handlerNoRetry, 3, self.callSuccess)
self.assertEqual(result, self.SUCCESS_RESULT)
self.assertEqual(retry_stats._STATS_COLLECTION, {})
def testFailureNoRetryNoSetup(self):
self.assertEqual(retry_stats._STATS_COLLECTION, {})
self.assertRaises(TestRetryException,
retry_stats.RetryWithStats,
self.CAT, self.handlerNoRetry, 3, self.callFailure)
self.assertRaises(TestRetryException,
retry_stats.RetryWithStats,
self.CAT, self.handlerNoRetry, 3, self.callFailure)
self.assertEqual(retry_stats._STATS_COLLECTION, {})
def testSuccess(self):
retry_stats.SetupStats([self.CAT])
self._verifyStats(self.CAT)
# Succeed once.
result = retry_stats.RetryWithStats(
self.CAT, self.handlerNoRetry, 3, self.callSuccess)
self.assertEqual(result, self.SUCCESS_RESULT)
self._verifyStats(self.CAT, success=1)
# Succeed twice.
result = retry_stats.RetryWithStats(
self.CAT, self.handlerNoRetry, 3, self.callSuccess)
self.assertEqual(result, self.SUCCESS_RESULT)
self._verifyStats(self.CAT, success=2)
def testSuccessRetry(self):
retry_stats.SetupStats([self.CAT])
self._verifyStats(self.CAT)
# Use this scoped list as a persistent counter.
call_counter = ['fail 1', 'fail 2']
def callRetrySuccess():
if call_counter:
raise TestRetryException(call_counter.pop())
else:
return self.SUCCESS_RESULT
# Retry twice, then succeed.
result = retry_stats.RetryWithStats(
self.CAT, self.handlerRetry, 3, callRetrySuccess)
self.assertEqual(result, self.SUCCESS_RESULT)
self._verifyStats(self.CAT, success=1, retry=2)
def testFailureNoRetry(self):
retry_stats.SetupStats([self.CAT])
self._verifyStats(self.CAT)
# Fail once without retries.
self.assertRaises(TestRetryException,
retry_stats.RetryWithStats,
self.CAT, self.handlerNoRetry, 3, self.callFailure)
self._verifyStats(self.CAT, failure=1)
# Fail twice without retries.
self.assertRaises(TestRetryException,
retry_stats.RetryWithStats,
self.CAT, self.handlerNoRetry, 3, self.callFailure)
self._verifyStats(self.CAT, failure=2)
def testFailureRetry(self):
retry_stats.SetupStats([self.CAT])
self._verifyStats(self.CAT)
# Fail once with exhausted retries.
self.assertRaises(TestRetryException,
retry_stats.RetryWithStats,
self.CAT, self.handlerRetry, 3, self.callFailure)
self._verifyStats(self.CAT, failure=1, retry=3) # 3 retries = 4 attempts.
# Fail twice with exhausted retries.
self.assertRaises(TestRetryException,
retry_stats.RetryWithStats,
self.CAT, self.handlerRetry, 3, self.callFailure)
self._verifyStats(self.CAT, failure=2, retry=6)
if __name__ == '__main__':
cros_test_lib.main()