cosmos 4.0.3 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -5
  3. data/Manifest.txt +11 -1
  4. data/README.md +3 -2
  5. data/Rakefile +18 -4
  6. data/appveyor.yml +19 -0
  7. data/cosmos.gemspec +14 -3
  8. data/data/config/cmd_tlm_server.yaml +3 -0
  9. data/data/crc.txt +63 -60
  10. data/demo/config/targets/INST/cmd_tlm_server.txt +1 -0
  11. data/demo/config/targets/INST/cmd_tlm_server2.txt +7 -0
  12. data/demo/config/tools/cmd_sequence/cmd_sequence.txt +2 -0
  13. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +8 -12
  14. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +7 -9
  15. data/demo/lib/cmd_sequence_exporter.rb +52 -0
  16. data/demo/lib/example_background_task.rb +1 -0
  17. data/demo/procedures/replay_test.rb +32 -0
  18. data/ext/cosmos/ext/structure/structure.c +39 -3
  19. data/install/config/tools/cmd_tlm_server/cmd_tlm_server.txt +1 -0
  20. data/install/config/tools/launcher/launcher.txt +2 -0
  21. data/lib/cosmos/config/config_parser.rb +2 -0
  22. data/lib/cosmos/core_ext/io.rb +89 -60
  23. data/lib/cosmos/gui/qt.rb +5 -8
  24. data/lib/cosmos/gui/qt_tool.rb +8 -8
  25. data/lib/cosmos/gui/text/ruby_editor.rb +12 -12
  26. data/lib/cosmos/gui/utilities/script_module_gui.rb +9 -9
  27. data/lib/cosmos/gui/widgets/realtime_button_bar.rb +18 -17
  28. data/lib/cosmos/interfaces/protocols/fixed_protocol.rb +2 -2
  29. data/lib/cosmos/interfaces/protocols/template_protocol.rb +3 -0
  30. data/lib/cosmos/interfaces/udp_interface.rb +27 -14
  31. data/lib/cosmos/io/buffered_file.rb +0 -1
  32. data/lib/cosmos/io/json_drb.rb +134 -214
  33. data/lib/cosmos/io/json_drb_object.rb +22 -61
  34. data/lib/cosmos/io/json_drb_rack.rb +79 -0
  35. data/lib/cosmos/io/json_rpc.rb +27 -0
  36. data/lib/cosmos/io/udp_sockets.rb +102 -58
  37. data/lib/cosmos/packets/commands.rb +1 -1
  38. data/lib/cosmos/packets/structure.rb +1 -1
  39. data/lib/cosmos/packets/structure_item.rb +37 -5
  40. data/lib/cosmos/script/cmd_tlm_server.rb +76 -2
  41. data/lib/cosmos/script/replay.rb +60 -0
  42. data/lib/cosmos/script/script.rb +20 -2
  43. data/lib/cosmos/script/scripting.rb +9 -9
  44. data/lib/cosmos/script/tools.rb +14 -0
  45. data/lib/cosmos/system/system.rb +185 -92
  46. data/lib/cosmos/system/target.rb +1 -1
  47. data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +44 -4
  48. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +4 -0
  49. data/lib/cosmos/tools/cmd_sequence/sequence_list.rb +7 -0
  50. data/lib/cosmos/tools/cmd_tlm_server/api.rb +347 -20
  51. data/lib/cosmos/tools/cmd_tlm_server/background_tasks.rb +3 -0
  52. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +329 -111
  53. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +13 -0
  54. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +261 -95
  55. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +46 -35
  56. data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +18 -8
  57. data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +39 -28
  58. data/lib/cosmos/tools/cmd_tlm_server/gui/replay_tab.rb +242 -0
  59. data/lib/cosmos/tools/cmd_tlm_server/gui/status_tab.rb +24 -8
  60. data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +18 -6
  61. data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +5 -4
  62. data/lib/cosmos/tools/cmd_tlm_server/replay_backend.rb +375 -0
  63. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +10 -2
  64. data/lib/cosmos/tools/data_viewer/data_viewer.rb +40 -5
  65. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +18 -20
  66. data/lib/cosmos/tools/launcher/launcher_config.rb +5 -16
  67. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +65 -39
  68. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +19 -0
  69. data/lib/cosmos/tools/replay/replay.rb +5 -505
  70. data/lib/cosmos/tools/script_runner/script_audit.rb +1 -0
  71. data/lib/cosmos/tools/script_runner/script_runner.rb +3 -4
  72. data/lib/cosmos/tools/script_runner/script_runner_config.rb +3 -4
  73. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +44 -23
  74. data/lib/cosmos/tools/test_runner/results_writer.rb +4 -0
  75. data/lib/cosmos/tools/test_runner/test_runner.rb +0 -3
  76. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +6 -2
  77. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +26 -1
  78. data/lib/cosmos/tools/tlm_viewer/screen.rb +24 -1
  79. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +25 -0
  80. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +24 -14
  81. data/lib/cosmos/top_level.rb +34 -24
  82. data/lib/cosmos/utilities/csv.rb +60 -8
  83. data/lib/cosmos/version.rb +5 -5
  84. data/spec/config/config_parser_spec.rb +10 -1
  85. data/spec/core_ext/socket_spec.rb +4 -2
  86. data/spec/gui/utilities/script_module_gui_spec.rb +102 -0
  87. data/spec/install/config/data/data.txt +1 -0
  88. data/spec/install/config/targets/INST/cmd_tlm/inst_cmds.txt +2 -0
  89. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +1 -2
  90. data/spec/interfaces/protocols/template_protocol_spec.rb +72 -2
  91. data/spec/interfaces/serial_interface_spec.rb +1 -1
  92. data/spec/interfaces/udp_interface_spec.rb +14 -0
  93. data/spec/io/buffered_file_spec.rb +37 -0
  94. data/spec/io/json_drb_object_spec.rb +2 -15
  95. data/spec/io/json_drb_spec.rb +61 -121
  96. data/spec/io/udp_sockets_spec.rb +42 -2
  97. data/spec/packet_logs/packet_log_reader_spec.rb +5 -2
  98. data/spec/packets/binary_accessor_spec.rb +1 -1
  99. data/spec/packets/packet_item_spec.rb +1 -1
  100. data/spec/packets/structure_item_spec.rb +5 -6
  101. data/spec/script/cmd_tlm_server_spec.rb +39 -4
  102. data/spec/script/commands_disconnect_spec.rb +1 -1
  103. data/spec/script/commands_spec.rb +2 -1
  104. data/spec/script/scripting_spec.rb +18 -3
  105. data/spec/script/telemetry_spec.rb +5 -0
  106. data/spec/spec_helper.rb +43 -26
  107. data/spec/streams/tcpip_socket_stream_spec.rb +2 -2
  108. data/spec/system/system_spec.rb +11 -9
  109. data/spec/system/target_spec.rb +3 -0
  110. data/spec/tools/cmd_tlm_server/api_spec.rb +543 -29
  111. data/spec/tools/cmd_tlm_server/background_task_spec.rb +2 -2
  112. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +31 -75
  113. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +199 -66
  114. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +85 -9
  115. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +29 -127
  116. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +10 -50
  117. data/spec/tools/launcher/launcher_config_spec.rb +1 -1
  118. data/spec/tools/table_manager/table_item_spec.rb +1 -1
  119. data/spec/tools/table_manager/tablemanager_core_spec.rb +4 -4
  120. data/spec/top_level/top_level_spec.rb +151 -3
  121. data/spec/utilities/csv_spec.rb +24 -5
  122. metadata +61 -9
  123. data/lib/cosmos/tools/replay/replay_server.rb +0 -91
@@ -180,7 +180,10 @@ module Cosmos
180
180
 
181
181
  # Corrupt the second config
182
182
  second_config_path = System.instance.send(:find_configuration, second_config_name)
183
- FileUtils.mv File.join(second_config_path, 'system.txt'), File.join(second_config_path, 'system2.txt')
183
+ md5 = File.basename(second_config_path, '.*')
184
+ Zip::File.open(second_config_path) do |zip|
185
+ zip.file.rename(File.join(md5, 'system.txt'), File.join(md5, 'system2.txt'))
186
+ end
184
187
 
185
188
  # Return to original config
186
189
  System.load_configuration
@@ -195,7 +198,7 @@ module Cosmos
195
198
  FileUtils.mv File.join(Cosmos::USERPATH, 'system.txt'),
