token_unittest.cc 93 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329
  1. // Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <config.h>
  7. #include <fstream>
  8. #include <eval/token.h>
  9. #include <dhcp/pkt4.h>
  10. #include <dhcp/pkt6.h>
  11. #include <dhcp/dhcp4.h>
  12. #include <dhcp/dhcp6.h>
  13. #include <dhcp/option_string.h>
  14. #include <dhcp/option_vendor.h>
  15. #include <dhcp/option_vendor_class.h>
  16. #include <log/logger_manager.h>
  17. #include <log/logger_name.h>
  18. #include <log/logger_support.h>
  19. #include <testutils/log_utils.h>
  20. #include <boost/shared_ptr.hpp>
  21. #include <boost/scoped_ptr.hpp>
  22. #include <gtest/gtest.h>
  23. #include <arpa/inet.h>
  24. using namespace std;
  25. using namespace isc::dhcp;
  26. using namespace isc::asiolink;
  27. using namespace isc::log;
  28. using namespace isc::dhcp::test;
  29. namespace {
  30. /// @brief Test fixture for testing Tokens.
  31. ///
  32. /// This class provides several convenience objects to be used during testing
  33. /// of the Token family of classes.
  34. class TokenTest : public LogContentTest {
  35. public:
  36. /// @brief Initializes Pkt4,Pkt6 and options that can be useful for
  37. /// evaluation tests.
  38. TokenTest() {
  39. pkt4_.reset(new Pkt4(DHCPDISCOVER, 12345));
  40. pkt6_.reset(new Pkt6(DHCPV6_SOLICIT, 12345));
  41. // Add options with easily identifiable strings in them
  42. option_str4_.reset(new OptionString(Option::V4, 100, "hundred4"));
  43. option_str6_.reset(new OptionString(Option::V6, 100, "hundred6"));
  44. pkt4_->addOption(option_str4_);
  45. pkt6_->addOption(option_str6_);
  46. }
  47. /// @brief Inserts RAI option with several suboptions
  48. ///
  49. /// The structure inserted is:
  50. /// - RAI (option 82)
  51. /// - option 1 (containing string "one")
  52. /// - option 13 (containing string "thirteen")
  53. void insertRelay4Option() {
  54. // RAI (Relay Agent Information) option
  55. OptionPtr rai(new Option(Option::V4, DHO_DHCP_AGENT_OPTIONS));
  56. OptionPtr sub1(new OptionString(Option::V4, 1, "one"));
  57. OptionPtr sub13(new OptionString(Option::V4, 13, "thirteen"));
  58. rai->addOption(sub1);
  59. rai->addOption(sub13);
  60. pkt4_->addOption(rai);
  61. }
  62. /// @brief Adds relay encapsulations with some suboptions
  63. ///
  64. /// This will add 2 relay encapsulations all will have
  65. /// msg_type of RELAY_FORW
  66. /// Relay 0 (closest to server) will have
  67. /// linkaddr = peeraddr = 0, hop-count = 1
  68. /// option 100 "hundred.zero", option 101 "hundredone.zero"
  69. /// Relay 1 (closest to client) will have
  70. /// linkaddr 1::1= peeraddr = 1::2, hop-count = 0
  71. /// option 100 "hundred.one", option 102 "hundredtwo.one"
  72. void addRelay6Encapsulations() {
  73. // First relay
  74. Pkt6::RelayInfo relay0;
  75. relay0.msg_type_ = DHCPV6_RELAY_FORW;
  76. relay0.hop_count_ = 1;
  77. relay0.linkaddr_ = isc::asiolink::IOAddress("::");
  78. relay0.peeraddr_ = isc::asiolink::IOAddress("::");
  79. OptionPtr optRelay01(new OptionString(Option::V6, 100,
  80. "hundred.zero"));
  81. OptionPtr optRelay02(new OptionString(Option::V6, 101,
  82. "hundredone.zero"));
  83. relay0.options_.insert(make_pair(optRelay01->getType(), optRelay01));
  84. relay0.options_.insert(make_pair(optRelay02->getType(), optRelay02));
  85. pkt6_->addRelayInfo(relay0);
  86. // Second relay
  87. Pkt6::RelayInfo relay1;
  88. relay1.msg_type_ = DHCPV6_RELAY_FORW;
  89. relay1.hop_count_ = 0;
  90. relay1.linkaddr_ = isc::asiolink::IOAddress("1::1");
  91. relay1.peeraddr_ = isc::asiolink::IOAddress("1::2");
  92. OptionPtr optRelay11(new OptionString(Option::V6, 100,
  93. "hundred.one"));
  94. OptionPtr optRelay12(new OptionString(Option::V6, 102,
  95. "hundredtwo.one"));
  96. relay1.options_.insert(make_pair(optRelay11->getType(), optRelay11));
  97. relay1.options_.insert(make_pair(optRelay12->getType(), optRelay12));
  98. pkt6_->addRelayInfo(relay1);
  99. }
  100. /// @brief Verify that the relay6 option evaluatiosn work properly
  101. ///
  102. /// Given the nesting level and option code extract the option
  103. /// and compare it to the expected string.
  104. ///
  105. /// @param test_level The nesting level
  106. /// @param test_code The code of the option to extract
  107. /// @param result_addr The expected result of the address as a string
  108. void verifyRelay6Option(const uint8_t test_level,
  109. const uint16_t test_code,
  110. const TokenOption::RepresentationType& test_rep,
  111. const std::string& result_string) {
  112. // Create the token
  113. ASSERT_NO_THROW(t_.reset(new TokenRelay6Option(test_level,
  114. test_code,
  115. test_rep)));
  116. // We should be able to evaluate it
  117. EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
  118. // We should have one value on the stack
  119. ASSERT_EQ(1, values_.size());
  120. // And it should match the expected result
  121. // Invalid nesting levels result in a 0 length string
  122. EXPECT_EQ(result_string, values_.top());
  123. // Then we clear the stack
  124. clearStack();
  125. }
  126. /// @brief Verify that the relay6 field evaluations work properly
  127. ///
  128. /// Given the nesting level, the field to extract and the expected
  129. /// address create a token and evaluate it then compare the addresses
  130. ///
  131. /// @param test_level The nesting level
  132. /// @param test_field The type of the field to extract
  133. /// @param result_addr The expected result of the address as a string
  134. void verifyRelay6Eval(const uint8_t test_level,
  135. const TokenRelay6Field::FieldType test_field,
  136. const int result_len,
  137. const uint8_t result_addr[]) {
  138. // Create the token
  139. ASSERT_NO_THROW(t_.reset(new TokenRelay6Field(test_level, test_field)));
  140. // We should be able to evaluate it
  141. EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
  142. // We should have one value on the stack
  143. ASSERT_EQ(1, values_.size());
  144. // And it should match the expected result
  145. // Invalid nesting levels result in a 0 length string
  146. EXPECT_EQ(result_len, values_.top().size());
  147. if (result_len != 0) {
  148. EXPECT_EQ(0, memcmp(result_addr, &values_.top()[0], result_len));
  149. }
  150. // Then we clear the stack
  151. clearStack();
  152. }
  153. /// @brief Convenience function. Removes token and values stacks.
  154. void clearStack() {
  155. while (!values_.empty()) {
  156. values_.pop();
  157. }
  158. t_.reset();
  159. }
  160. /// @brief Aux. function that stores integer values as 4 bytes string.
  161. ///
  162. /// @param value integer value to be stored
  163. /// @return 4 bytes long string with encoded value.
  164. string encode(uint32_t value) {
  165. string tmp(4,0);
  166. tmp[0] = value >> 24;
  167. tmp[1] = value >> 16;
  168. tmp[2] = value >> 8;
  169. tmp[3] = value;
  170. return (tmp);
  171. }
  172. TokenPtr t_; ///< Just a convenience pointer
  173. ValueStack values_; ///< evaluated values will be stored here
  174. Pkt4Ptr pkt4_; ///< A stub DHCPv4 packet
  175. Pkt6Ptr pkt6_; ///< A stub DHCPv6 packet
  176. OptionPtr option_str4_; ///< A string option for DHCPv4
  177. OptionPtr option_str6_; ///< A string option for DHCPv6
  178. OptionVendorPtr vendor_; ///< Vendor option used during tests
  179. OptionVendorClassPtr vendor_class_; ///< Vendor class option used during tests
  180. /// @brief Verify that the substring eval works properly
  181. ///
  182. /// This function takes the parameters and sets up the value
  183. /// stack then executes the eval and checks the results.
  184. ///
  185. /// @param test_string The string to operate on
  186. /// @param test_start The postion to start when getting a substring
  187. /// @param test_length The length of the substring to get
  188. /// @param result_string The expected result of the eval
  189. /// @param should_throw The eval will throw
  190. void verifySubstringEval(const std::string& test_string,
  191. const std::string& test_start,
  192. const std::string& test_length,
  193. const std::string& result_string,
  194. bool should_throw = false) {
  195. // create the token
  196. ASSERT_NO_THROW(t_.reset(new TokenSubstring()));
  197. // push values on stack
  198. values_.push(test_string);
  199. values_.push(test_start);
  200. values_.push(test_length);
  201. // evaluate the token
  202. if (should_throw) {
  203. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
  204. ASSERT_EQ(0, values_.size());
  205. } else {
  206. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  207. // verify results
  208. ASSERT_EQ(1, values_.size());
  209. EXPECT_EQ(result_string, values_.top());
  210. // remove result
  211. values_.pop();
  212. }
  213. }
  214. /// @brief Creates vendor-option with specified value and adds it to packet
  215. ///
  216. /// This method creates specified vendor option, removes any existing
  217. /// vendor options and adds the new one to v4 or v6 packet.
  218. ///
  219. /// @param u universe (V4 or V6)
  220. /// @param vendor_id specifies enterprise-id value.
  221. void setVendorOption(Option::Universe u, uint32_t vendor_id) {
  222. vendor_.reset(new OptionVendor(u, vendor_id));
  223. switch (u) {
  224. case Option::V4:
  225. pkt4_->delOption(DHO_VIVSO_SUBOPTIONS);
  226. pkt4_->addOption(vendor_);
  227. break;
  228. case Option::V6:
  229. pkt6_->delOption(D6O_VENDOR_OPTS);
  230. pkt6_->addOption(vendor_);
  231. break;
  232. }
  233. }
  234. /// @brief Creates vendor-class option with specified values and adds it to packet
  235. ///
  236. /// This method creates specified vendor-class option, removes any existing
  237. /// vendor class options and adds the new one to v4 or v6 packet.
  238. /// It also creates data tuples with greek alphabet names.
  239. ///
  240. /// @param u universe (V4 or V6)
  241. /// @param vendor_id specifies enterprise-id value.
  242. /// @param tuples_size number of data tuples to create.
  243. void setVendorClassOption(Option::Universe u, uint32_t vendor_id,
  244. size_t tuples_size = 0) {
  245. // Create the option first.
  246. vendor_class_.reset(new OptionVendorClass(u, vendor_id));
  247. // Now let's add specified number of data tuples
  248. OpaqueDataTuple::LengthFieldType len = (u == Option::V4?OpaqueDataTuple::LENGTH_1_BYTE:
  249. OpaqueDataTuple::LENGTH_2_BYTES);
  250. const char * content[] = { "alpha", "beta", "delta", "gamma", "epsilon",
  251. "zeta", "eta", "theta", "iota", "kappa" };
  252. ASSERT_TRUE(tuples_size < sizeof(content));
  253. for (int i = 0; i < tuples_size; i++) {
  254. OpaqueDataTuple tuple(len);
  255. tuple.assign(string(content[i]));
  256. if (u == Option::V4 && i == 0) {
  257. // vendor-clas for v4 has a pecurilar quirk. The first tuple is being
  258. // added, even if there's no data at all.
  259. vendor_class_->setTuple(0, tuple);
  260. } else {
  261. vendor_class_->addTuple(tuple);
  262. }
  263. }
  264. switch (u) {
  265. case Option::V4:
  266. pkt4_->delOption(DHO_VIVCO_SUBOPTIONS);
  267. pkt4_->addOption(vendor_class_);
  268. break;
  269. case Option::V6:
  270. pkt6_->delOption(D6O_VENDOR_CLASS);
  271. pkt6_->addOption(vendor_class_);
  272. break;
  273. }
  274. }
  275. /// @brief Auxiliary function that evaluates tokens and checks result
  276. ///
  277. /// Depending on the universe, either pkt4_ or pkt6_ are supposed to have
  278. /// all the necessary values and options set. The result is checked
  279. /// on the values_ stack.
  280. ///
  281. /// @param u universe (V4 or V6)
  282. /// @param expected_result text representation of the expected outcome
  283. void evaluate(Option::Universe u, std::string expected_result) {
  284. switch (u) {
  285. case Option::V4:
  286. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  287. break;
  288. case Option::V6:
  289. EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
  290. break;
  291. default:
  292. ADD_FAILURE() << "Invalid universe specified.";
  293. }
  294. ASSERT_EQ(1, values_.size());
  295. EXPECT_EQ(expected_result, values_.top());
  296. }
  297. /// @brief Tests if vendor token behaves properly.
  298. ///
  299. /// @param u universe (V4 or V6)
  300. /// @param token_vendor_id enterprise-id used in the token
  301. /// @param option_vendor_id enterprise-id used in option (0 means don't
  302. /// create the option)
  303. /// @param expected_result text representation of the expected outcome
  304. void testVendorExists(Option::Universe u, uint32_t token_vendor_id,
  305. uint32_t option_vendor_id, std::string expected_result) {
  306. // Let's clear any old values, so we can run multiple cases in each test
  307. clearStack();
  308. // Create the token
  309. ASSERT_NO_THROW(t_.reset(new TokenVendor(u, token_vendor_id,
  310. TokenOption::EXISTS)));
  311. // If specified option is non-zero, create it.
  312. if (option_vendor_id) {
  313. setVendorOption(u, option_vendor_id);
  314. }
  315. evaluate(u, expected_result);
  316. }
  317. /// @brief Tests if vendor token properly returns enterprise-id.
  318. ///
  319. /// @param u universe (V4 or V6)
  320. /// @param option_vendor_id enterprise-id used in option (0 means don't
  321. /// create the option)
  322. /// @param expected_result text representation of the expected outcome
  323. void testVendorEnterprise(Option::Universe u, uint32_t option_vendor_id,
  324. std::string expected_result) {
  325. // Let's clear any old values, so we can run multiple cases in each test
  326. clearStack();
  327. ASSERT_NO_THROW(t_.reset(new TokenVendor(u, 0, TokenVendor::ENTERPRISE_ID)));
  328. if (option_vendor_id) {
  329. setVendorOption(u, option_vendor_id);
  330. }
  331. evaluate(u, expected_result);
  332. }
  333. /// @brief Tests if vendor class token properly returns enterprise-id.
  334. ///
  335. /// @param u universe (V4 or V6)
  336. /// @param option_vendor_id enterprise-id used in option (0 means don't
  337. /// create the option)
  338. /// @param expected_result text representation of the expected outcome
  339. void testVendorClassEnterprise(Option::Universe u, uint32_t option_vendor_id,
  340. std::string expected_result) {
  341. // Let's clear any old values, so we can run multiple cases in each test
  342. clearStack();
  343. ASSERT_NO_THROW(t_.reset(new TokenVendorClass(u, 0, TokenVendor::ENTERPRISE_ID)));
  344. if (option_vendor_id) {
  345. setVendorClassOption(u, option_vendor_id);
  346. }
  347. evaluate(u, expected_result);
  348. }
  349. /// @brief Tests if vendor class token can report existence properly.
  350. ///
  351. /// @param u universe (V4 or V6)
  352. /// @param token_vendor_id enterprise-id used in the token
  353. /// @param option_vendor_id enterprise-id used in option (0 means don't
  354. /// create the option)
  355. /// @param expected_result text representation of the expected outcome
  356. void testVendorClassExists(Option::Universe u, uint32_t token_vendor_id,
  357. uint32_t option_vendor_id, std::string expected_result) {
  358. // Let's clear any old values, so we can run multiple cases in each test
  359. clearStack();
  360. ASSERT_NO_THROW(t_.reset(new TokenVendorClass(u, token_vendor_id,
  361. TokenOption::EXISTS)));
  362. if (option_vendor_id) {
  363. setVendorClassOption(u, option_vendor_id);
  364. }
  365. evaluate(u, expected_result);
  366. }
  367. /// @brief Tests if vendor class token can handle sub-options properly.
  368. ///
  369. /// @param u universe (V4 or V6)
  370. /// @param token_vendor_id enterprise-id used in the token
  371. /// @param token_option_code option code in the token
  372. /// @param option_vendor_id enterprise-id used in option (0 means don't
  373. /// create the option)
  374. /// @param option_code sub-option code (0 means don't create suboption)
  375. /// @param expected_result text representation of the expected outcome
  376. void testVendorSuboption(Option::Universe u,
  377. uint32_t token_vendor_id, uint16_t token_option_code,
  378. uint32_t option_vendor_id, uint16_t option_code,
  379. TokenOption::RepresentationType repr, std::string expected) {
  380. // Let's clear any old values, so we can run multiple cases in each test
  381. clearStack();
  382. ASSERT_NO_THROW(t_.reset(new TokenVendor(u, token_vendor_id, repr,
  383. token_option_code)));
  384. if (option_vendor_id) {
  385. setVendorOption(u, option_vendor_id);
  386. if (option_code) {
  387. ASSERT_TRUE(vendor_);
  388. OptionPtr subopt(new OptionString(u, option_code, "alpha"));
  389. vendor_->addOption(subopt);
  390. }
  391. }
  392. evaluate(u, expected);
  393. }
  394. /// @brief Tests if vendor class token can handle data chunks properly.
  395. ///
  396. /// @param u universe (V4 or V6)
  397. /// @param token_vendor_id enterprise-id used in the token
  398. /// @param token_index data index used in the token
  399. /// @param option_vendor_id enterprise-id used in option (0 means don't
  400. /// create the option)
  401. /// @param data_tuples number of data tuples in the option
  402. /// @param expected_result text representation of the expected outcome
  403. void testVendorClassData(Option::Universe u,
  404. uint32_t token_vendor_id, uint16_t token_index,
  405. uint32_t option_vendor_id, uint16_t data_tuples,
  406. std::string expected) {
  407. // Let's clear any old values, so we can run multiple cases in each test
  408. clearStack();
  409. ASSERT_NO_THROW(t_.reset(new TokenVendorClass(u, token_vendor_id,
  410. TokenVendor::DATA, token_index)));
  411. if (option_vendor_id) {
  412. setVendorClassOption(u, option_vendor_id, data_tuples);
  413. }
  414. evaluate(u, expected);
  415. }
  416. };
  417. // This tests the toBool() conversions
  418. TEST_F(TokenTest, toBool) {
  419. ASSERT_NO_THROW(Token::toBool("true"));
  420. EXPECT_TRUE(Token::toBool("true"));
  421. ASSERT_NO_THROW(Token::toBool("false"));
  422. EXPECT_FALSE(Token::toBool("false"));
  423. // Token::toBool() is case-sensitive
  424. EXPECT_THROW(Token::toBool("True"), EvalTypeError);
  425. EXPECT_THROW(Token::toBool("TRUE"), EvalTypeError);
  426. // Proposed aliases
  427. EXPECT_THROW(Token::toBool("1"), EvalTypeError);
  428. EXPECT_THROW(Token::toBool("0"), EvalTypeError);
  429. EXPECT_THROW(Token::toBool(""), EvalTypeError);
  430. }
  431. // This simple test checks that a TokenString, representing a constant string,
  432. // can be used in Pkt4 evaluation. (The actual packet is not used)
  433. TEST_F(TokenTest, string4) {
  434. // Store constant string "foo" in the TokenString object.
  435. ASSERT_NO_THROW(t_.reset(new TokenString("foo")));
  436. // Make sure that the token can be evaluated without exceptions.
  437. ASSERT_NO_THROW(t_->evaluate(*pkt4_, values_));
  438. // Check that the evaluation put its value on the values stack.
  439. ASSERT_EQ(1, values_.size());
  440. EXPECT_EQ("foo", values_.top());
  441. // Check that the debug output was correct. Add the strings
  442. // to the test vector in the class and then call checkFile
  443. // for comparison
  444. addString("EVAL_DEBUG_STRING Pushing text string 'foo'");
  445. EXPECT_TRUE(checkFile());
  446. }
  447. // This simple test checks that a TokenString, representing a constant string,
  448. // can be used in Pkt6 evaluation. (The actual packet is not used)
  449. TEST_F(TokenTest, string6) {
  450. // Store constant string "foo" in the TokenString object.
  451. ASSERT_NO_THROW(t_.reset(new TokenString("foo")));
  452. // Make sure that the token can be evaluated without exceptions.
  453. ASSERT_NO_THROW(t_->evaluate(*pkt6_, values_));
  454. // Check that the evaluation put its value on the values stack.
  455. ASSERT_EQ(1, values_.size());
  456. EXPECT_EQ("foo", values_.top());
  457. // Check that the debug output was correct. Add the strings
  458. // to the test vector in the class and then call checkFile
  459. // for comparison
  460. addString("EVAL_DEBUG_STRING Pushing text string 'foo'");
  461. EXPECT_TRUE(checkFile());
  462. }
  463. // This simple test checks that a TokenHexString, representing a constant
  464. // string coded in hexadecimal, can be used in Pkt4 evaluation.
  465. // (The actual packet is not used)
  466. TEST_F(TokenTest, hexstring4) {
  467. TokenPtr empty;
  468. TokenPtr bad;
  469. TokenPtr nodigit;
  470. TokenPtr baddigit;
  471. TokenPtr bell;
  472. TokenPtr foo;
  473. TokenPtr cookie;
  474. // Store constant empty hexstring "" ("") in the TokenHexString object.
  475. ASSERT_NO_THROW(empty.reset(new TokenHexString("")));
  476. // Store bad encoded hexstring "0abc" ("").
  477. ASSERT_NO_THROW(bad.reset(new TokenHexString("0abc")));
  478. // Store hexstring with no digits "0x" ("").
  479. ASSERT_NO_THROW(nodigit.reset(new TokenHexString("0x")));
  480. // Store hexstring with a bad hexdigit "0xxabc" ("").
  481. ASSERT_NO_THROW(baddigit.reset(new TokenHexString("0xxabc")));
  482. // Store hexstring with an odd number of hexdigits "0x7" ("\a").
  483. ASSERT_NO_THROW(bell.reset(new TokenHexString("0x7")));
  484. // Store constant hexstring "0x666f6f" ("foo").
  485. ASSERT_NO_THROW(foo.reset(new TokenHexString("0x666f6f")));
  486. // Store constant hexstring "0x63825363" (DHCP_OPTIONS_COOKIE).
  487. ASSERT_NO_THROW(cookie.reset(new TokenHexString("0x63825363")));
  488. // Make sure that tokens can be evaluated without exceptions,
  489. // and verify the debug output
  490. ASSERT_NO_THROW(empty->evaluate(*pkt4_, values_));
  491. ASSERT_NO_THROW(bad->evaluate(*pkt4_, values_));
  492. ASSERT_NO_THROW(nodigit->evaluate(*pkt4_, values_));
  493. ASSERT_NO_THROW(baddigit->evaluate(*pkt4_, values_));
  494. ASSERT_NO_THROW(bell->evaluate(*pkt4_, values_));
  495. ASSERT_NO_THROW(foo->evaluate(*pkt4_, values_));
  496. ASSERT_NO_THROW(cookie->evaluate(*pkt4_, values_));
  497. // Check that the evaluation put its value on the values stack.
  498. ASSERT_EQ(7, values_.size());
  499. uint32_t expected = htonl(DHCP_OPTIONS_COOKIE);
  500. EXPECT_EQ(4, values_.top().size());
  501. EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
  502. values_.pop();
  503. EXPECT_EQ("foo", values_.top());
  504. values_.pop();
  505. EXPECT_EQ("\a", values_.top());
  506. values_.pop();
  507. EXPECT_EQ("", values_.top());
  508. values_.pop();
  509. EXPECT_EQ("", values_.top());
  510. values_.pop();
  511. EXPECT_EQ("", values_.top());
  512. values_.pop();
  513. EXPECT_EQ("", values_.top());
  514. // Check that the debug output was correct. Add the strings
  515. // to the test vector in the class and then call checkFile
  516. // for comparison
  517. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
  518. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
  519. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
  520. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
  521. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x07");
  522. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x666F6F");
  523. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x63825363");
  524. EXPECT_TRUE(checkFile());
  525. }
  526. // This simple test checks that a TokenHexString, representing a constant
  527. // string coded in hexadecimal, can be used in Pkt6 evaluation.
  528. // (The actual packet is not used)
  529. TEST_F(TokenTest, hexstring6) {
  530. TokenPtr empty;
  531. TokenPtr bad;
  532. TokenPtr nodigit;
  533. TokenPtr baddigit;
  534. TokenPtr bell;
  535. TokenPtr foo;
  536. TokenPtr cookie;
  537. // Store constant empty hexstring "" ("") in the TokenHexString object.
  538. ASSERT_NO_THROW(empty.reset(new TokenHexString("")));
  539. // Store bad encoded hexstring "0abc" ("").
  540. ASSERT_NO_THROW(bad.reset(new TokenHexString("0abc")));
  541. // Store hexstring with no digits "0x" ("").
  542. ASSERT_NO_THROW(nodigit.reset(new TokenHexString("0x")));
  543. // Store hexstring with a bad hexdigit "0xxabc" ("").
  544. ASSERT_NO_THROW(baddigit.reset(new TokenHexString("0xxabc")));
  545. // Store hexstring with an odd number of hexdigits "0x7" ("\a").
  546. ASSERT_NO_THROW(bell.reset(new TokenHexString("0x7")));
  547. // Store constant hexstring "0x666f6f" ("foo").
  548. ASSERT_NO_THROW(foo.reset(new TokenHexString("0x666f6f")));
  549. // Store constant hexstring "0x63825363" (DHCP_OPTIONS_COOKIE).
  550. ASSERT_NO_THROW(cookie.reset(new TokenHexString("0x63825363")));
  551. // Make sure that tokens can be evaluated without exceptions.
  552. ASSERT_NO_THROW(empty->evaluate(*pkt6_, values_));
  553. ASSERT_NO_THROW(bad->evaluate(*pkt6_, values_));
  554. ASSERT_NO_THROW(nodigit->evaluate(*pkt6_, values_));
  555. ASSERT_NO_THROW(baddigit->evaluate(*pkt6_, values_));
  556. ASSERT_NO_THROW(bell->evaluate(*pkt6_, values_));
  557. ASSERT_NO_THROW(foo->evaluate(*pkt6_, values_));
  558. ASSERT_NO_THROW(cookie->evaluate(*pkt6_, values_));
  559. // Check that the evaluation put its value on the values stack.
  560. ASSERT_EQ(7, values_.size());
  561. uint32_t expected = htonl(DHCP_OPTIONS_COOKIE);
  562. EXPECT_EQ(4, values_.top().size());
  563. EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
  564. values_.pop();
  565. EXPECT_EQ("foo", values_.top());
  566. values_.pop();
  567. EXPECT_EQ("\a", values_.top());
  568. values_.pop();
  569. EXPECT_EQ("", values_.top());
  570. values_.pop();
  571. EXPECT_EQ("", values_.top());
  572. values_.pop();
  573. EXPECT_EQ("", values_.top());
  574. values_.pop();
  575. EXPECT_EQ("", values_.top());
  576. // Check that the debug output was correct. Add the strings
  577. // to the test vector in the class and then call checkFile
  578. // for comparison
  579. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
  580. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
  581. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
  582. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
  583. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x07");
  584. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x666F6F");
  585. addString("EVAL_DEBUG_HEXSTRING Pushing hex string 0x63825363");
  586. EXPECT_TRUE(checkFile());
  587. }
  588. // This test checks that a TokenIpAddress, representing an IP address as
  589. // a constant string, can be used in Pkt4/Pkt6 evaluation.
  590. // (The actual packet is not used)
  591. TEST_F(TokenTest, ipaddress) {
  592. TokenPtr bad4;
  593. TokenPtr bad6;
  594. TokenPtr ip4;
  595. TokenPtr ip6;
  596. // Bad IP addresses
  597. ASSERT_NO_THROW(bad4.reset(new TokenIpAddress("10.0.0.0.1")));
  598. ASSERT_NO_THROW(bad6.reset(new TokenIpAddress(":::")));
  599. // IP addresses
  600. ASSERT_NO_THROW(ip4.reset(new TokenIpAddress("10.0.0.1")));
  601. ASSERT_NO_THROW(ip6.reset(new TokenIpAddress("2001:db8::1")));
  602. // Make sure that tokens can be evaluated without exceptions.
  603. ASSERT_NO_THROW(ip4->evaluate(*pkt4_, values_));
  604. ASSERT_NO_THROW(ip6->evaluate(*pkt6_, values_));
  605. ASSERT_NO_THROW(bad4->evaluate(*pkt4_, values_));
  606. ASSERT_NO_THROW(bad6->evaluate(*pkt6_, values_));
  607. // Check that the evaluation put its value on the values stack.
  608. ASSERT_EQ(4, values_.size());
  609. // Check bad addresses (they pushed '' on the value stack)
  610. EXPECT_EQ(0, values_.top().size());
  611. values_.pop();
  612. EXPECT_EQ(0, values_.top().size());
  613. values_.pop();
  614. // Check IPv6 address
  615. uint8_t expected6[] = { 0x20, 1, 0xd, 0xb8, 0, 0, 0, 0,
  616. 0, 0, 0, 0, 0, 0, 0, 1 };
  617. EXPECT_EQ(16, values_.top().size());
  618. EXPECT_EQ(0, memcmp(expected6, &values_.top()[0], 16));
  619. values_.pop();
  620. // Check IPv4 address
  621. uint8_t expected4[] = { 10, 0, 0, 1 };
  622. EXPECT_EQ(4, values_.top().size());
  623. EXPECT_EQ(0, memcmp(expected4, &values_.top()[0], 4));
  624. // Check that the debug output was correct. Add the strings
  625. // to the test vector in the class and then call checkFile
  626. // for comparison
  627. addString("EVAL_DEBUG_IPADDRESS Pushing IPAddress 0x0A000001");
  628. addString("EVAL_DEBUG_IPADDRESS Pushing IPAddress "
  629. "0x20010DB8000000000000000000000001");
  630. addString("EVAL_DEBUG_IPADDRESS Pushing IPAddress 0x");
  631. addString("EVAL_DEBUG_IPADDRESS Pushing IPAddress 0x");
  632. EXPECT_TRUE(checkFile());
  633. }
  634. // This test checks if a token representing an option value is able to extract
  635. // the option from an IPv4 packet and properly store the option's value.
  636. TEST_F(TokenTest, optionString4) {
  637. TokenPtr found;
  638. TokenPtr not_found;
  639. // The packets we use have option 100 with a string in them.
  640. ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::TEXTUAL)));
  641. ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::TEXTUAL)));
  642. // This should evaluate to the content of the option 100 (i.e. "hundred4")
  643. ASSERT_NO_THROW(found->evaluate(*pkt4_, values_));
  644. // This should evaluate to "" as there is no option 101.
  645. ASSERT_NO_THROW(not_found->evaluate(*pkt4_, values_));
  646. // There should be 2 values evaluated.
  647. ASSERT_EQ(2, values_.size());
  648. // This is a stack, so the pop order is inversed. We should get the empty
  649. // string first.
  650. EXPECT_EQ("", values_.top());
  651. values_.pop();
  652. // Then the content of the option 100.
  653. EXPECT_EQ("hundred4", values_.top());
  654. // Check that the debug output was correct. Add the strings
  655. // to the test vector in the class and then call checkFile
  656. // for comparison
  657. addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'hundred4'");
  658. addString("EVAL_DEBUG_OPTION Pushing option 101 with value ''");
  659. EXPECT_TRUE(checkFile());
  660. }
  661. // This test checks if a token representing option value is able to extract
  662. // the option from an IPv4 packet and properly store its value in a
  663. // hexadecimal format.
  664. TEST_F(TokenTest, optionHexString4) {
  665. TokenPtr found;
  666. TokenPtr not_found;
  667. // The packets we use have option 100 with a string in them.
  668. ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::HEXADECIMAL)));
  669. ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::HEXADECIMAL)));
  670. // This should evaluate to the content of the option 100 (i.e. "hundred4")
  671. ASSERT_NO_THROW(found->evaluate(*pkt4_, values_));
  672. // This should evaluate to "" as there is no option 101.
  673. ASSERT_NO_THROW(not_found->evaluate(*pkt4_, values_));
  674. // There should be 2 values evaluated.
  675. ASSERT_EQ(2, values_.size());
  676. // This is a stack, so the pop order is inversed. We should get the empty
  677. // string first.
  678. EXPECT_EQ("", values_.top());
  679. values_.pop();
  680. // Then the content of the option 100.
  681. EXPECT_EQ("hundred4", values_.top());
  682. // Check that the debug output was correct. Add the strings
  683. // to the test vector in the class and then call checkFile
  684. // for comparison
  685. addString("EVAL_DEBUG_OPTION Pushing option 100 with value 0x68756E6472656434");
  686. addString("EVAL_DEBUG_OPTION Pushing option 101 with value 0x");
  687. EXPECT_TRUE(checkFile());
  688. }
  689. // This test checks if a token representing an option value is able to check
  690. // the existence of the option from an IPv4 packet.
  691. TEST_F(TokenTest, optionExistsString4) {
  692. TokenPtr found;
  693. TokenPtr not_found;
  694. // The packets we use have option 100 with a string in them.
  695. ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::EXISTS)));
  696. ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::EXISTS)));
  697. ASSERT_NO_THROW(found->evaluate(*pkt4_, values_));
  698. ASSERT_NO_THROW(not_found->evaluate(*pkt4_, values_));
  699. // There should be 2 values evaluated.
  700. ASSERT_EQ(2, values_.size());
  701. // This is a stack, so the pop order is inversed.
  702. EXPECT_EQ("false", values_.top());
  703. values_.pop();
  704. EXPECT_EQ("true", values_.top());
  705. // Check that the debug output was correct. Add the strings
  706. // to the test vector in the class and then call checkFile
  707. // for comparison
  708. addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'true'");
  709. addString("EVAL_DEBUG_OPTION Pushing option 101 with value 'false'");
  710. EXPECT_TRUE(checkFile());
  711. }
  712. // This test checks if a token representing an option value is able to extract
  713. // the option from an IPv6 packet and properly store the option's value.
  714. TEST_F(TokenTest, optionString6) {
  715. TokenPtr found;
  716. TokenPtr not_found;
  717. // The packets we use have option 100 with a string in them.
  718. ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::TEXTUAL)));
  719. ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::TEXTUAL)));
  720. // This should evaluate to the content of the option 100 (i.e. "hundred6")
  721. ASSERT_NO_THROW(found->evaluate(*pkt6_, values_));
  722. // This should evaluate to "" as there is no option 101.
  723. ASSERT_NO_THROW(not_found->evaluate(*pkt6_, values_));
  724. // There should be 2 values evaluated.
  725. ASSERT_EQ(2, values_.size());
  726. // This is a stack, so the pop order is inversed. We should get the empty
  727. // string first.
  728. EXPECT_EQ("", values_.top());
  729. values_.pop();
  730. // Then the content of the option 100.
  731. EXPECT_EQ("hundred6", values_.top());
  732. // Check that the debug output was correct. Add the strings
  733. // to the test vector in the class and then call checkFile
  734. // for comparison
  735. addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'hundred6'");
  736. addString("EVAL_DEBUG_OPTION Pushing option 101 with value ''");
  737. EXPECT_TRUE(checkFile());
  738. }
  739. // This test checks if a token representing an option value is able to extract
  740. // the option from an IPv6 packet and properly store its value in hexadecimal
  741. // format.
  742. TEST_F(TokenTest, optionHexString6) {
  743. TokenPtr found;
  744. TokenPtr not_found;
  745. // The packets we use have option 100 with a string in them.
  746. ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::HEXADECIMAL)));
  747. ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::HEXADECIMAL)));
  748. // This should evaluate to the content of the option 100 (i.e. "hundred6")
  749. ASSERT_NO_THROW(found->evaluate(*pkt6_, values_));
  750. // This should evaluate to "" as there is no option 101.
  751. ASSERT_NO_THROW(not_found->evaluate(*pkt6_, values_));
  752. // There should be 2 values evaluated.
  753. ASSERT_EQ(2, values_.size());
  754. // This is a stack, so the pop order is inversed. We should get the empty
  755. // string first.
  756. EXPECT_EQ("", values_.top());
  757. values_.pop();
  758. // Then the content of the option 100.
  759. EXPECT_EQ("hundred6", values_.top());
  760. // Check that the debug output was correct. Add the strings
  761. // to the test vector in the class and then call checkFile
  762. // for comparison
  763. addString("EVAL_DEBUG_OPTION Pushing option 100 with value 0x68756E6472656436");
  764. addString("EVAL_DEBUG_OPTION Pushing option 101 with value 0x");
  765. EXPECT_TRUE(checkFile());
  766. }
  767. // This test checks if a token representing an option value is able to check
  768. // the existence of the option from an IPv6 packet.
  769. TEST_F(TokenTest, optionExistsString6) {
  770. TokenPtr found;
  771. TokenPtr not_found;
  772. // The packets we use have option 100 with a string in them.
  773. ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::EXISTS)));
  774. ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::EXISTS)));
  775. ASSERT_NO_THROW(found->evaluate(*pkt6_, values_));
  776. ASSERT_NO_THROW(not_found->evaluate(*pkt6_, values_));
  777. // There should be 2 values evaluated.
  778. ASSERT_EQ(2, values_.size());
  779. // This is a stack, so the pop order is inversed.
  780. EXPECT_EQ("false", values_.top());
  781. values_.pop();
  782. EXPECT_EQ("true", values_.top());
  783. // Check that the debug output was correct. Add the strings
  784. // to the test vector in the class and then call checkFile
  785. // for comparison
  786. addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'true'");
  787. addString("EVAL_DEBUG_OPTION Pushing option 101 with value 'false'");
  788. EXPECT_TRUE(checkFile());
  789. }
  790. // This test checks that the existing relay4 option can be found.
  791. TEST_F(TokenTest, relay4Option) {
  792. // Insert relay option with sub-options 1 and 13
  793. insertRelay4Option();
  794. // Creating the token should be safe.
  795. ASSERT_NO_THROW(t_.reset(new TokenRelay4Option(13, TokenOption::TEXTUAL)));
  796. // We should be able to evaluate it.
  797. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  798. // we should have one value on the stack
  799. ASSERT_EQ(1, values_.size());
  800. // The option should be found and relay4[13] should evaluate to the
  801. // content of that sub-option, i.e. "thirteen"
  802. EXPECT_EQ("thirteen", values_.top());
  803. // Check that the debug output was correct. Add the strings
  804. // to the test vector in the class and then call checkFile
  805. // for comparison
  806. addString("EVAL_DEBUG_OPTION Pushing option 13 with value 'thirteen'");
  807. EXPECT_TRUE(checkFile());
  808. }
  809. // This test checks that the code properly handles cases when
  810. // there is a RAI option, but there's no requested sub-option.
  811. TEST_F(TokenTest, relay4OptionNoSuboption) {
  812. // Insert relay option with sub-options 1 and 13
  813. insertRelay4Option();
  814. // Creating the token should be safe.
  815. ASSERT_NO_THROW(t_.reset(new TokenRelay4Option(15, TokenOption::TEXTUAL)));
  816. // We should be able to evaluate it.
  817. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  818. // we should have one value on the stack
  819. ASSERT_EQ(1, values_.size());
  820. // The option should NOT be found (there is no sub-option 15),
  821. // so the expression should evaluate to ""
  822. EXPECT_EQ("", values_.top());
  823. // Check that the debug output was correct. Add the strings
  824. // to the test vector in the class and then call checkFile
  825. // for comparison
  826. addString("EVAL_DEBUG_OPTION Pushing option 15 with value ''");
  827. EXPECT_TRUE(checkFile());
  828. }
  829. // This test checks that the code properly handles cases when
  830. // there's no RAI option at all.
  831. TEST_F(TokenTest, relay4OptionNoRai) {
  832. // We didn't call insertRelay4Option(), so there's no RAI option.
  833. // Creating the token should be safe.
  834. ASSERT_NO_THROW(t_.reset(new TokenRelay4Option(13, TokenOption::TEXTUAL)));
  835. // We should be able to evaluate it.
  836. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  837. // we should have one value on the stack
  838. ASSERT_EQ(1, values_.size());
  839. // The option should NOT be found (there is no sub-option 13),
  840. // so the expression should evaluate to ""
  841. EXPECT_EQ("", values_.top());
  842. // Check that the debug output was correct. Add the strings
  843. // to the test vector in the class and then call checkFile
  844. // for comparison
  845. addString("EVAL_DEBUG_OPTION Pushing option 13 with value ''");
  846. EXPECT_TRUE(checkFile());
  847. }
  848. // This test checks that only the RAI is searched for the requested
  849. // sub-option.
  850. TEST_F(TokenTest, relay4RAIOnly) {
  851. // Insert relay option with sub-options 1 and 13
  852. insertRelay4Option();
  853. // Add options 13 and 70 to the packet.
  854. OptionPtr opt13(new OptionString(Option::V4, 13, "THIRTEEN"));
  855. OptionPtr opt70(new OptionString(Option::V4, 70, "SEVENTY"));
  856. pkt4_->addOption(opt13);
  857. pkt4_->addOption(opt70);
  858. // The situation is as follows:
  859. // Packet:
  860. // - option 13 (containing "THIRTEEN")
  861. // - option 82 (rai)
  862. // - option 1 (containing "one")
  863. // - option 13 (containing "thirteen")
  864. // Let's try to get option 13. It should get the one from RAI
  865. ASSERT_NO_THROW(t_.reset(new TokenRelay4Option(13, TokenOption::TEXTUAL)));
  866. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  867. ASSERT_EQ(1, values_.size());
  868. EXPECT_EQ("thirteen", values_.top());
  869. // Try to get option 1. It should get the one from RAI
  870. clearStack();
  871. ASSERT_NO_THROW(t_.reset(new TokenRelay4Option(1, TokenOption::TEXTUAL)));
  872. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  873. ASSERT_EQ(1, values_.size());
  874. EXPECT_EQ("one", values_.top());
  875. // Try to get option 70. It should fail, as there's no such
  876. // sub option in RAI.
  877. clearStack();
  878. ASSERT_NO_THROW(t_.reset(new TokenRelay4Option(70, TokenOption::TEXTUAL)));
  879. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  880. ASSERT_EQ(1, values_.size());
  881. EXPECT_EQ("", values_.top());
  882. // Try to check option 1. It should return "true"
  883. clearStack();
  884. ASSERT_NO_THROW(t_.reset(new TokenRelay4Option(1, TokenOption::EXISTS)));
  885. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  886. ASSERT_EQ(1, values_.size());
  887. EXPECT_EQ("true", values_.top());
  888. // Try to check option 70. It should return "false"
  889. clearStack();
  890. ASSERT_NO_THROW(t_.reset(new TokenRelay4Option(70, TokenOption::EXISTS)));
  891. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  892. ASSERT_EQ(1, values_.size());
  893. EXPECT_EQ("false", values_.top());
  894. // Check that the debug output was correct. Add the strings
  895. // to the test vector in the class and then call checkFile
  896. // for comparison
  897. addString("EVAL_DEBUG_OPTION Pushing option 13 with value 'thirteen'");
  898. addString("EVAL_DEBUG_OPTION Pushing option 1 with value 'one'");
  899. addString("EVAL_DEBUG_OPTION Pushing option 70 with value ''");
  900. addString("EVAL_DEBUG_OPTION Pushing option 1 with value 'true'");
  901. addString("EVAL_DEBUG_OPTION Pushing option 70 with value 'false'");
  902. EXPECT_TRUE(checkFile());
  903. }
  904. // Verifies if the DHCPv4 packet fields can be extracted.
  905. TEST_F(TokenTest, pkt4Fields) {
  906. pkt4_->setGiaddr(IOAddress("192.0.2.1"));
  907. pkt4_->setCiaddr(IOAddress("192.0.2.2"));
  908. pkt4_->setYiaddr(IOAddress("192.0.2.3"));
  909. pkt4_->setSiaddr(IOAddress("192.0.2.4"));
  910. // We're setting hardware address to uncommon (7 bytes rather than 6 and
  911. // hardware type 123) HW address. We'll use it in hlen and htype checks.
  912. HWAddrPtr hw(new HWAddr(HWAddr::fromText("01:02:03:04:05:06:07", 123)));
  913. pkt4_->setHWAddr(hw);
  914. // Check hardware address field.
  915. ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::CHADDR)));
  916. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  917. ASSERT_EQ(1, values_.size());
  918. uint8_t expected_hw[] = { 1, 2, 3, 4, 5, 6, 7 };
  919. ASSERT_EQ(7, values_.top().size());
  920. EXPECT_EQ(0, memcmp(expected_hw, &values_.top()[0], 7));
  921. // Check hlen value field.
  922. clearStack();
  923. ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::HLEN)));
  924. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  925. ASSERT_EQ(1, values_.size());
  926. ASSERT_EQ(4, values_.top().size());
  927. uint32_t expected_hlen = htonl(7);
  928. EXPECT_EQ(0, memcmp(&expected_hlen, &values_.top()[0], 4));
  929. // Check htype value.
  930. clearStack();
  931. ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::HTYPE)));
  932. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  933. ASSERT_EQ(1, values_.size());
  934. ASSERT_EQ(4, values_.top().size());
  935. uint32_t expected_htype = htonl(123);
  936. EXPECT_EQ(0, memcmp(&expected_htype, &values_.top()[0], 4));
  937. // Check giaddr value.
  938. clearStack();
  939. ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::GIADDR)));
  940. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  941. ASSERT_EQ(1, values_.size());
  942. uint8_t expected_addr[] = { 192, 0, 2, 1 };
  943. ASSERT_EQ(4, values_.top().size());
  944. EXPECT_EQ(0, memcmp(expected_addr, &values_.top()[0], 4));
  945. // Check ciaddr value.
  946. clearStack();
  947. ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::CIADDR)));
  948. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  949. ASSERT_EQ(1, values_.size());
  950. expected_addr[3] = 2;
  951. ASSERT_EQ(4, values_.top().size());
  952. EXPECT_EQ(0, memcmp(expected_addr, &values_.top()[0], 4));
  953. // Check yiaddr value.
  954. clearStack();
  955. ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::YIADDR)));
  956. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  957. ASSERT_EQ(1, values_.size());
  958. expected_addr[3] = 3;
  959. ASSERT_EQ(4, values_.top().size());
  960. EXPECT_EQ(0, memcmp(expected_addr, &values_.top()[0], 4));
  961. // Check siaddr value.
  962. clearStack();
  963. ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::SIADDR)));
  964. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  965. ASSERT_EQ(1, values_.size());
  966. expected_addr[3] = 4;
  967. ASSERT_EQ(4, values_.top().size());
  968. EXPECT_EQ(0, memcmp(expected_addr, &values_.top()[0], 4));
  969. // Check a DHCPv6 packet throws.
  970. clearStack();
  971. ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::HLEN)));
  972. EXPECT_THROW(t_->evaluate(*pkt6_, values_), EvalTypeError);
  973. // Check that the debug output was correct. Add the strings
  974. // to the test vector in the class and then call checkFile
  975. // for comparison
  976. addString("EVAL_DEBUG_PKT4 Pushing PKT4 field mac with value 0x01020304050607");
  977. addString("EVAL_DEBUG_PKT4 Pushing PKT4 field hlen with value 0x00000007");
  978. addString("EVAL_DEBUG_PKT4 Pushing PKT4 field htype with value 0x0000007B");
  979. addString("EVAL_DEBUG_PKT4 Pushing PKT4 field giaddr with value 0xC0000201");
  980. addString("EVAL_DEBUG_PKT4 Pushing PKT4 field ciaddr with value 0xC0000202");
  981. addString("EVAL_DEBUG_PKT4 Pushing PKT4 field yiaddr with value 0xC0000203");
  982. addString("EVAL_DEBUG_PKT4 Pushing PKT4 field siaddr with value 0xC0000204");
  983. EXPECT_TRUE(checkFile());
  984. }
  985. // This test checks if a token representing an == operator is able to
  986. // compare two values (with incorrectly built stack).
  987. TEST_F(TokenTest, optionEqualInvalid) {
  988. ASSERT_NO_THROW(t_.reset(new TokenEqual()));
  989. // CASE 1: There's not enough values on the stack. == is an operator that
  990. // takes two parameters. There are 0 on the stack.
  991. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
  992. // CASE 2: One value is still not enough.
  993. values_.push("foo");
  994. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
  995. }
  996. // This test checks if a token representing an == operator is able to
  997. // compare two different values.
  998. TEST_F(TokenTest, optionEqualFalse) {
  999. ASSERT_NO_THROW(t_.reset(new TokenEqual()));
  1000. values_.push("foo");
  1001. values_.push("bar");
  1002. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1003. // After evaluation there should be a single value that represents
  1004. // result of "foo" == "bar" comparision.
  1005. ASSERT_EQ(1, values_.size());
  1006. EXPECT_EQ("false", values_.top());
  1007. // Check that the debug output was correct. Add the strings
  1008. // to the test vector in the class and then call checkFile
  1009. // for comparison
  1010. addString("EVAL_DEBUG_EQUAL Popping 0x626172 and 0x666F6F "
  1011. "pushing result 'false'");
  1012. EXPECT_TRUE(checkFile());
  1013. }
  1014. // This test checks if a token representing an == operator is able to
  1015. // compare two identical values.
  1016. TEST_F(TokenTest, optionEqualTrue) {
  1017. ASSERT_NO_THROW(t_.reset(new TokenEqual()));
  1018. values_.push("foo");
  1019. values_.push("foo");
  1020. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1021. // After evaluation there should be a single value that represents
  1022. // result of "foo" == "foo" comparision.
  1023. ASSERT_EQ(1, values_.size());
  1024. EXPECT_EQ("true", values_.top());
  1025. // Check that the debug output was correct. Add the strings
  1026. // to the test vector in the class and then call checkFile
  1027. // for comparison
  1028. addString("EVAL_DEBUG_EQUAL Popping 0x666F6F and 0x666F6F "
  1029. "pushing result 'true'");
  1030. EXPECT_TRUE(checkFile());
  1031. }
  1032. // This test checks if a token representing a not is able to
  1033. // negate a boolean value (with incorrectly built stack).
  1034. TEST_F(TokenTest, operatorNotInvalid) {
  1035. ASSERT_NO_THROW(t_.reset(new TokenNot()));
  1036. // CASE 1: The stack is empty.
  1037. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
  1038. // CASE 2: The top value is not a boolean
  1039. values_.push("foo");
  1040. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
  1041. }
  1042. // This test checks if a token representing a not operator is able to
  1043. // negate a boolean value.
  1044. TEST_F(TokenTest, operatorNot) {
  1045. ASSERT_NO_THROW(t_.reset(new TokenNot()));
  1046. values_.push("true");
  1047. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1048. // After evaluation there should be the negation of the value.
  1049. ASSERT_EQ(1, values_.size());
  1050. EXPECT_EQ("false", values_.top());
  1051. // Double negation is identity.
  1052. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1053. ASSERT_EQ(1, values_.size());
  1054. EXPECT_EQ("true", values_.top());
  1055. // Check that the debug output was correct. Add the strings
  1056. // to the test vector in the class and then call checkFile
  1057. // for comparison
  1058. addString("EVAL_DEBUG_NOT Popping 'true' pushing 'false'");
  1059. addString("EVAL_DEBUG_NOT Popping 'false' pushing 'true'");
  1060. EXPECT_TRUE(checkFile());
  1061. }
  1062. // This test checks if a token representing an and is able to
  1063. // conjugate two values (with incorrectly built stack).
  1064. TEST_F(TokenTest, operatorAndInvalid) {
  1065. ASSERT_NO_THROW(t_.reset(new TokenAnd()));
  1066. // CASE 1: There's not enough values on the stack. and is an operator that
  1067. // takes two parameters. There are 0 on the stack.
  1068. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
  1069. // CASE 2: One value is still not enough.
  1070. values_.push("foo");
  1071. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
  1072. // CASE 3: The two values must be logical
  1073. values_.push("true");
  1074. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
  1075. // Swap the 2 values
  1076. values_.push("true");
  1077. values_.push("foo");
  1078. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
  1079. }
  1080. // This test checks if a token representing an and operator is able to
  1081. // conjugate false with another logical
  1082. TEST_F(TokenTest, operatorAndFalse) {
  1083. ASSERT_NO_THROW(t_.reset(new TokenAnd()));
  1084. values_.push("true");
  1085. values_.push("false");
  1086. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1087. // After evaluation there should be a single "false" value
  1088. ASSERT_EQ(1, values_.size());
  1089. EXPECT_EQ("false", values_.top());
  1090. // After true and false, check false and true
  1091. values_.push("true");
  1092. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1093. ASSERT_EQ(1, values_.size());
  1094. EXPECT_EQ("false", values_.top());
  1095. // And false and false
  1096. values_.push("false");
  1097. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1098. ASSERT_EQ(1, values_.size());
  1099. EXPECT_EQ("false", values_.top());
  1100. // Check that the debug output was correct. Add the strings
  1101. // to the test vector in the class and then call checkFile
  1102. // for comparison
  1103. addString("EVAL_DEBUG_AND Popping 'false' and 'true' pushing 'false'");
  1104. addString("EVAL_DEBUG_AND Popping 'true' and 'false' pushing 'false'");
  1105. addString("EVAL_DEBUG_AND Popping 'false' and 'false' pushing 'false'");
  1106. EXPECT_TRUE(checkFile());
  1107. }
  1108. // This test checks if a token representing an and is able to
  1109. // conjugate two true values.
  1110. TEST_F(TokenTest, operatorAndTrue) {
  1111. ASSERT_NO_THROW(t_.reset(new TokenAnd()));
  1112. values_.push("true");
  1113. values_.push("true");
  1114. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1115. // After evaluation there should be a single "true" value
  1116. ASSERT_EQ(1, values_.size());
  1117. EXPECT_EQ("true", values_.top());
  1118. // Check that the debug output was correct. Add the strings
  1119. // to the test vector in the class and then call checkFile
  1120. // for comparison
  1121. addString("EVAL_DEBUG_AND Popping 'true' and 'true' pushing 'true'");
  1122. EXPECT_TRUE(checkFile());
  1123. }
  1124. // This test checks if a token representing an or is able to
  1125. // combinate two values (with incorrectly built stack).
  1126. TEST_F(TokenTest, operatorOrInvalid) {
  1127. ASSERT_NO_THROW(t_.reset(new TokenOr()));
  1128. // CASE 1: There's not enough values on the stack. or is an operator that
  1129. // takes two parameters. There are 0 on the stack.
  1130. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
  1131. // CASE 2: One value is still not enough.
  1132. values_.push("foo");
  1133. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
  1134. // CASE 3: The two values must be logical
  1135. values_.push("true");
  1136. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
  1137. // Swap the 2 values
  1138. values_.push("true");
  1139. values_.push("foo");
  1140. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
  1141. }
  1142. // This test checks if a token representing an or is able to
  1143. // conjugate two false values.
  1144. TEST_F(TokenTest, operatorOrFalse) {
  1145. ASSERT_NO_THROW(t_.reset(new TokenOr()));
  1146. values_.push("false");
  1147. values_.push("false");
  1148. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1149. // After evaluation there should be a single "false" value
  1150. ASSERT_EQ(1, values_.size());
  1151. EXPECT_EQ("false", values_.top());
  1152. // Check that the debug output was correct. Add the strings
  1153. // to the test vector in the class and then call checkFile
  1154. // for comparison
  1155. addString("EVAL_DEBUG_OR Popping 'false' and 'false' pushing 'false'");
  1156. EXPECT_TRUE(checkFile());
  1157. }
  1158. // This test checks if a token representing an == operator is able to
  1159. // conjugate true with another logical
  1160. TEST_F(TokenTest, operatorOrTrue) {
  1161. ASSERT_NO_THROW(t_.reset(new TokenOr()));
  1162. values_.push("false");
  1163. values_.push("true");
  1164. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1165. // After evaluation there should be a single "true" value
  1166. ASSERT_EQ(1, values_.size());
  1167. EXPECT_EQ("true", values_.top());
  1168. // After false or true, checks true or false
  1169. values_.push("false");
  1170. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1171. ASSERT_EQ(1, values_.size());
  1172. EXPECT_EQ("true", values_.top());
  1173. // And true or true
  1174. values_.push("true");
  1175. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1176. ASSERT_EQ(1, values_.size());
  1177. EXPECT_EQ("true", values_.top());
  1178. // Check that the debug output was correct. Add the strings
  1179. // to the test vector in the class and then call checkFile
  1180. // for comparison
  1181. addString("EVAL_DEBUG_OR Popping 'true' and 'false' pushing 'true'");
  1182. addString("EVAL_DEBUG_OR Popping 'false' and 'true' pushing 'true'");
  1183. addString("EVAL_DEBUG_OR Popping 'true' and 'true' pushing 'true'");
  1184. EXPECT_TRUE(checkFile());
  1185. }
  1186. // This test checks if a token representing a substring request
  1187. // throws an exception if there aren't enough values on the stack.
  1188. // The stack from the top is: length, start, string.
  1189. // The actual packet is not used.
  1190. TEST_F(TokenTest, substringNotEnoughValues) {
  1191. ASSERT_NO_THROW(t_.reset(new TokenSubstring()));
  1192. // Subsring requires three values on the stack, try
  1193. // with 0, 1 and 2 all should throw an exception
  1194. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
  1195. values_.push("");
  1196. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
  1197. values_.push("0");
  1198. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
  1199. // Three should work
  1200. values_.push("0");
  1201. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1202. // As we had an empty string to start with we should have an empty
  1203. // one after the evaluate
  1204. ASSERT_EQ(1, values_.size());
  1205. EXPECT_EQ("", values_.top());
  1206. // Check that the debug output was correct. Add the strings
  1207. // to the test vector in the class and then call checkFile
  1208. // for comparison
  1209. addString("EVAL_DEBUG_SUBSTRING_EMPTY Popping length 0, start 0, "
  1210. "string 0x pushing result 0x");
  1211. EXPECT_TRUE(checkFile());
  1212. }
  1213. // Test getting the whole string in different ways
  1214. TEST_F(TokenTest, substringWholeString) {
  1215. // Get the whole string
  1216. verifySubstringEval("foobar", "0", "6", "foobar");
  1217. // Get the whole string with "all"
  1218. verifySubstringEval("foobar", "0", "all", "foobar");
  1219. // Get the whole string with an extra long number
  1220. verifySubstringEval("foobar", "0", "123456", "foobar");
  1221. // Get the whole string counting from the back
  1222. verifySubstringEval("foobar", "-6", "all", "foobar");
  1223. // Check that the debug output was correct. Add the strings
  1224. // to the test vector in the class and then call checkFile
  1225. // for comparison
  1226. addString("EVAL_DEBUG_SUBSTRING Popping length 6, start 0, "
  1227. "string 0x666F6F626172 pushing result 0x666F6F626172");
  1228. addString("EVAL_DEBUG_SUBSTRING Popping length all, start 0, "
  1229. "string 0x666F6F626172 pushing result 0x666F6F626172");
  1230. addString("EVAL_DEBUG_SUBSTRING Popping length 123456, start 0, "
  1231. "string 0x666F6F626172 pushing result 0x666F6F626172");
  1232. addString("EVAL_DEBUG_SUBSTRING Popping length all, start -6, "
  1233. "string 0x666F6F626172 pushing result 0x666F6F626172");
  1234. EXPECT_TRUE(checkFile());
  1235. }
  1236. // Test getting a suffix, in this case the last 3 characters
  1237. TEST_F(TokenTest, substringTrailer) {
  1238. verifySubstringEval("foobar", "3", "3", "bar");
  1239. verifySubstringEval("foobar", "3", "all", "bar");
  1240. verifySubstringEval("foobar", "-3", "all", "bar");
  1241. verifySubstringEval("foobar", "-3", "123", "bar");
  1242. // Check that the debug output was correct. Add the strings
  1243. // to the test vector in the class and then call checkFile
  1244. // for comparison
  1245. addString("EVAL_DEBUG_SUBSTRING Popping length 3, start 3, "
  1246. "string 0x666F6F626172 pushing result 0x626172");
  1247. addString("EVAL_DEBUG_SUBSTRING Popping length all, start 3, "
  1248. "string 0x666F6F626172 pushing result 0x626172");
  1249. addString("EVAL_DEBUG_SUBSTRING Popping length all, start -3, "
  1250. "string 0x666F6F626172 pushing result 0x626172");
  1251. addString("EVAL_DEBUG_SUBSTRING Popping length 123, start -3, "
  1252. "string 0x666F6F626172 pushing result 0x626172");
  1253. EXPECT_TRUE(checkFile());
  1254. }
  1255. // Test getting the middle of the string in different ways
  1256. TEST_F(TokenTest, substringMiddle) {
  1257. verifySubstringEval("foobar", "1", "4", "ooba");
  1258. verifySubstringEval("foobar", "-5", "4", "ooba");
  1259. verifySubstringEval("foobar", "-1", "-4", "ooba");
  1260. verifySubstringEval("foobar", "5", "-4", "ooba");
  1261. // Check that the debug output was correct. Add the strings
  1262. // to the test vector in the class and then call checkFile
  1263. // for comparison
  1264. addString("EVAL_DEBUG_SUBSTRING Popping length 4, start 1, "
  1265. "string 0x666F6F626172 pushing result 0x6F6F6261");
  1266. addString("EVAL_DEBUG_SUBSTRING Popping length 4, start -5, "
  1267. "string 0x666F6F626172 pushing result 0x6F6F6261");
  1268. addString("EVAL_DEBUG_SUBSTRING Popping length -4, start -1, "
  1269. "string 0x666F6F626172 pushing result 0x6F6F6261");
  1270. addString("EVAL_DEBUG_SUBSTRING Popping length -4, start 5, "
  1271. "string 0x666F6F626172 pushing result 0x6F6F6261");
  1272. EXPECT_TRUE(checkFile());
  1273. }
  1274. // Test getting the last letter in different ways
  1275. TEST_F(TokenTest, substringLastLetter) {
  1276. verifySubstringEval("foobar", "5", "all", "r");
  1277. verifySubstringEval("foobar", "5", "1", "r");
  1278. verifySubstringEval("foobar", "5", "5", "r");
  1279. verifySubstringEval("foobar", "-1", "all", "r");
  1280. verifySubstringEval("foobar", "-1", "1", "r");
  1281. verifySubstringEval("foobar", "-1", "5", "r");
  1282. // Check that the debug output was correct. Add the strings
  1283. // to the test vector in the class and then call checkFile
  1284. // for comparison
  1285. addString("EVAL_DEBUG_SUBSTRING Popping length all, start 5, "
  1286. "string 0x666F6F626172 pushing result 0x72");
  1287. addString("EVAL_DEBUG_SUBSTRING Popping length 1, start 5, "
  1288. "string 0x666F6F626172 pushing result 0x72");
  1289. addString("EVAL_DEBUG_SUBSTRING Popping length 5, start 5, "
  1290. "string 0x666F6F626172 pushing result 0x72");
  1291. addString("EVAL_DEBUG_SUBSTRING Popping length all, start -1, "
  1292. "string 0x666F6F626172 pushing result 0x72");
  1293. addString("EVAL_DEBUG_SUBSTRING Popping length 1, start -1, "
  1294. "string 0x666F6F626172 pushing result 0x72");
  1295. addString("EVAL_DEBUG_SUBSTRING Popping length 5, start -1, "
  1296. "string 0x666F6F626172 pushing result 0x72");
  1297. EXPECT_TRUE(checkFile());
  1298. }
  1299. // Test we get only what is available if we ask for a longer string
  1300. TEST_F(TokenTest, substringLength) {
  1301. // Test off the front
  1302. verifySubstringEval("foobar", "0", "-4", "");
  1303. verifySubstringEval("foobar", "1", "-4", "f");
  1304. verifySubstringEval("foobar", "2", "-4", "fo");
  1305. verifySubstringEval("foobar", "3", "-4", "foo");
  1306. // and the back
  1307. verifySubstringEval("foobar", "3", "4", "bar");
  1308. verifySubstringEval("foobar", "4", "4", "ar");
  1309. verifySubstringEval("foobar", "5", "4", "r");
  1310. verifySubstringEval("foobar", "6", "4", "");
  1311. // Check that the debug output was correct. Add the strings
  1312. // to the test vector in the class and then call checkFile
  1313. // for comparison
  1314. addString("EVAL_DEBUG_SUBSTRING Popping length -4, start 0, "
  1315. "string 0x666F6F626172 pushing result 0x");
  1316. addString("EVAL_DEBUG_SUBSTRING Popping length -4, start 1, "
  1317. "string 0x666F6F626172 pushing result 0x66");
  1318. addString("EVAL_DEBUG_SUBSTRING Popping length -4, start 2, "
  1319. "string 0x666F6F626172 pushing result 0x666F");
  1320. addString("EVAL_DEBUG_SUBSTRING Popping length -4, start 3, "
  1321. "string 0x666F6F626172 pushing result 0x666F6F");
  1322. addString("EVAL_DEBUG_SUBSTRING Popping length 4, start 3, "
  1323. "string 0x666F6F626172 pushing result 0x626172");
  1324. addString("EVAL_DEBUG_SUBSTRING Popping length 4, start 4, "
  1325. "string 0x666F6F626172 pushing result 0x6172");
  1326. addString("EVAL_DEBUG_SUBSTRING Popping length 4, start 5, "
  1327. "string 0x666F6F626172 pushing result 0x72");
  1328. addString("EVAL_DEBUG_SUBSTRING_RANGE Popping length 4, start 6, "
  1329. "string 0x666F6F626172 pushing result 0x");
  1330. EXPECT_TRUE(checkFile());
  1331. }
  1332. // Test that we get nothing if the starting postion is out of the string
  1333. TEST_F(TokenTest, substringStartingPosition) {
  1334. // Off the front
  1335. verifySubstringEval("foobar", "-7", "1", "");
  1336. verifySubstringEval("foobar", "-7", "-11", "");
  1337. verifySubstringEval("foobar", "-7", "all", "");
  1338. // and the back
  1339. verifySubstringEval("foobar", "6", "1", "");
  1340. verifySubstringEval("foobar", "6", "-11", "");
  1341. verifySubstringEval("foobar", "6", "all", "");
  1342. // Check that the debug output was correct. Add the strings
  1343. // to the test vector in the class and then call checkFile
  1344. // for comparison
  1345. addString("EVAL_DEBUG_SUBSTRING_RANGE Popping length 1, start -7, "
  1346. "string 0x666F6F626172 pushing result 0x");
  1347. addString("EVAL_DEBUG_SUBSTRING_RANGE Popping length -11, start -7, "
  1348. "string 0x666F6F626172 pushing result 0x");
  1349. addString("EVAL_DEBUG_SUBSTRING_RANGE Popping length all, start -7, "
  1350. "string 0x666F6F626172 pushing result 0x");
  1351. addString("EVAL_DEBUG_SUBSTRING_RANGE Popping length 1, start 6, "
  1352. "string 0x666F6F626172 pushing result 0x");
  1353. addString("EVAL_DEBUG_SUBSTRING_RANGE Popping length -11, start 6, "
  1354. "string 0x666F6F626172 pushing result 0x");
  1355. addString("EVAL_DEBUG_SUBSTRING_RANGE Popping length all, start 6, "
  1356. "string 0x666F6F626172 pushing result 0x");
  1357. EXPECT_TRUE(checkFile());
  1358. }
  1359. // Check what happens if we use strings that aren't numbers for start or length
  1360. // We should return the empty string
  1361. TEST_F(TokenTest, substringBadParams) {
  1362. verifySubstringEval("foobar", "0ick", "all", "", true);
  1363. verifySubstringEval("foobar", "ick0", "all", "", true);
  1364. verifySubstringEval("foobar", "ick", "all", "", true);
  1365. verifySubstringEval("foobar", "0", "ick", "", true);
  1366. verifySubstringEval("foobar", "0", "0ick", "", true);
  1367. verifySubstringEval("foobar", "0", "ick0", "", true);
  1368. verifySubstringEval("foobar", "0", "allaboard", "", true);
  1369. // These should result in a throw which should generate it's own
  1370. // log entry
  1371. }
  1372. // lastly check that we don't get anything if the string is empty or
  1373. // we don't ask for any characters from it.
  1374. TEST_F(TokenTest, substringReturnEmpty) {
  1375. verifySubstringEval("", "0", "all", "");
  1376. verifySubstringEval("foobar", "0", "0", "");
  1377. // Check that the debug output was correct. Add the strings
  1378. // to the test vector in the class and then call checkFile
  1379. // for comparison
  1380. addString("EVAL_DEBUG_SUBSTRING_EMPTY Popping length all, start 0, "
  1381. "string 0x pushing result 0x");
  1382. addString("EVAL_DEBUG_SUBSTRING Popping length 0, start 0, "
  1383. "string 0x666F6F626172 pushing result 0x");
  1384. EXPECT_TRUE(checkFile());
  1385. }
  1386. // Check if we can use the substring and equal tokens together
  1387. // We put the result on the stack first then the substring values
  1388. // then evaluate the substring which should leave the original
  1389. // result on the bottom with the substring result on next.
  1390. // Evaulating the equals should produce true for the first
  1391. // and false for the second.
  1392. // throws an exception if there aren't enough values on the stack.
  1393. // The stack from the top is: length, start, string.
  1394. // The actual packet is not used.
  1395. TEST_F(TokenTest, substringEquals) {
  1396. TokenPtr tequal;
  1397. ASSERT_NO_THROW(t_.reset(new TokenSubstring()));
  1398. ASSERT_NO_THROW(tequal.reset(new TokenEqual()));
  1399. // The final expected value
  1400. values_.push("ooba");
  1401. // The substring values
  1402. values_.push("foobar");
  1403. values_.push("1");
  1404. values_.push("4");
  1405. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1406. // we should have two values on the stack
  1407. ASSERT_EQ(2, values_.size());
  1408. // next the equals eval
  1409. EXPECT_NO_THROW(tequal->evaluate(*pkt4_, values_));
  1410. ASSERT_EQ(1, values_.size());
  1411. EXPECT_EQ("true", values_.top());
  1412. // get rid of the result
  1413. values_.pop();
  1414. // and try it again but with a bad final value
  1415. // The final expected value
  1416. values_.push("foob");
  1417. // The substring values
  1418. values_.push("foobar");
  1419. values_.push("1");
  1420. values_.push("4");
  1421. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1422. // we should have two values on the stack
  1423. ASSERT_EQ(2, values_.size());
  1424. // next the equals eval
  1425. EXPECT_NO_THROW(tequal->evaluate(*pkt4_, values_));
  1426. ASSERT_EQ(1, values_.size());
  1427. EXPECT_EQ("false", values_.top());
  1428. // Check that the debug output was correct. Add the strings
  1429. // to the test vector in the class and then call checkFile
  1430. // for comparison
  1431. addString("EVAL_DEBUG_SUBSTRING Popping length 4, start 1, "
  1432. "string 0x666F6F626172 pushing result 0x6F6F6261");
  1433. addString("EVAL_DEBUG_EQUAL Popping 0x6F6F6261 and 0x6F6F6261 "
  1434. "pushing result 'true'");
  1435. addString("EVAL_DEBUG_SUBSTRING Popping length 4, start 1, "
  1436. "string 0x666F6F626172 pushing result 0x6F6F6261");
  1437. addString("EVAL_DEBUG_EQUAL Popping 0x6F6F6261 and 0x666F6F62 "
  1438. "pushing result 'false'");
  1439. EXPECT_TRUE(checkFile());
  1440. }
  1441. // This test checks if a token representing a concat request
  1442. // throws an exception if there aren't enough values on the stack.
  1443. // The actual packet is not used.
  1444. TEST_F(TokenTest, concat) {
  1445. ASSERT_NO_THROW(t_.reset(new TokenConcat()));
  1446. // Concat requires two values on the stack, try
  1447. // with 0 and 1 both should throw an exception
  1448. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
  1449. values_.push("foo");
  1450. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
  1451. // Two should work
  1452. values_.push("bar");
  1453. EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
  1454. // Check the result
  1455. ASSERT_EQ(1, values_.size());
  1456. EXPECT_EQ("foobar", values_.top());
  1457. // Check that the debug output was correct. Add the strings
  1458. // to the test vector in the class and then call checkFile
  1459. // for comparison
  1460. addString("EVAL_DEBUG_CONCAT Popping 0x626172 and 0x666F6F "
  1461. "pushing 0x666F6F626172");
  1462. EXPECT_TRUE(checkFile());
  1463. }
  1464. // This test checks if we can properly extract the link and peer
  1465. // address fields from relay encapsulations. Our packet has
  1466. // two relay encapsulations. We attempt to extract the two
  1467. // fields from both of the encapsulations and compare them.
  1468. // We also try to extract one of the fields from an encapsulation
  1469. // that doesn't exist (level 2), this should result in an empty
  1470. // string.
  1471. TEST_F(TokenTest, relay6Field) {
  1472. // Values for the address results
  1473. uint8_t zeroaddr[] = { 0, 0, 0, 0, 0, 0, 0, 0,
  1474. 0, 0, 0, 0, 0, 0, 0, 0 };
  1475. uint8_t linkaddr[] = { 0, 1, 0, 0, 0, 0, 0, 0,
  1476. 0, 0, 0, 0, 0, 0, 0, 1 };
  1477. uint8_t peeraddr[] = { 0, 1, 0, 0, 0, 0, 0, 0,
  1478. 0, 0, 0, 0, 0, 0, 0, 2 };
  1479. // We start by adding a set of relay encapsulations to the
  1480. // basic v6 packet.
  1481. addRelay6Encapsulations();
  1482. // Then we work our way through the set of choices
  1483. // Level 0 both link and peer address should be 0::0
  1484. verifyRelay6Eval(0, TokenRelay6Field::LINKADDR, 16, zeroaddr);
  1485. verifyRelay6Eval(0, TokenRelay6Field::PEERADDR, 16, zeroaddr);
  1486. // Level 1 link and peer should have different non-zero addresses
  1487. verifyRelay6Eval(1, TokenRelay6Field::LINKADDR, 16, linkaddr);
  1488. verifyRelay6Eval(1, TokenRelay6Field::PEERADDR, 16, peeraddr);
  1489. // Level 2 has no encapsulation so the address should be zero length
  1490. verifyRelay6Eval(2, TokenRelay6Field::LINKADDR, 0, zeroaddr);
  1491. // Lets check that the layout of the address returned by the
  1492. // token matches that of the TokenIpAddress
  1493. TokenPtr trelay;
  1494. TokenPtr taddr;
  1495. TokenPtr tequal;
  1496. ASSERT_NO_THROW(trelay.reset(new TokenRelay6Field(1, TokenRelay6Field::LINKADDR)));
  1497. ASSERT_NO_THROW(taddr.reset(new TokenIpAddress("1::1")));
  1498. ASSERT_NO_THROW(tequal.reset(new TokenEqual()));
  1499. EXPECT_NO_THROW(trelay->evaluate(*pkt6_, values_));
  1500. EXPECT_NO_THROW(taddr->evaluate(*pkt6_, values_));
  1501. EXPECT_NO_THROW(tequal->evaluate(*pkt6_, values_));
  1502. // We should have a single value on the stack and it should be "true"
  1503. ASSERT_EQ(1, values_.size());
  1504. EXPECT_EQ("true", values_.top());
  1505. // be tidy
  1506. clearStack();
  1507. // Check that the debug output was correct. Add the strings
  1508. // to the test vector in the class and then call checkFile
  1509. // for comparison
  1510. addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field linkaddr nest 0 "
  1511. "with value 0x00000000000000000000000000000000");
  1512. addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field peeraddr nest 0 "
  1513. "with value 0x00000000000000000000000000000000");
  1514. addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field linkaddr nest 1 "
  1515. "with value 0x00010000000000000000000000000001");
  1516. addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field peeraddr nest 1 "
  1517. "with value 0x00010000000000000000000000000002");
  1518. addString("EVAL_DEBUG_RELAY6_RANGE Pushing PKT6 relay field linkaddr nest 2 "
  1519. "with value 0x");
  1520. addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field linkaddr nest 1 "
  1521. "with value 0x00010000000000000000000000000001");
  1522. addString("EVAL_DEBUG_IPADDRESS Pushing IPAddress "
  1523. "0x00010000000000000000000000000001");
  1524. addString("EVAL_DEBUG_EQUAL Popping 0x00010000000000000000000000000001 "
  1525. "and 0x00010000000000000000000000000001 pushing result 'true'");
  1526. EXPECT_TRUE(checkFile());
  1527. }
  1528. // This test checks if we can properly extract an option
  1529. // from relay encapsulations. Our packet has two relay
  1530. // encapsulations. Both include a common option with the
  1531. // original message (option 100) and both include their
  1532. // own option (101 and 102). We attempt to extract the
  1533. // options and compare them to expected values. We also
  1534. // try to extract an option from an encapsulation
  1535. // that doesn't exist (level 2), this should result in an empty
  1536. // string.
  1537. TEST_F(TokenTest, relay6Option) {
  1538. // We start by adding a set of relay encapsulations to the
  1539. // basic v6 packet.
  1540. addRelay6Encapsulations();
  1541. // Then we work our way through the set of choices
  1542. // Level 0 both options it has and the check that
  1543. // the checking for an option it doesn't have results
  1544. // in an empty string.
  1545. verifyRelay6Option(0, 100, TokenOption::TEXTUAL, "hundred.zero");
  1546. verifyRelay6Option(0, 100, TokenOption::EXISTS, "true");
  1547. verifyRelay6Option(0, 101, TokenOption::TEXTUAL, "hundredone.zero");
  1548. verifyRelay6Option(0, 102, TokenOption::TEXTUAL, "");
  1549. verifyRelay6Option(0, 102, TokenOption::EXISTS, "false");
  1550. // Level 1, again both options it has and the one for level 0
  1551. verifyRelay6Option(1, 100, TokenOption::TEXTUAL, "hundred.one");
  1552. verifyRelay6Option(1, 101, TokenOption::TEXTUAL, "");
  1553. verifyRelay6Option(1, 102, TokenOption::TEXTUAL, "hundredtwo.one");
  1554. // Level 2, no encapsulation so no options
  1555. verifyRelay6Option(2, 100, TokenOption::TEXTUAL, "");
  1556. // Check that the debug output was correct. Add the strings
  1557. // to the test vector in the class and then call checkFile
  1558. // for comparison
  1559. addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'hundred.zero'");
  1560. addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'true'");
  1561. addString("EVAL_DEBUG_OPTION Pushing option 101 with value 'hundredone.zero'");
  1562. addString("EVAL_DEBUG_OPTION Pushing option 102 with value ''");
  1563. addString("EVAL_DEBUG_OPTION Pushing option 102 with value 'false'");
  1564. addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'hundred.one'");
  1565. addString("EVAL_DEBUG_OPTION Pushing option 101 with value ''");
  1566. addString("EVAL_DEBUG_OPTION Pushing option 102 with value 'hundredtwo.one'");
  1567. addString("EVAL_DEBUG_OPTION Pushing option 100 with value ''");
  1568. EXPECT_TRUE(checkFile());
  1569. }
  1570. // Verifies if the DHCPv6 packet fields can be extracted.
  1571. TEST_F(TokenTest, pkt6Fields) {
  1572. // The default test creates a v6 DHCPV6_SOLICIT packet with a
  1573. // transaction id of 12345.
  1574. // Check the message type
  1575. ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::MSGTYPE)));
  1576. EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
  1577. ASSERT_EQ(1, values_.size());
  1578. uint32_t expected = htonl(1);
  1579. EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
  1580. // Check the transaction id field
  1581. clearStack();
  1582. ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID)));
  1583. EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
  1584. ASSERT_EQ(1, values_.size());
  1585. expected = htonl(12345);
  1586. EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
  1587. // Check that working with a v4 packet generates an error
  1588. clearStack();
  1589. ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID)));
  1590. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
  1591. // Check that the debug output was correct. Add the strings
  1592. // to the test vector in the class and then call checkFile
  1593. // for comparison
  1594. addString("EVAL_DEBUG_PKT6 Pushing PKT6 field msgtype with value 0x00000001");
  1595. addString("EVAL_DEBUG_PKT6 Pushing PKT6 field transid with value 0x00003039");
  1596. EXPECT_TRUE(checkFile());
  1597. }
  1598. // This test verifies if expression vendor[4491].exist works properly in DHCPv4.
  1599. TEST_F(TokenTest, vendor4SpecificVendorExists) {
  1600. // Case 1: no option, should evaluate to false
  1601. testVendorExists(Option::V4, 4491, 0, "false");
  1602. // Case 2: option present, but uses different enterprise-id, should fail
  1603. testVendorExists(Option::V4, 4491, 1234, "false");
  1604. // Case 3: option present and has matchin enterprise-id, should suceed
  1605. testVendorExists(Option::V4, 4491, 4491, "true");
  1606. addString("EVAL_DEBUG_VENDOR_NO_OPTION Option with code 125 missing, "
  1607. "pushing result false");
  1608. addString("EVAL_DEBUG_VENDOR_ENTERPRISE_ID_MISMATCH Was looking for 4491, "
  1609. "option had 1234, pushing result false");
  1610. addString("EVAL_DEBUG_VENDOR_EXISTS Option with enterprise-id 4491 "
  1611. "found, pushing result true");
  1612. logCheckVerbose(true);
  1613. EXPECT_TRUE(checkFile());
  1614. }
  1615. // This test verifies if expression vendor[4491].exist works properly in DHCPv6.
  1616. TEST_F(TokenTest, vendor6SpecificVendorExists) {
  1617. // Case 1: no option, should evaluate to false
  1618. testVendorExists(Option::V6, 4491, 0, "false");
  1619. // Case 2: option present, but uses different enterprise-id, should fail
  1620. testVendorExists(Option::V6, 4491, 1234, "false");
  1621. // Case 3: option present and has matchin enterprise-id, should suceed
  1622. testVendorExists(Option::V6, 4491, 4491, "true");
  1623. }
  1624. /// Test if expression vendor[*].exists works properly for DHCPv4.
  1625. TEST_F(TokenTest, vendor4AnyVendorExists) {
  1626. // Case 1: no option, should evaluate to false
  1627. testVendorExists(Option::V4, 0, 0, "false");
  1628. // Case 2: option present with vendor-id 1234, should succeed
  1629. testVendorExists(Option::V4, 0, 1234, "true");
  1630. // Case 3: option present with vendor-id 4491, should succeed
  1631. testVendorExists(Option::V4, 0, 4491, "true");
  1632. }
  1633. // Test if expression vendor[*].exists works properly for DHCPv6.
  1634. TEST_F(TokenTest, vendor6AnyVendorExists) {
  1635. // Case 1: no option, should evaluate to false
  1636. testVendorExists(Option::V6, 0, 0, "false");
  1637. // Case 2: option present with vendor-id 1234, should succeed
  1638. testVendorExists(Option::V6, 0, 1234, "true");
  1639. // Case 3: option present with vendor-id 4491, should succeed
  1640. testVendorExists(Option::V6, 0, 4491, "true");
  1641. }
  1642. // Test if expression vendor[*].enterprise works properly for DHCPv4.
  1643. TEST_F(TokenTest, vendor4enterprise) {
  1644. // Case 1: No option present, should return empty string
  1645. testVendorEnterprise(Option::V4, 0, "");
  1646. // Case 2: Option with vendor-id 1234, should return "1234"
  1647. testVendorEnterprise(Option::V4, 1234, encode(1234));
  1648. // Case 3: Option with vendor-id set to maximum value, should still
  1649. // be able to handle it
  1650. testVendorEnterprise(Option::V4, 4294967295, encode(4294967295));
  1651. }
  1652. // Test if expression vendor[*].enterprise works properly for DHCPv6.
  1653. TEST_F(TokenTest, vendor6enterprise) {
  1654. // Case 1: No option present, should return empty string
  1655. testVendorEnterprise(Option::V6, 0, "");
  1656. // Case 2: Option with vendor-id 1234, should return "1234"
  1657. testVendorEnterprise(Option::V6, 1234, encode(1234));
  1658. // Case 3: Option with vendor-id set to maximum value, should still
  1659. // be able to handle it
  1660. testVendorEnterprise(Option::V6, 4294967295, encode(4294967295));
  1661. }
  1662. // This one tests "vendor[4491].option[1].exists" expression. There are so many
  1663. // wonderful ways in which this could fail: the option could not be there,
  1664. // it could have different enterprise-id, may not have suboption 1. Or may
  1665. // have the suboption with valid type, but enterprise may be different.
  1666. TEST_F(TokenTest, vendor4SuboptionExists) {
  1667. // Case 1: expression vendor[4491].option[1].exists, no option present
  1668. testVendorSuboption(Option::V4, 4491, 1, 0, 0, TokenOption::EXISTS, "false");
  1669. // Case 2: expression vendor[4491].option[1].exists, option with vendor-id = 1234,
  1670. // no suboptions, expected result "false"
  1671. testVendorSuboption(Option::V4, 4491, 1, 1234, 0, TokenOption::EXISTS, "false");
  1672. // Case 3: expression vendor[4491].option[1].exists, option with vendor-id = 1234,
  1673. // suboption 1, expected result "false"
  1674. testVendorSuboption(Option::V4, 4491, 1, 1234, 1, TokenOption::EXISTS, "false");
  1675. // Case 4: expression vendor[4491].option[1].exists, option with vendor-id = 4491,
  1676. // suboption 2, expected result "false"
  1677. testVendorSuboption(Option::V4, 4491, 1, 4491, 2, TokenOption::EXISTS, "false");
  1678. // Case 5: expression vendor[4491].option[1].exists, option with vendor-id = 4491,
  1679. // suboption 1, expected result "true"
  1680. testVendorSuboption(Option::V4, 4491, 1, 4491, 1, TokenOption::EXISTS, "true");
  1681. }
  1682. // This is similar to the previous one, but tests vendor[4491].option[1].exists
  1683. // for DHCPv6.
  1684. TEST_F(TokenTest, vendor6SuboptionExists) {
  1685. // Case 1: expression vendor[4491].option[1].exists, no option present
  1686. testVendorSuboption(Option::V6, 4491, 1, 0, 0, TokenOption::EXISTS, "false");
  1687. // Case 2: expression vendor[4491].option[1].exists, option with vendor-id = 1234,
  1688. // no suboptions, expected result "false"
  1689. testVendorSuboption(Option::V6, 4491, 1, 1234, 0, TokenOption::EXISTS, "false");
  1690. // Case 3: expression vendor[4491].option[1].exists, option with vendor-id = 1234,
  1691. // suboption 1, expected result "false"
  1692. testVendorSuboption(Option::V6, 4491, 1, 1234, 1, TokenOption::EXISTS, "false");
  1693. // Case 4: expression vendor[4491].option[1].exists, option with vendor-id = 4491,
  1694. // suboption 2, expected result "false"
  1695. testVendorSuboption(Option::V6, 4491, 1, 4491, 2, TokenOption::EXISTS, "false");
  1696. // Case 5: expression vendor[4491].option[1].exists, option with vendor-id = 4491,
  1697. // suboption 1, expected result "true"
  1698. testVendorSuboption(Option::V6, 4491, 1, 4491, 1, TokenOption::EXISTS, "true");
  1699. }
  1700. // This test verifies if vendor[4491].option[1].hex expression properly returns
  1701. // value of said sub-option or empty string if desired option is not present.
  1702. // This test is for DHCPv4.
  1703. TEST_F(TokenTest, vendor4SuboptionHex) {
  1704. // Case 1: no option present, should return empty string
  1705. testVendorSuboption(Option::V4, 4491, 1, 0, 0, TokenOption::HEXADECIMAL, "");
  1706. // Case 2: option with vendor-id = 1234, no suboptions, expected result ""
  1707. testVendorSuboption(Option::V4, 4491, 1, 1234, 0, TokenOption::HEXADECIMAL, "");
  1708. // Case 3: option with vendor-id = 1234, suboption 1, expected result ""
  1709. testVendorSuboption(Option::V4, 4491, 1, 1234, 1, TokenOption::HEXADECIMAL, "");
  1710. // Case 4: option with vendor-id = 4491, suboption 2, expected result ""
  1711. testVendorSuboption(Option::V4, 4491, 1, 4491, 2, TokenOption::HEXADECIMAL, "");
  1712. // Case 5: option with vendor-id = 4491, suboption 1, expected result content
  1713. // of the option
  1714. testVendorSuboption(Option::V4, 4491, 1, 4491, 1, TokenOption::HEXADECIMAL, "alpha");
  1715. }
  1716. // This test verifies if vendor[4491].option[1].hex expression properly returns
  1717. // value of said sub-option or empty string if desired option is not present.
  1718. // This test is for DHCPv4.
  1719. TEST_F(TokenTest, vendor6SuboptionHex) {
  1720. // Case 1: no option present, should return empty string
  1721. testVendorSuboption(Option::V6, 4491, 1, 0, 0, TokenOption::HEXADECIMAL, "");
  1722. // Case 2: option with vendor-id = 1234, no suboptions, expected result ""
  1723. testVendorSuboption(Option::V6, 4491, 1, 1234, 0, TokenOption::HEXADECIMAL, "");
  1724. // Case 3: option with vendor-id = 1234, suboption 1, expected result ""
  1725. testVendorSuboption(Option::V6, 4491, 1, 1234, 1, TokenOption::HEXADECIMAL, "");
  1726. // Case 4: option with vendor-id = 4491, suboption 2, expected result ""
  1727. testVendorSuboption(Option::V6, 4491, 1, 4491, 2, TokenOption::HEXADECIMAL, "");
  1728. // Case 5: option with vendor-id = 4491, suboption 1, expected result content
  1729. // of the option
  1730. testVendorSuboption(Option::V6, 4491, 1, 4491, 1, TokenOption::HEXADECIMAL, "alpha");
  1731. }
  1732. // This test verifies that "vendor-class[4491].exists" expression can be used
  1733. // in DHCPv4.
  1734. TEST_F(TokenTest, vendorClass4SpecificVendorExists) {
  1735. // Case 1: no option present, should fail
  1736. testVendorClassExists(Option::V4, 4491, 0, "false");
  1737. // Case 2: option exists, but has different vendor-id (1234), should fail
  1738. testVendorClassExists(Option::V4, 4491, 1234, "false");
  1739. // Case 3: option exists and has matching vendor-id, should succeed
  1740. testVendorClassExists(Option::V4, 4491, 4491, "true");
  1741. }
  1742. // This test verifies that "vendor-class[4491].exists" expression can be used
  1743. // in DHCPv6.
  1744. TEST_F(TokenTest, vendorClass6SpecificVendorExists) {
  1745. // Case 1: no option present, should fail
  1746. testVendorClassExists(Option::V6, 4491, 0, "false");
  1747. // Case 2: option exists, but has different vendor-id (1234), should fail
  1748. testVendorClassExists(Option::V6, 4491, 1234, "false");
  1749. // Case 3: option exists and has matching vendor-id, should succeed
  1750. testVendorClassExists(Option::V6, 4491, 4491, "true");
  1751. }
  1752. // This test verifies that "vendor-class[*].exists" can be used in DHCPv4
  1753. // and it matches a vendor class option with any vendor-id.
  1754. TEST_F(TokenTest, vendorClass4AnyVendorExists) {
  1755. // Case 1: no option present, should fail
  1756. testVendorClassExists(Option::V4, 0, 0, "false");
  1757. // Case 2: option exists, should succeed, regardless of the vendor-id
  1758. testVendorClassExists(Option::V4, 0, 1234, "true");
  1759. // Case 3: option exists, should succeed, regardless of the vendor-id
  1760. testVendorClassExists(Option::V4, 0, 4491, "true");
  1761. }
  1762. // This test verifies that "vendor-class[*].exists" can be used in DHCPv6
  1763. // and it matches a vendor class option with any vendor-id.
  1764. TEST_F(TokenTest, vendorClass6AnyVendorExists) {
  1765. // Case 1: no option present, should fail
  1766. testVendorClassExists(Option::V6, 0, 0, "false");
  1767. // Case 2: option exists, should succeed, regardless of the vendor-id
  1768. testVendorClassExists(Option::V6, 0, 1234, "true");
  1769. // Case 3: option exists, should succeed, regardless of the vendor-id
  1770. testVendorClassExists(Option::V6, 0, 4491, "true");
  1771. }
  1772. // Test if expression "vendor-class.enterprise" works properly for DHCPv4.
  1773. TEST_F(TokenTest, vendorClass4enterprise) {
  1774. // Case 1: No option present, should return empty string
  1775. testVendorClassEnterprise(Option::V4, 0, "");
  1776. // Case 2: Option with vendor-id 1234, should return "1234"
  1777. testVendorClassEnterprise(Option::V4, 1234, encode(1234));
  1778. // Case 3: Option with vendor-id set to maximum value, should still
  1779. // be able to handle it
  1780. testVendorClassEnterprise(Option::V4, 4294967295, encode(4294967295));
  1781. }
  1782. // Test if expression "vendor-class.enterprise" works properly for DHCPv6.
  1783. TEST_F(TokenTest, vendorClass6enterprise) {
  1784. // Case 1: No option present, should return empty string
  1785. testVendorClassEnterprise(Option::V6, 0, "");
  1786. // Case 2: Option with vendor-id 1234, should return "1234"
  1787. testVendorClassEnterprise(Option::V6, 1234, encode(1234));
  1788. // Case 3: Option with vendor-id set to maximum value, should still
  1789. // be able to handle it.
  1790. testVendorClassEnterprise(Option::V6, 4294967295, encode(4294967295));
  1791. }
  1792. // Test that expression "vendor-class[4491].data" is able to retrieve content
  1793. // of the first tuple of the vendor-class option in DHCPv4.
  1794. TEST_F(TokenTest, vendorClass4SpecificVendorData) {
  1795. // Case 1: Expression looks for vendor-id 4491, data[0], there is no
  1796. // vendor-class option at all, expected result is empty string.
  1797. testVendorClassData(Option::V4, 4491, 0, 0, 0, "");
  1798. // Case 2: Expression looks for vendor-id 4491, data[0], there is
  1799. // vendor-class with vendor-id 1234 and no data, expected result is empty string.
  1800. testVendorClassData(Option::V4, 4491, 0, 1234, 0, "");
  1801. // Case 3: Expression looks for vendor-id 4491, data[0], there is
  1802. // vendor-class with vendor-id 4491 and no data, expected result is empty string
  1803. testVendorClassData(Option::V4, 4491, 0, 4491, 0, "");
  1804. // Case 4: Expression looks for vendor-id 4491, data[0], there is
  1805. // vendor-class with vendor-id 1234 and 1 data tuple, expected result is empty string
  1806. testVendorClassData(Option::V4, 4491, 0, 1234, 1, "");
  1807. // Case 5: Expression looks for vendor-id 4491, data[0], there is
  1808. // vendor-class with vendor-id 4491 and 1 data tuple, expected result is
  1809. // content of that data ("alpha")
  1810. testVendorClassData(Option::V4, 4491, 0, 4491, 1, "alpha");
  1811. }
  1812. // Test that expression "vendor-class[4491].data" is able to retrieve content
  1813. // of the first tuple of the vendor-class option in DHCPv6.
  1814. TEST_F(TokenTest, vendorClass6SpecificVendorData) {
  1815. // Case 1: Expression looks for vendor-id 4491, data[0], there is no
  1816. // vendor-class option at all, expected result is empty string.
  1817. testVendorClassData(Option::V6, 4491, 0, 0, 0, "");
  1818. // Case 2: Expression looks for vendor-id 4491, data[0], there is
  1819. // vendor-class with vendor-id 1234 and no data, expected result is empty string.
  1820. testVendorClassData(Option::V6, 4491, 0, 1234, 0, "");
  1821. // Case 3: Expression looks for vendor-id 4491, data[0], there is
  1822. // vendor-class with vendor-id 4491 and no data, expected result is empty string
  1823. testVendorClassData(Option::V6, 4491, 0, 4491, 0, "");
  1824. // Case 4: Expression looks for vendor-id 4491, data[0], there is
  1825. // vendor-class with vendor-id 1234 and 1 data tuple, expected result is empty string
  1826. testVendorClassData(Option::V6, 4491, 0, 1234, 1, "");
  1827. // Case 5: Expression looks for vendor-id 4491, data[0], there is
  1828. // vendor-class with vendor-id 4491 and 1 data tuple, expected result is
  1829. // content of that data ("alpha")
  1830. testVendorClassData(Option::V6, 4491, 0, 4491, 1, "alpha");
  1831. }
  1832. // Test that expression "vendor-class[*].data" is able to retrieve content
  1833. // of the first tuple of the vendor-class option in DHCPv4.
  1834. TEST_F(TokenTest, vendorClass4AnyVendorData) {
  1835. // Case 1: Expression looks for any vendor-id (0), data[0], there is no
  1836. // vendor-class option at all, expected result is empty string.
  1837. testVendorClassData(Option::V4, 0, 0, 0, 0, "");
  1838. // Case 2: Expression looks for any vendor-id (0), data[0], there is
  1839. // vendor-class with vendor-id 1234 and no data, expected result is empty string.
  1840. testVendorClassData(Option::V4, 0, 0, 1234, 0, "");
  1841. // Case 3: Expression looks for any vendor-id (0), data[0], there is
  1842. // vendor-class with vendor-id 4491 and no data, expected result is empty string
  1843. testVendorClassData(Option::V4, 0, 0, 4491, 0, "");
  1844. // Case 4: Expression looks for any vendor-id (0), data[0], there is
  1845. // vendor-class with vendor-id 1234 and 1 data tuple, expected result is empty string
  1846. testVendorClassData(Option::V4, 0, 0, 1234, 1, "alpha");
  1847. // Case 5: Expression looks for any vendor-id (0), data[0], there is
  1848. // vendor-class with vendor-id 4491 and 1 data tuple, expected result is
  1849. // content of that data ("alpha")
  1850. testVendorClassData(Option::V4, 0, 0, 4491, 1, "alpha");
  1851. }
  1852. // Test that expression "vendor-class[*].data" is able to retrieve content
  1853. // of the first tuple of the vendor-class option in DHCPv6.
  1854. TEST_F(TokenTest, vendorClass6AnyVendorData) {
  1855. // Case 1: Expression looks for any vendor-id (0), data[0], there is no
  1856. // vendor-class option at all, expected result is empty string.
  1857. testVendorClassData(Option::V6, 0, 0, 0, 0, "");
  1858. // Case 2: Expression looks for any vendor-id (0), data[0], there is
  1859. // vendor-class with vendor-id 1234 and no data, expected result is empty string.
  1860. testVendorClassData(Option::V6, 0, 0, 1234, 0, "");
  1861. // Case 3: Expression looks for any vendor-id (0), data[0], there is
  1862. // vendor-class with vendor-id 4491 and no data, expected result is empty string
  1863. testVendorClassData(Option::V6, 0, 0, 4491, 0, "");
  1864. // Case 4: Expression looks for any vendor-id (0), data[0], there is
  1865. // vendor-class with vendor-id 1234 and 1 data tuple, expected result is empty string
  1866. testVendorClassData(Option::V6, 0, 0, 1234, 1, "alpha");
  1867. // Case 5: Expression looks for any vendor-id (0), data[0], there is
  1868. // vendor-class with vendor-id 4491 and 1 data tuple, expected result is
  1869. // content of that data ("alpha")
  1870. testVendorClassData(Option::V6, 0, 0, 4491, 1, "alpha");
  1871. }
  1872. // This test verifies if expression vendor-class[4491].data[3] is able to access
  1873. // the tuple specified by index. This is a DHCPv4 test.
  1874. TEST_F(TokenTest, vendorClass4DataIndex) {
  1875. // Case 1: Expression looks for vendor-id 4491, data[3], there is no
  1876. // vendor-class option at all, expected result is empty string.
  1877. testVendorClassData(Option::V4, 4491, 3, 0, 0, "");
  1878. // Case 2: Expression looks for vendor-id 4491, data[3], there is
  1879. // vendor-class with vendor-id 1234 and no data, expected result is empty string.
  1880. testVendorClassData(Option::V4, 4491, 3, 1234, 0, "");
  1881. // Case 3: Expression looks for vendor-id 4491, data[3], there is
  1882. // vendor-class with vendor-id 4491 and no data, expected result is empty string
  1883. testVendorClassData(Option::V4, 4491, 3, 4491, 0, "");
  1884. // Case 4: Expression looks for vendor-id 4491, data[3], there is
  1885. // vendor-class with vendor-id 1234 and 2 data tuples, expected result is empty string.
  1886. testVendorClassData(Option::V4, 4491, 3, 1234, 1, "");
  1887. // Case 5: Expression looks for vendor-id 4491, data[3], there is
  1888. // vendor-class with vendor-id 4491, but has only 2 data tuples, expected
  1889. // result is empty string.
  1890. testVendorClassData(Option::V4, 4491, 3, 1234, 1, "");
  1891. // Case 6: Expression looks for vendor-id 4491, data[3], there is
  1892. // vendor-class with vendor-id 4491 and 5 data tuples, expected result is
  1893. // content of that tuple ("gamma")
  1894. testVendorClassData(Option::V4, 4491, 3, 4491, 5, "gamma");
  1895. }
  1896. // This test verifies if expression vendor-class[4491].data[3] is able to access
  1897. // the tuple specified by index. This is a DHCPv6 test.
  1898. TEST_F(TokenTest, vendorClass6DataIndex) {
  1899. // Case 1: Expression looks for vendor-id 4491, data[3], there is no
  1900. // vendor-class option at all, expected result is empty string.
  1901. testVendorClassData(Option::V6, 4491, 3, 0, 0, "");
  1902. // Case 2: Expression looks for vendor-id 4491, data[3], there is
  1903. // vendor-class with vendor-id 1234 and no data, expected result is empty string.
  1904. testVendorClassData(Option::V6, 4491, 3, 1234, 0, "");
  1905. // Case 3: Expression looks for vendor-id 4491, data[3], there is
  1906. // vendor-class with vendor-id 4491 and no data, expected result is empty string
  1907. testVendorClassData(Option::V6, 4491, 3, 4491, 0, "");
  1908. // Case 4: Expression looks for vendor-id 4491, data[3], there is
  1909. // vendor-class with vendor-id 1234 and 2 data tuples, expected result is empty string.
  1910. testVendorClassData(Option::V6, 4491, 3, 1234, 1, "");
  1911. // Case 5: Expression looks for vendor-id 4491, data[3], there is
  1912. // vendor-class with vendor-id 4491, but has only 2 data tuples, expected
  1913. // result is empty string.
  1914. testVendorClassData(Option::V6, 4491, 3, 1234, 1, "");
  1915. // Case 6: Expression looks for vendor-id 4491, data[3], there is
  1916. // vendor-class with vendor-id 4491 and 5 data tuples, expected result is
  1917. // content of that tuple ("gamma")
  1918. testVendorClassData(Option::V6, 4491, 3, 4491, 5, "gamma");
  1919. }
  1920. };