q-ruby-driver 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +66 -0
- data/README.txt +58 -0
- data/bin/q-ruby-driver +7 -0
- data/lib/q-ruby-driver.rb +49 -0
- data/lib/q-ruby-driver/q_connection.rb +78 -0
- data/lib/q-ruby-driver/q_exception.rb +24 -0
- data/lib/q-ruby-driver/q_io.rb +481 -0
- data/lib/q-ruby-driver/q_message.rb +57 -0
- data/spec/q-ruby-driver_spec.rb +186 -0
- data/spec/spec_helper.rb +17 -0
- data/test/test_connection.rb +63 -0
- data/test/test_helper.rb +15 -0
- data/test/test_io.rb +167 -0
- metadata +137 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
module QRubyDriver
|
2
|
+
|
3
|
+
# Provided for legacy compatibility with previous versions of q-ruby-driver
|
4
|
+
# Usage of this class is deprecated
|
5
|
+
class QMessage
|
6
|
+
|
7
|
+
attr :message_type
|
8
|
+
attr :exception
|
9
|
+
attr :value
|
10
|
+
attr :message_type
|
11
|
+
attr :message
|
12
|
+
attr :timing
|
13
|
+
|
14
|
+
@exception = false
|
15
|
+
|
16
|
+
def create(value, sync = false)
|
17
|
+
@value = value
|
18
|
+
sync == true ? @message_type = :sync : @message_type = :async
|
19
|
+
|
20
|
+
start_time = Time.now
|
21
|
+
|
22
|
+
qio = QIO.new
|
23
|
+
qio.write_message(value, sync)
|
24
|
+
qio.pos=0
|
25
|
+
@message = qio.read
|
26
|
+
puts [@message].inspect
|
27
|
+
@length = @message.length
|
28
|
+
@timing = Time.now - start_time
|
29
|
+
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
# Decodes a binary message into a QMessage
|
34
|
+
def decode(message)
|
35
|
+
start_time= Time.now
|
36
|
+
@message = message
|
37
|
+
qio = QIO.new(@message)
|
38
|
+
begin
|
39
|
+
@length, @message_type = qio.message_header()
|
40
|
+
@value = qio.read_item()
|
41
|
+
rescue QException => qe
|
42
|
+
@exception = qe
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
if @message.nil?
|
48
|
+
"QMessage [None]"
|
49
|
+
elsif !@exception.nil?
|
50
|
+
"QException [#{@message.unpack("H*")}] Type[#{@message_type}] Length [#{@length}] Value[#{@value}]"
|
51
|
+
else
|
52
|
+
"QMessage [#{@message.unpack("H*")}] Type[#{@message_type}] Length [#{@length}] Value[#{@value}]"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require File.expand_path(
|
2
|
+
File.join(File.dirname(__FILE__), %w[.. lib q-ruby-driver]))
|
3
|
+
|
4
|
+
include QRubyDriver
|
5
|
+
|
6
|
+
# RSpec tests require a live Q instance to which we can connect.
|
7
|
+
# See TestUnit tests for a self-contained test
|
8
|
+
|
9
|
+
describe QRubyDriver do
|
10
|
+
|
11
|
+
HOST, PORT = "localhost", 5001
|
12
|
+
|
13
|
+
it "should allow a basic Q connection to a Q instance" do
|
14
|
+
q_conn = QConnection.new HOST, PORT
|
15
|
+
q_conn.close
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should allow us to send a hand crafted message via a Q connection with async" do
|
19
|
+
q_conn = QConnection.new HOST, PORT
|
20
|
+
q_conn.send_raw("01000000120000000a0004000000613a6062")
|
21
|
+
q_conn.close
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should allow us to send a hand crafted message via a Q connection with sync" do
|
25
|
+
q_conn = QConnection.new HOST, PORT
|
26
|
+
q_conn.send_raw("01010000110000000a0003000000613a31")
|
27
|
+
q_conn.close
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should allow us to get a String" do
|
31
|
+
q_conn = QConnection.new HOST, PORT
|
32
|
+
response = q_conn.get("2+2")
|
33
|
+
q_conn.close
|
34
|
+
response.should.== 4
|
35
|
+
puts response
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should allow us to get a variable to set its value" do
|
39
|
+
q_conn = QConnection.new HOST, PORT
|
40
|
+
q_conn.get("a:`cheesy")
|
41
|
+
response = q_conn.get("a")
|
42
|
+
q_conn.close
|
43
|
+
response.should.== "cheesy"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should allow us to get a dictionary" do
|
47
|
+
q_conn = QConnection.new HOST, PORT
|
48
|
+
response = q_conn.get("`a`b!2 3")
|
49
|
+
q_conn.close
|
50
|
+
response.should.is_a? Hash
|
51
|
+
response.length.should.== 2
|
52
|
+
response["a"].should.== 2
|
53
|
+
response["b"].should.== 3
|
54
|
+
|
55
|
+
puts response.inspect
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should allow us to get vectors" do
|
59
|
+
q_conn = QConnection.new HOST, PORT
|
60
|
+
q_conn.get("a:`IBM`GOOG`APPL")
|
61
|
+
response = q_conn.get("a")
|
62
|
+
q_conn.close
|
63
|
+
response.should.is_a? Array
|
64
|
+
response.length.should.== 3
|
65
|
+
response[0].should.== "IBM"
|
66
|
+
response[1].should.== "GOOG"
|
67
|
+
response[2].should.== "APPL"
|
68
|
+
|
69
|
+
puts response.inspect
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should allow us to create a 1,000,000 trades" do
|
73
|
+
q_conn = QConnection.new HOST, PORT
|
74
|
+
q_conn.get("""trade:( []date:`date$();
|
75
|
+
time:`time$();
|
76
|
+
sym:`symbol$();
|
77
|
+
price:`float$();
|
78
|
+
size:`int$();
|
79
|
+
exchange:`symbol$();
|
80
|
+
c:()
|
81
|
+
);
|
82
|
+
""")
|
83
|
+
q_conn.get("portfolio:`IBM`GOOG`VOD`BA`AIB`MSFT`BOI / define variable portfolio")
|
84
|
+
q_conn.get("countries:(portfolio!`USA`USA`UK`USA`IRL`USA`IRL) / some countries")
|
85
|
+
q_conn.get("dts: .z.D-til 200 / A few dates")
|
86
|
+
q_conn.get("st: 09:30:00.000 / market open")
|
87
|
+
q_conn.get("et: 16:00:00.000 / market close")
|
88
|
+
q_conn.get("exchanges:`N`L`O`C / Some exchanges")
|
89
|
+
q_conn.get("n:1000000 / The number of trades to create")
|
90
|
+
response = q_conn.get("\\t insert[`trade;(n?dts;st+n?et-st;n?portfolio;n?100f;n?1000;n?exchanges;n?.Q.A,'reverse .Q.a)] / create 1m random trades")
|
91
|
+
|
92
|
+
puts "Created a million trades in #{response}ms"
|
93
|
+
|
94
|
+
response = q_conn.get("count trade")
|
95
|
+
response.should.== 1000000
|
96
|
+
q_conn.close
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should allow us to select from the trades table" do
|
100
|
+
q_conn = QConnection.new HOST, PORT
|
101
|
+
response = q_conn.get("select max price by sym from trade")
|
102
|
+
response.keys[0].length.should.== 1
|
103
|
+
|
104
|
+
puts response.inspect
|
105
|
+
|
106
|
+
response[response.keys[0]]["price"].length.should.== 7
|
107
|
+
response.keys[0]["sym"].length.should.== 7
|
108
|
+
response.keys[0]["sym"].include?("GOOG").should.== true
|
109
|
+
response.keys[0]["sym"].include?("BA").should.== true
|
110
|
+
response.keys[0]["sym"].include?("BOI").should.== true
|
111
|
+
response.keys[0]["sym"].include?("IBM").should.== true
|
112
|
+
response.keys[0]["sym"].include?("MSFT").should.== true
|
113
|
+
response.keys[0]["sym"].include?("VOD").should.== true
|
114
|
+
response.keys[0]["sym"].include?("CHEESE").should.== false
|
115
|
+
|
116
|
+
q_conn.close
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should support getting functions" do
|
120
|
+
q_conn = QConnection.new HOST, PORT
|
121
|
+
response = q_conn.get("show_me:{[something] show something;show_me};")
|
122
|
+
puts response
|
123
|
+
q_conn.get("show_me(`hello)")
|
124
|
+
|
125
|
+
q_conn.close
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
it "should return exceptions" do
|
130
|
+
q_conn = QConnection.new HOST, PORT
|
131
|
+
begin
|
132
|
+
q_conn.get("somethingmissing")
|
133
|
+
rescue QRubyDriver::QException => e
|
134
|
+
puts e.message
|
135
|
+
end
|
136
|
+
q_conn.close
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should be able to handle multi-type dictionaries" do
|
140
|
+
q_conn = QConnection.new HOST, PORT
|
141
|
+
response = q_conn.get("(`b,1)!(`a,3)")
|
142
|
+
q_conn.close
|
143
|
+
response.should.is_a? Hash
|
144
|
+
response.length.should.== 2
|
145
|
+
|
146
|
+
response["b"].should.== "a"
|
147
|
+
response[1].should.== 3
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should be able to handle lists" do
|
152
|
+
q_conn = QConnection.new HOST, PORT
|
153
|
+
response = q_conn.get("enlist til 5")
|
154
|
+
q_conn.close
|
155
|
+
response.should.is_a? Array
|
156
|
+
response.length.should.== 1
|
157
|
+
response[0].should.is_a? Array
|
158
|
+
|
159
|
+
response[0][0].should.== 0
|
160
|
+
response[0][1].should.== 1
|
161
|
+
response[0][2].should.== 2
|
162
|
+
response[0][3].should.== 3
|
163
|
+
response[0][4].should.== 4
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should support character arrays" do
|
168
|
+
q_conn = QConnection.new HOST, PORT
|
169
|
+
response = q_conn.get("\"hello\"")
|
170
|
+
q_conn.close
|
171
|
+
|
172
|
+
response.should.is_a? Array
|
173
|
+
response.length.should.== 5
|
174
|
+
response.should.== "hello"
|
175
|
+
end
|
176
|
+
|
177
|
+
# it "should be able to support arrays as parameters" do
|
178
|
+
# q_conn = QConnection.new HOST, PORT
|
179
|
+
# values = ["a",1,2,3,4,5]
|
180
|
+
# response = q_conn.get(values)
|
181
|
+
# response.length.should.==values
|
182
|
+
# q_conn.close
|
183
|
+
# end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
require File.expand_path(
|
3
|
+
File.join(File.dirname(__FILE__), %w[.. lib q-ruby-driver-ruby-driver]))
|
4
|
+
|
5
|
+
include QRubyDriver
|
6
|
+
|
7
|
+
Spec::Runner.configure do |config|
|
8
|
+
# == Mock Framework
|
9
|
+
#
|
10
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
11
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
12
|
+
#
|
13
|
+
# config.mock_with :mocha
|
14
|
+
# config.mock_with :flexmock
|
15
|
+
# config.mock_with :rr
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require './test_helper'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
# Tests the socket connection using a dummy server
|
6
|
+
# which gives a spoof response
|
7
|
+
|
8
|
+
class TestConnection < Test::Unit::TestCase
|
9
|
+
|
10
|
+
HOST = "127.0.0.1"
|
11
|
+
@@port = 12300
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@@serv = TCPServer.new(HOST, @@port)
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
@@conn.close
|
19
|
+
@@port += 1
|
20
|
+
end
|
21
|
+
|
22
|
+
# helper methods
|
23
|
+
def string_to_int_array(str)
|
24
|
+
str.each_byte.map{|x| x}
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_async
|
28
|
+
request = "Hello world!"
|
29
|
+
Thread.new() {
|
30
|
+
# listen for initial connection
|
31
|
+
s = @@serv.accept
|
32
|
+
s.recv(100)
|
33
|
+
s.write ['0','1','0','2'].pack('H4')
|
34
|
+
sleep(1) # wait a bit
|
35
|
+
expected = [1, 0, 0, 0, request.length+14, 0, 0, 0, 10, 0, request.length, 0, 0, 0] + string_to_int_array(request)
|
36
|
+
assert_equal(expected,string_to_int_array(s.recv(100)))
|
37
|
+
}
|
38
|
+
@@conn=QRubyDriver::QConnection.new(HOST, @@port)
|
39
|
+
@@conn.set(request)
|
40
|
+
sleep(5)
|
41
|
+
assert(true)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_sync
|
45
|
+
request = "Hello world!"
|
46
|
+
obj = ["foo",[91,34],["bar",[true,false,true]]]
|
47
|
+
Thread.new() {
|
48
|
+
# listen for initial connection
|
49
|
+
s = @@serv.accept
|
50
|
+
s.recv(100)
|
51
|
+
s.write ['0','1','0','2'].pack('H4')
|
52
|
+
sleep(1) # wait a bit
|
53
|
+
expected = [1, 1, 0, 0, request.length+14, 0, 0, 0, 10, 0, request.length, 0, 0, 0] + string_to_int_array(request)
|
54
|
+
assert_equal(expected,string_to_int_array(s.recv(100)))
|
55
|
+
qio=QRubyDriver::QIO.new()
|
56
|
+
qio.write_message(obj, :response)
|
57
|
+
qio.pos=0
|
58
|
+
s.write qio.read
|
59
|
+
}
|
60
|
+
@@conn=QRubyDriver::QConnection.new(HOST, @@port)
|
61
|
+
assert_equal(obj, @@conn.get(request))
|
62
|
+
end
|
63
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
begin
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
rescue Bundler::BundlerError => e
|
7
|
+
$stderr.puts e.message
|
8
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
9
|
+
exit e.status_code
|
10
|
+
end
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
13
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
14
|
+
|
15
|
+
require 'q-ruby-driver'
|
data/test/test_io.rb
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
require './test_helper'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
# These tests do round-trip integration testing
|
5
|
+
# (i.e. write then read) on the QIO class
|
6
|
+
class TestIO < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@qio=QRubyDriver::QIO.new()
|
10
|
+
end
|
11
|
+
|
12
|
+
# helper methods
|
13
|
+
def string_to_int_array(str)
|
14
|
+
str.each_byte.map{|x| x}
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_string
|
18
|
+
str="This is a %1$5#!@-ing string"
|
19
|
+
|
20
|
+
expected=[1, 0, 0, 0, str.length+14, 0, 0, 0, 10, 0, 28, 0, 0, 0]+string_to_int_array(str)
|
21
|
+
|
22
|
+
@qio.write_message(str)
|
23
|
+
@qio.pos=0
|
24
|
+
assert_equal(expected, string_to_int_array(@qio.read()))
|
25
|
+
@qio.pos=0
|
26
|
+
assert_equal(str, @qio.read_message())
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_int
|
30
|
+
int=1
|
31
|
+
|
32
|
+
expected=[1, 0, 0, 0, 13, 0, 0, 0, 250, 1, 0, 0, 0]
|
33
|
+
|
34
|
+
@qio.write_message(int)
|
35
|
+
@qio.pos=0
|
36
|
+
assert_equal(expected, string_to_int_array(@qio.read()))
|
37
|
+
@qio.pos=0
|
38
|
+
assert_equal(int, @qio.read_message())
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_float
|
42
|
+
float=3.68423
|
43
|
+
|
44
|
+
expected=[1, 0, 0, 0, 17, 0, 0, 0, 247, 97, 137, 7, 148, 77, 121, 13, 64]
|
45
|
+
|
46
|
+
@qio.write_message(float)
|
47
|
+
@qio.pos=0
|
48
|
+
assert_equal(expected, string_to_int_array(@qio.read()))
|
49
|
+
@qio.pos=0
|
50
|
+
assert_equal(float, @qio.read_message())
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_symbol
|
54
|
+
sym="This is a %1$5#!@-ing symbol".to_sym
|
55
|
+
expected=[1, 0, 0, 0, 38, 0, 0, 0, 245]+string_to_int_array(sym.to_s)+[0]
|
56
|
+
|
57
|
+
@qio.write_message(sym)
|
58
|
+
@qio.pos=0
|
59
|
+
assert_equal(expected, string_to_int_array(@qio.read()))
|
60
|
+
@qio.pos=0
|
61
|
+
assert_equal(sym.to_s, @qio.read_message())
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_exception
|
65
|
+
exc=Exception.new("This is an exception")
|
66
|
+
expected=[1, 0, 0, 0, 30, 0, 0, 0, 128]+string_to_int_array(exc.message)+[0]
|
67
|
+
|
68
|
+
@qio.write_message(exc)
|
69
|
+
@qio.pos=0
|
70
|
+
assert_equal(expected, string_to_int_array(@qio.read()))
|
71
|
+
@qio.pos=0
|
72
|
+
|
73
|
+
# should throw the exception when reading
|
74
|
+
begin
|
75
|
+
@qio.read_message()
|
76
|
+
rescue QRubyDriver::QException => qe
|
77
|
+
assert_equal(exc.message, qe.message)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_int_vector
|
82
|
+
vector=[1,3]
|
83
|
+
|
84
|
+
expected=[1, 0, 0, 0, 22, 0, 0, 0, 6, 0, 2, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0]
|
85
|
+
|
86
|
+
@qio.write_message(vector)
|
87
|
+
@qio.pos=0
|
88
|
+
assert_equal(expected, string_to_int_array(@qio.read()))
|
89
|
+
@qio.pos=0
|
90
|
+
assert_equal(vector, @qio.read_message())
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_bool_vector
|
94
|
+
vector=[true,false,true]
|
95
|
+
|
96
|
+
msg_header=[1, 0, 0, 0, 17, 0, 0, 0]
|
97
|
+
bool_vector = [1, 0, 3, 0, 0, 0, 1, 0, 1]
|
98
|
+
expected=msg_header+bool_vector
|
99
|
+
|
100
|
+
@qio.write_message(vector)
|
101
|
+
@qio.pos=0
|
102
|
+
assert_equal(expected, string_to_int_array(@qio.read()))
|
103
|
+
@qio.pos=0
|
104
|
+
assert_equal(vector, @qio.read_message())
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_symbol_vector
|
108
|
+
vector=[:symbol1, :symbol2, :symbol3]
|
109
|
+
|
110
|
+
msg_header = [1, 0, 0, 0, 38, 0, 0, 0]
|
111
|
+
sym_vector = [11, 0, 3, 0, 0, 0]+vector.map{|x| string_to_int_array(x.to_s)+[0]}.flatten
|
112
|
+
expected=msg_header+sym_vector
|
113
|
+
|
114
|
+
@qio.write_message(vector)
|
115
|
+
@qio.pos=0
|
116
|
+
assert_equal(expected, string_to_int_array(@qio.read()))
|
117
|
+
@qio.pos=0
|
118
|
+
assert_equal(vector.map{|x|x.to_s}, @qio.read_message())
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_list
|
122
|
+
list=["foo",[91,34],["bar",[true,false,true]]]
|
123
|
+
|
124
|
+
msg_header = [1, 0, 0, 0, 61, 0, 0, 0]
|
125
|
+
list1_header = [0, 0, 3, 0, 0, 0]
|
126
|
+
string_foo = [10, 0, 3, 0, 0, 0] + string_to_int_array("foo")
|
127
|
+
int_vector = [6, 0, 2, 0, 0, 0, 91, 0, 0, 0, 34, 0, 0, 0]
|
128
|
+
list2_header = [0, 0, 2, 0, 0, 0]
|
129
|
+
string_bar = [10, 0, 3, 0, 0, 0] + string_to_int_array("bar")
|
130
|
+
bool_vector = [1, 0, 3, 0, 0, 0, 1, 0, 1]
|
131
|
+
expected=msg_header+list1_header+string_foo+int_vector+list2_header+string_bar+bool_vector
|
132
|
+
|
133
|
+
@qio.write_message(list)
|
134
|
+
@qio.pos=0
|
135
|
+
assert_equal(expected, string_to_int_array(@qio.read()))
|
136
|
+
@qio.pos=0
|
137
|
+
assert_equal(list, @qio.read_message())
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_flip
|
141
|
+
hash={:foo => [91,34, 20], :bar => [true,false,true], :woof => ["beatles","stones","zeppelin"], :meow => [:how, :now, :cow]}
|
142
|
+
|
143
|
+
msg_header = [1, 0, 0, 0, 131, 0, 0, 0]
|
144
|
+
flip_dict_header = [98, 0, 99]
|
145
|
+
sym_vector_1 = [11, 0, 4, 0, 0, 0] + hash.keys.map{|x|string_to_int_array(x.to_s)+[0]}.flatten
|
146
|
+
list_header = [0, 0, 4, 0, 0, 0]
|
147
|
+
int_vector = [6, 0, 3, 0, 0, 0, 91, 0, 0, 0, 34, 0, 0, 0, 20, 0, 0, 0]
|
148
|
+
bool_vector = [1, 0, 3, 0, 0, 0, 1, 0, 1]
|
149
|
+
# I'm not actually sure if "char_vector_list" is the correct IPC format
|
150
|
+
# but it is my expectation for now until I learn otherwise
|
151
|
+
char_vector_list = [0, 0, 3, 0, 0, 0] + hash[:woof].map{|x| [10, 0, x.length, 0, 0, 0] + string_to_int_array(x.to_s)}.flatten
|
152
|
+
sym_vector_2 = [11, 0, 3, 0, 0, 0] + hash[:meow].map{|x|string_to_int_array(x.to_s)+[0]}.flatten
|
153
|
+
|
154
|
+
expected = msg_header + flip_dict_header + sym_vector_1 + list_header + int_vector + bool_vector + char_vector_list + sym_vector_2
|
155
|
+
|
156
|
+
@qio.write_message(hash)
|
157
|
+
@qio.pos=0
|
158
|
+
assert_equal(expected, string_to_int_array(@qio.read()))
|
159
|
+
@qio.pos=0
|
160
|
+
|
161
|
+
expected_hash={}
|
162
|
+
hash.keys.each {|k| expected_hash[k.to_s]=hash[k]}
|
163
|
+
expected_hash['meow'] = expected_hash['meow'].map{|x|x.to_s}
|
164
|
+
|
165
|
+
assert_equal(expected_hash, @qio.read_message())
|
166
|
+
end
|
167
|
+
end
|