196
199
  File.join(Cosmos::USERPATH,'config','system')
197
200
 
198
- File.delete(File.join(@config_targets,'SYSTEM','cmd_tlm','test1_tlm.txt'))
201
+ FileUtils.rm_f(File.join(@config_targets,'SYSTEM','cmd_tlm','test1_tlm.txt'))
199
202
  end
200
203
  end
201
204
 
@@ -975,7 +975,7 @@ module Cosmos
975
975
  it "complains about writing a frozen buffer" do
976
976
  buffer = "BLANK WORLD".freeze
977
977
  string = "HELLO"
978
- expect {BinaryAccessor.write(string, 0, string.length*8, :STRING, buffer, :BIG_ENDIAN, :ERROR) }.to raise_error(RuntimeError, "can't modify frozen String")
978
+ expect {BinaryAccessor.write(string, 0, string.length*8, :STRING, buffer, :BIG_ENDIAN, :ERROR) }.to raise_error(RuntimeError, /can't modify frozen String/)
979
979
  end
980
980
 
981
981
  it "writes aligned 8-bit unsigned integers" do
@@ -324,7 +324,7 @@ module Cosmos
324
324
  describe "clone" do
325
325
  it "duplicates the entire PacketItem" do
326
326
  pi2 = @pi.clone
327
- expect(@pi == pi2).to be true
327
+ expect(@pi < pi2).to be true
328
328
  end
329
329
  end
330
330
 
@@ -149,8 +149,8 @@ module Cosmos
149
149
  expect(si1 > si2).to be false
150
150
 
151
151
  si2 = StructureItem.new("si2", 0, 8, :UINT, :BIG_ENDIAN, nil)
152
- expect(si1 < si2).to be false
153
- expect(si1 == si2).to be true
152
+ expect(si1 < si2).to be true
153
+ expect(si1 == si2).to be false
154
154
  expect(si1 > si2).to be false
155
155
  end
156
156
 
@@ -170,9 +170,8 @@ module Cosmos
170
170
  expect(si1 > si2).to be true
171
171
 
172
172
  si2 = StructureItem.new("si2", -8, 8, :UINT, :BIG_ENDIAN, nil)
173
- expect(si1 < si2).to be false
174
- # si1 == si2 even though they have different names and sizes
175
- expect(si1 == si2).to be true
173
+ expect(si1 < si2).to be true
174
+ expect(si1 == si2).to be false
176
175
  expect(si1 > si2).to be false
177
176
  end
178
177
 
@@ -189,7 +188,7 @@ module Cosmos
189
188
  it "duplicates the entire structure item " do
190
189
  si1 = StructureItem.new("si1", -8, 1, :UINT, :LITTLE_ENDIAN, nil)
191
190
  si2 = si1.clone
192
- expect(si1 == si2).to be true
191
+ expect(si1 < si2).to be true
193
192
  end
194
193
  end
195
194
 
@@ -70,7 +70,7 @@ module Cosmos
70
70
  end
71
71
  end
72
72
 
73
- describe "get_interface_info" do
73
+ describe "get_interface_info" do
74
74
  it "returns interface info" do
75
75
  state, clients, tx_q_size, rx_q_size, bytes_tx, bytes_rx, cmd_cnt, tlm_cnt = get_interface_info("INST_INT")
76
76
  connect_interface("INST_INT")
@@ -86,7 +86,7 @@ module Cosmos
86
86
  end
87
87
  end
88
88
 
89
- describe "get_router_info" do
89
+ describe "get_router_info" do
90
90
  it "returns router info" do
91
91
  connect_router("PREIDENTIFIED_ROUTER")
92
92
  state, clients, tx_q_size, rx_q_size, bytes_tx, bytes_rx, pkts_rcvd, pkts_sent = get_router_info("PREIDENTIFIED_ROUTER")
@@ -110,6 +110,20 @@ module Cosmos
110
110
  end
111
111
  end
112
112
 
113
+ describe "get_target_ignored_parameters" do
114
+ it "returns ignored parameters" do
115
+ params = get_target_ignored_parameters("INST")
116
+ expect(params.length).to be >= 0
117
+ end
118
+ end
119
+
120
+ describe "get_target_ignored_items" do
121
+ it "returns ignored items" do
122
+ items = get_target_ignored_items("INST")
123
+ expect(items.length).to be >= 0
124
+ end
125
+ end
126
+
113
127
  describe "get_cmd_cnt" do
114
128
  it "returns cmd count" do
115
129
  expect(get_cmd_cnt("INST", "COLLECT")).to be >= 0
@@ -122,9 +136,16 @@ module Cosmos
122
136
  end
123
137
  end
124
138
 
139
+ describe "get_packet_loggers" do
140
+ it "returns all the packet logger names" do
141
+ loggers = get_packet_loggers()
142
+ expect(loggers).to include("DEFAULT")
143
+ end
144
+ end
145
+
125
146
  describe "get_packet_logger_info" do
126
147
  it "returns packet logger info" do
127
- interfaces, cmd_logging, cmd_q_size, cmd_filename, cmd_file_size,
148
+ interfaces, cmd_logging, cmd_q_size, cmd_filename, cmd_file_size,
128
149
  tlm_logging, tlm_q_size, tlm_filename, tlm_file_size, = get_packet_logger_info("DEFAULT")
129
150
  expect(interfaces).to include("INST_INT")
130
151
  expect(cmd_logging).to eql true
@@ -171,6 +192,20 @@ module Cosmos
171
192
  end
172
193
  end
173
194
 
195
+ describe "subscribe_server_messages, get_server_message, unsubscribe_server_messages" do
196
+ it "raises an error if non_block and the queue is empty" do
197
+ id = subscribe_server_messages
198
+ expect { get_server_message(id, true) }.to raise_error(ThreadError, "queue empty")
199
+ unsubscribe_server_messages(id)
200
+ end
201
+
202
+ it "subscribes and gets server messages" do
203
+ id = subscribe_server_messages
204
+ CmdTlmServer.instance.post_server_message("This is a test")
205
+ result = get_server_message(id, true)
206
+ expect(result).to eql "This is a test"
207
+ unsubscribe_server_messages(id)
208
+ end
209
+ end
174
210
  end
175
211
  end
176
-
@@ -254,7 +254,7 @@ module Cosmos
254
254
  describe "get_cmd_param_list" do
255
255
  it "returns all the parameters for a command" do
256
256
  list = get_cmd_param_list("INST", "COLLECT")
257
- expect(list).to include(["TYPE", 0, {"NORMAL"=>0, "SPECIAL"=>1}, "Collect type", nil, nil, true])
257
+ expect(list).to include(["TYPE", 0, {"NORMAL"=>0, "SPECIAL"=>1}, "Collect type", nil, nil, true, "UINT"])
258
258
  end
259
259
  end
260
260
 
@@ -272,7 +272,8 @@ module Cosmos
272
272
  describe "get_cmd_param_list" do
273
273
  it "returns all the parameters for a command" do
274
274
  list = get_cmd_param_list("INST", "COLLECT")
275
- expect(list).to include(["TYPE", 0, {"NORMAL"=>0, "SPECIAL"=>1}, "Collect type", nil, nil, true])
275
+ #puts list
276
+ expect(list).to include(["TYPE", 0, {"NORMAL"=>0, "SPECIAL"=>1}, "Collect type", nil, nil, true, "UINT"])
276
277
  end
277
278
  end
278
279
 
@@ -79,21 +79,37 @@ module Cosmos
79
79
  it "gets file listings" do
80
80
  capture_io do |stdout|
81
81
  expect(self).to receive(:gets) { 'file' }
82
- expect(save_file_dialog(Dir.pwd, "Save Something!!!")).to eql 'file'
82
+ expect(save_file_dialog()).to eql 'file'
83
+ expect(stdout.string).to include "Save File"
84
+ stdout.rewind
85
+ expect(self).to receive(:gets) { 'file' }
86
+ expect(save_file_dialog(Dir.pwd, "Save Something!!!", "*.txt")).to eql 'file'
83
87
  expect(stdout.string).to include "Save Something!!!"
84
88
  stdout.rewind
85
89
  expect(self).to receive(:gets) { 'file' }
86
- expect(open_file_dialog("C:/")).to eql 'file'
90
+ expect(open_file_dialog()).to eql 'file'
87
91
  expect(stdout.string).to include "Open File"
88
92
  stdout.rewind
89
93
  expect(self).to receive(:gets) { 'file' }
94
+ expect(open_file_dialog(Dir.pwd, "Test Open", "*.txt")).to eql 'file'
95
+ expect(stdout.string).to include "Test Open"
96
+ stdout.rewind
97
+ expect(self).to receive(:gets) { 'file' }
90
98
  expect(open_files_dialog()).to eql 'file'
91
99
  expect(stdout.string).to include "Open File(s)"
92
100
  stdout.rewind
101
+ expect(self).to receive(:gets) { 'file' }
102
+ expect(open_files_dialog(Dir.pwd, "Test Open Files")).to eql 'file'
103
+ expect(stdout.string).to include "Test Open Files"
104
+ stdout.rewind
93
105
  expect(self).to receive(:gets) { 'dir' }
94
106
  expect(open_directory_dialog()).to eql 'dir'
95
107
  expect(stdout.string).to include "Open Directory"
96
108
  stdout.rewind
109
+ expect(self).to receive(:gets) { 'dir' }
110
+ expect(open_directory_dialog(Dir.pwd, "Test Dir")).to eql 'dir'
111
+ expect(stdout.string).to include "Test Dir"
112
+ stdout.rewind
97
113
  end
98
114
  end
99
115
  end
@@ -742,4 +758,3 @@ module Cosmos
742
758
 
743
759
  end
744
760
  end
745
-
@@ -168,6 +168,11 @@ module Cosmos
168
168
  expect(packet.target_name).to eql "SYSTEM"
169
169
  expect(packet.packet_name).to eql "META"
170
170
  expect(packet.received_time).to be_within(1).of Time.now
171
+ expect(packet.received_count).to eql 0
172
+ packet = get_packet(id)
173
+ expect(packet.target_name).to eql "SYSTEM"
174
+ expect(packet.packet_name).to eql "META"
175
+ expect(packet.received_time).to be_within(1).of Time.now
171
176
  expect(packet.received_count).to eql 1
172
177
  unsubscribe_packet_data(id)
173
178
  end
@@ -20,13 +20,12 @@ def load(file, wrap = false)
20
20
  end
21
21
 
22
22
  # NOTE: You MUST require simplecov before anything else!
23
- if RUBY_ENGINE == 'ruby' and !ENV['COSMOS_NO_SIMPLECOV']
23
+ if !ENV['COSMOS_NO_SIMPLECOV']
24
24
  require 'simplecov'
25
- require 'coveralls'
26
- Coveralls.wear!
25
+ require 'codecov'
27
26
  SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
28
27
  SimpleCov::Formatter::HTMLFormatter,
29
- Coveralls::SimpleCov::Formatter
28
+ SimpleCov::Formatter::Codecov,
30
29
  ])
