test_fragments.py 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251
  1. #!/usr/bin/env python
  2. #
  3. # Copyright 2021 Espressif Systems (Shanghai) CO LTD
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. #
  17. import os
  18. import sys
  19. import tempfile
  20. import unittest
  21. from io import StringIO
  22. from pyparsing import ParseException, ParseFatalException, Word, alphanums
  23. try:
  24. from fragments import FRAGMENT_TYPES, Fragment, FragmentFile, Mapping
  25. from sdkconfig import SDKConfig
  26. except ImportError:
  27. sys.path.append('../')
  28. from fragments import FRAGMENT_TYPES, Fragment, FragmentFile, Mapping
  29. from sdkconfig import SDKConfig
  30. class SampleFragment(Fragment):
  31. grammars = {
  32. 'key_1': Fragment.KeyValue(Word(alphanums + '_').setResultsName('value'), 0, None, True),
  33. 'key_2': Fragment.KeyValue(Word(alphanums + '_').setResultsName('value'), 0, None, False),
  34. 'key_3': Fragment.KeyValue(Word(alphanums + '_').setResultsName('value'), 3, 5, False)
  35. }
  36. def set_key_value(self, key, parse_results):
  37. if key == 'key_1':
  38. self.key_1 = list()
  39. for result in parse_results:
  40. self.key_1.append(result['value'])
  41. elif key == 'key_2':
  42. self.key_2 = list()
  43. for result in parse_results:
  44. self.key_2.append(result['value'])
  45. def get_key_grammars(self):
  46. return self.__class__.grammars
  47. FRAGMENT_TYPES['test'] = SampleFragment
  48. class FragmentTest(unittest.TestCase):
  49. def setUp(self):
  50. with tempfile.NamedTemporaryFile(delete=False) as f:
  51. self.kconfigs_source_file = os.path.join(tempfile.gettempdir(), f.name)
  52. with tempfile.NamedTemporaryFile(delete=False) as f:
  53. self.kconfig_projbuilds_source_file = os.path.join(tempfile.gettempdir(), f.name)
  54. os.environ['COMPONENT_KCONFIGS_SOURCE_FILE'] = self.kconfigs_source_file
  55. os.environ['COMPONENT_KCONFIGS_PROJBUILD_SOURCE_FILE'] = self.kconfig_projbuilds_source_file
  56. os.environ['COMPONENT_KCONFIGS'] = ''
  57. os.environ['COMPONENT_KCONFIGS_PROJBUILD'] = ''
  58. # prepare_kconfig_files.py doesn't have to be called because COMPONENT_KCONFIGS and
  59. # COMPONENT_KCONFIGS_PROJBUILD are empty
  60. self.sdkconfig = SDKConfig('data/Kconfig', 'data/sdkconfig')
  61. def tearDown(self):
  62. try:
  63. os.remove(self.kconfigs_source_file)
  64. os.remove(self.kconfig_projbuilds_source_file)
  65. except Exception:
  66. pass
  67. @staticmethod
  68. def create_fragment_file(contents, name='test_fragment.lf'):
  69. f = StringIO(contents)
  70. f.name = name
  71. return f
  72. def test_basic(self):
  73. test_fragment = self.create_fragment_file(u"""
  74. [test:test]
  75. key_1:
  76. value_1
  77. value_2 # comments should be ignored
  78. value_3
  79. # this is a comment as well
  80. key_2: value_a
  81. # this is the last comment
  82. """)
  83. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  84. self.assertEqual(len(fragment_file.fragments[0].key_1), 3)
  85. self.assertEqual(fragment_file.fragments[0].key_1[0], 'value_1')
  86. self.assertEqual(fragment_file.fragments[0].key_1[1], 'value_2')
  87. self.assertEqual(fragment_file.fragments[0].key_1[2], 'value_3')
  88. self.assertEqual(len(fragment_file.fragments[0].key_2), 1)
  89. self.assertEqual(fragment_file.fragments[0].key_2[0], 'value_a')
  90. def test_duplicate_keys(self):
  91. test_fragment = self.create_fragment_file(u"""
  92. [test:test]
  93. key_1: value_1
  94. key_1: value_a
  95. """)
  96. with self.assertRaises(ParseFatalException):
  97. FragmentFile(test_fragment, self.sdkconfig)
  98. def test_empty_key(self):
  99. test_fragment = self.create_fragment_file(u"""
  100. [test:test]
  101. key_1:
  102. """)
  103. with self.assertRaises(ParseException):
  104. FragmentFile(test_fragment, self.sdkconfig)
  105. def test_conditional(self):
  106. test_fragment = self.create_fragment_file(u"""
  107. [test:test]
  108. key_1:
  109. value_1
  110. if A = y:
  111. value_2
  112. value_3
  113. if A = n:
  114. value_4
  115. if B = n:
  116. value_5
  117. """)
  118. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  119. self.assertEqual(fragment_file.fragments[0].key_1[0], 'value_1')
  120. self.assertEqual(fragment_file.fragments[0].key_1[1], 'value_2')
  121. self.assertEqual(fragment_file.fragments[0].key_1[2], 'value_3')
  122. self.assertEqual(fragment_file.fragments[0].key_1[3], 'value_5')
  123. test_fragment = self.create_fragment_file(u"""
  124. [test:test]
  125. key_1:
  126. value_1
  127. if B = y:
  128. value_2
  129. elif C = y:
  130. value_3
  131. elif A = y:
  132. value_4
  133. else:
  134. value_5
  135. value_6
  136. """)
  137. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  138. self.assertEqual(fragment_file.fragments[0].key_1[0], 'value_1')
  139. self.assertEqual(fragment_file.fragments[0].key_1[1], 'value_3')
  140. self.assertEqual(fragment_file.fragments[0].key_1[2], 'value_6')
  141. test_fragment = self.create_fragment_file(u"""
  142. [test:test]
  143. key_1:
  144. value_1
  145. if A = y:
  146. value_2
  147. if B = y:
  148. value_3
  149. else:
  150. value_4
  151. if C = y:
  152. value_5
  153. value_6
  154. value_7
  155. key_2:
  156. value_a
  157. if B != y:
  158. value_b
  159. """)
  160. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  161. self.assertEqual(fragment_file.fragments[0].key_1[0], 'value_1')
  162. self.assertEqual(fragment_file.fragments[0].key_1[1], 'value_2')
  163. self.assertEqual(fragment_file.fragments[0].key_1[2], 'value_4')
  164. self.assertEqual(fragment_file.fragments[0].key_1[3], 'value_5')
  165. self.assertEqual(fragment_file.fragments[0].key_1[4], 'value_6')
  166. self.assertEqual(fragment_file.fragments[0].key_1[5], 'value_7')
  167. self.assertEqual(fragment_file.fragments[0].key_2[0], 'value_a')
  168. self.assertEqual(fragment_file.fragments[0].key_2[1], 'value_b')
  169. test_fragment = self.create_fragment_file(u"""
  170. [test:test]
  171. key_1:
  172. if A = n:
  173. value_2
  174. """)
  175. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  176. self.assertEqual(len(fragment_file.fragments[0].key_1), 0)
  177. def test_empty_file(self):
  178. test_fragment = self.create_fragment_file(u"""
  179. """)
  180. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  181. self.assertEqual(len(fragment_file.fragments), 0)
  182. def test_setting_indent(self):
  183. test_fragment = self.create_fragment_file(u"""
  184. [test:test]
  185. key_1:
  186. value_1
  187. value_2
  188. value_3
  189. """)
  190. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  191. self.assertEqual(len(fragment_file.fragments[0].key_1), 3)
  192. self.assertEqual(fragment_file.fragments[0].key_1[0], 'value_1')
  193. self.assertEqual(fragment_file.fragments[0].key_1[1], 'value_2')
  194. self.assertEqual(fragment_file.fragments[0].key_1[2], 'value_3')
  195. test_fragment = self.create_fragment_file(u"""
  196. [test:test]
  197. key_1:
  198. value_1
  199. value_2 # first element dictates indent
  200. value_3
  201. """)
  202. with self.assertRaises(ParseFatalException):
  203. FragmentFile(test_fragment, self.sdkconfig)
  204. def test_values_num_limit(self):
  205. test_fragment = self.create_fragment_file(u"""
  206. [test:test]
  207. key_1:
  208. value_a
  209. key_3:
  210. value_1
  211. value_2
  212. value_3
  213. """)
  214. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  215. test_fragment = self.create_fragment_file(u"""
  216. [test:test]
  217. key_1:
  218. value_a
  219. key_3:
  220. value_1
  221. value_2
  222. value_3
  223. value_4
  224. """)
  225. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  226. self.assertEqual(len(fragment_file.fragments), 1)
  227. test_fragment = self.create_fragment_file(u"""
  228. [test:test]
  229. key_1:
  230. value_a
  231. key_3:
  232. value_1
  233. value_2
  234. value_3
  235. value_4
  236. value_5
  237. """)
  238. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  239. self.assertEqual(len(fragment_file.fragments), 1)
  240. test_fragment = self.create_fragment_file(u"""
  241. [test:test]
  242. key_1:
  243. value_a
  244. key_3:
  245. value_1
  246. value_2
  247. """)
  248. with self.assertRaises(ParseFatalException):
  249. FragmentFile(test_fragment, self.sdkconfig)
  250. test_fragment = self.create_fragment_file(u"""
  251. [test:test]
  252. key_1:
  253. value_a
  254. key_3:
  255. value_1
  256. value_2
  257. value_3
  258. value_4
  259. value_5
  260. value_6
  261. """)
  262. with self.assertRaises(ParseFatalException):
  263. FragmentFile(test_fragment, self.sdkconfig)
  264. def test_unsupported_key(self):
  265. test_fragment = self.create_fragment_file(u"""
  266. [test:test]
  267. key_1:
  268. value_a
  269. key_4:
  270. value_1
  271. """)
  272. with self.assertRaises(ParseFatalException):
  273. FragmentFile(test_fragment, self.sdkconfig)
  274. def test_empty_fragment(self):
  275. test_fragment = self.create_fragment_file(u"""
  276. [test:test]
  277. """)
  278. with self.assertRaises(ParseException):
  279. FragmentFile(test_fragment, self.sdkconfig)
  280. def test_empty_conditional(self):
  281. test_fragment = self.create_fragment_file(u"""
  282. [test:test]
  283. key_1:
  284. if B = y:
  285. else:
  286. value_1
  287. """)
  288. with self.assertRaises(ParseFatalException):
  289. FragmentFile(test_fragment, self.sdkconfig)
  290. test_fragment = self.create_fragment_file(u"""
  291. [test:test]
  292. key_1:
  293. if B = y:
  294. value_1
  295. else B = y:
  296. """)
  297. with self.assertRaises(ParseFatalException):
  298. FragmentFile(test_fragment, self.sdkconfig)
  299. test_fragment = self.create_fragment_file(u"""
  300. [test:test]
  301. key_1:
  302. if B = y:
  303. value_1
  304. elif B = y:
  305. else:
  306. value_2
  307. """)
  308. with self.assertRaises(ParseFatalException):
  309. FragmentFile(test_fragment, self.sdkconfig)
  310. def test_out_of_order_conditional(self):
  311. test_fragment = self.create_fragment_file(u"""
  312. [test:test]
  313. key_1:
  314. elif B = y:
  315. value_1
  316. else:
  317. value_2
  318. """)
  319. with self.assertRaises(ParseFatalException):
  320. FragmentFile(test_fragment, self.sdkconfig)
  321. test_fragment = self.create_fragment_file(u"""
  322. [test:test]
  323. key_1:
  324. else:
  325. value_2
  326. """)
  327. with self.assertRaises(ParseFatalException):
  328. FragmentFile(test_fragment, self.sdkconfig)
  329. def test_required_keys(self):
  330. test_fragment = self.create_fragment_file(u"""
  331. [test:test]
  332. key_2:
  333. value_1
  334. """)
  335. with self.assertRaises(ParseFatalException):
  336. FragmentFile(test_fragment, self.sdkconfig)
  337. def test_multiple_fragments(self):
  338. test_fragment = self.create_fragment_file(u"""
  339. [test:test1]
  340. key_1:
  341. value_1
  342. [test:test2]
  343. key_1:
  344. value_2
  345. """)
  346. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  347. self.assertEqual(len(fragment_file.fragments), 2)
  348. self.assertEqual(fragment_file.fragments[0].key_1[0], 'value_1')
  349. self.assertEqual(fragment_file.fragments[1].key_1[0], 'value_2')
  350. def test_whole_conditional_fragment(self):
  351. test_fragment = self.create_fragment_file(u"""
  352. if B = y:
  353. [test:test1]
  354. key_1:
  355. value_1
  356. else:
  357. [test:test2]
  358. key_1:
  359. value_2
  360. if A = y:
  361. [test:test3]
  362. key_1:
  363. value_3
  364. if C = y:
  365. value_6
  366. [test:test4]
  367. key_1:
  368. value_4
  369. [test:test5]
  370. key_1:
  371. value_5
  372. """)
  373. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  374. self.assertEqual(len(fragment_file.fragments), 4)
  375. self.assertEqual(fragment_file.fragments[0].name, 'test2')
  376. self.assertEqual(fragment_file.fragments[1].name, 'test3')
  377. self.assertEqual(fragment_file.fragments[1].key_1[1], 'value_6')
  378. self.assertEqual(fragment_file.fragments[2].name, 'test4')
  379. self.assertEqual(fragment_file.fragments[3].name, 'test5')
  380. def test_equivalent_conditional_fragment(self):
  381. test_fragment1 = self.create_fragment_file(u"""
  382. if A = y:
  383. [test:test1]
  384. key_1:
  385. value_1
  386. else:
  387. [test:test2]
  388. key_1:
  389. value_2
  390. """)
  391. fragment_file1 = FragmentFile(test_fragment1, self.sdkconfig)
  392. self.assertEqual(len(fragment_file1.fragments), 1)
  393. self.assertEqual(fragment_file1.fragments[0].key_1[0], 'value_1')
  394. test_fragment2 = self.create_fragment_file(u"""
  395. [test:test1]
  396. key_1:
  397. if A = y:
  398. value_1
  399. else:
  400. value_2
  401. """)
  402. fragment_file2 = FragmentFile(test_fragment2, self.sdkconfig)
  403. self.assertEqual(len(fragment_file2.fragments), 1)
  404. self.assertEqual(fragment_file2.fragments[0].key_1[0], 'value_1')
  405. class SectionsTest(FragmentTest):
  406. def test_basic(self):
  407. test_fragment = self.create_fragment_file(u"""
  408. [sections:test]
  409. entries:
  410. .section1
  411. .section2
  412. """)
  413. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  414. self.assertEqual(fragment_file.fragments[0].entries, {'.section1', '.section2'})
  415. def test_duplicate_entries(self):
  416. test_fragment = self.create_fragment_file(u"""
  417. [sections:test]
  418. entries:
  419. .section1
  420. .section2
  421. .section3
  422. .section2
  423. """)
  424. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  425. self.assertEqual(fragment_file.fragments[0].entries, {'.section1', '.section2', '.section3'})
  426. def test_empty_entries(self):
  427. test_fragment = self.create_fragment_file(u"""
  428. [sections:test]
  429. entries:
  430. """)
  431. with self.assertRaises(ParseException):
  432. FragmentFile(test_fragment, self.sdkconfig)
  433. test_fragment = self.create_fragment_file(u"""
  434. [sections:test]
  435. entries:
  436. if B = y:
  437. .section1
  438. """)
  439. with self.assertRaises(ParseFatalException):
  440. FragmentFile(test_fragment, self.sdkconfig)
  441. def test_entries_grammar(self):
  442. test_fragment = self.create_fragment_file(u"""
  443. [sections:test]
  444. entries:
  445. _valid1
  446. valid2.
  447. .valid3_-
  448. """)
  449. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  450. self.assertEqual(fragment_file.fragments[0].entries,
  451. {'_valid1', 'valid2.', '.valid3_-'})
  452. # invalid starting char
  453. test_fragment = self.create_fragment_file(u"""
  454. [sections:test]
  455. entries:
  456. 1invalid
  457. """)
  458. with self.assertRaises(ParseException):
  459. FragmentFile(test_fragment, self.sdkconfig)
  460. test_fragment = self.create_fragment_file(u"""
  461. [sections:test]
  462. entries:
  463. -invalid
  464. """)
  465. with self.assertRaises(ParseException):
  466. FragmentFile(test_fragment, self.sdkconfig)
  467. # + notation
  468. test_fragment = self.create_fragment_file(u"""
  469. [sections:test]
  470. entries:
  471. valid+
  472. """)
  473. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  474. self.assertEqual(fragment_file.fragments[0].entries,
  475. {'valid+'})
  476. test_fragment = self.create_fragment_file(u"""
  477. [sections:test]
  478. entries:
  479. inva+lid+
  480. """)
  481. with self.assertRaises(ParseFatalException):
  482. FragmentFile(test_fragment, self.sdkconfig)
  483. class SchemeTest(FragmentTest):
  484. def test_basic(self):
  485. test_fragment = self.create_fragment_file(u"""
  486. [scheme:test]
  487. entries:
  488. sections1 -> target1
  489. sections2 -> target2
  490. """)
  491. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  492. self.assertEqual(fragment_file.fragments[0].entries,
  493. {('sections1', 'target1'),
  494. ('sections2', 'target2')})
  495. def test_duplicate_entries(self):
  496. test_fragment = self.create_fragment_file(u"""
  497. [scheme:test]
  498. entries:
  499. sections1 -> target1
  500. sections2 -> target2
  501. sections2 -> target2
  502. """)
  503. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  504. self.assertEqual(fragment_file.fragments[0].entries,
  505. {('sections1', 'target1'),
  506. ('sections2', 'target2')})
  507. def test_empty_entries(self):
  508. test_fragment = self.create_fragment_file(u"""
  509. [scheme:test]
  510. entries:
  511. """)
  512. with self.assertRaises(ParseException):
  513. FragmentFile(test_fragment, self.sdkconfig)
  514. test_fragment = self.create_fragment_file(u"""
  515. [scheme:test]
  516. entries:
  517. if B = y:
  518. sections1 -> target1
  519. """)
  520. with self.assertRaises(ParseFatalException):
  521. FragmentFile(test_fragment, self.sdkconfig)
  522. def test_improper_grammar(self):
  523. test_fragment = self.create_fragment_file(u"""
  524. [scheme:test]
  525. entries:
  526. sections1, target1 # improper separator
  527. """)
  528. with self.assertRaises(ParseException):
  529. FragmentFile(test_fragment, self.sdkconfig)
  530. class MappingTest(FragmentTest):
  531. def test_basic(self):
  532. test_fragment = self.create_fragment_file(u"""
  533. [mapping:test]
  534. archive: lib.a
  535. entries:
  536. obj:symbol (noflash)
  537. obj (noflash)
  538. obj:symbol_2 (noflash)
  539. obj_2 (noflash)
  540. * (noflash)
  541. """)
  542. expected = {('obj', 'symbol', 'noflash'),
  543. ('obj', None, 'noflash'),
  544. ('obj', 'symbol_2', 'noflash'),
  545. ('obj_2', None, 'noflash'),
  546. ('*', None, 'noflash')}
  547. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  548. self.assertEqual(expected, fragment_file.fragments[0].entries)
  549. def test_archive(self):
  550. test_fragment = self.create_fragment_file(u"""
  551. [mapping:test]
  552. archive:
  553. entries:
  554. * (default)
  555. """)
  556. with self.assertRaises(ParseException):
  557. FragmentFile(test_fragment, self.sdkconfig)
  558. test_fragment = self.create_fragment_file(u"""
  559. [mapping:test]
  560. archive:
  561. lib1.a
  562. lib2.a
  563. entries:
  564. * (default)
  565. """)
  566. with self.assertRaises(ParseFatalException):
  567. FragmentFile(test_fragment, self.sdkconfig)
  568. def test_empty_entries(self):
  569. test_fragment = self.create_fragment_file(u"""
  570. [mapping:test]
  571. archive:
  572. lib.a
  573. entries:
  574. if B = y:
  575. * (noflash) # if condition is false, then no 'entries' key value
  576. """)
  577. expected = set()
  578. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  579. self.assertEqual(expected, fragment_file.fragments[0].entries)
  580. test_fragment = self.create_fragment_file(u"""
  581. [mapping:test]
  582. archive:
  583. lib.a
  584. entries:
  585. """)
  586. with self.assertRaises(ParseException):
  587. FragmentFile(test_fragment, self.sdkconfig)
  588. def test_duplicate_entries(self):
  589. test_fragment = self.create_fragment_file(u"""
  590. [mapping:test]
  591. archive:
  592. lib.a
  593. entries:
  594. obj:symbol (noflash)
  595. obj:symbol (noflash)
  596. """)
  597. expected = {('obj', 'symbol', 'noflash')}
  598. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  599. self.assertEqual(expected, fragment_file.fragments[0].entries)
  600. def test_invalid_grammar(self):
  601. test_fragment = self.create_fragment_file(u"""
  602. [mapping:test]
  603. archive:
  604. lib.a
  605. """)
  606. with self.assertRaises(ParseFatalException):
  607. FragmentFile(test_fragment, self.sdkconfig)
  608. test_fragment = self.create_fragment_file(u"""
  609. [mapping:test]
  610. entries:
  611. * (default)
  612. """)
  613. with self.assertRaises(ParseFatalException):
  614. FragmentFile(test_fragment, self.sdkconfig)
  615. test_fragment = self.create_fragment_file(u"""
  616. [mapping:test]
  617. archive: lib.a
  618. entries:
  619. obj: (noflash)
  620. """)
  621. with self.assertRaises(ParseException):
  622. FragmentFile(test_fragment, self.sdkconfig)
  623. test_fragment = self.create_fragment_file(u"""
  624. [mapping:test]
  625. archive: lib.a
  626. entries:
  627. obj: ()
  628. """)
  629. with self.assertRaises(ParseException):
  630. FragmentFile(test_fragment, self.sdkconfig)
  631. test_fragment = self.create_fragment_file(u"""
  632. [mapping:test]
  633. archive: lib.a
  634. entries:
  635. obj:symbol
  636. """)
  637. with self.assertRaises(ParseException):
  638. FragmentFile(test_fragment, self.sdkconfig)
  639. test_fragment = self.create_fragment_file(u"""
  640. [mapping:test]
  641. archive: lib.a
  642. entries:
  643. (noflash)
  644. """)
  645. with self.assertRaises(ParseException):
  646. FragmentFile(test_fragment, self.sdkconfig)
  647. test_fragment = self.create_fragment_file(u"""
  648. [mapping:test]
  649. archive: lib.a
  650. entries:
  651. obj:* (noflash)
  652. """)
  653. with self.assertRaises(ParseException):
  654. FragmentFile(test_fragment, self.sdkconfig)
  655. test_fragment = self.create_fragment_file(u"""
  656. [mapping:test]
  657. archive: lib.a
  658. entries:
  659. :symbol (noflash)
  660. """)
  661. with self.assertRaises(ParseException):
  662. FragmentFile(test_fragment, self.sdkconfig)
  663. test_fragment = self.create_fragment_file(u"""
  664. [mapping:test]
  665. archive: lib.a
  666. entries:
  667. *:symbol (noflash)
  668. """)
  669. with self.assertRaises(ParseException):
  670. FragmentFile(test_fragment, self.sdkconfig)
  671. def test_keep_flag(self):
  672. # Test parsing combinations and orders of flags
  673. test_fragment = self.create_fragment_file(u"""
  674. [mapping:map]
  675. archive: libmain.a
  676. entries:
  677. obj1 (default);
  678. text->flash_text KEEP(),
  679. rodata->flash_rodata KEEP() KEEP()
  680. """)
  681. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  682. fragment = fragment_file.fragments[0]
  683. expected = [('text', 'flash_text', [Mapping.Keep()]),
  684. ('rodata', 'flash_rodata', [Mapping.Keep(), Mapping.Keep()])]
  685. actual = fragment.flags[('obj1', None, 'default')]
  686. self.assertEqual(expected, actual)
  687. def test_align_flag(self):
  688. # Test parsing combinations and orders of flags
  689. test_fragment = self.create_fragment_file(u"""
  690. [mapping:map]
  691. archive: libmain.a
  692. entries:
  693. obj1 (default);
  694. text->flash_text ALIGN(8),
  695. rodata->flash_rodata ALIGN(8, pre),
  696. data->dram0_data ALIGN(8, pre, post),
  697. bss->dram0_bss ALIGN(8, post),
  698. common->dram0_bss ALIGN(8, pre, post) ALIGN(8)
  699. """)
  700. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  701. fragment = fragment_file.fragments[0]
  702. expected = [('text', 'flash_text', [Mapping.Align(8, True, False)]),
  703. ('rodata', 'flash_rodata', [Mapping.Align(8, True, False)]),
  704. ('data', 'dram0_data', [Mapping.Align(8, True, True)]),
  705. ('bss', 'dram0_bss', [Mapping.Align(8, False, True)]),
  706. ('common', 'dram0_bss', [Mapping.Align(8, True, True), Mapping.Align(8, True, False)])]
  707. actual = fragment.flags[('obj1', None, 'default')]
  708. self.assertEqual(expected, actual)
  709. # Wrong post, pre order
  710. test_fragment = self.create_fragment_file(u"""
  711. [mapping:map]
  712. archive: libmain.a
  713. entries:
  714. obj1 (noflash)
  715. text->iram0_text ALIGN(8, post, pre)
  716. """)
  717. with self.assertRaises(ParseFatalException):
  718. FragmentFile(test_fragment, self.sdkconfig)
  719. def test_sort_flag(self):
  720. # Test parsing combinations and orders of flags
  721. test_fragment = self.create_fragment_file(u"""
  722. [mapping:map]
  723. archive: libmain.a
  724. entries:
  725. obj1 (default);
  726. text->flash_text SORT(name),
  727. rodata->flash_rodata SORT(alignment),
  728. data->dram0_data SORT(init_priority),
  729. bss->dram0_bss SORT(name, alignment),
  730. common->dram0_bss SORT(alignment, name),
  731. iram->iram0_text SORT(name, name),
  732. dram->dram0_data SORT(alignment, alignment)
  733. """)
  734. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  735. fragment = fragment_file.fragments[0]
  736. expected = [('text', 'flash_text', [Mapping.Sort('name')]),
  737. ('rodata', 'flash_rodata', [Mapping.Sort('alignment')]),
  738. ('data', 'dram0_data', [Mapping.Sort('init_priority')]),
  739. ('bss', 'dram0_bss', [Mapping.Sort('name', 'alignment')]),
  740. ('common', 'dram0_bss', [Mapping.Sort('alignment', 'name')]),
  741. ('iram', 'iram0_text', [Mapping.Sort('name', 'name')]),
  742. ('dram', 'dram0_data', [Mapping.Sort('alignment', 'alignment')])]
  743. actual = fragment.flags[('obj1', None, 'default')]
  744. self.assertEqual(expected, actual)
  745. test_fragment = self.create_fragment_file(u"""
  746. [mapping:map]
  747. archive: libmain.a
  748. entries:
  749. obj1 (default)
  750. text->iram0_text SORT(name) SORT(alignment)
  751. """)
  752. def test_surround_flag(self):
  753. # Test parsing combinations and orders of flags
  754. test_fragment = self.create_fragment_file(u"""
  755. [mapping:map]
  756. archive: libmain.a
  757. entries:
  758. obj1 (default);
  759. text->flash_text SURROUND(sym1)
  760. """)
  761. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  762. fragment = fragment_file.fragments[0]
  763. expected = [('text', 'flash_text', [Mapping.Surround('sym1')])]
  764. actual = fragment.flags[('obj1', None, 'default')]
  765. self.assertEqual(expected, actual)
  766. def test_flag_order(self):
  767. # Test that the order in which the flags are specified is retained
  768. test_fragment = self.create_fragment_file(u"""
  769. [mapping:map]
  770. archive: libmain.a
  771. entries:
  772. obj1 (default);
  773. text->flash_text ALIGN(4) KEEP() SURROUND(sym1) ALIGN(8) SORT(name),
  774. rodata->flash_rodata KEEP() ALIGN(4) KEEP() SURROUND(sym1) ALIGN(8) ALIGN(4) SORT(name)
  775. """)
  776. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  777. fragment = fragment_file.fragments[0]
  778. expected = [('text', 'flash_text', [Mapping.Align(4, True, False),
  779. Mapping.Keep(),
  780. Mapping.Surround('sym1'),
  781. Mapping.Align(8, True, False),
  782. Mapping.Sort('name')]),
  783. ('rodata', 'flash_rodata', [Mapping.Keep(),
  784. Mapping.Align(4, True, False),
  785. Mapping.Keep(),
  786. Mapping.Surround('sym1'),
  787. Mapping.Align(8, True, False),
  788. Mapping.Align(4, True, False),
  789. Mapping.Sort('name')])]
  790. actual = fragment.flags[('obj1', None, 'default')]
  791. self.assertEqual(expected, actual)
  792. def test_flags_entries_multiple_flags(self):
  793. # Not an error, generation step handles this, since
  794. # it that step has a more complete information
  795. # about all mappings.
  796. test_fragment = self.create_fragment_file(u"""
  797. [mapping:map]
  798. archive: libmain.a
  799. entries:
  800. obj1 (default);
  801. text->flash_text ALIGN(4) KEEP() SURROUND(sym1) SORT(name),
  802. text->flash_text ALIGN(4) KEEP() SURROUND(sym1) SORT(name)
  803. """)
  804. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  805. fragment = fragment_file.fragments[0]
  806. expected = [('text', 'flash_text', [Mapping.Align(4, True, False),
  807. Mapping.Keep(),
  808. Mapping.Surround('sym1'),
  809. Mapping.Sort('name')]),
  810. ('text', 'flash_text', [Mapping.Align(4, True, False),
  811. Mapping.Keep(),
  812. Mapping.Surround('sym1'),
  813. Mapping.Sort('name')])]
  814. actual = fragment.flags[('obj1', None, 'default')]
  815. self.assertEqual(expected, actual)
  816. def test_flags_entries_multiple_flags_and_entries(self):
  817. # Not an error, generation step handles this, since
  818. # it that step has a more complete information
  819. # about all mappings. This can happen across multiple
  820. # mapping fragments.
  821. test_fragment = self.create_fragment_file(u"""
  822. [mapping:map]
  823. archive: libmain.a
  824. entries:
  825. obj1 (default);
  826. text->flash_text ALIGN(4) KEEP() SURROUND(sym1) SORT(name)
  827. obj1 (default);
  828. text->flash_text ALIGN(4) KEEP() SURROUND(sym1) SORT(name)
  829. """)
  830. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  831. fragment = fragment_file.fragments[0]
  832. expected = [('text', 'flash_text', [Mapping.Align(4, True, False),
  833. Mapping.Keep(),
  834. Mapping.Surround('sym1'),
  835. Mapping.Sort('name')]),
  836. ('text', 'flash_text', [Mapping.Align(4, True, False),
  837. Mapping.Keep(),
  838. Mapping.Surround('sym1'),
  839. Mapping.Sort('name')])]
  840. actual = fragment.flags[('obj1', None, 'default')]
  841. self.assertEqual(expected, actual)
  842. class DeprecatedMappingTest(FragmentTest):
  843. def test_valid_grammar(self):
  844. test_fragment = self.create_fragment_file(u"""
  845. [mapping]
  846. archive: lib.a
  847. entries:
  848. obj:symbol (noflash)
  849. # Comments should not matter
  850. obj (noflash)
  851. # Nor should whitespace
  852. obj : symbol_2 ( noflash )
  853. obj_2 ( noflash )
  854. * (noflash)
  855. """)
  856. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  857. self.assertEqual('lib.a', fragment_file.fragments[0].archive)
  858. self.assertEqual('lib_a', fragment_file.fragments[0].name)
  859. expected = {('obj', 'symbol', 'noflash'),
  860. ('obj', None, 'noflash'),
  861. ('obj', 'symbol_2', 'noflash'),
  862. ('obj_2', None, 'noflash'),
  863. ('*', None, 'noflash')
  864. }
  865. self.assertEqual(expected, fragment_file.fragments[0].entries)
  866. def test_explicit_blank_default_w_others(self):
  867. test_fragment = self.create_fragment_file(u"""
  868. [mapping]
  869. archive: lib.a
  870. entries:
  871. : A = n
  872. obj_a (noflash)
  873. : default
  874. """)
  875. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  876. expected = {('*', None, 'default')}
  877. self.assertEqual(expected, fragment_file.fragments[0].entries)
  878. def test_implicit_blank_default_w_others(self):
  879. test_fragment = self.create_fragment_file(u"""
  880. [mapping]
  881. archive: lib.a
  882. entries:
  883. : A = n
  884. obj_a (noflash)
  885. """)
  886. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  887. expected = {('*', None, 'default')}
  888. self.assertEqual(expected, fragment_file.fragments[0].entries)
  889. def test_explicit_blank_default(self):
  890. test_fragment = self.create_fragment_file(u"""
  891. [mapping]
  892. archive: lib.a
  893. entries:
  894. : default
  895. """)
  896. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  897. expected = {('*', None, 'default')}
  898. self.assertEqual(expected, fragment_file.fragments[0].entries)
  899. def test_implicit_blank_default(self):
  900. test_fragment = self.create_fragment_file(u"""
  901. [mapping]
  902. archive: lib.a
  903. entries:
  904. : default
  905. """)
  906. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  907. expected = {('*', None, 'default')}
  908. self.assertEqual(expected, fragment_file.fragments[0].entries)
  909. def test_multiple_entries(self):
  910. test_fragment = self.create_fragment_file(u"""
  911. [mapping]
  912. archive: lib.a
  913. entries:
  914. : A = n
  915. obj_a1 (noflash)
  916. obj_a2 (noflash)
  917. : B = n
  918. obj_b1 (noflash)
  919. obj_b2 (noflash)
  920. obj_b3 (noflash)
  921. : C = n
  922. obj_c1 (noflash)
  923. """)
  924. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  925. expected = {('obj_b1', None, 'noflash'),
  926. ('obj_b2', None, 'noflash'),
  927. ('obj_b3', None, 'noflash')}
  928. self.assertEqual(expected, fragment_file.fragments[0].entries)
  929. def test_blank_entries(self):
  930. test_fragment = self.create_fragment_file(u"""
  931. [mapping]
  932. archive: lib.a
  933. entries:
  934. : A = n
  935. obj_a (noflash)
  936. : B = n
  937. : C = n
  938. obj_c (noflash)
  939. : default
  940. obj (noflash)
  941. """)
  942. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  943. expected = {('*', None, 'default')}
  944. self.assertEqual(expected, fragment_file.fragments[0].entries)
  945. def test_blank_first_condition(self):
  946. test_fragment = self.create_fragment_file(u"""
  947. [mapping]
  948. archive: lib.a
  949. entries:
  950. obj_a (noflash)
  951. : CONFIG_B = y
  952. obj_b (noflash)
  953. """)
  954. with self.assertRaises(ParseException):
  955. FragmentFile(test_fragment, self.sdkconfig)
  956. def test_nonlast_default_1(self):
  957. test_fragment = self.create_fragment_file(u"""
  958. [mapping]
  959. archive: lib.a
  960. entries:
  961. : default
  962. obj_a (noflash)
  963. : CONFIG_A = y
  964. obj_A (noflash)
  965. """)
  966. with self.assertRaises(ParseException):
  967. FragmentFile(test_fragment, self.sdkconfig)
  968. def test_nonlast_default_2(self):
  969. test_fragment = self.create_fragment_file(u"""
  970. [mapping]
  971. archive: lib.a
  972. entries:
  973. : A = y
  974. obj_A (noflash)
  975. : default
  976. obj_a (noflash)
  977. : B = y
  978. obj_B (noflash
  979. """)
  980. with self.assertRaises(ParseException):
  981. FragmentFile(test_fragment, self.sdkconfig)
  982. def test_nonlast_default_3(self):
  983. test_fragment = self.create_fragment_file(u"""
  984. [mapping]
  985. archive: lib.a
  986. entries:
  987. : A = y
  988. obj_A (noflash)
  989. :
  990. obj_a (noflash)
  991. : B = y
  992. obj_B (noflash
  993. """)
  994. with self.assertRaises(ParseException):
  995. FragmentFile(test_fragment, self.sdkconfig)
  996. def test_duplicate_default_1(self):
  997. test_fragment = self.create_fragment_file(u"""
  998. [mapping]
  999. archive: lib.a
  1000. entries:
  1001. : CONFIG_A = y
  1002. obj_A (noflash)
  1003. : default
  1004. obj_a (noflash)
  1005. : CONFIG_B = y
  1006. obj_B (noflash)
  1007. : default
  1008. obj_a (noflash)
  1009. """)
  1010. with self.assertRaises(ParseException):
  1011. FragmentFile(test_fragment, self.sdkconfig)
  1012. def test_duplicate_default_2(self):
  1013. test_fragment = self.create_fragment_file(u"""
  1014. [mapping]
  1015. archive: lib.a
  1016. entries:
  1017. : CONFIG_A = y
  1018. obj_A (noflash)
  1019. : CONFIG_B = y
  1020. obj_a (noflash)
  1021. : default
  1022. obj_B (noflash)
  1023. :
  1024. obj_a (noflash)
  1025. """)
  1026. with self.assertRaises(ParseException):
  1027. FragmentFile(test_fragment, self.sdkconfig)
  1028. def test_mixed_deprecated_mapping(self):
  1029. test_fragment = self.create_fragment_file(u"""
  1030. [mapping]
  1031. archive: lib.a
  1032. entries:
  1033. : A = n
  1034. obj_A (noflash)
  1035. : default
  1036. obj_B (noflash)
  1037. [mapping:test]
  1038. archive: lib.a
  1039. entries:
  1040. if A = n:
  1041. obj_A (noflash)
  1042. else:
  1043. obj_B (noflash)
  1044. """)
  1045. fragment_file = FragmentFile(test_fragment, self.sdkconfig)
  1046. self.assertEqual(2, len(fragment_file.fragments))
  1047. self.assertEqual(fragment_file.fragments[0].entries,
  1048. fragment_file.fragments[1].entries)
  1049. if __name__ == '__main__':
  1050. unittest.main()