PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/tools/typemapgenerator/test/unit/mpiparsertest.rb

https://bitbucket.org/hkaiser/libgeodecomp
Ruby | 488 lines | 397 code | 74 blank | 17 comment | 0 complexity | 431c7db004e8736b706e850383e8b090 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1
  1. # Copyright (C) 2006,2007 Andreas Schaefer <gentryx@gmx.de>
  2. #
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 2 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful, but
  9. # WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. # General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software
  15. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. # 02110-1301 USA.
  17. require 'test/unit'
  18. require 'timeout'
  19. require 'mpiparser'
  20. require 'typemapgenerator'
  21. class TestMPIParser < Test::Unit::TestCase
  22. def setup
  23. @parser = MPIParser.new("./test/fixtures/doc/xml/")
  24. end
  25. def test_get_members_fom_car
  26. members = @parser.get_members("Car")
  27. expected = {
  28. "wheels" => {
  29. :type => "Wheel",
  30. :cardinality => "Car::NumWheels"
  31. },
  32. "engine" => {
  33. :type => "Engine",
  34. :cardinality => 1
  35. }
  36. }
  37. assert_equal(expected, members)
  38. end
  39. def test_get_parents
  40. assert_equal(%w{Car Luxury}, @parser.get_parents("BMW"))
  41. assert_equal([], @parser.get_parents("Car"))
  42. end
  43. def test_get_members_from_engine
  44. members = @parser.get_members("Engine")
  45. expected = {
  46. "capacity" => {
  47. :type => "double",
  48. :cardinality => 1
  49. },
  50. "gearRatios" => {
  51. :type => "double",
  52. :cardinality => 6
  53. },
  54. "fuel" => {
  55. :type => "Fuel",
  56. :cardinality => 1
  57. }
  58. }
  59. assert_equal(expected, members)
  60. end
  61. def test_resolve_class_simple
  62. @parser = MPIParser.new("./test/fixtures/doc/xml/", true)
  63. klass = "Coord<2>"
  64. members = {
  65. "x" => {
  66. :type => "int",
  67. :cardinality => 1
  68. },
  69. "y" => {
  70. :type => "int",
  71. :cardinality => 1
  72. }
  73. }
  74. parents = []
  75. classes = %w(Coord<2>)
  76. resolved_classes = { }
  77. resolved_parents = { }
  78. topological_class_sortation = []
  79. @parser.resolve_class_simple(klass, members, parents, classes,
  80. resolved_classes,
  81. resolved_parents,
  82. topological_class_sortation)
  83. resolved_classes["Coord<2>"].each do |name, spec|
  84. assert_equal("MPI::INT", spec[:type])
  85. end
  86. end
  87. def test_resolve_class_success
  88. klass = "Rim"
  89. classes = %w(Apple Melon Rim)
  90. resolved_classes = { }
  91. resolved_parents = { }
  92. topological_class_sortation = []
  93. @parser.resolve_class(klass, classes, resolved_classes, resolved_parents, topological_class_sortation)
  94. expected_typemap = Datatype.new
  95. expected_typemap.merge!(@parser.map_enums)
  96. expected_typemap["Rim"] = Datatype.cpp_to_mpi("Rim")
  97. members = @parser.get_members("Rim")
  98. members.values.each do |map|
  99. map[:type] = expected_typemap[map[:type]]
  100. end
  101. expected_resolved_classes = { }
  102. expected_resolved_classes["Rim"] = members
  103. assert_equal(["Apple", "Melon"], classes)
  104. assert_equal(expected_typemap, @parser.datatype_map)
  105. assert_equal(expected_resolved_classes, resolved_classes)
  106. assert_equal(["Rim"], topological_class_sortation)
  107. end
  108. def test_resolve_class_failure
  109. klass = "Wheel"
  110. classes = %{Apple Melon Wheel}
  111. resolved_classes = { }
  112. resolved_parents = { }
  113. topological_class_sortation = []
  114. @parser.resolve_class(klass,
  115. classes,
  116. resolved_classes,
  117. resolved_parents,
  118. topological_class_sortation)
  119. assert_equal(%{Apple Melon Wheel}, classes)
  120. assert_equal({ }, resolved_classes)
  121. assert_equal([], topological_class_sortation)
  122. end
  123. def test_template_parameters
  124. assert_equal(%w(A B), @parser.template_parameters("CoordPair"))
  125. assert_equal([], @parser.template_parameters("Car"))
  126. end
  127. def test_used_template_parameters
  128. expected = [["Coord<3 >", "Coord<2 >"],
  129. ["int", "double"],
  130. ["int", "int"]]
  131. assert_equal(expected, @parser.used_template_parameters("CoordPair"))
  132. expected = [["1"], ["2"], ["3"], ["4"]]
  133. assert_equal(expected.to_set,
  134. @parser.used_template_parameters("CoordContainer").to_set)
  135. end
  136. def test_resolve_class_with_fixed_template_parameters
  137. klass = "Coord<2 >"
  138. classes = ["Coord<2 >", "Coord<3 >"]
  139. resolved_classes = { }
  140. resolved_parents = { }
  141. topological_class_sortation = []
  142. @parser.resolve_class("Coord<2 >",
  143. classes,
  144. resolved_classes,
  145. resolved_parents,
  146. topological_class_sortation)
  147. @parser.resolve_class("Coord<3 >",
  148. classes,
  149. resolved_classes,
  150. resolved_parents,
  151. topological_class_sortation)
  152. coord2_spec = {
  153. "x"=> { :type=>"MPI::INT", :cardinality=>1},
  154. "y"=> { :type=>"MPI::INT", :cardinality=>1}
  155. }
  156. coord3_spec = {
  157. "x"=> { :type=>"MPI::INT", :cardinality=>1},
  158. "y"=> { :type=>"MPI::INT", :cardinality=>1},
  159. "z"=> { :type=>"MPI::INT", :cardinality=>1}
  160. }
  161. expected_resolved = {
  162. "Coord<2 >" => coord2_spec,
  163. "Coord<3 >" => coord3_spec
  164. }
  165. assert_equal(expected_resolved, resolved_classes)
  166. end
  167. def test_resolve_class_with_template_parameters_strict
  168. classes = ["Coord<2 >", "Coord<3 >", "CoordPair"]
  169. resolved_classes = { }
  170. resolved_parents = { }
  171. topological_class_sortation = []
  172. @parser.resolve_class("Coord<2 >",
  173. classes,
  174. resolved_classes,
  175. resolved_parents,
  176. topological_class_sortation)
  177. @parser.resolve_class("Coord<3 >",
  178. classes,
  179. resolved_classes,
  180. resolved_parents,
  181. topological_class_sortation)
  182. @parser.resolve_class("CoordPair",
  183. classes,
  184. resolved_classes,
  185. resolved_parents,
  186. topological_class_sortation)
  187. @parser.resolve_class("CoordContainer",
  188. classes,
  189. resolved_classes,
  190. resolved_parents,
  191. topological_class_sortation)
  192. expected1 = {
  193. "a" => { :type=>"MPI::COORD_3_", :cardinality=>1},
  194. "b" => { :type=>"MPI::COORD_2_", :cardinality=>1}
  195. }
  196. expected2 = {
  197. "a" => { :cardinality=>1, :type=>"MPI::INT"},
  198. "b" => { :cardinality=>1, :type=>"MPI::DOUBLE"}
  199. }
  200. assert_equal(expected1,
  201. resolved_classes["CoordPair<Coord<3 >,Coord<2 > >"])
  202. assert_equal(expected2,
  203. resolved_classes["CoordPair<int,double >"])
  204. end
  205. def test_resolve_class_with_template_parameters_sloppy
  206. @parser = MPIParser.new("./test/fixtures/doc/xml/", true)
  207. classes = ["Coord<2 >", "Coord<3 >",
  208. "CoordContainer", "CoordContainerContainer"]
  209. resolved_classes = { }
  210. resolved_parents = { }
  211. topological_class_sortation = []
  212. @parser.resolve_class("Coord<2 >",
  213. classes,
  214. resolved_classes,
  215. resolved_parents,
  216. topological_class_sortation)
  217. @parser.resolve_class("Coord<3 >",
  218. classes,
  219. resolved_classes,
  220. resolved_parents,
  221. topological_class_sortation)
  222. @parser.resolve_class("CoordContainer",
  223. classes,
  224. resolved_classes,
  225. resolved_parents,
  226. topological_class_sortation)
  227. @parser.resolve_class("CoordContainerContainer",
  228. classes,
  229. resolved_classes,
  230. resolved_parents,
  231. topological_class_sortation)
  232. expected1 = { }
  233. expected2 = {
  234. "pos" => { :type => "MPI::COORD_2_", :cardinality => 1 }
  235. }
  236. expected3 = {
  237. "pos" => { :type => "MPI::COORD_3_", :cardinality => 1 }
  238. }
  239. expected4 = { }
  240. expected5 = {
  241. "cargo1" => { :type => "MPI::COORDCONTAINER_1__PARTIAL", :cardinality => 1 },
  242. "cargo2" => { :type => "MPI::COORDCONTAINER_2_", :cardinality => 1 },
  243. "cargo3" => { :type => "MPI::COORDCONTAINER_3_", :cardinality => 1 },
  244. "cargo4" => { :type => "MPI::COORDCONTAINER_4__PARTIAL", :cardinality => 1 }
  245. }
  246. assert_equal(expected1, resolved_classes["CoordContainer<1 >"])
  247. assert_equal(expected2, resolved_classes["CoordContainer<2 >"])
  248. assert_equal(expected3, resolved_classes["CoordContainer<3 >"])
  249. assert_equal(expected4, resolved_classes["CoordContainer<4 >"])
  250. assert_equal(expected5, resolved_classes["CoordContainerContainer"])
  251. end
  252. def test_find_enums
  253. assert_equal(["Fuel"], @parser.find_enums)
  254. end
  255. def test_resolve_forest_success
  256. classes = %w{Engine Car Wheel Rim Tire}.to_set
  257. resolved_classes, resolved_parents, datatype_map, topological_class_sortation, headers =
  258. @parser.resolve_forest(classes)
  259. headers.map! { |elem| elem.gsub!(/(.+\/)(fixtures.+)/) { |match| $2 } }
  260. expected_datatype_map = Datatype.new
  261. expected_datatype_map.merge!(@parser.map_enums)
  262. classes.each do |klass|
  263. expected_datatype_map[klass] = Datatype.cpp_to_mpi(klass)
  264. end
  265. car_map = {
  266. "engine" => {
  267. :type => expected_datatype_map["Engine"],
  268. :cardinality => 1
  269. },
  270. "wheels" => {
  271. :type => expected_datatype_map["Wheel"],
  272. :cardinality => "Car::NumWheels"
  273. }
  274. }
  275. engine_map = {
  276. "capacity" => {
  277. :type => expected_datatype_map["double"],
  278. :cardinality => 1
  279. },
  280. "fuel" => {
  281. :type => expected_datatype_map["int"],
  282. :cardinality => 1
  283. },
  284. "gearRatios" => {
  285. :type => expected_datatype_map["double"],
  286. :cardinality => 6
  287. }
  288. }
  289. wheel_map = {
  290. "rim" => {
  291. :type => expected_datatype_map["Rim"],
  292. :cardinality => 1
  293. },
  294. "tire" => {
  295. :type => expected_datatype_map["Tire"],
  296. :cardinality => 1
  297. }
  298. }
  299. rim_map = {
  300. "chromePlated" => {
  301. :type => expected_datatype_map["bool"],
  302. :cardinality => 1
  303. }
  304. }
  305. tire_map = {
  306. "treadDepth" => {
  307. :type => expected_datatype_map["double"],
  308. :cardinality => 1
  309. }
  310. }
  311. expected_classes = {
  312. "Car" => car_map,
  313. "Engine" => engine_map,
  314. "Wheel" => wheel_map,
  315. "Rim" => rim_map,
  316. "Tire" => tire_map
  317. }
  318. expected_sortation = %w{Engine Tire Rim Wheel Car}
  319. expected_headers =
  320. ["fixtures/src/engine.h",
  321. "fixtures/src/tire.h",
  322. "fixtures/src/rim.h",
  323. "fixtures/src/wheel.h",
  324. "fixtures/src/car.h"]
  325. assert_equal(expected_datatype_map, datatype_map)
  326. assert_equal(expected_classes, resolved_classes)
  327. assert_equal(expected_sortation, topological_class_sortation)
  328. assert_equal(expected_headers, headers)
  329. end
  330. def test_fesolve_forest_failure
  331. classes = ["Wheel"]
  332. # catch inf. loops
  333. Timeout::timeout(10) do
  334. assert_raise(RuntimeError) { @parser.resolve_forest(classes) }
  335. end
  336. end
  337. def test_incomplete_strict_parsing_should_fail
  338. assert_raise(RuntimeError) do
  339. @parser.resolve_forest(%w(CarContainer))
  340. end
  341. end
  342. def test_find_classes_to_be_serialized
  343. expected_classes = ["Coord<2 >", "Coord<3 >"] +
  344. %w{CoordContainer CoordContainerContainer CoordPair Dummy Engine
  345. BMW Car Wheel Rim Tire CarContainer Luxury}
  346. expected_classes = expected_classes.to_set
  347. assert_equal(expected_classes, @parser.find_classes_to_be_serialized)
  348. end
  349. end
  350. class TestSloppyParsing < Test::Unit::TestCase
  351. def setup
  352. @parser = MPIParser.new("./test/fixtures/doc/xml/", true)
  353. end
  354. def test_incomplete_sloppy_parsing_should_succeed
  355. assert_nothing_raised do
  356. parser = MPIParser.new("./test/fixtures/doc/xml/", true)
  357. parser.resolve_forest(%w(Engine Car Wheel Rim Tire CarContainer))
  358. end
  359. end
  360. def test_incomplete_sloppy_parsing_should_yield_correct_members
  361. @parser.type_hierarchy_closure.delete "Engine"
  362. classes = %w(Car Wheel Rim Tire CarContainer)
  363. resolved_classes = @parser.resolve_forest(classes)[0]
  364. assert_equal(%w(wheels), resolved_classes["Car"].keys)
  365. assert_equal(%w(size spareWheel), resolved_classes["CarContainer"].keys.sort)
  366. end
  367. def test_incomplete_sloppy_parsing_should_yield_correct_typemap_names
  368. datatype_map = @parser.resolve_forest(%w(CarContainer Car Engine Wheel Rim Tire))[2]
  369. %w(Car Engine Wheel Rim Tire).each do |klass|
  370. assert_equal(Datatype.cpp_to_mpi(klass), datatype_map[klass])
  371. end
  372. assert_equal(Datatype.cpp_to_mpi("CarContainer", true),
  373. datatype_map["CarContainer"])
  374. end
  375. end
  376. class TestMapMemberTypesToMPI_Datatypes < Test::Unit::TestCase
  377. def setup
  378. @parser = MPIParser.new("./test/fixtures/doc/xml/")
  379. @members = massage_member_map({"x" => "int", "y" => "double" })
  380. @expected = massage_member_map({"x" => "MPI::INT", "y" => "MPI::DOUBLE"})
  381. end
  382. def test_builtin_types_should_succeed
  383. assert_equal(@expected,
  384. @parser.map_types_to_MPI_Datatypes(@members))
  385. end
  386. def test_userdefined_type_should_fail
  387. @members = massage_member_map({"x" => "int", "a" => "Gobble" })
  388. assert_raise(RuntimeError) do
  389. @parser.map_types_to_MPI_Datatypes(@members)
  390. end
  391. end
  392. def test_declared_userdefined_type_should_succeed
  393. @members = massage_member_map({"x" => "int", "a" => "Gobble" })
  394. @expected = massage_member_map({"x" => "MPI::INT", "a" =>
  395. "MPI_GOBBLE"})
  396. @parser.datatype_map["Gobble"] = "MPI_GOBBLE"
  397. assert_equal(@expected,
  398. @parser.map_types_to_MPI_Datatypes(@members))
  399. end
  400. def test_find_header
  401. actual = @parser.find_header("Car").gsub(/(.+\/)(fixtures.+)/) { |match| $2 }
  402. assert_equal("fixtures/src/car.h", actual)
  403. end
  404. private
  405. def massage_member_map(members)
  406. ret = { }
  407. members.each do |key, value|
  408. ret[key] = { }
  409. ret[key][:cardinality] = 1
  410. ret[key][:type] = value
  411. end
  412. return ret
  413. end
  414. end