cosmos 3.1.2 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
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,156 @@
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/state_parser'
15
+ require 'tempfile'
16
+
17
+ module Cosmos
18
+
19
+ describe StateParser 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 'STATE'
31
+ tf.close
32
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, "No current item for STATE")
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 'STATE'
41
+ tf.close
42
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Not enough parameters for STATE/)
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 'STATE mystate 0 RED extra'
51
+ tf.close
52
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Too many parameters for STATE/)
53
+ tf.unlink
54
+ end
55
+
56
+ it "should support STRING items" do
57
+ tf = Tempfile.new('unittest')
58
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Description"'
59
+ tf.puts ' APPEND_ITEM item1 128 STRING "state item"'
60
+ tf.puts ' STATE FALSE "FALSE STRING"'
61
+ tf.puts ' STATE TRUE "TRUE STRING"'
62
+ tf.close
63
+ @pc.process_file(tf.path, "TGT1")
64
+ @pc.telemetry["TGT1"]["PKT1"].write("ITEM1", "TRUE STRING")
65
+ @pc.telemetry["TGT1"]["PKT1"].read("ITEM1").should eql "TRUE"
66
+ @pc.telemetry["TGT1"]["PKT1"].write("ITEM1", "FALSE STRING")
67
+ @pc.telemetry["TGT1"]["PKT1"].read("ITEM1").should eql "FALSE"
68
+ tf.unlink
69
+ end
70
+
71
+ it "should warn about duplicate states and replace the duplicate" do
72
+ tf = Tempfile.new('unittest')
73
+ tf.puts 'COMMAND tgt1 pkt1 LITTLE_ENDIAN "Description"'
74
+ tf.puts ' APPEND_PARAMETER item1 8 UINT 0 2 0 "state item"'
75
+ tf.puts ' STATE FALSE 0'
76
+ tf.puts ' STATE TRUE 1'
77
+ tf.puts ' STATE FALSE 2'
78
+ tf.close
79
+ @pc.process_file(tf.path, "TGT1")
80
+ @pc.warnings.should include("Duplicate state defined on line 5: STATE FALSE 2")
81
+ @pc.commands["TGT1"]["PKT1"].buffer = "\x00"
82
+ @pc.commands["TGT1"]["PKT1"].read("ITEM1").should eql 0
83
+ @pc.commands["TGT1"]["PKT1"].buffer = "\x02"
84
+ @pc.commands["TGT1"]["PKT1"].read("ITEM1").should eql "FALSE"
85
+ tf.unlink
86
+ end
87
+
88
+ context "with telemetry" do
89
+ it "should only allow GREEN YELLOW or RED" do
90
+ tf = Tempfile.new('unittest')
91
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Description"'
92
+ tf.puts ' APPEND_ITEM item1 8 UINT "state item"'
93
+ tf.puts ' STATE WORST 1 ORANGE'
94
+ tf.close
95
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /Invalid state color ORANGE/)
96
+ tf.unlink
97
+ end
98
+
99
+ it "should record the state values and colors" do
100
+ tf = Tempfile.new('unittest')
101
+ tf.puts 'TELEMETRY tgt1 pkt1 LITTLE_ENDIAN "Description"'
102
+ tf.puts ' APPEND_ITEM item1 8 UINT "state item"'
103
+ tf.puts ' STATE STATE1 1 RED'
104
+ tf.puts ' STATE STATE2 2 YELLOW'
105
+ tf.puts ' STATE STATE3 3 GREEN'
106
+ tf.puts ' STATE STATE4 4'
107
+ tf.close
108
+ @pc.process_file(tf.path, "TGT1")
109
+ index = 1
110
+ colors = [:RED, :YELLOW, :GREEN]
111
+ @pc.telemetry["TGT1"]["PKT1"].items["ITEM1"].states.each do |name,val|
112
+ name.should eql "STATE#{index}"
113
+ val.should eql index
114
+ @pc.telemetry["TGT1"]["PKT1"].items["ITEM1"].state_colors[name].should eql colors[index - 1]
115
+
116
+ index += 1
117
+ end
118
+ @pc.telemetry["TGT1"]["PKT1"].limits_items.should eql [@pc.telemetry["TGT1"]["PKT1"].items["ITEM1"]]
119
+ tf.unlink
120
+ end
121
+ end
122
+
123
+ context "with command" do
124
+ it "should only allow HAZARDOUS as the third param" do
125
+ tf = Tempfile.new('unittest')
126
+ tf.puts 'COMMAND tgt1 pkt1 LITTLE_ENDIAN "Description"'
127
+ tf.puts ' APPEND_PARAMETER item1 8 UINT 0 0 0'
128
+ tf.puts ' STATE WORST 0 RED'
129
+ tf.close
130
+ expect { @pc.process_file(tf.path, "TGT1") }.to raise_error(ConfigParser::Error, /HAZARDOUS expected as third parameter/)
131
+ tf.unlink
132
+ end
133
+
134
+ it "should take HAZARDOUS and an optional description" do
135
+ tf = Tempfile.new('unittest')
136
+ tf.puts 'COMMAND tgt1 pkt1 LITTLE_ENDIAN "Description"'
137
+ tf.puts ' APPEND_PARAMETER item1 8 UINT 1 3 1'
138
+ tf.puts ' STATE GOOD 1'
139
+ tf.puts ' STATE BAD 2 HAZARDOUS'
140
+ tf.puts ' STATE WORST 3 HAZARDOUS "Hazardous description"'
141
+ tf.close
142
+ @pc.process_file(tf.path, "TGT1")
143
+ @pc.commands["TGT1"]["PKT1"].buffer = "\x01"
144
+ @pc.commands["TGT1"]["PKT1"].check_limits
145
+ @pc.commands["TGT1"]["PKT1"].items["ITEM1"].hazardous["GOOD"].should be_nil
146
+ @pc.commands["TGT1"]["PKT1"].items["ITEM1"].hazardous["BAD"].should_not be_nil
147
+ @pc.commands["TGT1"]["PKT1"].items["ITEM1"].hazardous["WORST"].should_not be_nil
148
+ @pc.commands["TGT1"]["PKT1"].items["ITEM1"].hazardous["WORST"].should eql "Hazardous description"
149
+ @pc.commands["TGT1"]["PKT1"].limits_items.should be_empty
150
+ tf.unlink
151
+ end
152
+ end
153
+
154
+ end
155
+ end
156
+ end
@@ -18,7 +18,7 @@ module Cosmos
18
18
 
