cosmos 3.5.3 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Manifest.txt +3 -0
  4. data/autohotkey/procedures/script_test.rb +4 -0
  5. data/autohotkey/tools/script_runner2.ahk +13 -0
  6. data/cosmos.gemspec +2 -2
  7. data/data/crc.txt +17 -17
  8. data/demo/config/data/crc.txt +10 -7
  9. data/demo/config/targets/INST/cmd_tlm/_ccsds_cmd.txt +9 -0
  10. data/demo/config/targets/INST/cmd_tlm/_ccsds_tlm.txt +19 -0
  11. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +19 -84
  12. data/demo/config/targets/INST/cmd_tlm/inst_tlm.txt +27 -110
  13. data/demo/config/tools/table_manager/TLMMonitoringTable_def.txt +3 -220
  14. data/demo/config/tools/tlm_extractor/_adcs_time.txt +2 -0
  15. data/demo/config/tools/tlm_extractor/tlm_extractor.txt +1 -1
  16. data/demo/config/tools/tlm_extractor/tlm_extractor2.txt +1 -1
  17. data/demo/config/tools/tlm_extractor/tlm_extractor3.txt +1 -1
  18. data/demo/config/tools/tlm_extractor/tlm_extractor4.txt +1 -1
  19. data/lib/cosmos/config/config_parser.rb +54 -1
  20. data/lib/cosmos/gui/utilities/script_module_gui.rb +31 -20
  21. data/lib/cosmos/io/json_drb.rb +33 -23
  22. data/lib/cosmos/io/json_drb_object.rb +4 -1
  23. data/lib/cosmos/io/tcpip_server.rb +1 -1
  24. data/lib/cosmos/packets/packet_config.rb +5 -1
  25. data/lib/cosmos/packets/parsers/macro_parser.rb +1 -1
  26. data/lib/cosmos/script/scripting.rb +28 -0
  27. data/lib/cosmos/streams/tcpip_socket_stream.rb +72 -19
  28. data/lib/cosmos/system/target.rb +16 -2
  29. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +28 -17
  30. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +14 -2
  31. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +1 -1
  32. data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +27 -20
  33. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +2 -2
  34. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +40 -36
  35. data/lib/cosmos/version.rb +5 -5
  36. data/spec/config/config_parser_spec.rb +1 -1
  37. data/spec/io/json_drb_spec.rb +7 -21
  38. data/spec/packets/packet_config_spec.rb +12 -12
  39. data/spec/packets/parsers/format_string_parser_spec.rb +3 -3
  40. data/spec/packets/parsers/limits_parser_spec.rb +10 -10
  41. data/spec/packets/parsers/limits_response_parser_spec.rb +2 -2
  42. data/spec/packets/parsers/macro_parser_spec.rb +6 -6
  43. data/spec/packets/parsers/packet_parser_spec.rb +1 -1
  44. data/spec/packets/parsers/processor_parser_spec.rb +2 -2
  45. data/spec/packets/parsers/state_parser_spec.rb +1 -1
  46. data/spec/script/scripting_spec.rb +23 -0
  47. data/spec/streams/tcpip_socket_stream_spec.rb +28 -0
  48. data/spec/system/system_spec.rb +20 -20
  49. data/spec/system/target_spec.rb +10 -10
  50. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +30 -22
  51. metadata +9 -6
@@ -198,7 +198,7 @@ module Cosmos
198
198
  else
199
199
  Logger.error "#{@interface.name} Connection Failed: #{connect_error.formatted(false, false)}"
200
200
  case connect_error
201
- when Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::ENOTSOCK, Errno::EHOSTUNREACH
201
+ when Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::ENOTSOCK, Errno::EHOSTUNREACH, IOError
202
202
  # Do not write an exception file for these extremely common cases
203
203
  else
204
204
  if RuntimeError === connect_error and (connect_error.message =~ /canceled/ or connect_error.message =~ /timeout/)
@@ -222,7 +222,7 @@ module Cosmos
222
222
  if err
223
223
  Logger.info "Connection Lost for #{@interface.name}: #{err.formatted(false, false)}"
224
224
  case err
225
- when Errno::ECONNABORTED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EBADF
225
+ when Errno::ECONNABORTED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EBADF, IOError
226
226
  # Do not write an exception file for these extremely common cases
