blob: 7e57f5e357cb69ab78de91c6e65578d205a08b4f [file] [log] [blame]
Matteo Scandolod2044a42017-08-07 16:08:28 -07001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070017""" fake_stub.py
18
19 Implements a simple fake grpc stub to use for unit testing.
20"""
21
22import functools
23
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070024ContentTypeMap = {}
25
26class FakeObj(object):
Scott Bakerff104cc2017-08-14 15:24:41 -070027 BASES=[]
28
Scott Baker03a163f2017-05-17 09:21:47 -070029 def __init__(self, fields=[], **kwargs):
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070030 super(FakeObj, self).__setattr__("is_set", {})
31 super(FakeObj, self).__setattr__("fields", [])
32
Scott Baker03a163f2017-05-17 09:21:47 -070033 for f in fields:
34 name = f["name"]
35 self.fields.append(name)
36 setattr(self, name, f["default"])
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070037
38 super(FakeObj, self).__setattr__("is_set", {})
39 for (k,v) in kwargs.items():
40 setattr(self, k, v)
41
42 def __repr__(self):
43 lines = []
44 for k in self.fields:
45 if self.is_set.get(k, False):
46 lines.append('%s: "%s"' % (k, getattr(self, k)))
47 if lines:
48 return "\n".join(lines) + "\n"
49 else:
50 return ""
51
52 def __setattr__(self, name, value):
53 self.is_set[name] = True
54 super(FakeObj, self).__setattr__(name, value)
55
Scott Baker500f8c72017-05-19 09:41:50 -070056 @property
57 def self_content_type_id(self):
58 return "xos.%s" % self.__class__.__name__.lower()
59
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070060class FakeExtensionManager(object):
61 def __init__(self, obj, extensions):
62 self.obj = obj
63 self.extensions = extensions
64
65 def _FindExtensionByName(self, name):
66 return name
67
68 def __getitem__(self, name, default=None):
69 if name in self.extensions:
70 return self.extensions[name]
71 return default
72
Scott Baker03a163f2017-05-17 09:21:47 -070073class FakeFieldOption(object):
74 def __init__(self, modelName=None):
75 self.modelName = modelName
76
77class FakeField(object):
78 def __init__(self, field):
79 extensions = {}
80
81 fk_model = field.get("fk_model", None)
82 if fk_model:
83 extensions["xos.foreignKey"] = FakeFieldOption(modelName=fk_model)
84
85 fk_reverse = field.get("fk_reverse", None)
86 if fk_reverse:
87 extensions["xos.reverseForeignKey"] = FakeFieldOption(modelName=fk_reverse)
88
89 self.Extensions = FakeExtensionManager(self, extensions)
90
91 def GetOptions(self):
92 return self
93
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070094class FakeDescriptor(object):
95 def __init__(self, objName):
96 global ContentTypeIdCounter
97 global ContentTypeMap
Scott Baker03a163f2017-05-17 09:21:47 -070098 self.objName = objName
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070099 if objName in ContentTypeMap:
100 ct = ContentTypeMap[objName]
101 else:
Scott Baker500f8c72017-05-19 09:41:50 -0700102 ct = "xos.%s" % objName.lower()
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700103 ContentTypeMap[objName] = ct
104 self.Extensions = FakeExtensionManager(self, {"xos.contentTypeId": ct})
105
106 def GetOptions(self):
107 return self
108
109 @property
110 def fields_by_name(self):
Scott Baker03a163f2017-05-17 09:21:47 -0700111 cls = globals()[self.objName]
112 fbn = {}
113 for field in cls.FIELDS:
114 fake_field = FakeField(field)
115 fbn[ field["name"] ] = fake_field
116
117 return fbn
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700118
Scott Bakerff104cc2017-08-14 15:24:41 -0700119class User(FakeObj):
120 FIELDS = ( {"name": "id", "default": 0},
121 {"name": "email", "default": ""},
122 {"name": "site_id", "default": 0, "fk_model": "Site"}, )
123
124 def __init__(self, **kwargs):
125 return super(User, self).__init__(self.FIELDS, **kwargs)
126
127 DESCRIPTOR = FakeDescriptor("User")
128
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700129class Slice(FakeObj):
Scott Baker03a163f2017-05-17 09:21:47 -0700130 FIELDS = ( {"name": "id", "default": 0},
131 {"name": "name", "default": ""},
Scott Bakerff104cc2017-08-14 15:24:41 -0700132 {"name": "site_id", "default": 0, "fk_model": "Site"},
133 {"name": "creator_id", "default": 0, "fk_model": "User"},
134 {"name": "leaf_model_name", "default": "Slice"} )
Scott Baker03a163f2017-05-17 09:21:47 -0700135
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700136 def __init__(self, **kwargs):
Scott Baker03a163f2017-05-17 09:21:47 -0700137 return super(Slice, self).__init__(self.FIELDS, **kwargs)
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700138
139 DESCRIPTOR = FakeDescriptor("Slice")
140
Scott Baker03a163f2017-05-17 09:21:47 -0700141class Site(FakeObj):
142 FIELDS = ( {"name": "id", "default": 0},
143 {"name": "name", "default": ""},
Scott Bakerff104cc2017-08-14 15:24:41 -0700144 {"name": "slice_ids", "default": 0, "fk_reverse": "Slice"},
145 {"name": "leaf_model_name", "default": "Site"})
Scott Baker03a163f2017-05-17 09:21:47 -0700146
147 def __init__(self, **kwargs):
148 return super(Site, self).__init__(self.FIELDS, **kwargs)
149
150 DESCRIPTOR = FakeDescriptor("Site")
151
Scott Baker500f8c72017-05-19 09:41:50 -0700152class Service(FakeObj):
153 FIELDS = ( {"name": "id", "default": 0},
Scott Bakerff104cc2017-08-14 15:24:41 -0700154 {"name": "name", "default": ""},
155 {"name": "leaf_model_name", "default": "Service"})
Scott Baker500f8c72017-05-19 09:41:50 -0700156
157 def __init__(self, **kwargs):
158 return super(Service, self).__init__(self.FIELDS, **kwargs)
159
160 DESCRIPTOR = FakeDescriptor("Service")
161
Scott Bakerff104cc2017-08-14 15:24:41 -0700162class ONOSService(FakeObj):
163 FIELDS = ( {"name": "id", "default": 0},
164 {"name": "name", "default": ""},
165 {"name": "leaf_model_name", "default": "ONOSService"})
166
167 BASES = ["Service"]
168
169 def __init__(self, **kwargs):
170 return super(ONOSService, self).__init__(self.FIELDS, **kwargs)
171
172 DESCRIPTOR = FakeDescriptor("ONOSService")
173
Scott Baker500f8c72017-05-19 09:41:50 -0700174class Tag(FakeObj):
175 FIELDS = ( {"name": "id", "default": 0},
176 {"name": "service_id", "default": None},
177 {"name": "name", "default": ""},
178 {"name": "value", "default": ""},
179 {"name": "content_type", "default": None},
180 {"name": "object_id", "default": None},
Scott Bakerff104cc2017-08-14 15:24:41 -0700181 {"name": "slice_ids", "default": 0, "fk_reverse": "Slice"},
182 {"name": "leaf_model_name", "default": "Tag"})
Scott Baker500f8c72017-05-19 09:41:50 -0700183
184 def __init__(self, **kwargs):
185 return super(Tag, self).__init__(self.FIELDS, **kwargs)
186
187 DESCRIPTOR = FakeDescriptor("Tag")
188
189class ID(FakeObj):
190 pass
191
192class FakeItemList(object):
193 def __init__(self, items):
194 self.items = items
195
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700196class FakeStub(object):
197 def __init__(self):
Scott Baker500f8c72017-05-19 09:41:50 -0700198 self.id_counter = 1
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700199 self.objs = {}
Scott Bakerff104cc2017-08-14 15:24:41 -0700200 for name in ["Slice", "Site", "Tag", "Service", "ONOSService", "User"]:
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700201 setattr(self, "Get%s" % name, functools.partial(self.get, name))
202 setattr(self, "List%s" % name, functools.partial(self.list, name))
203 setattr(self, "Create%s" % name, functools.partial(self.create, name))
204 setattr(self, "Delete%s" % name, functools.partial(self.delete, name))
205 setattr(self, "Update%s" % name, functools.partial(self.update, name))
206
207
208 def make_key(self, name, id):
209 return "%s:%d" % (name, id.id)
210
Scott Baker500f8c72017-05-19 09:41:50 -0700211 def get(self, classname, id, metadata=None):
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700212 obj = self.objs.get(self.make_key(classname, id), None)
213 return obj
214
Scott Baker500f8c72017-05-19 09:41:50 -0700215 def list(self, classname, empty, metadata=None):
216 items = []
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700217 for (k,v) in self.objs.items():
218 (this_classname, id) = k.split(":")
219 if this_classname == classname:
220 items.append(v)
Scott Baker500f8c72017-05-19 09:41:50 -0700221 return FakeItemList(items)
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700222
Scott Baker500f8c72017-05-19 09:41:50 -0700223 def create(self, classname, obj, metadata=None):
224 obj.id = self.id_counter
225 self.id_counter = self.id_counter + 1
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700226 k = self.make_key(classname, FakeObj(id=obj.id))
227 self.objs[k] = obj
Scott Bakerff104cc2017-08-14 15:24:41 -0700228
229 for base_classname in obj.BASES:
230 base_class = globals()[base_classname]
231 base_obj = base_class(id=obj.id, leaf_model_name = classname)
232 k = self.make_key(base_classname, base_obj)
233 self.objs[k] = base_obj
234
Scott Baker500f8c72017-05-19 09:41:50 -0700235 return obj
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700236
Scott Baker500f8c72017-05-19 09:41:50 -0700237 def update(self, classname, obj, metadata=None):
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700238 # TODO: partial update support?
239 k = self.make_key(classname, FakeObj(id=obj.id))
240 self.objs[k] = obj
Scott Baker500f8c72017-05-19 09:41:50 -0700241 return obj
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700242
Scott Baker500f8c72017-05-19 09:41:50 -0700243 def delete(self, classname, id, metadata=None):
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700244 k = self.make_key(classname, id)
245 del self.objs[k]
246
247class FakeSymDb(object):
248 def __init__(self):
249 self._classes = {}
Scott Bakerff104cc2017-08-14 15:24:41 -0700250 for name in ["Slice", "Site", "ID", "Tag", "Service", "ONOSService", "User"]:
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700251 self._classes["xos.%s" % name] = globals()[name]
252
253
254