From: Marcin Siodelski Date: Wed, 16 May 2012 12:44:49 +0000 (+0200) Subject: [1954] Unit tests aded for 8 command line options as well as CommandOptions class... X-Git-Tag: trac2351_base~226^2~76^2~15 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b04764bc6d95ffa182555d626b2dee91344e958a;p=thirdparty%2Fkea.git [1954] Unit tests aded for 8 command line options as well as CommandOptions class members. --- diff --git a/tests/tools/perfdhcp/command_options.cc b/tests/tools/perfdhcp/command_options.cc index 0d61d461d5..4e6b17c52f 100644 --- a/tests/tools/perfdhcp/command_options.cc +++ b/tests/tools/perfdhcp/command_options.cc @@ -27,21 +27,65 @@ namespace perfdhcp { // Reset stored values to the defaults. void CommandOptions::reset() { + uint8_t mac[6] = { 0x0, 0xC, 0x1, 0x2, 0x3, 0x4 }; + double lt[2] = { 1., 1. }; + ipversion_ = 4; + exchange_mode_ = DORR_SARR; + rate_ = 0; + report_delay_ = 0; + random_range_ = 0; + max_random_ = 0; + mac_prefix_.assign(mac, mac+6); + base_.resize(0); + num_request_.resize(0); + period_ = 0; + lost_time_set_ = 0; + lost_time_.assign(lt, lt+2); + max_drop_set_ = 0; + max_drop_.push_back(0); + max_drop_.push_back(0); + max_pdrop_.push_back(0.); + max_pdrop_.push_back(0.); + localname_.resize(0); + is_interface_ = false; + preload_ = 0; + aggressivity_ = 1; + local_port_ = 0; + seeded_ = false; + seed_ = 0; + broadcast_ = false; + rapid_commit_ = false; + use_first_ = false; + template_file_.resize(0); + xid_offset_.resize(0); + rnd_offset_.resize(0); + elp_offset_ = -1; + sid_offset_ = -1; + rip_offset_ = -1; + diags_.resize(0); + wrapped_.resize(0); + server_name_.resize(0); } -/// Parses the command-line options and records the results. -void -CommandOptions::parse(int argc, char* const argv[]) { +int +CommandOptions::parse(int argc, char** argv, bool force_reset /*=false */) { int ch; - - while((ch = getopt(argc, argv, ":h")) != -1) { + if (force_reset) { + reset(); + } + // Reset internal variable used by getopt to index elements + optind = 1; + while((ch = getopt(argc, argv, "hv46r:t:R:b:n:p:d:D:l:P:a:L:s:iBc1T:X:O:E:S:I:x:w:")) != -1) { switch (ch) { case 'h': - default: usage(); + break; + default: + ; } } + return(0); } void diff --git a/tests/tools/perfdhcp/command_options.h b/tests/tools/perfdhcp/command_options.h index 36bc1a3605..8f3043bc1d 100644 --- a/tests/tools/perfdhcp/command_options.h +++ b/tests/tools/perfdhcp/command_options.h @@ -15,6 +15,9 @@ #ifndef __COMMAND_OPTIONS_H #define __COMMAND_OPTIONS_H +#include +#include + namespace isc { namespace perfdhcp { @@ -25,6 +28,10 @@ namespace perfdhcp { /// class CommandOptions { public: + enum ExchangeMode { + DO_SA, + DORR_SARR + }; /// \brief Default Constructor /// @@ -44,20 +51,212 @@ public: /// /// \param argc Argument count passed to main(). /// \param argv Argument value array passed to main(). - void parse(int argc, char* const argv[]); + /// \param force_reset Force reset of state variables + /// return non-zero value if parse failed + int parse(int argc, char** argv, bool force_reset = false); /// \brief Returns IP version /// /// \return IP version to be used uint8_t getIpVersion() const { return ipversion_; } + /// \brief Returns packet exchange mode + /// + /// \return packet exchange mode + ExchangeMode getExchangeMode() const { return exchange_mode_; } + + /// \brief Returns echange rate + /// + /// \return exchange rate per second + int getRate() const { return rate_; } + + /// \brief Returns report delay + /// + /// \return delay between two consecutive reports + int getReportDelay() const { return report_delay_; } + + /// \brief Returns randomization range + /// + /// \return randomization range + uint32_t getRandomRange() const { return random_range_; } + + /// \brief Returns MAC addr prefix + /// + /// \ return MAC addr prefix to generate different clients + std::vector getMacPrefix() const { return mac_prefix_; } + + /// \brief Returns DUID prefix + /// + /// \return DUID prefix to generate different clients + std::vector getDuidPrefix() const { return duid_prefix_; } + + /// \brief Returns base values + /// + /// \return base values for xid generation + std::vector getBase() const { return base_; } + + /// \brief Returns number of exchanges + /// + /// \return number of exchange requests + std::vector getNumRequests() const { return num_request_; } + + /// \brief Returns test period + /// + /// \return test period + int getPeriod() const { return period_; } + + /// \brief Returns lost time + /// + /// \return return time before request is lost + std::vector getLostTime() const { return lost_time_; } + + /// \brief Returns max drops number + /// + /// \return maximum number of lost requests + std::vector getMaxDrop() const { return max_drop_; } + + /// \brief Returns max percentage of drops + /// + /// \return maximum percentage of lost requests + std::vector getMaxDropPercentage() const { return max_pdrop_; } + + /// \brief Returns local address or interface + /// + /// \return local address or interface + std::string getLocalName() const { return localname_; } + + /// \brief Checks if interface name is used + /// + /// \return true if interface name was specified + bool isInterface() const { return is_interface_; } + + /// \brief Returns number of preload exchanges + /// + /// \return number of preload exchanges + int getPreload() const { return preload_; } + + /// \brief Returns aggressivity value + /// + /// \return aggressivity value + int getAggressivity() const { return aggressivity_; } + + /// \brief Returns local port number + /// + /// \return local port number + int getLocalPort() const { return local_port_; } + + /// \brief Checks if seed provided + /// + /// \return true if seed was provided + bool isSeeded() const { return seeded_; } + + /// \brief Returns radom seed + /// + /// \return random seed + uint32_t getSeed() const { return seed_; } + + /// \brief Checks if broadcast + /// + /// \return true if broadcast handling + bool isBroadcast() const { return broadcast_; } + + /// \brief Check if rapid commit used + /// + /// \return true if rapid commit is used + bool isRapidCommit() const { return rapid_commit_; } + + /// \brief Check if server-ID taken from first package + /// + /// \return true if server-iD to be taken from first package + bool isUseFirst() const { return use_first_; } + + /// \brief Returns template file names + /// + /// \return template file names + std::vector getTemplateFiles() const { return template_file_; } + + /// brief Returns template offsets for xid + /// + /// \return template offsets for xid + std::vector getXidOffset() const { return xid_offset_; } + + /// \brief Returns template offsets for rnd + /// + /// \return template offsets for rnd + std::vector getRndOffset() const { return rnd_offset_; } + + /// \brief Returns template offset for elapsed time + /// + /// \return template offset for elapsed time + int getElpOffset() const { return elp_offset_; } + + /// \brief Returns template offset for server-ID + /// + /// \return template offset for server-ID + int getSidOffset() const { return sid_offset_; } + + /// \brief Returns template offset for requested IP + /// + /// \return template offset for requested IP + int getRipOffset() const { return elp_offset_; } + + /// \brief Returns diagnostic selectors + /// + /// \return diagnostic selector + std::string getDiags() const { return diags_; } + + /// \brief Returns wrapped command + /// + /// \return wrapped command + std::string getWrapped() const { return wrapped_; } + + /// \brief Returns server name + /// + /// \return server name + std::string getServerName() const { return server_name_; } + /// \brief Print usage /// /// Prints perfdhcp usage void usage(void); private: - uint8_t ipversion_; + uint8_t ipversion_; ///< IP version + ExchangeMode exchange_mode_ ; ///< Packet exchange mode (e.g. DORR/SARR) + int rate_; ///< rate in exchange per second + int report_delay_; ///< delay between two reports + uint32_t random_range_; ///< randomization range + uint32_t max_random_; ///< maximum random value + std::vector mac_prefix_; ///< MAC addr prefix + std::vector duid_prefix_; ///< DUID prefix + std::vector base_; ///< base values for xid + std::vector num_request_; ///< number of exchanges + int period_; ///< test period + int lost_time_set_; ///< losttime[0] was set + std::vector lost_time_; ///< time before a request is lost + int max_drop_set_; ///< max{p}drop[0] was set + std::vector max_drop_; ///< maximum number of lost requests + std::vector max_pdrop_; ///< maximum percentage + std::string localname_; ///< local address or interface + bool is_interface_; ///< interface vs local address + int preload_; ///< preload exchanges + int aggressivity_; ///< back to back exchanges + int local_port_; ///< local port number (host endian) + bool seeded_; ///< is a seed provided + uint32_t seed_; ///< randomization seed + bool broadcast_; ///< use broadcast + bool rapid_commit_; ///< add rapid commit option + bool use_first_; ///< where to take the server-ID + std::vector template_file_; ///< template file name + std::vector xid_offset_; ///< template offsets (xid)*/ + std::vector rnd_offset_; ///< template offsets (random) + int elp_offset_; ///< template offset (elapsed time) + int sid_offset_; ///< template offset (server ID) + int rip_offset_; ///< template offset (requested IP) + std::string diags_; ///< diagnostic selectors + std::string wrapped_; ///< wrapped command + std::string server_name_; ///< server + }; diff --git a/tests/tools/perfdhcp/tests/command_options_unittest.cc b/tests/tools/perfdhcp/tests/command_options_unittest.cc index f54d22a042..d155ef4419 100644 --- a/tests/tools/perfdhcp/tests/command_options_unittest.cc +++ b/tests/tools/perfdhcp/tests/command_options_unittest.cc @@ -30,13 +30,164 @@ class CommandOptionsTest : public virtual ::testing::Test, public virtual CommandOptions { public: - /// \brief Default Constructor CommandOptionsTest() : CommandOptions() { } +protected: + + /// \brief Parse command line and cleanup + /// + /// Tokenizes command line to array of C-strings, + /// parses arguments and de-allocates C-strings + /// + /// \param s Command line to parse + /// \return non-zero if parsing failed + int process(const std::string& s) { + int argc = 0; + char** argv = tokenizeString(s, &argc); + int r = parse(argc, argv, true); + for(int i = 0; i < argc; ++i) { + free(argv[i]); + argv[i] = NULL; + } + free(argv); + return (r); + } + + /// \brief Check initialized values + /// + /// Check if initialized values are correct + void checkDefaults() { + EXPECT_EQ(4, getIpVersion()); + EXPECT_EQ(DORR_SARR, getExchangeMode()); + EXPECT_EQ(0, getRate()); + EXPECT_EQ(0, getReportDelay()); + EXPECT_EQ(0, getRandomRange()); + // EXPECT_EQ(0, max_random_); + // TODO MAC and DUID checks + EXPECT_EQ(0, getBase().size()); + EXPECT_EQ(0, getNumRequests().size()); + EXPECT_EQ(0, getPeriod()); + for (int i = 0; i < getLostTime().size(); ++i) { + EXPECT_DOUBLE_EQ(1, getLostTime()[i]); + } + ASSERT_EQ(getMaxDrop().size(), getMaxDropPercentage().size()); + for (int i = 0; i < getMaxDrop().size(); ++i) { + EXPECT_EQ(0, getMaxDrop()[i]); + EXPECT_EQ(0, getMaxDropPercentage()[i]); + } + EXPECT_EQ("", getLocalName()); + EXPECT_FALSE(isInterface()); + EXPECT_EQ(0, getPreload()); + EXPECT_EQ(1, getAggressivity()); + EXPECT_EQ(0, getLocalPort()); + EXPECT_FALSE(isSeeded()); + EXPECT_EQ(0, getSeed()); + EXPECT_FALSE(isBroadcast()); + EXPECT_FALSE(isRapidCommit()); + EXPECT_FALSE(isUseFirst()); + EXPECT_EQ(0, getTemplateFiles().size()); + EXPECT_EQ(0, getXidOffset().size()); + EXPECT_EQ(0, getRndOffset().size()); + EXPECT_GT(0, getElpOffset()); + EXPECT_GT(0, getSidOffset()); + EXPECT_GT(0, getRipOffset()); + EXPECT_EQ("", getDiags()); + EXPECT_EQ("", getWrapped()); + EXPECT_EQ("", getServerName()); + } + + /// \brief Split string to array of C-strings + /// + /// \param s String to split (tokenize) + /// \param num Number of tokens returned + /// \return array of C-strings (tokens) + char** tokenizeString(const std::string& s, int* num) const { + char** results = NULL; + std::stringstream ss(s); + std::istream_iterator sit(ss); + std::istream_iterator send; + std::vector tokens(sit, send); + + if (tokens.size() > 0) { + results = static_cast(malloc(tokens.size() * sizeof(char*))); + if (results == NULL) { + throw std::bad_alloc(); + } + for (int i = 0; i < tokens.size(); ++i) { + char* cs = static_cast(malloc(tokens[i].length() + 1)); + strcpy(cs, tokens[i].c_str()); + results[i] = cs; + } + if (num != NULL) { + *num = tokens.size(); + } + } + + return results; + } + }; -TEST_F(CommandOptionsTest, defaults) { - EXPECT_EQ(4, getIpVersion()); +TEST_F(CommandOptionsTest, Defaults) { + process("perfdhcp"); + checkDefaults(); +} + +TEST_F(CommandOptionsTest, IpVersion) { + process("perfdhcp -6 -l ethx"); + EXPECT_EQ(6, getIpVersion()); + EXPECT_EQ("ethx", getLocalName()); } +TEST_F(CommandOptionsTest, Rate) { + process("perfdhcp -4 -r 10 -l ethx"); + EXPECT_EQ(10, getRate()); + EXPECT_NE(0, process("perfdhcp -4 -r 0 -l ethx")); + EXPECT_NE(0, process("perfdhcp -6 -t 5 -l ethx")); + EXPECT_NE(0, process("perfdhcp -4 -n 150 -l ethx")); + EXPECT_NE(0, process("perfdhcp -6 -p 120 -l ethx")); + EXPECT_NE(0, process("perfdhcp -4 -D 1400 -l ethx")); +} + +TEST_F(CommandOptionsTest, ReportDelay) { + process("perfdhcp -r 100 -t 17 -l ethx"); + EXPECT_EQ(17, getReportDelay()); +} + +TEST_F(CommandOptionsTest, RandomRange) { + process("perfdhcp -l ethx"); + EXPECT_EQ(200, getRandomRange()); +} + +TEST_F(CommandOptionsTest, Base) { + process("perfdhcp -6 -b MAC=10:20:30:40:50:60 -l ethx"); + uint8_t mac[6] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }; + std::vector v(mac, mac+6); + EXPECT_EQ(v, getMacPrefix()); + // TODO - test for DUID +} + +TEST_F(CommandOptionsTest, DropTime) { + process("perfdhcp -l ethx -d 12"); + ASSERT_EQ(2, getLostTime().size()); + EXPECT_DOUBLE_EQ(12, getLostTime()[0]); + EXPECT_DOUBLE_EQ(1, getLostTime()[1]); + + process("perfdhcp -l ethx -d 2 -d 4.7"); + ASSERT_EQ(2, getLostTime().size()); + EXPECT_DOUBLE_EQ(2, getLostTime()[0]); + EXPECT_DOUBLE_EQ(4.7, getLostTime()[1]); +} + +TEST_F(CommandOptionsTest, TimeOffset) { + process("perfdhcp -l ethx -E 4"); + ASSERT_EQ(5, getElpOffset()); + ASSERT_NE(0, process("perfdhcp -l ethx -E -3")); + ASSERT_NE(0, process("perfdhcp -l ethx -E 3 -i")); +} + +TEST_F(CommandOptionsTest, ExchangeMode) { + process("perfdhcp -i -l ethx"); + ASSERT_EQ(DO_SA, getExchangeMode()); +}