cosmos 4.3.0-java → 4.4.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (288) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +30 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
  4. data/.github/ISSUE_TEMPLATE/help---usage---general-question.md +12 -0
  5. data/.gitignore +1 -0
  6. data/.travis.yml +5 -5
  7. data/Manifest.txt +81 -44
  8. data/Rakefile +9 -0
  9. data/appveyor.yml +2 -1
  10. data/autohotkey/config/targets/INST/cmd_tlm/inst_cmds.txt +1 -1
  11. data/autohotkey/config/targets/INST/cmd_tlm/inst_tlm.txt +5 -5
  12. data/autohotkey/config/targets/INST/lib/sim_inst.rb +3 -1
  13. data/autohotkey/config/tools/handbook_creator/assets/css/bootstrap-theme.css +397 -0
  14. data/autohotkey/config/tools/handbook_creator/assets/css/bootstrap-theme.min.css +7 -0
  15. data/autohotkey/config/tools/handbook_creator/assets/css/bootstrap.css +7118 -0
  16. data/autohotkey/config/tools/handbook_creator/assets/css/bootstrap.min.css +7 -0
  17. data/autohotkey/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  18. data/autohotkey/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.svg +229 -0
  19. data/autohotkey/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  20. data/autohotkey/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  21. data/autohotkey/config/tools/handbook_creator/assets/js/bootstrap.js +2006 -0
  22. data/autohotkey/config/tools/handbook_creator/assets/js/bootstrap.min.js +7 -0
  23. data/autohotkey/config/tools/table_manager/ConfigTables_def.txt +2 -4
  24. data/autohotkey/config/tools/table_manager/SubTables/OneDimensionalSubTable_def.txt +31 -0
  25. data/autohotkey/config/tools/table_manager/SubTables/TwoDimensionalSubTable_def.txt +28 -0
  26. data/autohotkey/config/tools/test_runner/test_runner.txt +1 -1
  27. data/autohotkey/config/tools/test_runner/test_runner2.txt +1 -1
  28. data/autohotkey/config/tools/test_runner/test_runner3.txt +1 -1
  29. data/autohotkey/config/tools/test_runner/test_runner4.txt +1 -1
  30. data/autohotkey/tools/limits_monitor.ahk +1 -1
  31. data/autohotkey/tools/packet_viewer.ahk +1 -1
  32. data/autohotkey/tools/script_runner.ahk +16 -4
  33. data/bin/cosmos +1 -1
  34. data/bin/xtce_converter +1 -1
  35. data/cosmos.gemspec +5 -7
  36. data/data/config/_interfaces.yaml +4 -0
  37. data/data/config/cmd_sequence.yaml +14 -0
  38. data/data/config/housekeeping_params.yaml +14 -0
  39. data/data/config/interface_modifiers.yaml +11 -0
  40. data/data/config/item_modifiers.yaml +2 -1
  41. data/data/config/launcher.yaml +12 -2
  42. data/data/config/param_item_modifiers.yaml +2 -2
  43. data/data/config/parameter_modifiers.yaml +20 -0
  44. data/data/config/screen.yaml +2 -0
  45. data/data/config/script_runner.yaml +9 -0
  46. data/data/config/system.yaml +47 -10
  47. data/data/config/table_manager.yaml +7 -0
  48. data/data/config/target.yaml +12 -0
  49. data/data/config/telemetry_modifiers.yaml +3 -1
  50. data/data/config/test_runner.yaml +10 -9
  51. data/data/config/widgets.yaml +174 -11
  52. data/data/crc.txt +128 -125
  53. data/demo/Gemfile +1 -1
  54. data/demo/Launcher.bat +1 -9
  55. data/demo/Launcher2.bat +1 -0
  56. data/demo/LauncherMini.bat +1 -0
  57. data/demo/config/data/crc.txt +40 -20
  58. data/demo/config/system/system.txt +1 -1
  59. data/demo/config/system/system_alt_ports.txt +1 -1
  60. data/demo/config/targets/EXAMPLE/cmd_tlm_server.txt +1 -0
  61. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +2 -1
  62. data/demo/config/targets/INST/cmd_tlm/inst_tlm.txt +7 -7
  63. data/demo/config/targets/INST/cmd_tlm_server.txt +2 -0
  64. data/demo/config/targets/INST/lib/sim_inst.rb +15 -3
  65. data/demo/config/targets/INST/screens/adcs.txt +2 -2
  66. data/demo/config/targets/INST/screens/block.txt +1 -1
  67. data/demo/config/targets/INST/screens/commanding.txt +1 -1
  68. data/demo/config/targets/INST/screens/ground.txt +27 -5
  69. data/demo/config/targets/INST/screens/ground_error.gif +0 -0
  70. data/demo/config/{data/groundoff.gif → targets/INST/screens/ground_off.gif} +0 -0
  71. data/demo/config/{data/groundon.gif → targets/INST/screens/ground_on.gif} +0 -0
  72. data/demo/config/targets/INST/screens/limits.txt +69 -31
  73. data/demo/config/targets/INST/screens/other.txt +13 -3
  74. data/demo/config/targets/INST/screens/params.txt +54 -0
  75. data/demo/config/targets/INST/screens/satellite.gif +0 -0
  76. data/demo/config/tools/data_viewer/data_viewer.txt +3 -0
  77. data/demo/config/tools/handbook_creator/assets/css/bootstrap-theme.css +397 -0
  78. data/demo/config/tools/handbook_creator/assets/css/bootstrap-theme.min.css +7 -0
  79. data/demo/config/tools/handbook_creator/assets/css/bootstrap.css +7118 -0
  80. data/demo/config/tools/handbook_creator/assets/css/bootstrap.min.css +7 -0
  81. data/demo/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  82. data/demo/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.svg +229 -0
  83. data/demo/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  84. data/demo/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  85. data/demo/config/tools/handbook_creator/assets/img/ball_logo.bmp +0 -0
  86. data/demo/config/tools/handbook_creator/assets/img/ball_logo.gif +0 -0
  87. data/demo/config/tools/handbook_creator/assets/img/ball_logo.jpg +0 -0
  88. data/demo/config/tools/handbook_creator/assets/js/bootstrap.js +2006 -0
  89. data/demo/config/tools/handbook_creator/assets/js/bootstrap.min.js +7 -0
  90. data/demo/config/tools/handbook_creator/assets/js/html5shiv.js +8 -0
  91. data/demo/config/tools/handbook_creator/assets/js/jquery-1.10.2.min.js +6 -0
  92. data/demo/config/tools/handbook_creator/assets/js/respond.min.js +6 -0
  93. data/demo/config/tools/script_runner/script_runner.txt +1 -2
  94. data/demo/config/tools/test_runner/test_runner.txt +3 -1
  95. data/demo/lib/example_background_task.rb +1 -0
  96. data/demo/procedures/cosmos_api_test.rb +1 -1
  97. data/demo/procedures/interactive.rb +22 -0
  98. data/ext/cosmos/ext/packet/packet.c +0 -77
  99. data/install/Gemfile +1 -1
  100. data/install/Launcher.bat +1 -9
  101. data/install/config/data/crc.txt +17 -1
  102. data/install/config/system/system.txt +1 -1
  103. data/install/config/tools/handbook_creator/assets/css/bootstrap-theme.css +397 -0
  104. data/install/config/tools/handbook_creator/assets/css/bootstrap-theme.min.css +7 -0
  105. data/install/config/tools/handbook_creator/assets/css/bootstrap.css +7118 -0
  106. data/install/config/tools/handbook_creator/assets/css/bootstrap.min.css +7 -0
  107. data/install/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  108. data/install/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.svg +229 -0
  109. data/install/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  110. data/install/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  111. data/install/config/tools/handbook_creator/assets/img/ball_logo.bmp +0 -0
  112. data/install/config/tools/handbook_creator/assets/img/ball_logo.gif +0 -0
  113. data/install/config/tools/handbook_creator/assets/img/ball_logo.jpg +0 -0
  114. data/install/config/tools/handbook_creator/assets/js/bootstrap.js +2006 -0
  115. data/install/config/tools/handbook_creator/assets/js/bootstrap.min.js +7 -0
  116. data/install/config/tools/handbook_creator/assets/js/html5shiv.js +8 -0
  117. data/install/config/tools/handbook_creator/assets/js/jquery-1.10.2.min.js +6 -0
  118. data/install/config/tools/handbook_creator/assets/js/respond.min.js +6 -0
  119. data/lib/cosmos/config/config_parser.rb +4 -5
  120. data/lib/cosmos/dart/lib/dart_common.rb +1 -1
  121. data/lib/cosmos/gui/dialogs/details_dialog.rb +16 -1
  122. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +1 -0
  123. data/lib/cosmos/gui/dialogs/tlm_graph_dialog.rb +4 -2
  124. data/lib/cosmos/gui/opengl/earth_model.rb +1 -1
  125. data/lib/cosmos/gui/qt.rb +3 -1
  126. data/lib/cosmos/gui/qt_tool.rb +46 -23
  127. data/lib/cosmos/gui/text/ruby_editor.rb +44 -41
  128. data/lib/cosmos/gui/utilities/screenshot.rb +1 -1
  129. data/lib/cosmos/gui/utilities/script_module_gui.rb +92 -92
  130. data/lib/cosmos/interfaces.rb +1 -0
  131. data/lib/cosmos/interfaces/interface.rb +5 -1
  132. data/lib/cosmos/interfaces/protocols/fixed_protocol.rb +40 -18
  133. data/lib/cosmos/interfaces/protocols/template_protocol.rb +6 -1
  134. data/lib/cosmos/interfaces/simulated_target_interface.rb +14 -5
  135. data/lib/cosmos/io/json_drb.rb +11 -7
  136. data/lib/cosmos/packets/commands.rb +28 -11
  137. data/lib/cosmos/packets/packet.rb +69 -32
  138. data/lib/cosmos/packets/packet_config.rb +34 -1
  139. data/lib/cosmos/packets/parsers/state_parser.rb +0 -1
  140. data/lib/cosmos/packets/parsers/xtce_converter.rb +2 -0
  141. data/lib/cosmos/packets/parsers/xtce_parser.rb +4 -3
  142. data/lib/cosmos/packets/structure.rb +4 -2
  143. data/lib/cosmos/packets/telemetry.rb +19 -3
  144. data/lib/cosmos/script/api_shared.rb +12 -9
  145. data/lib/cosmos/script/scripting.rb +16 -14
  146. data/lib/cosmos/system/system.rb +39 -20
  147. data/lib/cosmos/system/target.rb +39 -9
  148. data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +94 -35
  149. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +3 -0
  150. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +1 -1
  151. data/lib/cosmos/tools/cmd_tlm_server/background_tasks.rb +2 -0
  152. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +30 -4
  153. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +1 -0
  154. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +9 -12
  155. data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +5 -2
  156. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +2 -0
  157. data/lib/cosmos/tools/config_editor/config_editor.rb +80 -24
  158. data/lib/cosmos/tools/config_editor/config_editor_frame.rb +2 -0
  159. data/lib/cosmos/tools/data_viewer/data_viewer.rb +15 -9
  160. data/lib/cosmos/tools/data_viewer/dump_component.rb +2 -9
  161. data/lib/cosmos/tools/data_viewer/text_component.rb +77 -0
  162. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +64 -38
  163. data/lib/cosmos/tools/launcher/launcher.rb +1 -0
  164. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +31 -17
  165. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +8 -6
  166. data/lib/cosmos/tools/script_runner/script_runner.rb +87 -29
  167. data/lib/cosmos/tools/script_runner/script_runner_config.rb +14 -0
  168. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +41 -7
  169. data/lib/cosmos/tools/table_manager/table_config.rb +5 -3
  170. data/lib/cosmos/tools/table_manager/table_manager.rb +6 -3
  171. data/lib/cosmos/tools/test_runner/test_runner.rb +14 -9
  172. data/lib/cosmos/tools/test_runner/test_runner_chooser.rb +21 -9
  173. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +3 -3
  174. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +5 -8
  175. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +11 -8
  176. data/lib/cosmos/tools/tlm_grapher/tlm_grapher.rb +9 -15
  177. data/lib/cosmos/tools/tlm_viewer/screen.rb +3 -1
  178. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +19 -13
  179. data/lib/cosmos/tools/tlm_viewer/widgets.rb +2 -0
  180. data/lib/cosmos/tools/tlm_viewer/widgets/aging_widget.rb +4 -5
  181. data/lib/cosmos/tools/tlm_viewer/widgets/array_widget.rb +3 -4
  182. data/lib/cosmos/tools/tlm_viewer/widgets/block_widget.rb +4 -5
  183. data/lib/cosmos/tools/tlm_viewer/widgets/canvas_clickable.rb +16 -2
  184. data/lib/cosmos/tools/tlm_viewer/widgets/canvas_widget.rb +17 -3
  185. data/lib/cosmos/tools/tlm_viewer/widgets/canvasdot_widget.rb +1 -2
  186. data/lib/cosmos/tools/tlm_viewer/widgets/canvasellipse_widget.rb +1 -1
  187. data/lib/cosmos/tools/tlm_viewer/widgets/canvasimage_widget.rb +12 -7
  188. data/lib/cosmos/tools/tlm_viewer/widgets/canvasimagevalue_widget.rb +79 -29
  189. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslabel_widget.rb +1 -0
  190. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslabelvalue_widget.rb +2 -1
  191. data/lib/cosmos/tools/tlm_viewer/widgets/canvasline_widget.rb +2 -0
  192. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslinevalue_widget.rb +4 -0
  193. data/lib/cosmos/tools/tlm_viewer/widgets/canvasvalue_widget.rb +33 -25
  194. data/lib/cosmos/tools/tlm_viewer/widgets/checkbutton_widget.rb +5 -3
  195. data/lib/cosmos/tools/tlm_viewer/widgets/combobox_widget.rb +5 -3
  196. data/lib/cosmos/tools/tlm_viewer/widgets/formatfontvalue_widget.rb +1 -1
  197. data/lib/cosmos/tools/tlm_viewer/widgets/formatvalue_widget.rb +4 -7
  198. data/lib/cosmos/tools/tlm_viewer/widgets/horizontal_widget.rb +5 -5
  199. data/lib/cosmos/tools/tlm_viewer/widgets/horizontalbox_widget.rb +6 -7
  200. data/lib/cosmos/tools/tlm_viewer/widgets/horizontalline_widget.rb +2 -4
  201. data/lib/cosmos/tools/tlm_viewer/widgets/label_widget.rb +10 -8
  202. data/lib/cosmos/tools/tlm_viewer/widgets/labelformatvalue_widget.rb +2 -3
  203. data/lib/cosmos/tools/tlm_viewer/widgets/labelled_widget.rb +58 -0
  204. data/lib/cosmos/tools/tlm_viewer/widgets/labelprogressbar_widget.rb +3 -4
  205. data/lib/cosmos/tools/tlm_viewer/widgets/labeltrendlimitsbar_widget.rb +2 -4
  206. data/lib/cosmos/tools/tlm_viewer/widgets/labelvalue_widget.rb +2 -1
  207. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluedesc_widget.rb +3 -5
  208. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluelimitsbar_widget.rb +2 -3
  209. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluelimitscolumn_widget.rb +2 -3
  210. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluerangebar_widget.rb +2 -3
  211. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluerangecolumn_widget.rb +2 -3
  212. data/lib/cosmos/tools/tlm_viewer/widgets/layout_widget.rb +3 -5
  213. data/lib/cosmos/tools/tlm_viewer/widgets/led_widget.rb +108 -0
  214. data/lib/cosmos/tools/tlm_viewer/widgets/limits_widget.rb +60 -10
  215. data/lib/cosmos/tools/tlm_viewer/widgets/limitsbar_widget.rb +22 -8
  216. data/lib/cosmos/tools/tlm_viewer/widgets/limitscolor_widget.rb +19 -13
  217. data/lib/cosmos/tools/tlm_viewer/widgets/limitscolumn_widget.rb +22 -8
  218. data/lib/cosmos/tools/tlm_viewer/widgets/linegraph_widget.rb +2 -3
  219. data/lib/cosmos/tools/tlm_viewer/widgets/matrixbycolumns_widget.rb +4 -3
  220. data/lib/cosmos/tools/tlm_viewer/widgets/multi_widget.rb +1 -3
  221. data/lib/cosmos/tools/tlm_viewer/widgets/progressbar_widget.rb +10 -5
  222. data/lib/cosmos/tools/tlm_viewer/widgets/radiobutton_widget.rb +7 -4
  223. data/lib/cosmos/tools/tlm_viewer/widgets/rangebar_widget.rb +4 -6
  224. data/lib/cosmos/tools/tlm_viewer/widgets/rangecolumn_widget.rb +3 -5
  225. data/lib/cosmos/tools/tlm_viewer/widgets/screenshotbutton_widget.rb +4 -3
  226. data/lib/cosmos/tools/tlm_viewer/widgets/scrollwindow_widget.rb +2 -3
  227. data/lib/cosmos/tools/tlm_viewer/widgets/sectionheader_widget.rb +2 -3
  228. data/lib/cosmos/tools/tlm_viewer/widgets/spacer_widget.rb +4 -6
  229. data/lib/cosmos/tools/tlm_viewer/widgets/tabbook_widget.rb +2 -3
  230. data/lib/cosmos/tools/tlm_viewer/widgets/tabitem_widget.rb +2 -3
  231. data/lib/cosmos/tools/tlm_viewer/widgets/textbox_widget.rb +13 -4
  232. data/lib/cosmos/tools/tlm_viewer/widgets/textfield_widget.rb +3 -4
  233. data/lib/cosmos/tools/tlm_viewer/widgets/timegraph_widget.rb +2 -7
  234. data/lib/cosmos/tools/tlm_viewer/widgets/title_widget.rb +6 -12
  235. data/lib/cosmos/tools/tlm_viewer/widgets/trendbar_widget.rb +5 -10
  236. data/lib/cosmos/tools/tlm_viewer/widgets/trendlimitsbar_widget.rb +5 -3
  237. data/lib/cosmos/tools/tlm_viewer/widgets/value_widget.rb +4 -4
  238. data/lib/cosmos/tools/tlm_viewer/widgets/valuelimitsbar_widget.rb +2 -3
  239. data/lib/cosmos/tools/tlm_viewer/widgets/valuelimitscolumn_widget.rb +2 -3
  240. data/lib/cosmos/tools/tlm_viewer/widgets/valuerangebar_widget.rb +3 -4
  241. data/lib/cosmos/tools/tlm_viewer/widgets/valuerangecolumn_widget.rb +2 -3
  242. data/lib/cosmos/tools/tlm_viewer/widgets/vertical_widget.rb +8 -7
  243. data/lib/cosmos/tools/tlm_viewer/widgets/verticalbox_widget.rb +9 -7
  244. data/lib/cosmos/tools/tlm_viewer/widgets/widget.rb +54 -46
  245. data/lib/cosmos/top_level.rb +23 -12
  246. data/lib/cosmos/version.rb +4 -4
  247. data/spec/gui/utilities/script_module_gui_spec.rb +44 -63
  248. data/spec/install/config/targets/INST/cmd_tlm/inst_cmds.txt +1 -1
  249. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm.txt +5 -5
  250. data/spec/install/yaml_docs_spec.rb +112 -0
  251. data/spec/interfaces/protocols/fixed_protocol_spec.rb +20 -9
  252. data/spec/interfaces/protocols/template_protocol_spec.rb +78 -25
  253. data/spec/packets/commands_spec.rb +22 -0
  254. data/spec/packets/packet_config_spec.rb +24 -0
  255. data/spec/packets/packet_item_spec.rb +2 -2
  256. data/spec/packets/packet_spec.rb +39 -6
  257. data/spec/packets/parsers/state_parser_spec.rb +33 -11
  258. data/spec/packets/structure_spec.rb +41 -0
  259. data/spec/packets/telemetry_spec.rb +23 -0
  260. data/spec/streams/tcpip_socket_stream_spec.rb +32 -27
  261. data/spec/system/system_spec.rb +77 -2
  262. data/spec/system/target_spec.rb +62 -1
  263. data/spec/tools/cmd_tlm_server/api_spec.rb +1 -1
  264. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +15 -7
  265. data/spec/top_level/top_level_spec.rb +29 -5
  266. data/tasks/gemfile_stats.rake +28 -14
  267. data/test/performance/config/system/system.txt +0 -0
  268. data/test/performance/config/targets/PACKET/cmd_tlm/packet_tlm.txt +5 -5
  269. data/test/performance/config/tools/handbook_creator/assets/css/bootstrap-theme.css +397 -0
  270. data/test/performance/config/tools/handbook_creator/assets/css/bootstrap-theme.min.css +7 -0
  271. data/test/performance/config/tools/handbook_creator/assets/css/bootstrap.css +7118 -0
  272. data/test/performance/config/tools/handbook_creator/assets/css/bootstrap.min.css +7 -0
  273. data/test/performance/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  274. data/test/performance/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.svg +229 -0
  275. data/test/performance/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  276. data/test/performance/config/tools/handbook_creator/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  277. data/test/performance/config/tools/handbook_creator/assets/img/ball_logo.bmp +0 -0
  278. data/test/performance/config/tools/handbook_creator/assets/img/ball_logo.gif +0 -0
  279. data/test/performance/config/tools/handbook_creator/assets/img/ball_logo.jpg +0 -0
  280. data/test/performance/config/tools/handbook_creator/assets/js/bootstrap.js +2006 -0
  281. data/test/performance/config/tools/handbook_creator/assets/js/bootstrap.min.js +7 -0
  282. data/test/performance/config/tools/handbook_creator/assets/js/html5shiv.js +8 -0
  283. data/test/performance/config/tools/handbook_creator/assets/js/jquery-1.10.2.min.js +6 -0
  284. data/test/performance/config/tools/handbook_creator/assets/js/respond.min.js +6 -0
  285. data/test/performance/config/tools/test_runner/test_runner.txt +1 -1
  286. data/test/performance/procedures/cosmos_api_test.rb +1 -1
  287. data/test/performance/tools/identify_performance.rb +82 -0
  288. metadata +92 -55
