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.
- checksums.yaml +4 -4
- data/Gemfile +3 -0
- data/Manifest.txt +17 -1
- data/autohotkey/tools/test_runner2.ahk +1 -0
- data/autohotkey/tools/tlm_grapher.ahk +13 -1
- data/data/crc.txt +39 -30
- data/demo/config/data/crc.txt +3 -3
- data/demo/config/targets/TEMPLATED/lib/templated_interface.rb +3 -1
- data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +7 -1
- data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +6 -1
- data/lib/cosmos.rb +2 -2
- data/lib/cosmos/gui/dialogs/about_dialog.rb +18 -5
- data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +0 -7
- data/lib/cosmos/gui/line_graph/overview_graph.rb +12 -2
- data/lib/cosmos/gui/utilities/script_module_gui.rb +11 -3
- data/lib/cosmos/interfaces/interface.rb +12 -0
- data/lib/cosmos/interfaces/stream_interface.rb +1 -21
- data/lib/cosmos/interfaces/tcpip_server_interface.rb +10 -0
- data/lib/cosmos/io/json_drb_object.rb +75 -56
- data/lib/cosmos/io/tcpip_server.rb +1 -11
- data/lib/cosmos/packet_logs.rb +1 -0
- data/lib/cosmos/packet_logs/ccsds_log_reader.rb +103 -0
- data/lib/cosmos/packets/packet.rb +70 -1
- data/lib/cosmos/packets/packet_config.rb +59 -611
- data/lib/cosmos/packets/parsers/format_string_parser.rb +58 -0
- data/lib/cosmos/packets/parsers/limits_parser.rb +146 -0
- data/lib/cosmos/packets/parsers/limits_response_parser.rb +52 -0
- data/lib/cosmos/packets/parsers/macro_parser.rb +116 -0
- data/lib/cosmos/packets/parsers/packet_item_parser.rb +215 -0
- data/lib/cosmos/packets/parsers/packet_parser.rb +123 -0
- data/lib/cosmos/packets/parsers/processor_parser.rb +63 -0
- data/lib/cosmos/packets/parsers/state_parser.rb +116 -0
- data/lib/cosmos/packets/structure.rb +59 -22
- data/lib/cosmos/packets/structure_item.rb +1 -1
- data/lib/cosmos/script/script.rb +4 -5
- data/lib/cosmos/streams/serial_stream.rb +5 -0
- data/lib/cosmos/streams/stream.rb +8 -2
- data/lib/cosmos/streams/stream_protocol.rb +1 -0
- data/lib/cosmos/streams/tcpip_client_stream.rb +37 -7
- data/lib/cosmos/streams/tcpip_socket_stream.rb +9 -6
- data/lib/cosmos/system/target.rb +3 -6
- data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +57 -48
- data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +7 -3
- data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +1 -1
- data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +7 -1
- data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +1 -2
- data/lib/cosmos/top_level.rb +22 -11
- data/lib/cosmos/utilities/message_log.rb +14 -9
- data/lib/cosmos/version.rb +5 -5
- data/spec/interfaces/cmd_tlm_server_interface_spec.rb +16 -16
- data/spec/interfaces/linc_interface_spec.rb +3 -0
- data/spec/interfaces/tcpip_client_interface_spec.rb +1 -0
- data/spec/interfaces/tcpip_server_interface_spec.rb +9 -0
- data/spec/io/json_drb_object_spec.rb +1 -1
- data/spec/io/serial_driver_spec.rb +0 -1
- data/spec/packet_logs/packet_log_writer_spec.rb +5 -3
- data/spec/packets/packet_config_spec.rb +22 -837
- data/spec/packets/packet_item_spec.rb +10 -10
- data/spec/packets/packet_spec.rb +239 -1
- data/spec/packets/parsers/format_string_parser_spec.rb +122 -0
- data/spec/packets/parsers/limits_parser_spec.rb +282 -0
- data/spec/packets/parsers/limits_response_parser_spec.rb +149 -0
- data/spec/packets/parsers/macro_parser_spec.rb +184 -0
- data/spec/packets/parsers/packet_item_parser_spec.rb +306 -0
- data/spec/packets/parsers/packet_parser_spec.rb +99 -0
- data/spec/packets/parsers/processor_parser_spec.rb +114 -0
- data/spec/packets/parsers/state_parser_spec.rb +156 -0
- data/spec/packets/structure_item_spec.rb +14 -14
- data/spec/packets/structure_spec.rb +162 -16
- data/spec/streams/fixed_stream_protocol_spec.rb +7 -4
- data/spec/streams/length_stream_protocol_spec.rb +3 -0
- data/spec/streams/preidentified_stream_protocol_spec.rb +3 -0
- data/spec/streams/serial_stream_spec.rb +12 -0
- data/spec/streams/stream_protocol_spec.rb +14 -0
- data/spec/streams/stream_spec.rb +1 -0
- data/spec/streams/tcpip_client_stream_spec.rb +3 -0
- data/spec/streams/tcpip_socket_stream_spec.rb +15 -3
- data/spec/streams/template_stream_protocol_spec.rb +5 -0
- data/spec/streams/terminated_stream_protocol_spec.rb +4 -0
- data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +21 -1
- data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +1 -1
- data/spec/tools/cmd_tlm_server/interfaces_spec.rb +1 -1
- metadata +19 -3
|
@@ -194,19 +194,19 @@ module Cosmos
|
|
|
194
194
|
it "should complain about default not matching data_type" do
|
|
195
195
|
pi = PacketItem.new("test", 0, 8, :UINT, :BIG_ENDIAN, 16)
|
|
196
196
|
pi.default = 1
|
|
197
|
-
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "
|
|
197
|
+
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "TEST: default must be an Array but is a Fixnum")
|
|
198
198
|
pi = PacketItem.new("test", 0, 8, :UINT, :BIG_ENDIAN, 16)
|
|
199
199
|
pi.default = []
|
|
200
200
|
expect { pi.check_default_and_range_data_types }.to_not raise_error
|
|
201
201
|
pi = PacketItem.new("test", 0, 32, :UINT, :BIG_ENDIAN, nil)
|
|
202
202
|
pi.default = 5.5
|
|
203
|
-
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "
|
|
203
|
+
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "TEST: default must be a Integer but is a Float")
|
|
204
204
|
pi = PacketItem.new("test", 0, 32, :UINT, :BIG_ENDIAN, nil)
|
|
205
205
|
pi.default = 5
|
|
206
206
|
expect { pi.check_default_and_range_data_types }.to_not raise_error
|
|
207
207
|
pi = PacketItem.new("test", 0, 32, :FLOAT, :BIG_ENDIAN, nil)
|
|
208
208
|
pi.default = "test"
|
|
209
|
-
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "
|
|
209
|
+
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "TEST: default must be a Float but is a String")
|
|
210
210
|
pi = PacketItem.new("test", 0, 32, :FLOAT, :BIG_ENDIAN, nil)
|
|
211
211
|
pi.default = 5
|
|
212
212
|
expect { pi.check_default_and_range_data_types }.to_not raise_error
|
|
@@ -215,13 +215,13 @@ module Cosmos
|
|
|
215
215
|
expect { pi.check_default_and_range_data_types }.to_not raise_error
|
|
216
216
|
pi = PacketItem.new("test", 0, 32, :STRING, :BIG_ENDIAN, nil)
|
|
217
217
|
pi.default = 5
|
|
218
|
-
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "
|
|
218
|
+
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "TEST: default must be a String but is a Fixnum")
|
|
219
219
|
pi = PacketItem.new("test", 0, 32, :STRING, :BIG_ENDIAN, nil)
|
|
220
220
|
pi.default = ''
|
|
221
221
|
expect { pi.check_default_and_range_data_types }.to_not raise_error
|
|
222
222
|
pi = PacketItem.new("test", 0, 32, :BLOCK, :BIG_ENDIAN, nil)
|
|
223
223
|
pi.default = 5.5
|
|
224
|
-
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "
|
|
224
|
+
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "TEST: default must be a String but is a Float")
|
|
225
225
|
pi = PacketItem.new("test", 0, 32, :BLOCK, :BIG_ENDIAN, nil)
|
|
226
226
|
pi.default = ''
|
|
227
227
|
expect { pi.check_default_and_range_data_types }.to_not raise_error
|
|
@@ -231,17 +231,17 @@ module Cosmos
|
|
|
231
231
|
pi = PacketItem.new("test", 0, 32, :UINT, :BIG_ENDIAN, nil)
|
|
232
232
|
pi.default = 5
|
|
233
233
|
pi.range = (5.5..10)
|
|
234
|
-
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "
|
|
234
|
+
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "TEST: minimum must be a Integer but is a Float")
|
|
235
235
|
pi.range = (5..10.5)
|
|
236
|
-
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "
|
|
236
|
+
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "TEST: maximum must be a Integer but is a Float")
|
|
237
237
|
pi = PacketItem.new("test", 0, 32, :FLOAT, :BIG_ENDIAN, nil)
|
|
238
238
|
pi.default = 5.5
|
|
239
239
|
pi.range = (5..10)
|
|
240
240
|
expect { pi.check_default_and_range_data_types }.to_not raise_error
|
|
241
241
|
pi.range = ('a'..'z')
|
|
242
|
-
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "
|
|
242
|
+
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "TEST: minimum must be a Float but is a String")
|
|
243
243
|
pi.range = (1.0..Rational(2))
|
|
244
|
-
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "
|
|
244
|
+
expect { pi.check_default_and_range_data_types }.to raise_error(ArgumentError, "TEST: maximum must be a Float but is a Rational")
|
|
245
245
|
end
|
|
246
246
|
end
|
|
247
247
|
|
|
@@ -349,7 +349,7 @@ module Cosmos
|
|
|
349
349
|
hash.keys.length.should eql 22
|
|
350
350
|
# Check the values from StructureItem
|
|
351
351
|
hash.keys.should include('name','bit_offset','bit_size','data_type','endianness','array_size','overflow')
|
|
352
|
-
hash["name"].should eql "
|
|
352
|
+
hash["name"].should eql "TEST"
|
|
353
353
|
hash["bit_offset"].should eql 0
|
|
354
354
|
hash["bit_size"].should eql 32
|
|
355
355
|
hash["data_type"].should eql :UINT
|
data/spec/packets/packet_spec.rb
CHANGED
|
@@ -91,6 +91,26 @@ module Cosmos
|
|
|
91
91
|
end
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
+
describe "set_received_time_fast" do
|
|
95
|
+
it "sets the received_time to a Time" do
|
|
96
|
+
p = Packet.new("tgt", "pkt")
|
|
97
|
+
t = Time.now
|
|
98
|
+
p.set_received_time_fast(t)
|
|
99
|
+
expect(p.received_time).to eql t
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "should set received_time to nil" do
|
|
103
|
+
p = Packet.new("tgt","pkt")
|
|
104
|
+
p.received_time = nil
|
|
105
|
+
p.received_time.should be_nil
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "should complain about non Time received_times" do
|
|
109
|
+
p = Packet.new("tgt","pkt")
|
|
110
|
+
expect {p.received_time = "1pm" }.to raise_error(ArgumentError, "received_time must be a Time but is a String")
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
94
114
|
describe "received_time=" do
|
|
95
115
|
it "should set the received_time to a Time" do
|
|
96
116
|
p = Packet.new("tgt", "pkt")
|
|
@@ -219,6 +239,42 @@ module Cosmos
|
|
|
219
239
|
end
|
|
220
240
|
end
|
|
221
241
|
|
|
242
|
+
describe "define" do
|
|
243
|
+
it "adds a PacketItem to a packet" do
|
|
244
|
+
p = Packet.new("tgt","pkt")
|
|
245
|
+
rc = GenericConversion.new("value / 2")
|
|
246
|
+
wc = GenericConversion.new("value * 2")
|
|
247
|
+
pi = PacketItem.new("item1",0,32,:FLOAT,:BIG_ENDIAN,nil,:ERROR)
|
|
248
|
+
pi.format_string = "%5.1f"
|
|
249
|
+
pi.read_conversion = rc
|
|
250
|
+
pi.write_conversion = wc
|
|
251
|
+
pi.state_colors = {'RED'=>0}
|
|
252
|
+
pi.id_value = 5
|
|
253
|
+
p.define(pi)
|
|
254
|
+
i = p.get_item("ITEM1")
|
|
255
|
+
i.format_string.should eql "%5.1f"
|
|
256
|
+
i.read_conversion.to_s.should eql rc.to_s
|
|
257
|
+
i.write_conversion.to_s.should eql wc.to_s
|
|
258
|
+
i.id_value.should eql 5.0
|
|
259
|
+
expect(p.id_items.length).to eq 1
|
|
260
|
+
expect(p.id_items[0].name).to eq 'ITEM1'
|
|
261
|
+
expect(p.limits_items[0].name).to eq 'ITEM1'
|
|
262
|
+
p.defined_length.should eql 4
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
it "allows PacketItems to be defined on top of each other" do
|
|
266
|
+
p = Packet.new("tgt","pkt")
|
|
267
|
+
pi = PacketItem.new("item1",0,8,:UINT,:BIG_ENDIAN)
|
|
268
|
+
p.define(pi)
|
|
269
|
+
pi = PacketItem.new("item2",0,32,:UINT,:BIG_ENDIAN)
|
|
270
|
+
p.define(pi)
|
|
271
|
+
p.defined_length.should eql 4
|
|
272
|
+
buffer = "\x01\x02\x03\x04"
|
|
273
|
+
p.read_item(p.get_item("item1"), :RAW, buffer).should eql 1
|
|
274
|
+
p.read_item(p.get_item("item2"), :RAW, buffer).should eql 0x1020304
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
222
278
|
describe "append_item" do
|
|
223
279
|
it "should take a format_string, read_conversion, write_conversion, and id_value" do
|
|
224
280
|
p = Packet.new("tgt","pkt")
|
|
@@ -243,6 +299,41 @@ module Cosmos
|
|
|
243
299
|
end
|
|
244
300
|
end
|
|
245
301
|
|
|
302
|
+
describe "append" do
|
|
303
|
+
it "adds a PacketItem to the end of a packet" do
|
|
304
|
+
p = Packet.new("tgt","pkt")
|
|
305
|
+
rc = GenericConversion.new("value / 2")
|
|
306
|
+
wc = GenericConversion.new("value * 2")
|
|
307
|
+
pi = PacketItem.new("item1",0,32,:FLOAT,:BIG_ENDIAN,nil,:ERROR)
|
|
308
|
+
pi.format_string = "%5.1f"
|
|
309
|
+
pi.read_conversion = rc
|
|
310
|
+
pi.write_conversion = wc
|
|
311
|
+
pi.limits.values = {:DEFAULT => [0, 1, 2, 3]}
|
|
312
|
+
pi.id_value = 5
|
|
313
|
+
p.append(pi)
|
|
314
|
+
i = p.get_item("ITEM1")
|
|
315
|
+
i.format_string.should eql "%5.1f"
|
|
316
|
+
i.read_conversion.to_s.should eql rc.to_s
|
|
317
|
+
i.write_conversion.to_s.should eql wc.to_s
|
|
318
|
+
i.id_value.should eql 5.0
|
|
319
|
+
expect(p.id_items.length).to eq 1
|
|
320
|
+
expect(p.id_items[0].name).to eq 'ITEM1'
|
|
321
|
+
expect(p.limits_items[0].name).to eq 'ITEM1'
|
|
322
|
+
p.defined_length.should eql 4
|
|
323
|
+
|
|
324
|
+
pi = PacketItem.new("item2",0,32,:FLOAT,:BIG_ENDIAN,nil,:ERROR)
|
|
325
|
+
p.append(pi)
|
|
326
|
+
i = p.get_item("ITEM2")
|
|
327
|
+
expect(i.bit_offset).to be 32 # offset updated inside the PacketItem
|
|
328
|
+
expect(i.format_string).to be nil
|
|
329
|
+
expect(i.read_conversion).to be nil
|
|
330
|
+
expect(i.write_conversion).to be nil
|
|
331
|
+
expect(i.id_value).to be nil
|
|
332
|
+
expect(p.id_items.length).to eq 1
|
|
333
|
+
p.defined_length.should eql 8
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
246
337
|
describe "get_item" do
|
|
247
338
|
it "should complain if an item doesn't exist" do
|
|
248
339
|
p = Packet.new("tgt","pkt")
|
|
@@ -383,6 +474,23 @@ module Cosmos
|
|
|
383
474
|
@buffer.should eql "\x05\x06\x07\x08"
|
|
384
475
|
end
|
|
385
476
|
|
|
477
|
+
it "clears the read cache" do
|
|
478
|
+
@p.append_item("item",8,:UINT)
|
|
479
|
+
i = @p.get_item("ITEM")
|
|
480
|
+
@p.buffer = "\x04"
|
|
481
|
+
cache = p.instance_variable_get(:@read_conversion_cache)
|
|
482
|
+
i.read_conversion = GenericConversion.new("value / 2")
|
|
483
|
+
expect(cache).to be nil
|
|
484
|
+
expect(@p.read("ITEM")).to be 2
|
|
485
|
+
cache = @p.instance_variable_get(:@read_conversion_cache)
|
|
486
|
+
expect(cache[i]).to be 2
|
|
487
|
+
@p.write("ITEM", 0x08, :RAW)
|
|
488
|
+
@p.buffer.should eql "\x08"
|
|
489
|
+
expect(cache[i]).to be nil
|
|
490
|
+
expect(@p.read("ITEM")).to be 4
|
|
491
|
+
expect(cache[i]).to be 4
|
|
492
|
+
end
|
|
493
|
+
|
|
386
494
|
it "should write the CONVERTED value" do
|
|
387
495
|
@p.append_item("item",8,:UINT)
|
|
388
496
|
i = @p.get_item("ITEM")
|
|
@@ -409,6 +517,7 @@ module Cosmos
|
|
|
409
517
|
@buffer.should eql "\x01\x00\x00\x00"
|
|
410
518
|
@p.write_item(i, "FALSE", :CONVERTED, @buffer)
|
|
411
519
|
@buffer.should eql "\x02\x00\x00\x00"
|
|
520
|
+
expect { @p.write_item(i, "BLAH", :CONVERTED, @buffer) }.to raise_error(RuntimeError, "Unknown state BLAH for ITEM")
|
|
412
521
|
i.write_conversion = GenericConversion.new("value / 2")
|
|
413
522
|
@p.write("ITEM", 4, :CONVERTED, @buffer)
|
|
414
523
|
@buffer.should eql "\x02\x00\x00\x00"
|
|
@@ -502,6 +611,113 @@ module Cosmos
|
|
|
502
611
|
end
|
|
503
612
|
end
|
|
504
613
|
|
|
614
|
+
describe "check_bit_offsets" do
|
|
615
|
+
it "should complain about overlapping items" do
|
|
616
|
+
p = Packet.new("tgt1","pkt1")
|
|
617
|
+
p.define_item("item1",0,8,:UINT)
|
|
618
|
+
p.define_item("item2",0,8,:UINT)
|
|
619
|
+
expect(p.check_bit_offsets[0]).to eql "Bit definition overlap at bit offset 0 for packet TGT1 PKT1 items ITEM2 and ITEM1"
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
it "should not complain with non-overlapping negative offsets" do
|
|
623
|
+
p = Packet.new("tgt1","pkt1")
|
|
624
|
+
p.define_item("item1",0,8,:UINT)
|
|
625
|
+
p.define_item("item2",8,-16,:BLOCK)
|
|
626
|
+
p.define_item("item3",-16,16,:UINT)
|
|
627
|
+
expect(p.check_bit_offsets[0]).to be_nil
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
it "should complain with overlapping negative offsets" do
|
|
631
|
+
p = Packet.new("tgt1","pkt1")
|
|
632
|
+
p.define_item("item1",0,8,:UINT)
|
|
633
|
+
p.define_item("item2",8,-16,:BLOCK)
|
|
634
|
+
p.define_item("item3",-17,16,:UINT)
|
|
635
|
+
expect(p.check_bit_offsets[0]).to eql "Bit definition overlap at bit offset -17 for packet TGT1 PKT1 items ITEM3 and ITEM2"
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
it "should complain about intersecting items" do
|
|
639
|
+
p = Packet.new("tgt1","pkt1")
|
|
640
|
+
p.define_item("item1",0,32,:UINT)
|
|
641
|
+
p.define_item("item2",16,32,:UINT)
|
|
642
|
+
expect(p.check_bit_offsets[0]).to eql "Bit definition overlap at bit offset 16 for packet TGT1 PKT1 items ITEM2 and ITEM1"
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
it "should complain about array overlapping items" do
|
|
646
|
+
p = Packet.new("tgt1","pkt1")
|
|
647
|
+
p.define_item("item1",0,8,:UINT,32)
|
|
648
|
+
p.define_item("item2",0,8,:UINT,32)
|
|
649
|
+
expect(p.check_bit_offsets[0]).to eql "Bit definition overlap at bit offset 0 for packet TGT1 PKT1 items ITEM2 and ITEM1"
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
it "should not complain with array non-overlapping negative offsets" do
|
|
653
|
+
p = Packet.new("tgt1","pkt1")
|
|
654
|
+
p.define_item("item1",0,8,:UINT)
|
|
655
|
+
p.define_item("item2",8,8,:INT,-16)
|
|
656
|
+
p.define_item("item3",-16,16,:UINT)
|
|
657
|
+
expect(p.check_bit_offsets[0]).to be_nil
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
it "should complain with array overlapping negative offsets" do
|
|
661
|
+
p = Packet.new("tgt1","pkt1")
|
|
662
|
+
p.define_item("item1",0,8,:UINT)
|
|
663
|
+
p.define_item("item2",8,8,:INT,-16)
|
|
664
|
+
p.define_item("item3",-17,16,:UINT)
|
|
665
|
+
expect(p.check_bit_offsets[0]).to eql "Bit definition overlap at bit offset -17 for packet TGT1 PKT1 items ITEM3 and ITEM2"
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
it "should complain about array intersecting items" do
|
|
669
|
+
p = Packet.new("tgt1","pkt1")
|
|
670
|
+
p.define_item("item1",0,8,:UINT,32)
|
|
671
|
+
p.define_item("item2",16,8,:UINT,32)
|
|
672
|
+
expect(p.check_bit_offsets[0]).to eql "Bit definition overlap at bit offset 16 for packet TGT1 PKT1 items ITEM2 and ITEM1"
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
it "should not complain about nonoverlapping big endian bitfields" do
|
|
676
|
+
p = Packet.new("tgt1","pkt1")
|
|
677
|
+
p.define_item("item1",0,12,:UINT,nil,:BIG_ENDIAN)
|
|
678
|
+
p.define_item("item2",12,4,:UINT,nil,:BIG_ENDIAN)
|
|
679
|
+
p.define_item("item3",16,16,:UINT,nil,:BIG_ENDIAN)
|
|
680
|
+
expect(p.check_bit_offsets[0]).to be_nil
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
it "should complain about overlapping big endian bitfields" do
|
|
684
|
+
p = Packet.new("tgt1","pkt1")
|
|
685
|
+
p.define_item("item1",0,12,:UINT,nil,:BIG_ENDIAN)
|
|
686
|
+
p.define_item("item2",10,6,:UINT,nil,:BIG_ENDIAN)
|
|
687
|
+
p.define_item("item3",16,16,:UINT,nil,:BIG_ENDIAN)
|
|
688
|
+
expect(p.check_bit_offsets[0]).to eql "Bit definition overlap at bit offset 10 for packet TGT1 PKT1 items ITEM2 and ITEM1"
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
it "should not complain about nonoverlapping little endian bitfields" do
|
|
692
|
+
p = Packet.new("tgt1","pkt1")
|
|
693
|
+
# bit offset in LITTLE_ENDIAN refers to MSB
|
|
694
|
+
p.define_item("item1",12,12,:UINT,nil,:LITTLE_ENDIAN)
|
|
695
|
+
p.define_item("item2",16,16,:UINT,nil,:LITTLE_ENDIAN)
|
|
696
|
+
expect(p.check_bit_offsets[0]).to be_nil
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
it "should complain about overlapping little endian bitfields" do
|
|
700
|
+
p = Packet.new("tgt1","pkt1")
|
|
701
|
+
# bit offset in LITTLE_ENDIAN refers to MSB
|
|
702
|
+
p.define_item("item1",12,12,:UINT,nil,:LITTLE_ENDIAN)
|
|
703
|
+
p.define_item("item2",10,10,:UINT,nil,:LITTLE_ENDIAN)
|
|
704
|
+
expect(p.check_bit_offsets[0]).to eql "Bit definition overlap at bit offset 12 for packet TGT1 PKT1 items ITEM1 and ITEM2"
|
|
705
|
+
end
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
describe "id_items" do
|
|
709
|
+
it "returns an array of the identifying items" do
|
|
710
|
+
p = Packet.new("tgt","pkt")
|
|
711
|
+
p.define_item("item1",0,32,:FLOAT,nil,:BIG_ENDIAN,:ERROR,"%5.1f",nil,nil,nil)
|
|
712
|
+
p.define_item("item2",0,32,:FLOAT,nil,:BIG_ENDIAN,:ERROR,"%5.1f",nil,nil,5)
|
|
713
|
+
p.define_item("item3",0,32,:FLOAT,nil,:BIG_ENDIAN,:ERROR,"%5.1f",nil,nil,nil)
|
|
714
|
+
p.define_item("item4",0,32,:FLOAT,nil,:BIG_ENDIAN,:ERROR,"%5.1f",nil,nil,6)
|
|
715
|
+
expect(p.id_items).to be_a Array
|
|
716
|
+
expect(p.id_items[0].name).to eq "ITEM2"
|
|
717
|
+
expect(p.id_items[1].name).to eq "ITEM4"
|
|
718
|
+
end
|
|
719
|
+
end
|
|
720
|
+
|
|
505
721
|
describe "identify?" do
|
|
506
722
|
it "should identify a buffer based on id_items" do
|
|
507
723
|
p = Packet.new("tgt","pkt")
|
|
@@ -1034,14 +1250,23 @@ module Cosmos
|
|
|
1034
1250
|
describe "clone" do
|
|
1035
1251
|
it "should duplicate the packet" do
|
|
1036
1252
|
p = Packet.new("tgt","pkt")
|
|
1253
|
+
p.processors['processor'] = Processor.new
|
|
1254
|
+
p.processors['processor'].name = "TestProcessor"
|
|
1037
1255
|
p2 = p.clone
|
|
1256
|
+
# No comparison operator
|
|
1257
|
+
# expect(p).to eql p2
|
|
1258
|
+
expect(p).to_not be p2
|
|
1038
1259
|
p2.target_name.should eql "TGT"
|
|
1039
1260
|
p2.packet_name.should eql "PKT"
|
|
1261
|
+
# No comparison operator
|
|
1262
|
+
# expect(p2.processors['processor']).to eql p.processors['processor']
|
|
1263
|
+
expect(p2.processors['processor']).to_not be p.processors['processor']
|
|
1264
|
+
expect(p2.processors['processor'].name).to eql p.processors['processor'].name
|
|
1040
1265
|
end
|
|
1041
1266
|
end
|
|
1042
1267
|
|
|
1043
1268
|
describe "reset" do
|
|
1044
|
-
it "
|
|
1269
|
+
it "resets the received_time and received_count" do
|
|
1045
1270
|
p = Packet.new("tgt","pkt")
|
|
1046
1271
|
p.processors['processor'] = double("reset", :reset => true)
|
|
1047
1272
|
p.received_time = Time.now
|
|
@@ -1050,6 +1275,19 @@ module Cosmos
|
|
|
1050
1275
|
p.received_time.should eql nil
|
|
1051
1276
|
p.received_count.should eql 0
|
|
1052
1277
|
end
|
|
1278
|
+
|
|
1279
|
+
it "clears the read conversion cache" do
|
|
1280
|
+
p = Packet.new("tgt","pkt")
|
|
1281
|
+
p.append_item("item",8,:UINT)
|
|
1282
|
+
i = p.get_item("ITEM")
|
|
1283
|
+
p.buffer = "\x04"
|
|
1284
|
+
i.read_conversion = GenericConversion.new("value / 2")
|
|
1285
|
+
expect(p.read("ITEM")).to be 2
|
|
1286
|
+
cache = p.instance_variable_get(:@read_conversion_cache)
|
|
1287
|
+
expect(cache[i]).to be 2
|
|
1288
|
+
p.reset
|
|
1289
|
+
expect(cache).to be_empty
|
|
1290
|
+
end
|
|
1053
1291
|
end
|
|
1054
1292
|
|
|
1055
1293
|
end # describe Packet
|
|
@@ -0,0 +1,122 @@
|
|
|
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/format_string_parser'
|
|
15
|
+
require 'tempfile'
|
|
16
|
+
|
|
17
|
+
module Cosmos
|
|
18
|
+
|
|
19
|
+
describe PacketConfig do
|
|
20
|
+
|
|
21
|
+
describe "process_file" 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
|
+
# Check for missing ITEM definitions
|
|
28
|
+
tf = Tempfile.new('unittest')
|
|
29
|
+
tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
|
|
30
|
+
tf.puts ' FORMAT_STRING'
|
|
31
|
+
tf.close
|
|
32
|
+
expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "No current item for FORMAT_STRING")
|
|
33
|
+
tf.unlink
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should complain if there are not enough parameters" do
|
|
37
|
+
tf = Tempfile.new('unittest')
|
|
38
|
+
tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
|
|
39
|
+
tf.puts 'ITEM myitem 0 8 UINT "Test Item"'
|
|
40
|
+
tf.puts ' FORMAT_STRING'
|
|
41
|
+
tf.close
|
|
42
|
+
expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Not enough parameters for FORMAT_STRING/)
|
|
43
|
+
tf.unlink
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should complain if there are too many parameters" do
|
|
47
|
+
tf = Tempfile.new('unittest')
|
|
48
|
+
tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
|
|
49
|
+
tf.puts 'ITEM myitem 0 8 UINT "Test Item"'
|
|
50
|
+
tf.puts "FORMAT_STRING '0x%x' extra"
|
|
51
|
+
tf.close
|
|
52
|
+
expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Too many parameters for FORMAT_STRING/)
|
|
53
|
+
tf.unlink
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should complain about invalid format strings" do
|
|
57
|
+
tf = Tempfile.new('unittest')
|
|
58
|
+
tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
|
|
59
|
+
tf.puts ' ITEM item1 0 8 INT'
|
|
60
|
+
tf.puts ' FORMAT_STRING "%*s"'
|
|
61
|
+
tf.close
|
|
62
|
+
expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid FORMAT_STRING specified for type INT: %*s")
|
|
63
|
+
tf.unlink
|
|
64
|
+
|
|
65
|
+
tf = Tempfile.new('unittest')
|
|
66
|
+
tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
|
|
67
|
+
tf.puts ' ITEM item1 0 8 STRING'
|
|
68
|
+
tf.puts ' FORMAT_STRING "%d"'
|
|
69
|
+
tf.close
|
|
70
|
+
expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "Invalid FORMAT_STRING specified for type STRING: %d")
|
|
71
|
+
tf.unlink
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should format integers" do
|
|
75
|
+
tf = Tempfile.new('unittest')
|
|
76
|
+
tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
|
|
77
|
+
tf.puts ' ITEM item1 0 8 INT'
|
|
78
|
+
tf.puts ' FORMAT_STRING "d%d"'
|
|
79
|
+
tf.puts ' ITEM item2 0 8 UINT'
|
|
80
|
+
tf.puts ' FORMAT_STRING "u%u"'
|
|
81
|
+
tf.puts ' ITEM item3 0 8 UINT'
|
|
82
|
+
tf.puts ' FORMAT_STRING "0x%x"'
|
|
83
|
+
tf.close
|
|
84
|
+
@pc.process_file(tf.path, "TGT1")
|
|
85
|
+
@pc.telemetry["TGT1"]["PKT1"].buffer = "\x0a\x0b\x0c"
|
|
86
|
+
@pc.telemetry["TGT1"]["PKT1"].read("ITEM1",:FORMATTED).should eql "d10"
|
|
87
|
+
@pc.telemetry["TGT1"]["PKT1"].read("ITEM2",:FORMATTED).should eql "u10"
|
|
88
|
+
@pc.telemetry["TGT1"]["PKT1"].read("ITEM3",:FORMATTED).should eql "0xa"
|
|
89
|
+
tf.unlink
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "should format floats" do
|
|
93
|
+
tf = Tempfile.new('unittest')
|
|
94
|
+
tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
|
|
95
|
+
tf.puts ' ITEM item1 0 32 FLOAT'
|
|
96
|
+
tf.puts ' FORMAT_STRING "%3.3f"'
|
|
97
|
+
tf.close
|
|
98
|
+
@pc.process_file(tf.path, "TGT1")
|
|
99
|
+
@pc.telemetry["TGT1"]["PKT1"].write("ITEM1",12345.12345)
|
|
100
|
+
@pc.telemetry["TGT1"]["PKT1"].read("ITEM1",:FORMATTED).should eql "12345.123"
|
|
101
|
+
tf.unlink
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "should format strings and blocks" do
|
|
105
|
+
tf = Tempfile.new('unittest')
|
|
106
|
+
tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Packet"'
|
|
107
|
+
tf.puts ' ITEM item1 0 32 STRING'
|
|
108
|
+
tf.puts ' FORMAT_STRING "String: %s"'
|
|
109
|
+
tf.puts ' ITEM item2 0 32 BLOCK'
|
|
110
|
+
tf.puts ' FORMAT_STRING "Block: %s"'
|
|
111
|
+
tf.close
|
|
112
|
+
@pc.process_file(tf.path, "TGT1")
|
|
113
|
+
@pc.telemetry["TGT1"]["PKT1"].write("ITEM1","HI")
|
|
114
|
+
@pc.telemetry["TGT1"]["PKT1"].read("ITEM1",:FORMATTED).should eql "String: HI"
|
|
115
|
+
@pc.telemetry["TGT1"]["PKT1"].write("ITEM2","\x00\x01\x02\x03")
|
|
116
|
+
@pc.telemetry["TGT1"]["PKT1"].read("ITEM2",:FORMATTED).should eql "Block: \x00\x01\x02\x03"
|
|
117
|
+
tf.unlink
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
end
|