227
227
  else
228
228
  Logger.error err.formatted
@@ -1485,46 +1485,50 @@ module Cosmos
1485
1485
 
1486
1486
  # Right click context_menu for the script
1487
1487
  def context_menu(point)
1488
- if @tab_book_shown
1489
- current_script = @tab_book.tab(@tab_book.currentIndex)
1490
- else
1491
- current_script = @script
1492
- end
1493
- menu = current_script.context_menu(point)
1494
- menu.addSeparator()
1495
- if not self.class.running?
1496
- exec_selected_action = Qt::Action.new(tr("Execute Selected Lines"), self)
1497
- exec_selected_action.statusTip = tr("Execute the selected lines as a standalone script")
1498
- exec_selected_action.connect(SIGNAL('triggered()')) { run_selection() }
1499
- menu.addAction(exec_selected_action)
1500
-
1501
- exec_cursor_action = Qt::Action.new(tr("Execute From Cursor"), self)
1502
- exec_cursor_action.statusTip = tr("Execute the script starting at the line containing the cursor")
1503
- exec_cursor_action.connect(SIGNAL('triggered()')) { run_from_cursor() }
1504
- menu.addAction(exec_cursor_action)
1505
-
1506
- menu.addSeparator()
1507
-
1508
- if RUBY_VERSION.split('.')[0].to_i > 1
1509
- syntax_action = Qt::Action.new(tr("Ruby Syntax Check Selected Lines"), self)
1510
- syntax_action.statusTip = tr("Check the selected lines for valid Ruby syntax")
1511
- syntax_action.connect(SIGNAL('triggered()')) { ruby_syntax_check_selection() }
1512
- menu.addAction(syntax_action)
1488
+ # Only show context menu if not running or paused. Otherwise will segfault if current tab goes away while menu
1489
+ # is shown
1490
+ if not self.class.running? or (running?() and @realtime_button_bar.state != 'Running')
1491
+ if @tab_book_shown
1492
+ current_script = @tab_book.tab(@tab_book.currentIndex)
1493
+ else
1494
+ current_script = @script
1513
1495
  end
1496
+ menu = current_script.context_menu(point)
1497
+ menu.addSeparator()
1498
+ if not self.class.running?
1499
+ exec_selected_action = Qt::Action.new(tr("Execute Selected Lines"), self)
1500
+ exec_selected_action.statusTip = tr("Execute the selected lines as a standalone script")
1501
+ exec_selected_action.connect(SIGNAL('triggered()')) { run_selection() }
1502
+ menu.addAction(exec_selected_action)
1503
+
1504
+ exec_cursor_action = Qt::Action.new(tr("Execute From Cursor"), self)
1505
+ exec_cursor_action.statusTip = tr("Execute the script starting at the line containing the cursor")
1506
+ exec_cursor_action.connect(SIGNAL('triggered()')) { run_from_cursor() }
1507
+ menu.addAction(exec_cursor_action)
1508
+
1509
+ menu.addSeparator()
1510
+
1511
+ if RUBY_VERSION.split('.')[0].to_i > 1
1512
+ syntax_action = Qt::Action.new(tr("Ruby Syntax Check Selected Lines"), self)
1513
+ syntax_action.statusTip = tr("Check the selected lines for valid Ruby syntax")
1514
+ syntax_action.connect(SIGNAL('triggered()')) { ruby_syntax_check_selection() }
1515
+ menu.addAction(syntax_action)
1516
+ end
1514
1517
 
1515
- mnemonic_action = Qt::Action.new(tr("Mnemonic Check Selected Lines"), self)
1516
- mnemonic_action.statusTip = tr("Check the selected lines for valid targets, packets, mnemonics and parameters")
1517
- mnemonic_action.connect(SIGNAL('triggered()')) { mnemonic_check_selection() }
1518
- menu.addAction(mnemonic_action)
1518
+ mnemonic_action = Qt::Action.new(tr("Mnemonic Check Selected Lines"), self)
1519
+ mnemonic_action.statusTip = tr("Check the selected lines for valid targets, packets, mnemonics and parameters")
1520
+ mnemonic_action.connect(SIGNAL('triggered()')) { mnemonic_check_selection() }
1521
+ menu.addAction(mnemonic_action)
1519
1522
 