@@ -181,6 +181,7 @@ module Cosmos
181
181
  unless option_parser and options
182
182
  option_parser, options = create_default_options()
183
183
  options.title = 'Launcher'
184
+ options.config_file = true # config_file is required
184
185
  end
185
186
  option_parser.separator "Launcher Specific Options:"
186
187
  option_parser.on("-m", "--mini", "Create mini launcher") do |arg|
@@ -84,11 +84,13 @@ module Cosmos
84
84
  # @param update_item_callback [Proc] Method to update an item in the GUI
85
85
  # @param clear_items_callback [Proc] Method to clear all items in the GUI
86
86
  # @param remove_item_callback [Proc] Method to remove an item from the GUI
87
- def initialize(new_item_callback, update_item_callback, clear_items_callback, remove_item_callback)
87
+ # @param clear_log_callback [Proc] Method to clear the log tab in the GUI
88
+ def initialize(new_item_callback, update_item_callback, clear_items_callback, remove_item_callback, clear_log_callback)
88
89
  @new_item_callback = new_item_callback
89
90
  @update_item_callback = update_item_callback
90
91
  @clear_items_callback = clear_items_callback
91
92
  @remove_item_callback = remove_item_callback
93
+ @clear_log_callback = clear_log_callback
92
94
  @ignored = []
