cosmos 4.4.1 → 4.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (160) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build_v4.yml +33 -0
  3. data/Dockerfile +10 -4
  4. data/Gemfile +1 -1
  5. data/Manifest.txt +26 -2
  6. data/README.md +4 -1
  7. data/Rakefile +33 -27
  8. data/autohotkey/tools/cmd_extractor.ahk +11 -9
  9. data/autohotkey/tools/cmd_sender.ahk +1 -1
  10. data/autohotkey/tools/cmd_sequence.ahk +1 -1
  11. data/autohotkey/tools/data_viewer.ahk +1 -1
  12. data/autohotkey/tools/limits_monitor.ahk +1 -1
  13. data/autohotkey/tools/packet_viewer.ahk +1 -1
  14. data/autohotkey/tools/script_runner.ahk +1 -1
  15. data/autohotkey/tools/test_runner2.ahk +1 -1
  16. data/autohotkey/tools/tlm_grapher.ahk +1 -1
  17. data/autohotkey/tools/tlm_grapher3.ahk +1 -1
  18. data/autohotkey/tools/tlm_viewer.ahk +1 -1
  19. data/autohotkey/tools/tlm_viewer2.ahk +1 -1
  20. data/autohotkey/tools/tlm_viewer5.ahk +1 -1
  21. data/bin/rubysloc +73 -28
  22. data/bin/xtce_converter +1 -1
  23. data/cosmos.gemspec +6 -12
  24. data/data/config/interface_modifiers.yaml +3 -2
  25. data/data/config/system.yaml +81 -24
  26. data/data/crc.txt +435 -435
  27. data/demo/Rakefile +4 -4
  28. data/demo/config/data/crc.txt +250 -250
  29. data/demo/config/system/system.txt +15 -7
  30. data/demo/config/system/system2.txt +15 -7
  31. data/demo/config/system/system_alt_ports.txt +15 -7
  32. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +1 -1
  33. data/demo/config/tools/handbook_creator/default_toc.xsl +59 -59
  34. data/ext/cosmos/ext/buffered_file/buffered_file.c +2 -2
  35. data/ext/cosmos/ext/config_parser/config_parser.c +1 -2
  36. data/ext/cosmos/ext/line_graph/line_graph.c +53 -94
  37. data/ext/cosmos/ext/packet/packet.c +0 -6
  38. data/ext/cosmos/ext/platform/platform.c +56 -21
  39. data/ext/cosmos/ext/polynomial_conversion/polynomial_conversion.c +4 -8
  40. data/ext/cosmos/ext/structure/structure.c +12 -0
  41. data/extensions/vscode/.gitignore +4 -0
  42. data/extensions/vscode/.vscode/launch.json +32 -0
  43. data/extensions/vscode/.vscode/settings.json +13 -0
  44. data/extensions/vscode/.vscode/tasks.json +79 -0
  45. data/extensions/vscode/License.txt +879 -0
  46. data/extensions/vscode/README.md +9 -0
  47. data/extensions/vscode/client/License.txt +879 -0
  48. data/extensions/vscode/client/README.md +39 -0
  49. data/extensions/vscode/client/cosmos.configuration.json +23 -0
  50. data/extensions/vscode/client/images/icon.png +0 -0
  51. data/extensions/vscode/client/package-lock.json +414 -0
  52. data/extensions/vscode/client/package.json +105 -0
  53. data/extensions/vscode/client/src/extension.ts +132 -0
  54. data/extensions/vscode/client/src/screen_preview.rb +25 -0
  55. data/extensions/vscode/client/syntaxes/cosmos.tmLanguage.json +219 -0
  56. data/extensions/vscode/client/tsconfig.json +17 -0
  57. data/extensions/vscode/package-lock.json +26 -0
  58. data/extensions/vscode/package.json +35 -0
  59. data/extensions/vscode/server/License.txt +879 -0
  60. data/extensions/vscode/server/package-lock.json +236 -0
  61. data/extensions/vscode/server/package.json +29 -0
  62. data/extensions/vscode/server/src/server.ts +59 -0
  63. data/extensions/vscode/server/tsconfig.json +16 -0
  64. data/install/Rakefile +4 -4
  65. data/install/config/data/crc.txt +145 -145
  66. data/install/config/system/system.txt +15 -7
  67. data/install/config/tools/handbook_creator/default_toc.xsl +59 -59
  68. data/lib/cosmos/config/config_parser.rb +2 -10
  69. data/lib/cosmos/core_ext/class.rb +10 -0
  70. data/lib/cosmos/core_ext/time.rb +5 -3
  71. data/lib/cosmos/dart/examples/dart_decom_client.rb +1 -1
  72. data/lib/cosmos/dart/lib/dart_common.rb +3 -3
  73. data/lib/cosmos/dart/lib/dart_decommutator.rb +4 -4
  74. data/lib/cosmos/dart/processes/dart_decom_server.rb +1 -1
  75. data/lib/cosmos/dart/processes/dart_master.rb +1 -1
  76. data/lib/cosmos/dart/spec/dart/dart_database_cleaner_spec.rb +2 -2
  77. data/lib/cosmos/gui/qt.rb +10 -10
  78. data/lib/cosmos/gui/qt_tool.rb +17 -12
  79. data/lib/cosmos/gui/text/completion_text_edit.rb +2 -0
  80. data/lib/cosmos/gui/widgets/dart_meta_frame.rb +1 -1
  81. data/lib/cosmos/interfaces/dart_status_interface.rb +1 -1
  82. data/lib/cosmos/interfaces/linc_interface.rb +3 -3
  83. data/lib/cosmos/interfaces/protocols/burst_protocol.rb +1 -1
  84. data/lib/cosmos/interfaces/protocols/crc_protocol.rb +1 -1
  85. data/lib/cosmos/interfaces/protocols/template_protocol.rb +3 -3
  86. data/lib/cosmos/interfaces/serial_interface.rb +7 -1
  87. data/lib/cosmos/interfaces/stream_interface.rb +1 -1
  88. data/lib/cosmos/interfaces/tcpip_server_interface.rb +16 -16
  89. data/lib/cosmos/io/io_multiplexer.rb +6 -2
  90. data/lib/cosmos/io/json_drb.rb +3 -11
  91. data/lib/cosmos/io/json_drb_object.rb +7 -2
  92. data/lib/cosmos/io/json_drb_rack.rb +25 -5
  93. data/lib/cosmos/io/json_rpc.rb +1 -1
  94. data/lib/cosmos/io/posix_serial_driver.rb +60 -22
  95. data/lib/cosmos/io/serial_driver.rb +11 -8
  96. data/lib/cosmos/io/win32_serial_driver.rb +8 -1
  97. data/lib/cosmos/packets/packet.rb +8 -8
  98. data/lib/cosmos/packets/packet_config.rb +1 -1
  99. data/lib/cosmos/packets/packet_item_limits.rb +2 -14
  100. data/lib/cosmos/packets/parsers/xtce_converter.rb +10 -10
  101. data/lib/cosmos/packets/parsers/xtce_parser.rb +3 -0
  102. data/lib/cosmos/packets/structure.rb +18 -5
  103. data/lib/cosmos/packets/structure_item.rb +4 -21
  104. data/lib/cosmos/script/api_shared.rb +18 -1
  105. data/lib/cosmos/script/extract.rb +1 -1
  106. data/lib/cosmos/script/script.rb +4 -11
  107. data/lib/cosmos/streams/serial_stream.rb +11 -6
  108. data/lib/cosmos/system/system.rb +47 -13
  109. data/lib/cosmos/tools/cmd_sender/cmd_param_table_item_delegate.rb +15 -0
  110. data/lib/cosmos/tools/cmd_sender/cmd_params.rb +25 -3
  111. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +7 -0
  112. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +0 -5
  113. data/lib/cosmos/tools/cmd_tlm_server/api.rb +10 -8
  114. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +2 -2
  115. data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +1 -1
  116. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +29 -26
  117. data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +1 -1
  118. data/lib/cosmos/tools/cmd_tlm_server/router_thread.rb +5 -0
  119. data/lib/cosmos/tools/config_editor/config_editor.rb +1 -1
  120. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +1 -1
  121. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +1 -1
  122. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +5 -2
  123. data/lib/cosmos/tools/test_runner/test.rb +1 -1
  124. data/lib/cosmos/tools/test_runner/test_runner.rb +4 -4
  125. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +3 -3
  126. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +1 -4
  127. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +3 -3
  128. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_dart_thread.rb +1 -1
  129. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +2 -2
  130. data/lib/cosmos/tools/tlm_viewer/widgets/canvasdot_widget.rb +2 -0
  131. data/lib/cosmos/top_level.rb +1 -1
  132. data/lib/cosmos/utilities/simulated_target.rb +1 -1
  133. data/lib/cosmos/version.rb +5 -5
  134. data/make_gems.sh +1 -1
  135. data/spec/core_ext/class_spec.rb +54 -0
  136. data/spec/core_ext/time_spec.rb +4 -0
  137. data/spec/gui/qt_spec.rb +1 -1
  138. data/spec/gui/utilities/script_module_gui_spec.rb +1 -1
  139. data/spec/interfaces/linc_interface_spec.rb +1 -1
  140. data/spec/interfaces/serial_interface_spec.rb +1 -5
  141. data/spec/io/json_drb_rack_spec.rb +166 -0
  142. data/spec/io/json_rpc_spec.rb +4 -5
  143. data/spec/io/posix_serial_driver_spec.rb +87 -0
  144. data/spec/io/win32_serial_driver_spec.rb +17 -1
  145. data/spec/packet_logs/packet_log_reader_spec.rb +34 -35
  146. data/spec/packets/packet_item_limits_spec.rb +6 -33
  147. data/spec/packets/structure_item_spec.rb +3 -21
  148. data/spec/script/extract_spec.rb +4 -1
  149. data/spec/system/system_spec.rb +109 -1
  150. data/spec/tools/cmd_tlm_server/api_spec.rb +12 -12
  151. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +2 -2
  152. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +4 -3
  153. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +2 -3
  154. data/spec/top_level/top_level_spec.rb +2 -2
  155. data/spec/utilities/logger_spec.rb +3 -3
  156. data/test/performance/Rakefile +4 -4
  157. data/test/performance/config/data/crc.txt +67 -48
  158. metadata +59 -9
  159. data/.coveralls.yml +0 -1
  160. data/.travis.yml +0 -16
