cosmos 3.1.2 → 3.2.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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/Manifest.txt +17 -1
  4. data/autohotkey/tools/test_runner2.ahk +1 -0
  5. data/autohotkey/tools/tlm_grapher.ahk +13 -1
  6. data/data/crc.txt +39 -30
  7. data/demo/config/data/crc.txt +3 -3
  8. data/demo/config/targets/TEMPLATED/lib/templated_interface.rb +3 -1
  9. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +7 -1
  10. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +6 -1
  11. data/lib/cosmos.rb +2 -2
  12. data/lib/cosmos/gui/dialogs/about_dialog.rb +18 -5
  13. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +0 -7
  14. data/lib/cosmos/gui/line_graph/overview_graph.rb +12 -2
  15. data/lib/cosmos/gui/utilities/script_module_gui.rb +11 -3
  16. data/lib/cosmos/interfaces/interface.rb +12 -0
  17. data/lib/cosmos/interfaces/stream_interface.rb +1 -21
  18. data/lib/cosmos/interfaces/tcpip_server_interface.rb +10 -0
  19. data/lib/cosmos/io/json_drb_object.rb +75 -56
  20. data/lib/cosmos/io/tcpip_server.rb +1 -11
  21. data/lib/cosmos/packet_logs.rb +1 -0
  22. data/lib/cosmos/packet_logs/ccsds_log_reader.rb +103 -0
  23. data/lib/cosmos/packets/packet.rb +70 -1
  24. data/lib/cosmos/packets/packet_config.rb +59 -611
  25. data/lib/cosmos/packets/parsers/format_string_parser.rb +58 -0
  26. data/lib/cosmos/packets/parsers/limits_parser.rb +146 -0
  27. data/lib/cosmos/packets/parsers/limits_response_parser.rb +52 -0
  28. data/lib/cosmos/packets/parsers/macro_parser.rb +116 -0
  29. data/lib/cosmos/packets/parsers/packet_item_parser.rb +215 -0
  30. data/lib/cosmos/packets/parsers/packet_parser.rb +123 -0
  31. data/lib/cosmos/packets/parsers/processor_parser.rb +63 -0
  32. data/lib/cosmos/packets/parsers/state_parser.rb +116 -0
  33. data/lib/cosmos/packets/structure.rb +59 -22
  34. data/lib/cosmos/packets/structure_item.rb +1 -1
  35. data/lib/cosmos/script/script.rb +4 -5
  36. data/lib/cosmos/streams/serial_stream.rb +5 -0
  37. data/lib/cosmos/streams/stream.rb +8 -2
  38. data/lib/cosmos/streams/stream_protocol.rb +1 -0
  39. data/lib/cosmos/streams/tcpip_client_stream.rb +37 -7
  40. data/lib/cosmos/streams/tcpip_socket_stream.rb +9 -6
  41. data/lib/cosmos/system/target.rb +3 -6
  42. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +57 -48
  43. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +7 -3
  44. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +1 -1
  45. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +7 -1
  46. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +1 -2
  47. data/lib/cosmos/top_level.rb +22 -11
  48. data/lib/cosmos/utilities/message_log.rb +14 -9
  49. data/lib/cosmos/version.rb +5 -5
  50. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +16 -16
  51. data/spec/interfaces/linc_interface_spec.rb +3 -0
  52. data/spec/interfaces/tcpip_client_interface_spec.rb +1 -0
  53. data/spec/interfaces/tcpip_server_interface_spec.rb +9 -0
  54. data/spec/io/json_drb_object_spec.rb +1 -1
  55. data/spec/io/serial_driver_spec.rb +0 -1
  56. data/spec/packet_logs/packet_log_writer_spec.rb +5 -3
  57. data/spec/packets/packet_config_spec.rb +22 -837
  58. data/spec/packets/packet_item_spec.rb +10 -10
  59. data/spec/packets/packet_spec.rb +239 -1
  60. data/spec/packets/parsers/format_string_parser_spec.rb +122 -0
  61. data/spec/packets/parsers/limits_parser_spec.rb +282 -0
  62. data/spec/packets/parsers/limits_response_parser_spec.rb +149 -0
  63. data/spec/packets/parsers/macro_parser_spec.rb +184 -0
  64. data/spec/packets/parsers/packet_item_parser_spec.rb +306 -0
  65. data/spec/packets/parsers/packet_parser_spec.rb +99 -0
  66. data/spec/packets/parsers/processor_parser_spec.rb +114 -0
  67. data/spec/packets/parsers/state_parser_spec.rb +156 -0
  68. data/spec/packets/structure_item_spec.rb +14 -14
  69. data/spec/packets/structure_spec.rb +162 -16
  70. data/spec/streams/fixed_stream_protocol_spec.rb +7 -4
  71. data/spec/streams/length_stream_protocol_spec.rb +3 -0
  72. data/spec/streams/preidentified_stream_protocol_spec.rb +3 -0
  73. data/spec/streams/serial_stream_spec.rb +12 -0
  74. data/spec/streams/stream_protocol_spec.rb +14 -0
  75. data/spec/streams/stream_spec.rb +1 -0
  76. data/spec/streams/tcpip_client_stream_spec.rb +3 -0
  77. data/spec/streams/tcpip_socket_stream_spec.rb +15 -3
  78. data/spec/streams/template_stream_protocol_spec.rb +5 -0
  79. data/spec/streams/terminated_stream_protocol_spec.rb +4 -0
  80. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +21 -1
  81. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +1 -1
  82. data/spec/tools/cmd_tlm_server/interfaces_spec.rb +1 -1
  83. metadata +19 -3
