|
| 1 | +# Copyright 2017 Google Inc. |
| 2 | +# |
| 3 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +# you may not use this file except in compliance with the License. |
| 5 | +# You may obtain a copy of the License at |
| 6 | +# |
| 7 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +# |
| 9 | +# Unless required by applicable law or agreed to in writing, software |
| 10 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +# See the License for the specific language governing permissions and |
| 13 | +# limitations under the License. |
| 14 | + |
| 15 | +import functools |
| 16 | +import operator |
| 17 | +import unittest |
| 18 | + |
| 19 | +from google.cloud import error_reporting |
| 20 | +from google.cloud.gapic.errorreporting.v1beta1 import ( |
| 21 | + error_stats_service_client) |
| 22 | +from google.cloud.proto.devtools.clouderrorreporting.v1beta1 import ( |
| 23 | + error_stats_service_pb2) |
| 24 | +from google.protobuf.duration_pb2 import Duration |
| 25 | + |
| 26 | +from test_utils.retry import RetryResult |
| 27 | +from test_utils.system import unique_resource_id |
| 28 | + |
| 29 | + |
| 30 | +ERROR_MSG = 'Stackdriver Error Reporting System Test' |
| 31 | + |
| 32 | + |
| 33 | +def setUpModule(): |
| 34 | + Config.CLIENT = error_reporting.Client() |
| 35 | + |
| 36 | + |
| 37 | +class Config(object): |
| 38 | + """Run-time configuration to be modified at set-up. |
| 39 | +
|
| 40 | + This is a mutable stand-in to allow test set-up to modify |
| 41 | + global state. |
| 42 | + """ |
| 43 | + CLIENT = None |
| 44 | + |
| 45 | + |
| 46 | +def _list_groups(client): |
| 47 | + """List Error Groups from the last 60 seconds. |
| 48 | +
|
| 49 | + This class provides a wrapper around making calls to the GAX |
| 50 | + API. It's used by the system tests to find the appropriate error group |
| 51 | + to verify the error was successfully reported. |
| 52 | +
|
| 53 | + :type client: :class:`~google.cloud.error_reporting.client.Client` |
| 54 | + :param client: The client containing a project and credentials. |
| 55 | +
|
| 56 | + :rtype: :class:`~google.gax.ResourceIterator` |
| 57 | + :returns: Iterable of :class:`~.error_stats_service_pb2.ErrorGroupStats`. |
| 58 | + """ |
| 59 | + gax_api = error_stats_service_client.ErrorStatsServiceClient( |
| 60 | + credentials=client._credentials) |
| 61 | + project_name = gax_api.project_path(client.project) |
| 62 | + |
| 63 | + time_range = error_stats_service_pb2.QueryTimeRange() |
| 64 | + time_range.period = error_stats_service_pb2.QueryTimeRange.PERIOD_1_HOUR |
| 65 | + |
| 66 | + duration = Duration(seconds=60 * 60) |
| 67 | + |
| 68 | + return gax_api.list_group_stats( |
| 69 | + project_name, time_range, timed_count_duration=duration) |
| 70 | + |
| 71 | + |
| 72 | +def _simulate_exception(class_name, client): |
| 73 | + """Simulates an exception to verify it was reported. |
| 74 | +
|
| 75 | + :type class_name: str |
| 76 | + :param class_name: The name of a custom error class to |
| 77 | + create (and raise). |
| 78 | +
|
| 79 | + :type client: :class:`~google.cloud.error_reporting.client.Client` |
| 80 | + :param client: The client that will report the exception. |
| 81 | + """ |
| 82 | + custom_exc = type(class_name, (RuntimeError,), {}) |
| 83 | + try: |
| 84 | + raise custom_exc(ERROR_MSG) |
| 85 | + except RuntimeError: |
| 86 | + client.report_exception() |
| 87 | + |
| 88 | + |
| 89 | +def _get_error_count(class_name, client): |
| 90 | + """Counts the number of errors in the group of the test exception. |
| 91 | +
|
| 92 | + :type class_name: str |
| 93 | + :param class_name: The name of a custom error class used. |
| 94 | +
|
| 95 | + :type client: :class:`~google.cloud.error_reporting.client.Client` |
| 96 | + :param client: The client containing a project and credentials. |
| 97 | +
|
| 98 | + :rtype: int |
| 99 | + :returns: Group count for errors that match ``class_name``. If no |
| 100 | + match is found, returns :data:`None`. |
| 101 | + """ |
| 102 | + groups = _list_groups(client) |
| 103 | + for group in groups: |
| 104 | + if class_name in group.representative.message: |
| 105 | + return group.count |
| 106 | + |
| 107 | + |
| 108 | +class TestErrorReporting(unittest.TestCase): |
| 109 | + |
| 110 | + def test_report_exception(self): |
| 111 | + # Get a class name unique to this test case. |
| 112 | + class_name = 'RuntimeError' + unique_resource_id('_') |
| 113 | + |
| 114 | + # Simulate an error: group won't exist until we report |
| 115 | + # first exception. |
| 116 | + _simulate_exception(class_name, Config.CLIENT) |
| 117 | + |
| 118 | + is_one = functools.partial(operator.eq, 1) |
| 119 | + is_one.__name__ = 'is_one' # partial() has no name. |
| 120 | + wrapped_get_count = RetryResult(is_one)(_get_error_count) |
| 121 | + |
| 122 | + error_count = wrapped_get_count(class_name, Config.CLIENT) |
| 123 | + self.assertEqual(error_count, 1) |
0 commit comments