Class: MobyController::QT::SutAdapter
- Inherits:
-
SutAdapter
- Object
- SutAdapter
- MobyController::QT::SutAdapter
- Defined in:
- lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb
Overview
Sut adapter that used TCP/IP connections to send and receive data from QT side.
Instance Attribute Summary collapse
-
#deflate_compression_level ⇒ Object
Returns the value of attribute deflate_compression_level.
-
#deflate_minimum_size ⇒ Object
Returns the value of attribute deflate_minimum_size.
-
#deflate_service_request ⇒ Object
Returns the value of attribute deflate_service_request.
-
#socket_connect_timeout ⇒ Object
Returns the value of attribute socket_connect_timeout.
-
#socket_read_timeout ⇒ Object
Returns the value of attribute socket_read_timeout.
-
#socket_received_bytes ⇒ Object
readonly
Returns the value of attribute socket_received_bytes.
-
#socket_received_packets ⇒ Object
readonly
Returns the value of attribute socket_received_packets.
-
#socket_sent_bytes ⇒ Object
readonly
Returns the value of attribute socket_sent_bytes.
-
#socket_sent_packets ⇒ Object
readonly
Returns the value of attribute socket_sent_packets.
-
#socket_write_timeout ⇒ Object
Returns the value of attribute socket_write_timeout.
-
#sut_id ⇒ Object
readonly
Returns the value of attribute sut_id.
Instance Method Summary collapse
-
#append_command(node_list) ⇒ Object
TODO: document me.
-
#connect(id = nil) ⇒ Object
TODO: document me.
- #connected? ⇒ Boolean
-
#disconnect ⇒ Object
TODO: document me.
-
#group? ⇒ Boolean
TODO: document me.
-
#initialize(sut_id, receive_timeout = 25, send_timeout = 25, connect_timeout = 25) ⇒ SutAdapter
constructor
TODO: better way to set the host and port parameters Initialize the tcp adapter for communicating with the device.
-
#send_grouped_request ⇒ Object
Sends a grouped command message to the server.
-
#send_service_request(message, return_checksum = false) ⇒ Object
- Send the message to the qt server If there is no exception propagated the send to the device was successful == params message
-
message in qttas protocol format == returns the response body.
-
#set_message_builder(builder) ⇒ Object
Set the document builder for the grouped behaviour message.
- #timeout_capable_socket_opener(ip, port, timeout = nil) ⇒ Object
Constructor Details
#initialize(sut_id, receive_timeout = 25, send_timeout = 25, connect_timeout = 25) ⇒ SutAdapter
TODO: better way to set the host and port parameters
Initialize the tcp adapter for communicating with the device. Communication is done using two tcp channels one form commanding the device and one for receiving ui state data. UI state data receivin is done in a seprate thread so it is good once usage is complete the shutdown_comms is called
params
sut_id id for the sut so that client details can be fetched from params
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 52 def initialize( sut_id, receive_timeout = 25, send_timeout = 25, connect_timeout = 25 ) # reset socket @socket = nil # connection state is false by default @connected = false # store sut id @sut_id = sut_id # reset hooks - no hooks by default @hooks = {} # reset sent/received bytes and packets counters @socket_received_bytes = 0 @socket_sent_bytes = 0 @socket_received_packets = 0 @socket_sent_packets = 0 # set timeouts @socket_read_timeout = receive_timeout @socket_write_timeout = send_timeout @socket_connect_timeout = connect_timeout # randomized value for initial message packet counter @counter = rand( 1000 ) # optimization - use local variables for less AST lookups @tcp_socket_select_method = TCPSocket.method( :select ) @tdriver_checksum_crc16_ibm_method = TDriver::Checksum.method( :crc16_ibm ) # retrieve sut configuration _sut_parameters = $parameters[ @sut_id ] # determine which inflate method to use if _sut_parameters[ :win_native, false ].to_s.true? @inflate_method = method( :inflate_windows_native ) else @inflate_method = method( :inflate ) end # default size 1kb @deflate_minimum_size = _sut_parameters[ :io_deflate_minimum_size_in_bytes, 1024 ].to_i # enabled by default - deflate outgoing service request if size > deflate_minimum_size @deflate_service_request = _sut_parameters[ :io_deflate_service_request, true ].true? # retrieve default compression level - best compression by default @deflate_compression_level = _sut_parameters[ :io_deflate_compression_level, 9 ].to_i end |
Instance Attribute Details
#deflate_compression_level ⇒ Object
Returns the value of attribute deflate_compression_level.
35 36 37 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 35 def deflate_compression_level @deflate_compression_level end |
#deflate_minimum_size ⇒ Object
Returns the value of attribute deflate_minimum_size.
35 36 37 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 35 def deflate_minimum_size @deflate_minimum_size end |
#deflate_service_request ⇒ Object
Returns the value of attribute deflate_service_request.
35 36 37 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 35 def deflate_service_request @deflate_service_request end |
#socket_connect_timeout ⇒ Object
Returns the value of attribute socket_connect_timeout.
35 36 37 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 35 def socket_connect_timeout @socket_connect_timeout end |
#socket_read_timeout ⇒ Object
Returns the value of attribute socket_read_timeout.
35 36 37 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 35 def socket_read_timeout @socket_read_timeout end |
#socket_received_bytes ⇒ Object (readonly)
Returns the value of attribute socket_received_bytes.
27 28 29 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 27 def socket_received_bytes @socket_received_bytes end |
#socket_received_packets ⇒ Object (readonly)
Returns the value of attribute socket_received_packets.
27 28 29 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 27 def socket_received_packets @socket_received_packets end |
#socket_sent_bytes ⇒ Object (readonly)
Returns the value of attribute socket_sent_bytes.
27 28 29 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 27 def socket_sent_bytes @socket_sent_bytes end |
#socket_sent_packets ⇒ Object (readonly)
Returns the value of attribute socket_sent_packets.
27 28 29 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 27 def socket_sent_packets @socket_sent_packets end |
#socket_write_timeout ⇒ Object
Returns the value of attribute socket_write_timeout.
35 36 37 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 35 def socket_write_timeout @socket_write_timeout end |
#sut_id ⇒ Object (readonly)
Returns the value of attribute sut_id.
27 28 29 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 27 def sut_id @sut_id end |
Instance Method Details
#append_command(node_list) ⇒ Object
TODO: document me
211 212 213 214 215 216 217 218 219 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 211 def append_command( node_list ) node_list.each { | child | @_builder.doc.root.add_child( child ) } end |
#connect(id = nil) ⇒ Object
TODO: document me
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 148 def connect( id = nil ) id ||= @sut_id sut_parameters = $parameters[ id, {} ] begin # retrieve ip and verify that value is not empty or nil ip = sut_parameters[ :qttas_server_ip, nil ].not_blank( 'Connection failure; QTTAS server IP not defined in SUT configuration' ).to_s # retrieve port and verify that value is not empty or nil port = sut_parameters[ :qttas_server_port, nil ].not_blank( 'Connection failure; QTTAS server port not defined in SUT configuration' ).to_i # executes the code block before openning the connection execute_hook( 'before_connect', id, ip, port ) if hooked?( 'before_connect' ) # open tcp/ip connection # Using ruby TCPSocket this way will utilize the underlying kernel to do the timeout, which by default is too long (In my tests, on ubuntu 10.10, TCPSocket.open # will wait for exactly 380 seconds before throwing exception which is *FAR* too long .. @socket = TCPSocket.open( ip, port ) # open tcp/ip connectio ## The block will actually double the time, so halve it. Actual timeout will +1 if it's an odd number # @socket = timeout_capable_socket_opener(ip,port,(@socket_connect_timeout.to_i / 2.0).ceil) # set connected status to true @connected = true # communication authentication etc can be done here execute_hook( 'after_connect', id, ip, port, @socket ) if hooked?( 'after_connect' ) rescue execute_hook( 'connection_failed', id, ip, port, $! ) if hooked?( 'connection_failed' ) #If reporter active report connetion error raise IOError, "Connection failure; verify that QTTAS server is up and running at #{ ip }:#{ port }.\n Nested exception: #{ $!. }" end true end |
#connected? ⇒ Boolean
243 244 245 246 247 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 243 def connected? @connected end |
#disconnect ⇒ Object
TODO: document me
112 113 114 115 116 117 118 119 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 112 def disconnect # disconnect socket only if connected @socket.close if @connected @connected = false end |
#group? ⇒ Boolean
TODO: document me
195 196 197 198 199 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 195 def group? @_group end |
#send_grouped_request ⇒ Object
Sends a grouped command message to the server. Sets group to false and nils the builder to prevent future behviours of being grouped (unless so wanted)
returns
the amout of commands grouped (and send)
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 225 def send_grouped_request @_group = false size = @_builder.doc.root.children.size send_service_request( Comms::MessageGenerator.generate( @_builder.to_xml ) ) @_builder = nil size end |
#send_service_request(message, return_checksum = false) ⇒ Object
Send the message to the qt server
If there is no exception propagated the send to the device was successful
params
- message
-
message in qttas protocol format
returns
the response body
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 255 def send_service_request( , return_checksum = false ) = 0 header = nil body = nil crc = nil connect if !@connected # increase message count @counter += 1 # set request message id . = @counter # deflate message body if @deflate_service_request == true # do not deflate messages below 1kb .deflate( @deflate_compression_level ) unless .size < @deflate_minimum_size end # generate binary message to be sent to socket = .( @counter ) # write request message to socket write_socket( ) until == @counter # read message header from socket, unpack string to array # header[ 0 ] = command_flag # header[ 1 ] = body_size # header[ 2 ] = crc # header[ 3 ] = compression_flag # header[ 4 ] = message_id header = read_socket( 12 ).unpack( 'CISCI' ) # read message body from socket body = read_socket( header[ 1 ] ) # calculate body crc16 checksum crc = @tdriver_checksum_crc16_ibm_method.call( body ) # read the message body and compare crc checksum raise IOError, "CRC checksum did not match, response message body is corrupted! (#{ crc } != #{ header[ 2 ] })" if crc != header[ 2 ] # validate response message; check that response message id matches the request # if smaller than expected try to read the next message but if bigger raise error = header[ 4 ] if < @counter $logger.warning "Response to request did not match: \"#{ header[ 4 ].to_s }\"<\"#{ @counter.to_s }\"" elsif > @counter $logger.fatal "Response to request did not match: \"#{ header[ 4 ].to_s }\">\"#{ @counter.to_s }\"" # save to file? $logger.fatal body raise RuntimeError, "Response to request did not match: \"#{ header[ 4 ].to_s }\"!=\"#{ @counter.to_s }\"" end end # inflate the message body if compressed body = @inflate_method.call( body ) if ( header[ 3 ] == 2 ) # raise exception if messages error flag is set # Flag statuses: # 0 -> ERROR_MSG # 1 -> VALID_MSG # 2 -> OK_MESSAGE if header[ 0 ] == 0 if body =~ /The application with Id \d+ is no longer available/ raise MobyBase::ApplicationNotAvailableError, body else raise RuntimeError, body end end # return the body and checksum if required return_checksum ? [ body, body.hash ] : body end |
#set_message_builder(builder) ⇒ Object
Set the document builder for the grouped behaviour message.
202 203 204 205 206 207 208 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 202 def ( builder ) @_group = true @_builder = builder end |
#timeout_capable_socket_opener(ip, port, timeout = nil) ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/testability-driver-plugins/testability-driver-qt-sut-plugin/sut/adapter.rb', line 121 def timeout_capable_socket_opener(ip,port,timeout=nil) addr = Socket.getaddrinfo(ip, nil) sock = Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0) if timeout secs = Integer(timeout) usecs = Integer((timeout - secs) * 1_000_000) optval = [secs, usecs].pack("l_2") ## actual timeout gets triggered after 2 times of "timeout" value, most likely because my patch applies timeout to read AND write .. sock.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, optval sock.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval ## also, worth checking if there's actually some Socket::SO_* that applies the timeout to connection forming .. end begin sock.connect_nonblock(Socket.pack_sockaddr_in(port, addr[0][3])) rescue Errno::EINPROGRESS resp = IO.select([sock],nil, nil, timeout.to_i) begin sock.connect_nonblock(Socket.pack_sockaddr_in(port, addr[0][3])) rescue Errno::EISCONN end end sock ## Its also worth noting that if we set RCV AND SNDTIMEOT to some value when checking for established socket, ## it might make sense to set the defaults values back again so that only during the connection, timeout is ## different.. end |