1520
- elsif running?() and @realtime_button_bar.state != 'Running'
1521
- exec_selected_action = Qt::Action.new(tr("Execute Selected Lines While Paused"), self)
1522
- exec_selected_action.statusTip = tr("Execute the selected lines as a standalone script")
1523
- exec_selected_action.connect(SIGNAL('triggered()')) { run_selection_while_paused() }
1524
- menu.addAction(exec_selected_action)
1523
+ elsif running?() and @realtime_button_bar.state != 'Running'
1524
+ exec_selected_action = Qt::Action.new(tr("Execute Selected Lines While Paused"), self)
1525
+ exec_selected_action.statusTip = tr("Execute the selected lines as a standalone script")
1526
+ exec_selected_action.connect(SIGNAL('triggered()')) { run_selection_while_paused() }
1527
+ menu.addAction(exec_selected_action)
1528
+ end
1529
+ menu.exec(current_script.mapToGlobal(point))
1530
+ menu.dispose
1525
1531
  end
1526
- menu.exec(current_script.mapToGlobal(point))
1527
- menu.dispose
1528
1532
  end
1529
1533
 
1530
1534
  def load_file_into_script(filename)
@@ -1,12 +1,12 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- COSMOS_VERSION = '3.5.3'
3
+ COSMOS_VERSION = '3.6.0'
4
4
  module Cosmos
5
5
  module Version
6
6
  MAJOR = '3'
7
- MINOR = '5'
8
- PATCH = '3'
9
- BUILD = '351455c115f9d09210eb410fa47da30f60787489'
7
+ MINOR = '6'
8
+ PATCH = '0'
9
+ BUILD = 'c536539999e6ee8e176d875a88e4ae639bb1e196'
10
10
  end
11
- VERSION = '3.5.3'
11
+ VERSION = '3.6.0'
12
12
  end
@@ -128,7 +128,7 @@ module Cosmos
128
128
  tf.close
129
129
 
130
130
  msg_callback = double(:call => true)
