cosmos 3.3.3 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.travis.yml +2 -1
  4. data/Gemfile +4 -3
  5. data/Manifest.txt +22 -0
  6. data/autohotkey/tools/handbook_creator.ahk +9 -0
  7. data/autohotkey/tools/packet_viewer.ahk +4 -0
  8. data/bin/exchndl20-x64.dll +0 -0
  9. data/bin/exchndl20.dll +0 -0
  10. data/bin/exchndl21-x64.dll +0 -0
  11. data/bin/exchndl21.dll +0 -0
  12. data/bin/exchndl22-x64.dll +0 -0
  13. data/bin/exchndl22.dll +0 -0
  14. data/bin/mgwhelp-x64.dll +0 -0
  15. data/bin/mgwhelp.dll +0 -0
  16. data/cosmos.gemspec +1 -0
  17. data/data/crc.txt +30 -24
  18. data/demo/config/data/crc.txt +3 -3
  19. data/demo/config/tools/handbook_creator/templates/command_packets.html.erb +3 -1
  20. data/demo/config/tools/handbook_creator/templates/telemetry_packets.html.erb +3 -1
  21. data/demo/procedures/cosmos_api_test.rb +1 -1
  22. data/ext/cosmos/ext/low_fragmentation_array/low_fragmentation_array.c +4 -0
  23. data/ext/cosmos/ext/platform/platform.c +22 -2
  24. data/ext/cosmos/ext/structure/structure.c +631 -104
  25. data/ext/cosmos/ext/telemetry/telemetry.c +3 -2
  26. data/lib/cosmos/gui/line_graph/line_graph_drawing.rb +71 -92
  27. data/lib/cosmos/gui/line_graph/overview_graph.rb +1 -1
  28. data/lib/cosmos/gui/qt.rb +38 -24
  29. data/lib/cosmos/gui/text/ruby_editor.rb +1 -1
  30. data/lib/cosmos/packets/binary_accessor.rb +1 -288
  31. data/lib/cosmos/packets/telemetry.rb +2 -1
  32. data/lib/cosmos/script/cmd_tlm_server.rb +110 -0
  33. data/lib/cosmos/script/commands.rb +166 -0
  34. data/lib/cosmos/script/extract.rb +2 -2
  35. data/lib/cosmos/script/limits.rb +108 -0
  36. data/lib/cosmos/script/script.rb +28 -1487
  37. data/lib/cosmos/script/scripting.rb +889 -0
  38. data/lib/cosmos/script/telemetry.rb +174 -0
  39. data/lib/cosmos/script/tools.rb +138 -0
  40. data/lib/cosmos/streams/stream_protocol.rb +9 -6
  41. data/lib/cosmos/system/target.rb +55 -38
  42. data/lib/cosmos/tools/cmd_tlm_server/api.rb +6 -3
  43. data/lib/cosmos/tools/cmd_tlm_server/connections.rb +0 -1
  44. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +17 -7
  45. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +15 -4
  46. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +15 -8
  47. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +41 -13
  48. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +18 -1
  49. data/lib/cosmos/tools/tlm_viewer/widgets/canvasline_widget.rb +1 -1
  50. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslinevalue_widget.rb +1 -1
  51. data/lib/cosmos/tools/tlm_viewer/widgets/limitsbar_widget.rb +1 -1
  52. data/lib/cosmos/tools/tlm_viewer/widgets/rangebar_widget.rb +1 -1
  53. data/lib/cosmos/top_level.rb +1 -1
  54. data/lib/cosmos/utilities/ruby_lex_utils.rb +1 -1
  55. data/lib/cosmos/version.rb +5 -5
  56. data/spec/gui/line_graph/line_clip_spec.rb +6 -6
  57. data/spec/gui/qt_spec.rb +102 -0
  58. data/spec/interfaces/interface_spec.rb +9 -9
  59. data/spec/interfaces/linc_interface_spec.rb +72 -15
  60. data/spec/interfaces/serial_interface_spec.rb +9 -9
  61. data/spec/interfaces/simulated_target_interface_spec.rb +7 -7
  62. data/spec/interfaces/stream_interface_spec.rb +4 -4
  63. data/spec/interfaces/tcpip_client_interface_spec.rb +8 -8
  64. data/spec/interfaces/tcpip_server_interface_spec.rb +9 -9
  65. data/spec/interfaces/udp_interface_spec.rb +20 -20
  66. data/spec/io/json_drb_spec.rb +4 -4
  67. data/spec/io/raw_logger_pair_spec.rb +20 -20
  68. data/spec/io/raw_logger_spec.rb +3 -3
  69. data/spec/io/tcpip_server_spec.rb +9 -9
  70. data/spec/io/udp_sockets_spec.rb +2 -2
  71. data/spec/io/win32_serial_driver_spec.rb +2 -2
  72. data/spec/packets/binary_accessor_spec.rb +143 -6
  73. data/spec/packets/commands_spec.rb +5 -5
  74. data/spec/packets/limits_spec.rb +15 -15
  75. data/spec/packets/packet_config_spec.rb +19 -19
  76. data/spec/packets/packet_item_limits_spec.rb +3 -3
  77. data/spec/packets/packet_item_spec.rb +4 -4
  78. data/spec/packets/packet_spec.rb +33 -33
  79. data/spec/packets/structure_item_spec.rb +19 -19
  80. data/spec/packets/telemetry_spec.rb +6 -6
  81. data/spec/script/cmd_tlm_server_spec.rb +110 -0
  82. data/spec/script/commands_disconnect_spec.rb +270 -0
  83. data/spec/script/commands_spec.rb +288 -0
  84. data/spec/script/limits_spec.rb +153 -0
  85. data/spec/script/script_spec.rb +32 -696
  86. data/spec/script/scripting_spec.rb +436 -0
  87. data/spec/script/telemetry_spec.rb +130 -0
  88. data/spec/script/tools_spec.rb +117 -0
  89. data/spec/spec_helper.rb +10 -5
  90. data/spec/streams/preidentified_stream_protocol_spec.rb +4 -4
  91. data/spec/streams/serial_stream_spec.rb +8 -8
  92. data/spec/streams/stream_protocol_spec.rb +4 -4
  93. data/spec/streams/tcpip_client_stream_spec.rb +3 -3
  94. data/spec/streams/tcpip_socket_stream_spec.rb +7 -7
  95. data/spec/streams/template_stream_protocol_spec.rb +1 -1
  96. data/spec/system/system_spec.rb +6 -6
  97. data/spec/system/target_spec.rb +2 -0
  98. data/spec/tools/cmd_tlm_server/api_spec.rb +17 -17
  99. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +5 -5
  100. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +3 -3
  101. data/spec/top_level/top_level_spec.rb +8 -8
  102. data/spec/utilities/csv_spec.rb +3 -3
  103. data/spec/utilities/message_log_spec.rb +3 -3
  104. data/spec/utilities/ruby_lex_utils_spec.rb +7 -7
  105. data/test/performance/config/tools/launcher/launcher_threads.txt +8 -1
  106. data/test/performance/tools/CmdTlmServerMemProf +1 -1
  107. data/test/performance/tools/TlmGrapherMemProf +19 -0
  108. data/test/performance/tools/TlmGrapherMemProf.bat +59 -0
  109. metadata +38 -2
