Added rsshared ptr helper object (only use in test for memory management)

Added first nxs_test
modified pserviceserver to allow better dependency injection 

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@7279 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
chrisparker126 2014-04-18 21:58:14 +00:00
parent a929f80596
commit ef8f48ae73
17 changed files with 340 additions and 86 deletions

View File

@ -117,6 +117,8 @@ public:
public:
typedef std::map<RsNxsGrp*, RsGxsGrpMetaData*> GrpStoreMap;
RsGeneralDataService(){}
virtual ~RsGeneralDataService(){return;}

View File

@ -38,6 +38,7 @@
#include "rsgxsnetutils.h"
#include "pqi/p3cfgmgr.h"
#include "rsgixs.h"
#include "util/rssharedptr.h"
/// keep track of transaction number
typedef std::map<uint32_t, NxsTransaction*> TransactionIdMap;
@ -64,6 +65,8 @@ class RsGxsNetService : public RsNetworkExchangeService, public p3ThreadedServic
{
public:
typedef RsSharedPtr<RsGxsNetService> pointer;
static const uint32_t FRAGMENT_SIZE;
/*!
* only one observer is allowed

View File

@ -33,7 +33,7 @@ const int pqiservicezone = 60478;
* #define SERVICE_DEBUG 1
****/
void pqiService::setServiceServer(p3ServiceServer *server)
void pqiService::setServiceServer(p3ServiceServerIface *server)
{
mServiceServer = server;
}

View File

@ -55,7 +55,7 @@
// DataType is defined in the serialiser directory.
class RsRawItem;
class p3ServiceServer;
class p3ServiceServerIface;
class pqiService
@ -68,7 +68,7 @@ class pqiService
virtual ~pqiService() { return; }
public:
void setServiceServer(p3ServiceServer *server);
void setServiceServer(p3ServiceServerIface *server);
//
virtual bool recv(RsRawItem *) = 0;
virtual bool send(RsRawItem *item);
@ -78,7 +78,7 @@ virtual RsServiceInfo getServiceInfo() = 0;
virtual int tick() { return 0; }
private:
p3ServiceServer *mServiceServer; // const, no need for mutex.
p3ServiceServerIface *mServiceServer; // const, no need for mutex.
};
#include <map>
@ -89,7 +89,21 @@ virtual int tick() { return 0; }
* to the base level pqiPublisher instead.
*/
class p3ServiceServer
// use interface to allow DI
class p3ServiceServerIface
{
public:
virtual ~p3ServiceServerIface() {}
virtual bool recvItem(RsRawItem *) = 0;
virtual bool sendItem(RsRawItem *) = 0;
};
class p3ServiceServer : public p3ServiceServerIface
{
public:
p3ServiceServer(pqiPublisher *pub, p3ServiceControl *ctrl);
@ -100,6 +114,7 @@ bool recvItem(RsRawItem *);
bool sendItem(RsRawItem *);
int tick();
public:
private:

View File

@ -35,10 +35,16 @@
#include <string.h>
#include <stdint.h>
#include <util/rsrandom.h>
#include <vector>
#include <list>
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> class t_RsGenericIdType
{
public:
typedef std::list<t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER> > std_list;
typedef std::vector<t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER> > std_vector;
t_RsGenericIdType()
{
memset(bytes,0,ID_SIZE_IN_BYTES) ; // by default, ids are set to null()

View File

@ -1243,6 +1243,19 @@ std::ostream& RsNxsSyncMsgItem::print(std::ostream &out, uint16_t indent)
return out;
}
RsNxsGrp* RsNxsGrp::clone() const {
RsNxsGrp* grp = new RsNxsGrp(PacketService());
*grp = *this;
if(this->metaData)
{
grp->metaData = new RsGxsGrpMetaData();
*(grp->metaData) = *(this->metaData);
}
return grp;
}
std::ostream& RsNxsGrp::print(std::ostream &out, uint16_t indent){
printRsItemBase(out, "RsNxsGrp", indent);

View File

@ -200,6 +200,8 @@ public:
//std::cout << "\nGrp refcount-- : " << --refcount << std::endl;
}
RsNxsGrp* clone() const;
virtual void clear();
virtual std::ostream &print(std::ostream &out, uint16_t indent);

View File

@ -156,7 +156,7 @@ uint8_t RsItem::PacketType()
}
uint8_t RsItem::PacketSubType()
uint8_t RsItem::PacketSubType() const
{
return (type & 0xFF);
}
@ -170,7 +170,7 @@ RsItem::RsItem(uint8_t ver, uint16_t service, uint8_t subtype)
return;
}
uint16_t RsItem::PacketService()
uint16_t RsItem::PacketService() const
{
return (type >> 8) & 0xFFFF;
}