131
- expect(msg_callback).to receive(:call).once.with(/Parsing .* bytes of #{tf.path}/)
131
+ expect(msg_callback).to receive(:call).once.with(/Parsing .* bytes of .*#{File.basename(tf.path)}/)
132
132
 
133
133
  ConfigParser.message_callback = msg_callback
134
134
  @cp.parse_file(tf.path) do |keyword, params|
@@ -17,6 +17,7 @@ module Cosmos
17
17
  describe JsonDRb do
18
18
  before(:each) do
19
19
  @json = JsonDRb.new
20
+ @pipe_reader, @pipe_writer = IO.pipe
20
21
  end
21
22
 
22
23
  describe "initialize" do
@@ -122,21 +123,6 @@ module Cosmos
122
123
  end
123
124
 
124
125
  describe "receive_message" do
125
- it "returns nil if 4 bytes of data aren't available" do
126
- @json.start_service('127.0.0.1', 7777, self)
127
- socket = TCPSocket.open('127.0.0.1',7777)
128
- # Stub recv_nonblock so it returns nothing
129
- allow(socket).to receive(:recv_nonblock) { "" }
130
- sleep 0.1
131
- JsonDRb.send_data(socket, "\x00")
132
- response_data = JsonDRb.receive_message(socket, '')
133
- expect(response_data).to be_nil
134
- socket.close
135
- sleep 0.1
136
- @json.stop_service
137
- sleep(0.1)
138
- end
139
-
140
126
  it "processes success requests" do
141
127
  class MyServer1
142
128
  def my_method(param)
@@ -148,7 +134,7 @@ module Cosmos
148
134
  sleep 0.1
149
135
  request = JsonRpcRequest.new('my_method', 'param', 1).to_json
150
136
  JsonDRb.send_data(socket, request)
151
- response_data = JsonDRb.receive_message(socket, '')
137
+ response_data = JsonDRb.receive_message(socket, '', @pipe_reader)
152
138
  response = JsonRpcResponse.from_json(response_data)
153
139
  expect(response).to be_a(JsonRpcSuccessResponse)
154
140
  socket.close
@@ -166,7 +152,7 @@ module Cosmos
166
152
  sleep 0.1
167
153
  request = JsonRpcRequest.new('my_method', 'param', 1).to_json
168
154
  JsonDRb.send_data(socket, request)
169
- response_data = JsonDRb.receive_message(socket, '')
155
+ response_data = JsonDRb.receive_message(socket, '', @pipe_reader)
170
156
  response = JsonRpcResponse.from_json(response_data)
171
157
  expect(response).to be_a(JsonRpcErrorResponse)
172
158
  expect(response.error.code).to eql -32601
@@ -188,7 +174,7 @@ module Cosmos
188
174
  sleep 0.1
189
175
  request = JsonRpcRequest.new('my_method', 'param1', 1).to_json
190
176
  JsonDRb.send_data(socket, request)
191
- response_data = JsonDRb.receive_message(socket, '')
177
+ response_data = JsonDRb.receive_message(socket, '', @pipe_reader)
192
178
  response = JsonRpcResponse.from_json(response_data)
193
179
  expect(response).to be_a(JsonRpcErrorResponse)
194
180
  expect(response.error.code).to eql -32602
@@ -211,7 +197,7 @@ module Cosmos
211
197
  sleep 0.1
212
198
  request = JsonRpcRequest.new('my_method', 'param', 1).to_json
213
199
  JsonDRb.send_data(socket, request)
214
- response_data = JsonDRb.receive_message(socket, '')
200
+ response_data = JsonDRb.receive_message(socket, '', @pipe_reader)
215
201
  response = JsonRpcResponse.from_json(response_data)
216
202
  expect(response).to be_a(JsonRpcErrorResponse)
217
203
  expect(response.error.code).to eql -1
@@ -228,7 +214,7 @@ module Cosmos
228
214
  sleep 0.1
229
215
  request = JsonRpcRequest.new('send', 'param', 1).to_json
230
216
  JsonDRb.send_data(socket, request)
231
- response_data = JsonDRb.receive_message(socket, '')
217
+ response_data = JsonDRb.receive_message(socket, '', @pipe_reader)
232
218
  response = JsonRpcResponse.from_json(response_data)
233
219
  expect(response).to be_a(JsonRpcErrorResponse)
234
220
  expect(response.error.code).to eql -1
@@ -247,7 +233,7 @@ module Cosmos
247
233
  request.gsub!("jsonrpc","version")
248
234
  request.gsub!("2.0","1.1")
249
235
  JsonDRb.send_data(socket, request)
250
- response_data = JsonDRb.receive_message(socket, '')
236
+ response_data = JsonDRb.receive_message(socket, '', @pipe_reader)
251
237
  response = JsonRpcResponse.from_json(response_data)
252
238
  expect(response).to be_a(JsonRpcErrorResponse)
253
239
  expect(response.error.code).to eql -32600
@@ -26,7 +26,7 @@ module Cosmos
26
26
  tf = Tempfile.new('unittest')
27
27
  tf.puts("BLAH")
28
28
  tf.close
29
- expect { @pc.process_file(tf.path, 'SYSTEM') }.to raise_error(ConfigParser::Error, "Unknown keyword 'BLAH'")
29
+ expect { @pc.process_file(tf.path, 'SYSTEM') }.to raise_error(ConfigParser::Error, /Unknown keyword 'BLAH'/)
30
30
  tf.unlink
31
31
  end
32
32
 
@@ -46,7 +46,7 @@ module Cosmos
46
46
  tf = Tempfile.new('unittest')
47
47
  tf.puts(keyword)
48
48
  tf.close
49
- expect { @pc.process_file(tf.path, "SYSTEM") }.to raise_error(ConfigParser::Error, "No current packet for #{keyword}")
49
+ expect { @pc.process_file(tf.path, "SYSTEM") }.to raise_error(ConfigParser::Error, /No current packet for #{keyword}/)
50
50
  tf.unlink
51
51
  end # end for each tlm_keywords
52
52
  end
@@ -59,7 +59,7 @@ module Cosmos
59
59
  tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
60
60
  tf.puts keyword
61
61
  tf.close
62
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "No current item for #{keyword}")
62
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /No current item for #{keyword}/)
63
63
  tf.unlink
64
64
  end
65
65
  end
@@ -241,7 +241,7 @@ module Cosmos
241
241
  tf.puts 'SELECT_TELEMETRY TGT PKT'
242
242
  tf.puts ' SELECT_PARAMETER ITEM'
243
243
  tf.close
244
- expect { @pc.process_file(tf.path, "TGT") }.to raise_error(ConfigParser::Error, "SELECT_PARAMETER only applies to command packets")
244
+ expect { @pc.process_file(tf.path, "TGT") }.to raise_error(ConfigParser::Error, /SELECT_PARAMETER only applies to command packets/)
245
245
  end
246
246
 
247
247
  it "complains if the parameter is not found" do
@@ -259,7 +259,7 @@ module Cosmos
259
259
  tf.puts ' SELECT_PARAMETER PARAMX'
260
260
  tf.puts ' DESCRIPTION "New description"'
261
261
  tf.close
262
- expect { @pc.process_file(tf.path, "TGT") }.to raise_error(ConfigParser::Error, "PARAMX not found in command packet TGT PKT")
262
+ expect { @pc.process_file(tf.path, "TGT") }.to raise_error(ConfigParser::Error, /PARAMX not found in command packet TGT PKT/)
263
263
  end
264
264
  end
265
265
 
@@ -271,7 +271,7 @@ module Cosmos
271
271
  tf.puts 'SELECT_COMMAND TGT PKT'
272
272
  tf.puts ' SELECT_ITEM PARAM'
273
273
  tf.close
274
- expect { @pc.process_file(tf.path, "TGT") }.to raise_error(ConfigParser::Error, "SELECT_ITEM only applies to telemetry packets")
274
+ expect { @pc.process_file(tf.path, "TGT") }.to raise_error(ConfigParser::Error, /SELECT_ITEM only applies to telemetry packets/)
275
275
  end
276
276
 
277
277
  it "complains if the item is not found" do
@@ -289,7 +289,7 @@ module Cosmos
289
289
  tf.puts ' SELECT_ITEM ITEMX'
290
290
  tf.puts ' DESCRIPTION "New description"'
291
291
  tf.close
292
- expect { @pc.process_file(tf.path, "TGT") }.to raise_error(ConfigParser::Error, "ITEMX not found in telemetry packet TGT PKT")
292
+ expect { @pc.process_file(tf.path, "TGT") }.to raise_error(ConfigParser::Error, /ITEMX not found in telemetry packet TGT PKT/)
293
293
  end
294
294
  end
295
295
 
@@ -716,14 +716,14 @@ module Cosmos
716
716
  tf.puts ' ITEM item1 0 8 UINT'
717
717
  tf.puts ' REQUIRED'
718
718
  tf.close
719
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "REQUIRED only applies to command parameters")
719
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /REQUIRED only applies to command parameters/)
720
720
  tf.unlink
