q-ruby-driver 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|