From 7e77c01624fb625a256acbe2c5d2a8324c5b73a2 Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 20 Apr 2011 20:54:44 +0000 Subject: [PATCH] added print-cache code to the tests suite git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4163 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- .../src/tests/printcache/argstream.h | 814 ++++++++++++++++++ libretroshare/src/tests/printcache/main.cpp | 110 +++ .../src/tests/printcache/printcache.pro | 9 + 3 files changed, 933 insertions(+) create mode 100644 libretroshare/src/tests/printcache/argstream.h create mode 100644 libretroshare/src/tests/printcache/main.cpp create mode 100644 libretroshare/src/tests/printcache/printcache.pro diff --git a/libretroshare/src/tests/printcache/argstream.h b/libretroshare/src/tests/printcache/argstream.h new file mode 100644 index 000000000..137856794 --- /dev/null +++ b/libretroshare/src/tests/printcache/argstream.h @@ -0,0 +1,814 @@ +/* Copyright (C) 2004 Xavier Décoret +* + * argsteam is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Foobar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ARGSTREAM_H +#define ARGSTREAM_H + + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + class argstream; + + template + class ValueHolder; + + template + argstream& operator>> (argstream&, const ValueHolder&); + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // Interface of ValueHolder + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + template + class ValueHolder + { + public: + ValueHolder(char s, + const char* l, + T& b, + const char* desc, + bool mandatory); + ValueHolder(const char* l, + T& b, + const char* desc, + bool mandatory); + ValueHolder(char s, + T& b, + const char* desc, + bool mandatory); + friend argstream& operator>><>(argstream& s,const ValueHolder& v); + std::string name() const; + std::string description() const; + private: + std::string shortName_; + std::string longName_; + T* value_; + T initialValue_; + std::string description_; + bool mandatory_; + }; + template + inline ValueHolder + parameter(char s, + const char* l, + T& b, + const char* desc="", + bool mandatory = true) + { + return ValueHolder(s,l,b,desc,mandatory); + } + template + inline ValueHolder + parameter(char s, + T& b, + const char* desc="", + bool mandatory = true) + { + return ValueHolder(s,b,desc,mandatory); + } + template + inline ValueHolder + parameter(const char* l, + T& b, + const char* desc="", + bool mandatory = true) + { + return ValueHolder(l,b,desc,mandatory); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // Interface of OptionHolder + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + class OptionHolder + { + public: + inline OptionHolder(char s, + const char* l, + bool& b, + const char* desc); + inline OptionHolder(const char* l, + bool& b, + const char* desc); + inline OptionHolder(char s, + bool& b, + const char* desc); + friend argstream& operator>>(argstream& s,const OptionHolder& v); + inline std::string name() const; + inline std::string description() const; + protected: + inline OptionHolder(char s, + const char* l, + const char* desc); + friend OptionHolder help(char s='h', + const char* l="help", + const char* desc="Display this help"); + private: + std::string shortName_; + std::string longName_; + bool* value_; + std::string description_; + }; + inline OptionHolder + option(char s, + const char* l, + bool& b, + const char* desc="") + { + return OptionHolder(s,l,b,desc); + } + inline OptionHolder + option(char s, + bool& b, + const char* desc="") + { + return OptionHolder(s,b,desc); + } + inline OptionHolder + option(const char* l, + bool& b, + const char* desc="") + { + return OptionHolder(l,b,desc); + } + inline OptionHolder + help(char s, + const char* l, + const char* desc) + { + return OptionHolder(s,l,desc); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // Interface of ValuesHolder + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + template + class ValuesHolder + { + public: + ValuesHolder(const O& o, + const char* desc, + int len); + template friend argstream& operator>>(argstream& s,const ValuesHolder& v); + std::string name() const; + std::string description() const; + typedef T value_type; + private: + mutable O value_; + std::string description_; + int len_; + char letter_; + }; + template + inline ValuesHolder + values(const O& o, + const char* desc="", + int len=-1) + { + return ValuesHolder(o,desc,len); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // Interface of ValueParser + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + template + class ValueParser + { + public: + inline T operator()(const std::string& s) const + { + std::istringstream is(s); + T t; + is>>t; + return t; + } + }; + // We need to specialize for string otherwise parsing of a value that + // contains space (for example a string with space passed in quotes on the + // command line) would parse only the first element of the value!!! + template <> + class ValueParser + { + public: + inline std::string operator()(const std::string& s) const + { + return s; + } + }; + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // Interface of argstream + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + class argstream + { + public: + inline argstream(int argc,char** argv); + inline argstream(const char* c); + template + friend argstream& operator>>(argstream& s,const ValueHolder& v); + friend inline argstream& operator>>(argstream& s,const OptionHolder& v); + template + friend argstream& operator>>(argstream& s,const ValuesHolder& v); + + inline bool helpRequested() const; + inline bool isOk() const; + inline std::string errorLog() const; + inline std::string usage() const; + inline void defaultErrorHandling(bool ignoreUnused=false) const; + static inline char uniqueLetter(); + protected: + void parse(int argc,char** argv); + private: + typedef std::list::iterator value_iterator; + typedef std::pair help_entry; + std::string progName_; + std::map options_; + std::list values_; + bool minusActive_; + bool isOk_; + std::deque argHelps_; + std::string cmdLine_; + std::deque errors_; + bool helpRequested_; + }; + //************************************************************ + // Implementation of ValueHolder + //************************************************************ + template + ValueHolder::ValueHolder(char s, + const char* l, + T& v, + const char* desc, + bool mandatory) + : shortName_(1,s), + longName_(l), + value_(&v), + initialValue_(v), + description_(desc), + mandatory_(mandatory) + { + } + template + ValueHolder::ValueHolder(const char* l, + T& v, + const char* desc, + bool mandatory) + : longName_(l), + value_(&v), + initialValue_(v), + description_(desc), + mandatory_(mandatory) + { + } + template + ValueHolder::ValueHolder(char s, + T& v, + const char* desc, + bool mandatory) + : shortName_(1,s), + value_(&v), + initialValue_(v), + description_(desc), + mandatory_(mandatory) + { + } + template + std::string + ValueHolder::name() const + { + std::ostringstream os; + if (!shortName_.empty()) os<<'-'< + std::string + ValueHolder::description() const + { + std::ostringstream os; + os< + //************************************************************ + template + ValuesHolder::ValuesHolder(const O& o, + const char* desc, + int len) + : value_(o), + description_(desc), + len_(len) + { + letter_ = argstream::uniqueLetter(); + } + template + std::string + ValuesHolder::name() const + { + std::ostringstream os; + os< + std::string + ValuesHolder::description() const + { + return description_; + } + //************************************************************ + // Implementation of argstream + //************************************************************ + inline + argstream::argstream(int argc,char** argv) + : progName_(argv[0]), + minusActive_(true), + isOk_(true) + { + parse(argc,argv); + } + inline + argstream::argstream(const char* c) + : progName_(""), + minusActive_(true), + isOk_(true) + { + std::string s(c); + // Build argc, argv from s. We must add a dummy first element for + // progName because parse() expects it!! + std::deque args; + args.push_back(""); + std::istringstream is(s); + while (is.good()) + { + std::string t; + is>>t; + args.push_back(t); + } + char* pargs[args.size()]; + char** p = pargs; + for (std::deque::const_iterator + iter = args.begin(); + iter != args.end();++iter) + { + *p++ = const_cast(iter->c_str()); + } + parse(args.size(),pargs); + } + inline void + argstream::parse(int argc,char** argv) + { + // Run thru all arguments. + // * it has -- in front : it is a long name option, if remainder is empty, + // it is an error + // * it has - in front : it is a sequence of short name options, if + // remainder is empty, deactivates option (- will + // now be considered a char). + // * if any other char, or if option was deactivated + // : it is a value. Values are split in parameters + // (immediately follow an option) and pure values. + // Each time a value is parsed, if the previously parsed argument was an + // option, then the option is linked to the value in case of it is a + // option with parameter. The subtle point is that when several options + // are given with short names (ex: -abc equivalent to -a -b -c), the last + // parsed option is -c). + // Since we use map for option, any successive call overides the previous + // one: foo -a -b -a hello is equivalent to foo -b -a hello + // For values it is not true since we might have several times the same + // value. + value_iterator* lastOption = NULL; + for (char** a = argv,**astop=a+argc;++a!=astop;) + { + std::string s(*a); + if (minusActive_ && s[0] == '-') + { + if (s.size() > 1 && s[1] == '-') + { + if (s.size() == 2) + { + minusActive_ = false; + continue; + } + lastOption = &(options_[s.substr(2)] = values_.end()); + } + else + { + if (s.size() > 1) + { + // Parse all chars, if it is a minus we have an error + for (std::string::const_iterator cter = s.begin(); + ++cter != s.end();) + { + if (*cter == '-') + { + isOk_ = false; + std::ostringstream os; + os<<"- in the middle of a switch "<::const_iterator + iter = options_.begin();iter != options_.end();++iter) + { + std::cout<<"DEBUG: option "<first; + if (iter->second != values_.end()) + { + std::cout<<" -> "<<*(iter->second); + } + std::cout<::const_iterator + iter = values_.begin();iter != values_.end();++iter) + { + std::cout<<"DEBUG: value "<<*iter<::const_iterator + iter = argHelps_.begin();iter != argHelps_.end();++iter) + { + if (lmaxfirst.size()) lmax = iter->first.size(); + } + for (std::deque::const_iterator + iter = argHelps_.begin();iter != argHelps_.end();++iter) + { + os<<'\t'<first<first.size(),' ') + <<" : "<second<<'\n'; + } + return os.str(); + } + inline std::string + argstream::errorLog() const + { + std::string s; + for(std::deque::const_iterator iter = errors_.begin(); + iter != errors_.end();++iter) + { + s += *iter; + s += '\n'; + } + return s; + } + inline char + argstream::uniqueLetter() + { + static unsigned int c = 'a'; + return c++; + } + template + argstream& + operator>>(argstream& s,const ValueHolder& v) + { + // Search in the options if there is any such option defined either with a + // short name or a long name. If both are found, only the last one is + // used. +#ifdef ARGSTREAM_DEBUG + std::cout<<"DEBUG: searching "<::iterator iter = + s.options_.find(v.shortName_); + if (iter == s.options_.end()) + { + iter = s.options_.find(v.longName_); + } + if (iter != s.options_.end()) + { + // If we find counterpart for value holder on command line, either it + // has an associated value in which case we assign it, or it has not, in + // which case we have an error. + if (iter->second != s.values_.end()) + { +#ifdef ARGSTREAM_DEBUG + std::cout<<"DEBUG: found value "<<*(iter->second)< p; + *(v.value_) = p(*(iter->second)); + // The option and its associated value are removed, the subtle thing + // is that someother options might have this associated value too, + // which we must invalidate. + s.values_.erase(iter->second); + for (std::map::iterator + jter = s.options_.begin();jter != s.options_.end();++jter) + { + if (jter->second == iter->second) + { + jter->second = s.values_.end(); + } + } + s.options_.erase(iter); + } + else + { + s.isOk_ = false; + std::ostringstream os; + os<<"No value following switch "<first + <<" on command line"; + s.errors_.push_back(os.str()); + } + } + else + { + if (v.mandatory_) + { + s.isOk_ = false; + std::ostringstream os; + os<<"Mandatory parameter "; + if (!v.shortName_.empty()) os<<'-'<>(argstream& s,const OptionHolder& v) + { + // Search in the options if there is any such option defined either with a + // short name or a long name. If both are found, only the last one is + // used. +#ifdef ARGSTREAM_DEBUG + std::cout<<"DEBUG: searching "<::iterator iter = + s.options_.find(v.shortName_); + if (iter == s.options_.end()) + { + iter = s.options_.find(v.longName_); + } + if (iter != s.options_.end()) + { + // If we find counterpart for value holder on command line then the + // option is true and if an associated value was found, it is ignored + if (v.value_ != NULL) + { + *(v.value_) = true; + } + else + { + s.helpRequested_ = true; + } + // The option only is removed + s.options_.erase(iter); + } + else + { + if (v.value_ != NULL) + { + *(v.value_) = false; + } + else + { + s.helpRequested_ = false; + } + } + return s; + } + template + argstream& + operator>>(argstream& s,const ValuesHolder& v) + { + s.argHelps_.push_back(argstream::help_entry(v.name(),v.description())); + { + std::ostringstream os; + os<<' '<::iterator first = s.values_.begin(); + // We add to the iterator as much values as we can, limited to the length + // specified (if different of -1) + int n = v.len_ != -1?v.len_:s.values_.size(); + while (first != s.values_.end() && n-->0) + { + // Read the value from the string *first + ValueParser p; + *(v.value_++) = p(*first ); + s.argHelps_.push_back(argstream::help_entry(v.name(),v.description())); + // The value we just removed was maybe "remembered" by an option so we + // remove it now. + for (std::map::iterator + jter = s.options_.begin();jter != s.options_.end();++jter) + { + if (jter->second == first) + { + jter->second = s.values_.end(); + } + } + ++first; + } + // Check if we have enough values + if (n != 0) + { + s.isOk_ = false; + std::ostringstream os; + os<<"Expecting "< +#include +#include + +#include "argstream.h" +#include "pqi/pqistreamer.h" +#include "pqi/pqibin.h" +#include "serialiser/rsdistribitems.h" +#include "pqi/pqistore.h" + +int main(int argc, char **argv) +{ + try + { + argstream as(argc,argv) ; + bool full_print = false ; + + std::string cacheFileName; + + as >> parameter('f',"file",cacheFileName,"cache file name to read",true) + >> option('F',"full",full_print,"full dump of distrib items") + >> help() ; + + as.defaultErrorHandling() ; + + std::cout << "opening file: " << cacheFileName << std::endl; + // open file + BinInterface *bio = new BinFileInterface(cacheFileName.c_str(), BIN_FLAGS_READABLE); + RsSerialiser *rsSerialiser = new RsSerialiser(); + RsSerialType *serialType = new RsDistribSerialiser(); + rsSerialiser->addSerialType(serialType); + pqistore *store = new pqistore(rsSerialiser, "", bio, BIN_FLAGS_READABLE); + RsItem* item; + + std::set already ; + int signed_msgs = 0 ; + int distrib_msgs = 0 ; + int nb_duplicated = 0 ; + + // then print out contents to screen + while(NULL != (item = store->GetItem())) + { + + if(full_print) + item->print(std::cout, 0); + else + { + { + RsDistribMsg *i = dynamic_cast(item) ; + if(i!=NULL) + { + std::cerr << "Grp=" << i->grpId << ", parent=" << i->parentId << ", msgId=" << i->msgId ; + + if(already.find(i->msgId)!=already.end()) + { + std::cerr << " *** double ***" ; + ++nb_duplicated ; + } + else + already.insert(i->msgId) ; + + std::cerr << std::endl; + ++distrib_msgs ; + } + } + { + RsDistribSignedMsg *i = dynamic_cast(item) ; + if(i!=NULL) + { + std::cerr << "Grp=" << i->grpId << ", msgId=" << i->msgId << ", type=" << i->packet.tlvtype << ", len=" << i->packet.bin_len ; + + if(already.find(i->msgId)!=already.end()) + { + std::cerr << " *** double ***" ; + ++nb_duplicated ; + } + else + already.insert(i->msgId) ; + + std::cerr << std::endl; + + ++signed_msgs ; + } + } + } + } + + std::cerr << std::endl ; + std::cerr << "Signed messages (RsDistribMsg) : " << distrib_msgs << std::endl; + std::cerr << "Signed messages (RsDistribSignedMsg): " << signed_msgs << std::endl; + std::cerr << "Duplicate messages : " << nb_duplicated << std::endl; + + return 0; + } + catch(std::exception& e) + { + std::cerr << "Unhandled exception: " << e.what() << std::endl; + return 1 ; + } +} + + + diff --git a/libretroshare/src/tests/printcache/printcache.pro b/libretroshare/src/tests/printcache/printcache.pro new file mode 100644 index 000000000..4126e251d --- /dev/null +++ b/libretroshare/src/tests/printcache/printcache.pro @@ -0,0 +1,9 @@ +TEMPLATE = app +CONFIG = debug + +SOURCES = main.cpp + +INCLUDEPATH *= ../.. +LIBS = -lstdc++ -lm ../../lib/libretroshare.a ../../../../libbitdht/src/lib/libbitdht.a \ + -lssl -lcrypto -lgpgme -lupnp -lgnome-keyring +