31
30
  SimpleCov.start do
32
31
  merge_timeout 12 * 60 * 60 # merge the last 12 hours of results
@@ -87,32 +86,16 @@ RSpec.configure do |config|
87
86
  Cosmos.disable_warnings do
88
87
  Object.const_set(:STDOUT, $saved_stdout_const)
89
88
  end
90
- if RUBY_ENGINE == 'ruby'
91
- # Kill any leftover threads
92
- if Thread.list.length > 1
93
- Thread.list.each do |t|
94
- t.kill if t != Thread.current
95
- end
96
- sleep(0.2)
97
- end
98
- else
99
- # Kill any leftover threads
100
- if Thread.list.length > 2
101
- Thread.list[2..-1].each do |t|
102
- t.kill if t != Thread.current
103
- end
104
- sleep(0.2)
105
- end
106
- end
89
+ kill_leftover_threads()
107
90
  end
108
91
 
109
92
  config.after(:each) do
110
93
  # Make sure we didn't leave any lingering threads
111
- if RUBY_ENGINE == 'ruby'
112
- expect(Thread.list.length).to eql(1), "At end of test expect 1 remaining thread but found #{Thread.list.length}.\nEnsure you kill all spawned threads before the test finishes."
113
- else
114
- expect(Thread.list.length).to be <= 2, "At end of test expect 2 remaining thread but found #{Thread.list.length}.\nEnsure you kill all spawned threads before the test finishes."
115
- end
94
+ threads = running_threads()
95
+ thread_count = threads.size()
96
+ running_threads_str = threads.join("\n")
97
+
98
+ expect(thread_count).to eql(1), "At end of test expect 1 remaining thread but found #{thread_count}.\nEnsure you kill all spawned threads before the test finishes.\nThreads:\n#{running_threads_str}"
116
99
  end
117
100
  end
118
101
 
@@ -152,6 +135,40 @@ def capture_io
152
135
  $stdout = STDOUT
153
136
  end
154
137
 
138
+ # Get a list of running threads, ignoring jruby system threads if necessary.
139
+ def running_threads
140
+ threads = []
141
+ Thread.list.each do |t|
142
+ if RUBY_ENGINE == 'jruby'
143
+ thread_name = JRuby.reference(t).native_thread.get_name
144
+ threads << t.inspect unless thread_name == "Finalizer" or thread_name.include?("JRubyWorker")
145
+ else
146
+ threads << t.inspect
147
+ end
148
+ end
149
+ return threads
150
+ end
151
+
152
+ # Kill threads that are not "main", ignoring jruby system threads if necessary.
153
+ def kill_leftover_threads
154
+ if RUBY_ENGINE == 'jruby'
155
+ if Thread.list.length > 2
156
+ Thread.list.each do |t|
157
+ thread_name = JRuby.reference(t).native_thread.get_name
158
+ t.kill if t != Thread.current and thread_name != "Finalizer" and !thread_name.include?("JRubyWorker")
159
+ end
160
+ sleep(0.2)
161
+ end
162
+ else
163
+ if Thread.list.length > 1
164
+ Thread.list.each do |t|
165
+ t.kill if t != Thread.current
166
+ end
167
+ sleep(0.2)
168
+ end
169
+ end
170
+ end
171
+
155
172
  RSpec.configure do |c|
156
173
  if ENV.key?("PROFILE")
157
174
  c.before(:suite) do
@@ -164,7 +164,7 @@ module Cosmos
164
164
  4
165
165
  end
166
166
  end
167
- expect(IO).to receive(:select).at_least(:once).and_return([])
167
+ expect(IO).to receive(:fast_select).at_least(:once).and_return([])
168
168
  $index = 1
169
169
  ss = TcpipSocketStream.new(write,nil,nil,nil)
170
170
  ss.connect
@@ -174,7 +174,7 @@ module Cosmos
174
174
  it "handles socket timeouts" do
175
175
  write = double("write_socket")
176
176
  allow(write).to receive(:write_nonblock).and_raise(Errno::EWOULDBLOCK)
177
- expect(IO).to receive(:select).at_least(:once).and_return(nil)
177
+ expect(IO).to receive(:fast_select).at_least(:once).and_return(nil)
178
178
  ss = TcpipSocketStream.new(write,nil,nil,nil)
179
179
  ss.connect
180
180
  expect { ss.write('test') }.to raise_error(Timeout::Error)
@@ -44,7 +44,7 @@ module Cosmos
44
44
  describe "instance" do
45
45
  it "creates default ports" do
46
46
  # Don't check the actual port numbers but just that they exist
47
- expect(System.ports.keys).to eql %w(CTS_API TLMVIEWER_API CTS_PREIDENTIFIED CTS_CMD_ROUTER)
47
+ expect(System.ports.keys).to eql %w(CTS_API TLMVIEWER_API CTS_PREIDENTIFIED CTS_CMD_ROUTER REPLAY_API REPLAY_PREIDENTIFIED REPLAY_CMD_ROUTER)
48
48
  end
49
49
 
50
50
  it "creates default paths" do
@@ -201,7 +201,7 @@ module Cosmos
201
201
  # Force a reload of the configuration
202
202
  System.class_eval('@@instance = nil')
203
203
  capture_io do |stdout|
204
- allow(FileUtils).to receive(:cp_r) { raise "Error" }
204
+ allow(Zip::File).to receive(:open) { raise "Error" }
205
205
  System.commands
206
206
  expect(stdout.string).to match "Problem saving configuration"
207
207
  end
@@ -290,8 +290,10 @@ module Cosmos
290
290
 
291
291
  describe "load_configuration" do
292
292
  after(:all) do
