1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include <gtest/gtest.h>
22 #include <HippoMocks/hippomocks.h>
24 #include <PrimitiveServerResource.h>
26 #include <OCPlatform.h>
29 using namespace std::placeholders;
31 using namespace testing;
33 using namespace OIC::Service;
36 typedef OCStackResult (*registerResourceSig)(OCResourceHandle&,
43 static constexpr char RESOURCE_URI[]{ "a/test" };
44 static constexpr char RESOURCE_TYPE[]{ "resourceType" };
45 static constexpr char KEY[]{ "key" };
47 TEST(ServerResourceBuilderCreateTest, ThrowIfUriIsInvalid)
49 ASSERT_THROW(PrimitiveServerResource::Builder("", "", "").create(), PlatformException);
52 class ServerResourceBuilderTest: public Test
60 mocks.OnCallFuncOverload(static_cast<registerResourceSig>(OCPlatform::registerResource))
65 TEST_F(ServerResourceBuilderTest, RegisterResourceWhenCallCreate)
67 mocks.ExpectCallFuncOverload(static_cast<registerResourceSig>(OCPlatform::registerResource))
69 PrimitiveServerResource::Builder(RESOURCE_URI, RESOURCE_TYPE, "").create();
72 TEST_F(ServerResourceBuilderTest, ResourceServerHasPropertiesSetByBuilder)
74 auto serverResource = PrimitiveServerResource::Builder(RESOURCE_URI, RESOURCE_TYPE, "").
75 setDiscoverable(false).setObservable(true).create();
77 EXPECT_FALSE(serverResource->isDiscoverable());
78 EXPECT_TRUE(serverResource->isObservable());
81 TEST_F(ServerResourceBuilderTest, ResourceServerHasAttrsSetByBuilder)
83 ResourceAttributes attrs;
86 auto serverResource = PrimitiveServerResource::Builder(RESOURCE_URI, RESOURCE_TYPE, "").
87 setAttributes(attrs).create();
89 PrimitiveServerResource::LockGuard lock{ serverResource };
90 EXPECT_EQ(attrs, serverResource->getAttributes());
94 class ServerResourceTest: public Test
98 PrimitiveServerResource::Ptr server;
101 void SetUp() override
104 server = PrimitiveServerResource::Builder(RESOURCE_URI, RESOURCE_TYPE, "").create();
107 virtual void initMocks()
109 mocks.OnCallFuncOverload(static_cast< registerResourceSig >(OCPlatform::registerResource)).
112 mocks.OnCallFunc(OCPlatform::unregisterResource).Return(OC_STACK_OK);
116 TEST_F(ServerResourceTest, AccessAttributesWithLock)
118 constexpr int value{ 100 };
121 PrimitiveServerResource::LockGuard lock{ server };
122 auto& attr = server->getAttributes();
126 ASSERT_EQ(value, server->getAttribute<int>(KEY));
129 TEST_F(ServerResourceTest, ThrowIfTryToAccessAttributesWithoutLock)
131 ASSERT_THROW(server->getAttributes(), NoLockException);
134 TEST_F(ServerResourceTest, ThrowIfLockRecursively)
136 PrimitiveServerResource::LockGuard lock{ server };
138 ASSERT_THROW(PrimitiveServerResource::LockGuard again{ server }, DeadLockException);
141 TEST_F(ServerResourceTest, AccessingAttributesWithMethodsWithinLockDoesntCauseDeadLock)
143 constexpr int value{ 100 };
146 PrimitiveServerResource::LockGuard lock{ server };
147 server->setAttribute(KEY, value);
150 ASSERT_EQ(value, server->getAttribute<int>(KEY));
155 class ServerResourceHandlingRequestTest: public ServerResourceTest
158 EntityHandler handler;
160 static constexpr OCRequestHandle fakeRequestHandle =
161 reinterpret_cast<OCRequestHandle>(0x1234);
162 static constexpr OCResourceHandle fakeResourceHandle =
163 reinterpret_cast<OCResourceHandle>(0x4321);
166 OCResourceRequest::Ptr createRequest(OCMethod method = OC_REST_GET)
168 auto request = make_shared<OCResourceRequest>();
170 OCEntityHandlerRequest ocEntityHandlerRequest { 0 };
171 OC::MessageContainer mc;
172 OCRepresentation ocRep;
174 mc.addRepresentation(ocRep);
176 string json = mc.getJSONRepresentation(OCInfoFormat::ExcludeOC);
178 ocEntityHandlerRequest.requestHandle = fakeRequestHandle;
179 ocEntityHandlerRequest.resource = fakeResourceHandle;
180 ocEntityHandlerRequest.method = method;
181 ocEntityHandlerRequest.reqJSONPayload = &json[0];
183 formResourceRequest(OC_REQUEST_FLAG, &ocEntityHandlerRequest, request);
189 OCStackResult registerResourceFake(OCResourceHandle&, string&, const string&,
190 const string&, EntityHandler handler, uint8_t)
192 this->handler = handler;
196 void initMocks() override
198 mocks.OnCallFuncOverload(
199 static_cast<registerResourceSig>(OCPlatform::registerResource)).Do(
200 bind(&ServerResourceHandlingRequestTest::registerResourceFake,
201 this, _1, _2, _3, _4, _5, _6));
203 mocks.OnCallFunc(OCPlatform::unregisterResource).Return(OC_STACK_OK);
207 TEST_F(ServerResourceHandlingRequestTest, CallSendResponseWhenReceiveRequest)
209 mocks.ExpectCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
211 ASSERT_EQ(OC_EH_OK, handler(createRequest()));
214 TEST_F(ServerResourceHandlingRequestTest, ReturnErrorCodeWhenSendResponseFailed)
216 mocks.ExpectCallFunc(OCPlatform::sendResponse).Return(OC_STACK_ERROR);
218 ASSERT_EQ(OC_EH_ERROR, handler(createRequest()));
221 TEST_F(ServerResourceHandlingRequestTest, SendResponseWithSameHandlesPassedByRequest)
223 mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
224 [](const shared_ptr<OCResourceResponse> response)
226 return response->getRequestHandle() == fakeRequestHandle &&
227 response->getResourceHandle() == fakeResourceHandle;
229 ).Return(OC_STACK_OK);
231 ASSERT_EQ(OC_EH_OK, handler(createRequest()));
234 TEST_F(ServerResourceHandlingRequestTest, SendResponseWithPrimitiveResponseResults)
236 constexpr int errorCode{ 1999 };
237 constexpr OCEntityHandlerResult result{ OC_EH_SLOW };
239 server->setGetRequestHandler(
240 [](const PrimitiveRequest&, ResourceAttributes&) -> PrimitiveGetResponse
242 return PrimitiveGetResponse::create(result, errorCode);
246 mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
247 [](const shared_ptr<OCResourceResponse> response)
249 return response->getErrorCode() == errorCode &&
250 response->getResponseResult() == result;
252 ).Return(OC_STACK_OK);
254 ASSERT_EQ(OC_EH_OK, handler(createRequest()));
257 TEST_F(ServerResourceHandlingRequestTest, SendSetResponseWithCustomAttrsAndResults)
259 constexpr int errorCode{ 1999 };
260 constexpr OCEntityHandlerResult result{ OC_EH_SLOW };
261 constexpr char value[]{ "value" };
263 server->setSetRequestHandler(
264 [](const PrimitiveRequest&, ResourceAttributes&) -> PrimitiveSetResponse
266 ResourceAttributes attrs;
268 return PrimitiveSetResponse::create(attrs, result, errorCode);
272 mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
273 [](const shared_ptr<OCResourceResponse> response)
275 return value == response->getResourceRepresentation()[KEY].getValue<std::string>()
276 && response->getErrorCode() == errorCode
277 && response->getResponseResult() == result;
279 ).Return(OC_STACK_OK);
281 ASSERT_EQ(OC_EH_OK, handler(createRequest(OC_REST_PUT)));
286 class ServerResourceSynchronizationTest: public ServerResourceHandlingRequestTest
290 static void withLock(PrimitiveServerResource::Ptr serverResource, int count)
292 for (int i=0; i<count; ++i)
294 PrimitiveServerResource::LockGuard lock{ serverResource };
296 auto& attrs = serverResource->getAttributes();
298 attrs[KEY] = attrs[KEY].get<int>() + 1;
302 static void withSetter(PrimitiveServerResource::Ptr serverResource, int count)
304 for (int i=0; i<count; ++i)
306 PrimitiveServerResource::LockGuard lock{ serverResource };
308 serverResource->setAttribute(KEY, serverResource->getAttribute<int>(KEY) + 1);
313 TEST_F(ServerResourceSynchronizationTest, MultipleAccessToServerResource)
316 vector<thread> threads;
318 server->setAttribute(KEY, 0);
320 for (int i = 20; i >= 0; --i) {
321 int count = 5000 + i * 100;
322 threads.push_back(thread { withLock, server, count });
326 for (int i = 20; i >= 0; --i) {
327 int count = 5000 + i * 100;
328 threads.push_back(thread { withSetter, server, count });
332 for (auto& t : threads)
337 ASSERT_EQ(expected, server->getAttribute<int>(KEY));
340 TEST_F(ServerResourceSynchronizationTest, MultipleAccessToServerResourceWithRequests)
343 vector<thread> threads;
345 mocks.OnCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
347 server->setAttribute(KEY, 0);
349 for (int i = 20; i >= 0; --i) {
350 int count = 5000 + i * 100;
351 threads.push_back(thread{ withLock, server, count });
355 for (int i = 20; i >= 0; --i) {
356 int count = 5000 + i * 100;
357 threads.push_back(thread{ withSetter, server, count });
361 threads.push_back(thread{
364 for (int i=0; i<10000; ++i)
366 if (i % 5 == 0) handler(createRequest(OC_REST_OBSERVE));
367 handler(createRequest((i & 1) ? OC_REST_GET : OC_REST_PUT));
372 for (auto& t : threads)
377 ASSERT_EQ(expected, server->getAttribute<int>(KEY));