@@ -0,0 +1,436 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'spec_helper'
12
+ require 'cosmos'
13
+ require 'cosmos/script/script'
14
+ require 'tempfile'
15
+
16
+ module Cosmos
17
+
18
+ describe Script do
19
+
20
+ before(:all) do
21
+ cts = File.join(Cosmos::USERPATH,'config','tools','cmd_tlm_server','cmd_tlm_server.txt')
22
+ FileUtils.mkdir_p(File.dirname(cts))
23
+ File.open(cts,'w') do |file|
24
+ file.puts 'INTERFACE INST_INT interface.rb'
25
+ file.puts 'TARGET INST'
26
+ end
27
+ System.class_eval('@@instance = nil')
28
+
29
+ require 'cosmos/script'
30
+ end
31
+
32
+ after(:all) do
33
+ clean_config()
34
+ FileUtils.rm_rf File.join(Cosmos::USERPATH,'config','tools')
35
+ end
36
+
37
+ before(:each) do
38
+ allow_any_instance_of(Interface).to receive(:connected?).and_return(true)
39
+ allow_any_instance_of(Interface).to receive(:disconnect)
40
+ allow_any_instance_of(Interface).to receive(:write)
41
+ allow_any_instance_of(Interface).to receive(:read)
42
+
43
+ @server = CmdTlmServer.new
44
+ shutdown_cmd_tlm()
45
+ initialize_script_module()
46
+ sleep 0.1
47
+ end
48
+
49
+ after(:each) do
50
+ @server.stop
51
+ shutdown_cmd_tlm()
52
+ sleep(0.1)
53
+ end
54
+
55
+ describe "play_wav_file" do
56
+ it "plays a wav file if Qt is available" do
57
+ module Qt
58
+ def self.execute_in_main_thread(bool); yield; end
59
+ class CoreApplication; def self.instance; true; end; end;
60
+ class Sound; def self.isAvailable; true; end; end
61
+ end
62
+ expect(Qt::Sound).to receive(:play).with("sound.wav")
63
+ play_wav_file("sound.wav")
64
+ end
65
+ end
66
+
67
+ describe "status_bar" do
68
+ it "sets the ScriptRunner status bar" do
69
+ class ScriptRunner; end
70
+ sc = ScriptRunner.new
71
+ expect(sc).to receive(:script_set_status).with("HI")
72
+ status_bar("HI")
73
+ end
74
+ end
75
+
76
+ describe "ask_string, ask" do
77
+ it "gets user input" do
78
+ $stdout = StringIO.new
79
+ expect(self).to receive(:gets) { '10' }
80
+ expect(ask_string("Question", 5)).to eql '10'
81
+ expect(self).to receive(:gets) { '10' }
82
+ expect(ask("")).to eql 10
83
+ $stdout = STDOUT
84
+ end
85
+ end
86
+
87
+ describe "prompt, prompt_message_box" do
88
+ it "prompts the user for input" do
89
+ $stdout = StringIO.new
90
+ expect(self).to receive(:gets) { 'message' }
91
+ expect(prompt("")).to eql 'message'
92
+ expect(self).to receive(:gets) { 'b1' }
93
+ expect(message_box("",["b1","b2"])).to eql 'b1'
94
+ $stdout = STDOUT
95
+ end
96
+ end
97
+
98
+ describe "check, check_formatted, check_with_units, check_raw" do
99
+ it "checks the number of parameters" do
100
+ expect { check("INST HEALTH_STATUS TEMP1", -100.0) }.to raise_error(/Invalid number of arguments/)
101
+ expect { check("INST", "HEALTH_STATUS", "TEMP1") }.to raise_error(/Invalid number of arguments/)
102
+ end
103
+
104
+ it "checks a telemetry item vs a condition" do
105
+ capture_io do |stdout|
106
+ check("INST HEALTH_STATUS TEMP1 == -100")
107
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 == -100 success"
108
+ stdout.rewind
109
+
110
+ check("INST","HEALTH_STATUS","TEMP1","== -100")
111
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 == -100 success"
112
+ stdout.rewind
113
+
114
+ check_formatted("INST HEALTH_STATUS TEMP1 == '-100.000'")
115
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 == '-100.000' success"
116
+ stdout.rewind
117
+
118
+ check_formatted("INST","HEALTH_STATUS","TEMP1","== '-100.000'")
119
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 == '-100.000' success"
120
+ stdout.rewind
121
+
122
+ check_with_units("INST HEALTH_STATUS TEMP1 == '-100.000 C'")
123
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 == '-100.000 C' success"
124
+ stdout.rewind
125
+
126
+ check_with_units("INST","HEALTH_STATUS","TEMP1","== '-100.000 C'")
127
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 == '-100.000 C' success"
128
+ stdout.rewind
129
+
130
+ check_raw("INST HEALTH_STATUS TEMP1")
131
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 == 0"
132
+ end
133
+
134
+ check("INST HEALTH_STATUS TEMP1 < 0")
135
+ expect { check("INST HEALTH_STATUS TEMP1 > 0") }.to raise_error(Cosmos::CheckError)
136
+ end
137
+ end
138
+
139
+ describe "check_tolerance, check_tolerance_raw" do
140
+ it "checks the number of parameters" do
141
+ expect { check_tolerance("INST HEALTH_STATUS TEMP1", -100.0) }.to raise_error(/Invalid number of arguments/)
142
+ expect { check_tolerance("INST", "HEALTH_STATUS", "TEMP1", -100.0, 1, 0) }.to raise_error(/Invalid number of arguments/)
143
+ end
144
+
145
+ it "checks a telemetry item vs tolerance" do
146
+ capture_io do |stdout|
147
+ check_tolerance("INST HEALTH_STATUS TEMP1", -100.0, 1)
148
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 was within range"
149
+ stdout.rewind
150
+
151
+ check_tolerance("INST", "HEALTH_STATUS", "TEMP1", -100.0, 1)
152
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 was within range"
153
+ stdout.rewind
154
+
155
+ expect { check_tolerance("INST HEALTH_STATUS TEMP1", -200.0, 1) }.to raise_error(CheckError, /CHECK: INST HEALTH_STATUS TEMP1 failed to be within range/)
156
+ stdout.rewind
157
+
158
+ check_tolerance_raw("INST HEALTH_STATUS TEMP1", 0, 1)
159
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 was within range"
160
+ stdout.rewind
161
+
162
+ expect { check_tolerance_raw("INST HEALTH_STATUS TEMP1", 100, 1) }.to raise_error(CheckError, /CHECK: INST HEALTH_STATUS TEMP1 failed to be within range/)
163
+ stdout.rewind
164
+ end
165
+ end
166
+ end
167
+
168
+ describe "check_expression" do
169
+ it "checks an arbitrary expression" do
170
+ capture_io do |stdout|
171
+ check_expression("true == true")
172
+ expect(stdout.string).to match "CHECK: true == true is TRUE"
173
+ end
174
+
175
+ expect { check_expression("true == false") }.to raise_error(CheckError, "CHECK: true == false is FALSE")
176
+ end
177
+ end
178
+
179
+ describe "wait, wait_raw" do
180
+ it "checks the number of parameters" do
181
+ expect { wait("INST", "HEALTH_STATUS", "TEMP1", -100.0) }.to raise_error(/Invalid number of arguments/)
182
+ expect { wait("INST", "HEALTH_STATUS", "TEMP1", -100.0, 1, 5, nil) }.to raise_error(/Invalid number of arguments/)
183
+ end
184
+
185
+ it "waits for an infinite time" do
186
+ expect(self).to receive(:gets) { "\n" }
187
+ capture_io do |stdout|
188
+ wait()
189
+ expect(stdout.string).to match "WAIT: Indefinite for actual time"
190
+ end
191
+ end
192
+
193
+ it "waits for a specified number of seconds" do
194
+ capture_io do |stdout|
195
+ wait(0.1)
196
+ expect(stdout.string).to match "WAIT: 0.1 seconds with actual time"
197
+ end
198
+ end
199
+
200
+ it "handles a bad wait parameter" do
201
+ expect { wait("1") }.to raise_error(/Non-numeric wait time/)
202
+ end
203
+
204
+ it "waits for telemetry check to be true" do
205
+ capture_io do |stdout|
206
+ # Success
207
+ wait("INST HEALTH_STATUS TEMP1 == -100.0", 5)
208
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 == -100.0"
209
+ stdout.rewind
210
+ wait("INST HEALTH_STATUS TEMP1 == -100.0", 5, 0.1) # polling rate
211
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 == -100.0"
212
+ stdout.rewind
213
+ wait("INST","HEALTH_STATUS","TEMP1","== -100.0", 5)
214
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 == -100.0"
215
+ stdout.rewind
216
+ wait("INST","HEALTH_STATUS","TEMP1","== -100.0", 5, 0.1)
217
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 == -100.0"
218
+ stdout.rewind
219
+ wait_raw("INST HEALTH_STATUS TEMP1 == 0", 5)
220
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 == 0"
221
+ stdout.rewind
222
+ wait_tolerance("INST HEALTH_STATUS TEMP1", -100.0, 1, 5)
223
+
224
+ # Failure
225
+ wait("INST HEALTH_STATUS TEMP1 == -200.0", 0.1)
226
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 == -200.0 failed"
227
+ stdout.rewind
228
+ wait_raw("INST HEALTH_STATUS TEMP1 == 100", 0.1)
229
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 == 100 failed"
230
+ stdout.rewind
231
+ end
232
+ end
233
+ end
234
+
235
+ describe "wait_tolerance, wait_tolerance_raw" do
236
+ it "checks the number of parameters" do
237
+ expect { wait_tolerance("INST", "HEALTH_STATUS", "TEMP1", -100.0, 1, 5, 0.1, nil) }.to raise_error(/Invalid number of arguments/)
238
+ end
239
+
240
+ it "waits for telemetry check to be true" do
241
+ capture_io do |stdout|
242
+ # Success
243
+ wait_tolerance("INST HEALTH_STATUS TEMP1", -100.0, 1, 5)
244
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 was within"
245
+ stdout.rewind
246
+ wait_tolerance("INST HEALTH_STATUS TEMP1", -100.0, 1, 5, 0.1)
247
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 was within"
248
+ stdout.rewind
249
+ wait_tolerance("INST","HEALTH_STATUS","TEMP1", -100.0, 1, 5)
250
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 was within"
251
+ stdout.rewind
252
+ wait_tolerance("INST","HEALTH_STATUS","TEMP1", -100.0, 1, 5, 0.1)
253
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 was within"
254
+ stdout.rewind
255
+ wait_tolerance_raw("INST HEALTH_STATUS TEMP1", 0, 1, 5)
256
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 was within"
257
+ stdout.rewind
258
+
259
+ # Failure
260
+ wait_tolerance("INST HEALTH_STATUS TEMP1", -200.0, 1, 0.1)
261
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 failed to be within"
262
+ stdout.rewind
263
+ wait_tolerance_raw("INST HEALTH_STATUS TEMP1", 100, 1, 0.1)
264
+ expect(stdout.string).to match "WAIT: INST HEALTH_STATUS TEMP1 failed to be within"
265
+ stdout.rewind
266
+ end
267
+ end
268
+ end
269
+
270
+ describe "wait_expression" do
271
+ it "waits for an expression to be true" do
272
+ capture_io do |stdout|
273
+ # Success
274
+ wait_expression("true == true", 5)
275
+ expect(stdout.string).to match "WAIT: true == true is TRUE"
276
+ stdout.rewind
277
+
278
+ # Failure
279
+ wait_expression("true == false", 0.1)
280
+ expect(stdout.string).to match "WAIT: true == false is FALSE"
281
+ stdout.rewind
282
+ end
283
+ end
284
+ end
285
+
286
+ describe "wait_check, wait_check_raw" do
287
+ it "checks the number of parameters" do
288
+ expect { wait_check("INST HEALTH_STATUS TEMP1 == -100.0") }.to raise_error(/Invalid number of arguments/)
289
+ expect { wait_check("INST", "HEALTH_STATUS", "TEMP1", -100.0) }.to raise_error(/Invalid number of arguments/)
290
+ expect { wait_check("INST", "HEALTH_STATUS", "TEMP1", -100.0, 5, 0.1, nil) }.to raise_error(/Invalid number of arguments/)
291
+ end
292
+
293
+ it "waits for telemetry check to be true" do
294
+ capture_io do |stdout|
295
+ # Success
296
+ wait_check("INST HEALTH_STATUS TEMP1 == -100.0", 5)
297
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 == -100.0"
298
+ stdout.rewind
299
+ wait_check("INST HEALTH_STATUS TEMP1 == -100.0", 5, 0.1)
300
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 == -100.0"
301
+ stdout.rewind
302
+ wait_check("INST","HEALTH_STATUS","TEMP1", "== -100.0", 5)
303
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 == -100.0"
304
+ stdout.rewind
305
+ wait_check("INST","HEALTH_STATUS","TEMP1", "== -100.0", 5, 0.1)
306
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 == -100.0"
307
+ stdout.rewind
308
+ wait_check_raw("INST HEALTH_STATUS TEMP1 == 0", 5)
309
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 == 0"
310
+ stdout.rewind
311
+ end
312
+
313
+ # Failure
314
+ expect { wait_check("INST HEALTH_STATUS TEMP1 == -200.0", 0.1) }.to raise_error(CheckError, /CHECK: INST HEALTH_STATUS TEMP1 == -200.0 failed/)
315
+ expect { wait_check_raw("INST HEALTH_STATUS TEMP1 == 100", 0.1) }.to raise_error(CheckError, /CHECK: INST HEALTH_STATUS TEMP1 == 100 failed/)
316
+ end
317
+ end
318
+
319
+ describe "wait_check_tolerance, wait_check_tolerance_raw" do
320
+ it "checks the number of parameters" do
321
+ expect { wait_check_tolerance("INST", "HEALTH_STATUS", "TEMP1", -100.0, 1, 5, 0.1, nil) }.to raise_error(/Invalid number of arguments/)
322
+ end
323
+
324
+ it "waits for telemetry check to be true" do
325
+ capture_io do |stdout|
326
+ # Success
327
+ wait_check_tolerance("INST HEALTH_STATUS TEMP1", -100.0, 1, 5)
328
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 was within"
329
+ stdout.rewind
330
+ wait_check_tolerance("INST","HEALTH_STATUS","TEMP1", -100.0, 1, 5)
331
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 was within"
332
+ stdout.rewind
333
+ wait_check_tolerance("INST","HEALTH_STATUS","TEMP1", -100.0, 1, 5, 0.1)
334
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 was within"
335
+ stdout.rewind
336
+ wait_check_tolerance_raw("INST HEALTH_STATUS TEMP1", 0, 1, 5)
337
+ expect(stdout.string).to match "CHECK: INST HEALTH_STATUS TEMP1 was within"
338
+ stdout.rewind
339
+ end
340
+
341
+ # Failure
342
+ expect { wait_check_tolerance("INST HEALTH_STATUS TEMP1", -200.0, 1, 0.1) }.to raise_error(CheckError, /CHECK: INST HEALTH_STATUS TEMP1 failed to be within/)
343
+
344
+ expect { wait_check_tolerance_raw("INST HEALTH_STATUS TEMP1", 100, 1, 0.1) }.to raise_error(CheckError, /CHECK: INST HEALTH_STATUS TEMP1 failed to be within/)
345
+
346
+ end
347
+ end
348
+
349
+ describe "wait_check_expression" do
350
+ it "waits for an expression to be true" do
351
+ capture_io do |stdout|
352
+ # Success
353
+ wait_check_expression("true == true", 5)
354
+ expect(stdout.string).to match "CHECK: true == true is TRUE"
355
+ stdout.rewind
356
+ end
357
+
358
+ # Failure
359
+ expect { wait_check_expression("true == false", 0.1) }.to raise_error(CheckError, /CHECK: true == false is FALSE/)
360
+ end
361
+ end
362
+
363
+ describe "wait_packet, wait_check_packet" do
364
+ it "waits for a certain number of packets" do
365
+ capture_io do |stdout|
366
+ wait_packet("INST","HEALTH_STATUS",1,0.1)
367
+ end
368
+
369
+ expect { wait_check_packet("INST","HEALTH_STATUS",1,0.1) }.to raise_error(CheckError, /INST HEALTH_STATUS expected to be received 1 times but only received 0 times/)
370
+ end
371
+ end
372
+
373
+ describe "cosmos_script_sleep" do
374
+ it "pauses the running script inside ScriptRunnerFrame" do
375
+ class ScriptRunnerFrame; def self.instance; true; end; end
376
+ allow(ScriptRunnerFrame).to receive_message_chain(:instance, :pause?).and_return(true)
377
+ expect(ScriptRunnerFrame).to receive_message_chain(:instance, :perform_pause)
378
+ cosmos_script_sleep(0.1)
379
+ end
380
+ end
381
+
382
+ describe "start" do
383
+ it "starts a script locally" do
384
+ class ScriptRunnerFrame; def self.instance; false; end; end
385
+ start("cosmos.rb")
386
+ end
387
+
388
+ it "starts a script without the .rb extension" do
389
+ class ScriptRunnerFrame; def self.instance; false; end; end
390
+ start("cosmos")
391
+ end
392
+
393
+ it "raises an error if the script can't be found" do
394
+ class ScriptRunnerFrame; def self.instance; false; end; end
395
+ expect { start("unknown_script.rb") }.to raise_error(RuntimeError)
396
+ end
397
+
398
+ it "starts a script within ScriptRunnerFrame" do
399
+ class ScriptRunnerFrame
400
+ @@instrumented_cache = {}
401
+ def self.instance; true; end
402
+ def self.instrumented_cache; @@instrumented_cache; end
403
+ def self.instrumented_cache=(value); @@instrumented_cache = value; end
404
+ def self.instrument_script(file_text, path, bool); "#"; end
405
+ end
406
+ start("cosmos.rb")
407
+ # This one should use the cached version
408
+ start("cosmos.rb")
409
+ end
410
+ end
411
+
412
+ describe "load_utility" do
413
+ it "requires a script" do
414
+ class ScriptRunnerFrame; def self.instance; false; end; end;
415
+ expect { load_utility("example.rb") }.to raise_error(RuntimeError, /Procedure not found/)
416
+ end
417
+
418
+ it "requires a script within ScriptRunnerFrame" do
419
+ class ScriptRunnerFrame
420
+ @@instrumented_cache = {}
421
+ def self.instance; true; end
422
+ def self.instrumented_cache; @@instrumented_cache; end
423
+ def self.instrumented_cache=(value); @@instrumented_cache = value; end
424
+ def self.instrument_script(file_text, path, bool); "#"; end
425
+ end
426
+ allow(ScriptRunnerFrame).to receive_message_chain(:instance, :use_instrumentation)
427
+ allow(ScriptRunnerFrame).to receive_message_chain(:instance, :use_instrumentation=)
428
+ load_utility("cosmos.rb")
429
+ # This one should use the cached version
430
+ load_utility("cosmos.rb")
431
+ end
432
+ end
433
+
434
+ end
435
+ end
436
+
@@ -0,0 +1,130 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'spec_helper'
12
+ require 'cosmos'
13
+ require 'cosmos/script/script'
14
+ require 'tempfile'
15
+
16
+ module Cosmos
17
+
18
+ describe Script do
19
+
20
+ before(:all) do
21
+ cts = File.join(Cosmos::USERPATH,'config','tools','cmd_tlm_server','cmd_tlm_server.txt')
22
+ FileUtils.mkdir_p(File.dirname(cts))
23
+ File.open(cts,'w') do |file|
24
+ file.puts 'INTERFACE INST_INT interface.rb'
25
+ file.puts 'TARGET INST'
26
+ end
27
+ System.class_eval('@@instance = nil')
28
+
29
+ require 'cosmos/script'
30
+ end
31
+
32
+ after(:all) do
33
+ clean_config()
34
+ FileUtils.rm_rf File.join(Cosmos::USERPATH,'config','tools')
35
+ end
36
+
37
+ before(:each) do
38
+ allow_any_instance_of(Interface).to receive(:connected?).and_return(true)
39
+ allow_any_instance_of(Interface).to receive(:disconnect)
40
+ allow_any_instance_of(Interface).to receive(:write)
41
+ allow_any_instance_of(Interface).to receive(:read)
42
+
43
+ @server = CmdTlmServer.new
44
+ shutdown_cmd_tlm()
45
+ initialize_script_module()
46
+ sleep 0.1
47
+ end
48
+
49
+ after(:each) do
50
+ @server.stop
51
+ shutdown_cmd_tlm()
52
+ sleep(0.1)
53
+ end
54
+
55
+ describe "tlm, tlm_raw, tlm_formatted, tlm_with_units, tlm_variable, set_tlm, set_tlm_raw" do
56
+ it "passes through to the cmd_tlm_server" do
57
+ expect {
58
+ expect(tlm("INST HEALTH_STATUS TEMP1")).to eql -100.0
59
+ expect(tlm_raw("INST HEALTH_STATUS TEMP1")).to eql 0
60
+ expect(tlm_formatted("INST HEALTH_STATUS TEMP1")).to eql "-100.000"
61
+ expect(tlm_with_units("INST HEALTH_STATUS TEMP1")).to eql "-100.000 C"
62
+ expect(tlm_variable("INST HEALTH_STATUS TEMP1", :RAW)).to eql 0
63
+ set_tlm("INST HEALTH_STATUS TEMP1 = 1")
64
+ set_tlm_raw("INST HEALTH_STATUS TEMP1 = 0")
65
+ }.to_not raise_error
66
+ end
67
+ end
68
+
69
+ describe "get_tlm_packet" do
70
+ it "gets the packet values" do
71
+ expect(get_tlm_packet("INST", "HEALTH_STATUS", :RAW)).to include(["TEMP1", 0, :RED_LOW])
72
+ end
73
+ end
74
+
75
+ describe "get_tlm_values" do
76
+ it "gets the given values" do
77
+ vals = get_tlm_values([["INST", "HEALTH_STATUS", "TEMP1"], ["INST", "HEALTH_STATUS", "TEMP2"]])
78
+ expect(vals[0][0]).to eql -100.0
79
+ expect(vals[1][0]).to eql :RED_LOW
80
+ expect(vals[2][0]).to eql [-80.0, -70.0, 60.0, 80.0, -20.0, 20.0]
81
+ expect(vals[3]).to eql :DEFAULT
82
+ end
83
+ end
84
+
85
+ describe "get_tlm_list" do
86
+ it "gets packets for a given target" do
87
+ expect(get_tlm_list("INST")).to include(["HEALTH_STATUS", "Health and status from the instrument"])
88
+ end
89
+ end
90
+
91
+ describe "get_tlm_item_list" do
92
+ it "gets telemetry for a given packet" do
93
+ expect(get_tlm_item_list("INST", "HEALTH_STATUS")).to include(["TEMP1",nil,"Temperature #1"])
94
+ end
95
+ end
96
+
97
+ describe "get_tlm_details" do
98
+ it "gets telemetry for a given packet" do
99
+ details = get_tlm_details([["INST", "HEALTH_STATUS", "TEMP1"], ["INST", "HEALTH_STATUS", "TEMP2"]])
100
+ expect(details[0]["name"]).to eql "TEMP1"
101
+ expect(details[1]["name"]).to eql "TEMP2"
102
+ end
103
+ end
104
+
105
+ describe "get_target_list" do
106
+ it "returns the list of targets" do
107
+ expect(get_target_list).to include("INST")
108
+ end
109
+ end
110
+
111
+ describe "subscribe_packet_data, get_packet, unsubscribe_packet_data" do
112
+ it "raises an error if non_block and the queue is empty" do
113
+ id = subscribe_packet_data([["INST","HEALTH_STATUS"]])
114
+ expect { get_packet(id, true) }.to raise_error(ThreadError, "queue empty")
115
+ unsubscribe_packet_data(id)
116
+ end
117
+
118
+ it "subscribes and get limits events" do
119
+ id = subscribe_packet_data([["INST","HEALTH_STATUS"]])
120
+ CmdTlmServer.instance.post_packet(System.telemetry.packet("INST","HEALTH_STATUS"))
121
+ packet = get_packet(id, true)
122
+ expect(packet.target_name).to eql "INST"
123
+ expect(packet.packet_name).to eql "HEALTH_STATUS"
124
+ unsubscribe_packet_data(id)
125
+ end
126
+ end
127
+
128
+ end
129
+ end
130
+