@@ -1,12 +1,12 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- COSMOS_VERSION = '4.4.1'
3
+ COSMOS_VERSION = '4.5.2'
4
4
  module Cosmos
5
5
  module Version
6
6
  MAJOR = '4'
7
- MINOR = '4'
8
- PATCH = '1'
9
- BUILD = 'f8e9c89b2d7fcd0c558806ff6c9dd59d167786e4'
7
+ MINOR = '5'
8
+ PATCH = '2'
9
+ BUILD = 'a516d4699e4de74066155c12194c9286adcde9ea'
10
10
  end
11
- VERSION = '4.4.1'
11
+ VERSION = '4.5.2'
12
12
  end
data/make_gems.sh CHANGED
@@ -1,7 +1,7 @@
1
1
  # export VERSION= before running this
2
2
  git checkout master
3
3
  git pull
4
- rbenv global 2.4.4
4
+ rbenv global 2.5.9
5
5
  rake release VERSION=$VERSION
6
6
  rake commit_release VERSION=$VERSION
7
7
  mv *.gem ~/share/.
@@ -31,6 +31,60 @@ describe Class do
31
31
  my = MyClass.new
32
32
  expect(MyClass.test).to eql "Test"
33
33
  expect(my.test).to eql "Test"
34
+ # No accessor methods are created
35
+ expect { my.test = "Blah" }.to raise_error(NoMethodError)
36
+ end
37
+
38
+ it "does not allow arbitrary code" do
39
+ expect {
40
+ class MyClass
41
+ instance_attr_reader "test;puts 'HI'"
42
+ end
43
+ }.to raise_error(ArgumentError)
44
+
45
+ expect {
46
+ class MyClass
47
+ instance_attr_reader "test\nputs 'HI'"
48
+ end
49
+ }.to raise_error(ArgumentError)
50
+ end
51
+ end
52
+
53
+ describe "instance_attr_accessor" do
54
+ it "adds instance attribute readers for class variables" do
55
+ class MyClass
56
+ instance_attr_accessor :test
57
+ @@instance = nil
58
+ def self.instance
59
+ @@instance ||= self.new
60
+ return @@instance
61
+ end
62
+ def initialize
63
+ @test = "Test"
64
+ @@instance = self
65
+ end
66
+ end
67
+
68
+ my = MyClass.new
69
+ expect(MyClass.test).to eql "Test"
70
+ expect(my.test).to eql "Test"
71
+ my.test = "Blah"
72
+ expect(MyClass.test).to eql "Blah"
73
+ expect(my.test).to eql "Blah"
74
+ end
75
+
76
+ it "does not allow arbitrary code" do
77
+ expect {
78
+ class MyClass
79
+ instance_attr_accessor "test;puts 'HI'"
80
+ end
81
+ }.to raise_error(ArgumentError)
82
+
83
+ expect {
84
+ class MyClass
85
+ instance_attr_accessor "test\nputs 'HI'"
86
+ end
87
+ }.to raise_error(ArgumentError)
34
88
  end