93
95
  @ignored_stale = []
94
96
  @items = {}
@@ -98,15 +100,21 @@ module Cosmos
98
100
  @limits_set = :DEFAULT
99
101
  @colorblind = false
100
102
  @monitor_operational = true
103
+ @toggle_mode = false
101
104
  request_reset()
102
105
  end
103
106
 
104
107
  # Request that the limits items be refreshed from the server
105
- def request_reset(toggle_mode = false)
106
- @toggle_mode = toggle_mode
108
+ def request_reset
107
109
  @initialized = false
108
110
  end
109
111
 
112
+ # Switch between realtime and replay modes
113
+ def toggle_mode
114
+ @toggle_mode = true
115
+ request_reset()
116
+ end
117
+
110
118
  # Remove an item and optionally ignore it which means don't display it
111
119
  # again if it goes out of limits and don't have it count towards the
112
120
  # overall limit state. Still display its limits transitions in the log.
@@ -350,12 +358,16 @@ module Cosmos
350
358
  @items = {}
351
359
  @out_of_limits = []
352
360
  @stale = []
353
- @limits_set = get_limits_set()
354
361
  unsubscribe_limits_events(@queue_id) if @queue_id
355
- set_replay_mode(!get_replay_mode()) if @toggle_mode
356
- @toggle_mode = false
357
- @queue_id = subscribe_limits_events(100000)
362
+ if @toggle_mode
363
+ set_replay_mode(!get_replay_mode())
364
+ @clear_log_callback.call
365
+ @toggle_mode = false
366
+ end
358
367
  @clear_items_callback.call