19
19
  describe "name=" do
20
20
  it "should create new structure items" do
21
- StructureItem.new("test", 0, 8, :UINT, :BIG_ENDIAN, nil).name.should eql "test"
21
+ StructureItem.new("test", 0, 8, :UINT, :BIG_ENDIAN, nil).name.should eql "TEST"
22
22
  end
23
23
 
24
24
  it "should complain about non String names" do
@@ -38,7 +38,7 @@ module Cosmos
38
38
  end
39
39
 
40
40
  it "should complain about bad endianness" do
41
- expect { StructureItem.new("test", 0, 8, :UINT, :BLAH, nil) }.to raise_error(ArgumentError, "test: unknown endianness: BLAH - Must be :BIG_ENDIAN or :LITTLE_ENDIAN")
41
+ expect { StructureItem.new("test", 0, 8, :UINT, :BLAH, nil) }.to raise_error(ArgumentError, "TEST: unknown endianness: BLAH - Must be :BIG_ENDIAN or :LITTLE_ENDIAN")
42
42
  end
43
43
  end
44
44
 
@@ -51,7 +51,7 @@ module Cosmos
51
51
  end
52
52
 
53
53
  it "should complain about bad data types" do
54
- expect { StructureItem.new("test", 0, 0, :UNKNOWN, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "test: unknown data_type: UNKNOWN - Must be :INT, :UINT, :FLOAT, :STRING, :BLOCK, or :DERIVED")
54
+ expect { StructureItem.new("test", 0, 0, :UNKNOWN, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "TEST: unknown data_type: UNKNOWN - Must be :INT, :UINT, :FLOAT, :STRING, :BLOCK, or :DERIVED")
55
55
  end
56
56
  end
57
57
 
@@ -63,39 +63,39 @@ module Cosmos
63
63
  end
64
64
 
65
65
  it "should complain about bad overflow types" do
66
- expect { StructureItem.new("test", 0, 32, :INT, :BIG_ENDIAN, nil, :UNKNOWN) }.to raise_error(ArgumentError, "test: unknown overflow type: UNKNOWN - Must be :ERROR, :ERROR_ALLOW_HEX, :TRUNCATE, or :SATURATE")
66
+ expect { StructureItem.new("test", 0, 32, :INT, :BIG_ENDIAN, nil, :UNKNOWN) }.to raise_error(ArgumentError, "TEST: unknown overflow type: UNKNOWN - Must be :ERROR, :ERROR_ALLOW_HEX, :TRUNCATE, or :SATURATE")
67
67
  end
68
68
  end
69
69
 
70
70
  describe "bit_offset=" do
71
71
  it "should compain about bad bit offsets types" do
72
- expect { StructureItem.new("test", nil, 8, :UINT, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "test: bit_offset must be a Fixnum")
72
+ expect { StructureItem.new("test", nil, 8, :UINT, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "TEST: bit_offset must be a Fixnum")
73
73
  end
74
74
 
75
75
  it "should complain about unaligned bit offsets" do
76
76
  %w(FLOAT STRING BLOCK).each do |type|
77
- expect { StructureItem.new("test", 1, 32, type.to_sym, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "test: bit_offset for :FLOAT, :STRING, and :BLOCK items must be byte aligned")
77
+ expect { StructureItem.new("test", 1, 32, type.to_sym, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "TEST: bit_offset for :FLOAT, :STRING, and :BLOCK items must be byte aligned")
78
78
  end
79
79
  end
80
80
 
81
81
  it "should complain about non zero DERIVED bit offsets" do
82
- expect { StructureItem.new("test", 8, 0, :DERIVED, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "test: DERIVED items must have bit_offset of zero")
82
+ expect { StructureItem.new("test", 8, 0, :DERIVED, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "TEST: DERIVED items must have bit_offset of zero")
83
83
  end
84
84
  end
85
85
 
86
86
  describe "bit_size=" do
87
87
  it "should complain about bad bit sizes types" do
88
- expect { StructureItem.new("test", 0, nil, :UINT, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "test: bit_size must be a Fixnum")
88
+ expect { StructureItem.new("test", 0, nil, :UINT, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "TEST: bit_size must be a Fixnum")
89
89
  end
90
90
 
91
91
  it "should complain about 0 size INT, UINT, and FLOAT" do
92
92
  %w(INT UINT FLOAT).each do |type|
93
- expect { StructureItem.new("test", 0, 0, type.to_sym, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "test: bit_size cannot be negative or zero for :INT, :UINT, and :FLOAT items: 0")
93
+ expect { StructureItem.new("test", 0, 0, type.to_sym, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "TEST: bit_size cannot be negative or zero for :INT, :UINT, and :FLOAT items: 0")
94
94
  end
95
95
  end
96
96
 
97
97
  it "should complain about bad float bit sizes" do
98
- expect { StructureItem.new("test", 0, 8, :FLOAT, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "test: bit_size for FLOAT items must be 32 or 64. Given: 8")
98
+ expect { StructureItem.new("test", 0, 8, :FLOAT, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "TEST: bit_size for FLOAT items must be 32 or 64. Given: 8")
99
99
  end
100
100
 
101
101
  it "should create 32 and 64 bit floats" do
@@ -104,17 +104,17 @@ module Cosmos
104
104
  end
105
105
 
106
106
  it "should complain about non zero DERIVED bit sizes" do
107
- expect { StructureItem.new("test", 0, 8, :DERIVED, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "test: DERIVED items must have bit_size of zero")
107
+ expect { StructureItem.new("test", 0, 8, :DERIVED, :BIG_ENDIAN, nil) }.to raise_error(ArgumentError, "TEST: DERIVED items must have bit_size of zero")
108
108
  end
109
109
  end
110
110
 
111
111
  describe "array_size=" do
112
112
  it "should complain about bad array size types" do
113
- expect { StructureItem.new("test", 0, 8, :UINT, :BIG_ENDIAN, "") }.to raise_error(ArgumentError, "test: array_size must be a Fixnum")
113
+ expect { StructureItem.new("test", 0, 8, :UINT, :BIG_ENDIAN, "") }.to raise_error(ArgumentError, "TEST: array_size must be a Fixnum")
114
114
  end
115
115
 
116
116
  it "should complain about array size != multiple of bit size" do
117
- expect { StructureItem.new("test", 0, 8, :UINT, :BIG_ENDIAN, 10) }.to raise_error(ArgumentError, "test: array_size must be a multiple of bit_size")
117
+ expect { StructureItem.new("test", 0, 8, :UINT, :BIG_ENDIAN, 10) }.to raise_error(ArgumentError, "TEST: array_size must be a multiple of bit_size")
118
118
  end
119
119
 
120
120
  it "should not complain about array size != multiple of bit size with negative array size" do
@@ -181,7 +181,7 @@ module Cosmos
181
181
  hash = item.to_hash
182
182
  hash.keys.length.should eql 7
183
183
  hash.keys.should include('name','bit_offset','bit_size','data_type','endianness','array_size', 'overflow')
184
- hash["name"].should eql "test"
184
+ hash["name"].should eql "TEST"
185
185
  hash["bit_offset"].should eql 0
186
186
  hash["bit_size"].should eql 8
187
187
  hash["data_type"].should eql :UINT
@@ -34,6 +34,31 @@ module Cosmos
34
34
  end
35
35
  end # describe "initialize"
36
36
 
37
+ describe "defined?" do
38
+ it "returns true if any items have been defined" do
39
+ s = Structure.new
40
+ expect(s.defined?).to be false
41
+ s.define_item("test1",0,8,:UINT)
42
+ expect(s.defined?).to be true
43
+ end
44
+ end
45
+
46
+ describe "rename_item" do
47
+ it "renames a previously defined item" do
48
+ s = Structure.new
49
+ s.items["test1"].should be_nil
50
+ s.sorted_items[0].should be_nil
51
+ s.define_item("test1", 0, 8, :UINT)
52
+ s.items["TEST1"].should_not be_nil
53
+ s.sorted_items[0].should_not be_nil
54
+ s.sorted_items[0].name.should eql "TEST1"
55
+ s.rename_item("TEST1", "TEST2")
56
+ s.items["TEST1"].should be_nil
57
+ s.items["TEST2"].should_not be_nil
58
+ s.sorted_items[0].name.should eql "TEST2"
59
+ end
60
+ end
61
+
37
62
  describe "define_item" do
38
63
  before(:each) do
39
64
  @s = Structure.new
@@ -47,21 +72,21 @@ module Cosmos
47
72
  @s.sorted_items[0].should_not be_nil
48
73
  @s.sorted_items[0].name.should eql "TEST1"
49
74
  @s.defined_length.should eql 1
50
- @s.fixed_size.should be_truthy
75
+ @s.fixed_size.should be true
51
76
  end
52
77
 
53
- it "should add items with negative offsets" do
78
+ it "adds items with negative bit offsets" do
54
79
  @s.define_item("test1", -8, 8, :UINT)
55
80
  @s.defined_length.should eql 1
56
81
  @s.define_item("test2", 0, 4, :UINT)
57
82
  @s.defined_length.should eql 2
58
83
  @s.define_item("test3", 4, 4, :UINT)
59
84
  @s.defined_length.should eql 2
60
- @s.define_item("test4", 8, 0, :BLOCK)
61
- @s.defined_length.should eql 2
62
- @s.define_item("test5", -16, 8, :UINT)
85
+ @s.define_item("test4", 16, 0, :BLOCK)
63
86
  @s.defined_length.should eql 3
64
- @s.fixed_size.should be_falsey
87
+ @s.define_item("test5", -16, 8, :UINT)
88
+ @s.defined_length.should eql 4
89
+ @s.fixed_size.should be false
65
90
  end
66
91
 
67
92
  it "should add item with negative offset" do
@@ -81,7 +106,7 @@ module Cosmos
81
106
  @s.defined_length.should eql 3
82
107
  @s.define_item("test4", 8, 0, :BLOCK)
83
108
  @s.defined_length.should eql 3
84
- @s.fixed_size.should be_falsey
109
+ @s.fixed_size.should be false
85
110
  end
86
111
 
87
112
  it "should recalulate sorted_items when adding multiple items" do
@@ -94,7 +119,7 @@ module Cosmos
94
119
  @s.define_item("test3", 16, 8, :UINT)
95
120
  @s.sorted_items[-1].name.should eql "TEST3"
96
121
  @s.defined_length.should eql 5
97
- @s.fixed_size.should be_truthy
122
+ @s.fixed_size.should be true
98
123
  end
99
124
 
100
125
  it "should overwrite existing items" do
@@ -108,21 +133,73 @@ module Cosmos
108
133
  @s.items["TEST1"].bit_size.should eql 16
109
134
  @s.items["TEST1"].data_type.should eql :INT
110
135
  @s.defined_length.should eql 2
111
- @s.fixed_size.should be_truthy
136
+ @s.fixed_size.should be true
112
137
  end
113
138
  end # describe "define_item"
114
139
 
115
- describe "append_item" do
140
+ describe "define" do
116
141
  before(:each) do
117
142
  @s = Structure.new
118
143
  end
119
144
 
120
- it "should append an item to items" do
121
- @s.define_item("test1", 0, 8, :UINT)
145
+ it "adds the item to items and sorted_items" do
146
+ @s.items["test1"].should be_nil
147
+ @s.sorted_items[0].should be_nil
148
+ si = StructureItem.new("test1",0,8,:UINT,:BIG_ENDIAN)
149
+ @s.define(si)
150
+ @s.items["TEST1"].should_not be_nil
151
+ @s.sorted_items[0].should_not be_nil
152
+ @s.sorted_items[0].name.should eql "TEST1"
153
+ @s.defined_length.should eql 1
154
+ @s.fixed_size.should be true
155
+ end
156
+
157
+ it "allows items to be defined on top of each other" do
158
+ @s.items["test1"].should be_nil
159
+ @s.sorted_items[0].should be_nil
160
+ si = StructureItem.new("test1",0,8,:UINT,:BIG_ENDIAN)
161
+ @s.define(si)
162
+ @s.sorted_items[0].name.should eql "TEST1"
163
+ @s.items["TEST1"].bit_offset.should eql 0
122
164
  @s.items["TEST1"].bit_size.should eql 8
165
+ @s.items["TEST1"].data_type.should eql :UINT
166
+ @s.defined_length.should eql 1
167
+ si = StructureItem.new("test2",0,16,:INT,:BIG_ENDIAN)
168
+ @s.define(si)
169
+ @s.sorted_items[1].name.should eql "TEST2"
170
+ @s.items["TEST2"].bit_offset.should eql 0
171
+ @s.items["TEST2"].bit_size.should eql 16
172
+ @s.items["TEST2"].data_type.should eql :INT
173
+ @s.defined_length.should eql 2
174
+ buffer = "\x01\x02"
175
+ @s.read_item(@s.get_item("test1"), :RAW, buffer).should eql 1
176
+ @s.read_item(@s.get_item("test2"), :RAW, buffer).should eql 258
177
+ end
178
+
179
+ it "should overwrite existing items" do
180
+ si = StructureItem.new("test1",0,8,:UINT,:BIG_ENDIAN)
181
+ @s.define(si)
123
182
  @s.sorted_items[0].name.should eql "TEST1"
124
- @s.sorted_items[1].should be_nil
183
+ @s.items["TEST1"].bit_size.should eql 8
184
+ @s.items["TEST1"].data_type.should eql :UINT
125
185
  @s.defined_length.should eql 1
186
+ si = StructureItem.new("test1",0,16,:INT,:BIG_ENDIAN)
187
+ @s.define(si)
188
+ @s.sorted_items[0].name.should eql "TEST1"
189
+ @s.items["TEST1"].bit_size.should eql 16
190
+ @s.items["TEST1"].data_type.should eql :INT
191
+ @s.defined_length.should eql 2
192
+ @s.fixed_size.should be true
193
+ end
194
+ end
195
+
196
+ describe "append_item" do
197
+ before(:each) do
198
+ @s = Structure.new
199
+ end
200
+
201
+ it "should append an item to items" do
202
+ @s.define_item("test1", 0, 8, :UINT)
126
203
  @s.append_item("test2", 16, :UINT)
127
204
  @s.items["TEST2"].bit_size.should eql 16
128
205
  @s.sorted_items[0].name.should eql "TEST1"
@@ -152,7 +229,29 @@ module Cosmos
152
229
  @s.define_item("test1", 0, 8, :UINT, -8)
153
230
  expect { @s.append_item("test2", 8, :UINT) }.to raise_error(ArgumentError, "Can't append an item after a variably sized item")
154
231
  end
155
- end # describe "define_item"
232
+ end
233
+
234
+ describe "append" do
235
+ before(:each) do
236
+ @s = Structure.new
237
+ end
238
+
239
+ it "appends an item to the structure" do
240
+ @s.define_item("test1", 0, 8, :UINT)
241
+ item = StructureItem.new("test2", 0, 16, :UINT, :BIG_ENDIAN)
242
+ @s.append(item)
243
+ # Bit offset should change because we appended the item
244
+ @s.items["TEST2"].bit_offset.should eql 8
245
+ @s.sorted_items[0].name.should eql "TEST1"
246
+ @s.sorted_items[1].name.should eql "TEST2"
247
+ @s.defined_length.should eql 3
248
+ end
249
+
250
+ it "should complain if appending after a variably sized item" do
251
+ @s.define_item("test1", 0, 0, :BLOCK)
252
+ expect { @s.append(@item) }.to raise_error(ArgumentError, "Can't append an item after a variably sized item")
253
+ end
254
+ end
156
255
 
157
256
  describe "get_item" do
158
257
  before(:each) do
@@ -281,7 +380,7 @@ module Cosmos
281
380
  end
282
381
 
283
382
  describe "read_all" do
284
- it "should read all defined items" do
383
+ it "reads all defined items" do
285
384
  s = Structure.new(:BIG_ENDIAN)
286
385
  s.append_item("test1", 8, :UINT, 16)
287
386
  s.append_item("test2", 16, :UINT)
@@ -296,6 +395,22 @@ module Cosmos
296
395
  vals[1][1].should eql 0x0304
297
396
  vals[2][1].should eql 0x05060708
298
397
  end
398
+
399
+ it "reads all defined items synchronized" do
400
+ s = Structure.new(:BIG_ENDIAN)
401
+ s.append_item("test1", 8, :UINT, 16)
402
+ s.append_item("test2", 16, :UINT)
403
+ s.append_item("test3", 32, :UINT)
404
+
405
+ buffer = "\x01\x02\x03\x04\x05\x06\x07\x08"
406
+ vals = s.read_all(:RAW, buffer, false)
407
+ vals[0][0].should eql "TEST1"
408
+ vals[1][0].should eql "TEST2"
409
+ vals[2][0].should eql "TEST3"
410
+ vals[0][1].should eql [1,2]
411
+ vals[1][1].should eql 0x0304
412
+ vals[2][1].should eql 0x05060708
413
+ end
299
414
  end
300
415
 
301
416
  describe "formatted" do
@@ -312,10 +427,24 @@ module Cosmos
312
427
  s.formatted.should include("TEST3")
313
428
  s.formatted.should include("00000000: 07 08 09 0A")
314
429
  end
430
+
431
+ it "should alter the indentation of the item" do
432
+ s = Structure.new(:BIG_ENDIAN)
433
+ s.append_item("test1", 8, :UINT, 16)
434
+ s.write("test1", [1,2])
435
+ s.append_item("test2", 16, :UINT)
436
+ s.write("test2", 3456)
437
+ s.append_item("test3", 32, :BLOCK)
438
+ s.write("test3", "\x07\x08\x09\x0A")
439
+ s.formatted(:CONVERTED, 4).should include(" TEST1: [1, 2]")
440
+ s.formatted(:CONVERTED, 4).should include(" TEST2: 3456")
441
+ s.formatted(:CONVERTED, 4).should include(" TEST3")
442
+ s.formatted(:CONVERTED, 4).should include(" 00000000: 07 08 09 0A")
443
+ end
315
444
  end
316
445
 
317
446
  describe "buffer" do
318
- it "should return the buffer" do
447
+ it "returns the buffer" do
319
448
  s = Structure.new(:BIG_ENDIAN)
320
449
  s.append_item("test1", 8, :UINT, 16)
321
450
  s.write("test1", [1,2])
@@ -324,6 +453,8 @@ module Cosmos
324
453
  s.append_item("test3", 32, :UINT)
325
454
  s.write("test3", 0x05060708)
326
455
  s.buffer.should eql "\x01\x02\x03\x04\x05\x06\x07\x08"
456
+ expect(s.buffer).to_not be s.buffer
457
+ expect(s.buffer(false)).to be s.buffer(false)
327
458
  end
328
459
  end
329
460
 
@@ -376,8 +507,16 @@ module Cosmos
376
507
  s.write("test2", 0x0304)
377
508
  s.append_item("test3", 32, :UINT)
378
509
  s.write("test3", 0x05060708)
510
+ # Get a reference to the original buffer
511
+ old_buffer = s.buffer(false)
379
512
 
380
513
  s2 = s.clone
514
+ # Ensure we didn't modify the original buffer object
515
+ expect(s.buffer(false)).to be old_buffer
516
+ # Check that they are equal in value
517
+ expect(s2.buffer(false)).to eql s.buffer(false)
518
+ # But not the same object
519
+ expect(s2.buffer(false)).to_not be s.buffer(false)
381
520
  s2.read("test1").should eql [1,2]
382
521
  s2.read("test2").should eql 0x0304
383
522
  s2.read("test3").should eql 0x05060708
@@ -407,6 +546,13 @@ module Cosmos
407
546
  s.test1.should eql [3,4]
408
547
  end
409
548
 
549
+ it "raises an exception if there is no buffer" do
550
+ s = Structure.new(:BIG_ENDIAN, nil)
551
+ s.append_item("test1", 8, :UINT, 16)
552
+ s.enable_method_missing
553
+ expect { s.test1 }.to raise_error(/No buffer/)
554
+ end
555
+
410
556
  it "should complain if it can't find an item" do
411
557
  s = Structure.new(:BIG_ENDIAN)
412
558
  s.enable_method_missing