721
721
 
722
722
  tf = Tempfile.new('unittest')
723
723
  tf.puts 'COMMAND tgt1 pkt1 LITTLE_ENDIAN "Packet"'
724
724
  tf.puts ' REQUIRED'
725
725
  tf.close
726
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "No current item for REQUIRED")
726
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /No current item for REQUIRED/)
727
727
  tf.unlink
728
728
  end
729
729
 
@@ -748,7 +748,7 @@ module Cosmos
748
748
  tf.puts ' APPEND_ITEM item1 16 UINT'
749
749
  tf.puts ' MINIMUM_VALUE 1'
750
750
  tf.close
751
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "MINIMUM_VALUE only applies to command parameters")
751
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /MINIMUM_VALUE only applies to command parameters/)
752
752
  tf.unlink
753
753
 
754
754
  tf = Tempfile.new('unittest')
@@ -756,7 +756,7 @@ module Cosmos
756
756
  tf.puts ' APPEND_ITEM item1 16 UINT'
757
757
  tf.puts ' MAXIMUM_VALUE 3'
758
758
  tf.close
759
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "MAXIMUM_VALUE only applies to command parameters")
759
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /MAXIMUM_VALUE only applies to command parameters/)
760
760
  tf.unlink
761
761
 
762
762
  tf = Tempfile.new('unittest')