368
+
369
+ @limits_set = get_limits_set()
370
+ @queue_id = subscribe_limits_events(100000)
359
371
  get_out_of_limits().each do |target, packet, item, state|
360
372
  limits_change(target, packet, item, state)
361
373
  end
@@ -534,8 +546,8 @@ module Cosmos
534
546
  initialize_central_widget()
535
547
  complete_initialize()
536
548
 
537
- @limits_items = LimitsItems.new(
538
- method(:new_gui_item), method(:update_gui_item), method(:clear_gui_items), method(:remove_gui_item))
549
+ @limits_items = LimitsItems.new(method(:new_gui_item), method(:update_gui_item), \
550
+ method(:clear_gui_items), method(:remove_gui_item), method(:clear_log))
539
551
  if options.config_file
540
552
  begin
541
553
  result = @limits_items.open_config(options.config_file)
@@ -547,6 +559,7 @@ module Cosmos
547
559
 
548
560
  limits_thread()
549
561
  value_thread()
562
+ toggle_replay_mode() if options.replay
550
563
  end
551
564
 
552
565
  # Initialize all the actions in the application Menu
@@ -610,7 +623,6 @@ module Cosmos
610
623
  # Layout the main GUI tab widget with a view of all the out of limits items
611
624
  # in one tab and a log tab showing all limits events.
