cosmos 4.0.3 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -5
  3. data/Manifest.txt +11 -1
  4. data/README.md +3 -2
  5. data/Rakefile +18 -4
  6. data/appveyor.yml +19 -0
  7. data/cosmos.gemspec +14 -3
  8. data/data/config/cmd_tlm_server.yaml +3 -0
  9. data/data/crc.txt +63 -60
  10. data/demo/config/targets/INST/cmd_tlm_server.txt +1 -0
  11. data/demo/config/targets/INST/cmd_tlm_server2.txt +7 -0
  12. data/demo/config/tools/cmd_sequence/cmd_sequence.txt +2 -0
  13. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +8 -12
  14. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +7 -9
  15. data/demo/lib/cmd_sequence_exporter.rb +52 -0
  16. data/demo/lib/example_background_task.rb +1 -0
  17. data/demo/procedures/replay_test.rb +32 -0
  18. data/ext/cosmos/ext/structure/structure.c +39 -3
  19. data/install/config/tools/cmd_tlm_server/cmd_tlm_server.txt +1 -0
  20. data/install/config/tools/launcher/launcher.txt +2 -0
  21. data/lib/cosmos/config/config_parser.rb +2 -0
  22. data/lib/cosmos/core_ext/io.rb +89 -60
  23. data/lib/cosmos/gui/qt.rb +5 -8
  24. data/lib/cosmos/gui/qt_tool.rb +8 -8
  25. data/lib/cosmos/gui/text/ruby_editor.rb +12 -12
  26. data/lib/cosmos/gui/utilities/script_module_gui.rb +9 -9
  27. data/lib/cosmos/gui/widgets/realtime_button_bar.rb +18 -17
  28. data/lib/cosmos/interfaces/protocols/fixed_protocol.rb +2 -2
  29. data/lib/cosmos/interfaces/protocols/template_protocol.rb +3 -0
  30. data/lib/cosmos/interfaces/udp_interface.rb +27 -14
  31. data/lib/cosmos/io/buffered_file.rb +0 -1
  32. data/lib/cosmos/io/json_drb.rb +134 -214
  33. data/lib/cosmos/io/json_drb_object.rb +22 -61
  34. data/lib/cosmos/io/json_drb_rack.rb +79 -0
  35. data/lib/cosmos/io/json_rpc.rb +27 -0
  36. data/lib/cosmos/io/udp_sockets.rb +102 -58
  37. data/lib/cosmos/packets/commands.rb +1 -1
  38. data/lib/cosmos/packets/structure.rb +1 -1
  39. data/lib/cosmos/packets/structure_item.rb +37 -5
  40. data/lib/cosmos/script/cmd_tlm_server.rb +76 -2
  41. data/lib/cosmos/script/replay.rb +60 -0
  42. data/lib/cosmos/script/script.rb +20 -2
  43. data/lib/cosmos/script/scripting.rb +9 -9
  44. data/lib/cosmos/script/tools.rb +14 -0
  45. data/lib/cosmos/system/system.rb +185 -92
  46. data/lib/cosmos/system/target.rb +1 -1
  47. data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +44 -4
  48. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +4 -0
  49. data/lib/cosmos/tools/cmd_sequence/sequence_list.rb +7 -0
  50. data/lib/cosmos/tools/cmd_tlm_server/api.rb +347 -20
  51. data/lib/cosmos/tools/cmd_tlm_server/background_tasks.rb +3 -0
  52. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +329 -111
  53. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +13 -0
  54. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +261 -95
  55. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +46 -35
  56. data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +18 -8
  57. data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +39 -28
  58. data/lib/cosmos/tools/cmd_tlm_server/gui/replay_tab.rb +242 -0
  59. data/lib/cosmos/tools/cmd_tlm_server/gui/status_tab.rb +24 -8
  60. data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +18 -6
  61. data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +5 -4
  62. data/lib/cosmos/tools/cmd_tlm_server/replay_backend.rb +375 -0
  63. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +10 -2
  64. data/lib/cosmos/tools/data_viewer/data_viewer.rb +40 -5
  65. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +18 -20
  66. data/lib/cosmos/tools/launcher/launcher_config.rb +5 -16
  67. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +65 -39
  68. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +19 -0
  69. data/lib/cosmos/tools/replay/replay.rb +5 -505
  70. data/lib/cosmos/tools/script_runner/script_audit.rb +1 -0
  71. data/lib/cosmos/tools/script_runner/script_runner.rb +3 -4
  72. data/lib/cosmos/tools/script_runner/script_runner_config.rb +3 -4
  73. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +44 -23
  74. data/lib/cosmos/tools/test_runner/results_writer.rb +4 -0
  75. data/lib/cosmos/tools/test_runner/test_runner.rb +0 -3
  76. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +6 -2
  77. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +26 -1
  78. data/lib/cosmos/tools/tlm_viewer/screen.rb +24 -1
  79. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +25 -0
  80. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +24 -14
  81. data/lib/cosmos/top_level.rb +34 -24
  82. data/lib/cosmos/utilities/csv.rb +60 -8
  83. data/lib/cosmos/version.rb +5 -5
  84. data/spec/config/config_parser_spec.rb +10 -1
  85. data/spec/core_ext/socket_spec.rb +4 -2
  86. data/spec/gui/utilities/script_module_gui_spec.rb +102 -0
  87. data/spec/install/config/data/data.txt +1 -0
  88. data/spec/install/config/targets/INST/cmd_tlm/inst_cmds.txt +2 -0
  89. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +1 -2
  90. data/spec/interfaces/protocols/template_protocol_spec.rb +72 -2
  91. data/spec/interfaces/serial_interface_spec.rb +1 -1
  92. data/spec/interfaces/udp_interface_spec.rb +14 -0
  93. data/spec/io/buffered_file_spec.rb +37 -0
  94. data/spec/io/json_drb_object_spec.rb +2 -15
  95. data/spec/io/json_drb_spec.rb +61 -121
  96. data/spec/io/udp_sockets_spec.rb +42 -2
  97. data/spec/packet_logs/packet_log_reader_spec.rb +5 -2
  98. data/spec/packets/binary_accessor_spec.rb +1 -1
  99. data/spec/packets/packet_item_spec.rb +1 -1
  100. data/spec/packets/structure_item_spec.rb +5 -6
  101. data/spec/script/cmd_tlm_server_spec.rb +39 -4
  102. data/spec/script/commands_disconnect_spec.rb +1 -1
  103. data/spec/script/commands_spec.rb +2 -1
  104. data/spec/script/scripting_spec.rb +18 -3
  105. data/spec/script/telemetry_spec.rb +5 -0
  106. data/spec/spec_helper.rb +43 -26
  107. data/spec/streams/tcpip_socket_stream_spec.rb +2 -2
  108. data/spec/system/system_spec.rb +11 -9
  109. data/spec/system/target_spec.rb +3 -0
  110. data/spec/tools/cmd_tlm_server/api_spec.rb +543 -29
  111. data/spec/tools/cmd_tlm_server/background_task_spec.rb +2 -2
  112. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +31 -75
  113. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +199 -66
  114. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +85 -9
  115. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +29 -127
  116. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +10 -50
  117. data/spec/tools/launcher/launcher_config_spec.rb +1 -1
  118. data/spec/tools/table_manager/table_item_spec.rb +1 -1
  119. data/spec/tools/table_manager/tablemanager_core_spec.rb +4 -4
  120. data/spec/top_level/top_level_spec.rb +151 -3
  121. data/spec/utilities/csv_spec.rb +24 -5
  122. metadata +61 -9
  123. data/lib/cosmos/tools/replay/replay_server.rb +0 -91
