summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules/m_testnet.cpp163
1 files changed, 163 insertions, 0 deletions
diff --git a/src/modules/m_testnet.cpp b/src/modules/m_testnet.cpp
index e467923c9..ff37adf3c 100644
--- a/src/modules/m_testnet.cpp
+++ b/src/modules/m_testnet.cpp
@@ -15,6 +15,164 @@
#include "inspircd.h"
+struct vtbase
+{
+ virtual void isok(const char* name, int impl, Module* basemod, std::vector<std::string>& allmods) = 0;
+};
+
+template<typename T> struct vtable : public vtbase
+{
+ union u {
+ T function;
+ struct v {
+ size_t delta;
+ size_t vtoff;
+ } v;
+ } u;
+ vtable(T t) {
+ u.function = t;
+ }
+ /** member function pointer dereference from vtable; depends on the GCC 4.4 ABI (x86_64) */
+ template<typename E> void* read(E* obj)
+ {
+ if (u.v.delta & 1)
+ {
+ uint8_t* optr = reinterpret_cast<uint8_t*>(obj);
+ optr += u.v.vtoff;
+ uint8_t* vptr = *reinterpret_cast<uint8_t**>(optr);
+ vptr += u.v.delta - 1;
+ return *reinterpret_cast<void**>(vptr);
+ }
+ else
+ return reinterpret_cast<void*>(u.v.delta);
+ }
+ void isok(const char* name, int impl, Module* basemod, std::vector<std::string>& allmods)
+ {
+ void* base = read(basemod);
+ for(unsigned int i=0; i < allmods.size(); ++i)
+ {
+ Module* mod = ServerInstance->Modules->Find(allmods[i]);
+ void* fptr = read(mod);
+ for(EventHandlerIter j = ServerInstance->Modules->EventHandlers[impl].begin();
+ j != ServerInstance->Modules->EventHandlers[impl].end(); j++)
+ {
+ if (mod == *j)
+ {
+ if (fptr == base)
+ {
+ ServerInstance->SNO->WriteToSnoMask('a', "Module %s implements %s but uses default function",
+ mod->ModuleSourceFile.c_str(), name);
+ }
+ goto done;
+ }
+ }
+ if (fptr != base)
+ {
+ ServerInstance->SNO->WriteToSnoMask('a', "Module %s does not implement %s but overrides function",
+ mod->ModuleSourceFile.c_str(), name);
+ }
+ done:;
+ }
+ }
+};
+
+template<typename T> vtbase* vtinit(T t)
+{
+ return new vtable<T>(t);
+}
+
+static void checkall(Module* noimpl)
+{
+ std::vector<std::string> allmods = ServerInstance->Modules->GetAllModuleNames(0);
+#define CHK(name) do { \
+ vtbase* vt = vtinit(&Module::name); \
+ vt->isok(#name, I_ ## name, noimpl, allmods); \
+ delete vt; \
+} while (0)
+ CHK(OnUserConnect);
+ CHK(OnUserQuit);
+ CHK(OnUserDisconnect);
+ CHK(OnUserJoin);
+ CHK(OnUserPart);
+ CHK(OnRehash);
+ CHK(OnSendSnotice);
+ CHK(OnUserPreJoin);
+ CHK(OnUserPreKick);
+ CHK(OnUserKick);
+ CHK(OnOper);
+ CHK(OnInfo);
+ CHK(OnWhois);
+ CHK(OnUserPreInvite);
+ CHK(OnUserInvite);
+ CHK(OnUserPreMessage);
+ CHK(OnUserPreNotice);
+ CHK(OnUserPreNick);
+ CHK(OnUserMessage);
+ CHK(OnUserNotice);
+ CHK(OnMode);
+ CHK(OnGetServerDescription);
+ CHK(OnSyncUser);
+ CHK(OnSyncChannel);
+ CHK(OnDecodeMetaData);
+ CHK(OnWallops);
+ CHK(OnAcceptConnection);
+ CHK(OnChangeHost);
+ CHK(OnChangeName);
+ CHK(OnAddLine);
+ CHK(OnDelLine);
+ CHK(OnExpireLine);
+ CHK(OnUserPostNick);
+ CHK(OnPreMode);
+ CHK(On005Numeric);
+ CHK(OnKill);
+ CHK(OnRemoteKill);
+ CHK(OnLoadModule);
+ CHK(OnUnloadModule);
+ CHK(OnBackgroundTimer);
+ CHK(OnPreCommand);
+ CHK(OnCheckReady);
+ CHK(OnCheckInvite);
+ CHK(OnRawMode);
+ CHK(OnCheckKey);
+ CHK(OnCheckLimit);
+ CHK(OnCheckBan);
+ CHK(OnCheckChannelBan);
+ CHK(OnExtBanCheck);
+ CHK(OnStats);
+ CHK(OnChangeLocalUserHost);
+ CHK(OnPreTopicChange);
+ CHK(OnPostTopicChange);
+ CHK(OnEvent);
+ CHK(OnGlobalOper);
+ CHK(OnPostConnect);
+ CHK(OnAddBan);
+ CHK(OnDelBan);
+ CHK(OnChangeLocalUserGECOS);
+ CHK(OnUserRegister);
+ CHK(OnChannelPreDelete);
+ CHK(OnChannelDelete);
+ CHK(OnPostOper);
+ CHK(OnSyncNetwork);
+ CHK(OnSetAway);
+ CHK(OnUserList);
+ CHK(OnPostCommand);
+ CHK(OnPostJoin);
+ CHK(OnWhoisLine);
+ CHK(OnBuildNeighborList);
+ CHK(OnGarbageCollect);
+ CHK(OnText);
+ CHK(OnPassCompare);
+ CHK(OnRunTestSuite);
+ CHK(OnNamesListItem);
+ CHK(OnNumeric);
+ CHK(OnHookIO);
+ CHK(OnPreRehash);
+ CHK(OnModuleRehash);
+ CHK(OnSendWhoLine);
+ CHK(OnChangeIdent);
+ CHK(OnChannelRestrictionApply);
+}
+
class CommandTest : public Command
{
public:
@@ -41,6 +199,11 @@ class CommandTest : public Command
int i = parameters.size() > 1 ? atoi(parameters[1].c_str()) : 2;
ServerInstance->SE->Shutdown(IS_LOCAL(user)->GetFd(), i);
}
+ else if (parameters[0] == "check")
+ {
+ checkall(creator);
+ ServerInstance->SNO->WriteToSnoMask('a', "Module check complete");
+ }
return CMD_SUCCESS;
}
};