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
|
@@ -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
|