@@ -0,0 +1,282 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'spec_helper'
12
+ require 'cosmos'
13
+ require 'cosmos/packets/packet_config'
14
+ require 'cosmos/packets/parsers/limits_parser'
15
+ require 'tempfile'
16
+
17
+ module Cosmos
18
+
19
+ describe LimitsParser do
20
+
21
+ describe "parse" do
22
+ before(:each) do
23
+ @pc = PacketConfig.new
24
+ end
25
+
26
+ it "raises if a current item is not defined" do
27
+ tf = Tempfile.new('unittest')
28
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
29
+ tf.puts ' LIMITS mylimits 1 ENABLED 0 10 20 30 12 18'
30
+ tf.close
31
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "No current item for LIMITS")
32
+ tf.unlink
33
+ end
34
+
35
+ it "raises if there are not enough parameters" do
36
+ tf = Tempfile.new('unittest')
37
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
38
+ tf.puts ' ITEM myitem 0 8 UINT "Test Item"'
39
+ tf.puts ' LIMITS DEFAULT 1 ENABLED 0 10 20 30 12'
40
+ tf.close
41
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Must give both a green low and green high/)
42
+ tf.unlink
43
+
44
+ tf = Tempfile.new('unittest')
45
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
46
+ tf.puts ' ITEM myitem 0 8 UINT "Test Item"'
47
+ tf.puts ' LIMITS DEFAULT 1 ENABLED 0 10 20'
48
+ tf.close
49
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Not enough parameters for LIMITS/)
50
+ tf.unlink
51
+ end
52
+
53
+ it "raises if there are too many parameters" do
54
+ tf = Tempfile.new('unittest')
55
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
56
+ tf.puts ' ITEM myitem 0 8 UINT "Test Item"'
57
+ tf.puts ' LIMITS DEFAULT 1 ENABLED 0 10 20 30 12 18 20'
58
+ tf.close
59
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Too many parameters for LIMITS/)
60
+ tf.unlink
61
+ end
62
+
63
+ it "raises if applied to a command PARAMETER" do
64
+ tf = Tempfile.new('unittest')
65
+ tf.puts 'COMMAND tgt1 pkt1 LITTLE_ENDIAN "Packet"'
66
+ tf.puts ' APPEND_PARAMETER item1 16 UINT 0 0 0 "Item"'
67
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 7 3 5'
68
+ tf.close
69
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /LIMITS only applies to telemetry items/)
70
+ tf.unlink
71
+ end
72
+
73
+ it "raises if a DEFAULT limits set isn't defined" do
74
+ tf = Tempfile.new('unittest')
75
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
76
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
77
+ tf.puts ' LIMITS TVAC 3 ENABLED 1 2 6 7 3 5'
78
+ tf.close
79
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /DEFAULT limits set must be defined/)
80
+ tf.unlink
81
+ end
82
+
83
+ it "sets a warning if a new limits set persistence isn't consistent with DEFAULT" do
84
+ tf = Tempfile.new('unittest')
85
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
86
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
87
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 7 3 5'
88
+ tf.puts ' LIMITS TVAC 1 DISABLED 1 2 6 7 3 5'
89
+ tf.close
90
+ @pc.process_file(tf.path, "TGT1")
91
+ expect(@pc.warnings[-1]).to match(/persistence setting conflict with DEFAULT/)
92
+ tf.unlink
93
+ end
94
+
95
+ it "sets a warning if a new limits set enable isn't consistent with DEFAULT" do
96
+ tf = Tempfile.new('unittest')
97
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
98
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
99
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 7 3 5'
100
+ tf.puts ' LIMITS TVAC 3 DISABLED 1 2 6 7 3 5'
101
+ tf.close
102
+ @pc.process_file(tf.path, "TGT1")
103
+ expect(@pc.warnings[-1]).to match(/enable setting conflict with DEFAULT/)
104
+ tf.unlink
105
+ end
106
+
107
+ it "records 2 warnings if a new limits set persistence and enable isn't consistent with DEFAULT" do
108
+ tf = Tempfile.new('unittest')
109
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
110
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
111
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 7 3 5'
112
+ tf.puts ' LIMITS TVAC 1 DISABLED 1 2 6 7 3 5'
113
+ tf.close
114
+ @pc.process_file(tf.path, "TGT1")
115
+ expect(@pc.warnings.length).to eql 2
116
+ tf.unlink
117
+ end
118
+
119
+ it "raises if the second parameter isn't a number" do
120
+ tf = Tempfile.new('unittest')
121
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
122
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
123
+ tf.puts ' LIMITS DEFAULT TRUE ENABLED 1 2 6 7 3 5'
124
+ tf.close
125
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Persistence must be an integer/)
126
+ tf.unlink
127
+ end
128
+
129
+ it "raises if the third parameter isn't ENABLED or DISABLED" do
130
+ tf = Tempfile.new('unittest')
131
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
132
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
133
+ tf.puts ' LIMITS DEFAULT 3 TRUE 1 2 6 7 3 5'
134
+ tf.close
135
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Initial LIMITS state must be ENABLED or DISABLED/)
136
+ tf.unlink
137
+ end
138
+
139
+ it "raises if the fourth through ninth parameter aren't numbers'" do
140
+ msgs = ['','','','','red low','yellow low','yellow high','red high','green low','green high']
141
+ (4..9).each do |index|
142
+ tf = Tempfile.new('unittest')
143
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
144
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
145
+ limits = %w(LIMITS DEFAULT 3 ENABLED 1 2 6 7 3 5)
146
+ limits[index] = 'X'
147
+ tf.puts limits.join(' ')
148
+ tf.close
149
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid #{msgs[index]} limit value/)
150
+ tf.unlink
151
+ end
152
+ end
153
+
154
+ it "raises if the 4 limits are out of order" do
155
+ tf = Tempfile.new('unittest')
156
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
157
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
158
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 2 1 3 4'
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.")
161
+ tf.unlink
162
+
163
+ tf = Tempfile.new('unittest')
164
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
165
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
166
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 5 3 7'
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.")
169
+ tf.unlink
170
+
171
+ tf = Tempfile.new('unittest')
172
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
173
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
174
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 5 4'
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.")
177
+ tf.unlink
178
+
179
+ tf = Tempfile.new('unittest')
180
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
181
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
182
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 3 0'
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.")
185
+ tf.unlink
186
+ end
187
+
188
+ it "raises if the 6 limits are out of order" do
189
+ tf = Tempfile.new('unittest')
190
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
191
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
192
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 7 0 5'
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.")
195
+ tf.unlink
196
+
197
+ tf = Tempfile.new('unittest')
198
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
199
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
200
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 3 6 7 2 5'
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.")
203
+ tf.unlink
204
+
205
+ tf = Tempfile.new('unittest')
206
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
207
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
208
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 8 3 7'
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.")
211
+ tf.unlink
212
+
213
+ tf = Tempfile.new('unittest')
214
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
215
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
216
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 8 3 9'
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.")
219
+ tf.unlink
220
+
221
+ tf = Tempfile.new('unittest')
222
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
223
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
224
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 8 4 3'
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.")
227
+ tf.unlink
228
+ end
229
+
230
+ it "should take 4 limits values" do
231
+ tf = Tempfile.new('unittest')
232
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
233
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
234
+ tf.puts ' LIMITS DEFAULT 1 ENABLED 1 2 6 7'
235
+ tf.close
236
+ @pc.process_file(tf.path, "TGT1")
237
+ item = @pc.telemetry["TGT1"]["PKT1"].items["ITEM1"]
238
+ item.limits.values[:DEFAULT].should_not be_nil
239
+ @pc.telemetry["TGT1"]["PKT1"].buffer = "\x04"
240
+ @pc.telemetry["TGT1"]["PKT1"].enable_limits("ITEM1")
241
+ @pc.telemetry["TGT1"]["PKT1"].check_limits
242
+ item.limits.state.should eql :GREEN
243
+ @pc.telemetry["TGT1"]["PKT1"].limits_items.should eql [item]
244
+ tf.unlink
245
+ end
246
+
247
+ it "should take 6 limits values" do
248
+ tf = Tempfile.new('unittest')
249
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
250
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
251
+ tf.puts ' LIMITS DEFAULT 1 ENABLED 1 2 6 7 3 5'
252
+ tf.close
253
+ @pc.process_file(tf.path, "TGT1")
254
+ item = @pc.telemetry["TGT1"]["PKT1"].items["ITEM1"]
255
+ item.limits.values[:DEFAULT].should_not be_nil
256
+ @pc.telemetry["TGT1"]["PKT1"].buffer = "\x04"
257
+ @pc.telemetry["TGT1"]["PKT1"].enable_limits("ITEM1")
258
+ @pc.telemetry["TGT1"]["PKT1"].check_limits
259
+ item.limits.state.should eql :BLUE
260
+ @pc.telemetry["TGT1"]["PKT1"].limits_items.should eql [item]
261
+ tf.unlink
262
+ end
263
+
264
+ it "create multiple limits sets" do
265
+ tf = Tempfile.new('unittest')
266
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
267
+ tf.puts ' APPEND_ITEM item1 16 UINT "Item"'
268
+ tf.puts ' LIMITS DEFAULT 1 ENABLED 1 2 6 7'
269
+ tf.puts ' LIMITS TVAC 1 ENABLED 1 2 6 7'
270
+ tf.close
271
+ @pc.process_file(tf.path, "TGT1")
272
+ item = @pc.telemetry["TGT1"]["PKT1"].items["ITEM1"]
273
+ expect(item.limits.values.length).to eql 2
274
+ expect(item.limits.values[:DEFAULT]).to_not be_nil
275
+ expect(item.limits.values[:TVAC]).to_not be_nil
276
+ tf.unlink
277
+ end
278
+
279
+ end
280
+
281
+ end
282
+ end
@@ -0,0 +1,149 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'spec_helper'
12
+ require 'cosmos'
13
+ require 'cosmos/packets/packet_config'
14
+ require 'cosmos/packets/parsers/limits_response_parser'
15
+ require 'tempfile'
16
+
17
+ module Cosmos
18
+
19
+ describe PacketConfig do
20
+
21
+ describe "parse" do
22
+ before(:each) do
23
+ @pc = PacketConfig.new
24
+ end
25
+
26
+ it "should complain if a current item is not defined" do
27
+ tf = Tempfile.new('unittest')
28
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
29
+ tf.puts ' LIMITS_RESPONSE'
30
+ tf.close
31
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "No current item for LIMITS_RESPONSE")
32
+ tf.unlink
33
+ end
34
+
35
+ it "should complain if there are not enough parameters" do
36
+ tf = Tempfile.new('unittest')
37
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
38
+ tf.puts 'ITEM myitem 0 8 UINT "Test Item"'
39
+ tf.puts ' LIMITS_RESPONSE'
40
+ tf.close
41
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Not enough parameters for LIMITS_RESPONSE/)
42
+ tf.unlink
43
+ end
44
+
45
+ it "should complain if applied to a command PARAMETER" do
46
+ tf = Tempfile.new('unittest')
47
+ tf.puts 'COMMAND tgt1 pkt1 LITTLE_ENDIAN "Packet"'
48
+ tf.puts ' APPEND_PARAMETER item1 16 UINT 0 0 0 "Item"'
49
+ tf.puts ' LIMITS_RESPONSE test.rb'
50
+ tf.close
51
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "LIMITS_RESPONSE only applies to telemetry items")
52
+ tf.unlink
53
+ end
54
+
55
+ it "should complain about missing response file" do
56
+ filename = File.join(File.dirname(__FILE__), "../../test_only.rb")
57
+ File.delete(filename) if File.exist?(filename)
58
+ @pc = PacketConfig.new
59
+
60
+ tf = Tempfile.new('unittest')
61
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
62
+ tf.puts ' ITEM item1 0 16 INT "Integer Item"'
63
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 7 3 5'
64
+ tf.puts ' LIMITS_RESPONSE test_only.rb'
65
+ tf.close
66
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /TestOnly class not found/)
67
+ tf.unlink
68
+ end
69
+
70
+ it "should complain about a non Cosmos::LimitsResponse class" do
71
+ filename = File.join(File.dirname(__FILE__), "../../limits_response1.rb")
72
+ File.open(filename, 'w') do |file|
73
+ file.puts "class LimitsResponse1"
74
+ file.puts " def call(target_name, packet_name, item, old_limits_state, new_limits_state)"
75
+ file.puts " end"
76
+ file.puts "end"
77
+ end
78
+ load 'limits_response1.rb'
79
+ File.delete(filename) if File.exist?(filename)
80
+
81
+ tf = Tempfile.new('unittest')
82
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
83
+ tf.puts ' ITEM item1 0 16 INT "Integer Item"'
84
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 1 2 6 7 3 5'
85
+ tf.puts ' LIMITS_RESPONSE limits_response1.rb'
86
+ tf.close
87
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /response must be a Cosmos::LimitsResponse but is a LimitsResponse1/)
88
+ tf.unlink
89
+ end
90
+
91
+ it "should set the response" do
92
+ filename = File.join(File.dirname(__FILE__), "../../limits_response2.rb")
93
+ File.open(filename, 'w') do |file|
94
+ file.puts "require 'cosmos/packets/limits_response'"
95
+ file.puts "class LimitsResponse2 < Cosmos::LimitsResponse"
96
+ file.puts " def call(target_name, packet_name, item, old_limits_state, new_limits_state)"
97
+ file.puts " puts \"\#{target_name} \#{packet_name} \#{item.name} \#{old_limits_state} \#{new_limits_state}\""
98
+ file.puts " end"
99
+ file.puts "end"
100
+ end
101
+ load 'limits_response2.rb'
102
+
103
+ tf = Tempfile.new('unittest')
104
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
105
+ tf.puts ' ITEM item1 0 16 INT "Integer Item"'
106
+ tf.puts ' LIMITS DEFAULT 1 ENABLED 1 2 6 7 3 5'
107
+ tf.puts ' LIMITS_RESPONSE limits_response2.rb'
108
+ tf.close
109
+ @pc.process_file(tf.path, "TGT1")
110
+ pkt = @pc.telemetry["TGT1"]["PKT1"]
111
+ pkt.get_item("ITEM1").limits.response.class.should eql LimitsResponse2
112
+
113
+ File.delete(filename) if File.exist?(filename)
114
+ tf.unlink
115
+ end
116
+
117
+ it "should call the response with parameters" do
118
+ filename = File.join(File.dirname(__FILE__), "../../limits_response2.rb")
119
+ File.open(filename, 'w') do |file|
120
+ file.puts "require 'cosmos/packets/limits_response'"
121
+ file.puts "class LimitsResponse2 < Cosmos::LimitsResponse"
122
+ file.puts " def initialize(val)"
123
+ file.puts " puts \"initialize: \#{val}\""
124
+ file.puts " end"
125
+ file.puts " def call(target_name, packet_name, item, old_limits_state, new_limits_state)"
126
+ file.puts " puts \"\#{target_name} \#{packet_name} \#{item.name} \#{old_limits_state} \#{new_limits_state}\""
127
+ file.puts " end"
128
+ file.puts "end"
129
+ end
130
+ load 'limits_response2.rb'
131
+
132
+ tf = Tempfile.new('unittest')
133
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
134
+ tf.puts ' ITEM item1 0 16 INT "Integer Item"'
135
+ tf.puts ' LIMITS DEFAULT 1 ENABLED 1 2 6 7 3 5'
136
+ tf.puts ' LIMITS_RESPONSE limits_response2.rb 2'
137
+ tf.close
138
+ capture_io do |stdout|
139
+ @pc.process_file(tf.path, "TGT1")
140
+ stdout.string.should eql "initialize: 2\n"
141
+ end
142
+
143
+ File.delete(filename) if File.exist?(filename)
144
+ tf.unlink
145
+ end
146
+
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,184 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'spec_helper'
12
+ require 'cosmos'
13
+ require 'cosmos/packets/packet_config'
14
+ require 'cosmos/packets/parsers/macro_parser'
15
+ require 'tempfile'
16
+
17
+ module Cosmos
18
+
19
+ describe MacroParser do
20
+ before(:each) do
21
+ @pc = PacketConfig.new
22
+ end
23
+
24
+ describe "start" do
25
+ it "complains if a current packet is not defined" do
26
+ # Check for missing TELEMETRY line
27
+ tf = Tempfile.new('unittest')
28
+ tf.puts ' MACRO_APPEND_START'
29
+ tf.close
30
+ expect { @pc.process_file(tf.path, "SYSTEM") }.to raise_error(ConfigParser::Error, "No current packet for MACRO_APPEND_START")
31
+ end
32
+
33
+ it "complains if there are not enough parameters" do
34
+ tf = Tempfile.new('unittest')
35
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
36
+ tf.puts ' MACRO_APPEND_START'
37
+ tf.close
38
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Not enough parameters for MACRO_APPEND_START/)
39
+ tf.unlink
40
+ end
41
+
42
+ it "complains if there are too many parameters" do
43
+ tf = Tempfile.new('unittest')
44
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
45
+ tf.puts 'MACRO_APPEND_START 0 1 "%s_%d" extra'
46
+ tf.close
47
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Too many parameters for MACRO_APPEND_START/)
48
+ tf.unlink
49
+ end
50
+
51
+ it "complains if a previous START hasn't been closed" do
52
+ # Check for missing TELEMETRY line
53
+ tf = Tempfile.new('unittest')
54
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
55
+ tf.puts ' MACRO_APPEND_START 1 5'
56
+ tf.puts ' MACRO_APPEND_START 1 5'
57
+ tf.close
58
+ expect { @pc.process_file(tf.path, "SYSTEM") }.to raise_error(ConfigParser::Error, /First close the previous/)
59
+ end
60
+
61
+ it "swaps reverse ranges to be in order" do
62
+ tf = Tempfile.new('unittest')
63
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Description"'
64
+ tf.puts 'MACRO_APPEND_START 4 1' # <-- Note the reverse order
65
+ tf.puts 'APPEND_ITEM BIT 16 UINT "Setting #x"'
66
+ tf.puts ' STATE BAD 0 RED'
67
+ tf.puts ' STATE GOOD 1 GREEN'
68
+ tf.puts 'MACRO_APPEND_END'
69
+ tf.close
70
+ @pc.process_file(tf.path, "TGT1")
71
+ pkt = @pc.telemetry["TGT1"]["PKT1"]
72
+ expect(pkt.items.length).to eql 7 # 4 plus the RECEIVED_XXX items
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'
78
+ limits_items = []
79
+ pkt.items.each do |name, item|
80
+ limits_items << item if name.include?('BIT')
81
+ end
82
+ expect(pkt.limits_items).to eql limits_items
83
+ tf.unlink
84
+ end
85
+ end
86
+
87
+ describe "end" do
88
+ it "complains if there are too many parameters" do
89
+ tf = Tempfile.new('unittest')
90
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
91
+ tf.puts 'MACRO_APPEND_START 0 1 "%s_%d"'
92
+ tf.puts 'MACRO_APPEND_END extra'
93
+ tf.close
94
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Too many parameters for MACRO_APPEND_END/)
95
+ tf.unlink
96
+ end
97
+
98
+ it "complains if there are no items in the macro" do
99
+ tf = Tempfile.new('unittest')
100
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
101
+ tf.puts 'MACRO_APPEND_START 0 1 "%s_%d"'
102
+ tf.puts 'MACRO_APPEND_END'
103
+ tf.close
104
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /No items appended/)
105
+ tf.unlink
106
+ end
107
+ end
108
+
109
+ describe "add_item" do
110
+ it "adds items with states to the packet" do
111
+ tf = Tempfile.new('unittest')
112
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Description"'
113
+ tf.puts 'MACRO_APPEND_START 1 5'
114
+ tf.puts 'APPEND_ITEM BIT 16 UINT "Setting #x"'
115
+ tf.puts ' STATE BAD 0 RED'
116
+ tf.puts ' STATE GOOD 1 GREEN'
117
+ tf.puts 'MACRO_APPEND_END'
118
+ tf.close
119
+ @pc.process_file(tf.path, "TGT1")
120
+ pkt = @pc.telemetry["TGT1"]["PKT1"]
121
+ expect(pkt.items.length).to eql 8 # 5 plus the RECEIVED_XXX items
122
+ pkt.items.keys.should include('BIT1','BIT2','BIT3','BIT4','BIT5')
123
+ expect(pkt.sorted_items[3].name).to eql 'BIT1'
124
+ expect(pkt.sorted_items[4].name).to eql 'BIT2'
125
+ expect(pkt.sorted_items[5].name).to eql 'BIT3'
126
+ expect(pkt.sorted_items[6].name).to eql 'BIT4'
127
+ expect(pkt.sorted_items[7].name).to eql 'BIT5'
128
+ limits_items = []
129
+ pkt.items.each do |name, item|
130
+ limits_items << item if name.include?('BIT')
131
+ end
132
+ pkt.limits_items.should eql limits_items
133
+ tf.unlink
134
+ end
135
+
136
+ it "adds items with limits to the packet" do
137
+ tf = Tempfile.new('unittest')
138
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Description"'
139
+ tf.puts 'MACRO_APPEND_START 1 5'
140
+ tf.puts 'APPEND_ITEM BIT 16 UINT "Setting #x"'
141
+ tf.puts ' LIMITS DEFAULT 3 ENABLED 0 1 3 4'
142
+ tf.puts 'MACRO_APPEND_END'
143
+ tf.close
144
+ @pc.process_file(tf.path, "TGT1")
145
+ pkt = @pc.telemetry["TGT1"]["PKT1"]
146
+ expect(pkt.items.length).to eql 8 # 5 plus the RECEIVED_XXX items
147
+ expect(pkt.items.keys).to include('BIT1','BIT2','BIT3','BIT4','BIT5')
148
+ expect(pkt.limits_items.collect{|item| item.name}).to include('BIT1','BIT2','BIT3','BIT4','BIT5')
149
+ tf.unlink
150
+ end
151
+
152
+ it "adds array items to the packet" do
153
+ tf = Tempfile.new('unittest')
154
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Description"'
155
+ tf.puts 'MACRO_APPEND_START 1 5'
156
+ tf.puts 'APPEND_ARRAY_ITEM BIT 16 INT 64 "Int Array Parameter"'
157
+ tf.puts 'MACRO_APPEND_END'
158
+ tf.close
159
+ @pc.process_file(tf.path, "TGT1")
160
+ pkt = @pc.telemetry["TGT1"]["PKT1"]
161
+ expect(pkt.items.length).to eql 8 # 5 plus the RECEIVED_XXX items
162
+ pkt.items.keys.should include('BIT1','BIT2','BIT3','BIT4','BIT5')
163
+ pkt.limits_items.should be_empty
164
+ tf.unlink
165
+ end
166
+
167
+ it "works with printf format strings" do
168
+ tf = Tempfile.new('unittest')
169
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Description"'
170
+ tf.puts 'MACRO_APPEND_START 8 12 "%02d_%s"'
171
+ tf.puts 'APPEND_ID_ITEM BIT 16 UINT 0 "Setting #x"'
172
+ tf.puts 'MACRO_APPEND_END'
173
+ tf.close
174
+ @pc.process_file(tf.path, "TGT1")
175
+ pkt = @pc.telemetry["TGT1"]["PKT1"]
176
+ expect(pkt.items.length).to eql 8 # 5 plus the RECEIVED_XXX items
177
+ pkt.items.keys.should include('08_BIT','09_BIT','10_BIT','11_BIT','12_BIT')
178
+ pkt.limits_items.should be_empty
179
+ tf.unlink
180
+ end
181
+
182
+ end
183
+ end
184
+ end