test_control_unittest.cc 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604
  1. // Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include "command_options_helper.h"
  15. #include "../test_control.h"
  16. #include <asiolink/io_address.h>
  17. #include <exceptions/exceptions.h>
  18. #include <dhcp/dhcp4.h>
  19. #include <dhcp/iface_mgr.h>
  20. #include <boost/date_time/posix_time/posix_time.hpp>
  21. #include <cstddef>
  22. #include <stdint.h>
  23. #include <string>
  24. #include <fstream>
  25. #include <gtest/gtest.h>
  26. using namespace std;
  27. using namespace boost::posix_time;
  28. using namespace isc;
  29. using namespace isc::dhcp;
  30. using namespace isc::perfdhcp;
  31. /// \brief Test Control class with protected members made public.
  32. ///
  33. /// This class makes protected TestControl class'es member public
  34. /// to allow unit testing.
  35. class NakedTestControl: public TestControl {
  36. public:
  37. /// \brief Incremental transaction id generator.
  38. ///
  39. /// This is incremental transaction id generator. It overrides
  40. /// the default transaction id generator that generates transaction
  41. /// ids using random function. This generator will generate values
  42. /// like: 1,2,3 etc.
  43. class IncrementalGenerator : public TestControl::NumberGenerator {
  44. public:
  45. /// \brief Default constructor.
  46. IncrementalGenerator() :
  47. NumberGenerator(),
  48. transid_(0) {
  49. }
  50. /// \brief Generate unique transaction id.
  51. ///
  52. /// Generate unique transaction ids incrementally:
  53. /// 1,2,3,4 etc.
  54. ///
  55. /// \return generated transaction id.
  56. virtual uint32_t generate() {
  57. return (++transid_);
  58. }
  59. /// \brief Return next transaction id value.
  60. uint32_t getNext() const {
  61. return (transid_ + 1);
  62. }
  63. private:
  64. uint32_t transid_; ///< Last generated transaction id.
  65. };
  66. /// \brief Sets the due times for sedning Solicit, Renew and Release.
  67. ///
  68. /// There are three class members that hold the due time for sending DHCP
  69. /// messages:
  70. /// - send_due_ - due time to send Solicit,
  71. /// - renew_due_ - due time to send Renew,
  72. /// - release_due_ - due time to send Release.
  73. /// Some tests in this test suite need to modify these values relative to
  74. /// the current time. This function modifies this values using time
  75. /// offset values (positive or negative) specified as a difference in
  76. /// seconds between current time and the due time.
  77. ///
  78. /// \param send_secs An offset of the due time for Solicit.
  79. /// \param renew_secs An offset of the due time for Renew.
  80. /// \param release_secs An offset of the due time for Release.
  81. void setRelativeDueTimes(const int send_secs, const int renew_secs = 0,
  82. const int release_secs = 0) {
  83. ptime now = microsec_clock::universal_time();
  84. basic_rate_control_.setRelativeDue(send_secs);
  85. renew_rate_control_.setRelativeDue(renew_secs);
  86. release_rate_control_.setRelativeDue(release_secs);
  87. }
  88. using TestControl::checkExitConditions;
  89. using TestControl::createMessageFromReply;
  90. using TestControl::factoryElapsedTime6;
  91. using TestControl::factoryGeneric;
  92. using TestControl::factoryIana6;
  93. using TestControl::factoryOptionRequestOption6;
  94. using TestControl::factoryRapidCommit6;
  95. using TestControl::factoryRequestList4;
  96. using TestControl::generateDuid;
  97. using TestControl::generateMacAddress;
  98. using TestControl::getCurrentTimeout;
  99. using TestControl::getTemplateBuffer;
  100. using TestControl::initPacketTemplates;
  101. using TestControl::initializeStatsMgr;
  102. using TestControl::openSocket;
  103. using TestControl::processReceivedPacket4;
  104. using TestControl::processReceivedPacket6;
  105. using TestControl::registerOptionFactories;
  106. using TestControl::reset;
  107. using TestControl::sendDiscover4;
  108. using TestControl::sendPackets;
  109. using TestControl::sendMultipleMessages6;
  110. using TestControl::sendRequest6;
  111. using TestControl::sendSolicit6;
  112. using TestControl::setDefaults4;
  113. using TestControl::setDefaults6;
  114. using TestControl::basic_rate_control_;
  115. using TestControl::renew_rate_control_;
  116. using TestControl::release_rate_control_;
  117. using TestControl::last_report_;
  118. using TestControl::transid_gen_;
  119. using TestControl::macaddr_gen_;
  120. using TestControl::first_packet_serverid_;
  121. using TestControl::interrupted_;
  122. NakedTestControl() : TestControl() {
  123. uint32_t clients_num = CommandOptions::instance().getClientsNum() == 0 ?
  124. 1 : CommandOptions::instance().getClientsNum();
  125. setMacAddrGenerator(NumberGeneratorPtr(new TestControl::SequentialGenerator(clients_num)));
  126. };
  127. };
  128. /// \brief Test Fixture Class
  129. ///
  130. /// This test fixture class is used to perform
  131. /// unit tests on perfdhcp TestControl class.
  132. class TestControlTest : public virtual ::testing::Test
  133. {
  134. public:
  135. typedef std::vector<uint8_t> MacAddress;
  136. typedef MacAddress::iterator MacAddressIterator;
  137. typedef std::vector<uint8_t> Duid;
  138. typedef Duid::iterator DuidIterator;
  139. /// \brief Default Constructor
  140. TestControlTest() { }
  141. /// \brief Create packet template file from binary data.
  142. ///
  143. /// Function creates file containing data from the provided buffer
  144. /// in hexadecimal format. The size parameter specifies the maximum
  145. /// size of the file. If total number of hexadecimal digits resulting
  146. /// from buffer size is greater than maximum file size the file is
  147. /// truncated.
  148. ///
  149. /// \param filename template file to be created.
  150. /// \param buffer with binary data to be stored in file.
  151. /// \param size target size of the file.
  152. /// \param invalid_chars inject invalid chars to the template file.
  153. /// \return true if file creation successful.
  154. bool createTemplateFile(const std::string& filename,
  155. const std::vector<uint8_t>& buf,
  156. const size_t size,
  157. const bool invalid_chars = false) const {
  158. std::ofstream temp_file;
  159. temp_file.open(filename.c_str(), ios::out | ios::trunc);
  160. if (!temp_file.is_open()) {
  161. return (false);
  162. }
  163. for (int i = 0; i < buf.size(); ++i) {
  164. int first_digit = buf[i] / 16;
  165. int second_digit = buf[i] % 16;
  166. // Insert two spaces between two hexadecimal digits.
  167. // Spaces are allowed in template files.
  168. temp_file << std::string(2, ' ');
  169. if (2 * i + 1 < size) {
  170. if (!invalid_chars) {
  171. temp_file << std::hex << first_digit << second_digit << std::dec;
  172. } else {
  173. temp_file << "XY";
  174. }
  175. } else if (2 * i < size) {
  176. if (!invalid_chars) {
  177. temp_file << std::hex << first_digit;
  178. } else {
  179. temp_file << "X";
  180. }
  181. } else {
  182. break;
  183. }
  184. }
  185. temp_file.close();
  186. return (true);
  187. }
  188. /// \brief Get local loopback interface name.
  189. ///
  190. /// Scan available network interfaces for local loopback
  191. /// interface and get its name. On Linux this interface is
  192. /// usually called 'lo' but on other systems, e.g. BSD
  193. /// it will have slightly different name. Local loopback
  194. /// interface is required for unit tests that require
  195. /// socket creation.
  196. ///
  197. /// \return local loopback interface name.
  198. std::string getLocalLoopback() const {
  199. const IfaceMgr::IfaceCollection& ifaces =
  200. IfaceMgr::instance().getIfaces();
  201. for (IfaceMgr::IfaceCollection::const_iterator iface = ifaces.begin();
  202. iface != ifaces.end();
  203. ++iface) {
  204. if (iface->flag_loopback_) {
  205. return (iface->getName());
  206. }
  207. }
  208. return ("");
  209. }
  210. /// \brief Get full path to a file in testdata directory.
  211. ///
  212. /// \param filename filename being appended to absolute
  213. /// path to testdata directory
  214. ///
  215. /// \return full path to a file in testdata directory.
  216. std::string getFullPath(const std::string& filename) const {
  217. std::ostringstream stream;
  218. stream << TEST_DATA_DIR << "/" << filename;
  219. return (stream.str());
  220. }
  221. /// \brief Match requested options in the buffer with given list.
  222. ///
  223. /// This method iterates through options provided in the buffer
  224. /// and matches them with the options specified with first parameter.
  225. /// Options in both vectors may be laid in different order.
  226. ///
  227. /// \param requested_options reference buffer with options.
  228. /// \param buf test buffer with options that will be matched.
  229. /// \return number of options from the buffer matched with options
  230. /// in the reference buffer.
  231. int matchRequestedOptions(const dhcp::OptionBuffer& requested_options,
  232. const dhcp::OptionBuffer& buf) const {
  233. size_t matched_num = 0;
  234. for (size_t i = 0; i < buf.size(); ++i) {
  235. for (int j = 0; j < requested_options.size(); ++j) {
  236. if (requested_options[j] == buf[i]) {
  237. // Requested option has been found.
  238. ++matched_num;
  239. }
  240. }
  241. }
  242. return (matched_num);
  243. }
  244. /// \brief Match requested DHCPv6 options in the buffer with given list.
  245. ///
  246. /// This method iterates through options provided in the buffer and
  247. /// matches them with the options specified with first parameter.
  248. /// Options in both vectors ma be laid in different order.
  249. ///
  250. /// \param requested_options reference buffer with options.
  251. /// \param buf test buffer with options that will be matched.
  252. /// \return number of options from the buffer matched with options in
  253. /// the reference buffer or -1 if error occured.
  254. int matchRequestedOptions6(const dhcp::OptionBuffer& requested_options,
  255. const dhcp::OptionBuffer& buf) const {
  256. // Sanity check.
  257. if ((requested_options.size() % 2 != 0) ||
  258. (buf.size() % 2 != 0)) {
  259. return -1;
  260. }
  261. size_t matched_num = 0;
  262. for (size_t i = 0; i < buf.size(); i += 2) {
  263. for (int j = 0; j < requested_options.size(); j += 2) {
  264. uint16_t opt_i = (buf[i + 1] << 8) + (buf[i] & 0xFF);
  265. uint16_t opt_j = (requested_options[j + 1] << 8)
  266. + (requested_options[j] & 0xFF);
  267. if (opt_i == opt_j) {
  268. // Requested option has been found.
  269. ++matched_num;
  270. }
  271. }
  272. }
  273. return (matched_num);
  274. }
  275. /// \brief Calculate the maximum vectors' mismatch position.
  276. ///
  277. /// This helper function calculates the maximum mismatch position
  278. /// between two vectors (two different DUIDs or MAC addresses).
  279. /// Calculated position is counted from the end of vectors.
  280. /// Calculation is based on number of simulated clients. When number
  281. /// of clients is less than 256 different DUIDs or MAC addresses can
  282. /// can be coded in such a way that they differ on last vector element.
  283. /// If number of clients is between 257 and 65536 they can differ
  284. /// on two last positions so the returned value will be 2 and so on.
  285. ///
  286. /// \param clients_num number of simulated clients
  287. /// \return maximum mismatch position
  288. int unequalOctetPosition(int clients_num) const {
  289. if (!clients_num) {
  290. return (0);
  291. }
  292. clients_num--;
  293. int cnt = 0;
  294. while (clients_num) {
  295. clients_num >>= 8;
  296. ++cnt;
  297. }
  298. return (cnt);
  299. }
  300. /// \brief Test generation of mulitple DUIDs
  301. ///
  302. /// This method checks the generation of multiple DUIDs. Number
  303. /// of iterations depends on the number of simulated clients.
  304. /// It is expected that DUID's size is 14 (consists of DUID-LLT
  305. /// HW type field, 4 octets of time value and MAC address). The
  306. /// MAC address can be randomized depending on the number of
  307. /// simulated clients. The DUID-LLT and HW type are expected to
  308. /// be constant. The time value has to be properly calculated
  309. /// as the number of seconds since DUID time epoch. The parts
  310. /// of MAC address has to change if multiple clients are simulated
  311. /// and do not change if single client is simulated.
  312. void testDuid() const {
  313. int clients_num = CommandOptions::instance().getClientsNum();
  314. // Initialize Test Control class.
  315. NakedTestControl tc;
  316. // The old duid will be holding the previously generated DUID.
  317. // It will be used to compare against the new one. If we have
  318. // multiple clients we want to make sure that duids differ.
  319. uint8_t randomized = 0;
  320. Duid old_duid(tc.generateDuid(randomized));
  321. Duid new_duid(0);
  322. // total_dist shows the total difference between generated duid.
  323. // It has to be greater than zero if multiple clients are simulated.
  324. size_t total_dist = 0;
  325. // Number of unique DUIDs.
  326. size_t unique_duids = 0;
  327. // Holds the position if the octet on which two DUIDS can be different.
  328. // If number of clients is 256 or less it is last DUID octet (except for
  329. // single client when subsequent DUIDs have to be equal). If number of
  330. // clients is between 257 and 65536 the last two octets can differ etc.
  331. int unequal_pos = unequalOctetPosition(clients_num);
  332. // Keep generated DUIDs in this container.
  333. std::list<std::vector<uint8_t> > duids;
  334. // Perform number of iterations to generate number of DUIDs.
  335. for (int i = 0; i < 10 * clients_num; ++i) {
  336. if (new_duid.empty()) {
  337. new_duid = old_duid;
  338. } else {
  339. std::swap(old_duid, new_duid);
  340. new_duid = tc.generateDuid(randomized);
  341. }
  342. // The DUID-LLT is expected to start with DUID_LLT value
  343. // of 1 and hardware ethernet type equal to 1 (HWETHER_TYPE).
  344. const uint8_t duid_llt_and_hw[4] = { 0x0, 0x1, 0x0, 0x1 };
  345. // We assume DUID-LLT length 14. This includes 4 octets of
  346. // DUID_LLT value, two octets of hardware type, 4 octets
  347. // of time value and 6 octets of variable link layer (MAC)
  348. // address.
  349. const int duid_llt_size = 14;
  350. ASSERT_EQ(duid_llt_size, new_duid.size());
  351. // The first four octets do not change.
  352. EXPECT_TRUE(std::equal(new_duid.begin(), new_duid.begin() + 4,
  353. duid_llt_and_hw));
  354. // As described in RFC3315: 'the time value is the time
  355. // that the DUID is generated represented in seconds
  356. // since midnight (UTC), January 1, 2000, modulo 2^32.'
  357. uint32_t duid_time = 0;
  358. // Pick 4 bytes of the time from generated DUID and put them
  359. // in reverse order (in DUID they are stored in network order).
  360. for (int j = 4; j < 8; ++j) {
  361. duid_time |= new_duid[j] << (j - 4);
  362. }
  363. // Calculate the duration since epoch time.
  364. ptime now = microsec_clock::universal_time();
  365. ptime duid_epoch(from_iso_string("20000101T000000"));
  366. time_period period(duid_epoch, now);
  367. // Current time is the same or later than time from the DUID because
  368. // DUID had been generated before reference duration was calculated.
  369. EXPECT_GE(period.length().total_seconds(), duid_time);
  370. // Get the mismatch position (counting from the end) of
  371. // mismatched octet between previously generated DUID
  372. // and current.
  373. std::pair<DuidIterator, DuidIterator> mismatch_pos =
  374. std::mismatch(old_duid.begin(), old_duid.end(),
  375. new_duid.begin());
  376. size_t mismatch_dist =
  377. std::distance(mismatch_pos.first, old_duid.end());
  378. // For single client total_dist is expected to be 0 because
  379. // old_duid and new_duid should always match. If we have
  380. // more clients then duids have to differ except the case
  381. // if randomization algorithm generates the same values but
  382. // this would be an error in randomization algorithm.
  383. total_dist += mismatch_dist;
  384. // Mismatch may have occured on the DUID octet position
  385. // up to calculated earlier unequal_pos.
  386. ASSERT_LE(mismatch_dist, unequal_pos);
  387. // unique will inform if tested DUID is unique.
  388. bool unique = true;
  389. for (std::list<std::vector<uint8_t> >::const_iterator it =
  390. duids.begin();
  391. it != duids.end(); ++it) {
  392. // DUIDs should be of the same size if we want to compare them.
  393. ASSERT_EQ(new_duid.size(), it->size());
  394. // Check if DUID is unique.
  395. if (std::equal(new_duid.begin(), new_duid.end(), it->begin())) {
  396. unique = false;
  397. }
  398. }
  399. // Expecting that DUIDs will be unique only when
  400. // first clients-num iterations is performed.
  401. // After that, DUIDs become non unique.
  402. if (unique) {
  403. ++unique_duids;
  404. }
  405. // For number of iterations equal to clients_num,2*clients_num
  406. // 3*clients_num ... we have to have number of unique duids
  407. // equal to clients_num.
  408. if ((i != 0) && (i % clients_num == 0)) {
  409. ASSERT_EQ(clients_num, unique_duids);
  410. }
  411. // Remember generated DUID.
  412. duids.push_back(new_duid);
  413. }
  414. // If we have more than one client at least one mismatch occured.
  415. if (clients_num < 2) {
  416. EXPECT_EQ(0, total_dist);
  417. }
  418. }
  419. /// \brief Test DHCPv4 exchanges.
  420. ///
  421. /// Function simulates DHCPv4 exchanges. Function caller specifies
  422. /// number of exchanges to be simulated and number of simulated
  423. /// responses. When number of responses is lower than number of
  424. /// iterations than the difference between them is the number
  425. /// of simulated packet drops. This is useful to test if program
  426. /// exit conditions are handled properly (maximum number of packet
  427. /// drops specified as -D<max-drops> is taken into account).
  428. ///
  429. /// \param iterations_num number of exchanges to simulate.
  430. /// \param receive_num number of received OFFER packets.
  431. /// \param iterations_performed actual number of iterations.
  432. void testPkt4Exchange(int iterations_num,
  433. int receive_num,
  434. bool use_templates,
  435. int& iterations_performed) const {
  436. int sock_handle = 0;
  437. NakedTestControl tc;
  438. tc.initializeStatsMgr();
  439. // Use templates files to crate packets.
  440. if (use_templates) {
  441. tc.initPacketTemplates();
  442. ASSERT_NO_THROW(tc.getTemplateBuffer(0));
  443. ASSERT_NO_THROW(tc.getTemplateBuffer(1));
  444. }
  445. // Incremental transaction id generator will generate
  446. // predictable values of transaction id for each iteration.
  447. // This is important because we need to simulate responses
  448. // from the server and use the same transaction ids as in
  449. // packets sent by client.
  450. TestControl::NumberGeneratorPtr
  451. generator(new NakedTestControl::IncrementalGenerator());
  452. tc.setTransidGenerator(generator);
  453. // Socket is needed to send packets through the interface.
  454. ASSERT_NO_THROW(sock_handle = tc.openSocket());
  455. TestControl::TestControlSocket sock(sock_handle);
  456. uint32_t transid = 0;
  457. for (int i = 0; i < iterations_num; ++i) {
  458. if (use_templates) {
  459. ASSERT_NO_THROW(tc.sendDiscover4(sock, tc.getTemplateBuffer(0)));
  460. } else {
  461. ASSERT_NO_THROW(tc.sendDiscover4(sock));
  462. }
  463. ++transid;
  464. // Do not simulate responses for packets later
  465. // that specified as receive_num. This simulates
  466. // packet drops.
  467. if (i < receive_num) {
  468. boost::shared_ptr<Pkt4> offer_pkt4(createOfferPkt4(transid));
  469. ASSERT_NO_THROW(tc.processReceivedPacket4(sock, offer_pkt4));
  470. ++transid;
  471. }
  472. if (tc.checkExitConditions()) {
  473. iterations_performed = i + 1;
  474. break;
  475. }
  476. iterations_performed = i + 1;
  477. }
  478. }
  479. /// \brief Test DHCPv6 exchanges.
  480. ///
  481. /// Function simulates DHCPv6 exchanges. Function caller specifies
  482. /// number of exchanges to be simulated and number of simulated
  483. /// responses. When number of responses is lower than number of
  484. /// iterations than the difference between them is the number
  485. /// of simulated packet drops. This is useful to test if program
  486. /// exit conditions are handled properly (maximum number of packet
  487. /// drops specified as -D<max-drops> is taken into account).
  488. ///
  489. /// \param iterations_num number of exchanges to simulate.
  490. /// \param receive_num number of received OFFER packets.
  491. /// \param iterations_performed actual number of iterations.
  492. void testPkt6Exchange(int iterations_num,
  493. int receive_num,
  494. bool use_templates,
  495. int& iterations_performed) const {
  496. int sock_handle = 0;
  497. NakedTestControl tc;
  498. tc.initializeStatsMgr();
  499. // Use templates files to crate packets.
  500. if (use_templates) {
  501. tc.initPacketTemplates();
  502. ASSERT_NO_THROW(tc.getTemplateBuffer(0));
  503. ASSERT_NO_THROW(tc.getTemplateBuffer(1));
  504. }
  505. // Incremental transaction id generator will generate
  506. // predictable values of transaction id for each iteration.
  507. // This is important because we need to simulate responses
  508. // from the server and use the same transaction ids as in
  509. // packets sent by client.
  510. TestControl::NumberGeneratorPtr
  511. generator(new NakedTestControl::IncrementalGenerator());
  512. tc.setTransidGenerator(generator);
  513. // Socket is needed to send packets through the interface.
  514. ASSERT_NO_THROW(sock_handle = tc.openSocket());
  515. TestControl::TestControlSocket sock(sock_handle);
  516. uint32_t transid = 0;
  517. for (int i = 0; i < iterations_num; ++i) {
  518. // Do not simulate responses for packets later
  519. // that specified as receive_num. This simulates
  520. // packet drops.
  521. if (use_templates) {
  522. ASSERT_NO_THROW(tc.sendSolicit6(sock, tc.getTemplateBuffer(0)));
  523. } else {
  524. ASSERT_NO_THROW(tc.sendSolicit6(sock));
  525. }
  526. ++transid;
  527. if (i < receive_num) {
  528. boost::shared_ptr<Pkt6>
  529. advertise_pkt6(createAdvertisePkt6(transid));
  530. // Receive ADVERTISE and send REQUEST.
  531. ASSERT_NO_THROW(tc.processReceivedPacket6(sock,
  532. advertise_pkt6));
  533. ++transid;
  534. }
  535. if (tc.checkExitConditions()) {
  536. iterations_performed = i + 1;
  537. break;
  538. }
  539. iterations_performed = i + 1;
  540. }
  541. }
  542. /// \brief Test generation of multiple MAC addresses.
  543. ///
  544. /// This method validates generation of multiple MAC addresses.
  545. /// The MAC address can be randomized depending on the number
  546. /// of simulated clients. This test checks if different MAC
  547. /// addresses are generated if number of simulated clients is
  548. /// greater than 1. It also checks if the same MAC addresses is
  549. /// generated if only 1 client is simulated.
  550. void testMacAddress() const {
  551. int clients_num = CommandOptions::instance().getClientsNum();
  552. // The old_mac will be holding the value of previously generated
  553. // MAC address. We will be comparing the newly generated one with it
  554. // to see if it changes when mulitple clients are simulated or if it
  555. // does not change when single client is simulated.
  556. MacAddress old_mac(CommandOptions::instance().getMacTemplate());
  557. // Holds the position if the octet on which two MAC addresses can
  558. // be different. If number of clients is 256 or less it is last MAC
  559. // octet (except for single client when subsequent MAC addresses
  560. // have to be equal). If number of clients is between 257 and 65536
  561. // the last two octets can differ etc.
  562. int unequal_pos = unequalOctetPosition(clients_num);
  563. // Number of unique MACs.
  564. size_t unique_macs = 0;
  565. // Initialize Test Controller.
  566. NakedTestControl tc;
  567. size_t total_dist = 0;
  568. // Keep generated MACs in this container.
  569. std::list<std::vector<uint8_t> > macs;
  570. // Do many iterations to generate and test MAC address values.
  571. for (int i = 0; i < clients_num * 10; ++i) {
  572. // Generate new MAC address.
  573. uint8_t randomized = 0;
  574. MacAddress new_mac(tc.generateMacAddress(randomized));
  575. // Get the mismatch position (counting from the end) of
  576. // mismatched octet between previously generated MAC address
  577. // and current.
  578. std::pair<MacAddressIterator, MacAddressIterator> mismatch_pos =
  579. std::mismatch(old_mac.begin(), old_mac.end(), new_mac.begin());
  580. size_t mismatch_dist =
  581. std::distance(mismatch_pos.first, old_mac.end());
  582. // For single client total_dist is expected to be 0 because
  583. // old_mac and new_mac should always match. If we have
  584. // more clients then MAC addresses have to differ except
  585. // the case if randomization algorithm generates the same
  586. // values but this would be an error in randomization algorithm.
  587. total_dist += mismatch_dist;
  588. // Mismatch may have occured on the MAC address'es octet position
  589. // up to calculated earlier unequal_pos.
  590. ASSERT_LE(mismatch_dist, unequal_pos);
  591. // unique will inform if tested DUID is unique.
  592. bool unique = true;
  593. for (std::list<std::vector<uint8_t> >::const_iterator it =
  594. macs.begin();
  595. it != macs.end(); ++it) {
  596. // MACs should be of the same size if we want to compare them.
  597. ASSERT_EQ(new_mac.size(), it->size());
  598. // Check if MAC is unique.
  599. if (std::equal(new_mac.begin(), new_mac.end(), it->begin())) {
  600. unique = false;
  601. }
  602. }
  603. // Expecting that MACs will be unique only when
  604. // first clients-num iterations is performed.
  605. // After that, MACs become non unique.
  606. if (unique) {
  607. ++unique_macs;
  608. }
  609. // For number of iterations equal to clients_num,2*clients_num
  610. // 3*clients_num ... we have to have number of unique MACs
  611. // equal to clients_num.
  612. if ((i != 0) && (i % clients_num == 0)) {
  613. ASSERT_EQ(clients_num, unique_macs);
  614. }
  615. // Remember generated MAC.
  616. macs.push_back(new_mac);
  617. }
  618. if (clients_num < 2) {
  619. EXPECT_EQ(total_dist, 0);
  620. }
  621. }
  622. /// \brief Test that the DHCPv4 Release or Renew message is created
  623. /// correctly and comprises expected options.
  624. ///
  625. /// \param msg_type A type of the message to be tested: DHCPV6_RELEASE
  626. /// or DHCPV6_RENEW.
  627. void testCreateRenewRelease(const uint16_t msg_type) {
  628. // This command line specifies that the Release/Renew messages should
  629. // be sent with the same rate as the Solicit messages.
  630. std::ostringstream s;
  631. s << "perfdhcp -6 -l lo -r 10 ";
  632. s << (msg_type == DHCPV6_RELEASE ? "-F" : "-f") << " 10 ";
  633. s << "-R 10 -L 10547 -n 10 -e address-and-prefix ::1";
  634. ASSERT_NO_THROW(processCmdLine(s.str()));
  635. // Create a test controller class.
  636. NakedTestControl tc;
  637. // Set the transaction id generator which will be used by the
  638. // createRenew or createRelease function to generate transaction id.
  639. boost::shared_ptr<NakedTestControl::IncrementalGenerator>
  640. generator(new NakedTestControl::IncrementalGenerator());
  641. tc.setTransidGenerator(generator);
  642. // Create a Reply packet. The createRelease or createReply function will
  643. // need Reply packet to create a corresponding Release or Reply.
  644. Pkt6Ptr reply = createReplyPkt6(1);
  645. Pkt6Ptr msg;
  646. // Check that the message is created.
  647. ASSERT_NO_THROW(msg = tc.createMessageFromReply(msg_type, reply));
  648. ASSERT_TRUE(msg);
  649. // Check that the message type and transaction id is correct.
  650. EXPECT_EQ(msg_type, msg->getType());
  651. EXPECT_EQ(1, msg->getTransid());
  652. // Check that the message has expected options. These are the same for
  653. // Release and Renew.
  654. // Client Identifier.
  655. OptionPtr opt_clientid = msg->getOption(D6O_CLIENTID);
  656. ASSERT_TRUE(opt_clientid);
  657. EXPECT_TRUE(reply->getOption(D6O_CLIENTID)->getData() ==
  658. opt_clientid->getData());
  659. // Server identifier
  660. OptionPtr opt_serverid = msg->getOption(D6O_SERVERID);
  661. ASSERT_TRUE(opt_serverid);
  662. EXPECT_TRUE(reply->getOption(D6O_SERVERID)->getData() ==
  663. opt_serverid->getData());
  664. // IA_NA
  665. OptionPtr opt_ia_na = msg->getOption(D6O_IA_NA);
  666. ASSERT_TRUE(opt_ia_na);
  667. EXPECT_TRUE(reply->getOption(D6O_IA_NA)->getData() ==
  668. opt_ia_na->getData());
  669. // IA_PD
  670. OptionPtr opt_ia_pd = msg->getOption(D6O_IA_PD);
  671. ASSERT_TRUE(opt_ia_pd);
  672. EXPECT_TRUE(reply->getOption(D6O_IA_PD)->getData() ==
  673. opt_ia_pd->getData());
  674. // Make sure that exception is thrown if the Reply message is NULL.
  675. EXPECT_THROW(tc.createMessageFromReply(msg_type, Pkt6Ptr()),
  676. isc::BadValue);
  677. }
  678. /// \brief Test sending DHCPv6 Releases or Renews.
  679. ///
  680. /// This function simulates acquiring 10 leases from the server. Returned
  681. /// Reply messages are cached and used to send Renew or Release messages.
  682. /// The maxmimal number of Renew or Release messages which can be sent is
  683. /// equal to the number of leases acquired (10). This function also checks
  684. /// that an attempt to send more Renew or Release messages than the number
  685. /// of leases acquired will fail.
  686. ///
  687. /// \param msg_type A type of the message which is simulated to be sent
  688. /// (DHCPV6_RENEW or DHCPV6_RELEASE).
  689. void testSendRenewRelease(const uint16_t msg_type) {
  690. std::string loopback_iface(getLocalLoopback());
  691. if (loopback_iface.empty()) {
  692. std::cout << "Skipping the test because loopback interface could"
  693. " not be detected" << std::endl;
  694. return;
  695. }
  696. // Build a command line. Depending on the message type, we will use
  697. // -f<renew-rate> or -F<release-rate> parameter.
  698. std::ostringstream s;
  699. s << "perfdhcp -6 -l " << loopback_iface << " -r 10 ";
  700. s << (msg_type == DHCPV6_RENEW ? "-f" : "-F");
  701. s << " 10 -R 10 -L 10547 -n 10 ::1";
  702. ASSERT_NO_THROW(processCmdLine(s.str()));
  703. // Create a test controller class.
  704. NakedTestControl tc;
  705. tc.initializeStatsMgr();
  706. // Set the transaction id generator to sequential to control to
  707. // guarantee that transaction ids are predictable.
  708. boost::shared_ptr<NakedTestControl::IncrementalGenerator>
  709. generator(new NakedTestControl::IncrementalGenerator());
  710. tc.setTransidGenerator(generator);
  711. // Socket has to be created so as we can actually send packets.
  712. int sock_handle = 0;
  713. ASSERT_NO_THROW(sock_handle = tc.openSocket());
  714. TestControl::TestControlSocket sock(sock_handle);
  715. // Send a number of Solicit messages. Each generated Solicit will be
  716. // assigned a different transaction id, starting from 1 to 10.
  717. tc.sendPackets(sock, 10);
  718. // Simulate Advertise responses from the server. Each advertise is
  719. // assigned a transaction id from the range of 1 to 10, so as they
  720. // match the transaction ids from the Solicit messages.
  721. for (int i = generator->getNext() - 10; i < generator->getNext(); ++i) {
  722. Pkt6Ptr advertise(createAdvertisePkt6(i));
  723. // If Advertise is matched with the Solicit the call below will
  724. // trigger a corresponding Request. They will be assigned
  725. // transaction ids from the range from 11 to 20 (the range of
  726. // 1 to 10 has been used by Solicit-Advertise).
  727. ASSERT_NO_THROW(tc.processReceivedPacket6(sock, advertise));
  728. }
  729. // Requests have been sent, so now let's simulate responses from the
  730. // server. Generate corresponding Reply messages with the transaction
  731. // ids from the range from 11 to 20.
  732. for (int i = generator->getNext() - 10; i < generator->getNext(); ++i) {
  733. Pkt6Ptr reply(createReplyPkt6(i));
  734. // Each Reply packet corresponds to the new lease acquired. Since
  735. // -f<renew-rate> option has been specified, received Reply
  736. // messages are held so as Renew messages can be sent for
  737. // existing leases.
  738. ASSERT_NO_THROW(tc.processReceivedPacket6(sock, reply));
  739. }
  740. uint64_t msg_num;
  741. // Try to send 5 messages. It should be successful because 10 Reply
  742. // messages has been received. For each of them we should be able to
  743. // send Renew or Release.
  744. ASSERT_NO_THROW(
  745. msg_num = tc.sendMultipleMessages6(sock, msg_type, 5)
  746. );
  747. // Make sure that we have sent 5 messages.
  748. EXPECT_EQ(5, msg_num);
  749. // Try to do it again. We should still have 5 Reply packets for
  750. // which Renews or Releases haven't been sent yet.
  751. ASSERT_NO_THROW(
  752. msg_num = tc.sendMultipleMessages6(sock, msg_type, 5)
  753. );
  754. EXPECT_EQ(5, msg_num);
  755. // We used all the Reply packets (we sent Renew or Release for each of
  756. // them already). Therefore, no further Renew or Release messages should
  757. // be sent before we acquire new leases.
  758. ASSERT_NO_THROW(
  759. msg_num = tc.sendMultipleMessages6(sock, msg_type, 5)
  760. );
  761. // Make sure that no message has been sent.
  762. EXPECT_EQ(0, msg_num);
  763. }
  764. /// \brief Parse command line string with CommandOptions.
  765. ///
  766. /// \param cmdline command line string to be parsed.
  767. /// \throw isc::Unexpected if unexpected error occured.
  768. /// \throw isc::InvalidParameter if command line is invalid.
  769. void processCmdLine(const std::string& cmdline) const {
  770. CommandOptionsHelper::process(cmdline);
  771. }
  772. /// \brief Create DHCPv4 OFFER packet.
  773. ///
  774. /// \param transid transaction id.
  775. /// \return instance of the packet.
  776. boost::shared_ptr<Pkt4>
  777. createOfferPkt4(uint32_t transid) const {
  778. boost::shared_ptr<Pkt4> offer(new Pkt4(DHCPOFFER, transid));
  779. OptionPtr opt_serverid = Option::factory(Option::V4,
  780. DHO_DHCP_SERVER_IDENTIFIER,
  781. OptionBuffer(4, 1));
  782. offer->setYiaddr(asiolink::IOAddress("127.0.0.1"));
  783. offer->addOption(opt_serverid);
  784. offer->updateTimestamp();
  785. return (offer);
  786. }
  787. /// \brief Create DHCPv6 ADVERTISE packet.
  788. ///
  789. /// \param transid transaction id.
  790. /// \return instance of the packet.
  791. Pkt6Ptr
  792. createAdvertisePkt6(const uint32_t transid) const {
  793. boost::shared_ptr<Pkt6> advertise(new Pkt6(DHCPV6_ADVERTISE, transid));
  794. // Add IA_NA if requested by the client.
  795. if (CommandOptions::instance().getLeaseType()
  796. .includes(CommandOptions::LeaseType::ADDRESS)) {
  797. OptionPtr opt_ia_na = Option::factory(Option::V6, D6O_IA_NA);
  798. advertise->addOption(opt_ia_na);
  799. }
  800. // Add IA_PD if requested by the client.
  801. if (CommandOptions::instance().getLeaseType()
  802. .includes(CommandOptions::LeaseType::PREFIX)) {
  803. OptionPtr opt_ia_pd = Option::factory(Option::V6, D6O_IA_PD);
  804. advertise->addOption(opt_ia_pd);
  805. }
  806. OptionPtr opt_serverid(new Option(Option::V6, D6O_SERVERID));
  807. NakedTestControl tc;
  808. uint8_t randomized = 0;
  809. std::vector<uint8_t> duid(tc.generateDuid(randomized));
  810. OptionPtr opt_clientid(Option::factory(Option::V6, D6O_CLIENTID, duid));
  811. advertise->addOption(opt_serverid);
  812. advertise->addOption(opt_clientid);
  813. advertise->updateTimestamp();
  814. return (advertise);
  815. }
  816. Pkt6Ptr
  817. createReplyPkt6(const uint32_t transid) const {
  818. Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, transid));
  819. // Add IA_NA if requested by the client.
  820. if (CommandOptions::instance().getLeaseType()
  821. .includes(CommandOptions::LeaseType::ADDRESS)) {
  822. OptionPtr opt_ia_na = Option::factory(Option::V6, D6O_IA_NA);
  823. reply->addOption(opt_ia_na);
  824. }
  825. // Add IA_PD if requested by the client.
  826. if (CommandOptions::instance().getLeaseType()
  827. .includes(CommandOptions::LeaseType::PREFIX)) {
  828. OptionPtr opt_ia_pd = Option::factory(Option::V6, D6O_IA_PD);
  829. reply->addOption(opt_ia_pd);
  830. }
  831. OptionPtr opt_serverid(new Option(Option::V6, D6O_SERVERID));
  832. NakedTestControl tc;
  833. uint8_t randomized = 0;
  834. std::vector<uint8_t> duid(tc.generateDuid(randomized));
  835. OptionPtr opt_clientid(Option::factory(Option::V6, D6O_CLIENTID, duid));
  836. reply->addOption(opt_serverid);
  837. reply->addOption(opt_clientid);
  838. reply->updateTimestamp();
  839. return (reply);
  840. }
  841. };
  842. // This test verifies that the class members are reset to expected values.
  843. TEST_F(TestControlTest, reset) {
  844. ASSERT_NO_THROW(processCmdLine("perfdhcp -6 -l ethx -r 50 -f 30 -F 10 -a 3 all"));
  845. NakedTestControl tc;
  846. tc.reset();
  847. EXPECT_EQ(3, tc.basic_rate_control_.getAggressivity());
  848. EXPECT_EQ(3, tc.renew_rate_control_.getAggressivity());
  849. EXPECT_EQ(3, tc.release_rate_control_.getAggressivity());
  850. EXPECT_EQ(50, tc.basic_rate_control_.getRate());
  851. EXPECT_EQ(30, tc.renew_rate_control_.getRate());
  852. EXPECT_EQ(10, tc.release_rate_control_.getRate());
  853. EXPECT_FALSE(tc.last_report_.is_not_a_date_time());
  854. EXPECT_FALSE(tc.transid_gen_);
  855. EXPECT_FALSE(tc.macaddr_gen_);
  856. EXPECT_TRUE(tc.first_packet_serverid_.empty());
  857. EXPECT_FALSE(tc.interrupted_);
  858. }
  859. TEST_F(TestControlTest, GenerateDuid) {
  860. // Simple command line that simulates one client only. Always the
  861. // same DUID will be generated.
  862. ASSERT_NO_THROW(processCmdLine("perfdhcp -l 127.0.0.1 all"));
  863. testDuid();
  864. // Simulate 50 clients. Different DUID will be generated.
  865. ASSERT_NO_THROW(processCmdLine("perfdhcp -l 127.0.0.1 -R 50 all"));
  866. testDuid();
  867. }
  868. TEST_F(TestControlTest, MisMatchVerionServer) {
  869. NakedTestControl tc;
  870. // make sure we catch -6 paired with v4 address
  871. ASSERT_NO_THROW(processCmdLine("perfdhcp -l 127.0.0.1 -6 192.168.1.1"));
  872. EXPECT_THROW(tc.openSocket(), isc::InvalidParameter);
  873. // make sure we catch -4 paired with v6 address
  874. ASSERT_NO_THROW(processCmdLine("perfdhcp -l 127.0.0.1 -4 ff02::1:2"));
  875. EXPECT_THROW(tc.openSocket(), isc::InvalidParameter);
  876. }
  877. TEST_F(TestControlTest, GenerateMacAddress) {
  878. // Simulate one client only. Always the same MAC address will be
  879. // generated.
  880. ASSERT_NO_THROW(processCmdLine("perfdhcp -l 127.0.0.1 all"));
  881. testMacAddress();
  882. // Simulate 50 clients. Different MAC addresses will be generated.
  883. ASSERT_NO_THROW(processCmdLine("perfdhcp -l 127.0.0.1 -R 50 all"));
  884. testMacAddress();
  885. }
  886. TEST_F(TestControlTest, Options4) {
  887. using namespace isc::dhcp;
  888. NakedTestControl tc;
  889. // By default the IP version mode is V4 so there is no need to
  890. // parse command line to override the IP version. Note that
  891. // registerOptionFactories is used for both V4 and V6.
  892. tc.registerOptionFactories();
  893. // Create option with buffer size equal to 1 and holding DHCPDISCOVER
  894. // message type.
  895. OptionPtr opt_msg_type(Option::factory(Option::V4, DHO_DHCP_MESSAGE_TYPE,
  896. OptionBuffer(1, DHCPDISCOVER)));
  897. // Validate the option type and universe.
  898. EXPECT_EQ(Option::V4, opt_msg_type->getUniverse());
  899. EXPECT_EQ(DHO_DHCP_MESSAGE_TYPE, opt_msg_type->getType());
  900. // Validate the message type from the option we have now created.
  901. uint8_t msg_type = 0;
  902. ASSERT_NO_THROW(msg_type = opt_msg_type->getUint8());
  903. EXPECT_EQ(DHCPDISCOVER, msg_type);
  904. // Create another option: DHCP_PARAMETER_REQUEST_LIST
  905. OptionPtr
  906. opt_requested_options(Option::factory(Option::V4,
  907. DHO_DHCP_PARAMETER_REQUEST_LIST));
  908. // Here is a list of options that we are requesting in the
  909. // server's response.
  910. const uint8_t requested_options[] = {
  911. DHO_SUBNET_MASK,
  912. DHO_BROADCAST_ADDRESS,
  913. DHO_TIME_OFFSET,
  914. DHO_ROUTERS,
  915. DHO_DOMAIN_NAME,
  916. DHO_DOMAIN_NAME_SERVERS,
  917. DHO_HOST_NAME
  918. };
  919. OptionBuffer
  920. requested_options_ref(requested_options,
  921. requested_options + sizeof(requested_options));
  922. // Get the option buffer. It should hold the combination of values
  923. // listed in requested_options array. However their order can be
  924. // different in general so we need to search each value separately.
  925. const OptionBuffer& requested_options_buf =
  926. opt_requested_options->getData();
  927. EXPECT_EQ(requested_options_ref.size(), requested_options_buf.size());
  928. size_t matched_num = matchRequestedOptions(requested_options_ref,
  929. requested_options_buf);
  930. // We want exactly the same requested options as listed in
  931. // requested_options array - nothing more or less.
  932. EXPECT_EQ(requested_options_ref.size(), matched_num);
  933. }
  934. TEST_F(TestControlTest, Options6) {
  935. using namespace isc::dhcp;
  936. // Lets override the IP version to test V6 options (-6 parameter)
  937. ASSERT_NO_THROW(processCmdLine("perfdhcp -l 127.0.0.1 -6 all"));
  938. NakedTestControl tc;
  939. tc.registerOptionFactories();
  940. // Validate the D6O_ELAPSED_TIME option.
  941. OptionPtr opt_elapsed_time(Option::factory(Option::V6, D6O_ELAPSED_TIME));
  942. // Validate the option type and universe.
  943. EXPECT_EQ(Option::V6, opt_elapsed_time->getUniverse());
  944. EXPECT_EQ(D6O_ELAPSED_TIME, opt_elapsed_time->getType());
  945. // The default value of elapsed time is zero.
  946. uint16_t elapsed_time;
  947. ASSERT_NO_THROW(elapsed_time = opt_elapsed_time->getUint16());
  948. EXPECT_EQ(0, elapsed_time);
  949. // With the factory function we may also specify the actual
  950. // value of elapsed time. Let's make use of std::vector
  951. // constructor to create the option buffer, 2 octets long
  952. // with each octet initialized to 0x1.
  953. size_t elapsed_time_buf_size = 2;
  954. uint8_t elapsed_time_pattern = 0x1;
  955. OptionPtr
  956. opt_elapsed_time2(Option::factory(Option::V6, D6O_ELAPSED_TIME,
  957. OptionBuffer(elapsed_time_buf_size,
  958. elapsed_time_pattern)));
  959. // Any buffer that has size neither equal to 0 nor 2 is considered invalid.
  960. elapsed_time_buf_size = 1;
  961. EXPECT_THROW(
  962. Option::factory(Option::V6, D6O_ELAPSED_TIME,
  963. OptionBuffer(elapsed_time_buf_size, elapsed_time_pattern)),
  964. isc::BadValue
  965. );
  966. // Validate the option type and universe.
  967. EXPECT_EQ(Option::V6, opt_elapsed_time2->getUniverse());
  968. EXPECT_EQ(D6O_ELAPSED_TIME, opt_elapsed_time2->getType());
  969. // Make sure the getUint16 does not throw exception. It wile throw
  970. // buffer is shorter than 2 octets.
  971. ASSERT_NO_THROW(elapsed_time = opt_elapsed_time2->getUint16());
  972. // Check the expected value of elapsed time.
  973. EXPECT_EQ(0x0101, elapsed_time);
  974. // Validate the D6O_RAPID_COMMIT option.
  975. OptionPtr opt_rapid_commit(Option::factory(Option::V6, D6O_RAPID_COMMIT));
  976. // Validate the option type and universe.
  977. EXPECT_EQ(Option::V6, opt_rapid_commit->getUniverse());
  978. EXPECT_EQ(D6O_RAPID_COMMIT, opt_rapid_commit->getType());
  979. // Rapid commit has no data payload.
  980. EXPECT_THROW(opt_rapid_commit->getUint8(), isc::OutOfRange);
  981. // Validate the D6O_CLIENTID option.
  982. OptionBuffer duid(CommandOptions::instance().getDuidTemplate());
  983. OptionPtr opt_clientid(Option::factory(Option::V6, D6O_CLIENTID, duid));
  984. EXPECT_EQ(Option::V6, opt_clientid->getUniverse());
  985. EXPECT_EQ(D6O_CLIENTID, opt_clientid->getType());
  986. const OptionBuffer& duid2 = opt_clientid->getData();
  987. ASSERT_EQ(duid.size(), duid2.size());
  988. // The Duid we set for option is the same we get.
  989. EXPECT_TRUE(std::equal(duid.begin(), duid.end(), duid2.begin()));
  990. // Validate the D6O_ORO (Option Request Option).
  991. OptionPtr opt_oro(Option::factory(Option::V6, D6O_ORO));
  992. // Prepare the reference buffer with requested options.
  993. const uint8_t requested_options[] = {
  994. 0, D6O_NAME_SERVERS,
  995. 0, D6O_DOMAIN_SEARCH
  996. };
  997. // Each option code in ORO is 2 bytes long. We calculate the number of
  998. // requested options by dividing the size of the buffer holding options
  999. // by the size of each individual option.
  1000. int requested_options_num = sizeof(requested_options) / sizeof(uint16_t);
  1001. OptionBuffer
  1002. requested_options_ref(requested_options,
  1003. requested_options + sizeof(requested_options));
  1004. // Get the buffer from option.
  1005. const OptionBuffer& requested_options_buf = opt_oro->getData();
  1006. // Size of reference buffer and option buffer have to be
  1007. // the same for comparison.
  1008. EXPECT_EQ(requested_options_ref.size(), requested_options_buf.size());
  1009. // Check if all options in the buffer are matched with reference buffer.
  1010. size_t matched_num = matchRequestedOptions6(requested_options_ref,
  1011. requested_options_buf);
  1012. EXPECT_EQ(requested_options_num, matched_num);
  1013. // Validate the D6O_IA_NA option.
  1014. OptionPtr opt_ia_na(Option::factory(Option::V6, D6O_IA_NA));
  1015. EXPECT_EQ(Option::V6, opt_ia_na->getUniverse());
  1016. EXPECT_EQ(D6O_IA_NA, opt_ia_na->getType());
  1017. // Every IA_NA option is expected to start with this sequence.
  1018. const uint8_t opt_ia_na_array[] = {
  1019. 0, 0, 0, 1, // IAID = 1
  1020. 0, 0, 3600 >> 8, 3600 & 0xff, // T1 = 3600
  1021. 0, 0, 5400 >> 8, 5400 & 0xff, // T2 = 5400
  1022. };
  1023. OptionBuffer opt_ia_na_ref(opt_ia_na_array,
  1024. opt_ia_na_array + sizeof(opt_ia_na_array));
  1025. const OptionBuffer& opt_ia_na_buf = opt_ia_na->getData();
  1026. ASSERT_EQ(opt_ia_na_buf.size(), opt_ia_na_ref.size());
  1027. EXPECT_TRUE(std::equal(opt_ia_na_ref.begin(), opt_ia_na_ref.end(),
  1028. opt_ia_na_buf.begin()));
  1029. // @todo Add more tests for IA address options.
  1030. }
  1031. TEST_F(TestControlTest, Packet4) {
  1032. // Use Interface Manager to get the local loopback interface.
  1033. // If interface can't be found we don't want to fail test.
  1034. std::string loopback_iface(getLocalLoopback());
  1035. if (!loopback_iface.empty()) {
  1036. ASSERT_NO_THROW(processCmdLine("perfdhcp -l " + loopback_iface +
  1037. " -L 10547 all"));
  1038. NakedTestControl tc;
  1039. int sock_handle = 0;
  1040. // We have to create the socket to setup some parameters of
  1041. // outgoing packet.
  1042. ASSERT_NO_THROW(sock_handle = tc.openSocket());
  1043. TestControl::TestControlSocket sock(sock_handle);
  1044. uint32_t transid = 123;
  1045. boost::shared_ptr<Pkt4> pkt4(new Pkt4(DHCPDISCOVER, transid));
  1046. // Set parameters on outgoing packet.
  1047. ASSERT_NO_THROW(tc.setDefaults4(sock, pkt4));
  1048. // Validate that packet has been setup correctly.
  1049. EXPECT_EQ(loopback_iface, pkt4->getIface());
  1050. EXPECT_EQ(sock.ifindex_, pkt4->getIndex());
  1051. EXPECT_EQ(DHCP4_CLIENT_PORT, pkt4->getLocalPort());
  1052. EXPECT_EQ(DHCP4_SERVER_PORT, pkt4->getRemotePort());
  1053. EXPECT_EQ(1, pkt4->getHops());
  1054. EXPECT_EQ(asiolink::IOAddress("255.255.255.255"),
  1055. pkt4->getRemoteAddr());
  1056. EXPECT_EQ(asiolink::IOAddress(sock.addr_), pkt4->getLocalAddr());
  1057. EXPECT_EQ(asiolink::IOAddress(sock.addr_), pkt4->getGiaddr());
  1058. } else {
  1059. std::cout << "Unable to find the loopback interface. Skip test. "
  1060. << std::endl;
  1061. }
  1062. }
  1063. TEST_F(TestControlTest, Packet6) {
  1064. // Use Interface Manager to get the local loopback interface.
  1065. // If the interface can't be found we don't want to fail test.
  1066. std::string loopback_iface(getLocalLoopback());
  1067. if (!loopback_iface.empty()) {
  1068. ASSERT_NO_THROW(processCmdLine("perfdhcp -6 -l " + loopback_iface +
  1069. " -L 10547 servers"));
  1070. NakedTestControl tc;
  1071. int sock_handle = 0;
  1072. // Create the socket. It will be needed to set packet's
  1073. // parameters.
  1074. ASSERT_NO_THROW(sock_handle = tc.openSocket());
  1075. TestControl::TestControlSocket sock(sock_handle);
  1076. uint32_t transid = 123;
  1077. boost::shared_ptr<Pkt6> pkt6(new Pkt6(DHCPV6_SOLICIT, transid));
  1078. // Set packet's parameters.
  1079. ASSERT_NO_THROW(tc.setDefaults6(sock, pkt6));
  1080. // Validate if parameters have been set correctly.
  1081. EXPECT_EQ(loopback_iface, pkt6->getIface());
  1082. EXPECT_EQ(sock.ifindex_, pkt6->getIndex());
  1083. EXPECT_EQ(DHCP6_CLIENT_PORT, pkt6->getLocalPort());
  1084. EXPECT_EQ(DHCP6_SERVER_PORT, pkt6->getRemotePort());
  1085. EXPECT_EQ(sock.addr_, pkt6->getLocalAddr());
  1086. EXPECT_EQ(asiolink::IOAddress("FF05::1:3"), pkt6->getRemoteAddr());
  1087. } else {
  1088. std::cout << "Unable to find the loopback interface. Skip test. "
  1089. << std::endl;
  1090. }
  1091. }
  1092. TEST_F(TestControlTest, Packet4Exchange) {
  1093. // Get the local loopback interface to open socket on
  1094. // it and test packets exchanges. We don't want to fail
  1095. // the test if interface is not available.
  1096. std::string loopback_iface(getLocalLoopback());
  1097. if (loopback_iface.empty()) {
  1098. std::cout << "Unable to find the loopback interface. Skip test."
  1099. << std::endl;
  1100. return;
  1101. }
  1102. // Set number of iterations to some high value.
  1103. const int iterations_num = 100;
  1104. processCmdLine("perfdhcp -l " + loopback_iface
  1105. + " -r 100 -n 10 -R 20 -L 10547 127.0.0.1");
  1106. // The actual number of iterations will be stored in the
  1107. // following variable.
  1108. int iterations_performed = 0;
  1109. bool use_templates = false;
  1110. testPkt4Exchange(iterations_num, iterations_num, use_templates, iterations_performed);
  1111. // The command line restricts the number of iterations to 10
  1112. // with -n 10 parameter.
  1113. EXPECT_EQ(10, iterations_performed);
  1114. // With the following command line we restrict the maximum
  1115. // number of dropped packets to 20% of all.
  1116. // Use templates for this test.
  1117. processCmdLine("perfdhcp -l " + loopback_iface
  1118. + " -r 100 -R 20 -n 20 -D 10% -L 10547"
  1119. + " -T " + getFullPath("discover-example.hex")
  1120. + " -T " + getFullPath("request4-example.hex")
  1121. + " 127.0.0.1");
  1122. // The number iterations is restricted by the percentage of
  1123. // dropped packets (-D 10%). We also have to bump up the number
  1124. // of iterations because the percentage limitation checks starts
  1125. // at packet #10. We expect that at packet #12 the 10% threshold
  1126. // will be reached.
  1127. const int received_num = 10;
  1128. use_templates = true;
  1129. testPkt4Exchange(iterations_num, received_num, use_templates, iterations_performed);
  1130. EXPECT_EQ(12, iterations_performed);
  1131. }
  1132. TEST_F(TestControlTest, Packet6ExchangeFromTemplate) {
  1133. // Get the local loopback interface to open socket on
  1134. // it and test packets exchanges. We don't want to fail
  1135. // the test if interface is not available.
  1136. std::string loopback_iface(getLocalLoopback());
  1137. if (loopback_iface.empty()) {
  1138. std::cout << "Unable to find the loopback interface. Skip test."
  1139. << std::endl;
  1140. return;
  1141. }
  1142. const int iterations_num = 100;
  1143. // Set number of iterations to 10.
  1144. processCmdLine("perfdhcp -l " + loopback_iface
  1145. + " -6 -r 100 -n 10 -R 20 -L 10547 ::1");
  1146. int iterations_performed = 0;
  1147. // Set number of received packets equal to number of iterations.
  1148. // This simulates no packet drops.
  1149. bool use_templates = false;
  1150. testPkt6Exchange(iterations_num, iterations_num, use_templates,
  1151. iterations_performed);
  1152. // Actual number of iterations should be 10.
  1153. EXPECT_EQ(10, iterations_performed);
  1154. // The maximum number of dropped packets is 3 (because of -D 3).
  1155. use_templates = true;
  1156. processCmdLine("perfdhcp -l " + loopback_iface
  1157. + " -6 -r 100 -n 10 -R 20 -D 3 -L 10547"
  1158. + " -T " + getFullPath("solicit-example.hex")
  1159. + " -T " + getFullPath("request6-example.hex ::1"));
  1160. // For the first 3 packets we are simulating responses from server.
  1161. // For other packets we don't so packet as 4,5,6 will be dropped and
  1162. // then test should be interrupted and actual number of iterations will
  1163. // be 6.
  1164. const int received_num = 3;
  1165. // Simulate the number of Solicit-Advertise-Request-Reply (SARR) echanges.
  1166. // The test function generates server's responses and passes it to the
  1167. // TestControl class methods for processing. The number of exchanges
  1168. // actually performed is returned in 'iterations_performed' argument. If
  1169. // processing is successful, the number of performed iterations should be
  1170. // equal to the number of exchanges specified with the '-n' command line
  1171. // parameter (10 in this case). All exchanged packets carry the IA_NA option
  1172. // to simulate the IPv6 address acquisition and to verify that the
  1173. // IA_NA options returned by the server are processed correctly.
  1174. testPkt6Exchange(iterations_num, received_num, use_templates,
  1175. iterations_performed);
  1176. EXPECT_EQ(6, iterations_performed);
  1177. }
  1178. TEST_F(TestControlTest, Packet6Exchange) {
  1179. // Get the local loopback interface to open socket on
  1180. // it and test packets exchanges. We don't want to fail
  1181. // the test if interface is not available.
  1182. std::string loopback_iface(getLocalLoopback());
  1183. if (loopback_iface.empty()) {
  1184. std::cout << "Unable to find the loopback interface. Skip test."
  1185. << std::endl;
  1186. return;
  1187. }
  1188. const int iterations_num = 100;
  1189. // Set number of iterations to 10.
  1190. processCmdLine("perfdhcp -l " + loopback_iface
  1191. + " -e address-only"
  1192. + " -6 -r 100 -n 10 -R 20 -L 10547 ::1");
  1193. int iterations_performed = 0;
  1194. // Set number of received packets equal to number of iterations.
  1195. // This simulates no packet drops.
  1196. bool use_templates = false;
  1197. // Simulate the number of Solicit-Advertise-Request-Reply (SARR) echanges.
  1198. // The test function generates server's responses and passes it to the
  1199. // TestControl class methods for processing. The number of exchanges
  1200. // actually performed is returned in 'iterations_performed' argument. If
  1201. // processing is successful, the number of performed iterations should be
  1202. // equal to the number of exchanges specified with the '-n' command line
  1203. // parameter (10 in this case). All exchanged packets carry the IA_NA option
  1204. // to simulate the IPv6 address acqusition and to verify that the IA_NA
  1205. // options returned by the server are processed correctly.
  1206. testPkt6Exchange(iterations_num, iterations_num, use_templates,
  1207. iterations_performed);
  1208. // Actual number of iterations should be 10.
  1209. EXPECT_EQ(10, iterations_performed);
  1210. }
  1211. TEST_F(TestControlTest, Packet6ExchangePrefixDelegation) {
  1212. // Get the local loopback interface to open socket on
  1213. // it and test packets exchanges. We don't want to fail
  1214. // the test if interface is not available.
  1215. std::string loopback_iface(getLocalLoopback());
  1216. if (loopback_iface.empty()) {
  1217. std::cout << "Unable to find the loopback interface. Skip test."
  1218. << std::endl;
  1219. return;
  1220. }
  1221. const int iterations_num = 100;
  1222. // Set number of iterations to 10.
  1223. processCmdLine("perfdhcp -l " + loopback_iface
  1224. + " -e prefix-only"
  1225. + " -6 -r 100 -n 10 -R 20 -L 10547 ::1");
  1226. int iterations_performed = 0;
  1227. // Set number of received packets equal to number of iterations.
  1228. // This simulates no packet drops.
  1229. bool use_templates = false;
  1230. // Simulate the number of Solicit-Advertise-Request-Reply (SARR) echanges.
  1231. // The test function generates server's responses and passes it to the
  1232. // TestControl class methods for processing. The number of exchanges
  1233. // actually performed is returned in 'iterations_performed' argument. If
  1234. // processing is successful, the number of performed iterations should be
  1235. // equal to the number of exchanges specified with the '-n' command line
  1236. // parameter (10 in this case). All exchanged packets carry the IA_PD option
  1237. // to simulate the Prefix Delegation and to verify that the IA_PD options
  1238. // returned by the server are processed correctly.
  1239. testPkt6Exchange(iterations_num, iterations_num, use_templates,
  1240. iterations_performed);
  1241. // Actual number of iterations should be 10.
  1242. EXPECT_EQ(10, iterations_performed);
  1243. }
  1244. TEST_F(TestControlTest, Packet6ExchangeAddressAndPrefix) {
  1245. // Get the local loopback interface to open socket on
  1246. // it and test packets exchanges. We don't want to fail
  1247. // the test if interface is not available.
  1248. std::string loopback_iface(getLocalLoopback());
  1249. if (loopback_iface.empty()) {
  1250. std::cout << "Unable to find the loopback interface. Skip test."
  1251. << std::endl;
  1252. return;
  1253. }
  1254. const int iterations_num = 100;
  1255. // Set number of iterations to 10.
  1256. processCmdLine("perfdhcp -l " + loopback_iface
  1257. + " -e address-and-prefix"
  1258. + " -6 -r 100 -n 10 -R 20 -L 10547 ::1");
  1259. int iterations_performed = 0;
  1260. // Set number of received packets equal to number of iterations.
  1261. // This simulates no packet drops.
  1262. bool use_templates = false;
  1263. // Simulate the number of Solicit-Advertise-Request-Reply (SARR) echanges.
  1264. // The test function generates server's responses and passes it to the
  1265. // TestControl class methods for processing. The number of exchanges
  1266. // actually performed is returned in 'iterations_performed' argument. If
  1267. // processing is successful, the number of performed iterations should be
  1268. // equal to the number of exchanges specified with the '-n' command line
  1269. // parameter (10 in this case). All exchanged packets carry either IA_NA
  1270. // or IA_PD options to simulate the address and prefix acquisition with
  1271. // the single message and to verify that the IA_NA and IA_PD options
  1272. // returned by the server are processed correctly.
  1273. testPkt6Exchange(iterations_num, iterations_num, use_templates,
  1274. iterations_performed);
  1275. // Actual number of iterations should be 10.
  1276. EXPECT_EQ(10, iterations_performed);
  1277. }
  1278. TEST_F(TestControlTest, PacketTemplates) {
  1279. std::vector<uint8_t> template1(256);
  1280. std::string file1("test1.hex");
  1281. std::vector<uint8_t> template2(233);
  1282. std::string file2("test2.hex");
  1283. for (int i = 0; i < template1.size(); ++i) {
  1284. template1[i] = static_cast<uint8_t>(random() % 256);
  1285. }
  1286. for (int i = 0; i < template2.size(); ++i) {
  1287. template2[i] = static_cast<uint8_t>(random() % 256);
  1288. }
  1289. // Size of the file is 2 times larger than binary data size.
  1290. ASSERT_TRUE(createTemplateFile(file1, template1, template1.size() * 2));
  1291. ASSERT_TRUE(createTemplateFile(file2, template2, template2.size() * 2));
  1292. NakedTestControl tc;
  1293. ASSERT_NO_THROW(
  1294. processCmdLine("perfdhcp -l 127.0.0.1"
  1295. " -T " + file1 + " -T " + file2 + " all")
  1296. );
  1297. ASSERT_NO_THROW(tc.initPacketTemplates());
  1298. TestControl::TemplateBuffer buf1;
  1299. TestControl::TemplateBuffer buf2;
  1300. ASSERT_NO_THROW(buf1 = tc.getTemplateBuffer(0));
  1301. ASSERT_NO_THROW(buf2 = tc.getTemplateBuffer(1));
  1302. ASSERT_EQ(template1.size(), buf1.size());
  1303. ASSERT_EQ(template2.size(), buf2.size());
  1304. EXPECT_TRUE(std::equal(template1.begin(), template1.end(), buf1.begin()));
  1305. EXPECT_TRUE(std::equal(template2.begin(), template2.end(), buf2.begin()));
  1306. // Try to read template file with odd number of digits.
  1307. std::string file3("test3.hex");
  1308. // Size of the file is 2 times larger than binary data size and it is always
  1309. // even number. Substracting 1 makes file size odd.
  1310. ASSERT_TRUE(createTemplateFile(file3, template1, template1.size() * 2 - 1));
  1311. ASSERT_NO_THROW(
  1312. processCmdLine("perfdhcp -l 127.0.0.1 -T " + file3 + " all")
  1313. );
  1314. EXPECT_THROW(tc.initPacketTemplates(), isc::OutOfRange);
  1315. // Try to read empty file.
  1316. std::string file4("test4.hex");
  1317. ASSERT_TRUE(createTemplateFile(file4, template2, 0));
  1318. ASSERT_NO_THROW(
  1319. processCmdLine("perfdhcp -l 127.0.0.1 -T " + file4 + " all")
  1320. );
  1321. EXPECT_THROW(tc.initPacketTemplates(), isc::OutOfRange);
  1322. // Try reading file with non hexadecimal characters.
  1323. std::string file5("test5.hex");
  1324. ASSERT_TRUE(createTemplateFile(file5, template1, template1.size() * 2, true));
  1325. ASSERT_NO_THROW(
  1326. processCmdLine("perfdhcp -l 127.0.0.1 -T " + file5 + " all")
  1327. );
  1328. EXPECT_THROW(tc.initPacketTemplates(), isc::BadValue);
  1329. }
  1330. TEST_F(TestControlTest, processRenew) {
  1331. testSendRenewRelease(DHCPV6_RENEW);
  1332. }
  1333. TEST_F(TestControlTest, processRelease) {
  1334. testSendRenewRelease(DHCPV6_RELEASE);
  1335. }
  1336. // This test verifies that the DHCPV6 Renew message is created correctly
  1337. // and that it comprises all required options.
  1338. TEST_F(TestControlTest, createRenew) {
  1339. testCreateRenewRelease(DHCPV6_RENEW);
  1340. }
  1341. // This test verifies that the DHCPv6 Release message is created correctly
  1342. // and that it comprises all required options.
  1343. TEST_F(TestControlTest, createRelease) {
  1344. testCreateRenewRelease(DHCPV6_RELEASE);
  1345. }
  1346. // This test verifies that the current timeout value for waiting for
  1347. // the server's responses is valid. The timeout value corresponds to the
  1348. // time period between now and the next message to be sent from the
  1349. // perfdhcp to a server.
  1350. TEST_F(TestControlTest, getCurrentTimeout) {
  1351. // Process the command line: set the rate for Discovers to 10,
  1352. // and set Renew rate to 0 (-f flag absent).
  1353. ASSERT_NO_THROW(processCmdLine("perfdhcp -4 -l lo -r 10 ::1"));
  1354. NakedTestControl tc;
  1355. // Make sure that the renew rate is 0.
  1356. ASSERT_EQ(0, CommandOptions::instance().getRenewRate());
  1357. // Simulate the case when we are already behind the due time for
  1358. // the next Discover to be sent.
  1359. tc.setRelativeDueTimes(-3);
  1360. // Expected timeout value is 0, which means that perfdhcp should
  1361. // not wait for server's response but rather send the next
  1362. // message to a server immediately.
  1363. EXPECT_EQ(0, tc.getCurrentTimeout());
  1364. // Now, let's do set the due time to a value in the future. The returned
  1365. // timeout value should be somewhere between now and this time in the
  1366. // future. The value of ten seconds ahead should be safe and guarantee
  1367. // that the returned timeout value is non-zero, even though there is a
  1368. // delay between setting the send_due_ value and invoking the function.
  1369. tc.setRelativeDueTimes(10);
  1370. uint32_t timeout = tc.getCurrentTimeout();
  1371. EXPECT_GT(timeout, 0);
  1372. EXPECT_LE(timeout, 10000000);
  1373. }
  1374. // This test verifies that the current timeout value for waiting for the
  1375. // server's responses is valid. In this case, we are simulating that perfdhcp
  1376. // sends Renew requests to the server, apart from the regular 4-way exchanges.
  1377. // The timeout value depends on both the due time to send next Solicit and the
  1378. // due time to send Renew - the timeout should be ajusted to the due time that
  1379. // occurs sooner.
  1380. TEST_F(TestControlTest, getCurrentTimeoutRenew) {
  1381. // Set the Solicit rate to 10 and the Renew rate 5.
  1382. ASSERT_NO_THROW(processCmdLine("perfdhcp -6 -l lo -r 10 -f 5 ::1"));
  1383. NakedTestControl tc;
  1384. // Make sure, that the Renew rate has been set to 5.
  1385. ASSERT_EQ(5, CommandOptions::instance().getRenewRate());
  1386. // The send_due_ is in the past, the renew_due_ is in the future.
  1387. tc.setRelativeDueTimes(-3, 3);
  1388. EXPECT_EQ(0, tc.getCurrentTimeout());
  1389. // Swap the due times from the previous check. The effect should be the
  1390. // same.
  1391. tc.setRelativeDueTimes(3, -3);
  1392. EXPECT_EQ(0, tc.getCurrentTimeout());
  1393. // Set both due times to the future. The renew due time is to occur
  1394. // sooner. The timeout should be a value between now and the
  1395. // renew due time.
  1396. tc.setRelativeDueTimes(10, 5);
  1397. EXPECT_GT(tc.getCurrentTimeout(), 0);
  1398. EXPECT_LE(tc.getCurrentTimeout(), 5000000);
  1399. // Repeat the same check, but swap the due times.
  1400. tc.setRelativeDueTimes(5, 10);
  1401. EXPECT_GT(tc.getCurrentTimeout(), 0);
  1402. EXPECT_LE(tc.getCurrentTimeout(), 5000000);
  1403. }
  1404. // This test verifies that the current timeout value for waiting for the
  1405. // server's responses is valid. In this case, we are simulating that perfdhcp
  1406. // sends Release requests to the server, apart from the regular 4-way exchanges.
  1407. TEST_F(TestControlTest, getCurrentTimeoutRelease) {
  1408. // Set the Solicit rate to 10 and the Release rate 5.
  1409. ASSERT_NO_THROW(processCmdLine("perfdhcp -6 -l lo -r 10 -F 5 ::1"));
  1410. NakedTestControl tc;
  1411. // Make sure, that the Release rate has been set to 5.
  1412. ASSERT_EQ(5, CommandOptions::instance().getReleaseRate());
  1413. // The send_due_ is in the past, the renew_due_ is in the future.
  1414. tc.setRelativeDueTimes(-3, 0, 3);
  1415. EXPECT_EQ(0, tc.getCurrentTimeout());
  1416. // Swap the due times from the previous check. The effect should be the
  1417. // same.
  1418. tc.setRelativeDueTimes(3, 0, -3);
  1419. EXPECT_EQ(0, tc.getCurrentTimeout());
  1420. // Set both due times to the future. The renew due time is to occur
  1421. // sooner. The timeout should be a value between now and the
  1422. // release due time.
  1423. tc.setRelativeDueTimes(10, 0, 5);
  1424. EXPECT_GT(tc.getCurrentTimeout(), 0);
  1425. EXPECT_LE(tc.getCurrentTimeout(), 5000000);
  1426. // Repeat the same check, but swap the due times.
  1427. tc.setRelativeDueTimes(5, 0, 10);
  1428. EXPECT_GT(tc.getCurrentTimeout(), 0);
  1429. EXPECT_LE(tc.getCurrentTimeout(), 5000000);
  1430. }
  1431. // This test verifies that the current timeout value for waiting for the
  1432. // server's responses is valid. In this case, we are simulating that perfdhcp
  1433. // sends both Renew and Release requests to the server, apart from the regular
  1434. // 4-way exchanges.
  1435. TEST_F(TestControlTest, getCurrentTimeoutRenewRelease) {
  1436. // Set the Solicit rate to 10 and, Renew rate to 5, Release rate to 3.
  1437. ASSERT_NO_THROW(processCmdLine("perfdhcp -6 -l lo -r 10 -f 5 -F 3 ::1"));
  1438. NakedTestControl tc;
  1439. // Make sure the Renew and Release rates has been set to a non-zero value.
  1440. ASSERT_EQ(5, CommandOptions::instance().getRenewRate());
  1441. ASSERT_EQ(3, CommandOptions::instance().getReleaseRate());
  1442. // If any of the due times is in the past, the timeout value should be 0,
  1443. // to indicate that the next message should be sent immediately.
  1444. tc.setRelativeDueTimes(-3, 3, 5);
  1445. EXPECT_EQ(0, tc.getCurrentTimeout());
  1446. tc.setRelativeDueTimes(-3, 5, 3);
  1447. EXPECT_EQ(0, tc.getCurrentTimeout());
  1448. tc.setRelativeDueTimes(3, -3, 5);
  1449. EXPECT_EQ(0, tc.getCurrentTimeout());
  1450. tc.setRelativeDueTimes(3, 2, -5);
  1451. EXPECT_EQ(0, tc.getCurrentTimeout());
  1452. tc.setRelativeDueTimes(-3, -2, -5);
  1453. EXPECT_EQ(0, tc.getCurrentTimeout());
  1454. // If due times are in the future, the timeout value should be aligned to
  1455. // the due time which occurs the soonest.
  1456. tc.setRelativeDueTimes(10, 9, 8);
  1457. EXPECT_GT(tc.getCurrentTimeout(), 0);
  1458. EXPECT_LE(tc.getCurrentTimeout(), 8000000);
  1459. tc.setRelativeDueTimes(10, 8, 9);
  1460. EXPECT_GT(tc.getCurrentTimeout(), 0);
  1461. EXPECT_LE(tc.getCurrentTimeout(), 8000000);
  1462. tc.setRelativeDueTimes(5, 8, 9);
  1463. EXPECT_GT(tc.getCurrentTimeout(), 0);
  1464. EXPECT_LE(tc.getCurrentTimeout(), 5000000);
  1465. }