View File

@ -96,11 +96,11 @@ class RsItem: public RsMemoryManagement::SmallObject
uint8_t PacketVersion();
uint8_t PacketClass();
uint8_t PacketType();
uint8_t PacketSubType();
uint8_t PacketSubType() const;
/* For Service Packets */
RsItem(uint8_t ver, uint16_t service, uint8_t subtype);
uint16_t PacketService(); /* combined Packet class/type (mid 16bits) */
uint16_t PacketService() const; /* combined Packet class/type (mid 16bits) */
inline uint8_t priority_level() const { return _priority_level ;}
inline void setPriorityLevel(uint8_t l) { _priority_level = l ;}

View File

@ -0,0 +1,85 @@
/*
* rssharedptr.h
*
* Created on: 16 Apr 2014
* Author: crispy
*/
#ifndef RSSHAREDPTR_H_
#define RSSHAREDPTR_H_
#include <stdlib.h>
/*!
* Not thread safe!!
*/
template<class T>
class RsSharedPtr
{
public:
RsSharedPtr() : mShared(NULL), mCount(NULL) {}
RsSharedPtr(T* shared)
: mShared(shared), mCount(new int(0))
{
mCount++;
}
RsSharedPtr(const RsSharedPtr<T>& rsp)
{
mShared = rsp.mShared;
mCount = rsp.mCount;
mCount++;
}
void operator=(const RsSharedPtr<T>& rsp)
{
DecrementAndDeleteIfLast();
mShared = rsp.mShared;
RepointAndIncrement(rsp.mCount);
}
T* release() { mCount--; T* temp = mShared; mShared = NULL; return temp; }
T* get() { return mShared; }
T& operator*(){ return *mShared; }
T* operator->(){ return mShared; }
~RsSharedPtr()
{
DecrementAndDeleteIfLast();
}
private:
void DecrementAndDeleteIfLast()
{
mCount--;
if(mCount == 0 && mShared != NULL)
{
delete mShared;
delete mCount;
}
mShared = NULL;
mCount = NULL;
}
void RepointAndIncrement(int* count)
{
mCount = count;
mCount++;
}
private:
int* mCount;
T* mShared;
};
template<class T>
RsSharedPtr<T> rs_make_shared(T* ptr){ return RsSharedPtr<T>(ptr); }
#endif /* RSSHAREDPTR_H_ */

View File

