blob: bc5674797edfb133fe828b7724decd0a57f72038 [file] [log] [blame]
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -05001# Copyright 2017-present Open Networking 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 implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15from mock import Mock
16import random
17
18def mock_enumerator(items):
19 e = lambda:None
20 e.all = lambda:items
21 return e
22
Scott Bakerd1702d72017-11-17 12:12:00 -080023# A list of all mock object stores that have been created
24AllMockObjectStores = []
25
26class MockObjectList:
27 item_list = None
28
29 def __init__(self, initial=None):
30 self.id_counter = 0
31 if initial:
32 self.item_list=initial
33 elif self.item_list is None:
34 self.item_list=[]
35
36 def get_items(self):
37 return self.item_list
38
39 def count(self):
40 return len(self.get_items())
41
42 def first(self):
43 return self.get_items()[0]
44
45 def all(self):
46 return self.get_items()
47
48 def filter(self, **kwargs):
49 items = self.get_items()
50 for (k,v) in kwargs.items():
51 items = [x for x in items if getattr(x,k) == v]
52 return items
53
54 def get(self, **kwargs):
55 objs = self.filter(**kwargs)
56 if not objs:
Matteo Scandoloaee7e452018-05-21 16:45:35 -070057 raise IndexError("No objects matching %s" % str(kwargs))
Scott Bakerd1702d72017-11-17 12:12:00 -080058 return objs[0]
59
60class MockObjectStore(MockObjectList):
61 def save(self, o):
62 if (not hasattr(o,"id")) or (not o.id) or (o.id==98052):
63 for item in self.get_items():
64 if item.id >= self.id_counter:
65 self.id_counter = item.id + 1
66
67 o.id = self.id_counter
68 self.id_counter = self.id_counter + 1
69
70 for item in self.get_items():
71 if item.id == o.id:
72 item = o
73 break
74 else:
75 self.get_items().append(o)
76
Scott Baker5b7fba02018-10-17 08:46:46 -070077class MockObject(object):
Scott Bakerd1702d72017-11-17 12:12:00 -080078 objects = None
79 id = None
80 deleted = False
81
Scott Baker5b7fba02018-10-17 08:46:46 -070082 field_names = []
83
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -050084 def __init__(self, **kwargs):
Scott Baker5b7fba02018-10-17 08:46:46 -070085 object.__setattr__(self, 'is_set', {})
86
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -050087 setattr(self, 'backend_code', 0)
88 setattr(self, 'id', 98052)
89 setattr(self, 'pk', random.randint(0, 1<<30))
Scott Baker5b7fba02018-10-17 08:46:46 -070090
91 self.leaf_model = self
92
93 # reset is_set
94 self.is_set = {}
95
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -050096 for (k,v) in kwargs.items():
97 setattr(self,k,v)
98
Scott Baker5b7fba02018-10-17 08:46:46 -070099 self.is_new = True
100 self._initial = self._dict
101
102 def __setattr__(self, name, value):
103 self.is_set[name] = True
104 object.__setattr__(self, name, value)
105
Scott Bakerd1702d72017-11-17 12:12:00 -0800106 @property
107 def self_content_type_id(self):
108 return self.__class__.__name__
109
Scott Bakere0499552018-05-18 12:07:53 -0700110 def save(self, update_fields=[], always_update_timestamp=False):
Scott Bakerd1702d72017-11-17 12:12:00 -0800111 if self.objects:
112 self.objects.save(self)
113
114 def delete(self):
115 pass
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -0500116
117 def tologdict(self):
118 return {}
119
Scott Baker5b7fba02018-10-17 08:46:46 -0700120 @property
121 def _dict(self):
122 d={}
123 for name in self.field_names:
124 if self.is_set.get(name, False):
125 d[name] = getattr(self, name)
126 return d
127
128 @property
129 def diff(self):
130 d1 = self._initial
131 d2 = self._dict
132 all_field_names = self.field_names
133 diffs=[]
134 for k in all_field_names:
135 if (d1.get(k,None) != d2.get(k,None)):
136 diffs.append( (k, (d1.get(k,None), d2.get(k,None))) )
137
138 return dict(diffs)
139
140 @property
141 def has_changed(self):
142 return bool(self.diff)
143
144 @property
145 def changed_fields(self):
146 if self.is_new:
147 return self._dict.keys()
148 return self.diff.keys()
149
150 def has_field_changed(self, field_name):
151 return field_name in self.diff.keys()
152
153 def get_field_diff(self, field_name):
154 return self.diff.get(field_name, None)
155
156 def recompute_initial(self):
157 self._initial = self._dict
158
159 def save_changed_fields(self, always_update_timestamp=False):
160 if self.has_changed:
161 update_fields = self.changed_fields
162 if always_update_timestamp and "updated" not in update_fields:
163 update_fields.append("updated")
164 self.save(update_fields=sorted(update_fields), always_update_timestamp=always_update_timestamp)
165
166
Scott Bakerd1702d72017-11-17 12:12:00 -0800167def get_MockObjectStore(x):
168 store = globals()["Mock%sObjects" % x]()
169 if not store in AllMockObjectStores:
170 AllMockObjectStores.append(store)
171 return store
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -0500172
Scott Bakerc2fddaa2019-01-30 15:45:03 -0800173class ModelAccessor(object):
174 def check_db_connection_okay(self):
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -0500175 return True
176
Scott Bakerc2fddaa2019-01-30 15:45:03 -0800177 def connection_close(self):
178 pass
179
180 def journal_object(self, *args, **kwargs):
181 pass
182
183 def obj_exists(self, o):
184 # gRPC will default id to '0' for uninitialized objects
185 return (o.id is not None) and (o.id != 0)
186
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -0500187 def fetch_pending(self, model, deleted = False):
188 num = random.randint(1, 5)
189 object_list = []
190
191 for i in range(num):
192 if isinstance(model, list):
193 model = model[0]
194
195 try:
196 obj = model()
197 except:
198 import pdb
199 pdb.set_trace()
200
201 obj.name = "Opinionated Berry %d"%i
202 object_list.append(obj)
203
204 return object_list
205
Scott Bakerd1702d72017-11-17 12:12:00 -0800206 def reset_all_object_stores(self):
207 for store in AllMockObjectStores:
208 store.items = []
209
Matteo Scandoloa6a25c42018-03-13 16:04:22 -0700210 def get_model_class(self, classname):
211 return globals()[classname]
212
Scott Bakerc2fddaa2019-01-30 15:45:03 -0800213 def has_model_class(self, classname):
214 return classname in globals()
215
216 def __getattr__(self, name):
217 """ Wrapper for getattr to facilitate retrieval of classes """
218 has_model_class = self.__getattribute__("has_model_class")
219 get_model_class = self.__getattribute__("get_model_class")
220 if has_model_class(name):
221 return get_model_class(name)
222
223 # Default behaviour
224 return self.__getattribute__(name)
225
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -0500226model_accessor = ModelAccessor()
227
Scott Baker4839dec2019-02-27 16:50:37 -0800228def get_first_site():
229 return model_accessor.Site.objects.first().id
230
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -0500231class ObjectSet(object):
232 def __init__(self, objects):
233 self.objects = objects
234
235 def all(self):
236 return self.objects
237
238#####
239# DO NOT MODIFY THE CLASSES BELOW. THEY ARE AUTOGENERATED.
240#
241
242{% for m in proto.messages -%}
Scott Bakerd1702d72017-11-17 12:12:00 -0800243class Mock{{ m.name }}Objects(MockObjectStore): pass
244class {{ m.name }}(MockObject):
245 objects = get_MockObjectStore("{{ m.name }}")
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -0500246 {% for f in xproto_base_fields(m, proto.message_table) + m.fields -%}
247 {{ f.name }} = {{ xproto_first_non_empty([f.options.default, "None"]) }}
Scott Bakerd1702d72017-11-17 12:12:00 -0800248 {% if f.link -%}{{ f.name }}_id = None{% endif %}
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -0500249 {% endfor %}
250 leaf_model_name = "{{ m.name }}"
Scott Baker5b7fba02018-10-17 08:46:46 -0700251
252 field_names = ["id", \
253 {% for f in xproto_base_fields(m, proto.message_table) + m.fields -%}
254 "{{ f.name }}",
255 {% endfor %}
256 ]
257
Sapan Bhatiabcbe8ce2017-11-14 13:02:30 -0500258{% endfor %}