1#!/usr/bin/python
2#
3# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7import datetime
8import unittest
9
10import mock
11import mox
12
13import common
14from autotest_lib.server.cros.dynamic_suite import reporting_utils
15
16
17class TestMergeBugTemplate(mox.MoxTestBase):
18    """Test bug can be properly merged and validated."""
19    def test_validate_success(self):
20        """Test a valid bug can be verified successfully."""
21        bug_template= {}
22        bug_template['owner'] = 'someone@company.com'
23        reporting_utils.BugTemplate.validate_bug_template(bug_template)
24
25
26    def test_validate_success(self):
27        """Test a valid bug can be verified successfully."""
28        # Bug template must be a dictionary.
29        bug_template = ['test']
30        self.assertRaises(reporting_utils.InvalidBugTemplateException,
31                          reporting_utils.BugTemplate.validate_bug_template,
32                          bug_template)
33
34        # Bug template must contain value for essential attribute, e.g., owner.
35        bug_template= {'no-owner': 'user1'}
36        self.assertRaises(reporting_utils.InvalidBugTemplateException,
37                          reporting_utils.BugTemplate.validate_bug_template,
38                          bug_template)
39
40        # Bug template must contain value for essential attribute, e.g., owner.
41        bug_template= {'owner': 'invalid_email_address'}
42        self.assertRaises(reporting_utils.InvalidBugTemplateException,
43                          reporting_utils.BugTemplate.validate_bug_template,
44                          bug_template)
45
46        # Check unexpected attributes.
47        bug_template= {}
48        bug_template['random tag'] = 'test'
49        self.assertRaises(reporting_utils.InvalidBugTemplateException,
50                          reporting_utils.BugTemplate.validate_bug_template,
51                          bug_template)
52
53        # Value for cc must be a list
54        bug_template= {}
55        bug_template['cc'] = 'test'
56        self.assertRaises(reporting_utils.InvalidBugTemplateException,
57                          reporting_utils.BugTemplate.validate_bug_template,
58                          bug_template)
59
60        # Value for labels must be a list
61        bug_template= {}
62        bug_template['labels'] = 'test'
63        self.assertRaises(reporting_utils.InvalidBugTemplateException,
64                          reporting_utils.BugTemplate.validate_bug_template,
65                          bug_template)
66
67
68    def test_merge_success(self):
69        """Test test and suite bug templates can be merged successfully."""
70        test_bug_template = {
71            'labels': ['l1'],
72            'owner': 'user1@chromium.org',
73            'status': 'Assigned',
74            'title': None,
75            'cc': ['cc1@chromium.org', 'cc2@chromium.org']
76        }
77        suite_bug_template = {
78            'labels': ['l2'],
79            'owner': 'user2@chromium.org',
80            'status': 'Fixed',
81            'summary': 'This is a short summary for suite bug',
82            'title': 'Title for suite bug',
83            'cc': ['cc2@chromium.org', 'cc3@chromium.org']
84        }
85        bug_template = reporting_utils.BugTemplate(suite_bug_template)
86        merged_bug_template = bug_template.finalize_bug_template(
87                test_bug_template)
88        self.assertEqual(merged_bug_template['owner'],
89                         test_bug_template['owner'],
90                         'Value in test bug template should prevail.')
91
92        self.assertEqual(merged_bug_template['title'],
93                         suite_bug_template['title'],
94                         'If an attribute has value None in test bug template, '
95                         'use the value given in suite bug template.')
96
97        self.assertEqual(merged_bug_template['summary'],
98                         suite_bug_template['summary'],
99                         'If an attribute does not exist in test bug template, '
100                         'but exists in suite bug template, it should be '
101                         'included in the merged template.')
102
103        self.assertEqual(merged_bug_template['cc'],
104                         test_bug_template['cc'] + suite_bug_template['cc'],
105                         'List values for an attribute should be merged.')
106
107        self.assertEqual(merged_bug_template['labels'],
108                         test_bug_template['labels'] +
109                         suite_bug_template['labels'],
110                         'List values for an attribute should be merged.')
111
112        test_bug_template['owner'] = ''
113        test_bug_template['cc'] = ['']
114        suite_bug_template['owner'] = ''
115        suite_bug_template['cc'] = ['']
116        bug_template = reporting_utils.BugTemplate(suite_bug_template)
117        merged_bug_template = bug_template.finalize_bug_template(
118                test_bug_template)
119        self.assertFalse('owner' in merged_bug_template,
120                         'owner should be removed from the merged template.')
121        self.assertFalse('cc' in merged_bug_template,
122                         'cc should be removed from the merged template.')
123
124
125class NewDatetime(datetime.datetime):
126    """Fake datetime.datetime class.
127
128    datetime.datetime cannot be patched directly since it's a built-in
129    type that is immutable. NewDatetime is created here for patching
130    datetime.datetime.now.
131    """
132    @classmethod
133    def utcnow(cls):
134        """Fake datetime.datetime.utcnow()."""
135        pass
136
137
138class TestLinks(unittest.TestCase):
139    """Test links of test can be properly generated."""
140
141    def setUp(self):
142        old_datetime = datetime.datetime
143        datetime.datetime = NewDatetime
144        mock_now = mock.patch('datetime.datetime.utcnow')
145        self._mock_now = mock_now.start()
146        self.addCleanup(mock_now.stop)
147        self.addCleanup(setattr, datetime, 'datetime', old_datetime)
148
149
150    def test_generate_test_history_link(self):
151        """Test a link of test history can be generated."""
152        self._mock_now.return_value = datetime.datetime(2018, 3, 29)
153        link = reporting_utils.link_test_history('jetstream_PrioritizedDevice')
154        expected_link = ('https://stainless.corp.google.com/search?'
155                         'test=^jetstream\_PrioritizedDevice$&'
156                         'first_date=2018-03-01&'
157                         'last_date=2018-03-29&'
158                         'row=model&col=build&view=matrix')
159        self.assertEqual(link, expected_link)
160
161
162if __name__ == '__main__':
163    unittest.main()
164