293
- File.delete(File.join(@config_targets,'SYSTEM','cmd_tlm','test1_tlm.txt'))
294
- File.delete(File.join(@config_targets,'SYSTEM','cmd_tlm','test2_tlm.txt'))
293
+ test1 = File.join(@config_targets,'SYSTEM','cmd_tlm','test1_tlm.txt')
294
+ FileUtils.rm_f(test1) if File.exist?(test1)
295
+ test2 = File.join(@config_targets,'SYSTEM','cmd_tlm','test2_tlm.txt')
296
+ FileUtils.rm_f(test2) if File.exist?(test2)
295
297
  end
296
298
 
297
299
  it "loads the initial configuration" do
@@ -352,11 +354,11 @@ module Cosmos
352
354
  expect(System.telemetry.packets('SYSTEM').keys).not_to include "TEST2"
353
355
 
354
356
  # Now remove system.txt from the third configuration and try to load it again to cause an error
355
- third_config_path = System.instance.send(:find_configuration, third_config_name)
356
- FileUtils.mv File.join(third_config_path, 'system.txt'), File.join(third_config_path, 'system2.txt')
357
- result, err = System.load_configuration(third_config_name)
358
- expect(result).to eql original_config_name
359
- expect(err).to_not be_nil
357
+ #third_config_path = System.instance.send(:find_configuration, third_config_name)
358
+ #FileUtils.mv File.join(third_config_path, 'system.txt'), File.join(third_config_path, 'system2.txt')
359
+ #result, err = System.load_configuration(third_config_name)
360
+ #expect(result).to eql original_config_name
361
+ #expect(err).to_not be_nil
360
362
  end
361
363
  end
362
364
  end
@@ -164,6 +164,9 @@ module Cosmos
164
164
  tf = Tempfile.new('unittest')
165
165
  tf.puts("REQUIRE system_file.rb")
166
166
  tf.close
167
+
168
+ # Initial require in target lib shouldn't be reported as error
169
+ expect(Logger).to_not receive(:error)
167
170
  Target.new("INST").process_file(tf.path)
168
171
  expect { SystemFile.new }.to_not raise_error
169
172
  File.delete filename
@@ -21,14 +21,58 @@ module Cosmos
21
21
  cts = File.join(Cosmos::USERPATH,'config','tools','cmd_tlm_server','cmd_tlm_server.txt')
22
22
  FileUtils.mkdir_p(File.dirname(cts))
23
23
  File.open(cts,'w') do |file|
24
- file.puts 'INTERFACE INT interface.rb'
24
+ file.puts 'INTERFACE INST_INT interface.rb'
25
+ file.puts ' TARGET INST'
26
+ file.puts ' PROTOCOL READ_WRITE OverrideProtocol'
25
27
  file.puts 'ROUTER ROUTE interface.rb'
28
+ file.puts 'BACKGROUND_TASK example_background_task1.rb'
29
+ file.puts 'BACKGROUND_TASK example_background_task2.rb'
30
+ end
31
+ @background1 = File.join(Cosmos::USERPATH,'lib','example_background_task1.rb')
32
+ File.open(@background1,'w') do |file|
33
+ file.write <<-DOC
34
+ require 'cosmos/tools/cmd_tlm_server/background_task'
35
+ module Cosmos
36
+ class ExampleBackgroundTask1 < BackgroundTask
37
+ def initialize
38
+ super()
39
+ @name = 'Example Background Task1'
40
+ @status = "This is example one"
41
+ end
42
+ def call
43
+ sleep 0.3
44
+ end
45
+ end
46
+ end
47
+ DOC
48
+ end
49
+ @background2 = File.join(Cosmos::USERPATH,'lib','example_background_task2.rb')
50
+ File.open(@background2,'w') do |file|
51
+ file.write <<-DOC
52
+ require 'cosmos/tools/cmd_tlm_server/background_task'
53
+ module Cosmos
54
+ class ExampleBackgroundTask2 < BackgroundTask
55
+ def initialize
56
+ super()
57
+ @name = 'Example Background Task2'
58
+ @status = "This is example two"
59
+ end
60
+ def call
61
+ loop do
62
+ sleep 1
63
+ end
64
+ end
65
+ end
66
+ end
67
+ DOC
26
68
  end
27
69
  end
28
70
 
29
71
  after(:all) do
30
72
  clean_config()
31
73
  FileUtils.rm_rf File.join(Cosmos::USERPATH,'config','tools')
74
+ FileUtils.rm_rf @background1
75
+ FileUtils.rm_rf @background2
32
76
  end
33
77
 
34
78
  before(:each) do
@@ -37,8 +81,8 @@ module Cosmos
37
81
  allow_any_instance_of(Interface).to receive(:disconnect)
38
82
  allow_any_instance_of(Interface).to receive(:write_raw)
39
83
  allow_any_instance_of(Interface).to receive(:read)
84
+ allow_any_instance_of(Interface).to receive(:write)
40
85
  @api = CmdTlmServer.new
41
- allow(@api.commanding).to receive(:send_command_to_target)
42
86
  end
43
87
 
44
88
  after(:each) do
@@ -395,6 +439,15 @@ module Cosmos
395
439
  end
396
440
  end
397
441
 
442
+ describe "get_cmd_buffer" do
443
+ it "returns a command packet buffer" do
444
+ @api.cmd("INST ABORT")
445
+ expect(@api.get_cmd_buffer("INST", "ABORT")[6..7].unpack("n")[0]).to eq 2
446
+ @api.cmd("INST COLLECT with TYPE NORMAL, DURATION 5")
447
+ expect(@api.get_cmd_buffer("INST", "COLLECT")[6..7].unpack("n")[0]).to eq 1
448
+ end
449
+ end
450
+
398
451
  describe "get_cmd_list" do
399
452
  it "returns command names sorted" do
400
453
  result = @api.get_cmd_list("INST")
@@ -431,15 +484,17 @@ module Cosmos
431
484
  result = @api.get_cmd_param_list("INST","COLLECT")
432
485
  # Each element in the results array contains:
433
486
  # name, default, states, description, full units, units, required
434
- expect(result).to include ['TYPE',0,{"NORMAL"=>0,"SPECIAL"=>1},'Collect type',nil,nil,true]
435
- expect(result).to include ['TEMP',0.0,nil,'Collect temperature','Celcius','C',false]
487
+ expect(result).to include ['TYPE',0,{"NORMAL"=>0,"SPECIAL"=>1},'Collect type',nil,nil,true,"UINT"]
488
+ expect(result).to include ['TEMP',0.0,nil,'Collect temperature','Celcius','C',false,"FLOAT"]
436
489
  end
437
490
 
438
491
  it "returns array parameters for the command" do
439
492
  result = @api.get_cmd_param_list("INST","ARYCMD")
440
493
  # Each element in the results array contains:
441
494
  # name, default, states, description, full units, units, required
442
- expect(result).to include ['ARRAY',[],nil,'Array parameter',nil,nil,false]
495
+ expect(result).to include ['ARRAY',[],nil,'Array parameter',nil,nil,false,"FLOAT"]
496
+ # Since ARRAY2 has a format string the default is in quotes
497
+ expect(result).to include ['ARRAY2',"[]",nil,'Array parameter',nil,nil,false,"UINT"]
443
498
  end
444
499
  end
445
500
 
@@ -466,22 +521,42 @@ module Cosmos
466
521
  expect(@api.get_cmd_value("INST", "COLLECT", "RECEIVED_TIMESECONDS")).to eql time.to_f
467
522
  expect(@api.get_cmd_value("INST", "COLLECT", "RECEIVED_COUNT")).to eql 5
468
523
  end
524
+
525
+ it "returns special values for time if time isn't set" do
526
+ time = Time.now
527
+ packet = System.commands.packet("INST", "COLLECT")
528
+ packet.received_time = nil
529
+ packet.restore_defaults
530
+ packet.received_count = 5
531
+ expect(@api.get_cmd_value("INST", "COLLECT", "TYPE")).to eql 'NORMAL'
532
+ expect(@api.get_cmd_value("INST", "COLLECT", "RECEIVED_TIMEFORMATTED")).to eql "No Packet Received Time"
533
+ expect(@api.get_cmd_value("INST", "COLLECT", "RECEIVED_TIMESECONDS")).to eql 0.0
534
+ expect(@api.get_cmd_value("INST", "COLLECT", "RECEIVED_COUNT")).to eql 5
535
+ end
469
536
  end
470
537
 
471
538
  describe "get_cmd_time" do
472
539
  it "returns command times" do
473
540
  time = Time.now
474
541
  time2 = Time.now + 2