35
89
  end
36
90
  end
@@ -183,6 +183,10 @@ describe Time do
183
183
  expect(parts[1]).to eql ccsds_ms
184
184
  expect(parts[2]).to be_within(50).of(ccsds_us)
185
185
  end
186
+
187
+ it "maintains precision" do
188
+ expect(Time.ccsds2sec(22766, 65115943, 552).round(6)).to eql(1967047515.943552)
189
+ end
186
190
  end
187
191
 
188
192
  describe "Time.yds2mdy" do
data/spec/gui/qt_spec.rb CHANGED
@@ -8,7 +8,7 @@
8
8
  # as published by the Free Software Foundation; version 3 with
9
9
  # attribution addendums as found in the LICENSE.txt
10
10
 
11
- if RUBY_ENGINE == 'ruby'
11
+ if RUBY_ENGINE == 'ruby' && !ENV['GITHUB_ACTIONS']
12
12
  require 'spec_helper'
13
13
  require 'cosmos/gui/qt'
14
14
 
@@ -8,7 +8,7 @@
8
8
  # as published by the Free Software Foundation; version 3 with
9
9
  # attribution addendums as found in the LICENSE.txt
10
10
 
11
- if RUBY_ENGINE == 'ruby'
11
+ if RUBY_ENGINE == 'ruby' && !ENV['CI']
12
12
  require 'spec_helper'
13
13
  require 'cosmos/gui/qt'
14
14
  require 'cosmos/script'
@@ -179,7 +179,7 @@ module Cosmos
179
179
  it "warns if an error code is set" do
180
180
  allow_any_instance_of(TcpipClientStream).to receive(:read).and_return @handshake.buffer(false)
181
181
  expect(Logger).to receive(:warn) do |msg|
182
- expect(msg).to eql "Warning sending command (12345): BAD"
182
+ expect(msg).to eql "LincInterface: Warning sending command (12345): BAD"
183
183
  end
184
184
  t = Thread.new do
185
185
  sleep 0.1
@@ -9,14 +9,11 @@
9
9
  # attribution addendums as found in the LICENSE.txt
10
10
 
11
11
  if RUBY_ENGINE == 'ruby' or Gem.win_platform?
12
-
13
12
  require 'spec_helper'
14
13
  require 'cosmos/interfaces/serial_interface'
15
14
 
16
15
  module Cosmos
17
-
18
- describe SerialInterface do
19
-
16
+ describe SerialInterface, :if => `change port /query 2>&1` !~ /No serial ports/ do
20
17
  describe "initialize" do
21
18
  it "initializes the instance variables" do
22
19
  i = SerialInterface.new('COM1','COM1','9600','NONE','1','0','0','burst')
@@ -66,5 +63,4 @@ if RUBY_ENGINE == 'ruby' or Gem.win_platform?
66
63
  end
67
64
  end
68
65
  end
69
-
70
66
  end