@@ -41,7 +41,7 @@ if RUBY_ENGINE == 'ruby' or Gem.win_platform?
41
41
  describe "connect" do
42
42
  it "passes a new SerialStream to the stream protocol" do
43
43
  # Ensure the 'NONE' parity is coverted to a symbol
44
- if Kernel.is_windows?
44
+ if Kernel.is_windows? && !ENV['APPVEYOR']
45
45
  i = SerialInterface.new('COM1','COM1','9600','NONE','1','0','0','burst')
46
46
  expect(i.connected?).to be false
47
47
  i.connect
@@ -83,6 +83,20 @@ module Cosmos
83
83
  expect(i.instance_variable_get(:@write_socket)).to be_nil
84
84
  expect(i.instance_variable_get(:@read_socket)).to be_nil
85
85
  end
86
+
87
+ it "creates one socket if read_port == write_src_port" do
88
+ i = UdpInterface.new('localhost','8888','8889', '8889')
89
+ expect(i.connected?).to be false
90
+ i.connect
91
+ expect(i.connected?).to be true
92
+ expect(i.instance_variable_get(:@write_socket)).to_not be_nil
93
+ expect(i.instance_variable_get(:@read_socket)).to_not be_nil
94
+ expect(i.instance_variable_get(:@read_socket)).to eql i.instance_variable_get(:@write_socket)
95
+ i.disconnect
96
+ expect(i.connected?).to be false
97
+ expect(i.instance_variable_get(:@write_socket)).to be_nil
98
+ expect(i.instance_variable_get(:@read_socket)).to be_nil
99
+ end
86
100
  end