475
- packet = System.commands.packet("INST", "COLLECT")
476
- packet.received_time = time
542
+ collect_cmd = System.commands.packet("INST", "COLLECT")
543
+ collect_cmd.received_time = time
544
+ abort_cmd = System.commands.packet("INST", "ABORT")
545
+ abort_cmd.received_time = time + 1
477
546
  packet2 = System.commands.packet("SYSTEM", "STARTLOGGING")
478
547
  packet2.received_time = time2
479
548
  expect(@api.get_cmd_time()).to eql ['SYSTEM', 'STARTLOGGING', time2.tv_sec, time2.tv_usec]
480
- expect(@api.get_cmd_time('INST')).to eql ['INST', 'COLLECT', time.tv_sec, time.tv_usec]
549
+ expect(@api.get_cmd_time('INST')).to eql ['INST', 'ABORT', time.tv_sec + 1, time.tv_usec]
481
550
  expect(@api.get_cmd_time('SYSTEM')).to eql ['SYSTEM', 'STARTLOGGING', time2.tv_sec, time2.tv_usec]
482
551
  expect(@api.get_cmd_time('INST', 'COLLECT')).to eql ['INST', 'COLLECT', time.tv_sec, time.tv_usec]
483
552
  expect(@api.get_cmd_time('SYSTEM', 'STARTLOGGING')).to eql ['SYSTEM', 'STARTLOGGING', time2.tv_sec, time2.tv_usec]
484
553
  end
554
+
555
+ it "returns nil if no times are set" do
556
+ System.commands.packets("INST").each { |name, pkt| pkt.received_time = nil }
557
+ expect(@api.get_cmd_time("INST")).to eql [nil, nil, nil, nil]
558
+ expect(@api.get_cmd_time("INST", "ABORT")).to eql ["INST", "ABORT", nil, nil]
559
+ end
485
560
  end
486
561
 
487
562
  def test_tlm_unknown(method)
@@ -499,12 +574,11 @@ module Cosmos
499
574
  end
500
575
 
501
576
  it "processes a string" do
502
- value = @api.tlm("INST HEALTH_STATUS TEMP1")
503
- expect(value).to eql -100.0
577
+ expect(@api.tlm("INST HEALTH_STATUS TEMP1")).to eql -100.0
504
578
  end
505
579
 
506
580
  it "processes parameters" do
507
- value = @api.tlm("INST","HEALTH_STATUS","TEMP1")
581
+ expect(@api.tlm("INST","HEALTH_STATUS","TEMP1")).to eql -100.0
508
582
  end
509
583
 
510
584
  it "complains if too many parameters" do
@@ -603,7 +677,7 @@ module Cosmos
603
677
  end
604
678
 
605
679
  describe "set_tlm" do
606
- it "complains about unknown targets, commands, and parameters" do
680
+ it "complains about unknown targets, packets, and parameters" do
607
681
  expect { @api.set_tlm("BLAH HEALTH_STATUS COLLECTS = 1") }.to raise_error(/does not exist/)
608
682
  expect { @api.set_tlm("INST UNKNOWN COLLECTS = 1") }.to raise_error(/does not exist/)
609
683
  expect { @api.set_tlm("INST HEALTH_STATUS BLAH = 1") }.to raise_error(/does not exist/)
@@ -612,6 +686,19 @@ module Cosmos
612
686
  expect { @api.set_tlm("INST","HEALTH_STATUS","BLAH",1) }.to raise_error(/does not exist/)
613
687
  end
614
688
 
689
+ it "doesn't allow SYSTEM META PKTID or CONFIG" do
690
+ expect { @api.set_tlm("SYSTEM META PKTID = 1") }.to raise_error(/set_tlm not allowed/)
691
+ expect { @api.set_tlm("SYSTEM META CONFIG = 1") }.to raise_error(/set_tlm not allowed/)
692
+ end
693
+
694
+ it "sets SYSTEM META command as well as tlm" do
695
+ cmd = System.commands.packet("SYSTEM", "META")
696
+ tlm = System.telemetry.packet("SYSTEM", "META")
697
+ @api.set_tlm("SYSTEM META RUBY_VERSION = 1.8.0")
698
+ expect(cmd.read("RUBY_VERSION")).to eq("1.8.0")
699
+ expect(tlm.read("RUBY_VERSION")).to eq("1.8.0")
700
+ end
701
+
615
702
  it "processes a string" do
616
703
  @api.set_tlm("INST HEALTH_STATUS TEMP1 = 0.0")
617
704
  expect(@api.tlm("INST HEALTH_STATUS TEMP1")).to be_within(0.00001).of(-0.05759)
@@ -628,7 +715,7 @@ module Cosmos
628
715
  end
629
716
 
630
717
  describe "set_tlm_raw" do
631
- it "complains about unknown targets, commands, and parameters" do
718
+ it "complains about unknown targets, packets, and parameters" do
632
719
  expect { @api.set_tlm_raw("BLAH HEALTH_STATUS COLLECTS = 1") }.to raise_error(/does not exist/)
633
720
  expect { @api.set_tlm_raw("INST UNKNOWN COLLECTS = 1") }.to raise_error(/does not exist/)
634
721
  expect { @api.set_tlm_raw("INST HEALTH_STATUS BLAH = 1") }.to raise_error(/does not exist/)
@@ -648,6 +735,148 @@ module Cosmos
648
735
  end
649
736
  end
650
737
 
