58f3515985add6fc8d2d54d8e2dca98bb57d275c
[profile/ivi/automotive-message-broker.git] / plugins / testplugin / testplugin.cpp
1 /*
2         Copyright (C) 2012  Intel Corporation
3
4         This library is free software; you can redistribute it and/or
5         modify it under the terms of the GNU Lesser General Public
6         License as published by the Free Software Foundation; either
7         version 2.1 of the License, or (at your option) any later version.
8
9         This library is distributed in the hope that it will be useful,
10         but WITHOUT ANY WARRANTY; without even the implied warranty of
11         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12         Lesser General Public License for more details.
13
14         You should have received a copy of the GNU Lesser General Public
15         License along with this library; if not, write to the Free Software
16         Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19
20 #include <iostream>
21 #include <boost/assert.hpp>
22 #include <boost/lexical_cast.hpp>
23 #include <glib.h>
24 #include <sstream>
25 //#include <json-glib/json-glib.h>
26 #include <listplusplus.h>
27 #include <vehicleproperty.h>
28 #include <abstractpropertytype.h>
29 #include "debugout.h"
30 #include "timestamp.h"
31 #include "testplugin.h"
32 #define __SMALLFILE__ std::string(__FILE__).substr(std::string(__FILE__).rfind("/")+1)
33 AbstractRoutingEngine *m_re;
34
35 #define TEST(success)   g_assert((success));
36 const std::string TestProptertyName1 = "TestPropertyName1";
37 const std::string TestProptertyName2 = "TestPropertyName2";
38
39 //std::list<ObdPid*> Obd2Amb::supportedPidsList;
40
41 void testBooleanToStringFromString()
42 {
43         BasicPropertyType<bool> boolean(true);
44         std::string isTrue = boolean.toString();
45         boolean.fromString(boolean.toString());
46         std::string isTrue2 = boolean.toString();
47
48         g_assert(isTrue == isTrue2);
49 }
50
51 bool beginsWith(std::string a, std::string b)
52 {
53         return (a.compare(0, b.length(), b) == 0);
54 }
55
56 /**
57  * Tests Core's methods:
58  * * setSupported
59  * * supported
60  * * sourcesForProperty
61  * * getPropertyInfo
62  */
63
64 bool TestPlugin::testCoreSetSupported()
65 {
66         PropertyList supported(routingEngine->supported());
67         TEST(contains(supported, TestProptertyName1) == false);
68
69         //
70         // CALL setSupported
71         //
72
73         // valid call
74         routingEngine->updateSupported(m_supportedProperties, PropertyList(), this);
75
76         TEST(routingEngine->getPropertyInfo(TestProptertyName1, uuid()).isValid() == true);
77         Zone::ZoneList zones(routingEngine->getPropertyInfo(TestProptertyName1, uuid()).zones());
78         TEST(contains(zones, Zone::LeftSide) == true);
79
80         supported = routingEngine->supported();
81         TEST(contains(supported, TestProptertyName1) == true);
82         TEST(contains(supported, TestProptertyName2) == true);
83         TEST(contains(supported, VehicleProperty::ClutchStatus) == false);
84
85         std::vector<std::string> sources = routingEngine->sourcesForProperty(TestProptertyName1);
86         TEST(contains(sources,uuid()) == true);
87
88         TEST(routingEngine->getPropertyInfo(TestProptertyName2, uuid()).isValid() == true);
89         zones = routingEngine->getPropertyInfo(TestProptertyName2, uuid()).zones();
90         TEST(contains(zones, Zone::FrontSide) == true);
91
92         return true;
93 }
94
95 /**
96  * Tests Core's methods:
97  * * unregisterSink
98  * * registerSink
99  * * sourcesForProperty
100  * * subscribeToProperty - 2 versions
101  * * unsubscribeToProperty
102  */
103
104 bool TestPlugin::testSubscription()
105 {
106         int oldSubscriptionsToSupportedCounter = subscriptionsToSupportedCounter;
107         int oldSubscriptionsToUnsupportedCounter = subscriptionsToUnsupportedCounter;
108         int oldUnsubscriptionsToSupportedCounter= unsubscriptionsToSupportedCounter;
109         int oldUnsubscriptionsToUnsupportedCounter = unsubscriptionsToUnsupportedCounter;
110
111         // ! subscription works without having sink registered ! so there is no need to test
112         // routingEngine->registerSink(this) and routingEngine->unregisterSink(this)
113         routingEngine->unregisterSink(this);
114         routingEngine->registerSink(this);
115
116         // VehicleProperty::ClutchStatus doesn't exist
117         TEST(routingEngine->subscribeToProperty(VehicleProperty::ClutchStatus, uuid(), this) == false);
118         TEST(oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
119         TEST(oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
120
121         // TestProptertyName1 exists in our testplugin
122         TEST(routingEngine->subscribeToProperty(TestProptertyName1, uuid(), this) == true);
123         TEST(++oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
124         TEST(oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
125
126         TEST(routingEngine->subscribeToProperty(TestProptertyName1, "", this) == false);
127         TEST(oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
128         TEST(oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
129
130         // "other" source means no subscription callback in our plugin
131         TEST(routingEngine->subscribeToProperty(TestProptertyName1, "other", this) == false);
132         TEST(oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
133         TEST(oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
134
135         // we have subscribed TestProptertyName1 and not subscribed TestProptertyName2
136         int oldSupportedPropertyChanges = supportedPropertyChanges;
137         int oldPropertyChanges = propertyChanges;
138
139         AbstractPropertyType* value = new BasicPropertyType<int>(TestProptertyName1, 22);
140         value->priority = AbstractPropertyType::Instant;
141         routingEngine->updateProperty(value, "");
142         TEST(oldSupportedPropertyChanges == supportedPropertyChanges);
143         TEST(oldPropertyChanges == propertyChanges);
144         routingEngine->updateProperty(value, uuid());
145         TEST(++oldSupportedPropertyChanges == supportedPropertyChanges);
146         TEST(++oldPropertyChanges == propertyChanges);
147         delete value;
148
149         value = new BasicPropertyType<short>(TestProptertyName2, 255);
150         value->priority = AbstractPropertyType::Instant;
151         routingEngine->updateProperty(value, "");
152         TEST(oldSupportedPropertyChanges == supportedPropertyChanges);
153         TEST(oldPropertyChanges == propertyChanges);
154         routingEngine->updateProperty(value, uuid());
155         TEST(oldSupportedPropertyChanges == supportedPropertyChanges);
156         TEST(oldPropertyChanges == propertyChanges);
157         delete value;
158
159         value = new BasicPropertyType<bool>(VehicleProperty::ClutchStatus, true);
160         value->priority = AbstractPropertyType::Instant;
161         routingEngine->updateSupported({VehicleProperty::ClutchStatus},PropertyList(), this);
162
163         class TestSink : public AbstractSink
164         {
165         public:
166                 TestSink(AbstractRoutingEngine* engine, map<string, string> config) : AbstractSink(engine, config) {}
167                 virtual const string uuid() { return "other"; }
168                 virtual void propertyChanged(AbstractPropertyType *value){ ++propertyChanges; }
169                 virtual void supportedChanged(const PropertyList & supportedProperties){};
170
171                 int propertyChanges = 0;
172         };
173
174         //some other sink is subscribed, not this plug-in!
175         TestSink anotherSink(routingEngine, {});
176         TEST(routingEngine->subscribeToProperty(VehicleProperty::ClutchStatus, &anotherSink) == true);
177         TEST(oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
178         TEST(++oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
179         routingEngine->updateProperty(value, uuid());// uuid() != "other" no sink notified
180         TEST(anotherSink.propertyChanges == 1);// one update
181         TEST(oldSupportedPropertyChanges == supportedPropertyChanges);// no updates
182         TEST(oldPropertyChanges == propertyChanges);// no updates
183         TEST(routingEngine->unsubscribeToProperty(VehicleProperty::ClutchStatus, &anotherSink) == true);
184         routingEngine->updateSupported(PropertyList(),{VehicleProperty::ClutchStatus}, this);
185         TEST(oldUnsubscriptionsToSupportedCounter == unsubscriptionsToSupportedCounter);
186         TEST(++oldUnsubscriptionsToUnsupportedCounter == unsubscriptionsToUnsupportedCounter);
187
188
189         /// test lamba subscription:
190
191         TEST (routingEngine->subscribeToProperty(VehicleProperty::VehicleSpeed,[](AbstractPropertyType* value)
192         {
193                 DebugOut(0)<<"lamba subscriptions work!"<<endl;
194                 TEST(value);
195         }) > 0);
196
197         /// change vehiclespeed to trigger subscribe above
198
199         PropertyList s;
200         s.push_back(VehicleProperty::VehicleSpeed);
201
202         routingEngine->updateSupported(s, PropertyList(), this);
203         VehicleProperty::VehicleSpeedType speed(10);
204         speed.priority = AbstractPropertyType::Instant;
205
206         routingEngine->updateProperty(&speed,uuid());
207         routingEngine->updateSupported(PropertyList(), s, this);
208
209         delete value;
210
211         // unsubscription
212
213         // VehicleProperty::ClutchStatus doesn't exist
214         TEST(routingEngine->unsubscribeToProperty(VehicleProperty::ClutchStatus, this) == false);
215         TEST(oldUnsubscriptionsToSupportedCounter == unsubscriptionsToSupportedCounter);
216         TEST(oldUnsubscriptionsToUnsupportedCounter == unsubscriptionsToUnsupportedCounter);
217
218         // TestProptertyName1 exists in our testplugin
219         // subscribed 2x, lets try to unsubscribe 3x
220         // we should get only one unsubscription callback
221         TEST(routingEngine->unsubscribeToProperty(TestProptertyName1, this) == true);
222         TEST(routingEngine->unsubscribeToProperty(TestProptertyName1, this) == false);
223         TEST(routingEngine->unsubscribeToProperty(TestProptertyName1, this) == false);
224         TEST(++oldUnsubscriptionsToSupportedCounter == unsubscriptionsToSupportedCounter);
225         TEST(oldUnsubscriptionsToUnsupportedCounter == unsubscriptionsToUnsupportedCounter);
226
227         // TestProptertyName2 not subscribed
228         TEST(routingEngine->unsubscribeToProperty(TestProptertyName2, this) == false);;
229         TEST(oldUnsubscriptionsToSupportedCounter == unsubscriptionsToSupportedCounter);
230         TEST(oldUnsubscriptionsToUnsupportedCounter == unsubscriptionsToUnsupportedCounter);
231
232         return true;
233 }
234
235 bool TestPlugin::testSetAndGet()
236 {
237         bool replySuccess(false);
238         int replyError(-1);
239         std::string replySignalName("");
240
241         // Invalid request test
242         AsyncSetPropertyRequest requestInvalid;
243         requestInvalid.timeout = 0;
244         AsyncPropertyReply* reply = routingEngine->setProperty(requestInvalid);
245         TEST(reply == nullptr);
246
247         requestInvalid.property = "NotExists";
248         requestInvalid.completed = [&](AsyncPropertyReply* reply)
249         {
250                 replySuccess = reply->success;
251                 replyError = reply->error;
252                 delete reply;
253         };
254
255         reply = routingEngine->setProperty(requestInvalid);
256
257         TEST(replySuccess == false);
258         TEST(replyError == -1);
259
260         AsyncSetPropertyRequest request;
261         request.timeout = 0;
262         request.property = TestProptertyName1;
263         request.zoneFilter = Zone::LeftSide;
264         request.value = VehicleProperty::getPropertyTypeForPropertyNameValue(request.property, "1");
265         request.completed = requestInvalid.completed;
266
267         reply = routingEngine->setProperty(request);
268         delete request.value;
269         request.value = nullptr;
270
271         TEST(replySuccess == true);
272         TEST(replyError == AsyncPropertyReply::NoError);
273 }
274
275 bool TestPlugin::testCoreUpdateSupported()
276 {
277         bool success = false;
278
279         PropertyList toAdd;
280         toAdd.push_back(VehicleProperty::ClutchStatus);
281
282         routingEngine->updateSupported(toAdd,PropertyList(), this);
283
284         PropertyList supported = routingEngine->supported();
285
286         success = contains(supported,VehicleProperty::ClutchStatus);
287
288         PropertyList toRemove = toAdd;
289
290         routingEngine->updateSupported(PropertyList(),toRemove, this);
291
292         supported = routingEngine->supported();
293
294         success &= !contains(supported,VehicleProperty::ClutchStatus);
295
296         return success;
297 }
298
299 void TestPlugin::setConfiguration(map<string, string> config)
300 {
301         //      //Config has been passed, let's start stuff up.
302 }
303
304 TestPlugin::TestPlugin(AbstractRoutingEngine *re, map<string, string> config)
305         : AbstractSource(re, config),
306           m_supportedProperties({TestProptertyName1, TestProptertyName2}),
307           subscriptionsToSupportedCounter(0),
308           subscriptionsToUnsupportedCounter(0),
309           unsubscriptionsToSupportedCounter(0),
310           unsubscriptionsToUnsupportedCounter(0),
311           propertyChanges(0),
312           supportedPropertyChanges(0)
313 {
314
315         DebugOut(0) << "Capabilities: " << endl;
316
317         for(auto prop : VehicleProperty::capabilities())
318         {
319                 DebugOut(0) << prop << endl;
320         }
321
322         DebugOut() << "Testing Core::setSupported... " << endl;
323         testCoreSetSupported();
324
325         DebugOut() << "Testing MapPropertyType... " << endl;
326         MapPropertyType<BasicPropertyType<Zone::Type>,BasicPropertyType<Door::Status>> propmap("something");
327         MapPropertyType<BasicPropertyType<Zone::Type>,BasicPropertyType<Door::Status>> propmaptwo("something");
328         propmap.append(Zone::RearLeft,Door::Ajar);
329         GVariant *var = propmap.toVariant();
330         gsize dictsize = g_variant_n_children(var);
331         //DebugOut() << var << endl;
332         propmaptwo.fromVariant(var);
333
334         g_assert(propmaptwo.toString() == propmap.toString());
335
336         DebugOut() << "Testing ListPropertyType... " << endl;
337         VehicleProperty::TripMetersType* tfirst = new VehicleProperty::TripMetersType();
338         VehicleProperty::TripMetersType* tsecond = new VehicleProperty::TripMetersType();
339         BasicPropertyType<uint16_t> v1(0);
340         BasicPropertyType<uint16_t> v2(5);
341         BasicPropertyType<uint16_t> v3(10);
342         tfirst->append(v1);
343         tfirst->append(v2);
344         tfirst->append(v3);
345         tsecond->fromVariant(tfirst->toVariant());
346
347         GVariant* testGVSVariant = g_variant_new("i", 9);
348         TEST(GVS<int>::value(testGVSVariant) == 9);
349
350         TEST (tfirst->toString() == tsecond->toString());
351
352         testBooleanToStringFromString();
353
354         TEST (testCoreUpdateSupported());
355
356         testSubscription();
357
358         testSetAndGet();
359 }
360
361 TestPlugin::~TestPlugin()
362 {
363         DebugOut() << "TestPlugin Destructor called!!!"<<endl;
364 }
365
366 PropertyList TestPlugin::supported()
367 {
368         return m_supportedProperties;
369 }
370
371 int TestPlugin::supportedOperations()
372 {
373         return Get | Set;
374 }
375
376 extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, map<string, string> config)
377 {
378         return new TestPlugin(routingengine, config);
379
380 }
381 const string TestPlugin::uuid()
382 {
383         return "f77af740-f1f8-11e1-aff1-0800200c9a66";
384 }
385 void TestPlugin::subscribeToPropertyChanges(VehicleProperty::Property property)
386 {
387         if(contains(m_supportedProperties, property))
388                 ++subscriptionsToSupportedCounter;
389         else
390                 ++subscriptionsToUnsupportedCounter;
391 }
392
393
394 void TestPlugin::unsubscribeToPropertyChanges(VehicleProperty::Property property)
395 {
396         if(contains(m_supportedProperties, property))
397                 ++unsubscriptionsToSupportedCounter;
398         else
399                 ++unsubscriptionsToUnsupportedCounter;
400 }
401
402
403 void TestPlugin::getPropertyAsync(AsyncPropertyReply *reply)
404 {
405
406 }
407
408 AsyncPropertyReply *TestPlugin::setProperty(AsyncSetPropertyRequest request )
409 {
410         AsyncPropertyReply* reply = new AsyncPropertyReply (request);
411         reply->success = true;
412         reply->error = AsyncPropertyReply::NoError;
413         if(reply->completed)
414                 reply->completed(reply);
415         return reply;
416 }
417
418 PropertyInfo TestPlugin::getPropertyInfo(const VehicleProperty::Property &property)
419 {
420         if(!contains(m_supportedProperties, property))
421                 return PropertyInfo::invalid();
422
423         if(property == TestProptertyName1){
424                 return PropertyInfo(10, {Zone::LeftSide});
425         }
426         else if(property == TestProptertyName2){
427                 return PropertyInfo(30, {Zone::FrontSide});
428         }
429         else{
430                 return PropertyInfo(60, {Zone::None});
431         }
432 }
433
434 void TestPlugin::propertyChanged(AbstractPropertyType *value)
435 {
436         ++propertyChanges;
437         if(value && contains(m_supportedProperties, value->name))
438                 supportedPropertyChanges++;
439
440 }