mod_validityVertifier.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. #include "stdafx.h"
  2. #include "SpBase.h"
  3. #include "SpTest.h"
  4. #include "modVer.h"
  5. #include "validityVertifier_msg_g.h"
  6. #include "validityVertifier_server_g.h"
  7. #include "../../Other/libpublicFun/publicFunExport.h"
  8. //#pragma comment(lib, "libpublicFun.lib")
  9. /*Integrated test deamon*/
  10. #define OP_START 1
  11. #define OP_TEST 2
  12. #define OP_CHECK 3
  13. struct TestModeInfo {
  14. TestModeInfo() :isTestMode(false), nLevel(0) {
  15. }
  16. bool isTestMode;
  17. int nLevel;
  18. };
  19. class CTestDeamon;
  20. class CValidityVerifyierSession : public validityVertifier::validityVertifierSrv_ServerSessionBase
  21. {
  22. public:
  23. CValidityVerifyierSession(CTestDeamon* pEntity) : m_pEntity(pEntity) {}
  24. virtual ~CValidityVerifyierSession() {}
  25. private:
  26. CTestDeamon* m_pEntity;
  27. };
  28. class CTestDeamon
  29. : public CEntityBase
  30. , public IEntityLifeListener
  31. , public IEntityStateListener
  32. , public ILogListener
  33. , public ICallbackListener
  34. , public ITerminalStateChangedListener
  35. , public ITimerListener
  36. , public ISysVarListener
  37. {
  38. public:
  39. CTestDeamon() : _dwStartedTestEntities(0) { _arrTestEntities.Clear(); }
  40. virtual ~CTestDeamon() {
  41. GetFunction()->UnsubscribeLog(m_subUUID);
  42. GetFunction()->GetPrivilegeFunction()->UnregistLiftEvent();
  43. GetFunction()->GetPrivilegeFunction()->UnregistEntityStateEvent(NULL);
  44. }
  45. virtual const char *GetEntityName() const { return "TestDeamon"; }
  46. const char* GetEntityVersion() const { return MODULE_VERSION_FULL; }
  47. virtual bool IsService()const { return true; }
  48. virtual CServerSessionBase* OnNewSession(const char*, const char*) { return new CValidityVerifyierSession(this); }
  49. virtual void OnPreStart(CAutoArray<CSimpleStringA> strArgs, CSmartPointer<ITransactionContext> pTransactionContext)
  50. {
  51. LOG_FUNCTION();
  52. for (int i = 0; i < strArgs.GetCount(); ++i) {
  53. auto& strParam = strArgs[i];
  54. if (strParam.IsStartWith("TestMode", true)) {
  55. if (strParam.IsEndWith("=ON", true)) {
  56. _testInfo.isTestMode = true;
  57. }
  58. }
  59. }
  60. IFFAILBREAK(GetFunction()->GetSystemRunInfo(_runInfo));
  61. auto privilegeFunc = GetFunction()->GetPrivilegeFunction();
  62. privilegeFunc->RegistEntityLifeEvent(this);
  63. /*register all entity state*/
  64. privilegeFunc->RegistEntityStateEvent(NULL, this);
  65. Dbg("to subscribe Error_Failed type log.");
  66. auto res = GetFunction()->SubscribeLog(m_subUUID, this, Log_Error, Severity_None, Error_Failed, -2, NULL, false);
  67. if (IS_FAILURED(res)) {
  68. LogError(Severity_High, res, 0, "subscribe Error_Failed type log failed!");
  69. }
  70. auto err = GetFunction()->RegistSysVarEvent("*", this);
  71. Dbg("RegistSysVarEvent, ret:%d", err);
  72. pTransactionContext->SendAnswer(Error_Succeed);
  73. }
  74. BOOL IsExcludeEntity(const CSimpleStringA& name)
  75. {
  76. if (name.Compare(GetEntityName()) == 0)
  77. return TRUE;
  78. for (int i = 0; i < _arrTestEntities.GetCount(); ++i) {
  79. if (name.Compare(_arrTestEntities[i]) == 0)
  80. return TRUE;
  81. }
  82. return FALSE;
  83. }
  84. void TestAllRegistedEntity()
  85. {
  86. CAutoArray<CSimpleStringA> arrStartEntities;
  87. CAutoArray< DWORD> arrEntitityID;
  88. IFFAILBREAK(GetFunction()->GetAllStartedEntity(arrStartEntities, arrEntitityID));
  89. for (int i = 0; i < arrStartEntities.GetCount(); ++i) {
  90. if(!IsExcludeEntity(arrStartEntities[i]))
  91. TestEntity(arrStartEntities[i]);
  92. }
  93. }
  94. virtual void OnStarted()
  95. {
  96. LOG_FUNCTION();
  97. IFFAILBREAK(GetFunction()->RegistTerminalStateChangeEvent(this));
  98. //IFFAILBREAK(GetFunction()->SetTimer(1, this, 60 * 1000));
  99. }
  100. virtual void OnPreClose(EntityCloseCauseEnum eCloseCause,CSmartPointer<ITransactionContext> pTransactionContext)
  101. {
  102. LOG_FUNCTION();
  103. pTransactionContext->SendAnswer(Error_Succeed);
  104. }
  105. //IEntityLifeListener
  106. void OnCreated(const char* pszEntityName, ErrorCodeEnum eOnStartErrorCode, const char* pszCallerEntity)
  107. {
  108. LOG_TRACE("%s created by %s turns out %s",pszEntityName, pszCallerEntity, SpStrError(eOnStartErrorCode));
  109. }
  110. void OnClosed(const char* pszEntityName,
  111. EntityCloseCauseEnum eCloseCause,
  112. ErrorCodeEnum eOnCloseErrorCode,
  113. const char* pszCallerEntity)
  114. {
  115. LOG_TRACE("%s closed by %s because reason: %s turns out: %s",pszEntityName, pszCallerEntity, SpStrCloseCause(eCloseCause), SpStrError(eOnCloseErrorCode));
  116. }
  117. void OnException(const char* pszEntityName, const char* pszFunctionName, EntityStateEnum eState, EntityStateEnum eLastState, ErrorCodeEnum eErrorCode)
  118. {
  119. THROW_FATAL("OnException: %s::%s, changed state from %s to %s: ec:%s",
  120. pszEntityName, pszFunctionName, SpStrEntityState(eLastState), SpStrEntityState(eState), SpStrError(eErrorCode));
  121. if (eState == EntityState_Failed || eState == EntityState_Lost) {
  122. RequireTerminalExit();
  123. }
  124. }
  125. //IEntityStateListener
  126. void OnEntityStateHook(const char* pszEntityName,
  127. const char* pszTriggerEntity,
  128. EntityStateEnum eState,
  129. EntityStateEnum eLastState)
  130. {
  131. LOG_TRACE(">>>%s's entity state refreshed from %s to %s by %s",
  132. pszEntityName, SpStrEntityState(eLastState), SpStrEntityState(eState), pszTriggerEntity);
  133. if (eState == EntityState_Failed || eState == EntityState_Lost) {
  134. RequireTerminalExit();
  135. }
  136. else if (eLastState == EntityState_Starting && eState == EntityState_Idle) {
  137. /** if meet multi-entities at one mod, do test maybe failed beacause mod is busy at starting other brother entity.*/
  138. //TestEntity(pszEntityName);
  139. }
  140. }
  141. virtual void OnSysVarEvent(const char* pszKey, const char* pszValue, const char* pszOldValue, const char* pszEntityName) {
  142. Dbg("OnSysVarEvent %s, old->new:%s->%s", pszKey, pszOldValue, pszValue);
  143. CSmartPointer<IEntityFunction> spFunction = GetFunction();
  144. std::map<std::string, std::string> srcData;
  145. srcData.insert(std::make_pair("pszKey", pszKey));
  146. srcData.insert(std::make_pair("oldValue", pszOldValue));
  147. srcData.insert(std::make_pair("curValue", pszValue));
  148. auto ret = generateJsonStr(srcData);
  149. if (ret.first)
  150. {
  151. Dbg(ret.second.c_str());
  152. validityVertifier::validityVertifierBroadcast cur = { ret.second.c_str() };
  153. SpSendBroadcast(GetFunction(), eMsg_validityVertifierBroadcast, eMsgSig_validityVertifierBroadcast, cur);
  154. }
  155. }
  156. void OnUserStateHook(const char* pszEntityName, DWORD dwState, DWORD dwLastState)
  157. {
  158. LOG_TRACE(">>>%s'user state refreshed to %d from %d", pszEntityName, dwState, dwLastState);
  159. }
  160. void OnCeateConnection(const char* pszCallerEntity, const char* pszServiceEntity)
  161. {
  162. LOG_TRACE(">>>OnCeateConnection: caller: %s, service: %s", pszCallerEntity, pszServiceEntity);
  163. }
  164. void OnCloseConnection(const char* pszCallerEntity, const char* pszServiceEntity)
  165. {
  166. LOG_TRACE(">>>OnCloseConnection: caller: %s, service: %s", pszCallerEntity, pszServiceEntity);
  167. }
  168. //ILogListener
  169. void OnLog(const CAutoArray<CUUID>& SubIDs
  170. , const CUUID nLogID
  171. , const LogTypeEnum eLogType
  172. , const SeverityLevelEnum eLevel
  173. , const DWORD dwSysError, const DWORD dwUserCode
  174. , const DWORD dwEntityInstanceID, const WORD wEntityDevelID
  175. , const CAutoArray<DWORD>& Param
  176. , const char* pszEntityName, const char* pszModuleName, const char* pszMessage, const linkContext& pLinkInfo)
  177. {
  178. LogEvent(eLevel, 0,
  179. CSimpleStringA::Format("Catched Test Failed Message: [%s][0x%03X][%s] - %s",
  180. pszModuleName, wEntityDevelID, pszEntityName, pszMessage));
  181. switch (eLevel) {
  182. case Severity_High:
  183. RequireTerminalExit();
  184. break;
  185. case Severity_Middle:
  186. /** do nothings*/
  187. break;
  188. default:
  189. break;
  190. }
  191. }
  192. void OnStateChanged(FrameworkStateEnum oldState, FrameworkStateEnum curState, const char* triggerEntity)
  193. {
  194. Dbg("OnStateChanged: from %s to %s trigged by %s",
  195. SpStrFrameworkState(oldState), SpStrFrameworkState(curState), triggerEntity);
  196. if (curState == FrameworkState_Running && _testInfo.isTestMode
  197. // && !(_runInfo.dwBootOption & BootOption_Benchmark) /** when under benchmark, still need to test entity??*/
  198. )
  199. {
  200. TestAllRegistedEntity();
  201. }
  202. }
  203. void OnTimeout(DWORD dwTimerID)
  204. {
  205. Dbg("timer out: %d, to shake hand", dwTimerID);
  206. CAutoArray<CSimpleStringA> arrStartEntities;
  207. CAutoArray< DWORD> arrEntitityID;
  208. IFFAILBREAK(GetFunction()->GetAllStartedEntity(arrStartEntities, arrEntitityID));
  209. for (int i = 0; i < arrStartEntities.GetCount(); ++i)
  210. {
  211. if (arrStartEntities[i].Compare(GetEntityName()) != 0)
  212. {
  213. TestEntity(arrStartEntities[i], TRUE);
  214. }
  215. }
  216. }
  217. struct TestCallbackResult : public IReleasable
  218. {
  219. TestCallbackResult() :strEntityName(true), op(0) {}
  220. virtual ~TestCallbackResult() {}
  221. CSimpleStringA strEntityName;
  222. int op;
  223. };
  224. /*ICallbackListener*/
  225. void OnAnswer(CSmartPointer<IAsynWaitSp> pAsynWaitSp)
  226. {
  227. CSmartPointer<ICallbackListener> listener;
  228. CSmartPointer<IReleasable> context;
  229. CHECK(pAsynWaitSp->GetCallback(listener, context));
  230. TestCallbackResult* result = static_cast<TestCallbackResult*>(context.GetRawPointer());
  231. CHECK(result != NULL);
  232. DWORD dwUserCode = 0;
  233. const auto ec = pAsynWaitSp->AsyncGetAnswer(dwUserCode);
  234. if (result->op == OP_START)
  235. {
  236. if (IS_FAILURED(ec))
  237. {
  238. THROW_ERROR("Start %s failed return %s!", result->strEntityName.GetData(), SpStrError(ec));
  239. }
  240. else
  241. {
  242. Dbg("Start entity %s succ.", result->strEntityName.GetData());
  243. _arrTestEntities[_dwStartedTestEntities++] = result->strEntityName;
  244. }
  245. }
  246. else if(result->op == OP_TEST)
  247. { /** OnExam returned.*/
  248. if (Error_IgnoreAll == ec || Error_NotImpl == ec)
  249. {
  250. LogWarn(Severity_Middle, Error_NotImpl, 0, CSimpleStringA::Format(
  251. "Test for entity [%s] is not OK: Detect no any TestCase!!", result->strEntityName.GetData()));
  252. }
  253. else if (Error_Accept == ec || Error_Succeed == ec)
  254. {
  255. LogEvent(Severity_High, 0, CSimpleStringA::Format("Test for entity[%s] succ.", result->strEntityName.GetData()));
  256. }
  257. else
  258. {
  259. TestCaseStatistics statistic;
  260. statistic.ConvertFormUserCode(dwUserCode);
  261. THROW_ERROR("Test for entity[%s] failed return %s: %.2lf percent tests failed, %u failed out of %u cases",
  262. result->strEntityName.GetData(), SpStrError(ec), statistic.FailureRate(), statistic.Failures(), statistic.Total());
  263. }
  264. Dbg("return usercode: 0x%08X", dwUserCode);
  265. }
  266. else if (result->op == OP_CHECK)
  267. {
  268. if (IS_FAILURED(ec))
  269. {
  270. THROW_ERROR("Check %s failed return %s!", result->strEntityName.GetData(), SpStrError(ec));
  271. }
  272. }
  273. }
  274. private:
  275. void RequireTerminalExit()
  276. {
  277. if (_testInfo.isTestMode)
  278. {
  279. Dbg("Test Failed! shutdown the terminal program...");
  280. auto pPriviFunc = GetFunction()->GetPrivilegeFunction();
  281. pPriviFunc->Reboot(RebootTrigger_DeadForever, RebootWay_Framework);
  282. }
  283. }
  284. void SetOPCallback(CSmartPointer<IAsynWaitSp>& spWait, const char* pcszName, int op)
  285. {
  286. TestCallbackResult* result = new TestCallbackResult();
  287. result->strEntityName = pcszName;
  288. result->op = op;
  289. spWait->SetCallback(this, result);
  290. }
  291. ErrorCodeEnum TestEntity(const char* lcpszEntityName, bool bShake = false)
  292. {
  293. if(!bShake)
  294. LogEvent(Severity_High, 0, CSimpleStringA::Format("Test specified entity: %s", lcpszEntityName));
  295. auto pPriviFunc = GetFunction()->GetPrivilegeFunction();
  296. CSmartPointer<IAsynWaitSp> waitSp;
  297. auto ec = pPriviFunc->TestEntity(lcpszEntityName, bShake ? Test_ShakeHand : Test_Examine, waitSp);
  298. if (IS_FAILURED(ec))
  299. {
  300. THROW_ERROR("Try to %s for %s failed return %s!", bShake ? "check" : "test", lcpszEntityName, SpStrError(ec));
  301. return Error_Failed;
  302. }
  303. SetOPCallback(waitSp, lcpszEntityName, bShake ? OP_CHECK : OP_TEST);
  304. return Error_Succeed;
  305. }
  306. private:
  307. TestModeInfo _testInfo;
  308. CUUID m_subUUID;
  309. CAutoArray<CSimpleStringA> _arrTestEntities;
  310. DWORD _dwStartedTestEntities;
  311. CSystemRunInfo _runInfo;
  312. };
  313. SP_BEGIN_ENTITY_MAP()
  314. SP_ENTITY(CTestDeamon)
  315. SP_END_ENTITY_MAP()