612
625
  def initialize_central_widget
613
-
614
626
  widget = Qt::Widget.new
615
627
  layout = Qt::VBoxLayout.new(widget)
616
628
  setCentralWidget(widget)
@@ -707,7 +719,7 @@ module Cosmos
707
719
  end
708
720
 
709
721
  def toggle_replay_mode
710
- @limits_items.request_reset(true)
722
+ @limits_items.toggle_mode()
711
723
  end
712
724
 
713
725
  # @return [String] Fully qualified path to the configuration file
@@ -815,9 +827,7 @@ module Cosmos
815
827
  @limits_thread = Thread.new do
816
828
  while true
817
829
  break if @cancel_thread
818
- Qt.execute_in_main_thread(true) do
819
- result, color = @limits_items.process_events()
820
- end
830
+ result, color = @limits_items.process_events()
821
831
  if result
822
832
  update_log(result, color)
823
833
  else
@@ -877,6 +887,10 @@ module Cosmos
877
887
  end
878
888
  end
879
889
 
890
+ def clear_log
891
+ Qt.execute_in_main_thread(true) { @log_output.clear() }
892
+ end
893
+
880
894
  # Remove a limits item from the list and optionally ignore
881
895
  #
882
896
  # @param widget [Qt::Widget] Widget to remove
@@ -999,12 +1013,12 @@ module Cosmos
999
1013
  options.remember_geometry = false
1000
1014
  options.title = "Limits Monitor"
1001
1015
  options.auto_size = false
1002
- options.config_file = nil
1003
1016
  options.production = false
1004
1017
  options.no_prompt = false
1005
1018
  option_parser.separator "Limits Monitor Specific Options:"
1006
- option_parser.on("-c", "--config FILE", "Use the specified configuration file") do |arg|
1007
- options.config_file = arg
1019
+ options.replay = false
1020
+ option_parser.on("--replay", "Start Limits Monitor in Replay mode") do
1021
+ options.replay = true
1008
1022
  end
1009
1023
  end
1010
1024
 
@@ -74,6 +74,7 @@ module Cosmos
74
74
  update_tlm_items(item_name)
75
75
  end
76
76
  end
77
+ toggle_replay_mode() if options.replay
77
78
  end
78
79
 
79
80
  # Unconfigure CosmosConfig to interact with splash screen
@@ -587,7 +588,7 @@ module Cosmos
587
588
  graph_action.statusTip = "Create a new COSMOS graph of #{target_name} #{packet_name} #{item_name}"
588
589
  graph_action.connect(SIGNAL('triggered()')) do
589
590
  @table.clearSelection
590
- TlmGraphDialog.new(self, target_name, packet_name, item_name)
591
+ TlmGraphDialog.new(self, target_name, packet_name, item_name, get_replay_mode())
591
592
  end
592
593
  menu.addAction(graph_action)
593
594
 
