Эх сурвалжийг харах

T19N0301 #comment 支持将spbase和rvccomm编译静态库

gifur 5 жил өмнө
parent
commit
bf076c4b1e

+ 8 - 2
CMakeLists.txt

@@ -65,6 +65,11 @@ message("RVC_VERSION=${RVC_VERSION_FULL}")
 configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_BINARY_DIR}/version.h")
 include_directories(${PROJECT_BINARY_DIR})
 
+# 设置生成文件的存放路径
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
 if(BUILD_TESTING)
 	include(CTest)
 	message(STATUS "build the tests.")
@@ -72,7 +77,7 @@ if(BUILD_TESTING)
 	set(GTEST_ROOT "${CMAKE_SOURCE_DIR}/third_party/gtest/googletest/include")
 	set(GMOCK_ROOT "${CMAKE_SOURCE_DIR}/third_party/gtest/googlemock/include")
 	if(MSVC)
-		set(TESTING_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
+		set(TESTING_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
 	else()
 		set(TESTING_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Testing")
 	endif()
@@ -86,7 +91,7 @@ endif()
 # Turn on solution folders (2.8.4+)
 set_property(GLOBAL PROPERTY USE_FOLDERS ON)
 
-set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install")
+set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install") # /${RVC_VERSION}
 # 如果使用绝对路径,会导致 CPack 因 CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION 失败
 # set(RVC_INCLUDE_PATH "${CMAKE_INSTALL_PREFIX}/include")
 # set(RVC_LIBRARY_PATH "${CMAKE_INSTALL_LIBDIR}")
@@ -96,6 +101,7 @@ set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install")
 set(RVC_INCLUDE_PATH "include")
 set(RVC_LIBRARY_PATH "lib")
 set(RVC_RUNTIME_PATH "bin")
+set(RVC_MODULE_LIBRARY_PATH "mod")
 
 if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_CONFIGURATION_TYPES STREQUAL Debug)
 	message(STATUS "debug type")

+ 10 - 2
Common/RVCComm.h

@@ -1,12 +1,17 @@
 #if !defined(AFX_RVCCOMM_H__12A1FE2E_023E_4CB8_99C5_E3AF870A5007__INCLUDED_)
 #define AFX_RVCCOMM_H__12A1FE2E_023E_4CB8_99C5_E3AF870A5007__INCLUDED_
 
+#ifdef RVCCOMM_LINKED_AS_STATIC_LIBRARY
+#define RVCCOMM_API
+#else
 #ifdef RVCCOMM_EXPORTS
 #define RVCCOMM_API __declspec(dllexport)
 #else
 #define RVCCOMM_API __declspec(dllimport)
-#pragma comment(lib, "RVCComm.lib")
 #endif
+#endif
+
+
 
 #include <windows.h>
 #include <string>
@@ -140,10 +145,13 @@ public:
 
 	// 错误回调,UserCode是后台服务自定义事件码, 如非后台服务产生的错误,则为0
 	virtual void OnError(DWORD dwSysCode, DWORD dwUserCode, const char *pErrMsg) =0;
-	
+
+#ifndef RVCCOMM_LINKED_AS_STATIC_LIBRARY
 #ifndef RVCCOMM_EXPORTS
 private:
 #endif
+#endif
+
 	IClientCommFunc *m_pClientComm;
 	LONG m_nRefCount;		
 };

+ 33 - 1
Common/SpBase.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #if defined(__cplusplus)
-
+#ifndef SPABASE_LINKED_AS_STATIC_LIBRARY
 #ifdef SPBASE_EXPORTS
 	#ifndef SPBASE_API
 		#define SPBASE_API __declspec(dllexport)
@@ -12,6 +12,9 @@
 		#pragma comment(lib, "SpBase.lib")
 	#endif
 #endif
+#else
+#define SPBASE_API
+#endif
 
 #endif // __cplusplus
 
@@ -228,11 +231,18 @@ public:
 
 class SPBASE_API CUUID
 {
+	
+#ifndef SPABASE_LINKED_AS_STATIC_LIBRARY
 #ifndef SPBASE_EXPORTS
 protected:
 #else
 public:
 #endif
+#else
+public:
+#endif
+	
+
 	union//Intel CPU byte order,otherwise the need to redefine
 	{
 		unsigned __int64 m_nUUID64;
@@ -889,8 +899,10 @@ public:
 	/** get entity service function */
 	CSmartPointer<IEntityFunction> GetFunction() { return m_pEntityFunction; }
 
+#ifndef SPABASE_LINKED_AS_STATIC_LIBRARY
 #ifndef SPBASE_EXPORTS
 protected:
+#endif
 #endif
 
 	/** 
@@ -931,8 +943,10 @@ public:
 	/** is this entity hosts service ? */
 	virtual bool IsService()const{return false;}
 
+#ifndef SPABASE_LINKED_AS_STATIC_LIBRARY
 #ifndef SPBASE_EXPORTS
 private:
+#endif
 #endif
 
 	/** dont access directly because of inner usage */
@@ -964,8 +978,10 @@ public:
 	/** get function pointer */
 	CSmartPointer<IServerSessionFunction> GetFunction(){return m_pSessionFunction;}
 
+#ifndef SPABASE_LINKED_AS_STATIC_LIBRARY
 #ifndef SPBASE_EXPORTS
 protected:
+#endif
 #endif
 
 	/** invoked when receives request from client */
@@ -983,9 +999,12 @@ protected:
 	/** is exclusive ? */
 	virtual bool IsExclusive() { return false; }
 
+#ifndef SPABASE_LINKED_AS_STATIC_LIBRARY
 #ifndef SPBASE_EXPORTS
 private:
 #endif
+#endif
+
 	/** dont access directly because of inner usage */
 	IServerSessionFunction* m_pSessionFunction;
 };
@@ -1095,11 +1114,16 @@ public:
 	/** invoke when delete the object */
 	virtual void OnDestroy() { delete this; }
 
+
+
+#ifndef SPABASE_LINKED_AS_STATIC_LIBRARY
 #ifndef SPBASE_EXPORTS
 private:
 #else
 public:
 #endif
+#endif
+
 	IClientSessionFunction* m_pSessionFunction;
 };
 
@@ -1123,11 +1147,19 @@ protected:
 	ErrorCodeEnum UnregistEntity(CEntityBase *pEntity);
 	ErrorCodeEnum GetRegistEntity(const char *pszEntityName,CSmartPointer<CEntityBase> &pEntity);
 
+
+
+#ifndef SPABASE_LINKED_AS_STATIC_LIBRARY
 #ifndef SPBASE_EXPORTS
 protected:
 #else
 public:
 #endif
+#else
+public:
+#endif
+
+
 	int m_nEntityCount;
 	CEntityBase* m_pEntityArray[32]; 
 	static ModuleBase* s_pModuleInst;

+ 5 - 0
Common/SpFSM.h

@@ -99,11 +99,16 @@ public:
 private:
 	void Trans(int next);
 
+#ifndef SPABASE_LINKED_AS_STATIC_LIBRARY
 #ifndef SPBASE_EXPORTS
 private:
 #else
 public:
 #endif
+#else
+public:
+#endif
+
 	void __ProcessEvent(FSMEvent *e);
 
 protected:

+ 3 - 0
Common/precompile.h

@@ -22,6 +22,9 @@
 #include <locale.h>
 #include <time.h>
 
+#ifdef SPABASE_LINKED_AS_STATIC_LIBRARY
+#define SPBASE_API
+#endif
 #ifdef SPBASE_EXPORTS
 #ifndef SPBASE_API
 #define SPBASE_API __declspec(dllexport)

+ 4 - 0
README.md

@@ -24,3 +24,7 @@
 
 ## 更新记录
 
+
+
+## 规范准则
+

+ 5 - 1
RVCComm/CMakeLists.txt

@@ -3,7 +3,7 @@ set(MODULE_NAME "RVCComm")
 set(MODULE_PREFIX "RVCCOMM")
 
 if(MSVC)
-	add_definitions(-DRVCCOMM_EXPORTS)
+	# add_definitions(-DRVCCOMM_EXPORTS)
 endif(MSVC)
 
 message(STATUS "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")
@@ -37,8 +37,12 @@ endif()
 
 add_library(${MODULE_NAME} SHARED ${${MODULE_PREFIX}_SRCS})
 target_link_libraries(${MODULE_NAME} ssl)
+target_compile_definitions(${MODULE_NAME} PRIVATE "-DRVCCOMM_EXPORTS=1")
 
 if (BUILD_TESTING)
+	add_library(${MODULE_NAME}_a STATIC ${${MODULE_PREFIX}_SRCS})
+	target_link_libraries(${MODULE_NAME}_a ssl)
+	target_compile_definitions(${MODULE_NAME}_a PRIVATE "-DRVCCOMM_LINKED_AS_STATIC_LIBRARY")
 	add_subdirectory(test)
 endif()
 

+ 2 - 1
RVCComm/ClientComm.h

@@ -9,8 +9,9 @@
 #pragma once
 #endif // _MSC_VER > 1000
 
-#include "RVCComm.h"
+// 调整了位置,解决出现编译错误 error C2011: “sockaddr”:“struct”类型重定义 2020年1月21日
 #include <winsock2.h>
+#include "RVCComm.h"
 #include "autolock.h"
 
 class CClientComm : public IClientCommFunc  

+ 3 - 5
RVCComm/test/CMakeLists.txt

@@ -4,16 +4,14 @@ set(MODULE_PREFIX "TEST_RVCCOMM")
 include_directories(..)
 set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.cpp)
 set(${MODULE_PREFIX}_TEST_DEFINITIONS "")