@ -8,6 +8,13 @@
#ifndef NXSDUMMYSERVICES_H_
#define NXSDUMMYSERVICES_H_
#include <list>
#include <map>
#include <retroshare/rstypes.h>
#include <gxs/rsgixs.h>
#include <gxs/rsgxsnetutils.h>
#include <algorithm>
namespace rs_nxs_test
{
@ -30,7 +37,7 @@ namespace rs_nxs_test
* @param membership
* @param cached
*/
RsNxsSimpleDummyCircles(std::list<Membership>& membership, bool cached)
RsNxsSimpleDummyCircles(std::list<Membership>& membership, bool cached);
/* GXS Interface - for working out who can receive */
bool isLoaded(const RsGxsCircleId &circleId);
@ -83,19 +90,26 @@ namespace rs_nxs_test
public:
RsNxsNetDummyMgr(RsPeerId ownId, std::set<RsPeerId> peers) : mOwnId(ownId), mPeers(peers) {
RsNxsNetDummyMgr(const RsPeerId& ownId, const std::list<RsPeerId>& peers) : mOwnId(ownId), mPeers(peers) {
}
const RsPeerId& getOwnId() { return mOwnId; }
void getOnlineList(uint32_t serviceId, std::set<RsPeerId>& ssl_peers) { ssl_peers = mPeers; }
void getOnlineList(const uint32_t serviceId, std::set<RsPeerId>& ssl_peers)
{
RsPeerId::std_list::iterator lit = mPeers.begin();
for(; lit != mPeers.end(); lit++)
ssl_peers.insert(*lit);
}
private:
RsPeerId mOwnId;
std::set<RsPeerId> mPeers;
std::list<RsPeerId> mPeers;
};
}
#endif /* NXSDUMMYSERVICES_H_ */

View File