@@ -0,0 +1,166 @@
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/io/json_drb_rack'
13
+
14
+ module Cosmos
15
+
16
+ describe JsonDrbRack do
17
+ before(:each) do
18
+ @env = {
19
+ "GATEWAY_INTERFACE" => "CGI/1.1",
20
+ "PATH_INFO" => "/index.html",
21
+ "QUERY_STRING" => "",
22
+ "REMOTE_ADDR" => "::1",
23
+ "REMOTE_HOST" => "localhost",
24
+ "REQUEST_METHOD" => "POST",
25
+ "REQUEST_URI" => "http://localhost:3000/index.html",
26
+ "SCRIPT_NAME" => "",
27
+ "SERVER_NAME" => "localhost",
28
+ "SERVER_PORT" => "3000",
29
+ "SERVER_PROTOCOL" => "HTTP/1.1",
30
+ "SERVER_SOFTWARE" => "WEBrick/1.3.1 (Ruby/2.0.0/2013-11-22)",
31
+ "HTTP_HOST" => "127.0.0.1:7777",
32
+ "HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0",
33
+ "HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
34
+ "HTTP_ACCEPT_LANGUAGE" => "zh-tw,zh;q=0.8,en-us;q=0.5,en;q=0.3",
35
+ "HTTP_ACCEPT_ENCODING" => "gzip, deflate",
36
+ "HTTP_COOKIE" => "jsonrpc.session=3iqp3ydRwFyqjcfO0GT2bzUh.bacc2786c7a81df0d0e950bec8fa1a9b1ba0bb61",
37
+ "HTTP_CONNECTION" => "keep-alive",
38
+ "HTTP_CACHE_CONTROL" => "max-age=0",
39
+ "rack.version" => [1, 2],
40
+ "rack.input" => StringIO.new(""),
41
+ "rack.errors" => nil,
42
+ "rack.multithread" => true,
43
+ "rack.multiprocess" => false,
44
+ "rack.run_once" => false,
45
+ "rack.url_scheme" => "http",
46
+ "HTTP_VERSION" => "HTTP/1.1",
47
+ "REQUEST_PATH" => "/index.html"
48
+ }
49
+ end
50
+
51
+ class MockDRb
52
+ class MockDRbAcl
53
+ def initialize(val = true)
54
+ @val = val
55
+ end
56
+ def allow_addr?(val)
57
+ return @val
58
+ end
59
+ end
60
+
61
+ def initialize(val, response_data = "response", error_code = nil)
62
+ @acl = MockDRbAcl.new(val)
63
+ @response_data = response_data
64
+ @error_code = error_code
65
+ end
66
+
67
+ def acl
68
+ @acl
69
+ end
70
+
71
+ def process_request(request_data, start_time)
72
+ return @response_data, @error_code
73
+ end
74
+ end
75
+
76
+ class MockSystem
77
+ def initialize(token = 'SuperSecret', hosts = ['127.0.0.1:7777'], origins = [])
78
+ @token = token
79
+ @hosts = hosts
80
+ @origins = origins
81
+ end
82
+ def x_csrf_token
83
+ @token
84
+ end
85
+ def allowed_hosts
86
+ @hosts
87
+ end
88
+ def allowed_origins
89
+ @origins
90
+ end
91
+ end
92
+
93
+ describe "call" do
94
+ it "supports the drb acl" do
95
+ json_drb_rack = JsonDrbRack.new(MockDRb.new(false), MockSystem.new)
96
+ status, type, body_array = json_drb_rack.call(@env)
97
+ expect(status).to eql 403
98
+ expect(type).to eql({'Content-Type' => "text/plain"})
99
+ expect(body_array).to eql ["Forbidden"]
100
+ end
101
+
102
+ it "handles X-Csrf-Token" do
103
+ json_drb_rack = JsonDrbRack.new(MockDRb.new(true), MockSystem.new('NeverGuess'))
104
+ @env['HTTP_X_CSRF_TOKEN'] = 'TryToGuess'
105
+ status, type, body_array = json_drb_rack.call(@env)
106
+ expect(status).to eql 403
107
+ expect(type).to eql({'Content-Type' => "text/plain"})
108
+ expect(body_array).to eql ["Forbidden: Bad X-Csrf-Token: #{@env['HTTP_X_CSRF_TOKEN']}"]
109
+
110
+ json_drb_rack = JsonDrbRack.new(MockDRb.new(true), MockSystem.new('NeverGuess'))
111
+ @env['HTTP_X_CSRF_TOKEN'] = 'NeverGuess'
112
+ status, type, body_array = json_drb_rack.call(@env)
113
+ expect(status).to eql 200
114
+ expect(type).to eql({'Content-Type' => "application/json-rpc"})
115
+ expect(body_array).to eql ["response"]
116
+ end
117
+
118
+ it "Handles Allowed Hosts" do
119
+ json_drb_rack = JsonDrbRack.new(MockDRb.new(true), MockSystem.new('NeverGuess'))
120
+ @env['HTTP_X_CSRF_TOKEN'] = 'NeverGuess'
121
+ @env['HTTP_HOST'] = "5.6.7.8:7777"
122
+ status, type, body_array = json_drb_rack.call(@env)
123
+ expect(status).to eql 403
124
+ expect(type).to eql({'Content-Type' => "text/plain"})
125
+ expect(body_array).to eql ["Forbidden: #{@env['HTTP_HOST']} not in allowed hosts"]
126
+
127
+ json_drb_rack = JsonDrbRack.new(MockDRb.new(true), MockSystem.new('NeverGuess', ['5.6.7.8:7777']))
128
+ @env['HTTP_X_CSRF_TOKEN'] = 'NeverGuess'
129
+ @env['HTTP_HOST'] = "5.6.7.8:7777"
130
+ status, type, body_array = json_drb_rack.call(@env)
131
+ expect(status).to eql 200
132
+ expect(type).to eql({'Content-Type' => "application/json-rpc"})
133
+ expect(body_array).to eql ["response"]
134
+ end
135
+
136
+ it "Handles Allowed Origins" do
137
+ json_drb_rack = JsonDrbRack.new(MockDRb.new(true), MockSystem.new('NeverGuess'))
138
+ @env['HTTP_X_CSRF_TOKEN'] = 'NeverGuess'
139
+ @env['HTTP_ORIGIN'] = "5.6.7.8:7777"
140
+ status, type, body_array = json_drb_rack.call(@env)
141
+ expect(status).to eql 403
142
+ expect(type).to eql({'Content-Type' => "text/plain"})
143
+ expect(body_array).to eql ["Forbidden: #{@env['HTTP_ORIGIN']} not in allowed origins"]
144
+
145
+ json_drb_rack = JsonDrbRack.new(MockDRb.new(true), MockSystem.new('NeverGuess', ['127.0.0.1:7777'], ['3.6.7.8:7777']))
146
+ @env['HTTP_X_CSRF_TOKEN'] = 'NeverGuess'
147
+ @env['HTTP_ORIGIN'] = "3.6.7.8:7777"
148
+ status, type, body_array = json_drb_rack.call(@env)
149
+ expect(status).to eql 200
150
+ expect(type).to eql({'Content-Type' => "application/json-rpc"})
151
+ expect(body_array).to eql ["response"]
152
+ end
153
+
154
+ it "Only accepts posts" do
155
+ json_drb_rack = JsonDrbRack.new(MockDRb.new(true), MockSystem.new('NeverGuess'))
156
+ @env['HTTP_X_CSRF_TOKEN'] = 'NeverGuess'
157
+ @env["REQUEST_METHOD"] = "GET"
158
+ status, type, body_array = json_drb_rack.call(@env)
159
+ expect(status).to eql 405
160
+ expect(type).to eql({'Content-Type' => "text/plain"})
161
+ expect(body_array).to eql ["Request not allowed"]
162
+ end
163
+
164
+ end
165
+ end
166
+ end
@@ -238,25 +238,25 @@ module Cosmos
238
238
 
