Upstream version 8.36.161.0
[platform/framework/web/crosswalk.git] / src / third_party / chromite / lib / stats_unittest.py
1 #!/usr/bin/python
2 # Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Unittests for stats."""
7
8 import logging
9 import os
10 import sys
11 import time
12 import urllib2
13
14 sys.path.insert(0, os.path.abspath('%s/../..' % os.path.dirname(__file__)))
15 from chromite.lib import cros_test_lib
16 from chromite.lib import parallel
17 from chromite.lib import parallel_unittest
18 from chromite.lib import partial_mock
19 from chromite.lib import stats
20 from chromite.lib import timeout_util
21
22
23 # pylint: disable=W0212
24
25
26 class StatsUploaderMock(partial_mock.PartialMock):
27   """Mocks out stats.StatsUploader."""
28
29   TARGET = 'chromite.lib.stats.StatsUploader'
30   ATTRS = ('URL', 'UPLOAD_TIMEOUT', '_Upload')
31
32   URL = 'Invalid Url'
33   # Increased timeout so that we don't get errors when the machine is loaded.
34   UPLOAD_TIMEOUT = 30
35
36   def _Upload(self, _inst, *_args, **_kwargs):
37     """Disable actual uploading."""
38     return
39
40
41 class StatsMock(partial_mock.PartialMock):
42   """Mocks out stats.Stats."""
43
44   TARGET = 'chromite.lib.stats.Stats'
45   ATTRS = ('__init__',)
46
47   def __init__(self):
48     partial_mock.PartialMock.__init__(self)
49     self.init_exception = False
50
51   def _target__init__(self, _inst, **kwargs):
52     """Fill in good values for username and host."""
53     if self.init_exception:
54       raise Exception('abc')
55
56     kwargs.setdefault('username', 'monkey@google.com')
57     kwargs.setdefault('host', 'typewriter.mtv.corp.google.com')
58     return self.backup['__init__'](_inst, **kwargs)
59
60
61 class StatsModuleMock(partial_mock.PartialMock):
62   """Mock out everything needed to use this module."""
63
64   def __init__(self):
65     partial_mock.PartialMock.__init__(self)
66     self.uploader_mock = StatsUploaderMock()
67     self.stats_mock = StatsMock()
68     self.parallel_mock = parallel_unittest.ParallelMock()
69
70   def PreStart(self):
71     self.StartPatcher(self.uploader_mock)
72     self.StartPatcher(self.stats_mock)
73     self.StartPatcher(self.parallel_mock)
74
75
76 class StatsCreationTest(cros_test_lib.MockLoggingTestCase):
77   """Test the stats creation functionality."""
78
79   def VerifyStats(self, cmd_stat):
80     self.assertNotEquals(cmd_stat.host, None)
81     self.assertNotEquals(cmd_stat.username, None)
82
83   def testIt(self):
84     """Test normal stats creation, exercising default functionality."""
85     cmd_stat = stats.Stats()
86     self.VerifyStats(cmd_stat)
87
88   def testSafeInitNormal(self):
89     """Test normal safe stats creation."""
90     cmd_stat = stats.Stats.SafeInit()
91     self.VerifyStats(cmd_stat)
92
93   def testSafeInitException(self):
94     """Safe stats creation handles exceptions properly."""
95     with cros_test_lib.LoggingCapturer() as logs:
96       cmd_stat = stats.Stats.SafeInit(monkey='foon')
97       self.assertEquals(cmd_stat, None)
98       self.AssertLogsContain(logs, 'Exception')
99
100
101 class ConditionsTest(cros_test_lib.MockTestCase):
102   """Test UploadConditionsMet."""
103
104   def testConditionsMet(self):
105     stat = stats.Stats(
106         username='chrome-bot@chromium.org', host='build42-m2.golo.chromium.org')
107     self.assertTrue(stats.StatsUploader._UploadConditionsMet(stat))
108
109   def testConditionsMet2(self):
110     stat = stats.Stats(
111         username='monkey@google.com', host='typewriter.mtv.corp.google.com')
112     self.assertTrue(stats.StatsUploader._UploadConditionsMet(stat))
113
114   def testConditionsNotMet(self):
115     stat = stats.Stats(
116         username='monkey@home.com', host='typewriter.mtv.corp.google.com')
117     self.assertFalse(stats.StatsUploader._UploadConditionsMet(stat))
118
119   def testConditionsNotMet2(self):
120     stat = stats.Stats(
121         username='monkey@google.com', host='typewriter.noname.com')
122     self.assertFalse(stats.StatsUploader._UploadConditionsMet(stat))
123
124
125 class UploadTest(cros_test_lib.MockLoggingTestCase):
126   """Test the upload functionality.
127
128   For the tests that validate debug log messages are printed, note that unit
129   tests are run with debug level logging.DEBUG, so logging.debug() messages in
130   the code under test will be displayed.
131   """
132
133   def setUp(self):
134     self.module_mock = StatsModuleMock()
135     self.StartPatcher(self.module_mock)
136
137     self.cmd_stats = stats.Stats(
138         host='test.golo.chromium.org', username='chrome-bot@chromium.org')
139
140   def testNormalRun(self):
141     """Going for code coverage."""
142     self.module_mock.uploader_mock.UnMockAttr('_Upload')
143     self.PatchObject(urllib2, 'urlopen', autospec=True)
144     stats.StatsUploader.Upload(self.cmd_stats)
145     with cros_test_lib.LoggingCapturer() as logs:
146       # pylint: disable=E1101
147       self.assertEquals(urllib2.urlopen.call_count, 1)
148       # Make sure no error messages are output in the normal case.
149       self.AssertLogsContain(logs, stats.StatsUploader.ENVIRONMENT_ERROR,
150                              inverted=True)
151       timeout_regex = stats.StatsUploader.TIMEOUT_ERROR % '\d+'
152       self.AssertLogsMatch(logs, timeout_regex, inverted=True)
153
154   def CheckSuppressException(self, e, msg):
155     """Verifies we don't propagate a given exception during upload."""
156     with cros_test_lib.LoggingCapturer() as logs:
157       stats.StatsUploader._Upload.side_effect = e
158       # Verify the exception is suppressed when error_ok=True
159       stats.StatsUploader.Upload(self.cmd_stats)
160       # Note: the default log level for unit tests is logging.DEBUG
161       self.AssertLogsContain(logs, msg)
162
163   def testUploadTimeoutIgnore(self):
164     """We don't propagate timeouts during upload."""
165     self.CheckSuppressException(
166         timeout_util.TimeoutError(),
167         stats.StatsUploader.TIMEOUT_ERROR
168         % (stats.StatsUploader.UPLOAD_TIMEOUT,))
169
170   def testEnvironmentErrorIgnore(self):
171     """We don't propagate any environment errors during upload."""
172     url = 'http://somedomainhere.com/foo/bar/uploader'
173     env_msg = stats.StatsUploader.ENVIRONMENT_ERROR
174     url_msg = stats.StatsUploader.HTTPURL_ERROR % url
175     self.CheckSuppressException(EnvironmentError(), env_msg)
176     self.CheckSuppressException(urllib2.HTTPError(url, None, None, None, None),
177                                 url_msg)
178     self.CheckSuppressException(urllib2.URLError(""), env_msg)
179
180   def testKeyboardInterruptError(self):
181     """We propagate KeyboardInterrupts."""
182     stats.StatsUploader._Upload.side_effect = KeyboardInterrupt()
183     # Verify the exception is suppressed when error_ok=True
184     self.assertRaises(KeyboardInterrupt, stats.StatsUploader.Upload,
185                       self.cmd_stats)
186
187   def testUploadTimeout(self):
188     """We timeout when the upload takes too long."""
189     def Sleep(*_args, **_kwargs):
190       time.sleep(stats.StatsUploader.UPLOAD_TIMEOUT)
191
192     stats.StatsUploader._Upload.side_effect = Sleep
193     with cros_test_lib.LoggingCapturer() as logs:
194       stats.StatsUploader.Upload(self.cmd_stats, timeout=1)
195       self.AssertLogsContain(logs, stats.StatsUploader.TIMEOUT_ERROR % ('1',))
196
197
198 class UploadContextTest(cros_test_lib.MockLoggingTestCase):
199   """Test the suppression behavior of the upload context."""
200
201   def setUp(self):
202     self.StartPatcher(StatsModuleMock())
203
204   def testNoErrors(self):
205     """Test that we don't print anything when there are no errors."""
206     with cros_test_lib.LoggingCapturer() as logs:
207       with stats.UploadContext() as queue:
208         queue.put([stats.Stats()])
209       self.AssertLogsContain(logs, stats.UNCAUGHT_UPLOAD_ERROR, inverted=True)
210       self.assertEquals(stats.StatsUploader._Upload.call_count, 1)
211
212   def testErrorSupression(self):
213     """"Test exception supression."""
214     for e in [parallel.BackgroundFailure]:
215       with cros_test_lib.LoggingCapturer() as logs:
216         with stats.UploadContext():
217           raise e()
218         self.AssertLogsContain(logs, stats.UNCAUGHT_UPLOAD_ERROR)
219
220   def testErrorPropagation(self):
221     """Test we propagate some exceptions."""
222     def RaiseContext(e):
223       with stats.UploadContext():
224         raise e()
225
226     for e in [KeyboardInterrupt, RuntimeError, Exception, BaseException,
227               SyntaxError,]:
228       self.assertRaises(e, RaiseContext, e)
229
230
231 if __name__ == '__main__':
232   cros_test_lib.main(level=logging.DEBUG)