@@ -764,7 +764,7 @@ module Cosmos
764
764
  tf.puts ' APPEND_ITEM item1 16 UINT'
765
765
  tf.puts ' DEFAULT_VALUE 2'
766
766
  tf.close
767
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "DEFAULT_VALUE only applies to command parameters")
767
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /DEFAULT_VALUE only applies to command parameters/)
768
768
  tf.unlink
769
769
  end
770
770
 
@@ -29,7 +29,7 @@ module Cosmos
29
29
  tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
30
30
  tf.puts ' FORMAT_STRING'
31
31
  tf.close
32
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "No current item for FORMAT_STRING")
32
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /No current item for FORMAT_STRING/)
33
33
  tf.unlink
34
34
  end
35
35
 
@@ -59,7 +59,7 @@ module Cosmos
59
59
  tf.puts ' ITEM item1 0 8 INT'
60
60
  tf.puts ' FORMAT_STRING "%*s"'
61
61
  tf.close
62
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid FORMAT_STRING specified for type INT: %*s")
62
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid FORMAT_STRING specified for type INT: \%\*s/)
63
63
  tf.unlink
64
64
 
65
65
  tf = Tempfile.new('unittest')
@@ -67,7 +67,7 @@ module Cosmos
67
67
  tf.puts ' ITEM item1 0 8 STRING'
68
68
  tf.puts ' FORMAT_STRING "%d"'
69
69
  tf.close
70
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid FORMAT_STRING specified for type STRING: %d")
70
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid FORMAT_STRING specified for type STRING: \%d/)
71
71
  tf.unlink
72
72
  end
73
73
 
@@ -28,7 +28,7 @@ module Cosmos
28
28
  tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
29
29
  tf.puts ' LIMITS mylimits 1 ENABLED 0 10 20 30 12 18'
30
30
  tf.close
31
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "No current item for LIMITS")
31
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /No current item for LIMITS/)
32
32
  tf.unlink
33
33
  end
34
34
 
@@ -157,7 +157,7 @@ module Cosmos
157
157
  tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
158
158
  tf.puts ' LIMITS DEFAULT 3 ENABLED 2 1 3 4'
159
159
  tf.close
160
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid limits specified. Ensure yellow limits are within red limits.")
160
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid limits specified. Ensure yellow limits are within red limits./)
161
161
  tf.unlink
162
162
 
163
163
  tf = Tempfile.new('unittest')
@@ -165,7 +165,7 @@ module Cosmos
165
165
  tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
166
166
  tf.puts ' LIMITS DEFAULT 3 ENABLED 1 5 3 7'
167
167
  tf.close
168
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid limits specified. Ensure yellow limits are within red limits.")
168
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid limits specified. Ensure yellow limits are within red limits./)
169
169
  tf.unlink
170
170
 
171
171
  tf = Tempfile.new('unittest')
@@ -173,7 +173,7 @@ module Cosmos
173
173
  tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
174
174
  tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 5 4'
175
175
  tf.close
176
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid limits specified. Ensure yellow limits are within red limits.")
176
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid limits specified. Ensure yellow limits are within red limits./)
177
177
  tf.unlink
178
178
 
179
179
  tf = Tempfile.new('unittest')
@@ -181,7 +181,7 @@ module Cosmos
181
181
  tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
182
182
  tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 3 0'
183
183
  tf.close
184
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid limits specified. Ensure yellow limits are within red limits.")
184
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid limits specified. Ensure yellow limits are within red limits./)
185
185
  tf.unlink
186
186
  end
187
187
 
@@ -191,7 +191,7 @@ module Cosmos
191
191
  tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
192
192
  tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 7 0 5'
193
193
  tf.close
194
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid limits specified. Ensure green limits are within yellow limits.")
194
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid limits specified. Ensure green limits are within yellow limits./)
195
195
  tf.unlink
196
196
 
197
197
  tf = Tempfile.new('unittest')
@@ -199,7 +199,7 @@ module Cosmos
199
199
  tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
200
200
  tf.puts ' LIMITS DEFAULT 3 ENABLED 1 3 6 7 2 5'
201
201
  tf.close
202
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid limits specified. Ensure green limits are within yellow limits.")
202
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid limits specified. Ensure green limits are within yellow limits./)
203
203
  tf.unlink