239
239
  it "reports an error if there is no 'result' or 'error' key" do
240
240
  json = JsonRpcResponse.new(10).as_json
241
- expect { JsonRpcResponse.from_json(json.to_json) }.to raise_error("Invalid JSON-RPC 2.0 Response")
241
+ expect { JsonRpcResponse.from_json(json.to_json) }.to raise_error(/Invalid JSON-RPC 2.0 Response/)
242
242
  end
243
243
 
244
244
  it "reports an error if the version isn't 2.0" do
245
245
  json = JsonRpcResponse.new(10).as_json
246
246
  json['jsonrpc'] = "1.1"
247
247
  json['result'] = "true"
248
- expect { JsonRpcResponse.from_json(json.to_json) }.to raise_error("Invalid JSON-RPC 2.0 Response")
248
+ expect { JsonRpcResponse.from_json(json.to_json) }.to raise_error(/Invalid JSON-RPC 2.0 Response/)
249
249
  end
250
250
 
251
251
  it "reports an error if there is both a 'result' and 'error' key" do
252
252
  json = JsonRpcResponse.new(10).as_json
253
253
  json['result'] = "true"
254
254
  json['error'] = {"code"=>-1, "message"=>"error"}
255
- expect { JsonRpcResponse.from_json(json.to_json) }.to raise_error("Invalid JSON-RPC 2.0 Response")
255
+ expect { JsonRpcResponse.from_json(json.to_json) }.to raise_error(/Invalid JSON-RPC 2.0 Response/)
256
256
  end
257
257
 
258
258
  it "reports an error if it is not json" do
259
- expect { JsonRpcResponse.from_json(Object.new) }.to raise_error("Invalid JSON-RPC 2.0 Response")
259
+ expect { JsonRpcResponse.from_json(Object.new) }.to raise_error(/Invalid JSON-RPC 2.0 Response/)
260
260
  end
261
261
 
262
262
  it "reports an error if the error hash is bad" do
@@ -268,4 +268,3 @@ module Cosmos
268
268
 
269
269
  end
270
270
  end