738
+ describe "inject_tlm" do
739
+ it "complains about non-existant targets" do
740
+ expect { @api.inject_tlm("BLAH","HEALTH_STATUS") }.to raise_error(RuntimeError, "Unknown target: BLAH")
741
+ end
742
+
743
+ it "complains about non-existant packets" do
744
+ expect { @api.inject_tlm("INST","BLAH") }.to raise_error(RuntimeError, "Telemetry packet 'INST BLAH' does not exist")
745
+ end
746
+
747
+ it "complains about non-existant items" do
748
+ expect { @api.inject_tlm("INST","HEALTH_STATUS",{BLAH: 0}) }.to raise_error(RuntimeError, "Packet item 'INST HEALTH_STATUS BLAH' does not exist")
749
+ end
750
+
751
+ it "logs errors writing routers" do
752
+ @api.inject_tlm("INST","HEALTH_STATUS",{TEMP1: 50, TEMP2: 50, TEMP3: 50, TEMP4: 50}, :CONVERTED)
753
+ allow_any_instance_of(Interface).to receive(:write_allowed?).and_raise("PROBLEM!")
754
+ expect(Logger).to receive(:error) do |msg|
755
+ expect(msg).to match /Problem writing to router/
756
+ end
757
+ @api.inject_tlm("INST","HEALTH_STATUS")
758
+ end
759
+
760
+ it "injects a packet into the system" do
761
+ @api.inject_tlm("INST","HEALTH_STATUS",{TEMP1: 10, TEMP2: 20}, :CONVERTED, true, true, false)
762
+ expect(@api.tlm("INST HEALTH_STATUS TEMP1")).to be_within(0.1).of(10.0)
763
+ expect(@api.tlm("INST HEALTH_STATUS TEMP2")).to be_within(0.1).of(20.0)
764
+ @api.inject_tlm("INST","HEALTH_STATUS",{TEMP1: 0, TEMP2: 0}, :RAW, true, true, false)
765
+ expect(@api.tlm("INST HEALTH_STATUS TEMP1")).to eql -100.0
766
+ expect(@api.tlm("INST HEALTH_STATUS TEMP2")).to eql -100.0
767
+ end
768
+
769
+ it "writes to routers and logs even if the packet has no interface" do
770
+ sys = System.targets["SYSTEM"]
771
+ interface = sys.interface
772
+ sys.interface = nil
773
+
774
+ allow_any_instance_of(Interface).to receive(:write_allowed?).and_raise("PROBLEM!")
775
+ expect(Logger).to receive(:error) do |msg|
776
+ expect(msg).to match /Problem writing to router/
777
+ end
778
+
779
+ @api.inject_tlm("SYSTEM","LIMITS_CHANGE")
780
+ sys.interface = interface
781
+ end
782
+ end
783
+
784
+ describe "override_tlm" do
785
+ it "complains about unknown targets, packets, and parameters" do
786
+ expect { @api.override_tlm("BLAH HEALTH_STATUS COLLECTS = 1") }.to raise_error(/does not exist/)
787
+ expect { @api.override_tlm("INST UNKNOWN COLLECTS = 1") }.to raise_error(/does not exist/)
788
+ expect { @api.override_tlm("INST HEALTH_STATUS BLAH = 1") }.to raise_error(/does not exist/)
789
+ expect { @api.override_tlm("BLAH","HEALTH_STATUS","COLLECTS",1) }.to raise_error(/does not exist/)
790
+ expect { @api.override_tlm("INST","UNKNOWN","COLLECTS",1) }.to raise_error(/does not exist/)
791
+ expect { @api.override_tlm("INST","HEALTH_STATUS","BLAH",1) }.to raise_error(/does not exist/)
792
+ end
793
+
794
+ it "complains if the target has no interface" do
795
+ expect { @api.override_tlm("SYSTEM META PKTID = 1") }.to raise_error(/Target 'SYSTEM' has no interface/)
796
+ end
797
+
798
+ it "complains if the target doesn't have OVERRIDE protocol" do
799
+ interface = OpenStruct.new
800
+ interface.name = "SYSTEM_INT"
801
+ System.targets["SYSTEM"].interface = interface # Set a dummy interface
802
+ expect { @api.override_tlm("SYSTEM META PKTID = 1") }.to raise_error(/Interface SYSTEM_INT does not have override/)
803
+ System.targets["SYSTEM"].interface = nil
804
+ end
805
+
806
+ it "complains with too many parameters" do
807
+ expect { @api.override_tlm("INST","HEALTH_STATUS","TEMP1","TEMP2",0.0) }.to raise_error(/Invalid number of arguments/)
808
+ end
809
+
810
+ it "calls _override_tlm in the interface" do
811
+ int = System.targets["INST"].interface
812
+ expect(int).to receive("_override_tlm").with("INST","HEALTH_STATUS","TEMP1",100.0)
813
+ @api.override_tlm("INST HEALTH_STATUS TEMP1 = 100.0")
814
+ expect(int).to receive("_override_tlm").with("INST","HEALTH_STATUS","TEMP2",50.0)
815
+ @api.override_tlm("INST","HEALTH_STATUS","TEMP2", 50.0)
816
+ end
817
+ end
818
+
819
+ describe "override_tlm_raw" do
820
+ it "complains about unknown targets, commands, and parameters" do
821
+ expect { @api.override_tlm_raw("BLAH HEALTH_STATUS COLLECTS = 1") }.to raise_error(/does not exist/)
822
+ expect { @api.override_tlm_raw("INST UNKNOWN COLLECTS = 1") }.to raise_error(/does not exist/)
823
+ expect { @api.override_tlm_raw("INST HEALTH_STATUS BLAH = 1") }.to raise_error(/does not exist/)
824
+ expect { @api.override_tlm_raw("BLAH","HEALTH_STATUS","COLLECTS",1) }.to raise_error(/does not exist/)
825
+ expect { @api.override_tlm_raw("INST","UNKNOWN","COLLECTS",1) }.to raise_error(/does not exist/)
826
+ expect { @api.override_tlm_raw("INST","HEALTH_STATUS","BLAH",1) }.to raise_error(/does not exist/)
827
+ end
828
+
829
+ it "complains if the target has no interface" do
830
+ expect { @api.override_tlm_raw("SYSTEM META PKTID = 1") }.to raise_error(/Target 'SYSTEM' has no interface/)
831
+ end
832
+
833
+ it "complains with too many parameters" do
834
+ expect { @api.override_tlm_raw("INST","HEALTH_STATUS","TEMP1","TEMP2",0.0) }.to raise_error(/Invalid number of arguments/)
835
+ end
836
+
837
+ it "calls _override_tlm_raw in the interface" do
838
+ int = System.targets["INST"].interface
839
+ expect(int).to receive("_override_tlm_raw").with("INST","HEALTH_STATUS","TEMP1",100.0)
840
+ @api.override_tlm_raw("INST HEALTH_STATUS TEMP1 = 100.0")
841
+ expect(int).to receive("_override_tlm_raw").with("INST","HEALTH_STATUS","TEMP2",50.0)
842
+ @api.override_tlm_raw("INST","HEALTH_STATUS","TEMP2", 50.0)
843
+ end
844
+ end
845
+
846
+ describe "normalize_tlm" do
847
+ it "complains about unknown targets, commands, and parameters" do
848
+ expect { @api.normalize_tlm("BLAH HEALTH_STATUS COLLECTS") }.to raise_error(/does not exist/)
849
+ expect { @api.normalize_tlm("INST UNKNOWN COLLECTS") }.to raise_error(/does not exist/)
850
+ expect { @api.normalize_tlm("INST HEALTH_STATUS BLAH") }.to raise_error(/does not exist/)
851
+ expect { @api.normalize_tlm("BLAH","HEALTH_STATUS","COLLECTS") }.to raise_error(/does not exist/)
852
+ expect { @api.normalize_tlm("INST","UNKNOWN","COLLECTS") }.to raise_error(/does not exist/)
853
+ expect { @api.normalize_tlm("INST","HEALTH_STATUS","BLAH") }.to raise_error(/does not exist/)
854
+ end
855
+
856
+ it "complains if the target has no interface" do
857
+ expect { @api.normalize_tlm("SYSTEM META PKTID") }.to raise_error(/Target 'SYSTEM' has no interface/)
858
+ end
859
+
860
+ it "complains with too many parameters" do
861
+ expect { @api.normalize_tlm("INST","HEALTH_STATUS","TEMP1",0.0) }.to raise_error(/Invalid number of arguments/)
862
+ end
863
+
864
+ it "calls _normalize_tlm in the interface" do
865
+ int = System.targets["INST"].interface
866
+ expect(int).to receive("_normalize_tlm").with("INST","HEALTH_STATUS","TEMP1")
867
+ @api.normalize_tlm("INST HEALTH_STATUS TEMP1")
868
+ expect(int).to receive("_normalize_tlm").with("INST","HEALTH_STATUS","TEMP2")
869
+ @api.normalize_tlm("INST","HEALTH_STATUS","TEMP2")
870
+ end
871
+ end
872
+
873
+ describe "get_tlm_buffer" do
874
+ it "returns a telemetry packet buffer" do
875
+ @api.inject_tlm("INST","HEALTH_STATUS",{TIMESEC: 0xDEADBEEF})
876
+ expect(@api.get_tlm_buffer("INST", "HEALTH_STATUS")[6..10].unpack("N")[0]).to eq 0xDEADBEEF
877
+ end
878
+ end
879
+
651
880
  describe "get_tlm_packet" do
652
881
  it "complains about non-existant targets" do
653
882
  expect { @api.get_tlm_packet("BLAH","HEALTH_STATUS") }.to raise_error(RuntimeError, "Telemetry target 'BLAH' does not exist")
@@ -666,15 +895,18 @@ module Cosmos
666
895
  end
667
896
 
668
897
  it "reads all telemetry items with their limits states" do
898
+ # Call inject_tlm to ensure the limits are set
899
+ @api.inject_tlm("INST","HEALTH_STATUS",{TEMP1: 0, TEMP2: 0, TEMP3: 0, TEMP4: 0}, :RAW)
900
+
669
901
  vals = @api.get_tlm_packet("INST","HEALTH_STATUS")
670
902
  expect(vals[0][0]).to eql "RECEIVED_TIMESECONDS"
671
- expect(vals[0][1]).to eql 0.0
903
+ expect(vals[0][1]).to be > 0
672
904
  expect(vals[0][2]).to be_nil
673
905
  expect(vals[1][0]).to eql "RECEIVED_TIMEFORMATTED"
674
- expect(vals[1][1]).to eql "No Packet Received Time"
906
+ expect(vals[1][1].split(' ')[0]).to eql Time.now.formatted.split(' ')[0]
675
907
  expect(vals[1][2]).to be_nil
676
908
  expect(vals[2][0]).to eql "RECEIVED_COUNT"
677
- expect(vals[2][1]).to eql 0
909
+ expect(vals[2][1]).to be > 0
678
910
  expect(vals[2][2]).to be_nil
679
911
  # Spot check a few more
680
912
  expect(vals[22][0]).to eql "TEMP1"
@@ -872,6 +1104,7 @@ module Cosmos
872
1104
 
873
1105
  describe "get_out_of_limits" do
874
1106
  it "returns all out of limits items" do
1107
+ @api.inject_tlm("INST","HEALTH_STATUS",{TEMP1: 0, TEMP2: 0, TEMP3: 0, TEMP4: 0}, :RAW)
875
1108
  items = @api.get_out_of_limits
