[AMB] - updated version number. we are now 0.15 development
[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 #include <jsonhelper.h>
33
34 #define __SMALLFILE__ std::string(__FILE__).substr(std::string(__FILE__).rfind("/")+1)
35 AbstractRoutingEngine *m_re;
36
37 #define TEST(success)   DebugOut(0) << "Testing " << ""#success"" << endl; g_assert((success));
38 const std::string TestProptertyName1 = "TestPropertyName1";
39 const std::string TestProptertyName2 = "TestPropertyName2";
40
41 //std::list<ObdPid*> Obd2Amb::supportedPidsList;
42
43 void testBooleanToStringFromString()
44 {
45         BasicPropertyType<bool> boolean(true);
46         std::string isTrue = boolean.toString();
47         boolean.fromString(boolean.toString());
48         std::string isTrue2 = boolean.toString();
49
50         TEST(isTrue == isTrue2);
51 }
52
53 bool beginsWith(std::string a, std::string b)
54 {
55         return (a.compare(0, b.length(), b) == 0);
56 }
57
58 /**
59  * Tests Core's methods:
60  * * setSupported
61  * * supported
62  * * sourcesForProperty
63  * * getPropertyInfo
64  */
65
66 bool TestPlugin::testCoreSetSupported()
67 {
68         PropertyList supported(routingEngine->supported());
69         TEST(contains(supported, TestProptertyName1) == false);
70
71         //
72         // CALL setSupported
73         //
74
75         // valid call
76         routingEngine->updateSupported(m_supportedProperties, PropertyList(), this);
77
78         TEST(routingEngine->getPropertyInfo(TestProptertyName1, uuid()).isValid() == true);
79         Zone::ZoneList zones(routingEngine->getPropertyInfo(TestProptertyName1, uuid()).zones());
80         TEST(contains(zones, Zone::LeftSide) == true);
81
82         supported = routingEngine->supported();
83         TEST(contains(supported, TestProptertyName1) == true);
84         TEST(contains(supported, TestProptertyName2) == true);
85         TEST(contains(supported, VehicleProperty::ClutchStatus) == false);
86
87         std::vector<std::string> sources = routingEngine->sourcesForProperty(TestProptertyName1);
88         TEST(contains(sources,uuid()) == true);
89
90         TEST(routingEngine->getPropertyInfo(TestProptertyName2, uuid()).isValid() == true);
91         zones = routingEngine->getPropertyInfo(TestProptertyName2, uuid()).zones();
92         TEST(contains(zones, Zone::FrontSide) == true);
93
94         return true;
95 }
96
97 /**
98  * Tests Core's methods:
99  * * unregisterSink
100  * * registerSink
101  * * sourcesForProperty
102  * * subscribeToProperty - 2 versions
103  * * unsubscribeToProperty
104  */
105
106 bool TestPlugin::testSubscription()
107 {
108         int oldSubscriptionsToSupportedCounter = subscriptionsToSupportedCounter;
109         int oldSubscriptionsToUnsupportedCounter = subscriptionsToUnsupportedCounter;
110         int oldUnsubscriptionsToSupportedCounter= unsubscriptionsToSupportedCounter;
111         int oldUnsubscriptionsToUnsupportedCounter = unsubscriptionsToUnsupportedCounter;
112
113         // ! subscription works without having sink registered ! so there is no need to test
114         // routingEngine->registerSink(this) and routingEngine->unregisterSink(this)
115         routingEngine->unregisterSink(this);
116         routingEngine->registerSink(this);
117
118         // VehicleProperty::ClutchStatus doesn't exist
119         TEST(routingEngine->subscribeToProperty(VehicleProperty::ClutchStatus, uuid(), this) == false);
120         TEST(oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
121         TEST(oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
122
123         // TestProptertyName1 exists in our testplugin
124         TEST(routingEngine->subscribeToProperty(TestProptertyName1, uuid(), this) == true);
125         TEST(++oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
126         TEST(oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
127
128         TEST(routingEngine->subscribeToProperty(TestProptertyName1, "", this) == false);
129         TEST(oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
130         TEST(oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
131
132         // "other" source means no subscription callback in our plugin
133         TEST(routingEngine->subscribeToProperty(TestProptertyName1, "other", this) == false);
134         TEST(oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
135         TEST(oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
136
137         // we have subscribed TestProptertyName1 and not subscribed TestProptertyName2
138         int oldSupportedPropertyChanges = supportedPropertyChanges;
139         int oldPropertyChanges = propertyChanges;
140
141         AbstractPropertyType* value = new BasicPropertyType<int>(TestProptertyName1, 22);
142         value->priority = AbstractPropertyType::Instant;
143         routingEngine->updateProperty(value, "");
144         TEST(oldSupportedPropertyChanges == supportedPropertyChanges);
145         TEST(oldPropertyChanges == propertyChanges);
146         routingEngine->updateProperty(value, uuid());
147         TEST(++oldSupportedPropertyChanges == supportedPropertyChanges);
148         TEST(++oldPropertyChanges == propertyChanges);
149         delete value;
150
151         value = new BasicPropertyType<short>(TestProptertyName2, 255);
152         value->priority = AbstractPropertyType::Instant;
153         routingEngine->updateProperty(value, "");
154         TEST(oldSupportedPropertyChanges == supportedPropertyChanges);
155         TEST(oldPropertyChanges == propertyChanges);
156         routingEngine->updateProperty(value, uuid());
157         TEST(oldSupportedPropertyChanges == supportedPropertyChanges);
158         TEST(oldPropertyChanges == propertyChanges);
159         delete value;
160
161         value = new BasicPropertyType<bool>(VehicleProperty::ClutchStatus, true);
162         value->priority = AbstractPropertyType::Instant;
163         routingEngine->updateSupported({VehicleProperty::ClutchStatus},PropertyList(), this);
164
165         class TestSink : public AbstractSink
166         {
167         public:
168                 TestSink(AbstractRoutingEngine* engine, map<string, string> config) : AbstractSink(engine, config) {}
169                 virtual const string uuid() { return "other"; }
170                 virtual void propertyChanged(AbstractPropertyType *value){ ++propertyChanges; }
171                 virtual void supportedChanged(const PropertyList & supportedProperties){};
172
173                 int propertyChanges = 0;
174         };
175
176         //some other sink is subscribed, not this plug-in!
177         TestSink anotherSink(routingEngine, {});
178         TEST(routingEngine->subscribeToProperty(VehicleProperty::ClutchStatus, &anotherSink) == true);
179         TEST(oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
180         TEST(++oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
181         routingEngine->updateProperty(value, uuid());// uuid() != "other" no sink notified
182         TEST(anotherSink.propertyChanges == 1);// one update
183         TEST(oldSupportedPropertyChanges == supportedPropertyChanges);// no updates
184         TEST(oldPropertyChanges == propertyChanges);// no updates
185         TEST(routingEngine->unsubscribeToProperty(VehicleProperty::ClutchStatus, &anotherSink) == true);
186         routingEngine->updateSupported(PropertyList(),{VehicleProperty::ClutchStatus}, this);
187         TEST(oldUnsubscriptionsToSupportedCounter == unsubscriptionsToSupportedCounter);
188         TEST(++oldUnsubscriptionsToUnsupportedCounter == unsubscriptionsToUnsupportedCounter);
189
190
191         /// test lamba subscription:
192
193         TEST (routingEngine->subscribeToProperty(VehicleProperty::VehicleSpeed,[](AbstractPropertyType* value)
194         {
195                 DebugOut(0)<<"lamba subscriptions work!"<<endl;
196                 TEST(value);
197         }) > 0);
198
199         /// change vehiclespeed to trigger subscribe above
200
201         PropertyList s;
202         s.push_back(VehicleProperty::VehicleSpeed);
203
204         routingEngine->updateSupported(s, PropertyList(), this);
205         VehicleProperty::VehicleSpeedType speed(10);
206         speed.priority = AbstractPropertyType::Instant;
207
208         routingEngine->updateProperty(&speed,uuid());
209         routingEngine->updateSupported(PropertyList(), s, this);
210
211         delete value;
212
213         // unsubscription
214
215         // VehicleProperty::ClutchStatus doesn't exist
216         TEST(routingEngine->unsubscribeToProperty(VehicleProperty::ClutchStatus, this) == false);
217         TEST(oldUnsubscriptionsToSupportedCounter == unsubscriptionsToSupportedCounter);
218         TEST(oldUnsubscriptionsToUnsupportedCounter == unsubscriptionsToUnsupportedCounter);
219
220         // TestProptertyName1 exists in our testplugin
221         // subscribed 2x, lets try to unsubscribe 3x
222         // we should get only one unsubscription callback
223         TEST(routingEngine->unsubscribeToProperty(TestProptertyName1, this) == true);
224         TEST(routingEngine->unsubscribeToProperty(TestProptertyName1, this) == false);
225         TEST(routingEngine->unsubscribeToProperty(TestProptertyName1, this) == false);
226         TEST(++oldUnsubscriptionsToSupportedCounter == unsubscriptionsToSupportedCounter);
227         TEST(oldUnsubscriptionsToUnsupportedCounter == unsubscriptionsToUnsupportedCounter);
228
229         // TestProptertyName2 not subscribed
230         TEST(routingEngine->unsubscribeToProperty(TestProptertyName2, this) == false);;
231         TEST(oldUnsubscriptionsToSupportedCounter == unsubscriptionsToSupportedCounter);
232         TEST(oldUnsubscriptionsToUnsupportedCounter == unsubscriptionsToUnsupportedCounter);
233
234         return true;
235 }
236
237 bool testListPlusPlus()
238 {
239         std::map<std::string, int> theMap;
240         theMap["1"] = 1;
241         theMap["2"] = 2;
242
243         TEST(amb::containsKey(theMap, "1"));
244         TEST(!amb::containsKey(theMap, "bar"));
245
246         std::vector<int> list;
247         list.push_back(1);
248         list.push_back(2);
249         list.push_back(3);
250
251         TEST(contains(list, 2));
252         removeOne(&list, 2);
253         TEST(!contains(list, 2));
254
255         class Complex
256         {
257         public:
258                 Complex(int a, int b): foo(a), bar(b) {}
259                 int foo;
260                 int bar;
261         };
262
263         Complex complex1(1, 2);
264
265         Complex complex2(2, 2);
266
267         std::vector<Complex> complexList;
268         complexList.push_back(complex1);
269         complexList.push_back(complex2);
270
271         TEST(contains(complexList, complex1, [](auto a, auto b) { return a.foo == b.foo && a.bar == b.bar; }));
272
273         return true;
274 }
275
276 void testJsonHelper()
277 {
278
279 }
280
281 bool TestPlugin::testSetAndGet()
282 {
283         bool replySuccess(false);
284         int replyError(-1);
285         std::string replySignalName("");
286
287         // Invalid request test
288         AsyncSetPropertyRequest requestInvalid;
289         requestInvalid.timeout = 0;
290         AsyncPropertyReply* reply = routingEngine->setProperty(requestInvalid);
291         TEST(reply == nullptr);
292
293         requestInvalid.property = "NotExists";
294         requestInvalid.completed = [&](AsyncPropertyReply* reply)
295         {
296                 replySuccess = reply->success;
297                 replyError = reply->error;
298                 delete reply;
299         };
300
301         reply = routingEngine->setProperty(requestInvalid);
302
303         TEST(replySuccess == false);
304         TEST(replyError == -1);
305
306         AsyncSetPropertyRequest request;
307         request.timeout = 0;
308         request.property = TestProptertyName1;
309         request.zoneFilter = Zone::LeftSide;
310         request.value = VehicleProperty::getPropertyTypeForPropertyNameValue(request.property, "1");
311         request.completed = requestInvalid.completed;
312
313         reply = routingEngine->setProperty(request);
314         delete request.value;
315         request.value = nullptr;
316
317         TEST(replySuccess == true);
318         TEST(replyError == AsyncPropertyReply::NoError);
319 }
320
321 bool TestPlugin::testCoreUpdateSupported()
322 {
323         bool success = false;
324
325         PropertyList toAdd;
326         toAdd.push_back(VehicleProperty::ClutchStatus);
327
328         routingEngine->updateSupported(toAdd, PropertyList(), this);
329
330         PropertyList supported = routingEngine->supported();
331
332         success = contains(supported,VehicleProperty::ClutchStatus);
333
334         PropertyList toRemove = toAdd;
335
336         routingEngine->updateSupported(PropertyList(),toRemove, this);
337
338         supported = routingEngine->supported();
339
340         success &= !contains(supported,VehicleProperty::ClutchStatus);
341
342         return success;
343 }
344
345 void TestPlugin::setConfiguration(map<string, string> config)
346 {
347         //      //Config has been passed, let's start stuff up.
348 }
349
350 TestPlugin::TestPlugin(AbstractRoutingEngine *re, map<string, string> config)
351         : AbstractSource(re, config),
352           m_supportedProperties({TestProptertyName1, TestProptertyName2}),
353           subscriptionsToSupportedCounter(0),
354           subscriptionsToUnsupportedCounter(0),
355           unsubscriptionsToSupportedCounter(0),
356           unsubscriptionsToUnsupportedCounter(0),
357           propertyChanges(0),
358           supportedPropertyChanges(0)
359 {
360
361         DebugOut(0) << "Capabilities: " << endl;
362
363         for(auto prop : VehicleProperty::capabilities())
364         {
365                 DebugOut(0) << prop << endl;
366         }
367
368         DebugOut() << "Testing Core::setSupported... " << endl;
369         testCoreSetSupported();
370
371         DebugOut() << "Testing MapPropertyType... " << endl;
372         MapPropertyType<BasicPropertyType<Door::Status>> propmap("Something");
373         MapPropertyType<BasicPropertyType<Door::Status>> propmaptwo("SomethingElse");
374         propmap.append("hi", Door::Ajar);
375         GVariant *var = propmap.toVariant();
376         gsize dictsize = g_variant_n_children(var);
377         //DebugOut() << var << endl;
378         propmaptwo.fromVariant(var);
379
380         g_assert(propmaptwo.toString() == propmap.toString());
381
382         ///test fromString:
383         propmap.fromString(propmaptwo.toString());
384
385         DebugOut() << "Testing map string equivalency: " << propmaptwo.toString() << "==" << propmap.toString() << endl;
386
387         g_assert(propmaptwo.toString() == propmap.toString());
388
389         DebugOut() << "Testing ListPropertyType... " << endl;
390         VehicleProperty::TripMetersType* tfirst = new VehicleProperty::TripMetersType();
391         VehicleProperty::TripMetersType* tsecond = new VehicleProperty::TripMetersType();
392         tfirst->append(0);
393         tfirst->append(5);
394         tfirst->append(10);
395         tsecond->fromVariant(tfirst->toVariant());
396
397         GVariant* testGVSVariant = g_variant_new("i", 9);
398         TEST(GVS<int>::value(testGVSVariant) == 9);
399
400         TEST (tfirst->toString() == tsecond->toString());
401
402         testBooleanToStringFromString();
403
404         TEST (testCoreUpdateSupported());
405
406         testSubscription();
407
408         testSetAndGet();
409
410         TEST(testListPlusPlus());
411
412         testJsonHelper();
413 }
414
415 TestPlugin::~TestPlugin()
416 {
417         DebugOut() << "TestPlugin Destructor called!!!"<<endl;
418 }
419
420 PropertyList TestPlugin::supported()
421 {
422         return m_supportedProperties;
423 }
424
425 int TestPlugin::supportedOperations()
426 {
427         return Get | Set;
428 }
429
430 extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
431 {
432         new TestPlugin(routingengine, config);
433 }
434 const string TestPlugin::uuid()
435 {
436         return "f77af740-f1f8-11e1-aff1-0800200c9a66";
437 }
438 void TestPlugin::subscribeToPropertyChanges(VehicleProperty::Property property)
439 {
440         if(contains(m_supportedProperties, property))
441                 ++subscriptionsToSupportedCounter;
442         else
443                 ++subscriptionsToUnsupportedCounter;
444 }
445
446
447 void TestPlugin::unsubscribeToPropertyChanges(VehicleProperty::Property property)
448 {
449         if(contains(m_supportedProperties, property))
450                 ++unsubscriptionsToSupportedCounter;
451         else
452                 ++unsubscriptionsToUnsupportedCounter;
453 }
454
455
456 void TestPlugin::getPropertyAsync(AsyncPropertyReply *reply)
457 {
458
459 }
460
461 AsyncPropertyReply *TestPlugin::setProperty(AsyncSetPropertyRequest request )
462 {
463         AsyncPropertyReply* reply = new AsyncPropertyReply (request);
464         reply->success = true;
465         reply->error = AsyncPropertyReply::NoError;
466         if(reply->completed)
467                 reply->completed(reply);
468         return reply;
469 }
470
471 PropertyInfo TestPlugin::getPropertyInfo(const VehicleProperty::Property &property)
472 {
473         if(!contains(m_supportedProperties, property))
474                 return PropertyInfo::invalid();
475
476         if(property == TestProptertyName1){
477                 return PropertyInfo(10, {Zone::LeftSide});
478         }
479         else if(property == TestProptertyName2){
480                 return PropertyInfo(30, {Zone::FrontSide});
481         }
482         else{
483                 return PropertyInfo(60, {Zone::None});
484         }
485 }
486
487 void TestPlugin::propertyChanged(AbstractPropertyType *value)
488 {
489         ++propertyChanges;
490         if(value && contains(m_supportedProperties, value->name))
491                 supportedPropertyChanges++;
492
493 }