@@ -628,12 +629,13 @@ module Cosmos
628
629
  "Set the polling rate to PERIOD (unit seconds)") do |arg|
629
630
  options.rate = Float(arg)
630
631
  end
632
+ options.replay = false
633
+ option_parser.on("--replay", "Start Packet Viewer in Replay mode") do
634
+ options.replay = true
635
+ end
631
636
  end
632
-
633
637
  super(option_parser, options)
634
638
  end
635
639
  end
636
-
637
- end # class PacketViewer
638
-
639
- end # module Cosmos
640
+ end
641
+ end
@@ -26,6 +26,7 @@ module Cosmos
26
26
  slots 'undo_available(bool)'
27
27
 
28
28
  UNTITLED_TAB_TEXT = ' Untitled '
29
+ MAX_RECENT_FILES = 20
29
30
 
30
31
  def initialize(options)
31
32
  # All code before super is executed twice in RubyQt Based classes
@@ -50,7 +51,9 @@ module Cosmos
50
51
  @no_icon = Qt::Icon.new
51
52
 
52
53
  begin
53
- ScriptRunnerConfig.new(options.config_file)
54
+ # Always create the ScriptRunnerConfig but note that it's optional to pass a config file
55
+ # If the user doesn't have one it will be created automatically if the default config is changed
56
+ @config = ScriptRunnerConfig.new(options.config_file)
54
57
  rescue => error
55
58
  ExceptionDialog.new(self, error, "Error parsing #{options.config_file}")
56
59
  end
@@ -95,13 +98,17 @@ module Cosmos
95
98
  @file_new.statusTip = 'Start a new script'
96
99
  @file_new.connect(SIGNAL('triggered()')) { file_new() }
97
100
 
101
+ @clear_file_open_recent = Qt::Action.new('&Clear Recent', self)
102
+ @clear_file_open_recent.statusTip = 'Clear the recently opened file list'
103
+ @clear_file_open_recent.connect(SIGNAL('triggered()')) { clear_file_open_recent() }
104
+
98
105
  @file_close = Qt::Action.new('&Close', self)
99
106
  @file_close_keyseq = Qt::KeySequence.new('Ctrl+W')
100
107
  @file_close.shortcut = @file_close_keyseq
101
108
  @file_close.statusTip = 'Close the script'
102
109
  @file_close.connect(SIGNAL('triggered()')) { file_close() }
103
110
 
104
- @file_reload = Qt::Action.new('&Reload', self)
111
+ @file_reload = Qt::Action.new('Re&load', self)
105
112
  @file_reload_keyseq = Qt::KeySequence.new('Ctrl+R')
106
113
  @file_reload.shortcut = @file_reload_keyseq
107
114
  @file_reload.statusTip = 'Reload a script'
@@ -257,6 +264,13 @@ module Cosmos
257
264
  @script_call_stack.connect(SIGNAL('triggered()')) { script_call_stack() }
258
265
  @script_call_stack.setEnabled(false)
259
266
 
267
+ @script_error_backtrace = Qt::Action.new('Show Error Backtrace', self)
268
+ @script_error_backtrace.statusTip = 'Show Error Backtrace from the last encountered exception'
269
+ @script_error_backtrace.connect(SIGNAL('triggered()')) do
270
+ ScriptRunnerFrame.show_backtrace = @script_error_backtrace.checked?
271
+ end
272
+ @script_error_backtrace.setCheckable(true)
273
+
260
274
  @script_debug = Qt::Action.new(Cosmos.get_icon('bug.png'), 'Toggle &Debug', self)
261
275
  @script_debug_keyseq = Qt::KeySequence.new('Ctrl+D')
262
276
  @script_debug.shortcut = @script_debug_keyseq
@@ -284,6 +298,20 @@ module Cosmos
284
298
  @file_open.setIcon(Cosmos.get_icon('open.png'))
285
299
  target_dirs_action(@file_open, System.paths['PROCEDURES'], 'procedures', method(:file_open))
286
300
 
301
+ @file_open_recent = @file_menu.addMenu('Open &Recent')
302
+ @file_open_recent.setIcon(Cosmos.get_icon('open.png'))
303
+ settings = Qt::Settings.new('Ball Aerospace', self.class.to_s)
304
+ if settings.contains('recent_files')
305
+ recent = settings.value('recent_files').toStringList()
306
+ recent.each do |filename|
307
+ action = Qt::Action.new(filename, self)
308
+ action.connect(SIGNAL('triggered()')) { open_filename(filename) }
309
+ @file_open_recent.addAction(action)
310
+ end
311
+ end
312
+ @file_open_recent.addSeparator()
313
+ @file_open_recent.addAction(@clear_file_open_recent)
314
+
287
315
  @file_menu.addAction(@file_close)
288
316
  @file_menu.addAction(@file_reload)
289
317
  @file_menu.addSeparator()
@@ -334,6 +362,7 @@ module Cosmos
334
362
  view_menu.addSeparator()
335
363
  view_menu.addAction(@script_log_message)
336
364
  view_menu.addAction(@script_call_stack)
365
+ view_menu.addAction(@script_error_backtrace)
337
366
  view_menu.addAction(@script_debug)
338
367
  view_menu.addAction(@script_disconnect)
339
368
 
@@ -409,35 +438,63 @@ module Cosmos
409
438
  # File->Open
410
439
  def file_open(filename = nil)
411
440
  if File.directory?(filename)
412
- filename = Qt::FileDialog.getOpenFileName(self, "Select Script", filename)
441
+ filenames = Qt::FileDialog.getOpenFileNames(self, "Select Script(s)", filename, "Scripts (*.rb);;All Files(*.*)")
442
+ else
443
+ filenames = [filename]
413
444
  end