876
1109
  (0..3).each do |i|
877
1110
  expect(items[i][0]).to eql "INST"
@@ -882,6 +1115,13 @@ module Cosmos
882
1115
  end
883
1116
  end
884
1117
 
1118
+ describe "get_overall_limits_state" do
1119
+ it "returns the overall system limits state" do
1120
+ @api.inject_tlm("INST","HEALTH_STATUS",{TEMP1: 0, TEMP2: 0, TEMP3: 0, TEMP4: 0}, :RAW)
1121
+ expect(@api.get_overall_limits_state).to eq :RED
1122
+ end
1123
+ end
1124
+
885
1125
  describe "limits_enabled?" do
886
1126
  it "complains about non-existant targets" do
887
1127
  expect { @api.limits_enabled?("BLAH","HEALTH_STATUS","TEMP1") }.to raise_error(RuntimeError, "Telemetry target 'BLAH' does not exist")
@@ -943,6 +1183,28 @@ module Cosmos
943
1183
  end
944
1184
  end
945
1185
 
1186
+ describe "get_stale" do
1187
+ it "complains about non-existant targets" do
1188
+ expect { @api.get_stale(false,"BLAH") }.to raise_error(RuntimeError, "Telemetry target 'BLAH' does not exist")
1189
+ end
1190
+
1191
+ it "gets stale packets for the specified target" do
1192
+ # By calling check_limits we make HEALTH_STATUS not stale
1193
+ System.telemetry.packet("INST","HEALTH_STATUS").check_limits
1194
+ stale = @api.get_stale(false,"INST").sort
1195
+ inst_pkts = []
1196
+ System.telemetry.packets("INST").each do |name, pkt|
1197
+ next if name == "HEALTH_STATUS" # not stale
1198
+ inst_pkts << ["INST", name]
1199
+ end
1200
+ expect(stale).to eq inst_pkts.sort
1201
+
1202
+ # Passing true only gets packets with limits items
1203
+ stale = @api.get_stale(true,"INST").sort
1204
+ expect(stale).to eq [["INST","PARAMS"]]
1205
+ end
1206
+ end
1207
+
946
1208
  describe "get_limits" do
947
1209
  it "complains about non-existant targets" do
948
1210
  expect { @api.get_limits("BLAH","HEALTH_STATUS","TEMP1") }.to raise_error(RuntimeError, "Telemetry target 'BLAH' does not exist")
@@ -1084,27 +1346,276 @@ module Cosmos
1084
1346
  end
1085
1347
  end
1086
1348
 
