cosmos 3.1.2 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -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 "
|
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, "
|
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, "
|
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, "
|
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, "
|
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, "
|
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, "
|
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, "
|
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, "
|
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, "
|
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, "
|
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, "
|
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, "
|
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 "
|
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
|
75
|
+
@s.fixed_size.should be true
|
51
76
|
end
|
52
77
|
|
53
|
-
it "
|
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",
|
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.
|
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
|
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
|
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
|
136
|
+
@s.fixed_size.should be true
|
112
137
|
end
|
113
138
|
end # describe "define_item"
|
114
139
|
|
115
|
-
describe "
|
140
|
+
describe "define" do
|
116
141
|
before(:each) do
|
117
142
|
@s = Structure.new
|
118
143
|
end
|
119
144
|
|
120
|
-
it "
|
121
|
-
@s.
|
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.
|
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
|
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 "
|
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 "
|
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
|