command_options_unittest.cc 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. // Copyright (C) 2012-2015 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 <config.h>
  15. #include <cstddef>
  16. #include <stdint.h>
  17. #include <string>
  18. #include <gtest/gtest.h>
  19. #include <boost/date_time/posix_time/posix_time.hpp>
  20. #include <dhcp/iface_mgr.h>
  21. #include <exceptions/exceptions.h>
  22. #include "command_options_helper.h"
  23. using namespace std;
  24. using namespace isc;
  25. using namespace isc::perfdhcp;
  26. using namespace boost::posix_time;
  27. // Verify that default constructor sets lease type to the expected value.
  28. TEST(LeaseTypeTest, defaultConstructor) {
  29. CommandOptions::LeaseType lease_type;
  30. EXPECT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS));
  31. }
  32. // Verify that the constructor sets the lease type to the specified value.
  33. TEST(LeaseTypeTest, constructor) {
  34. CommandOptions::LeaseType
  35. lease_type1(CommandOptions::LeaseType::ADDRESS);
  36. EXPECT_TRUE(lease_type1.is(CommandOptions::LeaseType::ADDRESS));
  37. CommandOptions::LeaseType
  38. lease_type2(CommandOptions::LeaseType::PREFIX);
  39. EXPECT_TRUE(lease_type2.is(CommandOptions::LeaseType::PREFIX));
  40. }
  41. // Verify that the lease type can be modified using set() function.
  42. TEST(LeaseTypeTest, set) {
  43. CommandOptions::LeaseType
  44. lease_type(CommandOptions::LeaseType::ADDRESS);
  45. EXPECT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS));
  46. lease_type.set(CommandOptions::LeaseType::PREFIX);
  47. EXPECT_TRUE(lease_type.is(CommandOptions::LeaseType::PREFIX));
  48. }
  49. // Verify that the includes() function returns true when the lease type
  50. // specified with the function argument is the same as the lease type
  51. // encapsulated by the LeaseType object on which include function is called
  52. // or when the lease type value encapsulated by this object is
  53. // ADDRESS_AND_PREFIX.
  54. TEST(LeaseTypeTest, includes) {
  55. // Lease type: ADDRESS
  56. CommandOptions::LeaseType lease_type(CommandOptions::LeaseType::ADDRESS);
  57. // Lease type IS ADDRESS.
  58. ASSERT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS));
  59. // Lease type includes the ADDRESS.
  60. EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::ADDRESS));
  61. // Lease type does not include PREFIX.
  62. EXPECT_FALSE(lease_type.includes(CommandOptions::LeaseType::PREFIX));
  63. // Lease type does not include ADDRESS_AND_PREFIX.
  64. EXPECT_FALSE(
  65. lease_type.includes(CommandOptions::LeaseType::ADDRESS_AND_PREFIX)
  66. );
  67. // Do the same check for PREFIX.
  68. lease_type.set(CommandOptions::LeaseType::PREFIX);
  69. EXPECT_FALSE(lease_type.includes(CommandOptions::LeaseType::ADDRESS));
  70. EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::PREFIX));
  71. EXPECT_FALSE(
  72. lease_type.includes(CommandOptions::LeaseType::ADDRESS_AND_PREFIX)
  73. );
  74. // When lease type is set to 'address-and-prefix' it means that client
  75. // requests both address and prefix (IA_NA and IA_PD). Therefore, the
  76. // LeaseType::includes() function should return true for both ADDRESS
  77. // and PREFIX.
  78. lease_type.set(CommandOptions::LeaseType::ADDRESS_AND_PREFIX);
  79. EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::ADDRESS));
  80. EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::PREFIX));
  81. EXPECT_TRUE(
  82. lease_type.includes(CommandOptions::LeaseType::ADDRESS_AND_PREFIX)
  83. );
  84. }
  85. // Verify that the LeaseType::fromCommandLine() function parses the lease-type
  86. // argument specified as -e<lease-type>.
  87. TEST(LeaseTypeTest, fromCommandLine) {
  88. CommandOptions::LeaseType
  89. lease_type(CommandOptions::LeaseType::ADDRESS);
  90. ASSERT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS));
  91. lease_type.fromCommandLine("prefix-only");
  92. ASSERT_TRUE(lease_type.is(CommandOptions::LeaseType::PREFIX));
  93. lease_type.fromCommandLine("address-only");
  94. EXPECT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS));
  95. lease_type.fromCommandLine("address-and-prefix");
  96. EXPECT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS_AND_PREFIX));
  97. EXPECT_THROW(lease_type.fromCommandLine("bogus-parameter"),
  98. isc::InvalidParameter);
  99. }
  100. // Verify that the LeaseType::toText() function returns the textual
  101. // representation of the lease type specified.
  102. TEST(LeaseTypeTest, toText) {
  103. CommandOptions::LeaseType lease_type;
  104. ASSERT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS));
  105. EXPECT_EQ("address-only (IA_NA option added to the client's request)",
  106. lease_type.toText());
  107. lease_type.set(CommandOptions::LeaseType::PREFIX);
  108. EXPECT_EQ("prefix-only (IA_PD option added to the client's request)",
  109. lease_type.toText());
  110. lease_type.set(CommandOptions::LeaseType::ADDRESS_AND_PREFIX);
  111. EXPECT_EQ("address-and-prefix (Both IA_NA and IA_PD options added to the"
  112. " client's request)", lease_type.toText());
  113. }
  114. /// \brief Test Fixture Class
  115. ///
  116. /// This test fixture class is used to perform
  117. /// unit tests on perfdhcp CommandOptions class.
  118. class CommandOptionsTest : public virtual ::testing::Test
  119. {
  120. public:
  121. /// \brief Default Constructor
  122. CommandOptionsTest() { }
  123. protected:
  124. /// \brief Parse command line and cleanup
  125. ///
  126. /// The method tokenizes command line to array of C-strings,
  127. /// parses arguments using CommandOptions class to set
  128. /// its data members and de-allocates array of C-strings.
  129. ///
  130. /// \param cmdline Command line to parse.
  131. /// \throws std::bad allocation if tokenization failed.
  132. /// \return true if program has been run in help or version mode ('h' or 'v' flag).
  133. bool process(const std::string& cmdline) {
  134. return (CommandOptionsHelper::process(cmdline));
  135. }
  136. /// \brief Check default initialized values
  137. ///
  138. /// Check if initialized values are correct
  139. void checkDefaults() {
  140. CommandOptions& opt = CommandOptions::instance();
  141. EXPECT_NO_THROW(process("perfdhcp 192.168.0.1"));
  142. EXPECT_EQ(4, opt.getIpVersion());
  143. EXPECT_EQ(CommandOptions::DORA_SARR, opt.getExchangeMode());
  144. EXPECT_TRUE(opt.getLeaseType().is(CommandOptions::LeaseType::ADDRESS));
  145. EXPECT_EQ(0, opt.getRate());
  146. EXPECT_EQ(0, opt.getRenewRate());
  147. EXPECT_EQ(0, opt.getReleaseRate());
  148. EXPECT_EQ(0, opt.getReportDelay());
  149. EXPECT_EQ(0, opt.getClientsNum());
  150. // default mac
  151. const uint8_t mac[6] = { 0x00, 0x0C, 0x01, 0x02, 0x03, 0x04 };
  152. std::vector<uint8_t> v1 = opt.getMacTemplate();
  153. ASSERT_EQ(6, v1.size());
  154. EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
  155. // Check if DUID is initialized. The DUID-LLT is expected
  156. // to start with DUID_LLT value of 1 and hardware ethernet
  157. // type equal to 1 (HWETHER_TYPE).
  158. const uint8_t duid_llt_and_hw[4] = { 0x0, 0x1, 0x0, 0x1 };
  159. // We assume DUID-LLT length 14. This includes 4 octets of
  160. // DUID_LLT value, two octets of hardware type, 4 octets
  161. // of time value and 6 octets of variable link layer (MAC)
  162. // address.
  163. const int duid_llt_size = 14;
  164. // DUID is not given from the command line but it is supposed
  165. // to be initialized by the CommandOptions private method
  166. // generateDuidTemplate().
  167. std::vector<uint8_t> v2 = opt.getDuidTemplate();
  168. ASSERT_EQ(duid_llt_size, opt.getDuidTemplate().size());
  169. EXPECT_TRUE(std::equal(v2.begin(), v2.begin() + 4,
  170. duid_llt_and_hw));
  171. // Check time field contents.
  172. ptime now = microsec_clock::universal_time();
  173. ptime duid_epoch(from_iso_string("20000101T000000"));
  174. time_period period(duid_epoch, now);
  175. uint32_t duration_sec = period.length().total_seconds();
  176. // Read time from the template generated.
  177. uint32_t duration_from_template = 0;
  178. memcpy(&duration_from_template, &v2[4], 4);
  179. duration_from_template = htonl(duration_from_template);
  180. // In special cases, we may have overflow in time field
  181. // so we give ourselves the margin of 10 seconds here.
  182. // If time value has been set more then 10 seconds back
  183. // it is safe to compare it with the time value generated
  184. // from now.
  185. if (duration_from_template > 10) {
  186. EXPECT_GE(duration_sec, duration_from_template);
  187. }
  188. EXPECT_EQ(0, opt.getBase().size());
  189. EXPECT_EQ(0, opt.getNumRequests().size());
  190. EXPECT_EQ(0, opt.getPeriod());
  191. for (size_t i = 0; i < opt.getDropTime().size(); ++i) {
  192. EXPECT_DOUBLE_EQ(1, opt.getDropTime()[i]);
  193. }
  194. ASSERT_EQ(opt.getMaxDrop().size(), opt.getMaxDropPercentage().size());
  195. for (size_t i = 0; i < opt.getMaxDrop().size(); ++i) {
  196. EXPECT_EQ(0, opt.getMaxDrop()[i]);
  197. EXPECT_EQ(0, opt.getMaxDropPercentage()[i]);
  198. }
  199. EXPECT_EQ("", opt.getLocalName());
  200. EXPECT_FALSE(opt.isInterface());
  201. EXPECT_EQ(0, opt.getPreload());
  202. EXPECT_EQ(1, opt.getAggressivity());
  203. EXPECT_EQ(0, opt.getLocalPort());
  204. EXPECT_FALSE(opt.isSeeded());
  205. EXPECT_EQ(0, opt.getSeed());
  206. EXPECT_FALSE(opt.isBroadcast());
  207. EXPECT_FALSE(opt.isRapidCommit());
  208. EXPECT_FALSE(opt.isUseFirst());
  209. EXPECT_EQ(0, opt.getTemplateFiles().size());
  210. EXPECT_EQ(0, opt.getTransactionIdOffset().size());
  211. EXPECT_EQ(0, opt.getRandomOffset().size());
  212. EXPECT_GT(0, opt.getElapsedTimeOffset());
  213. EXPECT_GT(0, opt.getServerIdOffset());
  214. EXPECT_GT(0, opt.getRequestedIpOffset());
  215. EXPECT_EQ("", opt.getDiags());
  216. EXPECT_EQ("", opt.getWrapped());
  217. EXPECT_EQ("192.168.0.1", opt.getServerName());
  218. }
  219. };
  220. TEST_F(CommandOptionsTest, Defaults) {
  221. EXPECT_NO_THROW(process("perfdhcp all"));
  222. checkDefaults();
  223. }
  224. TEST_F(CommandOptionsTest, HelpVersion) {
  225. // The parser is supposed to return true if 'h' or 'v' options
  226. // are specified.
  227. EXPECT_TRUE(process("perfdhcp -h"));
  228. EXPECT_TRUE(process("perfdhcp -v"));
  229. EXPECT_TRUE(process("perfdhcp -h -v"));
  230. EXPECT_TRUE(process("perfdhcp -6 -l ethx -h all"));
  231. EXPECT_TRUE(process("perfdhcp -l ethx -v all"));
  232. // No 'h' or 'v' option specified. The false value
  233. // should be returned.
  234. EXPECT_FALSE(process("perfdhcp -l ethx all"));
  235. }
  236. TEST_F(CommandOptionsTest, UseFirst) {
  237. CommandOptions& opt = CommandOptions::instance();
  238. EXPECT_NO_THROW(process("perfdhcp -1 -B -l ethx all"));
  239. EXPECT_TRUE(opt.isUseFirst());
  240. }
  241. TEST_F(CommandOptionsTest, IpVersion) {
  242. CommandOptions& opt = CommandOptions::instance();
  243. EXPECT_NO_THROW(process("perfdhcp -6 -l ethx -c -i all"));
  244. EXPECT_EQ(6, opt.getIpVersion());
  245. EXPECT_EQ("ethx", opt.getLocalName());
  246. EXPECT_TRUE(opt.isRapidCommit());
  247. EXPECT_FALSE(opt.isBroadcast());
  248. process("perfdhcp -4 -B -l ethx all");
  249. EXPECT_EQ(4, opt.getIpVersion());
  250. EXPECT_TRUE(opt.isBroadcast());
  251. EXPECT_FALSE(opt.isRapidCommit());
  252. // Negative test cases
  253. // -4 and -6 must not coexist
  254. EXPECT_THROW(process("perfdhcp -4 -6 -l ethx all"), isc::InvalidParameter);
  255. // -6 and -B must not coexist
  256. EXPECT_THROW(process("perfdhcp -6 -B -l ethx all"), isc::InvalidParameter);
  257. // -c and -4 (default) must not coexist
  258. EXPECT_THROW(process("perfdhcp -c -l ethx all"), isc::InvalidParameter);
  259. }
  260. TEST_F(CommandOptionsTest, LeaseType) {
  261. CommandOptions& opt = CommandOptions::instance();
  262. // Check that the -e address-only works for IPv6.
  263. ASSERT_NO_THROW(process("perfdhcp -6 -l etx -e address-only all"));
  264. EXPECT_EQ(6, opt.getIpVersion());
  265. EXPECT_EQ("etx", opt.getLocalName());
  266. EXPECT_TRUE(opt.getLeaseType().is(CommandOptions::LeaseType::ADDRESS));
  267. // Check that the -e address-only works for IPv4.
  268. ASSERT_NO_THROW(process("perfdhcp -4 -l etx -e address-only all"));
  269. EXPECT_EQ(4, opt.getIpVersion());
  270. EXPECT_EQ("etx", opt.getLocalName());
  271. EXPECT_TRUE(opt.getLeaseType().is(CommandOptions::LeaseType::ADDRESS));
  272. // Check that the -e prefix-only works.
  273. ASSERT_NO_THROW(process("perfdhcp -6 -l etx -e prefix-only all"));
  274. EXPECT_EQ(6, opt.getIpVersion());
  275. EXPECT_EQ("etx", opt.getLocalName());
  276. EXPECT_TRUE(opt.getLeaseType().is(CommandOptions::LeaseType::PREFIX));
  277. // Check that -e prefix-only must not coexist with -4 option.
  278. EXPECT_THROW(process("perfdhcp -4 -l ethx -e prefix-only all"),
  279. InvalidParameter);
  280. // Check that -e prefix-only must not coexist with -T options.
  281. EXPECT_THROW(process("perfdhcp -6 -l ethx -e prefix-only -T file1.hex"
  282. " -T file2.hex -E 4 all"), InvalidParameter);
  283. }
  284. TEST_F(CommandOptionsTest, Rate) {
  285. CommandOptions& opt = CommandOptions::instance();
  286. EXPECT_NO_THROW(process("perfdhcp -4 -r 10 -l ethx all"));
  287. EXPECT_EQ(10, opt.getRate());
  288. // Negative test cases
  289. // Rate must not be 0
  290. EXPECT_THROW(process("perfdhcp -4 -r 0 -l ethx all"),
  291. isc::InvalidParameter);
  292. // -r must be specified to use -n, -p and -D
  293. EXPECT_THROW(process("perfdhcp -6 -t 5 -l ethx all"),
  294. isc::InvalidParameter);
  295. EXPECT_THROW(process("perfdhcp -4 -n 150 -l ethx all"),
  296. isc::InvalidParameter);
  297. EXPECT_THROW(process("perfdhcp -6 -p 120 -l ethx all"),
  298. isc::InvalidParameter);
  299. EXPECT_THROW(process("perfdhcp -4 -D 1400 -l ethx all"),
  300. isc::InvalidParameter);
  301. }
  302. TEST_F(CommandOptionsTest, RenewRate) {
  303. CommandOptions& opt = CommandOptions::instance();
  304. // If -f is specified together with -r the command line should
  305. // be accepted and the renew rate should be set.
  306. EXPECT_NO_THROW(process("perfdhcp -6 -r 10 -f 10 -l ethx all"));
  307. EXPECT_EQ(10, opt.getRenewRate());
  308. // Check that the release rate can be set to different value than
  309. // rate specified as -r<rate>. Also, swap -f and -r to make sure
  310. // that order doesn't matter.
  311. EXPECT_NO_THROW(process("perfdhcp -6 -f 5 -r 10 -l ethx all"));
  312. EXPECT_EQ(5, opt.getRenewRate());
  313. // The renew rate should not be greater than the rate.
  314. EXPECT_THROW(process("perfdhcp -6 -r 10 -f 11 -l ethx all"),
  315. isc::InvalidParameter);
  316. // The renew-rate of 0 is invalid.
  317. EXPECT_THROW(process("perfdhcp -6 -r 10 -f 0 -l ethx all"),
  318. isc::InvalidParameter);
  319. // The negative renew-rate is invalid.
  320. EXPECT_THROW(process("perfdhcp -6 -r 10 -f -5 -l ethx all"),
  321. isc::InvalidParameter);
  322. // If -r<rate> is not specified the -f<renew-rate> should not
  323. // be accepted.
  324. EXPECT_THROW(process("perfdhcp -6 -f 10 -l ethx all"),
  325. isc::InvalidParameter);
  326. // Currently the -f<renew-rate> can be specified for IPv6 mode
  327. // only.
  328. EXPECT_THROW(process("perfdhcp -4 -r 10 -f 10 -l ethx all"),
  329. isc::InvalidParameter);
  330. // Renew rate should be specified.
  331. EXPECT_THROW(process("perfdhcp -6 -r 10 -f -l ethx all"),
  332. isc::InvalidParameter);
  333. // -f and -i are mutually exclusive
  334. EXPECT_THROW(process("perfdhcp -6 -r 10 -f 10 -l ethx -i all"),
  335. isc::InvalidParameter);
  336. }
  337. TEST_F(CommandOptionsTest, ReleaseRate) {
  338. CommandOptions& opt = CommandOptions::instance();
  339. // If -F is specified together with -r the command line should
  340. // be accepted and the release rate should be set.
  341. EXPECT_NO_THROW(process("perfdhcp -6 -r 10 -F 10 -l ethx all"));
  342. EXPECT_EQ(10, opt.getReleaseRate());
  343. // Check that the release rate can be set to different value than
  344. // rate specified as -r<rate>. Also, swap -F and -r to make sure
  345. // that order doesn't matter.
  346. EXPECT_NO_THROW(process("perfdhcp -6 -F 5 -r 10 -l ethx all"));
  347. EXPECT_EQ(5, opt.getReleaseRate());
  348. // The release rate should not be greater than the rate.
  349. EXPECT_THROW(process("perfdhcp -6 -r 10 -F 11 -l ethx all"),
  350. isc::InvalidParameter);
  351. // The release-rate of 0 is invalid.
  352. EXPECT_THROW(process("perfdhcp -6 -r 10 -F 0 -l ethx all"),
  353. isc::InvalidParameter);
  354. // The negative rlease-rate is invalid.
  355. EXPECT_THROW(process("perfdhcp -6 -r 10 -F -5 -l ethx all"),
  356. isc::InvalidParameter);
  357. // If -r<rate> is not specified the -F<release-rate> should not
  358. // be accepted.
  359. EXPECT_THROW(process("perfdhcp -6 -F 10 -l ethx all"),
  360. isc::InvalidParameter);
  361. // Currently the -F<release-rate> can be specified for IPv6 mode
  362. // only.
  363. EXPECT_THROW(process("perfdhcp -4 -r 10 -F 10 -l ethx all"),
  364. isc::InvalidParameter);
  365. // Release rate should be specified.
  366. EXPECT_THROW(process("perfdhcp -6 -r 10 -F -l ethx all"),
  367. isc::InvalidParameter);
  368. // -F and -i are mutually exclusive
  369. EXPECT_THROW(process("perfdhcp -6 -r 10 -F 10 -l ethx -i all"),
  370. isc::InvalidParameter);
  371. }
  372. TEST_F(CommandOptionsTest, ReleaseRenew) {
  373. CommandOptions& opt = CommandOptions::instance();
  374. // It should be possible to specify the -F, -f and -r options.
  375. EXPECT_NO_THROW(process("perfdhcp -6 -r 10 -F 3 -f 5 -l ethx all"));
  376. EXPECT_EQ(10, opt.getRate());
  377. EXPECT_EQ(3, opt.getReleaseRate());
  378. EXPECT_EQ(5, opt.getRenewRate());
  379. // It should be possible to specify the -F and -f with the values which
  380. // sum is equal to the rate specified as -r<rate>.
  381. EXPECT_NO_THROW(process("perfdhcp -6 -r 8 -F 3 -f 5 -l ethx all"));
  382. EXPECT_EQ(8, opt.getRate());
  383. EXPECT_EQ(3, opt.getReleaseRate());
  384. EXPECT_EQ(5, opt.getRenewRate());
  385. // Check that the sum of the release and renew rate is not greater
  386. // than the rate specified as -r<rate>.
  387. EXPECT_THROW(process("perfdhcp -6 -F 6 -f 5 -r 10 -l ethx all"),
  388. isc::InvalidParameter);
  389. }
  390. TEST_F(CommandOptionsTest, ReportDelay) {
  391. CommandOptions& opt = CommandOptions::instance();
  392. EXPECT_NO_THROW(process("perfdhcp -r 100 -t 17 -l ethx all"));
  393. EXPECT_EQ(17, opt.getReportDelay());
  394. // Negative test cases
  395. // -t must be positive integer
  396. EXPECT_THROW(process("perfdhcp -r 10 -t -8 -l ethx all"),
  397. isc::InvalidParameter);
  398. EXPECT_THROW(process("perfdhcp -r 10 -t 0 -l ethx all"),
  399. isc::InvalidParameter);
  400. EXPECT_THROW(process("perfdhcp -r 10 -t s -l ethx all"),
  401. isc::InvalidParameter);
  402. }
  403. TEST_F(CommandOptionsTest, ClientsNum) {
  404. CommandOptions& opt = CommandOptions::instance();
  405. EXPECT_NO_THROW(process("perfdhcp -R 200 -l ethx all"));
  406. EXPECT_EQ(200, opt.getClientsNum());
  407. process("perfdhcp -R 0 -l ethx all");
  408. EXPECT_EQ(0, opt.getClientsNum());
  409. // Negative test cases
  410. // Number of clients must be non-negative integer
  411. EXPECT_THROW(process("perfdhcp -R -5 -l ethx all"),
  412. isc::InvalidParameter);
  413. EXPECT_THROW(process("perfdhcp -R gs -l ethx all"),
  414. isc::InvalidParameter);
  415. }
  416. TEST_F(CommandOptionsTest, Base) {
  417. CommandOptions& opt = CommandOptions::instance();
  418. uint8_t mac[6] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60 };
  419. uint8_t duid[14] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  420. 0x01, 0x01, 0x01, 0x10, 0x11, 0x1F, 0x14 };
  421. // Test DUID and MAC together.
  422. EXPECT_NO_THROW(process("perfdhcp -b DUID=0101010101010101010110111F14"
  423. " -b MAC=10::20::30::40::50::60"
  424. " -l 127.0.0.1 all"));
  425. std::vector<uint8_t> v1 = opt.getMacTemplate();
  426. std::vector<uint8_t> v2 = opt.getDuidTemplate();
  427. v2 = opt.getDuidTemplate();
  428. EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
  429. EXPECT_TRUE(std::equal(v2.begin(), v2.end(), duid));
  430. // Test valid DUID.
  431. EXPECT_NO_THROW(
  432. process("perfdhcp -b duid=0101010101010101010110111F14 -l 127.0.0.1 all")
  433. );
  434. ASSERT_EQ(sizeof(duid) / sizeof(uint8_t), v2.size());
  435. EXPECT_TRUE(std::equal(v2.begin(), v2.end(), duid));
  436. // Test mix of upper/lower case letters.
  437. EXPECT_NO_THROW(process("perfdhcp -b DuiD=0101010101010101010110111F14"
  438. " -b Mac=10::20::30::40::50::60"
  439. " -l 127.0.0.1 all"));
  440. v1 = opt.getMacTemplate();
  441. v2 = opt.getDuidTemplate();
  442. EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
  443. EXPECT_TRUE(std::equal(v2.begin(), v2.end(), duid));
  444. // Use "ether" instead of "mac".
  445. EXPECT_NO_THROW(process("perfdhcp -b ether=10::20::30::40::50::60"
  446. " -l 127.0.0.1 all"));
  447. v1 = opt.getMacTemplate();
  448. EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
  449. // Use "ETHER" in upper case.
  450. EXPECT_NO_THROW(process("perfdhcp -b ETHER=10::20::30::40::50::60"
  451. " -l 127.0.0.1 all"));
  452. v1 = opt.getMacTemplate();
  453. EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
  454. // "t" is invalid character in DUID
  455. EXPECT_THROW(process("perfdhcp -6 -l ethx -b "
  456. "duid=010101010101010101t110111F14 all"),
  457. isc::InvalidParameter);
  458. // "3x" is invalid value in MAC address
  459. EXPECT_THROW(process("perfdhcp -b mac=10::2::3x::4::5::6 -l ethx all"),
  460. isc::InvalidParameter);
  461. // Base is not specified
  462. EXPECT_THROW(process("perfdhcp -b -l ethx all"),
  463. isc::InvalidParameter);
  464. // Typo: should be mac= instead of mc=
  465. EXPECT_THROW(process("perfdhcp -l ethx -b mc=00:01:02:03::04:05 all"),
  466. isc::InvalidParameter);
  467. // Too short DUID (< 6).
  468. EXPECT_THROW(process("perfdhcp -l ethx -b duid=00010203 all"),
  469. isc::InvalidParameter);
  470. // Odd number of digits.
  471. EXPECT_THROW(process("perfdhcp -l ethx -b duid=000102030405060 all"),
  472. isc::InvalidParameter);
  473. // Too short MAC (!= 6).
  474. EXPECT_THROW(process("perfdhcp -l ethx -b mac=00:01:02:04 all"),
  475. isc::InvalidParameter);
  476. }
  477. TEST_F(CommandOptionsTest, DropTime) {
  478. CommandOptions& opt = CommandOptions::instance();
  479. EXPECT_NO_THROW(process("perfdhcp -l ethx -d 12 all"));
  480. ASSERT_EQ(2, opt.getDropTime().size());
  481. EXPECT_DOUBLE_EQ(12, opt.getDropTime()[0]);
  482. EXPECT_DOUBLE_EQ(1, opt.getDropTime()[1]);
  483. EXPECT_NO_THROW(process("perfdhcp -l ethx -d 2 -d 4.7 all"));
  484. ASSERT_EQ(2, opt.getDropTime().size());
  485. EXPECT_DOUBLE_EQ(2, opt.getDropTime()[0]);
  486. EXPECT_DOUBLE_EQ(4.7, opt.getDropTime()[1]);
  487. // Negative test cases
  488. // Drop time must not be negative
  489. EXPECT_THROW(process("perfdhcp -l ethx -d -2 -d 4.7 all"),
  490. isc::InvalidParameter);
  491. EXPECT_THROW(process("perfdhcp -l ethx -d -9.1 -d 0 all"),
  492. isc::InvalidParameter);
  493. }
  494. TEST_F(CommandOptionsTest, TimeOffset) {
  495. CommandOptions& opt = CommandOptions::instance();
  496. EXPECT_NO_THROW(process("perfdhcp -l ethx -T file1.x -T file2.x -E 4 all"));
  497. EXPECT_EQ(4, opt.getElapsedTimeOffset());
  498. // Negative test cases
  499. // Argument -E must be used with -T
  500. EXPECT_THROW(process("perfdhcp -l ethx -E 3 -i all"),
  501. isc::InvalidParameter);
  502. // Value in -E not specified
  503. EXPECT_THROW(process("perfdhcp -l ethx -T file.x -E -i all"),
  504. isc::InvalidParameter);
  505. // Value for -E must not be negative
  506. EXPECT_THROW(process("perfdhcp -l ethx -E -3 -T file.x all"),
  507. isc::InvalidParameter);
  508. }
  509. TEST_F(CommandOptionsTest, ExchangeMode) {
  510. CommandOptions& opt = CommandOptions::instance();
  511. process("perfdhcp -l ethx -i all");
  512. EXPECT_EQ(CommandOptions::DO_SA, opt.getExchangeMode());
  513. // Negative test cases
  514. // No template file specified
  515. EXPECT_THROW(process("perfdhcp -i -l ethx -X 3 all"),
  516. isc::InvalidParameter);
  517. // Offsets can't be used in simple exchanges (-i)
  518. EXPECT_THROW(process("perfdhcp -i -l ethx -O 2 -T file.x all"),
  519. isc::InvalidParameter);
  520. EXPECT_THROW(process("perfdhcp -i -l ethx -E 3 -T file.x all"),
  521. isc::InvalidParameter);
  522. EXPECT_THROW(process("perfdhcp -i -l ethx -S 1 -T file.x all"),
  523. isc::InvalidParameter);
  524. EXPECT_THROW(process("perfdhcp -i -l ethx -I 2 -T file.x all"),
  525. isc::InvalidParameter);
  526. }
  527. TEST_F(CommandOptionsTest, Offsets) {
  528. CommandOptions& opt = CommandOptions::instance();
  529. EXPECT_NO_THROW(process("perfdhcp -E5 -4 -I 2 -S3 -O 30 -X7 -l ethx "
  530. "-X3 -T file1.x -T file2.x all"));
  531. EXPECT_EQ(2, opt.getRequestedIpOffset());
  532. EXPECT_EQ(5, opt.getElapsedTimeOffset());
  533. EXPECT_EQ(3, opt.getServerIdOffset());
  534. ASSERT_EQ(2, opt.getRandomOffset().size());
  535. EXPECT_EQ(30, opt.getRandomOffset()[0]);
  536. EXPECT_EQ(30, opt.getRandomOffset()[1]);
  537. ASSERT_EQ(2, opt.getTransactionIdOffset().size());
  538. EXPECT_EQ(7, opt.getTransactionIdOffset()[0]);
  539. EXPECT_EQ(3, opt.getTransactionIdOffset()[1]);
  540. // Negative test cases
  541. // IP offset/IA_NA offset must be positive
  542. EXPECT_THROW(process("perfdhcp -6 -I 0 -l ethx all"),
  543. isc::InvalidParameter);
  544. EXPECT_THROW(process("perfdhcp -6 -I -4 -l ethx all"),
  545. isc::InvalidParameter);
  546. // TODO - other negative cases
  547. }
  548. TEST_F(CommandOptionsTest, LocalPort) {
  549. CommandOptions& opt = CommandOptions::instance();
  550. EXPECT_NO_THROW(process("perfdhcp -l ethx -L 2000 all"));
  551. EXPECT_EQ(2000, opt.getLocalPort());
  552. // Negative test cases
  553. // Local port must be between 0..65535
  554. EXPECT_THROW(process("perfdhcp -l ethx -L -2 all"),
  555. isc::InvalidParameter);
  556. EXPECT_THROW(process("perfdhcp -l ethx -L all"),
  557. isc::InvalidParameter);
  558. EXPECT_THROW(process("perfdhcp -l ethx -L 65540 all"),
  559. isc::InvalidParameter);
  560. }
  561. TEST_F(CommandOptionsTest, Preload) {
  562. CommandOptions& opt = CommandOptions::instance();
  563. EXPECT_NO_THROW(process("perfdhcp -1 -P 3 -l ethx all"));
  564. EXPECT_EQ(3, opt.getPreload());
  565. // Negative test cases
  566. // Number of preload packages must not be negative integer
  567. EXPECT_THROW(process("perfdhcp -P -1 -l ethx all"),
  568. isc::InvalidParameter);
  569. EXPECT_THROW(process("perfdhcp -P -3 -l ethx all"),
  570. isc::InvalidParameter);
  571. }
  572. TEST_F(CommandOptionsTest, Seed) {
  573. CommandOptions& opt = CommandOptions::instance();
  574. EXPECT_NO_THROW(process("perfdhcp -6 -P 2 -s 23 -l ethx all"));
  575. EXPECT_EQ(23, opt.getSeed());
  576. EXPECT_TRUE(opt.isSeeded());
  577. EXPECT_NO_THROW(process("perfdhcp -6 -P 2 -s 0 -l ethx all"));
  578. EXPECT_EQ(0, opt.getSeed());
  579. EXPECT_FALSE(opt.isSeeded());
  580. // Negtaive test cases
  581. // Seed must be non-negative integer
  582. EXPECT_THROW(process("perfdhcp -6 -P 2 -s -5 -l ethx all"),
  583. isc::InvalidParameter);
  584. EXPECT_THROW(process("perfdhcp -6 -P 2 -s -l ethx all"),
  585. isc::InvalidParameter);
  586. }
  587. TEST_F(CommandOptionsTest, TemplateFiles) {
  588. CommandOptions& opt = CommandOptions::instance();
  589. EXPECT_NO_THROW(process("perfdhcp -T file1.x -l ethx all"));
  590. ASSERT_EQ(1, opt.getTemplateFiles().size());
  591. EXPECT_EQ("file1.x", opt.getTemplateFiles()[0]);
  592. EXPECT_NO_THROW(process("perfdhcp -T file1.x -s 12 -w start -T file2.x -4 -l ethx all"));
  593. ASSERT_EQ(2, opt.getTemplateFiles().size());
  594. EXPECT_EQ("file1.x", opt.getTemplateFiles()[0]);
  595. EXPECT_EQ("file2.x", opt.getTemplateFiles()[1]);
  596. // Negative test cases
  597. // No template file specified
  598. EXPECT_THROW(process("perfdhcp -s 12 -T -l ethx all"),
  599. isc::InvalidParameter);
  600. // Too many template files specified
  601. EXPECT_THROW(process("perfdhcp -s 12 -l ethx -T file.x "
  602. "-T file.x -T file.x all"),
  603. isc::InvalidParameter);
  604. }
  605. TEST_F(CommandOptionsTest, Wrapped) {
  606. CommandOptions& opt = CommandOptions::instance();
  607. EXPECT_NO_THROW(process("perfdhcp -B -w start -i -l ethx all"));
  608. EXPECT_EQ("start", opt.getWrapped());
  609. // Negative test cases
  610. // Missing command after -w, expected start/stop
  611. EXPECT_THROW(process("perfdhcp -B -i -l ethx -w all"),
  612. isc::InvalidParameter);
  613. }
  614. TEST_F(CommandOptionsTest, Diagnostics) {
  615. CommandOptions& opt = CommandOptions::instance();
  616. EXPECT_NO_THROW(process("perfdhcp -l ethx -i -x asTe all"));
  617. EXPECT_EQ("asTe", opt.getDiags());
  618. // Negative test cases
  619. // No diagnostics string specified
  620. EXPECT_THROW(process("perfdhcp -l ethx -i -x all"),
  621. isc::InvalidParameter);
  622. }
  623. TEST_F(CommandOptionsTest, Aggressivity) {
  624. CommandOptions& opt = CommandOptions::instance();
  625. process("perfdhcp -a 10 -l 192.168.0.1 all");
  626. EXPECT_EQ(10, opt.getAggressivity());
  627. // Negative test cases
  628. // Aggressivity must be non negative integer
  629. EXPECT_THROW(process("perfdhcp -l ethx -a 0 all"),
  630. isc::InvalidParameter);
  631. EXPECT_THROW(process("perfdhcp -l ethx -a all"),
  632. isc::InvalidParameter);
  633. EXPECT_THROW(process("perfdhcp -a -2 -l ethx -a 3 all"),
  634. isc::InvalidParameter);
  635. }
  636. TEST_F(CommandOptionsTest, MaxDrop) {
  637. CommandOptions& opt = CommandOptions::instance();
  638. EXPECT_NO_THROW(process("perfdhcp -D 25 -l ethx -r 10 all"));
  639. EXPECT_EQ(25, opt.getMaxDrop()[0]);
  640. EXPECT_NO_THROW(process("perfdhcp -D 25 -l ethx -D 15 -r 10 all"));
  641. EXPECT_EQ(25, opt.getMaxDrop()[0]);
  642. EXPECT_EQ(15, opt.getMaxDrop()[1]);
  643. EXPECT_NO_THROW(process("perfdhcp -D 15% -l ethx -r 10 all"));
  644. EXPECT_EQ(15, opt.getMaxDropPercentage()[0]);
  645. EXPECT_NO_THROW(process("perfdhcp -D 15% -D25% -l ethx -r 10 all"));
  646. EXPECT_EQ(15, opt.getMaxDropPercentage()[0]);
  647. EXPECT_EQ(25, opt.getMaxDropPercentage()[1]);
  648. EXPECT_NO_THROW(process("perfdhcp -D 1% -D 99% -l ethx -r 10 all"));
  649. EXPECT_EQ(1, opt.getMaxDropPercentage()[0]);
  650. EXPECT_EQ(99, opt.getMaxDropPercentage()[1]);
  651. // Negative test cases
  652. // Too many -D<value> options
  653. EXPECT_THROW(process("perfdhcp -D 0% -D 1 -l ethx -r20 -D 3 all"),
  654. isc::InvalidParameter);
  655. // Too many -D<value%> options
  656. EXPECT_THROW(process("perfdhcp -D 99% -D 13% -l ethx -r20 -D 10% all"),
  657. isc::InvalidParameter);
  658. // Percentage is out of bounds
  659. EXPECT_THROW(process("perfdhcp -D101% -D 13% -l ethx -r20 all"),
  660. isc::InvalidParameter);
  661. EXPECT_THROW(process("perfdhcp -D0% -D 13% -l ethx -r20 all"),
  662. isc::InvalidParameter);
  663. }
  664. TEST_F(CommandOptionsTest, NumRequest) {
  665. CommandOptions& opt = CommandOptions::instance();
  666. EXPECT_NO_THROW(process("perfdhcp -n 1000 -r 10 -l ethx all"));
  667. EXPECT_EQ(1000, opt.getNumRequests()[0]);
  668. EXPECT_NO_THROW(process("perfdhcp -n 5 -r 10 -n 500 -l ethx all"));
  669. EXPECT_EQ(5, opt.getNumRequests()[0]);
  670. EXPECT_EQ(500, opt.getNumRequests()[1]);
  671. // Negative test cases
  672. // Too many -n<value> parameters, expected maximum 2
  673. EXPECT_THROW(process("perfdhcp -n 1 -n 2 -l ethx -n3 -r 20 all"),
  674. isc::InvalidParameter);
  675. // Num request must be positive integer
  676. EXPECT_THROW(process("perfdhcp -n 1 -n -22 -l ethx -r 10 all"),
  677. isc::InvalidParameter);
  678. EXPECT_THROW(process("perfdhcp -n 0 -l ethx -r 10 all"),
  679. isc::InvalidParameter);
  680. }
  681. TEST_F(CommandOptionsTest, Period) {
  682. CommandOptions& opt = CommandOptions::instance();
  683. EXPECT_NO_THROW(process("perfdhcp -p 120 -l ethx -r 100 all"));
  684. EXPECT_EQ(120, opt.getPeriod());
  685. // Negative test cases
  686. // Test period must be positive integer
  687. EXPECT_THROW(process("perfdhcp -p 0 -l ethx -r 50 all"),
  688. isc::InvalidParameter);
  689. EXPECT_THROW(process("perfdhcp -p -3 -l ethx -r 50 all"),
  690. isc::InvalidParameter);
  691. }
  692. TEST_F(CommandOptionsTest, Interface) {
  693. // In order to make this test portable we need to know
  694. // at least one interface name on OS where test is run.
  695. // Interface Manager has ability to detect interfaces.
  696. // Although we don't call initIsInterface explicitly
  697. // here it is called by CommandOptions object interally
  698. // so this function is covered by the test.
  699. dhcp::IfaceMgr& iface_mgr = dhcp::IfaceMgr::instance();
  700. const dhcp::IfaceMgr::IfaceCollection& ifaces = iface_mgr.getIfaces();
  701. std::string iface_name;
  702. CommandOptions& opt = CommandOptions::instance();
  703. // The local loopback interface should be available.
  704. // If no interface have been found for any reason we should
  705. // not fail this test.
  706. if (ifaces.size() > 0) {
  707. // Get the name of the interface we detected.
  708. iface_name = (*ifaces.begin())->getName();
  709. // Use the name in the command parser.
  710. ASSERT_NO_THROW(process("perfdhcp -4 -l " + iface_name + " abc"));
  711. // We expect that command parser will detect that argument
  712. // specified along with '-l' is the interface name.
  713. EXPECT_TRUE(opt.isInterface());
  714. // If neither interface nor server is specified then
  715. // exception is expected to be thrown.
  716. EXPECT_THROW(process("perfdhcp -4"), isc::InvalidParameter);
  717. }
  718. }
  719. TEST_F(CommandOptionsTest, Server) {
  720. CommandOptions& opt = CommandOptions::instance();
  721. // There is at least server parameter needed. If server is not
  722. // specified the local interface must be specified.
  723. // The server value equal to 'all' means use broadcast.
  724. ASSERT_NO_THROW(process("perfdhcp all"));
  725. // Once command line is parsed we expect that server name is
  726. // set to broadcast address because 'all' was specified.
  727. EXPECT_TRUE(opt.isBroadcast());
  728. // The broadcast address is 255.255.255.255.
  729. EXPECT_EQ(DHCP_IPV4_BROADCAST_ADDRESS, opt.getServerName());
  730. // When all is specified for DHCPv6 mode we expect
  731. // FF02::1:2 as a server name which means All DHCP
  732. // servers and relay agents in local network segment
  733. ASSERT_NO_THROW(process("perfdhcp -6 all"));
  734. EXPECT_EQ(ALL_DHCP_RELAY_AGENTS_AND_SERVERS, opt.getServerName());
  735. // When server='servers' in DHCPv6 mode we expect
  736. // FF05::1:3 as server name which means All DHCP
  737. // servers in local network.
  738. ASSERT_NO_THROW(process("perfdhcp -6 servers"));
  739. EXPECT_EQ(ALL_DHCP_SERVERS, opt.getServerName());
  740. // If server name is neither 'all' nor 'servers'
  741. // the given argument value is expected to be
  742. // returned.
  743. ASSERT_NO_THROW(process("perfdhcp -6 abc"));
  744. EXPECT_EQ("abc", opt.getServerName());
  745. }