cosmos 3.8.0 → 3.8.1
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/autohotkey/tools/packet_viewer.ahk +4 -0
- data/cosmos.gemspec +1 -1
- data/data/crc.txt +277 -277
- data/demo/Gemfile +2 -2
- data/demo/config/data/crc.txt +176 -176
- data/demo/config/targets/INST/cmd_tlm/_ccsds_cmd.txt +2 -2
- data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +4 -4
- data/demo/procedures/example_test.rb +4 -0
- data/install/Gemfile +1 -1
- data/install/config/data/crc.txt +112 -112
- data/lib/cosmos/config/config_parser.rb +35 -1
- data/lib/cosmos/core_ext/string.rb +21 -17
- data/lib/cosmos/core_ext/time.rb +6 -2
- data/lib/cosmos/gui/opengl/gl_viewer.rb +4 -4
- data/lib/cosmos/gui/opengl/stl_shape.rb +5 -1
- data/lib/cosmos/gui/qt.rb +0 -26
- data/lib/cosmos/io/io_multiplexer.rb +27 -45
- data/lib/cosmos/packets/packet.rb +64 -24
- data/lib/cosmos/packets/packet_config.rb +254 -54
- data/lib/cosmos/packets/packet_item.rb +39 -10
- data/lib/cosmos/packets/parsers/packet_item_parser.rb +7 -2
- data/lib/cosmos/script/commands.rb +5 -0
- data/lib/cosmos/script/scripting.rb +5 -5
- data/lib/cosmos/script/telemetry.rb +5 -0
- data/lib/cosmos/tools/cmd_tlm_server/api.rb +22 -0
- data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +38 -10
- data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +48 -9
- data/lib/cosmos/tools/test_runner/test_runner.rb +76 -14
- data/lib/cosmos/tools/tlm_viewer/widgets/linegraph_widget.rb +11 -2
- data/lib/cosmos/tools/tlm_viewer/widgets/timegraph_widget.rb +15 -12
- data/lib/cosmos/top_level.rb +29 -32
- data/lib/cosmos/version.rb +4 -4
- data/spec/config/config_parser_spec.rb +8 -15
- data/spec/core_ext/socket_spec.rb +2 -2
- data/spec/core_ext/string_spec.rb +10 -0
- data/spec/core_ext/time_spec.rb +12 -4
- data/spec/io/io_multiplexer_spec.rb +11 -3
- data/spec/packets/packet_spec.rb +30 -0
- data/spec/script/commands_spec.rb +2 -1
- data/spec/script/scripting_spec.rb +22 -0
- data/spec/script/telemetry_spec.rb +2 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/tools/cmd_tlm_server/router_thread_spec.rb +2 -2
- data/spec/top_level/top_level_spec.rb +4 -2
- metadata +5 -5
@@ -103,7 +103,11 @@ module Cosmos
|
|
103
103
|
@select_keyseq = Qt::KeySequence.new(tr('Ctrl+S'))
|
104
104
|
@select.shortcut = @select_keyseq
|
105
105
|
@select.statusTip = tr('Select Test Suites/Groups/Cases')
|
106
|
-
@select.connect(SIGNAL('triggered()')) { show_select}
|
106
|
+
@select.connect(SIGNAL('triggered()')) { show_select }
|
107
|
+
|
108
|
+
@file_options = Qt::Action.new(tr('O&ptions'), self)
|
109
|
+
@file_options.statusTip = tr('Application Options')
|
110
|
+
@file_options.connect(SIGNAL('triggered()')) { file_options() }
|
107
111
|
|
108
112
|
# Script Actions
|
109
113
|
@test_results_log_message = Qt::Action.new(tr('Log Message to Test Results'), self)
|
@@ -141,21 +145,23 @@ module Cosmos
|
|
141
145
|
|
142
146
|
def initialize_menus
|
143
147
|
# File Menu
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
148
|
+
file_menu = menuBar.addMenu(tr('&File'))
|
149
|
+
file_menu.addAction(@show_last)
|
150
|
+
file_menu.addAction(@select)
|
151
|
+
file_menu.addSeparator()
|
152
|
+
file_menu.addAction(@file_options)
|
153
|
+
file_menu.addSeparator()
|
154
|
+
file_menu.addAction(@exit_action)
|
149
155
|
|
150
156
|
# Script Menu
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
157
|
+
script_menu = menuBar.addMenu(tr('&Script'))
|
158
|
+
script_menu.addAction(@test_results_log_message)
|
159
|
+
script_menu.addAction(@script_log_message)
|
160
|
+
script_menu.addAction(@show_call_stack)
|
161
|
+
script_menu.addAction(@toggle_debug)
|
162
|
+
script_menu.addAction(@script_disconnect)
|
163
|
+
script_menu.addSeparator()
|
164
|
+
script_menu.addAction(@script_audit)
|
159
165
|
|
160
166
|
# Help Menu
|
161
167
|
@about_string = "Test Runner provides a framework for developing high " \
|
@@ -816,6 +822,7 @@ module Cosmos
|
|
816
822
|
Qt::DialogButtonBox::Cancel)
|
817
823
|
connect(button_box, SIGNAL('rejected()'), box, SLOT('reject()'))
|
818
824
|
connect(button_box, SIGNAL('accepted()')) do
|
825
|
+
ScriptRunnerFrame.instance = @script_runner_frame
|
819
826
|
Cosmos.module_eval("class CustomTestSuite < TestSuite; end")
|
820
827
|
tree.topLevelItems do |suite_node|
|
821
828
|
next if suite_node.checkState == Qt::Unchecked
|
@@ -880,6 +887,7 @@ module Cosmos
|
|
880
887
|
@test_runner_chooser.test_suites = @@suites
|
881
888
|
@test_runner_chooser.select_suite("CustomTestSuite")
|
882
889
|
end
|
890
|
+
ScriptRunnerFrame.instance = nil
|
883
891
|
box.accept
|
884
892
|
end
|
885
893
|
dialog_layout.addWidget(button_box)
|
@@ -890,6 +898,60 @@ module Cosmos
|
|
890
898
|
dialog.dispose
|
891
899
|
end
|
892
900
|
|
901
|
+
def file_options
|
902
|
+
dialog = Qt::Dialog.new(self)
|
903
|
+
dialog.setWindowTitle('Test Runner Options')
|
904
|
+
layout = Qt::VBoxLayout.new
|
905
|
+
|
906
|
+
form = Qt::FormLayout.new
|
907
|
+
box = Qt::DoubleSpinBox.new
|
908
|
+
box.setRange(0, 60)
|
909
|
+
box.setValue(ScriptRunnerFrame.line_delay)
|
910
|
+
form.addRow(tr("&Delay between each script line:"), box)
|
911
|
+
monitor = Qt::CheckBox.new
|
912
|
+
form.addRow(tr("&Monitor limits:"), monitor)
|
913
|
+
pause_on_red = Qt::CheckBox.new
|
914
|
+
form.addRow(tr("Pause on &red limit:"), pause_on_red)
|
915
|
+
if ScriptRunnerFrame.monitor_limits
|
916
|
+
monitor.setCheckState(Qt::Checked)
|
917
|
+
pause_on_red.setCheckState(Qt::Checked) if ScriptRunnerFrame.pause_on_red
|
918
|
+
else
|
919
|
+
pause_on_red.setEnabled(false)
|
920
|
+
end
|
921
|
+
monitor.connect(SIGNAL('stateChanged(int)')) do
|
922
|
+
if monitor.isChecked()
|
923
|
+
pause_on_red.setEnabled(true)
|
924
|
+
else
|
925
|
+
pause_on_red.setCheckState(Qt::Unchecked)
|
926
|
+
pause_on_red.setEnabled(false)
|
927
|
+
end
|
928
|
+
end
|
929
|
+
layout.addLayout(form)
|
930
|
+
|
931
|
+
divider = Qt::Frame.new
|
932
|
+
divider.setFrameStyle(Qt::Frame::HLine | Qt::Frame::Raised)
|
933
|
+
divider.setLineWidth(1)
|
934
|
+
layout.addWidget(divider)
|
935
|
+
|
936
|
+
ok = Qt::PushButton.new('Ok')
|
937
|
+
ok.setDefault(true)
|
938
|
+
ok.connect(SIGNAL('clicked(bool)')) do
|
939
|
+
ScriptRunnerFrame.line_delay = box.value
|
940
|
+
ScriptRunnerFrame.monitor_limits = (monitor.checkState == Qt::Checked)
|
941
|
+
ScriptRunnerFrame.pause_on_red = (pause_on_red.checkState == Qt::Checked)
|
942
|
+
dialog.accept
|
943
|
+
end
|
944
|
+
cancel = Qt::PushButton.new('Cancel')
|
945
|
+
cancel.connect(SIGNAL('clicked(bool)')) { dialog.reject }
|
946
|
+
button_layout = Qt::HBoxLayout.new
|
947
|
+
button_layout.addWidget(ok)
|
948
|
+
button_layout.addWidget(cancel)
|
949
|
+
layout.addLayout(button_layout)
|
950
|
+
dialog.setLayout(layout)
|
951
|
+
dialog.exec
|
952
|
+
dialog.dispose
|
953
|
+
end
|
954
|
+
|
893
955
|
def process_config(filename)
|
894
956
|
ScriptRunnerFrame.instance = @script_runner_frame
|
895
957
|
|
@@ -33,10 +33,19 @@ module Cosmos
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def value=(data)
|
36
|
-
|
36
|
+
if data.is_a?(Array)
|
37
|
+
data2 = data.map(&:to_f)
|
38
|
+
data2.reject!{|val| val.nan? or val.infinite?}
|
39
|
+
@data.push(data2).flatten!
|
40
|
+
else
|
41
|
+
data2 = data.to_f
|
42
|
+
if !data2.infinite? and !data2.nan?
|
43
|
+
@data << data2
|
44
|
+
end
|
45
|
+
end
|
37
46
|
|
38
47
|
if @data.length > @num_samples
|
39
|
-
@data = @data
|
48
|
+
@data = @data.last(@num_samples)
|
40
49
|
end
|
41
50
|
if not @data.empty?
|
42
51
|
self.clear_lines
|
@@ -66,21 +66,24 @@ module Cosmos
|
|
66
66
|
# Don't regraph old data
|
67
67
|
return if @time[-1] == t_sec
|
68
68
|
|
69
|
-
|
70
|
-
|
69
|
+
data2 = data.to_f
|
70
|
+
if data2.infinite? or data2.nan?
|
71
|
+
# create time array
|
72
|
+
@time << t_sec
|
71
73
|
|
72
|
-
|
73
|
-
|
74
|
+
# create data array and graph
|
75
|
+
@data << data2
|
74
76
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
# truncate data if necessary
|
78
|
+
if @data.length > @num_samples
|
79
|
+
@data = @data[1..-1]
|
80
|
+
@time = @time[1..-1]
|
81
|
+
end
|
80
82
|
|
81
|
-
|
82
|
-
|
83
|
-
|
83
|
+
self.clear_lines
|
84
|
+
self.add_line('line', @data, @time)
|
85
|
+
self.graph
|
86
|
+
end
|
84
87
|
end
|
85
88
|
|
86
89
|
end
|
data/lib/cosmos/top_level.rb
CHANGED
@@ -162,11 +162,12 @@ module Cosmos
|
|
162
162
|
# No Gemfile - so no gem based extensions
|
163
163
|
end
|
164
164
|
|
165
|
+
# Check CORE
|
165
166
|
filename = File.join(::Cosmos::PATH, 'data', name)
|
166
167
|
return filename if File.exist? filename
|
167
168
|
|
168
|
-
# Check
|
169
|
-
filename = Cosmos.path('data'
|
169
|
+
# Check relative to executing file
|
170
|
+
filename = Cosmos.path($0, 'config/data/' + name)
|
170
171
|
return filename if File.exist? filename
|
171
172
|
|
172
173
|
nil
|
@@ -304,7 +305,7 @@ module Cosmos
|
|
304
305
|
if real_lines > 0
|
305
306
|
Logger.error output
|
306
307
|
self.write_unexpected_file(output)
|
307
|
-
if defined? ::Qt and
|
308
|
+
if defined? ::Qt and $qApp
|
308
309
|
Qt.execute_in_main_thread(false) do
|
309
310
|
dialog = Qt::Dialog.new do |box|
|
310
311
|
box.setWindowTitle('Unexpected text output')
|
@@ -528,7 +529,7 @@ module Cosmos
|
|
528
529
|
Logger.level = Logger::FATAL unless try_gui
|
529
530
|
Logger.fatal "Fatal Exception! Exiting..."
|
530
531
|
Logger.fatal error.formatted
|
531
|
-
if defined? ExceptionDialog and try_gui and
|
532
|
+
if defined? ExceptionDialog and try_gui and $qApp
|
532
533
|
Qt.execute_in_main_thread(true) {||ExceptionDialog.new(nil, error, '', true, false, log_file)}
|
533
534
|
else
|
534
535
|
if $stdout != STDOUT
|
@@ -618,39 +619,35 @@ module Cosmos
|
|
618
619
|
# @param filename [String] Name of the file to open in the editor
|
619
620
|
def self.open_in_text_editor(filename)
|
620
621
|
if filename
|
621
|
-
if
|
622
|
-
|
623
|
-
self.run_process("cmd /c \"start wordpad \"#{filename.gsub('/','\\')}\"\"")
|
624
|
-
else
|
625
|
-
self.run_process("cmd /c \"start \"\" \"#{filename.gsub('/','\\')}\"\"")
|
626
|
-
end
|
627
|
-
elsif Kernel.is_mac?
|
628
|
-
self.run_process("open -a TextEdit \"#{filename}\"")
|
622
|
+
if ENV['COSMOS_TEXT']
|
623
|
+
self.run_process("#{ENV['COSMOS_TEXT']} \"#{filename}\"")
|
629
624
|
else
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
editor = ENV['EDITOR']
|
634
|
-
editor = 'vi' unless editor
|
635
|
-
which_xterm = `which xterm 2>&1`.chomp
|
636
|
-
if which_xterm =~ /Command not found/i or which_xterm =~ /no .* in/i
|
637
|
-
# No xterm
|
638
|
-
which_gnome_terminal = `which gnome-terminal 2>&1`.chomp
|
639
|
-
if which_gnome_terminal =~ /Command not found/i or which_gnome_terminal =~ /no .* in/i
|
640
|
-
# No gnome-terminal - Do nothing
|
641
|
-
else
|
642
|
-
# Have gnome-terminal
|
643
|
-
system_call = "gnome-terminal -e #{editor} \"#{filename}\""
|
644
|
-
end
|
625
|
+
if Kernel.is_windows?
|
626
|
+
if File.extname(filename).to_s.downcase == '.csv'
|
627
|
+
self.run_process("cmd /c \"start wordpad \"#{filename.gsub('/','\\')}\"\"")
|
645
628
|
else
|
646
|
-
|
647
|
-
system_call = "xterm -e #{editor} \"#{filename}\""
|
629
|
+
self.run_process("cmd /c \"start \"\" \"#{filename.gsub('/','\\')}\"\"")
|
648
630
|
end
|
631
|
+
elsif Kernel.is_mac?
|
632
|
+
self.run_process("open -a TextEdit \"#{filename}\"")
|
649
633
|
else
|
650
|
-
|
651
|
-
|
634
|
+
which_gedit = `which gedit 2>&1`.chomp
|
635
|
+
if which_gedit.to_s.strip == "" or which_gedit =~ /Command not found/i or which_gedit =~ /no .* in/i
|
636
|
+
# No gedit
|
637
|
+
['xterm', 'gnome-terminal', 'urxvt', 'rxvt'].each do |terminal|
|
638
|
+
which_terminal = `which #{terminal} 2>&1`.chomp
|
639
|
+
next if which_terminal.to_s.strip == "" or which_terminal =~ /Command not found/i or which_terminal =~ /no .* in/i
|
640
|
+
editor = ENV['VISUAL']
|
641
|
+
editor = ENV['EDITOR'] unless editor
|
642
|
+
editor = 'vi' unless editor
|
643
|
+
self.run_process("#{terminal} -e \"#{editor} '#{filename}'\"")
|
644
|
+
break
|
645
|
+
end
|
646
|
+
else
|
647
|
+
# Have gedit
|
648
|
+
self.run_process("gedit \"#{filename}\"")
|
649
|
+
end
|
652
650
|
end
|
653
|
-
self.run_process(system_call)
|
654
651
|
end
|
655
652
|
end
|
656
653
|
end
|
data/lib/cosmos/version.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# encoding: ascii-8bit
|
2
2
|
|
3
|
-
COSMOS_VERSION = '3.8.
|
3
|
+
COSMOS_VERSION = '3.8.1'
|
4
4
|
module Cosmos
|
5
5
|
module Version
|
6
6
|
MAJOR = '3'
|
7
7
|
MINOR = '8'
|
8
|
-
PATCH = '
|
9
|
-
BUILD = '
|
8
|
+
PATCH = '1'
|
9
|
+
BUILD = 'fa125f2a38e0aa28f6d3000a80ea5167115172d7'
|
10
10
|
end
|
11
|
-
VERSION = '3.8.
|
11
|
+
VERSION = '3.8.1'
|
12
12
|
end
|
@@ -221,11 +221,6 @@ module Cosmos
|
|
221
221
|
expect(ConfigParser.handle_nil("HI")).to eql "HI"
|
222
222
|
expect(ConfigParser.handle_nil(5.0)).to eql 5.0
|
223
223
|
end
|
224
|
-
|
225
|
-
#it "should complain if it can't convert" do
|
226
|
-
# expect { ConfigParser.handle_nil(0) }.to raise_error(ArgumentError, "Value is not nil: 0")
|
227
|
-
# expect { ConfigParser.handle_nil(false) }.to raise_error(ArgumentError, "Value is not nil: false")
|
228
|
-
#end
|
229
224
|
end
|
230
225
|
|
231
226
|
describe "self.handle_true_false" do
|
@@ -245,11 +240,6 @@ module Cosmos
|
|
245
240
|
expect(ConfigParser.handle_true_false("HI")).to eql "HI"
|
246
241
|
expect(ConfigParser.handle_true_false(5.0)).to eql 5.0
|
247
242
|
end
|
248
|
-
|
249
|
-
#it "should complain if it can't convert" do
|
250
|
-
# expect { ConfigParser.handle_true_false(0) }.to raise_error(ArgumentError, "Value neither true or false: 0")
|
251
|
-
# expect { ConfigParser.handle_true_false(nil) }.to raise_error(ArgumentError, "Value neither true or false: ")
|
252
|
-
#end
|
253
243
|
end
|
254
244
|
|
255
245
|
describe "self.handle_true_false_nil" do
|
@@ -281,15 +271,18 @@ module Cosmos
|
|
281
271
|
expect(ConfigParser.handle_true_false("HI")).to eql "HI"
|
282
272
|
expect(ConfigParser.handle_true_false(5.0)).to eql 5.0
|
283
273
|
end
|
284
|
-
|
285
|
-
#it "should complain if it can't convert" do
|
286
|
-
# expect { ConfigParser.handle_true_false_nil(0) }.to raise_error(ArgumentError, "Value neither true, false, or nil: 0")
|
287
|
-
# expect { ConfigParser.handle_true_false_nil(1) }.to raise_error(ArgumentError, "Value neither true, false, or nil: 1")
|
288
|
-
#end
|
289
274
|
end
|
290
275
|
|
291
276
|
describe "self.handle_defined_constants" do
|
292
277
|
it "converts string constants to numbers" do
|
278
|
+
(1..64).each do |val|
|
279
|
+
# Unsigned
|
280
|
+
expect(ConfigParser.handle_defined_constants("MIN", :UINT, val)).to eql 0
|
281
|
+
expect(ConfigParser.handle_defined_constants("MAX", :UINT, val)).to eql (2**val - 1)
|
282
|
+
# Signed
|
283
|
+
expect(ConfigParser.handle_defined_constants("MIN", :INT, val)).to eql -((2**val) / 2)
|
284
|
+
expect(ConfigParser.handle_defined_constants("MAX", :INT, val)).to eql ((2**val) / 2 - 1)
|
285
|
+
end
|
293
286
|
[8,16,32,64].each do |val|
|
294
287
|
# Unsigned
|
295
288
|
expect(ConfigParser.handle_defined_constants("MIN_UINT#{val}")).to eql 0
|
@@ -25,8 +25,8 @@ describe Socket do
|
|
25
25
|
|
26
26
|
describe "lookup_hostname_from_ip" do
|
27
27
|
it "returns the hostname for the ip address" do
|
28
|
-
ipaddr = Resolv.getaddress "
|
29
|
-
expect(Socket.lookup_hostname_from_ip(ipaddr)).to match "
|
28
|
+
ipaddr = Resolv.getaddress "localhost"
|
29
|
+
expect(Socket.lookup_hostname_from_ip(ipaddr)).to match "localhost"
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -194,6 +194,16 @@ describe String do
|
|
194
194
|
it "converts an array" do
|
195
195
|
expect("[0,1,2,3]".convert_to_value).to eql [0,1,2,3]
|
196
196
|
end
|
197
|
+
|
198
|
+
it "just returns the string if something goes wrong" do
|
199
|
+
expect("[.a,2,3]".convert_to_value).to eql "[.a,2,3]"
|
200
|
+
end
|
201
|
+
|
202
|
+
it "doesn't match multiline strings" do
|
203
|
+
expect("12345\n12345".convert_to_value).to eql "12345\n12345"
|
204
|
+
expect("5.123\n5.123".convert_to_value).to eql "5.123\n5.123"
|
205
|
+
expect("[0,1,2,3]\n[0,1,2,3]".convert_to_value).to eql "[0,1,2,3]\n[0,1,2,3]"
|
206
|
+
end
|
197
207
|
end
|
198
208
|
|
199
209
|
describe "hex_to_byte_string" do
|
data/spec/core_ext/time_spec.rb
CHANGED
@@ -113,12 +113,20 @@ describe Time do
|
|
113
113
|
end
|
114
114
|
|
115
115
|
describe "formatted" do
|
116
|
-
it "formats the Time" do
|
117
|
-
expect(Time.new(2020,1,2,3,4,5.
|
116
|
+
it "formats the Time with date and fractional seconds" do
|
117
|
+
expect(Time.new(2020,1,2,3,4,5.123456).formatted(true, 6)).to eql "2020/01/02 03:04:05.123456"
|
118
118
|
end
|
119
119
|
|
120
|
-
it "formats the Time
|
121
|
-
expect(Time.new(2020,1,2,3,4,5.
|
120
|
+
it "formats the Time with date and no fractional seconds" do
|
121
|
+
expect(Time.new(2020,1,2,3,4,5.123456).formatted(true, 0)).to eql "2020/01/02 03:04:05"
|
122
|
+
end
|
123
|
+
|
124
|
+
it "formats the Time without the date and fractional seconds" do
|
125
|
+
expect(Time.new(2020,1,2,3,4,5.123456).formatted(false, 2)).to eql "03:04:05.12"
|
126
|
+
end
|
127
|
+
|
128
|
+
it "formats the Time without the date and no fractional seconds" do
|
129
|
+
expect(Time.new(2020,1,2,3,4,5.123456).formatted(false, 0)).to eql "03:04:05"
|
122
130
|
end
|
123
131
|
end
|
124
132
|
|
@@ -18,6 +18,15 @@ module Cosmos
|
|
18
18
|
@io = IoMultiplexer.new
|
19
19
|
end
|
20
20
|
|
21
|
+
describe "stream_operator" do
|
22
|
+
it "supports the << operator" do
|
23
|
+
@io.add_stream(STDOUT)
|
24
|
+
expect($stdout).to receive(:<<).with("TEST").and_return($stdout)
|
25
|
+
result = (@io << "TEST")
|
26
|
+
expect(result).to eql(@io)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
21
30
|
describe "add_stream" do
|
22
31
|
it "adds a single stream" do
|
23
32
|
@io.add_stream(STDOUT)
|
@@ -64,10 +73,10 @@ module Cosmos
|
|
64
73
|
describe "write write_nonblock" do
|
65
74
|
it "defers to the stream" do
|
66
75
|
@io.add_stream(STDOUT)
|
67
|
-
expect($stdout).to receive(:write).with("TEST")
|
76
|
+
expect($stdout).to receive(:write).with("TEST").and_return(4)
|
68
77
|
len = @io.write "TEST"
|
69
78
|
expect(len).to eql 4
|
70
|
-
expect($stdout).to receive(:write_nonblock).with("TEST")
|
79
|
+
expect($stdout).to receive(:write_nonblock).with("TEST").and_return(4)
|
71
80
|
len = @io.write_nonblock "TEST"
|
72
81
|
expect(len).to eql 4
|
73
82
|
end
|
@@ -88,7 +97,6 @@ module Cosmos
|
|
88
97
|
File.delete("unittest.txt")
|
89
98
|
end
|
90
99
|
end
|
91
|
-
|
92
100
|
end
|
93
101
|
end
|
94
102
|
|
data/spec/packets/packet_spec.rb
CHANGED
@@ -370,6 +370,36 @@ module Cosmos
|
|
370
370
|
expect(@p.read_item(i, :CONVERTED, "\x02")).to eql 1
|
371
371
|
end
|
372
372
|
|
373
|
+
it "prevents the read conversion cache from being corrupted" do
|
374
|
+
@p.append_item("item",8,:UINT)
|
375
|
+
i = @p.get_item("ITEM")
|
376
|
+
i.read_conversion = GenericConversion.new("'A String'")
|
377
|
+
i.units = "with units"
|
378
|
+
value = @p.read_item(i, :CONVERTED)
|
379
|
+
expect(value).to eql 'A String'
|
380
|
+
value << 'That got modified'
|
381
|
+
value = @p.read_item(i, :WITH_UNITS)
|
382
|
+
expect(value).to eql 'A String with units'
|
383
|
+
value << 'That got modified'
|
384
|
+
expect(@p.read_item(i, :WITH_UNITS)).to eql 'A String with units'
|
385
|
+
value = @p.read_item(i, :WITH_UNITS)
|
386
|
+
value << ' more things'
|
387
|
+
expect(@p.read_item(i, :WITH_UNITS)).to eql 'A String with units'
|
388
|
+
|
389
|
+
@p.buffer = "\x00"
|
390
|
+
i.read_conversion = GenericConversion.new("['A', 'B', 'C']")
|
391
|
+
value = @p.read_item(i, :CONVERTED)
|
392
|
+
expect(value).to eql ['A', 'B', 'C']
|
393
|
+
value << 'D'
|
394
|
+
value = @p.read_item(i, :WITH_UNITS)
|
395
|
+
expect(value).to eql ['A with units', 'B with units', 'C with units']
|
396
|
+
value << 'D'
|
397
|
+
expect(@p.read_item(i, :WITH_UNITS)).to eql ['A with units', 'B with units', 'C with units']
|
398
|
+
value = @p.read_item(i, :WITH_UNITS)
|
399
|
+
value << 'D'
|
400
|
+
expect(@p.read_item(i, :WITH_UNITS)).to eql ['A with units', 'B with units', 'C with units']
|
401
|
+
end
|
402
|
+
|
373
403
|
it "reads the CONVERTED value with states" do
|
374
404
|
@p.append_item("item",8,:UINT)
|
375
405
|
i = @p.get_item("ITEM")
|