lib_env = env.Clone()
SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', exports = 'lib_env')
+src_dir = lib_env.get('SRC_DIR')
+
server_builder_env = lib_env.Clone()
target_os = env.get('TARGET_OS')
'../common/primitiveResource/include/',
])
-server_builder_env.AppendUnique(CPPPATH = [env.get('SRC_DIR')+'/extlibs', 'include', 'src'])
+server_builder_env.AppendUnique(CPPPATH = [env.get('SRC_DIR')+'/extlibs', 'include'])
if target_os not in ['windows', 'winrt']:
server_builder_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall'])
# Source files and Targets
######################################################################
server_builder_src = env.Glob('src/*.cpp')
-server_builder_static = server_builder_env.StaticLibrary('ServerBuilder', server_builder_src)
-server_builder_shared = server_builder_env.SharedLibrary('ServerBuilder', server_builder_src)
+server_builder_static = server_builder_env.StaticLibrary('server_builder', server_builder_src)
+server_builder_shared = server_builder_env.SharedLibrary('server_builder', server_builder_src)
+
+server_builder_env.InstallTarget([server_builder_static,server_builder_shared], 'server_builder')
+
+######################################################################
+# Build Test
+######################################################################
+server_builder_test_env = server_builder_env.Clone();
+server_builder_test_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+
+server_builder_test_env.AppendUnique(CPPPATH = [env.get('SRC_DIR')+'/extlibs/hippomocks-master'])
+
+gtest = File(src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs/libgtest.a')
+gtest_main = File(src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs/libgtest_main.a')
+
+server_builder_test_env.PrependUnique(LIBS = [
+ gtest,
+ gtest_main,
+ 'server_builder',
+ 'service_common',
+ 'pthread',
+ 'oc',
+ 'octbstack',
+ 'oc_logger',
+ 'connectivity_abstraction',
+ 'coap',
+ ])
-server_builder_env.InstallTarget([server_builder_static,server_builder_shared], 'libServerBuilder')
+server_builder_test_src = env.Glob('unittests/*.cpp')
+server_builder_test = server_builder_test_env.Program('server_builder_test', server_builder_test_src)
+Alias("server_builder_test", server_builder_test)
+env.AppendTarget('server_builder_test')
--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <gtest/gtest.h>
+#include <HippoMocks/hippomocks.h>
+
+#include <PrimitiveServerResource.h>
+
+#include <OCPlatform.h>
+
+using namespace std;
+using namespace std::placeholders;
+
+using namespace testing;
+
+using namespace OIC::Service;
+using namespace OC;
+
+typedef OCStackResult (*registerResourceSig)(OCResourceHandle&,
+ string&,
+ const string&,
+ const string&,
+ EntityHandler,
+ uint8_t );
+
+static constexpr char KEY[] = "key";
+
+TEST(ServerResourceBuilderTest, ThrowIfUriIsInvalid)
+{
+ ASSERT_THROW(PrimitiveServerResource::Builder("", "", "").create(), PlatformException);
+}
+
+TEST(ServerResourceBuilderTest, RegisterResourceWhenCallCreate)
+{
+ MockRepository mocks;
+
+ mocks.ExpectCallFuncOverload(
+ static_cast<registerResourceSig>(OCPlatform::registerResource)).Return(OC_STACK_OK);
+
+ PrimitiveServerResource::Builder("a/test", "", "").create();
+}
+
+class ServerResourceTest: public Test
+{
+public:
+ MockRepository mocks;
+ PrimitiveServerResource::Ptr server;
+
+protected:
+ void SetUp() override
+ {
+ initMocks();
+ server = PrimitiveServerResource::Builder("a/test", "", "").create();
+ }
+
+ virtual void initMocks()
+ {
+ mocks.OnCallFuncOverload(static_cast< registerResourceSig >(OCPlatform::registerResource)).
+ Return(OC_STACK_OK);
+
+ mocks.OnCallFunc(OCPlatform::unregisterResource).Return(OC_STACK_OK);
+ }
+};
+
+TEST_F(ServerResourceTest, AccessAttributesWithLock)
+{
+ constexpr int value{ 100 };
+
+ {
+ PrimitiveServerResource::LockGuard lock{ server };
+ auto& attr = server->getAttributes();
+ attr[KEY] = value;
+ }
+
+ ASSERT_EQ(value, server->getAttribute<int>(KEY));
+}
+
+TEST_F(ServerResourceTest, ThrowIfTryToAccessAttributesWithoutLock)
+{
+ ASSERT_THROW(server->getAttributes(), NoLockException);
+}
+
+TEST_F(ServerResourceTest, ThrowIfLockRecursively)
+{
+ PrimitiveServerResource::LockGuard lock{ server };
+
+ ASSERT_THROW(PrimitiveServerResource::LockGuard again{ server }, DeadLockException);
+}
+
+TEST_F(ServerResourceTest, AccessingAttributesWithMethodsWithinLockDoesntCauseDeadLock)
+{
+ constexpr int value{ 100 };
+
+ {
+ PrimitiveServerResource::LockGuard lock{ server };
+ server->setAttribute(KEY, value);
+ }
+
+ ASSERT_EQ(value, server->getAttribute<int>(KEY));
+}
+
+
+
+class ServerResourceHandlingRequestTest: public ServerResourceTest
+{
+public:
+ EntityHandler handler;
+
+ static constexpr OCRequestHandle fakeRequestHandle =
+ reinterpret_cast<OCRequestHandle>(0x1234);
+ static constexpr OCResourceHandle fakeResourceHandle =
+ reinterpret_cast<OCResourceHandle>(0x4321);
+
+public:
+ OCResourceRequest::Ptr createRequest(OCMethod method = OC_REST_GET)
+ {
+ auto request = make_shared<OCResourceRequest>();
+
+ OCEntityHandlerRequest ocEntityHandlerRequest { 0 };
+ OC::MessageContainer mc;
+ OCRepresentation ocRep;
+
+ mc.addRepresentation(ocRep);
+
+ string json = mc.getJSONRepresentation(OCInfoFormat::ExcludeOC);
+
+ ocEntityHandlerRequest.requestHandle = fakeRequestHandle;
+ ocEntityHandlerRequest.resource = fakeResourceHandle;
+ ocEntityHandlerRequest.method = method;
+ ocEntityHandlerRequest.reqJSONPayload = &json[0];
+
+ formResourceRequest(OC_REQUEST_FLAG, &ocEntityHandlerRequest, request);
+
+ return request;
+ }
+
+protected:
+ OCStackResult registerResourceFake(OCResourceHandle&, string&, const string&,
+ const string&, EntityHandler handler, uint8_t)
+ {
+ this->handler = handler;
+ return OC_STACK_OK;
+ }
+
+ void initMocks() override
+ {
+ mocks.OnCallFuncOverload(
+ static_cast<registerResourceSig>(OCPlatform::registerResource)).Do(
+ bind(&ServerResourceHandlingRequestTest::registerResourceFake,
+ this, _1, _2, _3, _4, _5, _6));
+
+ mocks.OnCallFunc(OCPlatform::unregisterResource).Return(OC_STACK_OK);
+ }
+};
+
+TEST_F(ServerResourceHandlingRequestTest, CallSendResponseWhenReceiveRequest)
+{
+ mocks.ExpectCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
+
+ ASSERT_EQ(OC_EH_OK, handler(createRequest()));
+}
+
+TEST_F(ServerResourceHandlingRequestTest, ReturnErrorCodeWhenSendResponseFailed)
+{
+ mocks.ExpectCallFunc(OCPlatform::sendResponse).Return(OC_STACK_ERROR);
+
+ ASSERT_EQ(OC_EH_ERROR, handler(createRequest()));
+}
+
+TEST_F(ServerResourceHandlingRequestTest, SendResponseWithSameHandlesPassedByRequest)
+{
+ mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
+ [](const shared_ptr<OCResourceResponse> response)
+ {
+ return response->getRequestHandle() == fakeRequestHandle &&
+ response->getResourceHandle() == fakeResourceHandle;
+ }
+ ).Return(OC_STACK_OK);
+
+ ASSERT_EQ(OC_EH_OK, handler(createRequest()));
+}
+
+TEST_F(ServerResourceHandlingRequestTest, SendResponseWithPrimitiveResponseParams)
+{
+ constexpr int errorCode{ 1999 };
+ constexpr OCEntityHandlerResult result{ OC_EH_SLOW };
+
+ server->setGetRequestHandler(
+ [](const PrimitiveRequest&, ResourceAttributes&) -> PrimitiveGetResponse
+ {
+ return PrimitiveGetResponse::create(result, errorCode);
+ }
+ );
+
+ mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
+ [](const shared_ptr<OCResourceResponse> response)
+ {
+ return response->getErrorCode() == errorCode &&
+ response->getResponseResult() == result;
+ }
+ ).Return(OC_STACK_OK);
+
+ ASSERT_EQ(OC_EH_OK, handler(createRequest()));
+}
+
+
+
+class ServerResourceSynchronizationTest: public ServerResourceHandlingRequestTest
+{
+public:
+
+ static void withLock(PrimitiveServerResource::Ptr serverResource, int count)
+ {
+ for (int i=0; i<count; ++i)
+ {
+ PrimitiveServerResource::LockGuard lock{ serverResource };
+
+ auto& attrs = serverResource->getAttributes();
+
+ attrs[KEY] = attrs[KEY].get<int>() + 1;
+ }
+ }
+
+ static void withSetter(PrimitiveServerResource::Ptr serverResource, int count)
+ {
+ for (int i=0; i<count; ++i)
+ {
+ PrimitiveServerResource::LockGuard lock{ serverResource };
+
+ serverResource->setAttribute(KEY, serverResource->getAttribute<int>(KEY) + 1);
+ }
+ }
+};
+
+TEST_F(ServerResourceSynchronizationTest, MultipleAccessToServerResource)
+{
+ int expected { 0 };
+ vector<thread> threads;
+
+ server->setAttribute(KEY, 0);
+
+ for (int i = 20; i >= 0; --i) {
+ int count = 5000 + i * 100;
+ threads.push_back(thread { withLock, server, count });
+ expected += count;
+ }
+
+ for (int i = 20; i >= 0; --i) {
+ int count = 5000 + i * 100;
+ threads.push_back(thread { withSetter, server, count });
+ expected +=count;
+ }
+
+ for (auto& t : threads)
+ {
+ t.join();
+ }
+
+ ASSERT_EQ(expected, server->getAttribute<int>(KEY));
+}
+
+TEST_F(ServerResourceSynchronizationTest, MultipleAccessToServerResourceWithRequests)
+{
+ int expected { 0 };
+ vector<thread> threads;
+
+ mocks.ExpectCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
+
+ server->setAttribute(KEY, 0);
+
+ for (int i = 20; i >= 0; --i) {
+ int count = 5000 + i * 100;
+ threads.push_back(thread{ withLock, server, count });
+ expected += count;
+ }
+
+ for (int i = 20; i >= 0; --i) {
+ int count = 5000 + i * 100;
+ threads.push_back(thread{ withSetter, server, count });
+ expected +=count;
+ }
+
+ threads.push_back(thread{
+ [this]()
+ {
+ for (int i=0; i<10000; ++i)
+ {
+ if (i % 5 == 0) handler(createRequest(OC_REST_OBSERVE));
+ handler(createRequest((i & 1) ? OC_REST_GET : OC_REST_PUT));
+ }
+ }
+ });
+
+ for (auto& t : threads)
+ {
+ t.join();
+ }
+
+ ASSERT_EQ(expected, server->getAttribute<int>(KEY));
+}