Imported Upstream version 0.9.2
[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 #include "RCSRemoteResourceObject.h"
23 #include "RCSDiscoveryManager.h"
24 #include "RCSResourceObject.h"
25 #include "PrimitiveResource.h"
26 #include <condition_variable>
27
28 #include <mutex>
29
30 using namespace OIC::Service;
31 using namespace OC;
32
33 constexpr char RESOURCEURI[]{ "/a/TemperatureSensor" };
34 constexpr char RESOURCETYPE[]{ "Resource.Hosting" };
35 constexpr char RESOURCEINTERFACE[]{ "oic.if.baseline" };
36
37 constexpr char ATTR_KEY[]{ "Temperature" };
38 constexpr int ATTR_VALUE{ 0 };
39
40 constexpr int DEFAULT_WAITING_TIME_IN_MILLIS = 3000;
41
42 void getRemoteAttributesCallback(const RCSResourceAttributes&) {}
43 void setRemoteAttributesCallback(const RCSResourceAttributes&) {}
44 void resourceStateChanged(ResourceState) { }
45 void cacheUpdatedCallback(const RCSResourceAttributes&) {}
46
47 class RemoteResourceObjectTest: public TestWithMock
48 {
49 public:
50     RCSResourceObject::Ptr server;
51     RCSRemoteResourceObject::Ptr object;
52     std::shared_ptr< bool > finished;
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         finished = std::make_shared< bool >(false);
72
73         CreateResource();
74
75         WaitUntilDiscovered();
76     }
77
78     void TearDown()
79     {
80         TestWithMock::TearDown();
81
82         // This method is to make sure objects disposed.
83         WaitForPtrBeingUnique();
84
85         *finished = true;
86     }
87
88 private:
89     void CreateResource()
90     {
91         server = RCSResourceObject::Builder(RESOURCEURI, RESOURCETYPE, RESOURCEINTERFACE).build();
92         server->setAttribute(ATTR_KEY, ATTR_VALUE);
93     }
94
95     bool checkObject()
96     {
97         std::lock_guard<std::mutex> lock{ mutexForObject };
98         return object == nullptr;
99     }
100
101     void WaitUntilDiscovered()
102     {
103         while (checkObject())
104         {
105             RCSDiscoveryManager::getInstance()->discoverResource(RCSAddress::multicast(),
106                     "/oic/res?rt=Resource.Hosting", std::bind(resourceDiscovered, this, finished,
107                             std::placeholders::_1));
108
109             Wait(1000);
110         }
111     }
112
113     void WaitForPtrBeingUnique()
114     {
115         while((object && !object.unique()) || (server && !server.unique()))
116         {
117             std::this_thread::sleep_for(std::chrono::milliseconds{ 100 });
118         }
119     }
120
121     // This callback is to protect crash from crashes caused by delayed callbacks
122     static void resourceDiscovered(RemoteResourceObjectTest* test,
123             std::shared_ptr< bool > finished, RCSRemoteResourceObject::Ptr resourceObject)
124     {
125         if (*finished) return;
126
127         {
128             std::lock_guard< std::mutex > lock{ test->mutexForObject };
129
130             if (test->object) return;
131
132             test->object = resourceObject;
133         }
134
135         test->Proceed();
136     }
137
138 private:
139     std::condition_variable cond;
140     std::mutex mutex;
141     std::mutex mutexForObject;
142 };
143
144 TEST_F(RemoteResourceObjectTest, GetRemoteAttributesDoesNotAllowEmptyFunction)
145 {
146     ASSERT_THROW(object->getRemoteAttributes({ }), InvalidParameterException);
147 }
148
149 TEST_F(RemoteResourceObjectTest, GetRemoteAttributesGetsAttributesOfServer)
150 {
151     mocks.ExpectCallFunc(getRemoteAttributesCallback).Match(
152             [this](const RCSResourceAttributes& attrs)
153             {
154                 RCSResourceObject::LockGuard lock{ server };
155                 return attrs == server->getAttributes();
156             }
157     ).Do([this](const RCSResourceAttributes&){ Proceed(); });
158
159     object->getRemoteAttributes(getRemoteAttributesCallback);
160
161     Wait();
162 }
163
164 TEST_F(RemoteResourceObjectTest, SetRemoteAttributesDoesNotAllowEmptyFunction)
165 {
166     ASSERT_THROW(object->setRemoteAttributes({ }, { }), InvalidParameterException);
167 }
168
169 TEST_F(RemoteResourceObjectTest, SetRemoteAttributesSetsAttributesOfServer)
170 {
171     constexpr int newValue = ATTR_VALUE + 1;
172     RCSResourceAttributes newAttrs;
173     newAttrs[ATTR_KEY] = newValue;
174
175     mocks.ExpectCallFunc(setRemoteAttributesCallback).
176             Do([this](const RCSResourceAttributes&){ Proceed(); });
177
178     object->setRemoteAttributes(newAttrs, setRemoteAttributesCallback);
179     Wait();
180
181     ASSERT_EQ(newValue, server->getAttributeValue(ATTR_KEY));
182 }
183
184 TEST_F(RemoteResourceObjectTest, MonitoringIsNotStartedByDefault)
185 {
186     ASSERT_FALSE(object->isMonitoring());
187 }
188
189 TEST_F(RemoteResourceObjectTest, StartMonitoringThrowsIfFunctionIsEmpty)
190 {
191     ASSERT_THROW(object->startMonitoring({ }), InvalidParameterException);
192 }
193
194 TEST_F(RemoteResourceObjectTest, IsMonitoringReturnsTrueAfterStartMonitoring)
195 {
196     object->startMonitoring(resourceStateChanged);
197
198     ASSERT_TRUE(object->isMonitoring());
199 }
200
201 TEST_F(RemoteResourceObjectTest, StartMonitoringThrowsIfTryingToStartAgain)
202 {
203     object->startMonitoring(resourceStateChanged);
204
205     ASSERT_THROW(object->startMonitoring(resourceStateChanged), BadRequestException);
206 }
207
208 TEST_F(RemoteResourceObjectTest, DefaultStateIsNone)
209 {
210     ASSERT_EQ(ResourceState::NONE, object->getState());
211 }
212
213 TEST_F(RemoteResourceObjectTest, CachingIsNotStartedByDefault)
214 {
215     ASSERT_FALSE(object->isCaching());
216 }
217
218 TEST_F(RemoteResourceObjectTest, IsCachingReturnsTrueAfterStartCaching)
219 {
220     object->startCaching(cacheUpdatedCallback);
221
222     ASSERT_TRUE(object->isCaching());
223 }
224
225 TEST_F(RemoteResourceObjectTest, StartCachingThrowsIfTryingToStartAgain)
226 {
227     object->startCaching(cacheUpdatedCallback);
228
229     ASSERT_THROW(object->startCaching(), BadRequestException);
230 }
231
232 TEST_F(RemoteResourceObjectTest, DefaultCacheStateIsNone)
233 {
234     ASSERT_EQ(CacheState::NONE, object->getCacheState());
235 }
236
237 TEST_F(RemoteResourceObjectTest, CacheStateIsUnreadyAfterStartCaching)
238 {
239     object->startCaching();
240
241     ASSERT_EQ(CacheState::UNREADY, object->getCacheState());
242 }
243
244 TEST_F(RemoteResourceObjectTest, CacheStateIsReadyAfterCacheUpdated)
245 {
246     mocks.ExpectCallFunc(cacheUpdatedCallback).
247                 Do([this](const RCSResourceAttributes&){ Proceed(); });
248
249     object->startCaching(cacheUpdatedCallback);
250     Wait();
251
252     ASSERT_EQ(CacheState::READY, object->getCacheState());
253 }
254
255 TEST_F(RemoteResourceObjectTest, IsCachedAvailableReturnsTrueWhenCacheIsReady)
256 {
257     mocks.ExpectCallFunc(cacheUpdatedCallback).
258                 Do([this](const RCSResourceAttributes&){ Proceed(); });
259
260     object->startCaching(cacheUpdatedCallback);
261     Wait();
262
263     ASSERT_TRUE(object->isCachedAvailable());
264 }
265
266 TEST_F(RemoteResourceObjectTest, DISABLED_CacheUpdatedCallbackBeCalledWheneverCacheUpdated)
267 {
268     mocks.OnCallFunc(cacheUpdatedCallback).
269             Do([this](const RCSResourceAttributes&){ Proceed(); });
270     object->startCaching(cacheUpdatedCallback);
271     Wait();
272
273     mocks.ExpectCallFunc(cacheUpdatedCallback).
274             Do([this](const RCSResourceAttributes&){ Proceed(); });
275
276     server->setAttribute(ATTR_KEY, ATTR_VALUE + 1);
277
278     Wait();
279 }
280
281 TEST_F(RemoteResourceObjectTest, DISABLED_CacheUpdatedCallbackBeCalledWithUpdatedAttributes)
282 {
283     constexpr int newValue = ATTR_VALUE + 1;
284
285     mocks.OnCallFunc(cacheUpdatedCallback).
286             Do([this](const RCSResourceAttributes&){ Proceed(); });
287     object->startCaching(cacheUpdatedCallback);
288     Wait();
289
290     mocks.ExpectCallFunc(cacheUpdatedCallback).
291             Match([this](const RCSResourceAttributes& attrs){
292                 return attrs.at(ATTR_KEY) == newValue;
293             }).
294             Do([this](const RCSResourceAttributes&){ Proceed(); });
295
296     server->setAttribute(ATTR_KEY, newValue);
297
298     Wait();
299 }
300
301 TEST_F(RemoteResourceObjectTest, GetCachedAttributesThrowsIfCachingIsNotStarted)
302 {
303     ASSERT_THROW(object->getCachedAttributes(), BadRequestException);
304 }
305
306 TEST_F(RemoteResourceObjectTest, CachedAttributesHasSameAttributesWithServer)
307 {
308     mocks.OnCallFunc(cacheUpdatedCallback).
309             Do([this](const RCSResourceAttributes&){ Proceed(); });
310     object->startCaching(cacheUpdatedCallback);
311     Wait();
312
313     RCSResourceObject::LockGuard lock{ server };
314
315     ASSERT_EQ(object->getCachedAttributes(), server->getAttributes());
316 }
317
318 TEST_F(RemoteResourceObjectTest, GetCachedAttributeThrowsIfCachingIsNotStarted)
319 {
320     ASSERT_THROW(object->getCachedAttribute(ATTR_KEY), BadRequestException);
321 }
322
323 TEST_F(RemoteResourceObjectTest, GetCachedAttributeThrowsIfKeyIsInvalid)
324 {
325     mocks.OnCallFunc(cacheUpdatedCallback).
326             Do([this](const RCSResourceAttributes&){ Proceed(); });
327     object->startCaching(cacheUpdatedCallback);
328     Wait();
329
330     ASSERT_THROW(object->getCachedAttribute(""), InvalidKeyException);
331 }
332
333 TEST_F(RemoteResourceObjectTest, HasSameUriWithServer)
334 {
335     EXPECT_EQ(RESOURCEURI, object->getUri());
336 }
337
338 TEST_F(RemoteResourceObjectTest, HasSameTypeWithServer)
339 {
340     EXPECT_EQ(RESOURCETYPE, object->getTypes()[0]);
341 }
342
343 TEST_F(RemoteResourceObjectTest, HasSameInterfaceWithServer)
344 {
345     EXPECT_EQ(RESOURCEINTERFACE, object->getInterfaces()[0]);
346 }
347