Merge branch 'master' into simulator
[platform/upstream/iotivity.git] / service / resource-encapsulation / unittests / ResourceClientTest.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "UnitTestHelper.h"
22
23 #include "RCSRemoteResourceObject.h"
24 #include "RCSDiscoveryManager.h"
25 #include "RCSResourceObject.h"
26 #include "RCSAddress.h"
27
28 #include <condition_variable>
29 #include <mutex>
30
31 using namespace OIC::Service;
32 using namespace OC;
33
34 constexpr char RESOURCEURI[]{ "/a/TemperatureSensor" };
35 constexpr char RESOURCETYPE[]{ "resource.type" };
36 constexpr char RESOURCEINTERFACE[]{ "oic.if.baseline" };
37
38 constexpr char ATTR_KEY[]{ "Temperature" };
39 constexpr int ATTR_VALUE{ 0 };
40
41 constexpr int DEFAULT_WAITING_TIME_IN_MILLIS = 3000;
42
43 void getRemoteAttributesCallback(const RCSResourceAttributes&, int) {}
44 void setRemoteAttributesCallback(const RCSResourceAttributes&, int) {}
45 void resourceStateChanged(ResourceState) { }
46 void cacheUpdatedCallback(const RCSResourceAttributes&) {}
47
48 class RemoteResourceObjectTest: public TestWithMock
49 {
50 public:
51     RCSResourceObject::Ptr server;
52     RCSRemoteResourceObject::Ptr object;
53
54 public:
55     void Proceed()
56     {
57         cond.notify_all();
58     }
59
60     void Wait(int waitingTime = DEFAULT_WAITING_TIME_IN_MILLIS)
61     {
62         std::unique_lock< std::mutex > lock{ mutex };
63         cond.wait_for(lock, std::chrono::milliseconds{ waitingTime });
64     }
65
66 protected:
67     void SetUp()
68     {
69         TestWithMock::SetUp();
70
71         CreateResource();
72
73         WaitUntilDiscovered();
74
75         ASSERT_NE(object, nullptr);
76     }
77
78     void TearDown()
79     {
80         TestWithMock::TearDown();
81
82         // This method is to make sure objects disposed.
83         WaitForPtrBeingUnique();
84     }
85
86 private:
87     void CreateResource()
88     {
89         server = RCSResourceObject::Builder(RESOURCEURI, RESOURCETYPE, RESOURCEINTERFACE).build();
90         server->setAttribute(ATTR_KEY, ATTR_VALUE);
91     }
92
93     void WaitUntilDiscovered()
94     {
95         for (int i=0; i<10 && !object; ++i)
96         {
97             const std::string uri  = "/oic/res";
98             auto discoveryTask = RCSDiscoveryManager::getInstance()->discoverResourceByType(
99                     RCSAddress::multicast(), uri, RESOURCETYPE,
100                     std::bind(&RemoteResourceObjectTest::resourceDiscovered, this,
101                             std::placeholders::_1));
102             Wait(1000);
103         }
104     }
105
106     void WaitForPtrBeingUnique()
107     {
108         while((object && !object.unique()) || (server && !server.unique()))
109         {
110             std::this_thread::sleep_for(std::chrono::milliseconds{ 100 });
111         }
112     }
113
114     void resourceDiscovered(RCSRemoteResourceObject::Ptr resourceObject)
115     {
116         object = resourceObject;
117
118         Proceed();
119     }
120
121 private:
122     std::condition_variable cond;
123     std::mutex mutex;
124 };
125
126 TEST_F(RemoteResourceObjectTest, GetRemoteAttributesDoesNotAllowEmptyFunction)
127 {
128     ASSERT_THROW(object->getRemoteAttributes({ }), RCSInvalidParameterException);
129 }
130
131 TEST_F(RemoteResourceObjectTest, GetRemoteAttributesGetsAttributesOfServer)
132 {
133     mocks.ExpectCallFunc(getRemoteAttributesCallback).Match(
134             [this](const RCSResourceAttributes& attrs, int)
135             {
136                 RCSResourceObject::LockGuard lock{ server };
137                 return attrs == server->getAttributes();
138             }
139     ).Do([this](const RCSResourceAttributes&, int){ Proceed(); });
140
141     object->getRemoteAttributes(getRemoteAttributesCallback);
142
143     Wait();
144 }
145
146 TEST_F(RemoteResourceObjectTest, SetRemoteAttributesDoesNotAllowEmptyFunction)
147 {
148     ASSERT_THROW(object->setRemoteAttributes({ }, { }), RCSInvalidParameterException);
149 }
150
151 TEST_F(RemoteResourceObjectTest, SetRemoteAttributesSetsAttributesOfServer)
152 {
153     constexpr int newValue = ATTR_VALUE + 1;
154     RCSResourceAttributes newAttrs;
155     newAttrs[ATTR_KEY] = newValue;
156
157     mocks.ExpectCallFunc(setRemoteAttributesCallback).
158             Do([this](const RCSResourceAttributes&, int){ Proceed(); });
159
160     object->setRemoteAttributes(newAttrs, setRemoteAttributesCallback);
161     Wait();
162
163     ASSERT_EQ(newValue, server->getAttributeValue(ATTR_KEY));
164 }
165
166 TEST_F(RemoteResourceObjectTest, MonitoringIsNotStartedByDefault)
167 {
168     ASSERT_FALSE(object->isMonitoring());
169 }
170
171 TEST_F(RemoteResourceObjectTest, StartMonitoringThrowsIfFunctionIsEmpty)
172 {
173     ASSERT_THROW(object->startMonitoring({ }), RCSInvalidParameterException);
174 }
175
176 TEST_F(RemoteResourceObjectTest, IsMonitoringReturnsTrueAfterStartMonitoring)
177 {
178     object->startMonitoring(resourceStateChanged);
179
180     ASSERT_TRUE(object->isMonitoring());
181 }
182
183 TEST_F(RemoteResourceObjectTest, StartMonitoringThrowsIfTryingToStartAgain)
184 {
185     object->startMonitoring(resourceStateChanged);
186
187     ASSERT_THROW(object->startMonitoring(resourceStateChanged), RCSBadRequestException);
188 }
189
190 TEST_F(RemoteResourceObjectTest, DefaultStateIsNone)
191 {
192     ASSERT_EQ(ResourceState::NONE, object->getState());
193 }
194
195 TEST_F(RemoteResourceObjectTest, CachingIsNotStartedByDefault)
196 {
197     ASSERT_FALSE(object->isCaching());
198 }
199
200 TEST_F(RemoteResourceObjectTest, IsCachingReturnsTrueAfterStartCaching)
201 {
202     object->startCaching(cacheUpdatedCallback);
203
204     ASSERT_TRUE(object->isCaching());
205 }
206
207 TEST_F(RemoteResourceObjectTest, StartCachingThrowsIfTryingToStartAgain)
208 {
209     object->startCaching(cacheUpdatedCallback);
210
211     ASSERT_THROW(object->startCaching(), RCSBadRequestException);
212 }
213
214 TEST_F(RemoteResourceObjectTest, DefaultCacheStateIsNone)
215 {
216     ASSERT_EQ(CacheState::NONE, object->getCacheState());
217 }
218
219 TEST_F(RemoteResourceObjectTest, CacheStateIsUnreadyAfterStartCaching)
220 {
221     object->startCaching();
222
223     ASSERT_EQ(CacheState::UNREADY, object->getCacheState());
224 }
225
226 TEST_F(RemoteResourceObjectTest, CacheStateIsReadyAfterCacheUpdated)
227 {
228     mocks.ExpectCallFunc(cacheUpdatedCallback).
229                 Do([this](const RCSResourceAttributes&){ Proceed(); });
230
231     object->startCaching(cacheUpdatedCallback);
232     Wait();
233
234     ASSERT_EQ(CacheState::READY, object->getCacheState());
235 }
236
237 TEST_F(RemoteResourceObjectTest, IsCachedAvailableReturnsTrueWhenCacheIsReady)
238 {
239     mocks.ExpectCallFunc(cacheUpdatedCallback).
240                 Do([this](const RCSResourceAttributes&){ Proceed(); });
241
242     object->startCaching(cacheUpdatedCallback);
243     Wait();
244
245     ASSERT_TRUE(object->isCachedAvailable());
246 }
247
248 TEST_F(RemoteResourceObjectTest, DISABLED_CacheUpdatedCallbackBeCalledWheneverCacheUpdated)
249 {
250     mocks.OnCallFunc(cacheUpdatedCallback).
251             Do([this](const RCSResourceAttributes&){ Proceed(); });
252     object->startCaching(cacheUpdatedCallback);
253     Wait();
254
255     mocks.ExpectCallFunc(cacheUpdatedCallback).
256             Do([this](const RCSResourceAttributes&){ Proceed(); });
257
258     server->setAttribute(ATTR_KEY, ATTR_VALUE + 1);
259
260     Wait();
261 }
262
263 TEST_F(RemoteResourceObjectTest, DISABLED_CacheUpdatedCallbackBeCalledWithUpdatedAttributes)
264 {
265     constexpr int newValue = ATTR_VALUE + 1;
266
267     mocks.OnCallFunc(cacheUpdatedCallback).
268             Do([this](const RCSResourceAttributes&){ Proceed(); });
269     object->startCaching(cacheUpdatedCallback);
270     Wait();
271
272     mocks.ExpectCallFunc(cacheUpdatedCallback).
273             Match([this](const RCSResourceAttributes& attrs){
274                 return attrs.at(ATTR_KEY) == newValue;
275             }).
276             Do([this](const RCSResourceAttributes&){ Proceed(); });
277
278     server->setAttribute(ATTR_KEY, newValue);
279
280     Wait();
281 }
282
283 TEST_F(RemoteResourceObjectTest, GetCachedAttributesThrowsIfCachingIsNotStarted)
284 {
285     ASSERT_THROW(object->getCachedAttributes(), RCSBadRequestException);
286 }
287
288 TEST_F(RemoteResourceObjectTest, CachedAttributesHasSameAttributesWithServer)
289 {
290     mocks.OnCallFunc(cacheUpdatedCallback).
291             Do([this](const RCSResourceAttributes&){ Proceed(); });
292     object->startCaching(cacheUpdatedCallback);
293     Wait();
294
295     RCSResourceObject::LockGuard lock{ server };
296
297     ASSERT_EQ(object->getCachedAttributes(), server->getAttributes());
298 }
299
300 TEST_F(RemoteResourceObjectTest, GetCachedAttributeThrowsIfCachingIsNotStarted)
301 {
302     ASSERT_THROW(object->getCachedAttribute(ATTR_KEY), RCSBadRequestException);
303 }
304
305 TEST_F(RemoteResourceObjectTest, GetCachedAttributeThrowsIfKeyIsInvalid)
306 {
307     mocks.OnCallFunc(cacheUpdatedCallback).
308             Do([this](const RCSResourceAttributes&){ Proceed(); });
309     object->startCaching(cacheUpdatedCallback);
310     Wait();
311
312     ASSERT_THROW(object->getCachedAttribute(""), RCSInvalidKeyException);
313 }
314
315 TEST_F(RemoteResourceObjectTest, HasSameUriWithServer)
316 {
317     EXPECT_EQ(RESOURCEURI, object->getUri());
318 }
319
320 TEST_F(RemoteResourceObjectTest, HasSameTypeWithServer)
321 {
322     EXPECT_EQ(RESOURCETYPE, object->getTypes()[0]);
323 }
324
325 TEST_F(RemoteResourceObjectTest, HasSameInterfaceWithServer)
326 {
327     EXPECT_EQ(RESOURCEINTERFACE, object->getInterfaces()[0]);
328 }
329