87
101
 
88
102
  describe "read" do
@@ -50,6 +50,17 @@ module Cosmos
50
50
  end
51
51
  end
52
52
 
53
+ it "handles trying to read past the end" do
54
+ file = BufferedFile.open(@filename, "rb") do |file|
55
+ file.seek(-16, IO::SEEK_END)
56
+ expect(file.pos).to eql ((2 * BufferedFile::BUFFER_SIZE) - 16)
57
+ expect(file.read(DATA.length * 10)).to eql(DATA)
58
+ expect(file.pos).to eql BufferedFile::BUFFER_SIZE * 2
59
+ expect(file.read(DATA.length)).to be_nil
60
+ expect(file.pos).to eql BufferedFile::BUFFER_SIZE * 2
61
+ end
62
+ end
63
+
53
64
  it "reads equal to the buffer size" do
54
65
  file = BufferedFile.open(@filename, "rb") do |file|
55
66
  expect(file.read(BufferedFile::BUFFER_SIZE)).to eql(DATA * (BufferedFile::BUFFER_SIZE / DATA.length))
@@ -69,9 +80,35 @@ module Cosmos
69
80
  expect(file.read(BufferedFile::BUFFER_SIZE + 1)).to be_nil
70
81
  end
71
82
  end
83
+
84
+ it "reads greater than the buffer size after a previous read" do
85
+ file = BufferedFile.open(@filename, "rb") do |file|
86
+ expect(file.read(DATA.length * 10)).to eql(DATA * 10)
87
+ expect(file.pos).to eql DATA.length * 10
88
+ expect(file.read(BufferedFile::BUFFER_SIZE + 1)).to eql(DATA * ((BufferedFile::BUFFER_SIZE + 10) / DATA.length) << DATA[0])
89
+ expect(file.pos).to eql(DATA.length * 10 + BufferedFile::BUFFER_SIZE + 1)
90
+ end
91
+ end
72
92
  end
73
93
 
74
94
  describe "seek" do
95
+ it "raises if given more than 2 arguments" do
96
+ file = BufferedFile.open(@filename, "rb") do |file|
97
+ expect { file.seek(0, 4, IO::SEEK_CUR) }.to raise_error(ArgumentError)
98
+ end
99
+ end
100
+
101
+ it "implies SEEK_SET with 1 argument" do
102
+ file = BufferedFile.open(@filename, "rb") do |file|
103
+ expect(file.read(8)).to eql DATA[0..7]
104
+ expect(file.pos).to eql 8
105
+ file.seek(4, IO::SEEK_CUR)
106
+ expect(file.pos).to eql 12
107
+ file.seek(0)
108
+ expect(file.pos).to eql 0
109
+ end
110
+ end
111
+
75
112
  it "has reads still work afterwards" do
76
113
  file = BufferedFile.open(@filename, "rb") do |file|
77
114
  expect(file.read(8)).to eql DATA[0..7]
@@ -38,30 +38,17 @@ module Cosmos
38
38
  end
39
39
 
40
40
  it "raises an exception if the remote connection can't be made" do
41
- json = JsonDRb.new
42
- json.start_service('127.0.0.1', 7777, self)
43
- allow_any_instance_of(Socket).to receive(:connect_nonblock) { raise "Error" }
44
41
  obj = JsonDRbObject.new("localhost", 7777)
45
42
  expect { obj.my_method(10) }.to raise_error(DRb::DRbConnError)
46
43
  obj.disconnect
47
- json.stop_service
48
44
  sleep(0.1)
49
45
  end
50
46
 
51
47
  it "retries the request and then raise an exception" do