@ -9,13 +9,14 @@
#include "retroshare/rstypes.h"
#include "gxs/rsdataservice.h"
#include "nxsdummyservices.h"
#include "../common/data_support.h"
using namespace rs_nxs_test;
template<typename T>
void copy_all_but(T& ex, const std::list<T>& s, std::list<T> d)
void copy_all_but(T& ex, const std::list<T>& s, std::list<T>& d)
{
std::list<T>::const_iterator cit = s.begin();
typename std::list<T>::const_iterator cit = s.begin();
for(; cit != s.end(); cit++)
if(*cit != ex)
d.push_back(*cit);
@ -23,7 +24,6 @@ void copy_all_but(T& ex, const std::list<T>& s, std::list<T> d)
NxsGrpSync::NxsGrpSync()
{
// first choose ids
int numPeers = 2;
@ -40,21 +40,49 @@ NxsGrpSync::NxsGrpSync()
for(; it != mPeerIds.end(); it++)
{
// data stores
RsGeneralDataService* ds = new RsDataService("./", "grp_store" +
RsGeneralDataService* ds = new RsDataService("./", "grp_store_" +
it->toStdString(), mServType, NULL, "key");
mDataServices.insert(*it, ds);
mDataServices.insert(std::make_pair(*it, ds));
// net managers
std::list<RsPeerId> otherPeers;
copy_all_but<RsPeerId>(*it, mPeerIds, otherPeers);
RsNxsNetMgr* mgr = new RsNxsNetDummyMgr(*it, otherPeers);
RsNxsNetMgr* mgr = new rs_nxs_test::RsNxsNetDummyMgr(*it, otherPeers);
mNxsNetMgrs.insert(std::make_pair(*it, mgr));
RsNxsSimpleDummyReputation::RepMap reMap;
std::list<RsNxsSimpleDummyCircles::Membership> membership;
// now reputation service
mRep = new RsNxsSimpleDummyReputation();
mCircles = new RsNxsSimpleDummyCircles();
mRep = new RsNxsSimpleDummyReputation(reMap, true);
mCircles = new RsNxsSimpleDummyCircles(membership, true);
}
// lets create some a group each for all peers
DataMap::iterator mit = mDataServices.begin();
for(; mit != mDataServices.end(); mit++)
{
RsNxsGrp* grp = new RsNxsGrp(mServType);
init_item(*grp);
RsGxsGrpMetaData* meta = new RsGxsGrpMetaData();
init_item(meta);
grp->metaData = meta;
RsNxsGrp* grp_copy = grp->clone();
RsGeneralDataService::GrpStoreMap gsp;
gsp.insert(std::make_pair(grp, meta));
mit->second->storeGroup(gsp);
// the expected result is that each peer has the group of the others
it = mPeerIds.begin();
for(; it != mPeerIds.end(); it++)
{
if(mit->first != *it)
mExpectedResult[*it].push_back(grp_copy);
}
}
}
@ -72,8 +100,27 @@ RsGeneralDataService* NxsGrpSync::getDataService(const RsPeerId& peerId)
bool NxsGrpSync::checkTestPassed()
{
// look at data store of peer1 an compare to peer 2
return true;
// look at data store, as all peers should have same
// number of groups
DataMap::iterator mit = mDataServices.begin();
std::list<int> vals;
for(; mit != mDataServices.end(); mit++)
{
RsGxsGroupId::std_vector grpIds;
mit->second->retrieveGroupIds(grpIds);
vals.push_back(grpIds.size());
}
std::list<int>::iterator lit = vals.begin();
int prev = *lit;
bool passed = true;
for(; lit != vals.end(); lit++)
{
passed &= *lit == prev;
prev = *lit;
}
return passed;
}
RsNxsNetMgr* NxsGrpSync::getDummyNetManager(const RsPeerId& peerId)
@ -93,4 +140,23 @@ RsGixsReputation* NxsGrpSync::getDummyReputations(const RsPeerId& peerId)
uint16_t NxsGrpSync::getServiceType()
{
return mServType;
}
rs_nxs_test::NxsGrpSync::~NxsGrpSync()
{
// clean up data stores
DataMap::iterator mit = mDataServices.begin();
for(; mit != mDataServices.end(); mit++)
{
RsGxsGroupId::std_vector grpIds;
mit->second->resetDataStore();
std::string dbFile = "grp_store_" + mit->first.toStdString();
remove(dbFile.c_str());
}
}
RsServiceInfo rs_nxs_test::NxsGrpSync::getServiceInfo() {
return mServInfo;
}

View File

@ -11,30 +11,41 @@
#include "nxstestscenario.h"
class NxsGrpSync : public NxsTestScenario
namespace rs_nxs_test
{
public:
NxsGrpSync();
class NxsGrpSync : public NxsTestScenario
{
public:
void getPeers(std::list<RsPeerId>& peerIds);
RsGeneralDataService* getDataService(const RsPeerId& peerId);
bool checkTestPassed();
RsNxsNetMgr* getDummyNetManager(const RsPeerId& peerId);
RsGcxs* getDummyCircles(const RsPeerId& peerId);
RsGixsReputation* getDummyReputations(const RsPeerId& peerId);
uint16_t getServiceType();
NxsGrpSync();
~NxsGrpSync();
private:
void getPeers(std::list<RsPeerId>& peerIds);
RsGeneralDataService* getDataService(const RsPeerId& peerId);
bool checkTestPassed();
RsNxsNetMgr* getDummyNetManager(const RsPeerId& peerId);
RsGcxs* getDummyCircles(const RsPeerId& peerId);
RsGixsReputation* getDummyReputations(const RsPeerId& peerId);
uint16_t getServiceType();
RsServiceInfo getServiceInfo();
std::list<RsPeerId> mPeerIds;
std::map<RsPeerId, RsGeneralDataService*> mDataServices;
std::map<RsPeerId, RsNxsNetMgr*> mNxsNetMgrs;
RsGixsReputation* mRep;
RsGcxs* mCircles;
private:
int mServType;
};
std::list<RsPeerId> mPeerIds;
typedef std::map<RsPeerId, RsGeneralDataService*> DataMap;
typedef std::map<RsPeerId, std::list<RsNxsGrp*> > ExpectedMap;
DataMap mDataServices;
std::map<RsPeerId, RsNxsNetMgr*> mNxsNetMgrs;
RsGixsReputation* mRep;
RsGcxs* mCircles;
RsServiceInfo mServInfo;
ExpectedMap mExpectedResult;
uint16_t mServType;
};
}
#endif /* NXSGRPSYNC_TEST_H_ */

View File

@ -6,7 +6,7 @@ class NotifyWithPeerId : public RsNxsObserver
{
public:
NotifyWithPeerId(RsPeerId val, NxsTestHub& hub)
NotifyWithPeerId(RsPeerId val, rs_nxs_test::NxsTestHub& hub)
: mPeerId(val), mTestHub(hub){
}
@ -27,7 +27,29 @@ private:
rs_nxs_test::NxsTestHub& mTestHub;
};
rs_nxs_test::NxsTestHub::NxsTestHub(NxsTestScenario* testScenario)
using namespace rs_nxs_test;
class NxsTestHubConnection : public p3ServiceServerIface
{
public:
NxsTestHubConnection(const RsPeerId& id, RecvPeerItemIface* recvIface) : mPeerId(id), mRecvIface(recvIface) {}
bool recvItem(RsRawItem * i)
{
return mRecvIface->recvItem(i, mPeerId);
}
bool sendItem(RsRawItem * i)
{
return recvItem(i);
}
private:
RsPeerId mPeerId;
RecvPeerItemIface* mRecvIface;
};
rs_nxs_test::NxsTestHub::NxsTestHub(NxsTestScenario::pointer testScenario)
: mTestScenario(testScenario)
{
std::list<RsPeerId> peers;
@ -40,11 +62,21 @@ rs_nxs_test::NxsTestHub::NxsTestHub(NxsTestScenario* testScenario)
for(; cit != peers.end(); cit++)
{
RsGxsNetService* ns = new RsGxsNetService(mTestScenario->getServiceType(),
mTestScenario->getDataService(*cit), mTestScenario->getDummyNetManager(*cit),
RsGxsNetService::pointer ns = RsGxsNetService::pointer(
new RsGxsNetService(
mTestScenario->getServiceType(),
mTestScenario->getDataService(*cit),
mTestScenario->getDummyNetManager(*cit),
new NotifyWithPeerId(*cit, *this),
mTestScenario->getServiceInfo(), mTestScenario->getDummyReputations(*cit),
mTestScenario->getDummyCircles(*cit), true);
mTestScenario->getServiceInfo(),
mTestScenario->getDummyReputations(*cit),
mTestScenario->getDummyCircles(*cit), true
)
);
NxsTestHubConnection *connection =
new NxsTestHubConnection(*cit, this);
ns->setServiceServer(connection);
mPeerNxsMap.insert(std::make_pair(*cit, ns));
}
@ -118,11 +150,11 @@ void rs_nxs_test::NxsTestHub::notifyNewMessages(const RsPeerId& pid,
{
RsNxsMsg* msg = *it;
RsGxsMsgMetaData* meta = new RsGxsMsgMetaData();
bool ok = meta->deserialise(msg->meta.bin_data, msg->meta.bin_len);
bool ok = meta->deserialise(msg->meta.bin_data, &(msg->meta.bin_len));
toStore.insert(std::make_pair(msg, meta));
}
RsDataService* ds = mTestScenario->getDataService(pid);
RsGeneralDataService* ds = mTestScenario->getDataService(pid);
ds->storeMessage(toStore);
}
@ -139,55 +171,41 @@ void rs_nxs_test::NxsTestHub::notifyNewGroups(const RsPeerId& pid, std::vector<R
toStore.insert(std::make_pair(grp, meta));
}
RsDataService* ds = mTestScenario->getDataService(pid);
RsGeneralDataService* ds = mTestScenario->getDataService(pid);
ds->storeGroup(toStore);
}
void rs_nxs_test::NxsTestHub::Wait(int seconds) {
double dsecs = seconds;
#ifndef WINDOWS_SYS
usleep((int) (1000000));
usleep((int) (dsecs * 1000000));
#else
Sleep((int) (1000));
Sleep((int) (dsecs * 1000));
#endif
}
bool rs_nxs_test::NxsTestHub::recvItem(RsRawItem* item, const RsPeerId& peerFrom)
{
RsPeerId id = item->PeerId();
item->PeerId(peerFrom);
return mPeerNxsMap[id]->recv(item); //
}
void rs_nxs_test::NxsTestHub::tick()
{
// for each nxs instance pull out all items from each and then move to destination peer
typedef std::map<RsPeerId, std::list<RsItem*> > DestMap;
PeerNxsMap::iterator it = mPeerNxsMap.begin();
DestMap destMap;
for(; it != mPeerNxsMap.end(); it++)
{
RsGxsNetService* s = *it;
RsGxsNetService::pointer s = it->second;
s->tick();
RsItem* item = s->recvItem();
if(item != NULL)
destMap[item->PeerId()].push_back(item);
}
DestMap::iterator dit = destMap.begin();
for(; dit != destMap.end(); dit++ )
{
std::list<RsItem*> payload = dit->second;
const RsPeerId& pid = dit->first;
if(mPeerNxsMap.count(pid) > 0)
{
std::list<RsItem*>::iterator pit = payload.begin();
for(; pit != payload.end(); pit)
mPeerNxsMap[pid]->recvItem(*pit);
}
else
{
std::cerr << "Could not find peer: " << pid << std::endl;
}
}
}

View File

@ -15,6 +15,13 @@
namespace rs_nxs_test
{
class RecvPeerItemIface
{
public:
virtual ~RecvPeerItemIface(){}
virtual bool recvItem(RsRawItem *item, const RsPeerId& peerFrom) =0 ;
};
/*!
* Testing of nxs services occurs through use of two services
* When a service sends this class can interrogate the send and the receives of
@ -27,7 +34,7 @@ namespace rs_nxs_test
* and synchronise according to their subscriptions. The default is to subscribe to all groups held by other peer
* The threads for both net instances are started which begins their processing of transactions
*/
class NxsTestHub : public RsThread
class NxsTestHub : public RsThread, public RecvPeerItemIface
{
public:
@ -36,7 +43,7 @@ namespace rs_nxs_test
* This constructs the test hub
* for a give scenario in mind
*/
NxsTestHub(NxsTestScenario* testScenario);
NxsTestHub(NxsTestScenario::pointer testScenario);
/*!
* This cleans up what ever testing resources are left
@ -78,15 +85,20 @@ namespace rs_nxs_test
static void Wait(int seconds);
public:
bool recvItem(RsRawItem *item, const RsPeerId& peerFrom);
private:
void tick();
private:
typedef std::map<RsPeerId, RsGxsNetService* > PeerNxsMap ;
typedef std::map<RsPeerId, RsGxsNetService::pointer > PeerNxsMap ;
PeerNxsMap mPeerNxsMap;
NxsTestScenario *mTestScenario;
NxsTestScenario::pointer mTestScenario;
};
}

View File

@ -10,8 +10,10 @@
#include <map>
#include "retroshare/rstypes.h"
#include "gxs/rsgxsnetutils.h"
#include "gxs/rsdataservice.h"
#include "gxs/rsnxsobserver.h"
#include "util/rssharedptr.h"
namespace rs_nxs_test
{
@ -22,6 +24,8 @@ namespace rs_nxs_test
{
public:
typedef RsSharedPtr<NxsTestScenario> pointer;
virtual ~NxsTestScenario() {}
virtual void getPeers(std::list<RsPeerId>& peerIds) = 0;

View File

@ -10,13 +10,16 @@
#include "nxsgrpsync_test.h"
#include "nxstesthub.h"
TEST(libretroshare_gxs, gxs_grp_sync)
{
NxsGrpSync* gsync_test = new NxsGrpSync();
rs_nxs_test::NxsTestScenario::pointer gsync_test = rs_nxs_test::NxsTestScenario::pointer(
new rs_nxs_test::NxsGrpSync());
rs_nxs_test::NxsTestHub tHub(gsync_test);
tHub.StartTest();
rs_nxs_test::NxsTestHub::wait(10);
// wait for ten seconds
rs_nxs_test::NxsTestHub::Wait(10);
tHub.EndTest();
ASSERT_TRUE(tHub.testsPassed());