token_unittest.cc 114 KB

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