52
- class JsonDRbObjectServer
53
- def my_method(param)
54
- param * 2
55
- end
56
- end
57
-
58
- json = JsonDRb.new
59
- json.start_service('127.0.0.1', 7777, JsonDRbObjectServer.new)
60
- allow(JsonDRb).to receive(:send_data) { raise "Error" }
48
+ allow_any_instance_of(HTTPClient).to receive(:post) { raise "Error" }
61
49
  obj = JsonDRbObject.new("localhost", 7777)
62
50
  expect { obj.my_method(10) }.to raise_error(DRb::DRbConnError)
63
51
  obj.disconnect
64
- json.stop_service
65
52
  sleep(0.1)
66
53
  end
67
54
 
@@ -86,7 +73,7 @@ module Cosmos
86
73
  json = JsonDRb.new
87
74
  json.start_service('127.0.0.1', 7777, JsonDRbObjectServer.new)
88
75
  obj = JsonDRbObject.new("localhost", 7777)
89
- allow(JsonDRb).to receive(:receive_message) { nil }
76
+ allow_any_instance_of(JsonDrbRack).to receive(:call) { sleep(5.0); nil }
90
77
  expect { obj.my_method(10) }.to raise_error(DRb::DRbConnError)
91
78
  obj.disconnect
92
79
  json.stop_service
@@ -11,6 +11,7 @@
11
11
  require 'spec_helper'
12
12
  require 'cosmos/io/json_drb'
13
13
  require 'cosmos/io/json_rpc'
14
+ require 'httpclient'
14
15
 
15
16
  module Cosmos
16
17
 
@@ -52,6 +53,18 @@ module Cosmos
52
53
  end
53
54
 
54
55
  describe "start_service" do
56
+
57
+ it "can be started again after stopping" do
58
+ @json.start_service('127.0.0.1', 7777, self)
59
+ @json.stop_service
60
+ @json.start_service('127.0.0.1', 7777, self)
61
+ @json.stop_service
62
+ expect { @json.start_service('blah', 7777, self) }.to raise_error(/JsonDRb http server could not be started/)
63
+ @json.stop_service
64
+ @json.start_service('127.0.0.1', 7777, self)
65
+ @json.stop_service
66
+ end
67
+
55
68
  it "does nothing when passed no parameters" do
56
69
  expect(@json.thread).to be_nil
57
70
  @json.start_service()
@@ -69,12 +82,10 @@ module Cosmos
69
82
  capture_io do |stdout|
70
83
  expect(@json.thread).to be_nil
71
84
  system_exit_count = $system_exit_count
72
- @json.start_service('blah', 7777, self)
73
- thread = @json.thread
85
+ expect { @json.start_service('blah', 7777, self) }.to raise_error(/JsonDRb http server could not be started/)
86
+ sleep 5
74
87
  expect($system_exit_count).to eql(system_exit_count + 1)
75
- sleep 0.1
76
-
77
- expect(stdout.string).to match /listen thread/
88
+ expect(stdout.string).to match /JsonDRb http server could not be started or unexpectedly died/
78
89
  @json.stop_service
79
90
  sleep(0.1)
80
91
  end
@@ -84,25 +95,33 @@ module Cosmos
84
95
  end
85
96
  end
86
97
 
98
+ it "raises an error if the server doesn't start" do
99
+ allow(Rack::Handler::Puma).to receive(:run) {}
100
+ expect { @json.start_service('127.0.0.1', 7777, self) }.to raise_error(/JsonDRb http server could not be started/)
101
+ end
102
+
87
103
  it "creates a single listen thread" do
88
104
  expect(@json.thread).to be_nil
89
105
  @json.start_service('127.0.0.1', 7777, self)
106
+ sleep(1)
90
107
  expect(@json.thread.alive?).to be true
91
- expect { @json.start_service('127.0.0.1', 7777, self) }.to raise_error(/Error binding to port/)
108
+ num_threads = running_threads.length
109
+ @json.start_service('127.0.0.1', 7777, self)
110
+ sleep(1)
111
+ expect(running_threads.length).to eql num_threads
92
112
  @json.stop_service
93
113
  sleep(0.1)
94
114
  end
95
115
 
96
116
  it "rescues listen thread exceptions" do
97
117
  capture_io do |stdout|