1349
+ describe "get_packet" do
1350
+ it "creates a packet out of the get_packet_data" do
1351
+ time = Time.now
1352
+ expect(CmdTlmServer).to receive(:get_packet_data).and_return(["\xAB","INST","HEALTH_STATUS",time.to_f,0,10])
1353
+ pkt = @api.get_packet(10)
1354
+ expect(pkt.buffer[0]).to eq "\xAB"
1355
+ expect(pkt.target_name).to eq "INST"
1356
+ expect(pkt.packet_name).to eq "HEALTH_STATUS"
1357
+ expect(pkt.received_time.formatted).to eq time.formatted
1358
+ expect(pkt.received_count).to eq 10
1359
+ end
1360
+ end
1361
+
1362
+ describe "subscribe_server_messages" do
1363
+ it "calls CmdTlmServer" do
1364
+ stub_const("Cosmos::CmdTlmServer::DEFAULT_SERVER_MESSAGES_QUEUE_SIZE", 100)
1365
+ expect(CmdTlmServer).to receive(:subscribe_server_messages)
1366
+ @api.subscribe_server_messages
1367
+ end
1368
+ end
1369
+
1370
+ describe "unsubscribe_server_messages" do
1371
+ it "calls CmdTlmServer" do
1372
+ expect(CmdTlmServer).to receive(:unsubscribe_server_messages)
1373
+ @api.unsubscribe_server_messages(0)
1374
+ end
1375
+ end
1376
+
1377
+ describe "get_server_message" do
1378
+ it "gets a server message" do
1379
+ expect(CmdTlmServer).to receive(:get_server_message)
1380
+ @api.get_server_message(0)
1381
+ end
1382
+ end
1383
+
1384
+ describe "get_interface_targets" do
1385
+ it "returns the targets associated with an interface" do
1386
+ expect(@api.get_interface_targets("INST_INT")).to eql ["INST"]
1387
+ end
1388
+ end
1389
+
1390
+ describe "get_background_tasks" do
1391
+ it "gets background task details" do
1392
+ sleep 0.1
1393
+ tasks = @api.get_background_tasks
1394
+ expect(tasks[0][0]).to eql("Example Background Task1")
1395
+ expect(tasks[0][1]).to eql("sleep")
1396
+ expect(tasks[0][2]).to eql("This is example one")
1397
+ expect(tasks[1][0]).to eql("Example Background Task2")
1398
+ expect(tasks[1][1]).to eql("sleep")
1399
+ expect(tasks[1][2]).to eql("This is example two")
1400
+ sleep 0.5
1401
+ tasks = @api.get_background_tasks
1402
+ expect(tasks[0][0]).to eql("Example Background Task1")
1403
+ expect(tasks[0][1]).to eql("complete") # Thread completes
1404
+ expect(tasks[0][2]).to eql("This is example one")
1405
+ expect(tasks[1][0]).to eql("Example Background Task2")
1406
+ expect(tasks[1][1]).to eql("sleep")
1407
+ expect(tasks[1][2]).to eql("This is example two")
1408
+ end
1409
+ end
1410
+
1411
+ describe "get_server_status" do
1412
+ it "gets server details" do
1413
+ status = @api.get_server_status
1414
+ expect(status[0]).to eql 'DEFAULT'
1415
+ expect(status[1]).to eql 7777
1416
+ expect(status[2]).to eql 0
1417
+ expect(status[3]).to eql 0
1418
+ expect(status[4]).to eql 0.0
1419
+ expect(status[5]).to be > 10
1420
+ end
1421
+ end
1422
+
1423
+ describe "get_target_info" do
1424
+ it "complains about non-existant targets" do
1425
+ expect { @api.get_target_info("BLAH") }.to raise_error(RuntimeError, "Unknown target: BLAH")
1426
+ end
1427
+
1428
+ it "gets target cmd tlm count" do
1429
+ cmd1, tlm1 = @api.get_target_info("INST")
1430
+ @api.cmd("INST ABORT")
1431
+ @api.inject_tlm("INST","HEALTH_STATUS")
1432
+ cmd2, tlm2 = @api.get_target_info("INST")
1433
+ expect(cmd2 - cmd1).to eq 1
1434
+ expect(tlm2 - tlm1).to eq 1
1435
+ end
1436
+ end
1437
+
1438
+ describe "get_all_target_info" do
1439
+ it "gets target name, interface name, cmd & tlm count" do
1440
+ @api.cmd("INST ABORT")
1441
+ @api.inject_tlm("INST","HEALTH_STATUS")
1442
+ info = @api.get_all_target_info().sort
1443
+ expect(info[0][0]).to eq "INST"
1444
+ expect(info[0][1]).to eq "INST_INT"
1445
+ expect(info[0][2]).to be > 0
1446
+ expect(info[0][3]).to be > 0
1447
+ expect(info[1][0]).to eq "SYSTEM"
1448
+ expect(info[1][1]).to eq "" # No interface
1449
+ end
1450
+ end
1451
+
1452
+ describe "get_interface_info" do
1453
+ it "complains about non-existant interfaces" do
1454
+ expect { @api.get_interface_info("BLAH") }.to raise_error(RuntimeError, "Unknown interface: BLAH")
1455
+ end
1456
+
1457
+ it "gets interface info" do
1458
+ info = @api.get_interface_info("INST_INT")
1459
+ expect(info[0]).to eq "ATTEMPTING"
1460
+ expect(info[1..-1]).to eq [0,0,0,0,0,0,0]
1461
+ end
1462
+ end
1463
+
1464
+ describe "get_all_interface_info" do
1465
+ it "gets interface name and all info" do
1466
+ info = @api.get_all_interface_info.sort
1467
+ expect(info[0][0]).to eq "INST_INT"
1468
+ end
1469
+ end
1470
+
1471
+ describe "get_router_names" do
1472
+ it "returns all router names" do
1473
+ expect(@api.get_router_names.sort).to eq %w(PREIDENTIFIED_CMD_ROUTER PREIDENTIFIED_ROUTER ROUTE)
1474
+ end
1475
+ end
1476
+
1477
+ describe "get_router_info" do
1478
+ it "complains about non-existant routers" do
1479
+ expect { @api.get_router_info("BLAH") }.to raise_error(RuntimeError, "Unknown router: BLAH")
1480
+ end
1481
+
1482
+ it "gets router info" do
1483
+ info = @api.get_router_info("ROUTE")
1484
+ expect(info[0]).to eq "ATTEMPTING"
1485
+ expect(info[1..-1]).to eq [0,0,0,0,0,0,0]
1486
+ end
1487
+ end
1488
+
1489
+ describe "get_all_router_info" do
1490
+ it "gets router name and all info" do
1491
+ info = @api.get_all_router_info.sort
1492
+ expect(info[0][0]).to eq "PREIDENTIFIED_CMD_ROUTER"
1493
+ expect(info[1][0]).to eq "PREIDENTIFIED_ROUTER"
1494
+ expect(info[2][0]).to eq "ROUTE"
1495
+ end
1496
+ end
1497
+
1498
+ describe "get_cmd_cnt" do
1499
+ it "complains about non-existant targets" do
1500
+ expect { @api.get_cmd_cnt("BLAH", "ABORT") }.to raise_error(RuntimeError, /does not exist/)
1501
+ end
1502
+
1503
+ it "complains about non-existant packets" do
1504
+ expect { @api.get_cmd_cnt("INST", "BLAH") }.to raise_error(RuntimeError, /does not exist/)
1505
+ end
1506
+
1507
+ it "gets the command packet count" do
1508
+ cnt1 = @api.get_cmd_cnt("INST", "ABORT")
1509
+ @api.cmd("INST", "ABORT")
1510
+ cnt2 = @api.get_cmd_cnt("INST", "ABORT")
1511
+ expect(cnt2 - cnt1).to eq 1
1512
+ end
1513
+ end
1514
+
1515
+ describe "get_tlm_cnt" do
1516
+ it "complains about non-existant targets" do
1517
+ expect { @api.get_tlm_cnt("BLAH", "ABORT") }.to raise_error(RuntimeError, /does not exist/)
1518
+ end
1519
+
1520
+ it "complains about non-existant packets" do
1521
+ expect { @api.get_tlm_cnt("INST", "BLAH") }.to raise_error(RuntimeError, /does not exist/)
1522
+ end
1523
+
1524
+ it "gets the telemetry packet count" do
1525
+ cnt1 = @api.get_tlm_cnt("INST", "ADCS")
1526
+ @api.inject_tlm("INST","ADCS")
1527
+ cnt2 = @api.get_tlm_cnt("INST", "ADCS")
1528
+ expect(cnt2 - cnt1).to eq 1
1529
+ end
1530
+ end
1531
+
1532
+ describe "get_all_cmd_info" do
1533
+ it "gets tgt, pkt, rx cnt for all commands" do
1534
+ total = 1 # Unknown is 1
1535
+ System.commands.target_names.each do |tgt|
1536
+ total += System.commands.packets(tgt).keys.length
1537
+ end
1538
+ info = @api.get_all_cmd_info.sort
1539
+ expect(info.length).to eq total
1540
+ expect(info[0][0]).to eq "INST"
1541
+ expect(info[0][1]).to eq "ABORT"
1542
+ expect(info[0][2]).to be >= 0
1543
+ expect(info[-1][0]).to eq "UNKNOWN"
1544
+ expect(info[-1][1]).to eq "UNKNOWN"
1545
+ expect(info[-1][2]).to eq 0
1546
+ end
1547
+ end
1548
+
1549
+ describe "get_all_tlm_info" do
1550
+ it "gets tgt, pkt, rx cnt for all telemetry" do
1551
+ total = 1 # Unknown is 1
1552
+ System.telemetry.target_names.each do |tgt|
1553
+ total += System.telemetry.packets(tgt).keys.length
1554
+ end
1555
+ info = @api.get_all_tlm_info.sort
1556
+ expect(info.length).to eq total
1557
+ expect(info[0][0]).to eq "INST"
1558
+ expect(info[0][1]).to eq "ADCS"
1559
+ expect(info[0][2]).to be >= 0
1560
+ expect(info[-1][0]).to eq "UNKNOWN"
1561
+ expect(info[-1][1]).to eq "UNKNOWN"
1562
+ expect(info[-1][2]).to eq 0
1563
+ end
1564
+ end
1565
+
1566
+ describe "get_packet_logger_info" do
1567
+ it "complains about non-existant loggers" do
1568
+ expect { @api.get_packet_logger_info("BLAH") }.to raise_error(RuntimeError, "Unknown packet log writer: BLAH")
1569
+ end
1570
+
1571
+ it "gets packet logger info" do
1572
+ info = @api.get_packet_logger_info("DEFAULT")
1573
+ expect(info[0]).to eq ["INST_INT"]
1574
+ end
1575
+ end
1576
+
1577
+ describe "get_all_packet_logger_info" do
1578
+ it "gets all packet loggers info" do
1579
+ info = @api.get_all_packet_logger_info.sort
1580
+ expect(info[0][0]).to eq "DEFAULT"
1581
+ expect(info[0][1]).to eq ["INST_INT"]
1582
+ end
1583
+ end
1584
+
1585
+ describe "background_task apis" do
1586
+ it "starts, gets into, and stops background tasks" do
1587
+ @api.start_background_task("Example Background Task2")
1588
+ sleep 0.1
1589
+ info = @api.get_background_tasks.sort
1590
+ expect(info[1][0]).to eq "Example Background Task2"
1591
+ expect(info[1][1]).to eq "sleep"
1592
+ expect(info[1][2]).to eq "This is example two"
1593
+ @api.stop_background_task("Example Background Task2")
1594
+ sleep 0.1
1595
+ info = @api.get_background_tasks.sort
1596
+ expect(info[1][0]).to eq "Example Background Task2"
1597
+ expect(info[1][1]).to eq "complete"
1598
+ expect(info[1][2]).to eq "This is example two"
1599
+ end
1600
+ end
1601
+
1087
1602
  # All these methods simply pass through directly to CmdTlmServer without
1088
1603
  # adding any functionality. Thus we just test that they are are received
1089
1604
  # by the CmdTlmServer.
1090
1605
  describe "CmdTlmServer pass-throughs" do
1091
1606
  it "calls through to the CmdTlmServer" do
1092
1607
  @api.get_interface_names
1093
- @api.connect_interface("INT")
1094
- @api.disconnect_interface("INT")
1095
- @api.interface_state("INT")
1096
- @api.map_target_to_interface("INST", "INT")
1097
- @api.get_interface_info("INT")
1098
- @api.get_target_info("INST")
1099
- @api.get_cmd_cnt("INST", "COLLECT")
1100
- @api.get_tlm_cnt("INST", "HEALTH_STATUS")
1101
- @api.get_router_info("ROUTE")
1102
- @api.get_packet_logger_info('DEFAULT')
1103
- @api.get_router_names
1608
+ @api.connect_interface("INST_INT")
1609
+ @api.disconnect_interface("INST_INT")
1610
+ @api.interface_state("INST_INT")
1611
+ @api.map_target_to_interface("INST", "INST_INT")
1612
+ @api.get_target_ignored_parameters("INST")
1613
+ @api.get_target_ignored_items("INST")
1614
+ @api.get_packet_loggers
1104
1615
  @api.connect_router("ROUTE")
1105
1616
  @api.disconnect_router("ROUTE")
1106
1617
  @api.router_state("ROUTE")
1107
- @api.send_raw("INT","\x00\x01")
1618
+ @api.send_raw("INST_INT","\x00\x01")
1108
1619
  @api.get_cmd_log_filename('DEFAULT')
1109
1620
  @api.get_tlm_log_filename('DEFAULT')
1110
1621
  @api.start_logging('ALL')
@@ -1115,9 +1626,12 @@ module Cosmos
1115
1626
  @api.stop_tlm_log('ALL')
1116
1627
  @api.get_server_message_log_filename
1117
1628
  @api.start_new_server_message_log
1629
+ @api.start_raw_logging_interface
1630
+ @api.stop_raw_logging_interface
1631
+ @api.start_raw_logging_router
1632
+ @api.stop_raw_logging_router
1118
1633
  end
1119
1634
  end
1120
1635
 
1121
1636
  end
1122
1637
  end
1123
-