1#!/usr/bin/python2.7
2#
3# Copyright 2017 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 copy
8import unittest
9
10import common
11from autotest_lib.utils import labellib
12
13
14class KeyvalLabelTestCase(unittest.TestCase):
15    """Tests for basic KeyvalLabel functions."""
16
17    def test_parse_keyval_label(self):
18        got = labellib.parse_keyval_label('pool:suites')
19        self.assertEqual(got, labellib.KeyvalLabel('pool', 'suites'))
20
21    def test_parse_keyval_label_with_multiple_colons(self):
22        got = labellib.parse_keyval_label('pool:suites:penthouse')
23        self.assertEqual(got, labellib.KeyvalLabel('pool', 'suites:penthouse'))
24
25    def test_parse_keyval_label_raises(self):
26        with self.assertRaises(ValueError):
27            labellib.parse_keyval_label('webcam')
28
29    def test_format_keyval_label(self):
30        got = labellib.format_keyval_label(
31                labellib.KeyvalLabel('pool', 'suites'))
32        self.assertEqual(got, 'pool:suites')
33
34    def test_format_keyval_label_with_colon_in_value(self):
35        got = labellib.format_keyval_label(
36                labellib.KeyvalLabel('pool', 'suites:penthouse'))
37        self.assertEqual(got, 'pool:suites:penthouse')
38
39
40class LabelsMappingTestCase(unittest.TestCase):
41    """Tests for LabelsMapping class."""
42
43    def test_getlabels(self):
44        labels = ['webcam', 'pool:suites']
45        mapping = labellib.LabelsMapping(labels)
46        self.assertEqual(mapping.getlabels(), labels)
47
48    def test_init_and_getlabels_should_remove_duplicates(self):
49        labels = ['webcam', 'pool:suites', 'pool:party']
50        mapping = labellib.LabelsMapping(labels)
51        self.assertEqual(mapping.getlabels(), ['webcam', 'pool:suites'])
52
53    def test_init_and_getlabels_should_move_plain_labels_first(self):
54        labels = ['ohse:tsubame', 'webcam']
55        mapping = labellib.LabelsMapping(labels)
56        self.assertEqual(mapping.getlabels(), ['webcam', 'ohse:tsubame'])
57
58    def test_init_and_getlabels_should_preserve_plain_label_order(self):
59        labels = ['webcam', 'exec', 'method']
60        mapping = labellib.LabelsMapping(labels)
61        self.assertEqual(mapping.getlabels(), ['webcam', 'exec', 'method'])
62
63    def test_init_and_getlabels_should_preserve_keyval_label_order(self):
64        labels = ['class:protecta', 'method:metafalica', 'exec:chronicle_key']
65        mapping = labellib.LabelsMapping(labels)
66        self.assertEqual(mapping.getlabels(), labels)
67
68    def test_init_should_not_mutate_labels(self):
69        labels = ['class:protecta', 'exec:chronicle_key', 'method:metafalica']
70        input_labels = copy.deepcopy(labels)
71        mapping = labellib.LabelsMapping(input_labels)
72        mapping['class'] = 'distllista'
73        self.assertEqual(input_labels, labels)
74
75    def test_init_mutated_arg_should_not_affect_mapping(self):
76        labels = ['class:protecta', 'exec:chronicle_key', 'method:metafalica']
77        mapping = labellib.LabelsMapping(labels)
78        original_mapping = copy.deepcopy(mapping)
79        labels.pop()
80        self.assertEqual(mapping, original_mapping)
81
82    def test_duplicate_keys_should_take_first(self):
83        labels = ['webcam', 'pool:party', 'pool:suites']
84        mapping = labellib.LabelsMapping(labels)
85        self.assertEqual(mapping['pool'], 'party')
86
87    def test_getitem(self):
88        labels = ['webcam', 'pool:suites']
89        mapping = labellib.LabelsMapping(labels)
90        self.assertEqual(mapping['pool'], 'suites')
91
92    def test_in(self):
93        labels = ['webcam', 'pool:suites']
94        mapping = labellib.LabelsMapping(labels)
95        self.assertIn('pool', mapping)
96
97    def test_setitem(self):
98        labels = ['webcam']
99        mapping = labellib.LabelsMapping(labels)
100        mapping['pool'] = 'suites'
101        self.assertEqual(mapping['pool'], 'suites')
102
103    def test_setitem_to_none_should_delete(self):
104        labels = ['webcam', 'pool:suites']
105        mapping = labellib.LabelsMapping(labels)
106        mapping['pool'] = None
107        self.assertNotIn('pool', mapping)
108
109    def test_setitem_to_none_with_missing_key_should_noop(self):
110        labels = ['webcam', 'pool:suites']
111        mapping = labellib.LabelsMapping(labels)
112        mapping['foo'] = None
113        self.assertNotIn('foo', mapping)
114
115    def test_delitem(self):
116        labels = ['webcam', 'pool:suites']
117        mapping = labellib.LabelsMapping(labels)
118        del mapping['pool']
119        self.assertNotIn('pool', mapping)
120
121    def test_iter(self):
122        labels = ['webcam', 'pool:suites']
123        mapping = labellib.LabelsMapping(labels)
124        self.assertEqual(list(iter(mapping)), ['pool'])
125
126    def test_len(self):
127        labels = ['webcam', 'pool:suites']
128        mapping = labellib.LabelsMapping(labels)
129        self.assertEqual(len(mapping), 1)
130
131
132class CrosVersionTestCase(unittest.TestCase):
133    """Tests for CrosVersion functions."""
134
135    def test_parse_cros_version_without_rc(self):
136        got = labellib.parse_cros_version('lumpy-release/R27-3773.0.0')
137        self.assertEqual(got, labellib.CrosVersion('lumpy-release', 'lumpy',
138                                                   'R27', '3773.0.0', None))
139
140    def test_parse_cros_version_with_rc(self):
141        got = labellib.parse_cros_version('lumpy-release/R27-3773.0.0-rc1')
142        self.assertEqual(got, labellib.CrosVersion('lumpy-release', 'lumpy',
143                                                   'R27', '3773.0.0', 'rc1'))
144
145    def test_parse_cros_version_raises(self):
146        with self.assertRaises(ValueError):
147            labellib.parse_cros_version('foo')
148
149    def test_format_cros_version_without_rc(self):
150        got = labellib.format_cros_version(
151                labellib.CrosVersion('lumpy-release', 'lumpy', 'R27',
152                                     '3773.0.0', None))
153        self.assertEqual(got, 'lumpy-release/R27-3773.0.0')
154
155    def test_format_cros_version_with_rc(self):
156        got = labellib.format_cros_version(
157                labellib.CrosVersion('lumpy-release', 'lumpy',  'R27',
158                                     '3773.0.0', 'rc1'))
159        self.assertEqual(got, 'lumpy-release/R27-3773.0.0-rc1')
160
161    def test_parse_cros_version_for_board(self):
162        test_builds = ['lumpy-release/R27-3773.0.0-rc1',
163                       'trybot-lumpy-paladin/R27-3773.0.0',
164                       'lumpy-pre-cq/R27-3773.0.0-rc1',
165                       'lumpy-test-ap/R27-3773.0.0-rc1',
166                       'lumpy-toolchain/R27-3773.0.0-rc1',
167                       ]
168        for build in test_builds:
169            cros_version = labellib.parse_cros_version(build)
170            self.assertEqual(cros_version.board, 'lumpy')
171            self.assertEqual(cros_version.milestone, 'R27')
172
173        build = 'trybot-lumpy-a-pre-cq/R27-3773.0.0-rc1'
174        cros_version = labellib.parse_cros_version(build)
175        self.assertEqual(cros_version.board, 'lumpy-a')
176        self.assertEqual(cros_version.milestone, 'R27')
177
178        build = 'trybot-lumpy_a-pre-cq/R27-3773.0.0-rc1'
179        cros_version = labellib.parse_cros_version(build)
180        self.assertEqual(cros_version.board, 'lumpy_a')
181        self.assertEqual(cros_version.milestone, 'R27')
182
183
184if __name__ == '__main__':
185    unittest.main()
186