414
- unless filename.nil? || filename.empty?
415
- # If the user opens a file we already have open
416
- # just set the current tab to that file and return
417
- @tab_book.tabs.each_with_index do |tab, index|
418
- if tab.filename == filename
419
- @tab_book.setCurrentIndex(index)
420
- @tab_book.currentTab.set_text_from_file(filename)
421
- @tab_book.currentTab.filename = filename
422
- return
423
- end
445
+ filenames.compact!
446
+ return if filenames.nil? || filenames.empty?
447
+ filenames.each do |filename|
448
+ open_filename(filename)
449
+
450
+ found = false
451
+ @file_open_recent.actions.each do |action|
452
+ found = true if action.text == filename
424
453
  end
454
+ next if found
455
+ action = Qt::Action.new(filename, self)
456
+ action.connect(SIGNAL('triggered()')) { open_filename(filename) }
457
+ @file_open_recent.insertAction(@file_open_recent.actions[0], action)
458
+ # Add 2 for the separator and Clear Recent action
459
+ if @file_open_recent.actions.length > (MAX_RECENT_FILES + 2)
460
+ @file_open_recent.removeAction(@file_open_recent.actions[-3]) # ignore last 2
461
+ end
462
+ end
463
+ end
464
+
465
+ def clear_file_open_recent
466
+ # Subtract 2 for the separator and Clear Recent action
467
+ (@file_open_recent.actions.length - 2).times do
468
+ @file_open_recent.removeAction(@file_open_recent.actions[0])
469
+ end
470
+ end
425
471
 
426
- if ((@tab_book.count == 1) &&
427
- @tab_book.currentTab.filename.empty? &&
428
- !@tab_book.currentTab.modified)
429
- # Active Tab is an unmodified Untitled so just open the file in it
472
+ def open_filename(filename)
473
+ # If the user opens a file we already have open
474
+ # just set the current tab to that file and return
475
+ @tab_book.tabs.each_with_index do |tab, index|
476
+ if tab.filename == filename
477
+ @tab_book.setCurrentIndex(index)
430
478
  @tab_book.currentTab.set_text_from_file(filename)
431
479
  @tab_book.currentTab.filename = filename
432
- @tab_book.setTabText(@tab_book.currentIndex, File.basename(filename))
433
- else
434
- create_tab(filename)
480
+ return
435
481
  end
482
+ end
436
483
 
437
- update_title()
438
- @procedure_dir = File.dirname(filename)
439
- @procedure_dir << '/' if @procedure_dir[-1..-1] != '/' and @procedure_dir[-1..-1] != '\\'
484
+ if ((@tab_book.count == 1) &&
485
+ @tab_book.currentTab.filename.empty? &&
486
+ !@tab_book.currentTab.modified)
487
+ # Active Tab is an unmodified Untitled so just open the file in it
488
+ @tab_book.currentTab.set_text_from_file(filename)
489
+ @tab_book.currentTab.filename = filename
490
+ @tab_book.setTabText(@tab_book.currentIndex, File.basename(filename))
491
+ else
492
+ create_tab(filename)
440
493
  end
494
+
495
+ update_title()
496
+ @procedure_dir = File.dirname(filename)
497
+ @procedure_dir << '/' if @procedure_dir[-1..-1] != '/' and @procedure_dir[-1..-1] != '\\'
441
498
  end
442
499
 
443
500
  # File->Reload
@@ -565,6 +622,7 @@ module Cosmos
565
622
  ScriptRunnerFrame.pause_on_error = (pause_on_error.checkState == Qt::Checked)
566
623
  ScriptRunnerFrame.monitor_limits = (monitor.checkState == Qt::Checked)
567
624
  ScriptRunnerFrame.pause_on_red = (pause_on_red.checkState == Qt::Checked)
625
+ @config.write_config
568
626
  dialog.accept
569
627
  end
570
628
  cancel = Qt::PushButton.new('Cancel')
@@ -669,6 +727,10 @@ module Cosmos
669
727
  def closeEvent(event)
670
728
  if active_script_runner_frame().prompt_if_running_on_close()
671
729
  if prompt_for_save_if_needed_on_close()
730
+ settings = Qt::Settings.new('Ball Aerospace', self.class.to_s)
731
+ recent_files = @file_open_recent.actions.collect {|action| action.text }
732
+ # Ignore the last 2 because of the separator and Clear Recent action
733
+ settings.setValue('recent_files', Qt::Variant.new(recent_files[0..-3]))
672
734
  shutdown_cmd_tlm()
673
735
  @tab_book.tabs.each_with_index do |tab, index|
674
736
  tab.stop_message_log
@@ -986,9 +1048,6 @@ module Cosmos
986
1048
  options.disconnect_mode = false
987
1049
 
988
1050
  option_parser.separator "Script Runner Specific Options:"
989
- option_parser.on("-c", "--config FILE", "Use the specified configuration file") do |arg|
990
- options.config_file = arg
991
- end
992
1051
  option_parser.on("-s", "--server FILE", "Use the specified server configuration file for disconnect mode") do |arg|
993
1052
  options.server_config_file = arg
994
1053
  end
@@ -1003,6 +1062,5 @@ module Cosmos
1003
1062
  super(option_parser, options)
1004
1063
  end
1005
1064
  end
1006
- end # class ScriptRunner
1007
-
1008
- end # module Cosmos
1065
+ end
1066
+ end
@@ -16,12 +16,16 @@ module Cosmos
16
16
  # Processes the config file
17
17
  def initialize(filename)
18
18
  return unless filename
19
+ @filename = filename
19
20
  parser = ConfigParser.new("http://cosmosrb.com/docs/tools/#script-runner-configuration")
20
21
  parser.parse_file(filename) do |keyword, params|
21
22
  case keyword
22
23
  when 'LINE_DELAY'
23
24
  parser.verify_num_parameters(1, 1, "#{keyword} <Delay in Seconds>")
24
25
  ScriptRunnerFrame.line_delay = params[0].to_f
26
+ when 'PAUSE_ON_ERROR'
27
+ parser.verify_num_parameters(1, 1, "#{keyword} <TRUE or FALSE>")
28
+ ScriptRunnerFrame.pause_on_error = ConfigParser.handle_true_false(params[0])
25
29
  when 'MONITOR_LIMITS'
