Coverage for manila/tests/scheduler/filters/test_base.py: 100%
71 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
1# Copyright (c) 2013 OpenStack Foundation.
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
12# implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
16from unittest import mock
18from manila.scheduler.filters import base
19from manila import test
22class TestBaseFilter(test.TestCase):
24 def setUp(self):
25 super(TestBaseFilter, self).setUp()
26 self.filter = base.BaseFilter()
28 def test_filter_one_is_called(self):
30 filters = [1, 2, 3, 4]
31 filter_properties = {'x': 'y'}
33 side_effect = lambda value, props: value in [2, 3] # noqa: E731
34 self.mock_object(self.filter,
35 '_filter_one',
36 mock.Mock(side_effect=side_effect))
38 result = list(self.filter.filter_all(filters, filter_properties))
40 self.assertEqual([2, 3], result)
43class FakeExtension(object):
45 def __init__(self, plugin):
46 self.plugin = plugin
49class BaseFakeFilter(base.BaseFilter):
50 pass
53class FakeFilter1(BaseFakeFilter):
54 """Derives from BaseFakeFilter and has a fake entry point defined.
56 Entry point is returned by fake ExtensionManager.
57 Should be included in the output of all_classes.
58 """
61class FakeFilter2(BaseFakeFilter):
62 """Derives from BaseFakeFilter but has no entry point.
64 Should be not included in all_classes.
65 """
68class FakeFilter3(base.BaseFilter):
69 """Does not derive from BaseFakeFilter.
71 Should not be included.
72 """
75class FakeFilter4(BaseFakeFilter):
76 """Derives from BaseFakeFilter and has an entry point.
78 Should be included.
79 """
82class FakeFilter5(BaseFakeFilter):
83 """Derives from BaseFakeFilter but has no entry point.
85 Should not be included.
86 """
87 run_filter_once_per_request = True
90class FakeExtensionManager(list):
92 def __init__(self, namespace):
93 classes = [FakeFilter1, FakeFilter3, FakeFilter4]
94 exts = map(FakeExtension, classes)
95 super(FakeExtensionManager, self).__init__(exts)
96 self.namespace = namespace
99class TestBaseFilterHandler(test.TestCase):
101 def setUp(self):
102 super(TestBaseFilterHandler, self).setUp()
103 self.mock_object(base.base_handler.extension,
104 'ExtensionManager',
105 FakeExtensionManager)
106 self.handler = base.BaseFilterHandler(BaseFakeFilter, 'fake_filters')
108 def test_get_all_classes(self):
109 # In order for a FakeFilter to be returned by get_all_classes, it has
110 # to comply with these rules:
111 # * It must be derived from BaseFakeFilter
112 # AND
113 # * It must have a python entrypoint assigned (returned by
114 # FakeExtensionManager)
115 expected = [FakeFilter1, FakeFilter4]
116 result = self.handler.get_all_classes()
117 self.assertEqual(expected, result)
119 def _get_filtered_objects(self, filter_classes, index=0):
120 filter_objs_initial = [1, 2, 3, 4]
121 filter_properties = {'x': 'y'}
122 return self.handler.get_filtered_objects(filter_classes,
123 filter_objs_initial,
124 filter_properties,
125 index)
127 @mock.patch.object(FakeFilter4, 'filter_all')
128 @mock.patch.object(FakeFilter3, 'filter_all', return_value=None)
129 def test_get_filtered_objects_return_none(self, fake3_filter_all,
130 fake4_filter_all):
131 filter_classes = [FakeFilter1, FakeFilter2, FakeFilter3, FakeFilter4]
132 result, last_filter = self._get_filtered_objects(filter_classes)
133 self.assertIsNone(result)
134 self.assertFalse(fake4_filter_all.called)
135 self.assertEqual('FakeFilter3', last_filter)
137 def test_get_filtered_objects(self):
138 filter_objs_expected = [1, 2, 3, 4]
139 filter_classes = [FakeFilter1, FakeFilter2, FakeFilter3, FakeFilter4]
140 result, last_filter = self._get_filtered_objects(filter_classes)
141 self.assertEqual(filter_objs_expected, result)
142 self.assertEqual('FakeFilter4', last_filter)
144 def test_get_filtered_objects_with_filter_run_once(self):
145 filter_objs_expected = [1, 2, 3, 4]
146 filter_classes = [FakeFilter5]
148 with mock.patch.object(FakeFilter5, 'filter_all',
149 return_value=filter_objs_expected
150 ) as fake5_filter_all:
151 result, last_filter = self._get_filtered_objects(filter_classes)
152 self.assertEqual(filter_objs_expected, result)
153 self.assertEqual(1, fake5_filter_all.call_count)
155 result, last_filter = self._get_filtered_objects(
156 filter_classes, index=1)
157 self.assertEqual(filter_objs_expected, result)
158 self.assertEqual(1, fake5_filter_all.call_count)
160 result, last_filter = self._get_filtered_objects(
161 filter_classes, index=2)
162 self.assertEqual(filter_objs_expected, result)
163 self.assertEqual(1, fake5_filter_all.call_count)