-set(${MODULE_PREFIX}_TESTS
-	ClientCommTest.cpp
-	)
+file(GLOB ${MODULE_PREFIX}_TESTS "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
 
 #Google Test
 include_directories(${GTEST_ROOT})
 include_directories(${GMOCK_ROOT})
 list(APPEND comm_test_libraries gtest)
 list(APPEND comm_test_libraries gtest_main)
-list(APPEND comm_test_libraries RVCComm)
+list(APPEND comm_test_libraries RVCComm_a)
 
 list(APPEND addin_libs gmock)
 list(APPEND addin_libs gmock_main)
@@ -25,7 +23,7 @@ foreach(test ${${MODULE_PREFIX}_TESTS})
 	set_property(TARGET ${test_name} PROPERTY FOLDER "test/rvccomm")
 	# 会将 测试的执行程序生成在指定的文件夹,并且带上编译的配置条件比如 Debug
 	set_target_properties(${test_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
-
+	set_target_properties(${test_name} PROPERTIES COMPILE_DEFINITIONS "RVCCOMM_LINKED_AS_STATIC_LIBRARY=1")
 	add_test(NAME ${test_name} COMMAND ${TESTING_OUTPUT_DIRECTORY}/${test_name})
 	set_tests_properties(${teset_name} PROPERTIES FAIL_REGULAR_EXPRESSION "FAILED;ERROR;Failed;error")
 endforeach()

+ 56 - 1
RVCComm/test/ClientCommTest.cpp

@@ -1,3 +1,4 @@
+#include "ClientComm.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -14,4 +15,58 @@ using testing::MockFunction;
 using testing::Ref;
 using testing::Return;
 using testing::ReturnRef;
-using testing::TypedEq;
+using testing::TypedEq;
+
+class CClientCommMock : public CClientComm
+{
+public:
+	CClientCommMock(CSecureClientBase* pCallback = nullptr):CClientComm(pCallback){}
+	virtual ~CClientCommMock(){}
+
+	MOCK_METHOD0(IsConnectionOK, bool());
+	MOCK_METHOD0(IsSecureConnection, bool());
+
+	MOCK_METHOD3(Connect, bool(const char* pServerAddr, int nPort, int nOption));
+	MOCK_METHOD0(Close, void());
+
+	MOCK_METHOD1(SendPackage, string(const CSmartPointer<IPackage>& pSendPkg));
+	MOCK_METHOD1(ReceivePackage, CSmartPointer<IPackage>(int nWaitSecond));
+	MOCK_METHOD1(CreateNewPackage, CSmartPointer<IPackage>(const char* pServiceCode));
+	MOCK_METHOD1(CreateReplyPackage, CSmartPointer<IPackage>(const CSmartPointer<IPackage>& pRecvPkg));
+};
+
+class CMockSecureClient : public CSecureClientBase
+{
+public:
+	MOCK_METHOD0(GetFunction, CSmartPointer<IClientCommFunc>());
+	MOCK_METHOD0(OnAuthPass, void());
+	//MOCK_METHOD0(DecRefCount, void());
+	MOCK_METHOD1(OnReceivePackage, void(CSmartPointer<IPackage>& pRecvPkg));
+	MOCK_METHOD0(OnClose, void());
+	MOCK_METHOD3(OnError, void(DWORD dwSysCode, DWORD dwUserCode, const char* pErrMsg));
+};
+
+TEST(ClientCommTest, TestConnectionAction)
+{
+	//treat as callback in CClientComm
+	CMockSecureClient* secure_client_mock = new CMockSecureClient();
+	EXPECT_CALL(*secure_client_mock, GetFunction());
+
+	CClientCommMock* mock =  new CClientCommMock(secure_client_mock);
+	EXPECT_CALL(*mock, IsConnectionOK()).WillOnce(Return(true));
+	EXPECT_CALL(*mock, IsSecureConnection()).WillOnce(Return(true));
+	EXPECT_TRUE(mock->IsConnectionOK());
+	EXPECT_TRUE(mock->IsSecureConnection());
+
+	// replace default assigned m_pClientComm with mock object.
+	ON_CALL(*secure_client_mock, GetFunction()).WillByDefault(Return(mock));
+	ASSERT_NE(nullptr, secure_client_mock->m_pClientComm);
+	delete secure_client_mock->m_pClientComm;
+	secure_client_mock->m_pClientComm = mock;
+	EXPECT_TRUE(secure_client_mock->GetFunction() == CSmartPointer<IClientCommFunc>(mock));
+
+	secure_client_mock->
+
+	EXPECT_TRUE(secure_client_mock->m_nRefCount == 1);
+	secure_client_mock->DecRefCount();
+}

+ 2 - 2
libtoolkit/CMakeLists.txt

@@ -38,8 +38,8 @@ endif()
 
 
 if (BUILD_TESTING)
-	add_library(toolkit_a STATIC ${${MODULE_PREFIX}_SRCS})
-	target_link_libraries(toolkit_a dbghelp)
+	add_library(${MODULE_NAME}_a STATIC ${${MODULE_PREFIX}_SRCS})
+	target_link_libraries(${MODULE_NAME}_a dbghelp)
 	add_subdirectory(test)
 endif()
 

+ 1 - 1
libtoolkit/test/CMakeLists.txt

@@ -31,7 +31,7 @@ set(${MODULE_PREFIX}_TESTS
 include_directories(${GTEST_ROOT})
 list(APPEND comm_test_libraries gtest)
 list(APPEND comm_test_libraries gtest_main)
-list(APPEND comm_test_libraries toolkit_a)
+list(APPEND comm_test_libraries libtoolkit_a)
 
 foreach(test ${${MODULE_PREFIX}_TESTS})
 	get_filename_component(test_name ${test} NAME_WE)

+ 9 - 1
spbase/CMakeLists.txt

@@ -19,7 +19,7 @@ if (WIN32)
 endif()
 
 if(WIN32)
-    add_definitions(-DSPBASE_EXPORTS  -DSCEW_DLL)
+    #add_definitions(-DSPBASE_EXPORTS  -DSCEW_DLL)
 endif(WIN32)
 
 add_library(${MODULE_NAME} SHARED ${${MODULE_PREFIX}_SRCS})
@@ -29,9 +29,17 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../libtoolkit)
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../third_party/scew/scew)
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../third_party/scew/expat-2.1.0/lib)
 if(MSVC)
+    target_compile_definitions(${MODULE_NAME} PRIVATE "-DSPBASE_EXPORTS" "-DSCEW_DLL")
 	target_link_libraries(${MODULE_NAME} psapi imagehlp ws2_32  libtoolkit RVCComm scew)
 endif(MSVC)
 
+if (BUILD_TESTING)
+    add_library(${MODULE_NAME}_a STATIC ${${MODULE_PREFIX}_SRCS})
+    target_link_libraries(${MODULE_NAME}_a  psapi imagehlp ws2_32  libtoolkit RVCComm scew)
+    target_compile_definitions(${MODULE_NAME}_a PRIVATE "-DSPABASE_LINKED_AS_STATIC_LIBRARY")
+	add_subdirectory(test)
+endif()
+
 install(TARGETS ${MODULE_NAME} 
     RUNTIME DESTINATION "${RVC_RUNTIME_PATH}"
     ARCHIVE DESTINATION "${RVC_LIBRARY_PATH}"

+ 4 - 0
spbase/sp_cfg.h

@@ -7,6 +7,7 @@
 extern "C" {
 #endif
 
+#ifndef SPABASE_LINKED_AS_STATIC_LIBRARY
 #ifdef SPBASE_EXPORTS
 #ifndef SPBASE_API
 #define SPBASE_API __declspec(dllexport)
@@ -17,6 +18,9 @@ extern "C" {
 #pragma comment(lib, "SpBase.lib")
 #endif
 #endif
+#else
+#define SPBASE_API
+#endif
 
 #include "list.h"
 #include "spinlock.h"

+ 4 - 0
spbase/sp_mod.h

@@ -7,6 +7,7 @@
 extern "C" {
 #endif
 
+#ifndef SPABASE_LINKED_AS_STATIC_LIBRARY
 #ifdef SPBASE_EXPORTS
 #ifndef SPBASE_API
 #define SPBASE_API __declspec(dllexport)
@@ -17,6 +18,9 @@ extern "C" {
 #pragma comment(lib, "SpBase.lib")
 #endif
 #endif
+#else
+#define SPBASE_API
+#endif
 
 #include "list.h"
 //

+ 25 - 0
spbase/test/CMakeLists.txt

@@ -0,0 +1,25 @@
+set(MODULE_NAME "test_spbase")
+set(MODULE_PREFIX "TEST_SPBASE")
+
+include_directories(..)
+file(GLOB ${MODULE_PREFIX}_TESTS "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
+
+#Google Test
+include_directories(${GTEST_ROOT})
+include_directories(${GMOCK_ROOT})
+list(APPEND comm_test_libraries gtest)
+list(APPEND comm_test_libraries gtest_main)
+list(APPEND comm_test_libraries spbase_a)
+
+list(APPEND addin_libs gmock)
+list(APPEND addin_libs gmock_main)
+foreach(test ${${MODULE_PREFIX}_TESTS})
+	get_filename_component(test_name ${test} NAME_WE)
+	add_executable(${test_name} ${test})
+	target_link_libraries(${test_name} ${comm_test_libraries} ${addin_libs})
+	set_property(TARGET ${test_name} PROPERTY FOLDER "test/spbase")
+	set_target_properties(${test_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
+	set_target_properties(${test_name} PROPERTIES COMPILE_DEFINITIONS "SPABASE_LINKED_AS_STATIC_LIBRARY=1")
+	add_test(NAME ${test_name} COMMAND ${TESTING_OUTPUT_DIRECTORY}/${test_name})
+	set_tests_properties(${teset_name} PROPERTIES FAIL_REGULAR_EXPRESSION "FAILED;ERROR;Failed;error")
+endforeach()

+ 114 - 0
spbase/test/SpSecureClientTest.cpp

@@ -0,0 +1,114 @@
+#include "SpSecureClient.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using testing::_;
+using testing::A;
+using testing::An;
+using testing::AnyNumber;
+using testing::Const;
+using testing::DoDefault;
+using testing::Eq;
+using testing::Lt;
+using testing::MockFunction;
+using testing::Ref;
+using testing::Return;
+using testing::ReturnRef;
+using testing::TypedEq;
+
+class CMockServerSession : public CServerSessionBase
+{
+public:
+	CMockServerSession(CEntityBase* pEntity):m_pEntity(pEntity) {}
+	~CMockServerSession() {}
+
+	bool IsExclusive() override { return false; }
+	bool IsSessionOverlap() override { return true;  }
+private:
+	CEntityBase* m_pEntity;
+};
+
+class entity_function_mock : public IEntityFunction
+{
+	
+};
+
+class CMockEntity : public CEntityBase
+{
+public:
+	MOCK_METHOD0(OnStarted, void());
+	MOCK_METHOD2(OnPreStart, void(CAutoArray<CSimpleStringA> strArgs, CSmartPointer<ITransactionContext> pTransactionContext));
+	MOCK_METHOD2(OnNewSession, CServerSessionBase* (const char* /*pszRemoteEntityName*/, const char* /*pszParam*/));
+	MOCK_CONST_METHOD0(GetEntityName, const char* ());
+	MOCK_METHOD0(IsService, bool());
+};
+
+class client_comm_func_mock : public IClientCommFunc
+{
+public:
+	client_comm_func_mock() {}
+	virtual ~client_comm_func_mock() {}
+
+	MOCK_METHOD0(IsConnectionOK, bool());
+	MOCK_METHOD0(IsSecureConnection, bool());
+
+	MOCK_METHOD3(Connect, bool(const char* pServerAddr, int nPort, int nOption));
+	MOCK_METHOD0(Close, void());
+
+	MOCK_METHOD1(SendPackage, string(const CSmartPointer<IPackage>& pSendPkg));
+	MOCK_METHOD1(ReceivePackage, CSmartPointer<IPackage>(int nWaitSecond));
+	MOCK_METHOD1(CreateNewPackage, CSmartPointer<IPackage>(const char* pServiceCode));
+	MOCK_METHOD1(CreateReplyPackage, CSmartPointer<IPackage>(const CSmartPointer<IPackage>& pRecvPkg));
+};
+
+/*
+ * SpSecureClient 是用于Entity内连接分行服务使用的,继承该类并实现相关功能
+ */
+class CMockSecureClient : public SpSecureClient
+{
+public:
+	CMockSecureClient(CEntityBase* pEntityBase):SpSecureClient(pEntityBase){}
+	
+	//MOCK_METHOD3(Connect, bool(const char* pServerAddr, int nPort, int nOption));
+	MOCK_METHOD1(ConnectFromConfig, bool(int nOption));
+	MOCK_METHOD0(ConnectFromCentralSetting, bool());
+	MOCK_METHOD0(IsConnectionOK, bool());
+	MOCK_METHOD0(IsSecureConn, bool());
+	MOCK_METHOD0(Close, void());
+
+	MOCK_METHOD1(SendPackage, string(const CSmartPointer<IPackage>& pSendPkg));
+	MOCK_METHOD1(ReceivePackage, CSmartPointer<IPackage>(int nWaitSecond));
+	MOCK_METHOD1(CreateNewPackage, CSmartPointer<IPackage>(const char* pServiceCode));
+	MOCK_METHOD1(CreateReplyPackage, CSmartPointer<IPackage>(const CSmartPointer<IPackage>& pRecvPkg));
+
+	MOCK_METHOD3(OnErrorMsg, void(DWORD dwSysCode, DWORD dwUserCode, const CSimpleStringA& pErrMsg));
+	MOCK_METHOD1(OnPkgAnswer, void(const CSmartPointer<IPackage>& pRecvPkg));
+
+	MOCK_METHOD0(GetFunction, CSmartPointer<IClientCommFunc>());
+};
+
+TEST(SpSecureClientMockTest, SpSecureClientComm)
+{
+	testing::DefaultValue<bool>::Set(true);
+
+	CMockEntity* entity = new CMockEntity();
+	ON_CALL(*entity, GetEntityName()).WillByDefault(Return("MockEntity"));
+	EXPECT_CALL(*entity, OnStarted()).Times(1);
+
+	client_comm_func_mock* comm_func_mock = new client_comm_func_mock();
+
+
+	CMockSecureClient* mock = new CMockSecureClient(entity);
+
+	ON_CALL(*mock, GetFunction()).WillByDefault(testing::Return(comm_func_mock));
+	EXPECT_CALL(*mock, GetFunction());
+	EXPECT_TRUE(mock->GetFunction() == CSmartPointer<IClientCommFunc>(comm_func_mock));
+
+	mock->Connect("127.0.0.1", 8090, 1);
+
+	mock->DecRefCount();
+	delete comm_func_mock;
+	delete entity;
+
+	testing::DefaultValue<bool>::Clear();
+}

+ 1 - 1
sphost/CMakeLists.txt

@@ -17,7 +17,7 @@ include_directories(${PROJECT_SOURCE_DIR}/libtoolkit)
 if (WIN32)
   set (RC_VERSION_MAJOR ${RVC_VERSION_MAJOR})
   set (RC_VERSION_MINOR ${RVC_VERSION_MINOR})
-  set (RC_VERSION_BUILD ${RVC_VERSION_REVISION})
+  set (RC_VERSION_BUILD   ${RVC_VERSION_REVISION})
 
   configure_file(
     ${CMAKE_SOURCE_DIR}/Version.rc.in

+ 1 - 0
test/CMakeLists.txt

@@ -0,0 +1 @@
+add_subdirectory(module)

+ 48 - 0
test/module/CMakeLists.txt

@@ -0,0 +1,48 @@
+macro(define_moudle _module_name)
+	set(MODULE_NAME "mod_${_module_name}")
+	string(TOUPPER "MOD_${MODULE_NAME}" MODULE_PREFIX)
+endmacro(define_moudle)
+
+#macro(add_module _module_prefix _module_name)
+#endmacro(add_module)
+
+macro(add_module_libraries _module_prefix _module_name)
+	if(WIN32)
+	    set (RC_VERSION_MAJOR ${RVC_VERSION_MAJOR})
+        set (RC_VERSION_MINOR ${RVC_VERSION_MINOR})
+        set (RC_VERSION_BUILD   ${RVC_VERSION_REVISION})
+        set (RC_VERSION_PATCH 0)
+        set(RC_VERSION_DESCRIPTION "${CMAKE_SHARED_LIBRARY_PREFIX}${_module_name}${CMAKE_SHARED_LIBRARY_SUFFIX}")
+       configure_file(
+        ${CMAKE_SOURCE_DIR}/Version.rc.in
+        ${CMAKE_CURRENT_BINARY_DIR}/version.rc
+        @ONLY)
+        set(${_module_prefix}_SRCS ${${_module_prefix}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+    endif(WIN32)
+    add_library(${_module_name} SHARED ${${_module_prefix}_SRCS})
+endmacro(add_module_libraries)
+
+macro(deploy_module _module_prefix _module_name)
+    install(TARGETS ${_module_name} DESTINATION ${RVC_MODULE_LIBRARY_PATH} COMPONENT modules)
+    set_property(TARGET ${_module_name} PROPERTY FOLDER "module/")
+endmacro(deploy_module)
+
+#set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client)
+#set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp)
+#set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} msimg32)
+#target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
+
+file(GLOB module_dirs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/*")
+set(module_list "")
+foreach(module_dir ${module_dirs})
+    if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${module_dir})
+        list(APPEND module_list ${module_dir})
+    endif()
+endforeach()
+foreach(module ${module_list})
+    message(STATUS  "add module ${module}...")
+    add_subdirectory(${module})
+endforeach()
+
+
+

+ 9 - 0
test/module/mod_helloclient/CMakeLists.txt

@@ -0,0 +1,9 @@
+define_moudle("helloclient")
+set(${MODULE_PREFIX}_SRCS
+	mod_helloclient.cpp)
+
+add_module_libraries(${MODULE_PREFIX} ${MODULE_NAME})
+set(${MODULE_PREFIX}_LIBS spbase)
+target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
+
+deploy_module(${MODULE_PREFIX} ${MODULE_NAME})

+ 82 - 0
test/module/mod_helloclient/mod_helloclient.cpp

@@ -0,0 +1,82 @@
+#include "stdafx.h"
+#include "SpBase.h"
+
+#include "..\mod_helloservice\HelloService_client_g.h"
+
+using namespace HelloService;
+
+class HelloClientEntity : public CEntityBase, public ITimerListener, public ISysVarListener
+{
+public:
+	HelloClientEntity() : m_pClient(NULL) {}
+	virtual ~HelloClientEntity() {}
+	virtual const char *GetEntityName() const { return "HelloClient"; }
+
+	virtual void OnTimeout(DWORD dwTimerID)
+	{
+		LOG_FUNCTION();
+		m_pClient->Ping();
+	}
+
+	virtual void OnSysVarEvent(const char *pszKey, const char *pszValue,const char *pszOldValue,const char *pszEntityName)
+	{
+		LOG_TRACE("entity:%s key:%s value:%s", pszEntityName, pszKey, pszValue);
+	}
+
+	virtual void OnStarted()
+	{
+		LOG_FUNCTION();
+
+		//MessageBox(0, 0, 0, 0);
+
+		CSmartPointer<IEntityFunction> pFunc = GetFunction();
+		//pFunc->SetTimer(1, this, 1000);
+		//pFunc->RegistSysVarEvent("HelloState", this);
+
+#if 1
+		HelloService_ClientBase *client = new HelloService_ClientBase(this);
+		Dbg("before connect");
+		ErrorCodeEnum Error = client->Connect();
+		Dbg("after connect");
+		if (Error == Error_Succeed) {
+			LOG_TRACE("connect ok!");
+
+			// invoke Ping method
+			Dbg("before ping");
+			Error = client->Ping();
+			LOG_ASSERT(Error == Error_Succeed);
+			Dbg("after ping");
+
+			// invoke Hello method
+
+			HelloService_Hello_Req Hello_Req; // request msg
+			HelloService_Hello_Ans Hello_Ans; // answer msg,
+			Hello_Req.txt = "Hello, this message comes from HelloClient entity!";
+			Dbg("before hello");
+			Error = client->Hello(Hello_Req, Hello_Ans, -1);
+			Dbg("after hello");
+			//LOG_ASSERT(Error == Error_Succeed);
+			//LOG_TRACE((LPCSTR)Hello_Ans.txt);
+
+			client->GetFunction()->CloseSession();
+		}
+		client->SafeDelete();
+#endif
+
+		m_pClient = new HelloService_ClientBase(this);
+		m_pClient->Connect();
+	}
+
+	virtual void OnPreClose(EntityCloseCauseEnum eCloseCause,CSmartPointer<ITransactionContext> pTransactionContext) 
+	{ 
+		LOG_FUNCTION();
+		pTransactionContext->SendAnswer(Error_Succeed); 
+	}
+
+private:
+	HelloService_ClientBase *m_pClient;
+};
+
+SP_BEGIN_ENTITY_MAP()
+	SP_ENTITY(HelloClientEntity)
+SP_END_ENTITY_MAP()

+ 9 - 0
test/module/mod_helloservice/CMakeLists.txt

@@ -0,0 +1,9 @@
+define_moudle("helloservice")
+set(${MODULE_PREFIX}_SRCS
+	mod_helloservice.cpp)
+
+add_module_libraries(${MODULE_PREFIX} ${MODULE_NAME})
+set(${MODULE_PREFIX}_LIBS spbase)
+target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
+
+deploy_module(${MODULE_PREFIX} ${MODULE_NAME})

+ 80 - 0
test/module/mod_helloservice/HelloService_client_g.h

@@ -0,0 +1,80 @@
+
+#ifndef __HELLOSERVICE_CLIENT_G_H
+#define __HELLOSERVICE_CLIENT_G_H
+
+#pragma once
+
+// This code is generated by spgen tool!
+
+#include "HelloService_def_g.h"
+
+namespace HelloService {
+class HelloService_ClientBase : public CClientSessionBase {
+public:
+	HelloService_ClientBase(CEntityBase *pEntity) : m_pEntityBase(pEntity), m_bSysManaged(false) {}
+
+protected:
+	virtual ~HelloService_ClientBase() {}
+public:
+
+	ErrorCodeEnum Connect(CSmartPointer<IAsynWaitSp> &spAsyncWait)
+	{
+		CSmartPointer<IEntityFunction> pFunc = m_pEntityBase->GetFunction();
+		ErrorCodeEnum Error = pFunc->ConnectRemoteEntity(this, "HelloService", "HelloService", spAsyncWait);
+		if (Error == Error_Succeed) {
+			m_bSysManaged = true;
+		}
+		return Error;
+	}
+	ErrorCodeEnum Connect()
+	{
+		CSmartPointer<IAsynWaitSp> spAsyncWait;
+		ErrorCodeEnum Error = Connect(spAsyncWait);
+		if (Error == Error_Succeed) {
+			Error = spAsyncWait->WaitAnswer();
+		}
+		return Error;
+	}
+
+	ErrorCodeEnum Ping()
+	{
+		CSmartPointer<IClientSessionFunction> pFunc = GetFunction();
+		return pFunc->OnewayCall(HelloService_Method_Ping, HelloService_MethodSignature_Ping);
+	}
+
+	ErrorCodeEnum Hello(HelloService_Hello_Req &Req, CSmartPointer<IAsynWaitSp> &spAsyncWait, DWORD dwTimeout)
+	{
+		CSmartPointer<IClientSessionFunction> pFunc = GetFunction();
+		CAutoBuffer Buf = SpObject2Buffer(Req);
+		return pFunc->AsyncRequest(HelloService_Method_Hello, HelloService_MethodSignature_Hello, Buf, spAsyncWait, dwTimeout);
+	}
+	ErrorCodeEnum Hello(HelloService_Hello_Req &Req, HelloService_Hello_Ans &Ans, DWORD dwTimeout)
+	{
+		CSmartPointer<IAsynWaitSp> spAsyncWait;
+		ErrorCodeEnum Error = Hello(Req, spAsyncWait, dwTimeout);
+		if (Error == Error_Succeed) {
+			bool bEnd = false;
+			Error = SpWaitAnswerObject(spAsyncWait, Ans, bEnd);
+			LOG_ASSERT(Error || bEnd);
+		}
+		return Error;
+	}
+
+
+	bool SafeDelete()
+	{
+		if (!m_bSysManaged) {
+			delete this;
+		}
+		return m_bSysManaged;
+	}
+
+protected:
+	bool m_bSysManaged;
+	CEntityBase *m_pEntityBase;
+};
+
+///////////////////////////
+
+} // namespace HelloService
+#endif // __HELLOSERVICE_CLIENT_G_H

+ 57 - 0
test/module/mod_helloservice/HelloService_def_g.h

@@ -0,0 +1,57 @@
+#ifndef __HELLOSERVICE_DEF_G_H
+#define __HELLOSERVICE_DEF_G_H
+
+#pragma once
+
+// This code is generated by spgen tool!
+
+#include "spHelper.h"
+
+namespace HelloService {
+//
+// const goes here
+//
+
+#define HelloService_Method_Ping 0
+#define HelloService_Method_Hello 1
+
+#define HelloService_MethodSignature_Ping 0x8FA29144
+#define HelloService_MethodSignature_Hello 0x885E0CAD
+
+struct HelloService_Ping_Info
+{
+
+	void Serialize(SpBuffer &Buf)
+	{
+	}
+
+};
+
+struct HelloService_Hello_Req
+{
+	CSimpleStringA txt;
+
+	void Serialize(SpBuffer &Buf)
+	{
+		Buf & txt;
+	}
+
+};
+
+struct HelloService_Hello_Ans
+{
+	CSimpleStringA txt;
+
+	void Serialize(SpBuffer &Buf)
+	{
+		Buf & txt;
+	}
+
+};
+
+
+///////////////////////////
+
+} // namespace HelloService
+
+#endif // __HELLOSERVICE_DEF_G_H

+ 31 - 0
test/module/mod_helloservice/HelloService_msg_g.h

@@ -0,0 +1,31 @@
+
+#ifndef __HELLOSERVICE_MSG_G_H
+#define __HELLOSERVICE_MSG_G_H
+
+#pragma once
+
+// This code is generated by spgen tool!
+
+#include "spHelper.h"
+
+namespace HelloService {
+#define eMsg_TestEvent 0
+
+#define eMsgSig_TestEvent -403848640
+
+struct TestEvent
+{
+	CSimpleStringA m1;
+	int m2;
+
+	void Serialize(SpBuffer &Buf)
+	{
+		Buf & m1 & m2;
+	}
+
+};
+
+///////////////////////////
+
+} // namespace HelloService
+#endif // __HELLOSERVICE_MSG_G_H

+ 127 - 0
test/module/mod_helloservice/HelloService_server_g.h

@@ -0,0 +1,127 @@
+
+#ifndef __HELLOSERVICE_SERVER_G_H
+#define __HELLOSERVICE_SERVER_G_H
+
+#pragma once
+
+// This code is generated by spgen tool!
+
+#include "HelloService_def_g.h"
+
+namespace HelloService {
+class HelloService_ServerSessionBase : public CServerSessionBase
+{
+public:
+	HelloService_ServerSessionBase() { }
+
+	virtual ~HelloService_ServerSessionBase() { }
+
+	virtual bool IsExclusive() { return false; }
+
+	virtual bool IsSessionOverlap() { return true; }
+
+	virtual ErrorCodeEnum GetMessageAttr(DWORD dwMessageID, DWORD dwSignature, bool &bOverlap)
+	{
+		ErrorCodeEnum Error = Error_Succeed;
+		switch (dwMessageID) {
+		case HelloService_Method_Ping:
+			if (dwSignature == HelloService_MethodSignature_Ping) {
+				bOverlap = true;
+			} else {
+				Error = Error_MethodSignatureFailed;
+			}
+			break;
+		case HelloService_Method_Hello:
+			if (dwSignature == HelloService_MethodSignature_Hello) {
+				bOverlap = true;
+			} else {
+				Error = Error_MethodSignatureFailed;
+			}
+			break;
+		default:
+			Error = Error_MethodNotFound;
+			break;
+		}
+		return Error;
+	}
+
+	int CheckMessageSignature(DWORD dwMessageID, DWORD dwSignature)
+	{
+		ErrorCodeEnum Error = Error_Succeed;
+		switch (dwMessageID) {
+		case HelloService_Method_Ping:
+			if (dwSignature != HelloService_MethodSignature_Ping) {
+				Error = Error_MethodSignatureFailed;
+			}
+			break;
+		case HelloService_Method_Hello:
+			if (dwSignature != HelloService_MethodSignature_Hello) {
+				Error = Error_MethodSignatureFailed;
+			}
+			break;
+		default:
+			Error = Error_MethodNotFound;
+			break;
+		}
+		return Error;
+	}
+
+	virtual void Handle_Ping(SpOnewayCallContext<HelloService_Ping_Info>::Pointer ctx)
+	{
+	/// override by user
+	}
+
+	virtual void Handle_Hello(SpReqAnsContext<HelloService_Hello_Req, HelloService_Hello_Ans>::Pointer ctx)
+	{
+	/// override by user
+	}
+
+	virtual void OnRequest(CSmartPointer<ITransactionContext> pTransactionContext)
+	{
+		CAutoBuffer Buf;
+		DWORD dwMessageID;
+		DWORD dwMessageSignature;
+		ErrorCodeEnum Error = pTransactionContext->GetReceiveBuffer(dwMessageID, dwMessageSignature, Buf);
+		if (Error == Error_Succeed) {
+#ifdef DEBUG
+			assert(CheckMessageSignature(dwMessageID, dwMessageSignature) == Error_Succeed);
+#else
+			if (CheckMessageSignature(dwMessageID, dwMessageSignature) != Error_Succeed) {
+				pTransactionContext->SendAnswer(Error_MethodSignatureFailed);
+				return;
+			}
+#endif
+			switch (dwMessageID) {
+				case HelloService_Method_Ping:
+					{
+						SpOnewayCallContext<HelloService_Ping_Info>::Pointer ctx;
+						ctx.Attach(new SpOnewayCallContext<HelloService_Ping_Info>());
+						SpBuffer2Object(Buf, ctx->Info);
+						Handle_Ping(ctx);
+					}
+					break;
+				case HelloService_Method_Hello:
+					{
+						SpReqAnsContext<HelloService_Hello_Req,HelloService_Hello_Ans>::Pointer ctx;
+						ctx.Attach(new SpReqAnsContext<HelloService_Hello_Req,HelloService_Hello_Ans>(pTransactionContext));
+						SpBuffer2Object(Buf, ctx->Req);
+						Handle_Hello(ctx);
+					}
+					break;
+				default:
+					assert(0);
+					break;
+			}
+			
+		} else {
+			pTransactionContext->SendAnswer(Error);
+		}
+	}
+
+};
+
+
+///////////////////////////
+
+} // namespace HelloService
+#endif // __HELLOSERVICE_SERVER_G_H

+ 77 - 0
test/module/mod_helloservice/mod_helloservice.cpp

@@ -0,0 +1,77 @@
+#include "stdafx.h"
+#include "SpBase.h"
+#include "HelloService_server_g.h"
+#include "HelloService_msg_g.h"
+
+using namespace HelloService;
+
+class HelloService_Session : public HelloService_ServerSessionBase
+{
+public:
+	virtual void Handle_Ping(SpOnewayCallContext<HelloService_Ping_Info>::Pointer ctx)
+	{
+		LOG_FUNCTION();
+		LOG_TRACE("handle ping msg !");
+	}
+
+	virtual void Handle_Hello(SpReqAnsContext<HelloService_Hello_Req, HelloService_Hello_Ans>::Pointer ctx)
+	{
+		LOG_FUNCTION();
+		LOG_TRACE("handle hello msg %s!", ctx->Req.txt);
+		ctx->Ans.txt = "Hello, this message comes from Hello Service entity!";
+		ctx->Answer();
+	}
+};
+
+class HelloServiceEntity : public CEntityBase, public ITimerListener
+{
+public:
+	HelloServiceEntity() {}
+	virtual ~HelloServiceEntity() {}
+	virtual const char *GetEntityName() const { return "HelloService"; }
+
+	virtual void OnTimeout(DWORD dwTimerID)
+	{
+		Dbg("on timer id %d ", dwTimerID);
+#if 0
+		CSmartPointer<IEntityFunction> pFunc = GetFunction();
+		CSimpleStringA strValue;
+		pFunc->GetSysVar("HelloState", strValue);
+		LOG_TRACE("sys var = %s", (LPCSTR)strValue);
+		CSimpleStringA strValue1 = CSimpleStringA::Format("%d", atoi((LPCSTR)strValue)+1);
+		pFunc->SetSysVar("HelloState", strValue1);
+#endif
+#if 0
+		TestEvent evt;
+		evt.m1 = "from hello service, m1";
+		evt.m2 = 1234;
+		SpSendBroadcast(pFunc, SP_MSG_OF(TestEvent), SP_MSG_SIG_OF(TestEvent), evt);
+#endif
+		LogEvent(Severity_Middle, 0x20300001, "hello service test");
+	}
+
+	virtual void OnStarted()
+	{
+		LOG_FUNCTION();
+		//CSmartPointer<IEntityFunction> pFunc = GetFunction();
+		//pFunc->SetTimer(1, this, 2000);
+	}
+
+	virtual void OnPreClose(EntityCloseCauseEnum eCloseCause,CSmartPointer<ITransactionContext> pTransactionContext) 
+	{ 
+		LOG_FUNCTION();
+		pTransactionContext->SendAnswer(Error_Succeed); 
+	}
+
+	virtual CServerSessionBase *OnNewSession(const char* pszRemoteEntityName, const char * pszClass)
+	{
+		LOG_FUNCTION();
+		return new HelloService_Session();
+	}
+
+	virtual bool IsService()const{return true;}
+};
+
+SP_BEGIN_ENTITY_MAP()
+	SP_ENTITY(HelloServiceEntity)
+SP_END_ENTITY_MAP()