26
30
  parser.verify_num_parameters(0, 0, keyword)
27
31
  ScriptRunnerFrame.monitor_limits = true
@@ -35,5 +39,15 @@ module Cosmos
35
39
  end
36
40
  end
37
41
  end
42
+
43
+ def write_config
44
+ @filename = File.join(Cosmos::USERPATH, 'config', 'tools', 'script_runner', 'script_runner.txt') unless @filename
45
+ File.open(@filename, 'w') do |file|
46
+ file.puts("LINE_DELAY #{ScriptRunnerFrame.line_delay}")
47
+ file.puts("PAUSE_ON_ERROR #{ScriptRunnerFrame.pause_on_error ? 'TRUE' : 'FALSE'}")
48
+ file.puts("MONITOR_LIMITS") if ScriptRunnerFrame.monitor_limits
49
+ file.puts("PAUSE_ON_RED") if ScriptRunnerFrame.pause_on_red
50
+ end
51
+ end
38
52
  end
39
53
  end
@@ -89,6 +89,9 @@ module Cosmos
89
89
  SET_TLM_KEYWORDS = %w(set_tlm set_tlm_raw override_tlm_raw normalize_tlm_raw)
90
90
  CHECK_KEYWORDS = %w(check check_raw wait wait_raw wait_check wait_check_raw)
91
91
 
92
+ INSTANCE_VARS = %w(__return_val close_on_complete error eval_error filename instrumented_script \
93
+ line_number line_offset saved_instance saved_run_thread text text_binding uncaught_exception)
94
+
92
95
  attr_accessor :use_instrumentation
93
96
  attr_accessor :change_callback
94
97
  attr_accessor :run_callback
@@ -569,10 +572,14 @@ module Cosmos
569
572
  return nil if @cancel_instrumentation
570
573
  instrumented_line = ''
571
574
  if instrumentable
572
- # Skip the segment if it's empty. Note that the segment could have
573
- # originally had comments but they were stripped in
575
+ # Add a newline if it's empty to ensure the instrumented code has
576
+ # the same number of lines as the original script. Note that the
577
+ # segment could have originally had comments but they were stripped in
574
578
  # ruby_lex_utils.remove_comments
575
- next if segment.strip.empty?
579
+ if segment.strip.empty?
580
+ instrumented_text << "\n"
581
+ next
582
+ end
576
583
 
577
584
  # Create a variable to hold the segment's return value
578
585
  instrumented_line << "__return_val = nil; "
@@ -671,7 +678,7 @@ module Cosmos
671
678
  def exception_instrumentation(error, filename, line_number)
672
679
  if error.class == StopScript || error.class == SkipTestCase || !@use_instrumentation
673
680
  Kernel.raise error
674
- else
681
+ elsif !error.eql?(@@error)
675
682
  line_number = line_number + @line_offset if @active_script.object_id == @script.object_id
676
683
  handle_exception(error, false, filename, line_number)
677
684
  end
@@ -962,6 +969,10 @@ module Cosmos
962
969
  end
963
970
 
964
971
  if @script_binding
972
+ # Check for accessing an instance variable or local
973
+ if debug_text =~ /^@\S+$/ || @script_binding.local_variables.include?(debug_text.to_sym)
974
+ debug_text = "puts #{debug_text}" # Automatically add puts to print it
975
+ end
965
976
  eval(debug_text, @script_binding, 'debug', 1)
966
977
  else
967
978
  Object.class_eval(debug_text, 'debug', 1)
@@ -999,9 +1010,21 @@ module Cosmos
999
1010
  @debug_text.setPlainText("")
1000
1011
  end
1001
1012
  end
1002
-
1003
1013
  @debug_frame.addWidget(@debug_text)
1004
1014
 
1015
+ @locals_button = Qt::PushButton.new('Locals')
1016
+ @locals_button.connect(SIGNAL('clicked(bool)')) do
1017
+ next unless @script_binding
1018
+ @locals_button.setEnabled(false)
1019
+ vars = @script_binding.local_variables.map(&:to_s)
1020
+ puts "Locals: #{vars.reject {|x| INSTANCE_VARS.include?(x)}.sort.join(', ')}"
1021
+ while @output_io.string[-1..-1] == "\n"
1022
+ Qt::CoreApplication.processEvents()
1023
+ end
1024
+ @locals_button.setEnabled(true)
1025
+ end
1026
+ @debug_frame.addWidget(@locals_button)
1027
+
1005
1028
  @bottom_frame.layout.addLayout(@debug_frame)
1006
1029
  end
1007
1030
  end
@@ -1375,7 +1398,13 @@ module Cosmos
1375
1398
  $stdout.add_stream(@output_io)
1376
1399
  $stderr.add_stream(@output_io)
1377
1400
 
1378
- scriptrunner_puts "Starting script: #{File.basename(@filename)}" unless close_on_complete
1401
+ unless close_on_complete
1402
+ scriptrunner_puts("Starting script: #{File.basename(@filename)}")
1403
+ targets = get_disconnected_targets()
1404
+ if targets
1405
+ scriptrunner_puts("DISCONNECTED targets: #{targets.join(',')}")
1406
+ end
1407
+ end
1379
1408
  handle_output_io()
1380
1409
 
1381
1410
  # Start Limits Monitoring
@@ -1685,7 +1714,12 @@ module Cosmos
1685
1714
  if cached
1686
1715
  @active_script.setPlainText(cached.gsub("\r", ''))
1687
1716
  else
1688
- @active_script.setPlainText(File.read(filename).gsub("\r", ''))
1717
+ if File.exist?(filename)
1718
+ data = File.read(filename).gsub("\r", '')
1719
+ else
1720
+ data = ""
1721
+ end
1722
+ @active_script.setPlainText(data)
1689
1723
  end
1690
1724
  mark_breakpoints(filename)
1691
1725