98
- allow_any_instance_of(TCPServer).to receive(:accept_nonblock) { raise "BLAH" }
99
- @json.start_service('127.0.0.1', 7777, self)
100
- socket = TCPSocket.open('127.0.0.1',7777)
101
- sleep 0.1
118
+ allow(Rack::Handler::Puma).to receive(:run) { raise "BLAH" }
119
+ expect { @json.start_service('127.0.0.1', 7777, self) }.to raise_error(/JsonDRb http server could not be started/)
120
+ sleep(0.1)
102
121
  @json.stop_service
103
122
  sleep(0.1)
104
123
 
105
- expect(stdout.string).to match /JsonDRb listen thread unexpectedly died/
124
+ expect(stdout.string).to match /JsonDRb http server could not be started or unexpectedly died/
106
125
  end
107
126
 
108
127
  Dir[File.join(Cosmos::USERPATH,"*_exception.txt")].each do |file|
@@ -110,19 +129,19 @@ module Cosmos
110
129
  end
111
130
  end
112
131
 
113
- it "ignores connections via the ACL" do
132
+ it "rejects posts via the ACL" do
114
133
  @json.acl = ACL.new(['deny','127.0.0.1'], ACL::ALLOW_DENY)
115
134
  @json.start_service('127.0.0.1', 7777, self)
116
- socket = TCPSocket.open('127.0.0.1',7777)
117
- sleep 0.1
118
- expect(socket.eof?).to be true
119
- socket.close
135
+ client = HTTPClient.new
136
+ res = client.post("http://127.0.0.1:7777", "")
137
+ expect(res.status).to eq 403
138
+ expect(res.body).to match /Forbidden/
120
139
  @json.stop_service
121
140
  sleep(0.1)
122
141
  end
123
142
  end
124
143
 
125
- describe "receive_message" do
144
+ describe "process_request" do
126
145
  it "processes success requests" do
127
146
  class MyServer1
128
147
  def my_method(param)
@@ -130,15 +149,9 @@ module Cosmos
130
149
  end
131
150
 
132
151
  @json.start_service('127.0.0.1', 7777, MyServer1.new)
133
- socket = TCPSocket.open('127.0.0.1',7777)
134
- sleep 0.1
135
- request = JsonRpcRequest.new('my_method', 'param', 1).to_json
136
- JsonDRb.send_data(socket, request)
137
- response_data = JsonDRb.receive_message(socket, '', @pipe_reader)
138
- response = JsonRpcResponse.from_json(response_data)
139
- expect(response).to be_a(JsonRpcSuccessResponse)
140
- socket.close
141
- sleep 0.1
152
+ request_data = JsonRpcRequest.new('my_method', 'param', 1).to_json
153
+ response_data, error_code = @json.process_request(request_data, Time.now)
154
+ expect(error_code).to eq nil
142
155
  @json.stop_service
143
156
  sleep(0.1)
144
157
  end
@@ -148,17 +161,10 @@ module Cosmos
148
161
  end
149
162
 
150
163
  @json.start_service('127.0.0.1', 7777, MyServer2.new)
151
- socket = TCPSocket.open('127.0.0.1',7777)
152
- sleep 0.1
153
- request = JsonRpcRequest.new('my_method', 'param', 1).to_json
154
- JsonDRb.send_data(socket, request)
155
- response_data = JsonDRb.receive_message(socket, '', @pipe_reader)
156
- response = JsonRpcResponse.from_json(response_data)
157
- expect(response).to be_a(JsonRpcErrorResponse)
158
- expect(response.error.code).to eql -32601
159
- expect(response.error.message).to eql "Method not found"
160
- socket.close
161
- sleep 0.1
164
+ request_data = JsonRpcRequest.new('my_method', 'param', 1).to_json
165
+ response_data, error_code = @json.process_request(request_data, Time.now)
166
+ expect(error_code).to eql -32601
167
+ expect(response_data).to match /Method not found/
162
168
  @json.stop_service
163
169
  sleep(0.1)
164
170
  end
@@ -170,17 +176,10 @@ module Cosmos
170
176
  end
171
177
 
172
178
  @json.start_service('127.0.0.1', 7777, MyServer3.new)
