fix_spec 0.2.1 → 0.4.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.
- checksums.yaml +7 -0
- data/.travis.yml +1 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -2
- data/README.md +28 -1
- data/VERSION +1 -1
- data/features/builder.feature +164 -5
- data/features/equivalence_data_dictionary.feature +49 -1
- data/features/message_type.feature +11 -0
- data/features/nested_builder.feature +229 -2
- data/features/support/FIX50SP1.xml +9419 -0
- data/features/support/FIXT11.xml +383 -0
- data/features/support/env.rb +8 -0
- data/fix_spec.gemspec +10 -7
- data/lib/fix_spec/builder.rb +89 -27
- data/lib/fix_spec/configuration.rb +19 -2
- data/lib/fix_spec/cucumber.rb +1 -2
- data/spec/fix_spec/data_dictionary_spec.rb +12 -6
- metadata +32 -49
data/lib/fix_spec/builder.rb
CHANGED
@@ -9,21 +9,35 @@ module Builder
|
|
9
9
|
def self.message= msg
|
10
10
|
@message=msg
|
11
11
|
end
|
12
|
+
|
13
|
+
# Converts a FIX message string into a +quickfix.Message+.
|
14
|
+
#
|
15
|
+
# Params:
|
16
|
+
# +msg_string+:: the FIX message string
|
17
|
+
# +do_validation+:: if true, validation is performed using the DataDictionary
|
18
|
+
#
|
19
|
+
# Returns:
|
20
|
+
# +quickfix.Message+
|
21
|
+
#
|
22
|
+
# See also:
|
23
|
+
# +quickfix.MessageUtils#parse(Session, String)+
|
24
|
+
def self.parse_message msg_string, do_validation
|
25
|
+
begin_string = quickfix.MessageUtils.getStringField(msg_string, quickfix.field.BeginString::FIELD)
|
26
|
+
msg_type = quickfix.MessageUtils.getMessageType(msg_string)
|
27
|
+
payload_dict = quickfix.MessageUtils.isAdminMessage(msg_type) ? FIXSpec::session_data_dictionary : FIXSpec::application_data_dictionary
|
28
|
+
msg = quickfix.DefaultMessageFactory.new.create(begin_string, msg_type)
|
29
|
+
msg.parse(msg_string, FIXSpec::session_data_dictionary, payload_dict, do_validation)
|
30
|
+
msg
|
31
|
+
end
|
12
32
|
end
|
13
33
|
end
|
14
34
|
|
15
35
|
Given /^the following( unvalidated)? fix message:$/ do |unvalidated,fix_str|
|
16
|
-
|
17
|
-
unless unvalidated
|
18
|
-
FIXSpec::Builder.message = quickfix.MessageUtils.parse(factory, FIXSpec::data_dictionary, FIXSpec::Helpers.fixify_string(fix_str) )
|
19
|
-
else
|
20
|
-
FIXSpec::Builder.message = quickfix.MessageUtils.parse(factory, nil, FIXSpec::Helpers.fixify_string(fix_str) )
|
21
|
-
end
|
22
|
-
|
36
|
+
FIXSpec::Builder.message = FIXSpec::Builder.parse_message(FIXSpec::Helpers.fixify_string(fix_str), !unvalidated)
|
23
37
|
FIXSpec::Builder.message.should_not be_nil
|
24
38
|
end
|
25
39
|
|
26
|
-
Given /^I create a (?:fix|FIX|(
|
40
|
+
Given /^I create a (?:fix|FIX|(FIXT?\.\d+\.\d+)) message(?: of type "(.*)")?$/ do |begin_string, msg_type|
|
27
41
|
FIXSpec::Builder.message = quickfix.Message.new
|
28
42
|
|
29
43
|
unless begin_string.nil?
|
@@ -35,7 +49,7 @@ Given /^I create a (?:fix|FIX|(.*)) message(?: of type "(.*)")?$/ do |begin_stri
|
|
35
49
|
end
|
36
50
|
end
|
37
51
|
|
38
|
-
Given /^I create the following (?:fix|FIX|(
|
52
|
+
Given /^I create the following (?:fix|FIX|(FIXT?\.\d+\.\d+)) message(?: of type "(.*)")?:$/ do |begin_string, msg_type, table|
|
39
53
|
FIXSpec::Builder.message = quickfix.Message.new
|
40
54
|
|
41
55
|
unless begin_string.nil?
|
@@ -51,10 +65,64 @@ Given /^I create the following (?:fix|FIX|(.*)) message(?: of type "(.*)")?:$/ d
|
|
51
65
|
end
|
52
66
|
end
|
53
67
|
|
54
|
-
|
55
|
-
|
56
68
|
Given /^I set the (?:FIX|fix) message at(?: tag)? "(.*?)" to (".*"|\-?\d+(?:\.\d+)?(?:[eE][\+\-]?\d+)?|\[.*\]|%?\{.*\}|true|false|null)$/ do |fieldName, fieldValue|
|
57
69
|
FIXSpec::Builder.message.should_not be_nil
|
70
|
+
set_fields(FIXSpec::Builder.message, fieldName.split('/'), fieldValue)
|
71
|
+
end
|
72
|
+
|
73
|
+
Given(/^I add the following "(.*?)" group:$/) do |grpType, table|
|
74
|
+
FIXSpec::Builder.message.should_not be_nil
|
75
|
+
|
76
|
+
list_field_order = []
|
77
|
+
table.raw.each do |fieldName, fieldValue|
|
78
|
+
list_field_order.push(FIXSpec::data_dictionary.getFieldTag(fieldName))
|
79
|
+
end
|
80
|
+
|
81
|
+
group = quickfix.Group.new(FIXSpec::data_dictionary.getFieldTag(grpType), list_field_order.first, (list_field_order.to_java :int))
|
82
|
+
|
83
|
+
table.raw.each do |fieldName, fieldValue|
|
84
|
+
add_field(group, fieldName, fieldValue)
|
85
|
+
end
|
86
|
+
|
87
|
+
FIXSpec::Builder.message.addGroup(group)
|
88
|
+
end
|
89
|
+
|
90
|
+
def set_fields msgPart, fieldName, fieldValue
|
91
|
+
if fieldName.is_a? String
|
92
|
+
add_field msgPart, fieldName, fieldValue
|
93
|
+
elsif fieldName.is_a? Array
|
94
|
+
if fieldName.length > 1
|
95
|
+
add_array_field msgPart, fieldName, fieldValue
|
96
|
+
else
|
97
|
+
add_field msgPart, fieldName.first, fieldValue
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def add_array_field msgPart, fieldArray, fieldValue
|
103
|
+
if !FIXSpec::data_dictionary.nil?
|
104
|
+
fieldName = fieldArray.shift
|
105
|
+
tag = FIXSpec::data_dictionary.getFieldTag(fieldName)
|
106
|
+
fail "#{fieldName} is not a valid field" if tag == -1
|
107
|
+
|
108
|
+
arrayPosStr = fieldArray.shift
|
109
|
+
arrayPos = arrayPosStr.to_i
|
110
|
+
fail "#{arrayPos} is not a valid array index" unless arrayPos.to_s == arrayPosStr
|
111
|
+
fail "You need to specify a field for group #{fieldName}" if fieldArray.empty?
|
112
|
+
|
113
|
+
if msgPart.hasGroup(arrayPos+1, tag)
|
114
|
+
set_fields msgPart.getGroup(arrayPos+1, tag), fieldArray, fieldValue
|
115
|
+
else
|
116
|
+
group = quickfix.Group.new tag, -1
|
117
|
+
set_fields group, fieldArray, fieldValue
|
118
|
+
msgPart.addGroup group
|
119
|
+
end
|
120
|
+
else
|
121
|
+
fail "no data dictionary set"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def add_field msgPart, fieldName, fieldValue
|
58
126
|
|
59
127
|
#kill quotes
|
60
128
|
if fieldValue.match(/\"(.*)\"/)
|
@@ -64,34 +132,28 @@ Given /^I set the (?:FIX|fix) message at(?: tag)? "(.*?)" to (".*"|\-?\d+(?:\.\d
|
|
64
132
|
tag = -1
|
65
133
|
if !FIXSpec::data_dictionary.nil?
|
66
134
|
tag = FIXSpec::data_dictionary.getFieldTag(fieldName)
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
msg = msg.get_header
|
72
|
-
elsif FIXSpec::data_dictionary.is_trailer_field(tag)
|
73
|
-
msg = msg.get_trailer
|
135
|
+
if FIXSpec::session_data_dictionary.is_header_field(tag)
|
136
|
+
msgPart = msgPart.get_header
|
137
|
+
elsif FIXSpec::session_data_dictionary.is_trailer_field(tag)
|
138
|
+
msgPart = msgPart.get_trailer
|
74
139
|
end
|
75
140
|
|
76
141
|
case FIXSpec::data_dictionary.get_field_type_enum(tag).get_name
|
77
142
|
when "INT","DAYOFMONTH" then
|
78
|
-
|
143
|
+
msgPart.setInt(tag, fieldValue.to_i)
|
79
144
|
when "PRICE","FLOAT","QTY" then
|
80
|
-
|
145
|
+
msgPart.setDouble(tag, fieldValue.to_f)
|
81
146
|
when "BOOLEAN" then
|
82
|
-
|
147
|
+
msgPart.setBoolean(tag, fieldValue == "true")
|
83
148
|
else
|
84
149
|
#enum description => enum value
|
85
150
|
#e.g. tag 54 "BUY"=>"1"
|
86
151
|
fieldValue = FIXSpec::data_dictionary.get_reverse_value_name(tag, fieldValue)
|
87
|
-
|
152
|
+
msgPart.setString(tag, fieldValue)
|
88
153
|
end
|
89
|
-
|
90
154
|
else
|
91
155
|
tag = fieldName.to_i
|
92
|
-
|
156
|
+
msgPart.setString(tag, fieldValue)
|
93
157
|
end
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
158
|
|
159
|
+
end
|
@@ -2,11 +2,28 @@ module FIXSpec
|
|
2
2
|
module Configuration
|
3
3
|
|
4
4
|
def data_dictionary=(dd)
|
5
|
-
|
5
|
+
self.application_data_dictionary=dd
|
6
|
+
self.session_data_dictionary=dd
|
6
7
|
end
|
7
8
|
|
8
9
|
def data_dictionary
|
9
|
-
|
10
|
+
self.application_data_dictionary
|
11
|
+
end
|
12
|
+
|
13
|
+
def application_data_dictionary=(dd)
|
14
|
+
@application_data_dictionary=dd
|
15
|
+
end
|
16
|
+
|
17
|
+
def application_data_dictionary
|
18
|
+
@application_data_dictionary
|
19
|
+
end
|
20
|
+
|
21
|
+
def session_data_dictionary=(dd)
|
22
|
+
@session_data_dictionary=dd
|
23
|
+
end
|
24
|
+
|
25
|
+
def session_data_dictionary
|
26
|
+
@session_data_dictionary
|
10
27
|
end
|
11
28
|
|
12
29
|
def reset
|
data/lib/fix_spec/cucumber.rb
CHANGED
@@ -30,8 +30,7 @@ Then /^the (?:fix|FIX)(?: message)?(?: at(?: tag)? "(.*?)")? should( not)? be:$/
|
|
30
30
|
# raw fix
|
31
31
|
if tag.nil? and not exp_value.match(/{*}/)
|
32
32
|
require 'fix_spec/builder'
|
33
|
-
|
34
|
-
exp_message = FIXSpec::Builder.message = quickfix.MessageUtils.parse(factory, nil, FIXSpec::Helpers.fixify_string(exp_value) )
|
33
|
+
exp_message = FIXSpec::Builder.parse_message(FIXSpec::Helpers.fixify_string(exp_value), false)
|
35
34
|
exp_value = FIXSpec::Helpers.message_to_unordered_json(exp_message)
|
36
35
|
end
|
37
36
|
|
@@ -1,27 +1,33 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe FIXSpec::DataDictionary do
|
4
|
-
let(:
|
4
|
+
let(:app_dict) {FIXSpec::DataDictionary.new "features/support/FIX50SP1.xml" }
|
5
|
+
let(:session_dict) {FIXSpec::DataDictionary.new "features/support/FIXT11.xml" }
|
5
6
|
|
6
7
|
it "is a quickfix.DataDictionary" do
|
7
|
-
|
8
|
+
app_dict.is_a?(quickfix.DataDictionary).should be_true
|
9
|
+
session_dict.is_a?(quickfix.DataDictionary).should be_true
|
8
10
|
end
|
9
11
|
|
10
12
|
describe "get_reverse_value_name" do
|
11
13
|
it "gives me back the same if not an enum or if we are giving an enum" do
|
12
|
-
|
14
|
+
app_dict.get_reverse_value_name(1, 'Ralph').should ==('Ralph')
|
15
|
+
session_dict.get_reverse_value_name(49, 'Hagbard').should ==('Hagbard')
|
13
16
|
end
|
14
17
|
|
15
18
|
it "gives me back the same if is an enum and no description matches" do
|
16
|
-
|
19
|
+
app_dict.get_reverse_value_name(39, 'D').should ==('D')
|
20
|
+
session_dict.get_reverse_value_name(141, 'X').should ==('X')
|
17
21
|
end
|
18
22
|
|
19
23
|
it "knows enum lookup" do
|
20
|
-
|
24
|
+
app_dict.get_reverse_value_name(54, 'BUY').should ==('1')
|
25
|
+
app_dict.get_reverse_value_name(35, 'NEWORDERSINGLE').should ==('D')
|
26
|
+
session_dict.get_reverse_value_name(35, 'ORDER_SINGLE').should ==('D')
|
21
27
|
end
|
22
28
|
|
23
29
|
it "knows how to map msg type" do
|
24
|
-
|
30
|
+
app_dict.get_reverse_value_name(35, 'NewOrderSingle').should ==('D')
|
25
31
|
end
|
26
32
|
end
|
27
33
|
end
|
metadata
CHANGED
@@ -1,128 +1,113 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fix_spec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.2.1
|
4
|
+
version: 0.4.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Chris Busbey
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2015-04-15 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
|
-
name: json_spec
|
16
|
-
version_requirements: !ruby/object:Gem::Requirement
|
17
|
-
requirements:
|
18
|
-
- - ~>
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: 1.1.1
|
21
|
-
none: false
|
22
14
|
requirement: !ruby/object:Gem::Requirement
|
23
15
|
requirements:
|
24
16
|
- - ~>
|
25
17
|
- !ruby/object:Gem::Version
|
26
18
|
version: 1.1.1
|
27
|
-
|
19
|
+
name: json_spec
|
28
20
|
prerelease: false
|
29
21
|
type: :runtime
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: quickfix-jruby
|
32
22
|
version_requirements: !ruby/object:Gem::Requirement
|
33
23
|
requirements:
|
34
24
|
- - ~>
|
35
25
|
- !ruby/object:Gem::Version
|
36
|
-
version: 1.
|
37
|
-
|
26
|
+
version: 1.1.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
38
28
|
requirement: !ruby/object:Gem::Requirement
|
39
29
|
requirements:
|
40
30
|
- - ~>
|
41
31
|
- !ruby/object:Gem::Version
|
42
|
-
version: 1.
|
43
|
-
|
32
|
+
version: 1.6.0
|
33
|
+
name: quickfix-jruby
|
44
34
|
prerelease: false
|
45
35
|
type: :runtime
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: cuke_mem
|
48
36
|
version_requirements: !ruby/object:Gem::Requirement
|
49
37
|
requirements:
|
50
38
|
- - ~>
|
51
39
|
- !ruby/object:Gem::Version
|
52
|
-
version:
|
53
|
-
|
40
|
+
version: 1.6.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
54
42
|
requirement: !ruby/object:Gem::Requirement
|
55
43
|
requirements:
|
56
44
|
- - ~>
|
57
45
|
- !ruby/object:Gem::Version
|
58
46
|
version: 0.1.1
|
59
|
-
|
47
|
+
name: cuke_mem
|
60
48
|
prerelease: false
|
61
49
|
type: :runtime
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: rspec
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
65
51
|
requirements:
|
66
52
|
- - ~>
|
67
53
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
69
|
-
|
54
|
+
version: 0.1.1
|
55
|
+
- !ruby/object:Gem::Dependency
|
70
56
|
requirement: !ruby/object:Gem::Requirement
|
71
57
|
requirements:
|
72
58
|
- - ~>
|
73
59
|
- !ruby/object:Gem::Version
|
74
60
|
version: '2.14'
|
75
|
-
|
61
|
+
name: rspec
|
76
62
|
prerelease: false
|
77
63
|
type: :development
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: jeweler
|
80
64
|
version_requirements: !ruby/object:Gem::Requirement
|
81
65
|
requirements:
|
82
66
|
- - ~>
|
83
67
|
- !ruby/object:Gem::Version
|
84
|
-
version: '
|
85
|
-
|
68
|
+
version: '2.14'
|
69
|
+
- !ruby/object:Gem::Dependency
|
86
70
|
requirement: !ruby/object:Gem::Requirement
|
87
71
|
requirements:
|
88
72
|
- - ~>
|
89
73
|
- !ruby/object:Gem::Version
|
90
74
|
version: '1.8'
|
91
|
-
|
75
|
+
name: jeweler
|
92
76
|
prerelease: false
|
93
77
|
type: :development
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
name: cucumber
|
96
78
|
version_requirements: !ruby/object:Gem::Requirement
|
97
79
|
requirements:
|
98
80
|
- - ~>
|
99
81
|
- !ruby/object:Gem::Version
|
100
|
-
version: '1.
|
101
|
-
|
82
|
+
version: '1.8'
|
83
|
+
- !ruby/object:Gem::Dependency
|
102
84
|
requirement: !ruby/object:Gem::Requirement
|
103
85
|
requirements:
|
104
86
|
- - ~>
|
105
87
|
- !ruby/object:Gem::Version
|
106
88
|
version: '1.3'
|
107
|
-
|
89
|
+
name: cucumber
|
108
90
|
prerelease: false
|
109
91
|
type: :development
|
110
|
-
- !ruby/object:Gem::Dependency
|
111
|
-
name: rake
|
112
92
|
version_requirements: !ruby/object:Gem::Requirement
|
113
93
|
requirements:
|
114
94
|
- - ~>
|
115
95
|
- !ruby/object:Gem::Version
|
116
|
-
version: '
|
117
|
-
|
96
|
+
version: '1.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
118
98
|
requirement: !ruby/object:Gem::Requirement
|
119
99
|
requirements:
|
120
100
|
- - ~>
|
121
101
|
- !ruby/object:Gem::Version
|
122
102
|
version: '10.1'
|
123
|
-
|
103
|
+
name: rake
|
124
104
|
prerelease: false
|
125
105
|
type: :development
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '10.1'
|
126
111
|
description: Build and Inspect FIX Messages with RSpec and Cucumber steps
|
127
112
|
email: info@connamara.com
|
128
113
|
executables: []
|
@@ -151,6 +136,8 @@ files:
|
|
151
136
|
- features/paths.feature
|
152
137
|
- features/step_definitions/steps.rb
|
153
138
|
- features/support/FIX42.xml
|
139
|
+
- features/support/FIX50SP1.xml
|
140
|
+
- features/support/FIXT11.xml
|
154
141
|
- features/support/env.rb
|
155
142
|
- fix_spec.gemspec
|
156
143
|
- lib/fix_spec.rb
|
@@ -168,6 +155,7 @@ files:
|
|
168
155
|
homepage: http://github.com/connamara/fix_spec
|
169
156
|
licenses:
|
170
157
|
- GPL
|
158
|
+
metadata: {}
|
171
159
|
post_install_message:
|
172
160
|
rdoc_options: []
|
173
161
|
require_paths:
|
@@ -176,21 +164,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
176
164
|
requirements:
|
177
165
|
- - '>='
|
178
166
|
- !ruby/object:Gem::Version
|
179
|
-
segments:
|
180
|
-
- 0
|
181
|
-
hash: 2
|
182
167
|
version: '0'
|
183
|
-
none: false
|
184
168
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
169
|
requirements:
|
186
170
|
- - '>='
|
187
171
|
- !ruby/object:Gem::Version
|
188
172
|
version: '0'
|
189
|
-
none: false
|
190
173
|
requirements: []
|
191
174
|
rubyforge_project:
|
192
|
-
rubygems_version: 1.
|
175
|
+
rubygems_version: 2.1.9
|
193
176
|
signing_key:
|
194
|
-
specification_version:
|
177
|
+
specification_version: 4
|
195
178
|
summary: Build and Inspect FIX Messages
|
196
179
|
test_files: []
|