271
-
@@ -0,0 +1,87 @@
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
+ # NOTE: !ENV['DOCKER'] because of the following error while in container:
12
+ # Failure/Error: @handle = Kernel.open(port_name, File::RDWR | File::NONBLOCK)
13
+ # Errno::ENOENT:
14
+ # No such file or directory @ rb_sysopen - /dev/ttyS0
15
+ # ./lib/cosmos/io/posix_serial_driver.rb:48:in `initialize'
16
+
17
+ if RbConfig::CONFIG['target_os'] !~ /mswin|mingw|cygwin/i and RUBY_ENGINE == 'ruby' and !ENV['CI'] and !ENV['DOCKER']
18
+
19
+ require 'spec_helper'
20
+ require 'cosmos/io/posix_serial_driver'
21
+
22
+ module Cosmos
23
+
24
+ describe PosixSerialDriver do
25
+ describe "instance" do
26
+ it "enforces the baud rate to a known value" do
27
+ expect { PosixSerialDriver.new('/dev/ttyS0',10,:NONE) }.to raise_error(ArgumentError, "Invalid baud rate: 10")
28
+ end
29
+
30
+ it "supports even, odd, or no parity" do
31
+ expect { PosixSerialDriver.new('/dev/ttyS0',9600,:EVEN).close }.to_not raise_error
32
+ expect { PosixSerialDriver.new('/dev/ttyS0',9600,:ODD).close }.to_not raise_error
33
+ expect { PosixSerialDriver.new('/dev/ttyS0',9600,:NONE).close }.to_not raise_error
34
+ expect { PosixSerialDriver.new('/dev/ttyS0',9600,:BLAH) }.to raise_error(ArgumentError, "Invalid parity: BLAH")
35
+ end
36
+
37
+ it "supports 1 or 2 stop bits" do
38
+ expect { PosixSerialDriver.new('/dev/ttyS0',9600,:NONE,1).close }.to_not raise_error
39
+ expect { PosixSerialDriver.new('/dev/ttyS0',9600,:NONE,2).close }.to_not raise_error
40
+ expect { PosixSerialDriver.new('/dev/ttyS0',9600,:NONE,3) }.to raise_error(ArgumentError, "Invalid stop bits: 3")
41
+ end
42
+
43
+ it "supports 5-8 data bits" do
44
+ (5..8).each do |data_bits|
45
+ driver = PosixSerialDriver.new('/dev/ttyS0',9600,:NONE,1,10,nil,:NONE,data_bits)
46
+ handle = driver.instance_variable_get(:@handle)
47
+ expect(handle.tcgetattr.cflag & Termios::CSIZE).to eq(Termios.const_get("CS#{data_bits}"))
48
+ driver.close
49
+ end
50
+ expect { PosixSerialDriver.new('/dev/ttyS0',9600,:NONE,1,10,nil,:NONE,9) }.to raise_error(ArgumentError, "Invalid data bits: 9")
51
+ end
52
+
53
+ it "sets arbitrary Posix structure elements" do
54
+ driver = PosixSerialDriver.new('/dev/ttyS0',9600,:NONE,1,10,nil,:NONE,8)
55
+ handle = driver.instance_variable_get(:@handle)
56
+ # Verify non of the things we're going to set are already set
57
+ expect(handle.tcgetattr.iflag & Termios::IGNBRK).to eq(0)
58
+ expect(handle.tcgetattr.oflag & Termios::OPOST).to eq(0)
59
+ expect(handle.tcgetattr.cflag & Termios::CLOCAL).to eq(Termios::CLOCAL) # We set this by default
60
+ expect(handle.tcgetattr.lflag & Termios::ECHO).to eq(0)
61
+ expect(handle.tcgetattr.cc[Termios::VMIN]).to eq(1)
62
+ driver.close
63
+ # When setting a field the "1" is optional. When clearing a field the "0" is required.
64
+ # Entries in the "cc" special characters field are automatically converted to integers if they are numbers
65
+ struct = [["iflag", "IGNBRK"], ["oflag", "OPOST", "1"], ["cflag", "CLOCAL", "0"], ["lflag", "ECHO"], ["cc", "VMIN", "2"]]
66
+ driver = PosixSerialDriver.new('/dev/ttyS0',9600,:NONE,1,10,nil,:NONE,8,struct)
67
+ handle = driver.instance_variable_get(:@handle)
68
+ expect(handle.tcgetattr.iflag & Termios::IGNBRK).to eq(Termios::IGNBRK)
69
+ expect(handle.tcgetattr.oflag & Termios::OPOST).to eq(Termios::OPOST)
70
+ expect(handle.tcgetattr.cflag & Termios::CLOCAL).to eq(0)
71
+ expect(handle.tcgetattr.lflag & Termios::ECHO).to eq(Termios::ECHO)
72
+ expect(handle.tcgetattr.cc[Termios::VMIN]).to eq(2)
73
+ driver.close
74
+ end
75
+ end
76
+
77
+ describe "close, closed?" do
78
+ it "closes the handle" do
79
+ driver = PosixSerialDriver.new('/dev/ttyS0',9600)
80
+ expect(driver.closed?).to be false
81
+ driver.close
82
+ expect(driver.closed?).to be true
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -19,7 +19,8 @@ if RUBY_ENGINE == 'ruby' or Gem.win_platform?
19
19
  before(:each) do
20
20
  allow(Win32).to receive(:create_file).and_return(Object.new)
21
21
  state = double("comm_state")
22
- allow(state).to receive(:write)
22
+ @dcb_struct = {}
23
+ allow(state).to receive(:write) { |key, value| @dcb_struct[key] = value }
23
24
  allow(Win32).to receive(:get_comm_state).and_return(state)
24
25
  allow(Win32).to receive(:set_comm_state)
25
26
  allow(Win32).to receive(:set_comm_timeouts)
@@ -34,12 +35,14 @@ if RUBY_ENGINE == 'ruby' or Gem.win_platform?
34
35
  expect { Win32SerialDriver.new('COM1',9600,:EVEN) }.to_not raise_error
35
36
  expect { Win32SerialDriver.new('COM1',9600,:ODD) }.to_not raise_error
36
37
  expect { Win32SerialDriver.new('COM1',9600,:NONE) }.to_not raise_error
38
+ expect(@dcb_struct["Parity"]).to_not be_nil # Simply check that Parity was set
37
39
  expect { Win32SerialDriver.new('COM1',9600,:BLAH) }.to raise_error(ArgumentError, "Invalid parity: BLAH")
38
40
  end
39
41
 
40
42
  it "supports 1 or 2 stop bits" do
41
43
  expect { Win32SerialDriver.new('COM1',9600,:NONE,1) }.to_not raise_error
42
44
  expect { Win32SerialDriver.new('COM1',9600,:NONE,2) }.to_not raise_error
45
+ expect(@dcb_struct["StopBits"]).to_not be_nil # Simply check that StopBits was set
43
46
  expect { Win32SerialDriver.new('COM1',9600,:NONE,3) }.to raise_error(ArgumentError, "Invalid stop bits: 3")
44
47
  end
45
48
 
@@ -49,6 +52,19 @@ if RUBY_ENGINE == 'ruby' or Gem.win_platform?
49
52
  expect { Win32SerialDriver.new('COM1',9600,:NONE,1,10,nil,0.01,1000,:NONE,7) }.to_not raise_error
50
53
  expect { Win32SerialDriver.new('COM1',9600,:NONE,1,10,nil,0.01,1000,:NONE,8) }.to_not raise_error
51
54
  expect { Win32SerialDriver.new('COM1',9600,:NONE,1,10,nil,0.01,1000,:NONE,9) }.to raise_error(ArgumentError, "Invalid data bits: 9")