173
- socket = TCPSocket.open('127.0.0.1',7777)
174
- sleep 0.1
175
- request = JsonRpcRequest.new('my_method', 'param1', 1).to_json
176
- JsonDRb.send_data(socket, request)
177
- response_data = JsonDRb.receive_message(socket, '', @pipe_reader)
178
- response = JsonRpcResponse.from_json(response_data)
179
- expect(response).to be_a(JsonRpcErrorResponse)
180
- expect(response.error.code).to eql -32602
181
- expect(response.error.message).to eql "Invalid params"
182
- socket.close
183
- sleep 0.1
179
+ request_data = JsonRpcRequest.new('my_method', 'param1', 1).to_json
180
+ response_data, error_code = @json.process_request(request_data, Time.now)
181
+ expect(error_code).to eql -32602
182
+ expect(response_data).to match /Invalid params/
184
183
  @json.stop_service
185
184
  sleep(0.1)
186
185
  end
@@ -193,91 +192,32 @@ module Cosmos
193
192
  end
194
193
 
195
194
  @json.start_service('127.0.0.1', 7777, MyServer4.new)
196
- socket = TCPSocket.open('127.0.0.1',7777)
197
- sleep 0.1
198
- request = JsonRpcRequest.new('my_method', 'param', 1).to_json
199
- JsonDRb.send_data(socket, request)
200
- response_data = JsonDRb.receive_message(socket, '', @pipe_reader)
201
- response = JsonRpcResponse.from_json(response_data)
202
- expect(response).to be_a(JsonRpcErrorResponse)
203
- expect(response.error.code).to eql -1
204
- expect(response.error.message).to eql "Method Error"
205
- socket.close
206
- sleep 0.1
195
+ request_data = JsonRpcRequest.new('my_method', 'param', 1).to_json
196
+ response_data, error_code = @json.process_request(request_data, Time.now)
197
+ expect(error_code).to eql -1
198
+ expect(response_data).to match /Method Error/
207
199
  @json.stop_service
208
200
  sleep(0.1)
209
201
  end
210
202
 
211
203
  it "does not allow dangerous methods" do
212
204
  @json.start_service('127.0.0.1', 7777, self)
213
- socket = TCPSocket.open('127.0.0.1',7777)
214
- sleep 0.1
215
- request = JsonRpcRequest.new('send', 'param', 1).to_json
216
- JsonDRb.send_data(socket, request)
217
- response_data = JsonDRb.receive_message(socket, '', @pipe_reader)
218
- response = JsonRpcResponse.from_json(response_data)
219
- expect(response).to be_a(JsonRpcErrorResponse)
220
- expect(response.error.code).to eql -1
221
- expect(response.error.message).to eql "Cannot call unauthorized methods"
222
- socket.close
223
- sleep 0.1
205
+ request_data = JsonRpcRequest.new('send', 'param', 1).to_json
206
+ response_data, error_code = @json.process_request(request_data, Time.now)
207
+ expect(error_code).to eql -1
208
+ expect(response_data).to match /Cannot call unauthorized methods/
224
209
  @json.stop_service
225
210
  sleep(0.1)
226
211
  end
227
212
 
228
213
  it "handles an invalid JsonDRB request" do
229
214
  @json.start_service('127.0.0.1', 7777, self)
230
- socket = TCPSocket.open('127.0.0.1',7777)
231
- sleep 0.1
232
- request = JsonRpcRequest.new('send', 'param', 1).to_json
233
- request.gsub!("jsonrpc","version")
234
- request.gsub!("2.0","1.1")
235
- JsonDRb.send_data(socket, request)
236
- response_data = JsonDRb.receive_message(socket, '', @pipe_reader)
237
- response = JsonRpcResponse.from_json(response_data)
238
- expect(response).to be_a(JsonRpcErrorResponse)
239
- expect(response.error.code).to eql -32600
240
- expect(response.error.message).to eql "Invalid Request"
241
- socket.close
242
- sleep 0.1
243
- @json.stop_service
244
- sleep(0.1)
245
- end
246
- end
247
-
248
- describe "send_data" do
249
- it "retries if the socket blocks" do
250
- @json.start_service('127.0.0.1', 7777, self)
251
- socket = TCPSocket.open('127.0.0.1',7777)
252
- # Stub write_nonblock so it blocks
253
- $index = 0
254
- allow(socket).to receive(:write_nonblock) do
255
- case $index
256
- when 0
257
- $index += 1
258
- raise Errno::EWOULDBLOCK
259
- when 1
260
- $index += 1
261
- 5
262
- end
263
- end
264
- JsonDRb.send_data(socket, "\x00")
265
- socket.close
266
- @json.stop_service
267
- sleep(0.1)
268
- end
269
-
270
- it "eventuallies timeout if the socket blocks" do
271
- @json.start_service('127.0.0.1', 7777, self)
272
- socket = TCPSocket.open('127.0.0.1',7777)
273
- # Stub write_nonblock so it blocks
274
- $index = 0
275
- allow(socket).to receive(:write_nonblock) do
276
- raise Errno::EWOULDBLOCK
277
- end
278
- allow(IO).to receive(:select) { nil }
279
- expect { JsonDRb.send_data(socket, "\x00", 2) }.to raise_error(Timeout::Error)
280
- socket.close
215
+ request_data = JsonRpcRequest.new('send', 'param', 1).to_json
216
+ request_data.gsub!("jsonrpc","version")
217
+ request_data.gsub!("2.0","1.1")
218
+ response_data, error_code = @json.process_request(request_data, Time.now)
219
+ expect(error_code).to eql -32600
220
+ expect(response_data).to match /Invalid Request/
281
221
  @json.stop_service