204
204
 
205
205
  tf = Tempfile.new('unittest')
@@ -207,7 +207,7 @@ module Cosmos
207
207
  tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
208
208
  tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 8 3 7'
209
209
  tf.close
210
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid limits specified. Ensure green limits are within yellow limits.")
210
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid limits specified. Ensure green limits are within yellow limits./)
211
211
  tf.unlink
212
212
 
213
213
  tf = Tempfile.new('unittest')
@@ -215,7 +215,7 @@ module Cosmos
215
215
  tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
216
216
  tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 8 3 9'
217
217
  tf.close
218
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid limits specified. Ensure green limits are within yellow limits.")
218
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid limits specified. Ensure green limits are within yellow limits./)
219
219
  tf.unlink
220
220
 
221
221
  tf = Tempfile.new('unittest')
@@ -223,7 +223,7 @@ module Cosmos
223
223
  tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
224
224
  tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 8 4 3'
225
225
  tf.close
226
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid limits specified. Ensure green limits are within yellow limits.")
226
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid limits specified. Ensure green limits are within yellow limits./)
227
227
  tf.unlink
228
228
  end
229
229
 
@@ -28,7 +28,7 @@ module Cosmos
28
28
  tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
29
29
  tf.puts ' LIMITS_RESPONSE'
30
30
  tf.close
31
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "No current item for LIMITS_RESPONSE")
31
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /No current item for LIMITS_RESPONSE/)
32
32
  tf.unlink
33
33
  end
34
34
 
@@ -48,7 +48,7 @@ module Cosmos
48
48
  tf.puts ' APPEND_PARAMETER item1 16 UINT 0 0 0 "Item"'
49
49
  tf.puts ' LIMITS_RESPONSE test.rb'
50
50
  tf.close
51
- expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "LIMITS_RESPONSE only applies to telemetry items")
51
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /LIMITS_RESPONSE only applies to telemetry items/)
52
52
  tf.unlink
53
53
  end
54
54
 
@@ -27,7 +27,7 @@ module Cosmos
27
27
  tf = Tempfile.new('unittest')
28
28
  tf.puts ' MACRO_APPEND_START'
29
29
  tf.close
30
- expect { @pc.process_file(tf.path, "SYSTEM") }.to raise_error(ConfigParser::Error, "No current packet for MACRO_APPEND_START")
30
+ expect { @pc.process_file(tf.path, "SYSTEM") }.to raise_error(ConfigParser::Error, /No current packet for MACRO_APPEND_START/)
31
31
  end
32
32
 
33
33
  it "complains if there are not enough parameters" do
@@ -58,7 +58,7 @@ module Cosmos
58
58
  expect { @pc.process_file(tf.path, "SYSTEM") }.to raise_error(ConfigParser::Error, /First close the previous/)
59
59
  end
60
60
 
61
- it "swaps reverse ranges to be in order" do
61
+ it "supports descending order" do
62
62
  tf = Tempfile.new('unittest')
63
63
  tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Description"'
64
64
  tf.puts 'MACRO_APPEND_START 4 1' # <-- Note the reverse order
@@ -71,10 +71,10 @@ module Cosmos
71
71
  pkt = @pc.telemetry["TGT1"]["PKT1"]
72
72
  expect(pkt.items.length).to eql 7 # 4 plus the RECEIVED_XXX items
73
73
  expect(pkt.items.keys).to include('BIT1','BIT2','BIT3','BIT4')
74
- expect(pkt.sorted_items[3].name).to eql 'BIT1'
75
- expect(pkt.sorted_items[4].name).to eql 'BIT2'
76
- expect(pkt.sorted_items[5].name).to eql 'BIT3'
77
- expect(pkt.sorted_items[6].name).to eql 'BIT4'
74
+ expect(pkt.sorted_items[3].name).to eql 'BIT4'
75
+ expect(pkt.sorted_items[4].name).to eql 'BIT3'
76
+ expect(pkt.sorted_items[5].name).to eql 'BIT2'
77
+ expect(pkt.sorted_items[6].name).to eql 'BIT1'
78
78
  limits_items = []
79
79
  pkt.items.each do |name, item|
80
80
  limits_items << item if name.include?('BIT')