55
+ expect(@dcb_struct["ByteSize"]).to_not be_nil # Simply check that ByteSize was set
56
+ end
57
+
58
+ it "sets arbitrary Windows DCB structure elements" do
59
+ Win32SerialDriver.new('COM1',9600,:NONE,1,10,nil,0.01,1000,:NONE,8)
60
+ expect(@dcb_struct["fOutxDsrFlow"]).to be_nil # This isn't set by default
61
+ expect(@dcb_struct["Parity"]).to eq(0)
62
+ # Set a new variable in the Windows DCB struct and override the :NONE parity
63
+ # We pass them in as strings because that's how they're parsed
64
+ struct = [["fOutxDsrFlow", "1"], ["Parity", "4"]]
65
+ Win32SerialDriver.new('COM1',9600,:NONE,1,10,nil,0.01,1000,:NONE,8,struct)
66
+ expect(@dcb_struct["fOutxDsrFlow"]).to eq(1)
67
+ expect(@dcb_struct["Parity"]).to eq(4)
52
68
  end
53
69
 
54
70
  it "calculates the correct timeouts" do
@@ -23,7 +23,10 @@ module Cosmos
23
23
  plw = PacketLogWriter.new(:CMD,nil,true,nil,10000000,nil,false)
24
24
  @cmd_packets = []
25
25
  pkt = System.commands.packet("SYSTEM","STARTLOGGING").clone
26
- pkt.received_time = Time.new(2020,1,31,12,30,15)
26
+ # Avoid precision errors by rounding to nearest second and then add 1 to ensure
27
+ # the time is AFTER the initial META packet with the current time
28
+ @time = Time.now.round + 1
29
+ pkt.received_time = @time
27
30
  pkt.write('label','PKT1')
28
31
  plw.write(pkt)
29
32
  @cmd_packet_length = pkt.length
@@ -43,7 +46,7 @@ module Cosmos
43
46
  plw = PacketLogWriter.new(:TLM,nil,true,nil,10000000,nil,false)
44
47
  @tlm_packets = []
45
48
  pkt = System.telemetry.packet("SYSTEM","LIMITS_CHANGE").clone
46
- pkt.received_time = Time.new(2020,2,1,12,30,15)
49
+ pkt.received_time = @time
47
50
  pkt.write('PACKET','PKT1')
48
51
  plw.write(pkt)
49
52
  @tlm_packet_length = pkt.length
@@ -203,7 +206,7 @@ module Cosmos
203
206
  end
204
207
 
205
208
  # Corrupt the second config
206
- second_config_path = System.instance.send(:find_configuration, second_config_name)
209
+ second_config_path = System.instance.public_send(:find_configuration, second_config_name)
207
210
  md5 = File.basename(second_config_path, '.*')
208
211
  Zip::File.open(second_config_path) do |zip|
209
212
  zip.file.rename(File.join(md5, 'system.txt'), File.join(md5, 'system2.txt'))
@@ -239,10 +242,11 @@ module Cosmos
239
242
  expect(packet_offsets).to eql [PacketLogReader::COSMOS4_HEADER_LENGTH, PacketLogReader::COSMOS4_HEADER_LENGTH + meta_header_length + meta_length, PacketLogReader::COSMOS4_HEADER_LENGTH + meta_header_length + meta_length + header_length + @cmd_packet_length, PacketLogReader::COSMOS4_HEADER_LENGTH + meta_header_length + meta_length + (header_length + @cmd_packet_length) * 2]
240
243
 
241
244
  expect(@plr.open(Dir[File.join(@log_path,"*cmd.bin")][0])).to eql [true, nil]
242
- pkt = @plr.read_at_offset(packet_offsets[2])
245
+ pkt = @plr.read_at_offset(packet_offsets[2]) # Grab the second STARTLOGGING (META is 0)
243
246
  expect(pkt.target_name).to eql "SYSTEM"
244
247
  expect(pkt.packet_name).to eql "STARTLOGGING"
245
- expect(pkt.received_time).to eql Time.new(2020,1,31,12,30,16)
248
+ expect(pkt.read('LABEL')).to eql "PKT2"
249
+ expect(pkt.received_time).to eql @time + 1
246
250
  @plr.close
247
251
  end
248
252
 
@@ -257,10 +261,11 @@ module Cosmos
257
261
  expect(packet_offsets).to eql [PacketLogReader::COSMOS4_HEADER_LENGTH, PacketLogReader::COSMOS4_HEADER_LENGTH + meta_header_length + meta_length, PacketLogReader::COSMOS4_HEADER_LENGTH + meta_header_length + meta_length + header_length + @tlm_packet_length, PacketLogReader::COSMOS4_HEADER_LENGTH + meta_header_length + meta_length + (header_length + @tlm_packet_length) * 2]
258
262
 
259
263
  expect(@plr.open(Dir[File.join(@log_path,"*tlm.bin")][0])).to eql [true, nil]
260
- pkt = @plr.read_at_offset(packet_offsets[2])
264
+ pkt = @plr.read_at_offset(packet_offsets[2]) # Grab the second LIMITS_CHANGE (META is 0)
261
265
  expect(pkt.target_name).to eql "SYSTEM"
262
266
  expect(pkt.packet_name).to eql "LIMITS_CHANGE"
263
- expect(pkt.received_time).to eql Time.new(2020,2,1,12,30,16)
267
+ expect(pkt.read('PACKET')).to eql "PKT2"
268
+ expect(pkt.received_time).to eql @time + 1
264
269
  @plr.close
265
270
  end
266
271
  end
@@ -415,9 +420,8 @@ module Cosmos
415
420
  end
416
421
 
417
422
  it "returns all packets if the start time is before all" do
418
- time = Time.new(2000,1,31,12,30,16)
419
423
  index = 0
420
- @plr.each(Dir[File.join(@log_path,"*cmd.bin")][0], true, time) do |packet|
424
+ @plr.each(Dir[File.join(@log_path,"*cmd.bin")][0], true, @time) do |packet|
421
425
  next if packet.packet_name == 'META'
422
426
  expect(packet.target_name).to eql @cmd_packets[index].target_name