282
222
  sleep(0.1)
283
223
  end
@@ -44,7 +44,7 @@ module Cosmos
44
44
 
45
45
  it "handles timeouts" do
46
46
  allow_any_instance_of(UDPSocket).to receive(:write_nonblock) { raise Errno::EWOULDBLOCK }
47
- expect(IO).to receive(:select).at_least(:once).and_return([], nil)
47
+ expect(IO).to receive(:fast_select).at_least(:once).and_return([], nil)
48
48
  udp_write = UdpWriteSocket.new('127.0.0.1', 8888)
49
49
  expect { udp_write.write("\x01\x02",2.0) }.to raise_error(Timeout::Error)
50
50
  udp_write.close
@@ -88,12 +88,52 @@ module Cosmos
88
88
 
89
89
  it "handles timeouts" do
90
90
  allow_any_instance_of(UDPSocket).to receive(:recvfrom_nonblock) { raise Errno::EWOULDBLOCK }
91
- expect(IO).to receive(:select).at_least(:once).and_return([], nil)
91
+ expect(IO).to receive(:fast_select).at_least(:once).and_return([], nil)
92
92
  udp_read = UdpReadSocket.new(8889)
93
93
  expect { udp_read.read(2.0) }.to raise_error(Timeout::Error)
94
94
  end
95
95
  end
96
96
 
97
97
  end
98
+
99
+ describe UdpReadWriteSocket do
100
+
101
+ describe "initialize" do
102
+ it "creates a socket" do
103
+ udp = UdpReadWriteSocket.new(8888)
104
+ expect(udp.local_address.ip_address).to eql '0.0.0.0'
105
+ expect(udp.local_address.ip_port).to eql 8888
106
+ udp.close
107
+ if RUBY_ENGINE == 'ruby' # UDP multicast does not work in Jruby
108
+ udp = UdpReadWriteSocket.new(8888, '0.0.0.0', 0, '224.0.1.1')
109
+ expect(IPAddr.new_ntoh(udp.getsockopt(Socket::IPPROTO_IP, Socket::IP_MULTICAST_IF).data).to_s).to eql "0.0.0.0"
110
+ udp.close
111
+ end
112
+ end
113
+ end
114
+
115
+ describe "read" do
116
+ it "reads data" do
117
+ udp_read = UdpReadWriteSocket.new(8888)
118
+ udp_write = UdpWriteSocket.new('127.0.0.1', 8888)
119
+ udp_write.write("\x01\x02",2.0)
120
+ expect(udp_read.read).to eql "\x01\x02"
121
+ udp_read.close
122
+ udp_write.close
123
+ end
124
+ end
125
+
126
+ describe "write" do
127
+ it "writes data" do
128
+ udp_read = UdpReadSocket.new(8888)
129
+ udp_write = UdpReadWriteSocket.new(0, "0.0.0.0", 8888, '127.0.0.1')
130
+ udp_write.write("\x01\x02",2.0)
131
+ expect(udp_read.read).to eql "\x01\x02"
132
+ udp_read.close
133
+ udp_write.close
134
+ end
135
+ end
136
+
137
+ end
98
138
  end
99
139