cosmos 4.0.3-java → 4.1.0-java

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.
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 +12 -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
-