1
1

test_version_converter.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. import io
  2. import os
  3. import shutil
  4. import unittest
  5. from contextlib import contextmanager
  6. from glob import glob
  7. from lxml import etree as ET
  8. from odml.terminology import REPOSITORY_BASE
  9. from odml.tools.converters import VersionConverter
  10. from .util import ODML_CACHE_DIR as CACHE_DIR, create_test_dir, TEST_RESOURCES_DIR as RES_DIR
  11. try:
  12. unicode = unicode
  13. except NameError:
  14. unicode = str
  15. class TestVersionConverter(unittest.TestCase):
  16. def setUp(self):
  17. self.base_path = RES_DIR
  18. self.VC = VersionConverter
  19. self.doc = """
  20. <odML version="1">
  21. <date>2008-07-07</date>
  22. <section>
  23. <property>
  24. <value>0<unit>deg</unit><type>int</type><uncertainty/></value>
  25. <value>45<unit>deg</unit><type>int</type></value>
  26. <name>Orientations</name>
  27. </property>
  28. <type>some sec type</type>
  29. <name>sec_name</name>
  30. </section>
  31. <section>
  32. <type>some sec type</type>
  33. <name>sec_name</name>
  34. <property>
  35. <name>prop_name</name>
  36. </property>
  37. <property>
  38. <name>prop_name</name>
  39. </property>
  40. </section>
  41. <author>Author</author>
  42. </odML>
  43. """
  44. self.tmp_dir = None
  45. def tearDown(self):
  46. """
  47. Cleanup any created temporary files.
  48. """
  49. if self.tmp_dir and os.path.exists(self.tmp_dir):
  50. shutil.rmtree(self.tmp_dir)
  51. find_us = os.path.join(CACHE_DIR, "*local_repository_file_v1*")
  52. for file_path in glob(find_us):
  53. os.remove(file_path)
  54. @contextmanager
  55. def assertNotRaises(self, exc_type):
  56. try:
  57. yield None
  58. except exc_type:
  59. raise self.failureException('{} raised'.format(exc_type.__name__))
  60. def test_replace_same_name_entites(self):
  61. root = ET.fromstring(self.doc)
  62. sec_names = []
  63. sec_elems = []
  64. for sec in root.iter("section"):
  65. sec_names.append(sec.find("name").text)
  66. sec_elems.append(sec)
  67. self.assertEqual(sec_names[0], "sec_name")
  68. self.assertEqual(sec_names[0], sec_names[1])
  69. props_names = []
  70. for prop in sec_elems[1].iter("property"):
  71. props_names.append(prop.find("name").text)
  72. self.assertEqual(props_names[0], "prop_name")
  73. self.assertEqual(props_names[0], props_names[1])
  74. tree = ET.ElementTree(root)
  75. tree = self.VC._replace_same_name_entities(tree)
  76. root = tree.getroot()
  77. sec_names = []
  78. sec_elems = []
  79. for sec in root.iter("section"):
  80. sec_names.append(sec.find("name").text)
  81. sec_elems.append(sec)
  82. self.assertEqual(sec_names[0], "sec_name")
  83. self.assertEqual(sec_names[1], "sec_name-2")
  84. props_names = []
  85. for prop in sec_elems[1].iter("property"):
  86. props_names.append(prop.find("name").text)
  87. self.assertEqual(props_names[0], "prop_name")
  88. self.assertEqual(props_names[1], "prop_name-2")
  89. def test_convert_odml_file(self):
  90. with self.assertRaises(Exception) as exc:
  91. self.VC("/not_valid_path").convert()
  92. self.assertIn("Cannot parse provided file", str(exc.exception))
  93. root = ET.fromstring(self.doc)
  94. prop = root.find("section").find("property")
  95. val_elems = []
  96. for val in prop.iter("value"):
  97. val_elems.append(val)
  98. self.assertEqual(val_elems[0].find("unit").text, "deg")
  99. self.assertEqual(val_elems[0].find("type").text, "int")
  100. self.assertEqual(val_elems[0].find("uncertainty").text, None)
  101. self.assertEqual(prop.find("unit"), None)
  102. self.assertEqual(prop.find("type"), None)
  103. file = io.StringIO(unicode(self.doc))
  104. converter = self.VC(file)
  105. tree = converter._convert(converter._parse_xml())
  106. root = tree.getroot()
  107. prop = root.find("section").find("property")
  108. val_elems = []
  109. for val in prop.iter("value"):
  110. val_elems.append(val)
  111. self.assertEqual(len(val_elems), 1)
  112. self.assertEqual(val_elems[0].find("unit"), None)
  113. self.assertEqual(val_elems[0].find("type"), None)
  114. self.assertEqual(val_elems[0].find("uncertainty"), None)
  115. self.assertEqual(val_elems[0].text, "[0,45]")
  116. self.assertEqual(prop.find("unit").text, "deg")
  117. self.assertEqual(len(prop.findall("unit")), 1)
  118. self.assertEqual(prop.find("type").text, "int")
  119. self.assertEqual(len(prop.findall("type")), 1)
  120. self.assertEqual(prop.find("uncertainty").text, None)
  121. def test_convert_odml_file_document(self):
  122. """Test proper conversion of the odml.Document entity from
  123. odml model version 1 to version 1.1.
  124. The test checks for the proper conversion of all valid
  125. Document tags and exclusion of non-Document tags.
  126. """
  127. repo_file = os.path.join(RES_DIR, "local_repository_file_v1.1.xml")
  128. local_url = "file://%s" % repo_file
  129. repo_old_file = os.path.join(RES_DIR, "local_repository_file_v1.0.xml")
  130. local_old_url = "file://%s" % repo_old_file
  131. doc = """
  132. <odML version="1">
  133. <!-- Valid Document tags test -->
  134. <author>Document author</author>
  135. <version>1</version>
  136. <date>2017-10-18</date>
  137. <repository>%s</repository>
  138. <section><name>Document section</name></section>
  139. <!-- Unsupported Document tags test -->
  140. <invalid>Invalid Document tag</invalid>
  141. <property>Invalid Document property</property>
  142. <value>Invalid Document value</value>
  143. </odML>
  144. """ % local_url
  145. invalid_repo_doc = """
  146. <odML version="1">
  147. <repository>Unresolvable</repository>
  148. <section><name>Document section</name></section>
  149. </odML>
  150. """
  151. old_repo_doc = """
  152. <odML version="1">
  153. <repository>%s</repository>
  154. <section><name>Document section</name></section>
  155. </odML>
  156. """ % local_old_url
  157. file = io.StringIO(unicode(doc))
  158. converter = self.VC(file)
  159. conv_doc = converter._convert(converter._parse_xml())
  160. root = conv_doc.getroot()
  161. # Test export of Document tags, repository is excluded
  162. self.assertEqual(len(root.findall("author")), 1)
  163. self.assertEqual(len(root.findall("date")), 1)
  164. self.assertEqual(len(root.findall("repository")), 1)
  165. self.assertEqual(len(root.findall("section")), 1)
  166. # Test absence of non-Document tags
  167. self.assertEqual(len(root.findall("invalid")), 0)
  168. self.assertEqual(len(root.findall("property")), 0)
  169. self.assertEqual(len(root.findall("value")), 0)
  170. # Test warning message on non-importable repository
  171. file = io.StringIO(unicode(invalid_repo_doc))
  172. converter = self.VC(file)
  173. conv_doc = converter._convert(converter._parse_xml())
  174. root = conv_doc.getroot()
  175. self.assertEqual(root.findall("repository")[0].text, "Unresolvable")
  176. self.assertIn("not odML v1.1 compatible", converter.conversion_log[0])
  177. # Test warning message on old repository
  178. file = io.StringIO(unicode(old_repo_doc))
  179. converter = self.VC(file)
  180. conv_doc = converter._convert(converter._parse_xml())
  181. root = conv_doc.getroot()
  182. self.assertEqual(root.findall("repository")[0].text, local_old_url)
  183. self.assertIn("not odML v1.1 compatible", converter.conversion_log[0])
  184. def test_convert_odml_file_section(self):
  185. """Test proper conversion of the odml.Section entity from
  186. odml model version 1 to version 1.1.
  187. The test checks for the proper conversion of all valid
  188. Section tags and exclusion of non-Section tags.
  189. """
  190. repo_file = os.path.join(RES_DIR, "local_repository_file_v1.1.xml")
  191. local_url = "file://%s" % repo_file
  192. repo_old_file = os.path.join(RES_DIR, "local_repository_file_v1.0.xml")
  193. local_old_url = "file://%s" % repo_old_file
  194. doc = """
  195. <odML version="1">
  196. <!-- Valid Section tags test -->
  197. <section>
  198. <name>Section name</name>
  199. <type>Section type</type>
  200. <definition>Section definition</definition>
  201. <reference>Section reference</reference>
  202. <link>Section link</link>
  203. <repository>%s</repository>
  204. <include>Section include</include>
  205. <property><name>Section Property 1</name></property>
  206. <property><name>Section Property 2</name></property>
  207. <section>
  208. <name>SubSection name</name>
  209. <type>SubSection type</type>
  210. <definition>SubSection definition</definition>
  211. <reference>SubSection reference</reference>
  212. <link>SubSection link</link>
  213. <repository>%s</repository>
  214. <include>SubSection include</include>
  215. <property><name>SubSection Property</name></property>
  216. </section>
  217. </section>
  218. <section>
  219. <name>Unsupported Section tags test</name>
  220. <invalid>Invalid tag</invalid>
  221. <value>Invalid Value tag</value>
  222. <mapping>Unsupported mapping tag</mapping>
  223. </section>
  224. </odML>
  225. """ % (local_url, local_url)
  226. file = io.StringIO(unicode(doc))
  227. converter = self.VC(file)
  228. conv_doc = converter._convert(converter._parse_xml())
  229. root = conv_doc.getroot()
  230. root_id = root.findall("id")
  231. self.assertEqual(len(root_id), 1)
  232. sec = root.findall("section")
  233. self.assertEqual(len(sec), 2)
  234. # Test valid section tags.
  235. self.assertEqual(len(sec[0]), 11)
  236. self.assertEqual(sec[0].find("name").text, "Section name")
  237. self.assertEqual(sec[0].find("type").text, "Section type")
  238. self.assertEqual(sec[0].find("definition").text, "Section definition")
  239. self.assertEqual(sec[0].find("reference").text, "Section reference")
  240. self.assertEqual(sec[0].find("link").text, "Section link")
  241. self.assertEqual(sec[0].find("repository").text, local_url)
  242. self.assertEqual(sec[0].find("include").text, "Section include")
  243. self.assertEqual(len(sec[0].findall("property")), 2)
  244. self.assertEqual(len(sec[0].findall("section")), 1)
  245. self.assertEqual(len(sec[0].findall("id")), 1)
  246. # Test valid subsection tags.
  247. subsec = sec[0].find("section")
  248. self.assertEqual(len(subsec), 9)
  249. self.assertEqual(subsec.find("name").text, "SubSection name")
  250. self.assertEqual(subsec.find("type").text, "SubSection type")
  251. self.assertEqual(subsec.find("definition").text, "SubSection definition")
  252. self.assertEqual(subsec.find("reference").text, "SubSection reference")
  253. self.assertEqual(subsec.find("link").text, "SubSection link")
  254. self.assertEqual(subsec.find("repository").text, local_url)
  255. self.assertEqual(subsec.find("include").text, "SubSection include")
  256. self.assertEqual(len(subsec.findall("property")), 1)
  257. self.assertEqual(len(subsec.findall("id")), 1)
  258. # Test absence of non-Section tags
  259. self.assertEqual(len(sec[1]), 2)
  260. self.assertEqual(len(sec[1].findall("name")), 1)
  261. self.assertEqual(len(sec[1].findall("id")), 1)
  262. # Test presence of v1.0 repository tag and warning log entry
  263. doc = """
  264. <odML version="1">
  265. <section>
  266. <name>Unsupported Section include test</name>
  267. <repository>%s</repository>
  268. </section>
  269. </odML>""" % local_old_url
  270. file = io.StringIO(unicode(doc))
  271. converter = self.VC(file)
  272. conv_doc = converter._convert(converter._parse_xml())
  273. sec = conv_doc.getroot().findall("section")
  274. self.assertEqual(sec[0].find("repository").text, local_old_url)
  275. self.assertIn("not odML v1.1 compatible", converter.conversion_log[0])
  276. # Test presence of v1.0 include tag and warning log entry
  277. doc = """
  278. <odML version="1">
  279. <section>
  280. <name>Unsupported Section include test</name>
  281. <include>%s</include>
  282. </section>
  283. </odML>""" % local_old_url
  284. file = io.StringIO(unicode(doc))
  285. converter = self.VC(file)
  286. conv_doc = converter._convert(converter._parse_xml())
  287. sec = conv_doc.getroot().findall("section")
  288. self.assertEqual(sec[0].find("include").text, local_old_url)
  289. self.assertIn("not odML v1.1 compatible", converter.conversion_log[0])
  290. def test_convert_odml_file_property(self):
  291. """Test proper conversion of the odml.Property entity from
  292. odml model version 1 to version 1.1.
  293. The test checks for the proper conversion of all valid
  294. Property tags and exclusion of non-Property tags.
  295. """
  296. doc = """
  297. <odML version="1">
  298. <section>
  299. <name>Valid Property tags test</name>
  300. <property>
  301. <name>Property name</name>
  302. <type>Property type</type>
  303. <definition>Property definition</definition>
  304. <dependency>Property dependency</dependency>
  305. <dependency_value>Property dependency value</dependency_value>
  306. </property>
  307. </section>
  308. <section>
  309. <name>Unsupported Property tags test</name>
  310. <property>
  311. <name>Invalid Property</name>
  312. <invalid>Invalid tag</invalid>
  313. <section><name>Invalid Section</name></section>
  314. </property>
  315. <property>Property with no name</property>
  316. </section>
  317. </odML>
  318. """
  319. file = io.StringIO(unicode(doc))
  320. converter = self.VC(file)
  321. conv_doc = converter._convert(converter._parse_xml())
  322. root = conv_doc.getroot()
  323. sec = root.findall("section")
  324. # Test valid Property tags
  325. self.assertEqual(sec[0].find("name").text, "Valid Property tags test")
  326. self.assertEqual(len(sec[0].findall("property")), 1)
  327. prop = sec[0].find("property")
  328. self.assertEqual(len(prop), 6)
  329. self.assertEqual(prop.find("name").text, "Property name")
  330. self.assertEqual(prop.find("type").text, "Property type")
  331. self.assertEqual(prop.find("definition").text, "Property definition")
  332. self.assertEqual(prop.find("dependency").text, "Property dependency")
  333. self.assertEqual(prop.find("dependencyvalue").text, "Property dependency value")
  334. self.assertEqual(len(prop.findall("id")), 1)
  335. # Test non-import of Property w/o name
  336. self.assertEqual(len(sec[1].findall("property")), 1)
  337. # Test absence of non-Property tags
  338. prop = sec[1].find("property")
  339. self.assertEqual(len(prop), 2)
  340. self.assertEqual(len(prop.findall("name")), 1)
  341. self.assertEqual(len(prop.findall("id")), 1)
  342. def test_convert_odml_file_value(self):
  343. """Test proper conversion of the odml.Value entity from
  344. odml model version 1 to version 1.1.
  345. The test checks for the proper conversion of all valid
  346. Value tags and exclusion of non-Value tags.
  347. """
  348. doc = """
  349. <odML version="1">
  350. <section>
  351. <name>Values export test</name>
  352. <property>
  353. <name>Single value export</name>
  354. <value>1</value>
  355. </property>
  356. <property>
  357. <name>Multiple values export</name>
  358. <value>1</value>
  359. <value>2</value>
  360. <value>3</value>
  361. </property>
  362. <property>
  363. <name>Empty value export</name>
  364. <value></value>
  365. <value></value>
  366. <value></value>
  367. <value></value>
  368. </property>
  369. <property>
  370. <name>Supported Value tags export</name>
  371. <value>0.1
  372. <type>float</type>
  373. <uncertainty>0.05</uncertainty>
  374. <unit>mV</unit>
  375. <filename>raw.txt</filename>
  376. <reference>Value reference</reference>
  377. </value>
  378. </property>
  379. <property>
  380. <name>Supported Multiple Value tags export</name>
  381. <value>0.1
  382. <unit>mV</unit>
  383. <filename>raw.txt</filename>
  384. <reference>Value reference</reference>
  385. </value>
  386. <value>0.2
  387. <type>float</type>
  388. <uncertainty>0.05</uncertainty>
  389. <unit>mV</unit>
  390. <filename>raw.txt</filename>
  391. <reference>Value reference</reference>
  392. </value>
  393. <value>3
  394. <type>int</type>
  395. <uncertainty>0.06</uncertainty>
  396. <unit>kV</unit>
  397. <filename>raw2.txt</filename>
  398. <reference>Value reference 2</reference>
  399. </value>
  400. </property>
  401. <property>
  402. <name>Unsupported Value tags export</name>
  403. <value>
  404. <invalid>Invalid Value tag</invalid>
  405. <encoder>Encoder</encoder>
  406. <checksum>Checksum</checksum>
  407. </value>
  408. </property>
  409. <property>
  410. <name>Unsupported binary value type replace</name>
  411. <value>0
  412. <type>binary</type>
  413. </value>
  414. </property>
  415. <property>
  416. <name>Unsupported binary value dtype replace</name>
  417. <value>1
  418. <dtype>binary</dtype>
  419. </value>
  420. </property>
  421. <property>
  422. <value>Single, string, value, with, many, commata.<type>string</type></value>
  423. <name>testSingleString</name>
  424. </property>
  425. <property>
  426. <value>A<type>string</type></value>
  427. <value>B<type>string</type></value>
  428. <value>C<type>string</type></value>
  429. <name>testStringList</name>
  430. </property>
  431. <property>
  432. <value> Single string value with wrapping whitespace <type>string</type></value>
  433. <name>testStringWhiteSpace</name>
  434. </property>
  435. <property>
  436. <value> Multiple Strings <type>string</type></value>
  437. <value> with wrapping <type>string</type></value>
  438. <value> Whitespace <type>string</type></value>
  439. <name>testStringListWhiteSpace</name>
  440. </property>
  441. <property>
  442. <value> 1 <type>int</type></value>
  443. <value> 2 <type>int</type></value>
  444. <value> 3 <type>int</type></value>
  445. <name>testIntListWhiteSpace</name>
  446. </property>
  447. <property>
  448. <name>Single value with UUID</name>
  449. <value>1</value>
  450. <id>aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa</id>
  451. </property>
  452. <property>
  453. <name>Single value with none-UUID ID</name>
  454. <id>1</id>
  455. </property>
  456. <property>
  457. <name>Single value with empty ID</name>
  458. <id></id>
  459. </property>
  460. </section>
  461. </odML>
  462. """
  463. file = io.StringIO(unicode(doc))
  464. converter = self.VC(file)
  465. conv_doc = converter._convert(converter._parse_xml())
  466. root = conv_doc.getroot()
  467. root_id = root.findall("id")
  468. self.assertEqual(len(root_id), 1)
  469. sec = root.find("section")
  470. self.assertEqual(len(sec), 18)
  471. self.assertEqual(len(sec.findall("id")), 1)
  472. # Test single value export
  473. prop = sec.findall("property")[0]
  474. self.assertEqual(len(prop), 3)
  475. self.assertEqual(prop.find("value").text, "1")
  476. self.assertEqual(len(prop.findall("id")), 1)
  477. # Test multiple value export
  478. prop = sec.findall("property")[1]
  479. self.assertEqual(len(prop), 3)
  480. self.assertEqual(prop.find("value").text, "[1,2,3]")
  481. self.assertEqual(len(prop.findall("id")), 1)
  482. # Test empty value export
  483. prop = sec.findall("property")[2]
  484. self.assertEqual(len(prop), 2)
  485. self.assertEqual(prop.find("name").text, "Empty value export")
  486. self.assertEqual(len(prop.findall("id")), 1)
  487. # Test valid Value tags
  488. prop = sec.findall("property")[3]
  489. self.assertEqual(len(prop), 8)
  490. self.assertEqual(prop.find("value").text, "0.1")
  491. self.assertEqual(prop.find("type").text, "float")
  492. self.assertEqual(prop.find("uncertainty").text, "0.05")
  493. self.assertEqual(prop.find("unit").text, "mV")
  494. self.assertEqual(prop.find("value_origin").text, "raw.txt")
  495. self.assertEqual(prop.find("reference").text, "Value reference")
  496. self.assertEqual(len(prop.findall("filename")), 0)
  497. self.assertEqual(len(prop.findall("id")), 1)
  498. # Test valid multiple Value tag export
  499. prop = sec.findall("property")[4]
  500. self.assertEqual(len(prop), 8)
  501. self.assertEqual(prop.find("value").text, "[0.1,0.2,3]")
  502. self.assertEqual(prop.find("type").text, "float")
  503. self.assertEqual(prop.find("uncertainty").text, "0.05")
  504. self.assertEqual(prop.find("unit").text, "mV")
  505. self.assertEqual(prop.find("value_origin").text, "raw.txt")
  506. self.assertEqual(prop.find("reference").text, "Value reference")
  507. self.assertEqual(len(prop.findall("id")), 1)
  508. # Test non-export of invalid Value tags
  509. prop = sec.findall("property")[5]
  510. self.assertEqual(len(prop), 2)
  511. self.assertEqual(len(prop.findall("name")), 1)
  512. self.assertEqual(len(prop.findall("id")), 1)
  513. # Test dtype 'binary' replacement
  514. prop = sec.findall("property")[6]
  515. self.assertEqual(prop.find("name").text, "Unsupported binary value type replace")
  516. self.assertEqual(prop.find("type").text, "text")
  517. self.assertEqual(len(prop.findall("id")), 1)
  518. prop = sec.findall("property")[7]
  519. self.assertEqual(prop.find("name").text, "Unsupported binary value dtype replace")
  520. self.assertEqual(prop.find("type").text, "text")
  521. self.assertEqual(len(prop.findall("id")), 1)
  522. # Test single string value with commata
  523. prop = sec.findall("property")[8]
  524. self.assertEqual(prop.find("name").text, "testSingleString")
  525. self.assertEqual(prop.find("value").text,
  526. "Single, string, value, with, many, commata.")
  527. self.assertEqual(len(prop.findall("id")), 1)
  528. # Test string list import
  529. prop = sec.findall("property")[9]
  530. self.assertEqual(prop.find("name").text, "testStringList")
  531. self.assertEqual(prop.find("value").text, "[A,B,C]")
  532. self.assertEqual(len(prop.findall("id")), 1)
  533. # Test single string values wrapping whitespace removal
  534. prop = sec.findall("property")[10]
  535. self.assertEqual(prop.find("name").text, "testStringWhiteSpace")
  536. self.assertEqual(prop.find("value").text,
  537. "Single string value with wrapping whitespace")
  538. self.assertEqual(len(prop.findall("id")), 1)
  539. # Test multiple string values with wrapping whitespace removal
  540. prop = sec.findall("property")[11]
  541. self.assertEqual(prop.find("name").text, "testStringListWhiteSpace")
  542. self.assertEqual(prop.find("value").text,
  543. "[Multiple Strings,with wrapping,Whitespace]")
  544. self.assertEqual(len(prop.findall("id")), 1)
  545. # Test multiple int values with wrapping whitespaces
  546. prop = sec.findall("property")[12]
  547. self.assertEqual(prop.find("name").text, "testIntListWhiteSpace")
  548. self.assertEqual(prop.find("type").text, "int")
  549. self.assertEqual(prop.find("value").text, "[1,2,3]")
  550. self.assertEqual(len(prop.findall("id")), 1)
  551. # Test single value export
  552. prop = sec.findall("property")[13]
  553. self.assertEqual(len(prop), 3)
  554. self.assertEqual(prop.find("value").text, "1")
  555. self.assertEqual(len(prop.findall("id")), 1)
  556. self.assertEqual(prop.find("id").text, "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
  557. # Test single value export
  558. prop = sec.findall("property")[14]
  559. self.assertEqual(len(prop), 2)
  560. self.assertEqual(len(prop.findall("id")), 1)
  561. self.assertNotEqual(prop.find("id").text, "1")
  562. # Test single value export
  563. prop = sec.findall("property")[15]
  564. self.assertEqual(len(prop), 2)
  565. self.assertEqual(len(prop.findall("id")), 1)
  566. self.assertNotEqual(prop.find("id").text, "1")
  567. def test_parse_dict_document(self):
  568. # Test appending tags; not appending empty sections
  569. doc_dict = {'Document': {'author': 'HPL', 'sections': []}}
  570. root = self.VC("")._parse_dict_document(doc_dict).getroot()
  571. self.assertEqual(len(root.getchildren()), 1)
  572. self.assertIsNotNone(root.find("author"))
  573. # Test appending multiple sections
  574. doc_dict = {'Document': {'author': 'HPL', 'sections': [{'name': 'sec_one'},
  575. {'name': 'sec_two'}]}}
  576. root = self.VC("")._parse_dict_document(doc_dict).getroot()
  577. self.assertEqual(len(root.getchildren()), 3)
  578. self.assertEqual(len(root.findall("section")), 2)
  579. def test_parse_dict_sections(self):
  580. # Test appending tags; not appending empty subsections or properties
  581. root = ET.Element("root")
  582. sec_dict = [{'name': 'sec_one', 'sections': [], 'properties': []}]
  583. self.assertEqual(len(root.getchildren()), 0)
  584. self.VC("")._parse_dict_sections(root, sec_dict)
  585. self.assertEqual(len(root.getchildren()), 1)
  586. self.assertIsNotNone(root.find("section").find("name"))
  587. # Test appending multiple sections
  588. root = ET.Element("root")
  589. sec_dict = [{'name': 'sec_one'}, {'name': 'sec_two'}, {'name': 'sec_three'}]
  590. self.assertEqual(len(root.getchildren()), 0)
  591. self.VC("")._parse_dict_sections(root, sec_dict)
  592. self.assertEqual(len(root.getchildren()), 3)
  593. # Test appending subsections
  594. root = ET.Element("root")
  595. sec_dict = [{'name': 'sec_one', 'sections': [{'name': 'sub_one'},
  596. {'name': 'sub_two'}]}]
  597. self.assertEqual(len(root.getchildren()), 0)
  598. self.VC("")._parse_dict_sections(root, sec_dict)
  599. sec = root.find("section")
  600. self.assertEqual(len(sec.getchildren()), 3)
  601. self.assertEqual(len(sec.findall("section")), 2)
  602. # Test appending properties
  603. root = ET.Element("root")
  604. sec_dict = [{'name': 'sec_one', 'properties': [{'name': 'prop_one'},
  605. {'name': 'prop_two'}]}]
  606. self.assertEqual(len(root.getchildren()), 0)
  607. self.VC("")._parse_dict_sections(root, sec_dict)
  608. sec = root.find("section")
  609. self.assertEqual(len(sec.getchildren()), 3)
  610. self.assertEqual(len(sec.findall("property")), 2)
  611. def test_parse_dict_properties(self):
  612. # Test appending tags and moving values
  613. root = ET.Element("root")
  614. prop_dict = [{'name': 'prop_one', 'values': [{'unit': 'none'},
  615. {'value': '1'}]}]
  616. self.assertEqual(len(root.getchildren()), 0)
  617. self.VC("")._parse_dict_properties(root, prop_dict)
  618. self.assertEqual(len(root.getchildren()), 1)
  619. self.assertIsNotNone(root.find("property"))
  620. prop = root.find("property")
  621. self.assertEqual(len(prop.getchildren()), 3)
  622. self.assertIsNotNone(prop.find("name"))
  623. self.assertEqual(len(prop.findall("value")), 2)
  624. # Test multiple entries
  625. root = ET.Element("root")
  626. prop_dict = [{'name': 'prop_one'},
  627. {'name': 'prop_two'}]
  628. self.assertEqual(len(root.getchildren()), 0)
  629. self.VC("")._parse_dict_properties(root, prop_dict)
  630. self.assertEqual(len(root.getchildren()), 2)
  631. def test_parse_dict_values(self):
  632. root = ET.Element("root")
  633. val_dict = [{'unit': 'arbitrary', 'value': "['one', 'two']"},
  634. {'unit': 'mV', 'value': '1'}]
  635. self.VC("")._parse_dict_values(root, val_dict)
  636. self.assertEqual(len(root.getchildren()), 2)
  637. for val in root.iterchildren():
  638. self.assertEqual(val.tag, "value")
  639. self.assertEqual(len(val.getchildren()), 1)
  640. self.assertIsNotNone(val.find("unit"))
  641. self.assertIsNotNone(val.text)
  642. def test_handle_repository(self):
  643. repo = ET.Element("repository")
  644. # Test working and valid repository link
  645. repo.text = '/'.join([REPOSITORY_BASE, 'v1.1', 'analysis', 'analysis.xml'])
  646. converter = self.VC("")
  647. self.assertIsNone(converter._handle_repository(repo))
  648. self.assertEqual(converter.conversion_log, [])
  649. # Test replaced working repository link
  650. repo.text = '/'.join([REPOSITORY_BASE, 'v1.0', 'analysis', 'analysis.xml'])
  651. self.assertIsNone(converter._handle_repository(repo))
  652. self.assertEqual(repo.text, '/'.join([REPOSITORY_BASE, 'v1.1', 'analysis', 'analysis.xml']))
  653. self.assertEqual(len(converter.conversion_log), 1)
  654. self.assertTrue("[Info]" in converter.conversion_log[0])
  655. # Test invalid repository link
  656. invalid = "I am leading nowhere"
  657. repo.text = invalid
  658. self.assertIsNone(converter._handle_repository(repo))
  659. self.assertEqual(len(converter.conversion_log), 2)
  660. self.assertTrue("[Warning]" in converter.conversion_log[1])
  661. self.assertEqual(repo.text, invalid)
  662. def test_handle_include(self):
  663. repo = ET.Element("include")
  664. # Test working and valid repository link
  665. repo.text = '/'.join([REPOSITORY_BASE, 'v1.1', 'analysis', 'analysis.xml'])
  666. converter = self.VC("")
  667. self.assertIsNone(converter._handle_include(repo))
  668. self.assertEqual(converter.conversion_log, [])
  669. # Test replaced working repository link
  670. repo.text = '/'.join([REPOSITORY_BASE, 'v1.0', 'analysis', 'analysis.xml'])
  671. self.assertIsNone(converter._handle_include(repo))
  672. self.assertEqual(repo.text, '/'.join([REPOSITORY_BASE, 'v1.1', 'analysis', 'analysis.xml']))
  673. self.assertEqual(len(converter.conversion_log), 1)
  674. self.assertTrue("[Info]" in converter.conversion_log[0])
  675. # Test invalid repository link
  676. invalid = "I am leading nowhere"
  677. repo.text = invalid
  678. self.assertIsNone(converter._handle_include(repo))
  679. self.assertEqual(len(converter.conversion_log), 2)
  680. self.assertTrue("[Warning]" in converter.conversion_log[1])
  681. self.assertEqual(repo.text, invalid)
  682. def test_convert_xml_file(self):
  683. # Test minimal reading from an xml file.
  684. basefile = os.path.join(self.base_path, "version_conversion.xml")
  685. root = self.VC(basefile)._parse_xml().getroot()
  686. self.assertIsNotNone(root.find("section"))
  687. sec = root.find("section")
  688. self.assertIsNotNone(sec.find("name"))
  689. self.assertIsNotNone(sec.find("type"))
  690. self.assertIsNotNone(sec.find("section").find("name"))
  691. self.assertIsNotNone(sec.find("property"))
  692. prop = sec.find("property")
  693. self.assertIsNotNone(prop.find("name"))
  694. self.assertIsNotNone(prop.find("value"))
  695. def test_convert_yaml_file(self):
  696. # Test minimal reading from a yaml file.
  697. basefile = os.path.join(self.base_path, "version_conversion.yaml")
  698. root = self.VC(basefile)._parse_yaml().getroot()
  699. self.assertIsNotNone(root.find("section"))
  700. sec = root.find("section")
  701. self.assertIsNotNone(sec.find("name"))
  702. self.assertIsNotNone(sec.find("type"))
  703. self.assertIsNotNone(sec.find("section"))
  704. self.assertIsNotNone(sec.find("property"))
  705. prop = sec.find("property")
  706. self.assertIsNotNone(prop.find("name"))
  707. self.assertIsNotNone(prop.find("value"))
  708. def test_convert_json_file(self):
  709. # Test minimal reading from a json file.
  710. basefile = os.path.join(self.base_path, "version_conversion.json")
  711. root = self.VC(basefile)._parse_json().getroot()
  712. self.assertIsNotNone(root.find("section"))
  713. sec = root.find("section")
  714. self.assertIsNotNone(sec.find("name"))
  715. self.assertIsNotNone(sec.find("type"))
  716. self.assertIsNotNone(sec.find("section"))
  717. self.assertIsNotNone(sec.find("property"))
  718. prop = sec.find("property")
  719. self.assertIsNotNone(prop.find("name"))
  720. self.assertIsNotNone(prop.find("value"))
  721. def test_write_to_file(self):
  722. infile = os.path.join(self.base_path, "version_conversion.xml")
  723. self.tmp_dir = create_test_dir(__file__)
  724. # Test write to named file
  725. outfile = os.path.join(self.tmp_dir, "test.odml")
  726. self.VC(infile).write_to_file(outfile)
  727. self.assertTrue(os.path.exists(outfile))
  728. # Test file extension append write to named file w/o file extension
  729. outfile = os.path.join(self.tmp_dir, "test")
  730. self.VC(infile).write_to_file(outfile)
  731. self.assertFalse(os.path.exists(outfile))
  732. self.assertTrue(os.path.exists("%s.xml" % outfile))