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