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
@@ -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, "test: default must be an Array but is a Fixnum")
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, "test: default must be a Integer but is a Float")
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, "test: default must be a Float but is a String")
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, "test: default must be a String but is a Fixnum")
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, "test: default must be a String but is a Float")
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, "test: minimum must be a Integer but is a Float")
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, "test: maximum must be a Integer but is a Float")
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, "test: minimum must be a Float but is a String")
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, "test: maximum must be a Float but is a Rational")
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 "test"
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
@@ -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 "should reset the packet" do
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