423
427
  expect(packet.packet_name).to eql @cmd_packets[index].packet_name
@@ -429,51 +433,48 @@ module Cosmos
429
433
  end
430
434
 
431
435
  it "returns no packets if the start time is after all" do
432
- time = Time.new(2030,2,1,12,30,16)
433
436
  index = 0
434
- @plr.each(Dir[File.join(@log_path,"*tlm.bin")][0], true, time) do |packet|
437
+ @plr.each(Dir[File.join(@log_path,"*tlm.bin")][0], true, @time + 100) do |packet|
435
438
  index += 1
436
439
  end
437
440
  expect(index).to eql 0
438
441
  end
439
442
 
440
443
  it "returns all packets after a start time" do
441
- time = Time.new(2020,1,31,12,30,16)
442
444
  index = 0
443
- @plr.each(Dir[File.join(@log_path,"*cmd.bin")][0], true, time) do |packet|
444
- expect(packet.target_name).to eql @cmd_packets[index+1].target_name
445
- expect(packet.packet_name).to eql @cmd_packets[index+1].packet_name
446
- expect(packet.received_time).to eql @cmd_packets[index+1].received_time
447
- expect(packet.read('LABEL')).to eql @cmd_packets[index+1].read('LABEL')
445
+ @plr.each(Dir[File.join(@log_path,"*cmd.bin")][0], true, @time) do |packet|
446
+ next if packet.packet_name == 'META'
447
+ expect(packet.target_name).to eql @cmd_packets[index].target_name
448
+ expect(packet.packet_name).to eql @cmd_packets[index].packet_name
449
+ expect(packet.received_time).to eql @cmd_packets[index].received_time
450
+ expect(packet.read('LABEL')).to eql @cmd_packets[index].read('LABEL')
448
451
  index += 1
449
452
  end
450
- expect(index).to eql 2
453
+ expect(index).to eql 3
451
454
 
452
- time = Time.new(2020,2,1,12,30,16)
453
- index = 0
454
- @plr.each(Dir[File.join(@log_path,"*tlm.bin")][0], true, time) do |packet|
455
- expect(packet.target_name).to eql @tlm_packets[index+1].target_name
456
- expect(packet.packet_name).to eql @tlm_packets[index+1].packet_name
457
- expect(packet.received_time).to eql @tlm_packets[index+1].received_time
458
- expect(packet.read('PACKET')).to eql @tlm_packets[index+1].read('PACKET')
455
+ index = 1 # @time + 1
456
+ @plr.each(Dir[File.join(@log_path,"*tlm.bin")][0], true, @time + 1) do |packet|
457
+ next if packet.packet_name == 'META'
458
+ expect(packet.target_name).to eql @tlm_packets[index].target_name
459
+ expect(packet.packet_name).to eql @tlm_packets[index].packet_name
460
+ expect(packet.received_time).to eql @tlm_packets[index].received_time
461
+ expect(packet.read('PACKET')).to eql @tlm_packets[index].read('PACKET')
459
462
  index += 1
460
463
  end
461
- expect(index).to eql 2
464
+ expect(index).to eql 3
462
465
  end
463
466
 
464
467
  it "returns no packets if the end time is before all" do
465
- time = Time.new(2000,1,31,12,30,16)
466
468
  index = 0
467
- @plr.each(Dir[File.join(@log_path,"*tlm.bin")][0], true, nil, time) do |packet|
469
+ @plr.each(Dir[File.join(@log_path,"*tlm.bin")][0], true, nil, @time - 10) do |packet|
468
470
  index += 1
469
471
  end
470
472
  expect(index).to eql 0
471
473
  end
472
474
 
473
475
  it "returns all packets if the end time is after all" do
474
- time = Time.new(2030,2,1,12,30,16)
475
476
  index = 0
476
- @plr.each(Dir[File.join(@log_path,"*cmd.bin")][0], true, nil, time) do |packet|
477
+ @plr.each(Dir[File.join(@log_path,"*cmd.bin")][0], true, nil, @time + 10) do |packet|
477
478
  next if packet.packet_name == 'META'
478
479
  expect(packet.target_name).to eql @cmd_packets[index].target_name
479
480
  expect(packet.packet_name).to eql @cmd_packets[index].packet_name
@@ -485,9 +486,8 @@ module Cosmos
485
486
  end
486
487
 
487
488
  it "returns all packets before an end time" do
488
- time = Time.new(2020,1,31,12,30,16)
489
489
  index = 0
490
- @plr.each(Dir[File.join(@log_path,"*cmd.bin")][0], true, nil, time) do |packet|
490
+ @plr.each(Dir[File.join(@log_path,"*cmd.bin")][0], true, nil, @time) do |packet|
491
491
  next if packet.packet_name == 'META'
492
492
  expect(packet.target_name).to eql @cmd_packets[index].target_name
493
493
  expect(packet.packet_name).to eql @cmd_packets[index].packet_name
@@ -495,11 +495,10 @@ module Cosmos
495
495
  expect(packet.read('LABEL')).to eql @cmd_packets[index].read('LABEL')
496
496
  index += 1
497
497
  end
498
- expect(index).to eql 2
498
+ expect(index).to eql 1
499
499
 
500
- time = Time.new(2020,2,1,12,30,16)
501
500
  index = 0
502
- @plr.each(Dir[File.join(@log_path,"*tlm.bin")][0], true, nil, time) do |packet|
501
+ @plr.each(Dir[File.join(@log_path,"*tlm.bin")][0], true, nil, @time + 1) do |packet|
503
502
  next if packet.packet_name == 'META'
504
503
  expect(packet.target_name).to eql @tlm_packets[index].target_name
505
504
  expect(packet.packet_name).to eql @tlm_packets[index].packet_name