fix_spec 0.4.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9cfe02ee9bf33cc01066722933e18613110b0fb8
4
- data.tar.gz: eac8cb38a033e2c1cb94af52a4814f012549668b
3
+ metadata.gz: 84a6f29a2c4e0ebfd724af927d024aca207d820e
4
+ data.tar.gz: 2414ba4d24d0befb04dc363a4aa841bc493d95bb
5
5
  SHA512:
6
- metadata.gz: a22cf1c80179917aca80a29679305e94f317875c17c10431a1c6168d7e9ef32585bceeb061185ed7367946db95b0c0fe07104c97449a73ff9b5b26846bbd056a
7
- data.tar.gz: 1d5c343f4fe83ab49698b58c37d6510b64520e415008113dc399edfa8e8afb94fd5ef47105bbd47aba4f356b47d3f2f3266268d160dff184b585ffe9d2a497cd
6
+ metadata.gz: d3df2b03a89547f31ecaebf6dec9523863019a5197e135ff47b3701c3f3427f8ba8df864a498c13c05f0bb9ec7562b70804c51d7e1329ce239b7939dd116b48b
7
+ data.tar.gz: 05dcb29d126c50f3222f0c8e16d145576f37f2a3ae0f378b2c6234f48520d53950f2d0d63a06337f6ea650d62fa9e219a25d5ce459d2440b690974fa15f4635e
@@ -0,0 +1 @@
1
+ JRUBY_OPTS="-Xcompile.invokedynamic=false -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -J-noverify -Xcompile.mode=OFF"
@@ -0,0 +1 @@
1
+ jruby-1.7.19
@@ -1,11 +1,13 @@
1
1
  language: ruby
2
2
  rvm:
3
- - jruby-18mode
4
- - jruby-19mode
5
- - jruby
6
- env:
7
- - JAVA_OPTS=-XX:MaxPermSize=2048m
3
+ - jruby-18mode
4
+ - jruby-19mode
5
+ - jruby
6
+
7
+ jdk:
8
+ - oraclejdk8
8
9
 
9
10
  matrix:
10
11
  allow_failures:
11
12
  - rvm: jruby-18mode
13
+
@@ -15,6 +15,7 @@ Contributing to fix\_spec:
15
15
  1. Fork the [official repository](https://github.com/connamara/fix_spec/tree/master).
16
16
  2. Make your changes in a topic branch.
17
17
  3. Send a pull request.
18
+ 4. If you are new contributor to this project, sign the CLA
18
19
 
19
20
  Notes:
20
21
  * If you report a bug and don't include a fix, please include a failing test.
data/Gemfile CHANGED
@@ -9,4 +9,5 @@ group :development do
9
9
  gem "jeweler", "~> 1.8"
10
10
  gem "cucumber", "~> 1.3"
11
11
  gem "rake", "~> 10.1"
12
+ gem 'pry'
12
13
  end
@@ -3,6 +3,7 @@ GEM
3
3
  specs:
4
4
  addressable (2.3.5)
5
5
  builder (3.2.2)
6
+ coderay (1.1.1)
6
7
  cucumber (1.3.8)
7
8
  builder (>= 2.1.2)
8
9
  diff-lcs (>= 1.1.3)
@@ -14,6 +15,7 @@ GEM
14
15
  diff-lcs (1.2.4)
15
16
  faraday (0.8.8)
16
17
  multipart-post (~> 1.2.0)
18
+ ffi (1.9.10-java)
17
19
  gherkin (2.12.2)
18
20
  multi_json (~> 1.3)
19
21
  gherkin (2.12.2-java)
@@ -45,6 +47,7 @@ GEM
45
47
  rspec (~> 2.0)
46
48
  jwt (0.1.8)
47
49
  multi_json (>= 1.5)
50
+ method_source (0.8.2)
48
51
  multi_json (1.8.2)
49
52
  multi_test (0.0.2)
50
53
  multi_xml (0.5.5)
@@ -58,6 +61,11 @@ GEM
58
61
  multi_json (~> 1.0)
59
62
  multi_xml (~> 0.5)
60
63
  rack (~> 1.2)
64
+ pry (0.10.3-java)
65
+ coderay (~> 1.1.0)
66
+ method_source (~> 0.8.1)
67
+ slop (~> 3.4)
68
+ spoon (~> 0.0)
61
69
  quickfix-jruby (1.6.0-java)
62
70
  rack (1.5.2)
63
71
  rake (10.1.0)
@@ -71,6 +79,9 @@ GEM
71
79
  rspec-expectations (2.14.3)
72
80
  diff-lcs (>= 1.1.3, < 2.0)
73
81
  rspec-mocks (2.14.4)
82
+ slop (3.6.0)
83
+ spoon (0.0.4)
84
+ ffi
74
85
 
75
86
  PLATFORMS
76
87
  java
@@ -81,6 +92,7 @@ DEPENDENCIES
81
92
  cuke_mem (~> 0.1.1)
82
93
  jeweler (~> 1.8)
83
94
  json_spec (~> 1.1.1)
95
+ pry
84
96
  quickfix-jruby (~> 1.6.0)
85
97
  rake (~> 10.1)
86
98
  rspec (~> 2.14)
data/README.md CHANGED
@@ -22,6 +22,7 @@ fix_spec provides Cucumber steps that utilize its RSpec matchers.
22
22
  In order to us ethe Cucumber steps, in your `env.rb` you must:
23
23
 
24
24
  ```ruby
25
+ require "fix_spec"
25
26
  require "fix_spec/cucumber"
26
27
  ```
27
28
 
@@ -83,19 +84,14 @@ The background step isn't provided by fix_spec. The remaining steps fix_spec pr
83
84
 
84
85
  #### Building FIX Messages
85
86
 
86
- In order to use the Cucumber steps for building FIX messages, in your `env.rb` you must:
87
-
88
- ```ruby
89
- require "fix_spec/builder"
90
- ```
91
- Now you can use fix_spec builder steps in your features:
87
+ You can build FIX Message messages in your features:
92
88
 
93
89
  ```cucumber
94
90
  Feature: Order Adapter accepts Orders
95
91
 
96
92
  Scenario: It accepts Market Orders
97
93
 
98
- Given I create a FIX.4.2 message of type "NewOrderSingle"
94
+ Given I create a FIX.4.2 message of type "NewOrderSingle"
99
95
  And I set the FIX message at "SenderCompID" to "MY_SENDER"
100
96
  And I set the FIX message at "TargetCompID" to "MY_TARGET"
101
97
  And I set the FIX message at "OrdType" to "MARKET"
@@ -139,7 +135,7 @@ FIXSpec works best when a DataDictionary is provided. With a DataDictionary loa
139
135
  The DataDictionary is globally set:
140
136
 
141
137
  ```ruby
142
- FIXSpec::data_dictionary = FIXSpec::DataDictionary.new "config/FIX42.xml"
138
+ FIXSpec.data_dictionary = FIXSpec::DataDictionary.new "config/FIX42.xml"
143
139
  ```
144
140
 
145
141
  #### Exclusion
@@ -192,7 +188,7 @@ Contributers:
192
188
  * Brad Haan
193
189
  * [Mike Gatny](https://github.com/mgatny)
194
190
 
195
- ![Connamara Systems](http://www.connamara.com/images/home-connamara-logo-lg.png)
191
+ ![Connamara Systems](http://www.connamara.com/wp-content/uploads/2016/01/connamara_logo_dark.png)
196
192
 
197
193
  fix_spec is maintained and funded by [Connamara Systems, llc](http://connamara.com).
198
194
 
@@ -201,7 +197,7 @@ The names and logos for Connamara Systems are trademarks of Connamara Systems, l
201
197
  Licensing
202
198
  ---------
203
199
 
204
- fix_spec is Copyright © 2013 Connamara Systems, llc.
200
+ fix_spec is Copyright © 2016 Connamara Systems, llc.
205
201
 
206
202
  This software is available under the GPL and a commercial license. Please see the [LICENSE](LICENSE.txt) file for the terms specified by the GPL license. The commercial license offers more flexible licensing terms compared to the GPL, and includes support services. [Contact us](mailto:info@connamara.com) for more information on the Connamara commercial license, what it enables, and how you can start commercial development with it.
207
203
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 1.0.1
@@ -1,24 +1,25 @@
1
1
  $: << File.expand_path("../../../lib", __FILE__)
2
2
 
3
+ require "pry"
4
+ require "fix_spec"
3
5
  require "fix_spec/cucumber"
4
- require "fix_spec/builder"
5
6
 
6
7
  def last_fix
7
8
  @last_fix
8
9
  end
9
10
 
10
11
  Around('@with_data_dictionary') do |scenario, block|
11
- FIXSpec::data_dictionary= FIXSpec::DataDictionary.new "features/support/FIX42.xml"
12
+ FIXSpec.data_dictionary = FIXSpec::DataDictionary.new "features/support/FIX42.xml"
12
13
  block.call
13
- FIXSpec::data_dictionary= nil
14
+ FIXSpec.data_dictionary = nil
14
15
  end
15
16
 
16
17
  Around('@with_data_dictionary', '@fix50') do |scenario, block|
17
- FIXSpec::application_data_dictionary = FIXSpec::DataDictionary.new "features/support/FIX50SP1.xml"
18
- FIXSpec::session_data_dictionary = FIXSpec::DataDictionary.new "features/support/FIXT11.xml"
18
+ FIXSpec.application_data_dictionary = FIXSpec::DataDictionary.new "features/support/FIX50SP1.xml"
19
+ FIXSpec.session_data_dictionary = FIXSpec::DataDictionary.new "features/support/FIXT11.xml"
19
20
  block.call
20
- FIXSpec::application_data_dictionary = nil
21
- FIXSpec::session_data_dictionary = nil
21
+ FIXSpec.application_data_dictionary = nil
22
+ FIXSpec.session_data_dictionary = nil
22
23
  end
23
24
 
24
25
  Around('@ignore_length_and_checksum') do |scenario, block|
@@ -2,15 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: fix_spec 0.4.1 ruby lib
5
+ # stub: fix_spec 1.0.1 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "fix_spec"
9
- s.version = "0.4.1"
9
+ s.version = "1.0.1"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
12
13
  s.authors = ["Chris Busbey"]
13
- s.date = "2015-04-22"
14
+ s.date = "2016-03-09"
14
15
  s.description = "Build and Inspect FIX Messages with RSpec and Cucumber steps"
15
16
  s.email = "info@connamara.com"
16
17
  s.extra_rdoc_files = [
@@ -20,6 +21,8 @@ Gem::Specification.new do |s|
20
21
  s.files = [
21
22
  ".document",
22
23
  ".rspec",
24
+ ".ruby-env",
25
+ ".ruby-version",
23
26
  ".travis.yml",
24
27
  "CONTRIBUTION_GUIDELINES.md",
25
28
  "Gemfile",
@@ -44,21 +47,21 @@ Gem::Specification.new do |s|
44
47
  "fix_spec.gemspec",
45
48
  "lib/fix_spec.rb",
46
49
  "lib/fix_spec/builder.rb",
47
- "lib/fix_spec/configuration.rb",
48
50
  "lib/fix_spec/cucumber.rb",
49
51
  "lib/fix_spec/data_dictionary.rb",
50
52
  "lib/fix_spec/helpers.rb",
51
53
  "lib/fix_spec/matchers.rb",
52
54
  "lib/fix_spec/matchers/be_fix_eql.rb",
53
55
  "lib/fix_spec/matchers/have_fix_path.rb",
56
+ "lib/fix_spec/step_definitions/fix_steps.rb",
57
+ "lib/fix_spec/support/fix_helpers.rb",
54
58
  "spec/fix_spec/data_dictionary_spec.rb",
55
59
  "spec/fix_spec/helpers_spec.rb",
56
60
  "spec/spec_helper.rb"
57
61
  ]
58
62
  s.homepage = "http://github.com/connamara/fix_spec"
59
63
  s.licenses = ["GPL"]
60
- s.require_paths = ["lib"]
61
- s.rubygems_version = "2.1.9"
64
+ s.rubygems_version = "2.4.5"
62
65
  s.summary = "Build and Inspect FIX Messages"
63
66
 
64
67
  if s.respond_to? :specification_version then
@@ -72,6 +75,7 @@ Gem::Specification.new do |s|
72
75
  s.add_development_dependency(%q<jeweler>, ["~> 1.8"])
73
76
  s.add_development_dependency(%q<cucumber>, ["~> 1.3"])
74
77
  s.add_development_dependency(%q<rake>, ["~> 10.1"])
78
+ s.add_development_dependency(%q<pry>, [">= 0"])
75
79
  else
76
80
  s.add_dependency(%q<json_spec>, ["~> 1.1.1"])
77
81
  s.add_dependency(%q<quickfix-jruby>, ["~> 1.6.0"])
@@ -80,6 +84,7 @@ Gem::Specification.new do |s|
80
84
  s.add_dependency(%q<jeweler>, ["~> 1.8"])
81
85
  s.add_dependency(%q<cucumber>, ["~> 1.3"])
82
86
  s.add_dependency(%q<rake>, ["~> 10.1"])
87
+ s.add_dependency(%q<pry>, [">= 0"])
83
88
  end
84
89
  else
85
90
  s.add_dependency(%q<json_spec>, ["~> 1.1.1"])
@@ -89,6 +94,7 @@ Gem::Specification.new do |s|
89
94
  s.add_dependency(%q<jeweler>, ["~> 1.8"])
90
95
  s.add_dependency(%q<cucumber>, ["~> 1.3"])
91
96
  s.add_dependency(%q<rake>, ["~> 10.1"])
97
+ s.add_dependency(%q<pry>, [">= 0"])
92
98
  end
93
99
  end
94
100
 
@@ -1,11 +1,38 @@
1
1
  require 'quickfix'
2
2
  require 'json_spec'
3
3
 
4
- require 'fix_spec/configuration'
5
- require 'fix_spec/helpers'
6
- require 'fix_spec/matchers'
7
- require 'fix_spec/data_dictionary'
8
-
9
4
  module FIXSpec
10
- extend Configuration
5
+ extend self
6
+
7
+ attr_reader :application_data_dictionary, :session_data_dictionary
8
+
9
+ alias_method :data_dictionary, :application_data_dictionary
10
+
11
+ def data_dictionary=(dd)
12
+ @application_data_dictionary=dd
13
+ @session_data_dictionary=dd
14
+ end
15
+
16
+ def application_data_dictionary=(dd)
17
+ @application_data_dictionary=dd
18
+ end
19
+
20
+ def session_data_dictionary=(dd)
21
+ @session_data_dictionary=dd
22
+ end
23
+
24
+ def reset
25
+ instance_variables.each{|ivar| remove_instance_variable(ivar)}
26
+ end
27
+
28
+ autoload :Builder, 'fix_spec/builder'
29
+ autoload :DataDictionary, 'fix_spec/data_dictionary'
30
+ # don't load cucumber unless you're using it
31
+ autoload :Cucumber, 'fix_spec/cucumber'
32
+ autoload :Helpers, 'fix_spec/helpers'
33
+ autoload :Matchers, 'fix_spec/matchers'
34
+ end
35
+
36
+ RSpec.configure do |config|
37
+ config.include(FIXSpec::Matchers)
11
38
  end
@@ -1,173 +1,32 @@
1
- #encoding ascii
2
-
3
1
  module FIXSpec
4
- module Builder
5
- def self.message
6
- @message
7
- end
8
-
9
- def self.message= msg
10
- @message=msg
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
32
- end
33
- end
34
-
35
- Given /^the following( unvalidated)? fix message:$/ do |unvalidated,fix_str|
36
- FIXSpec::Builder.message = FIXSpec::Builder.parse_message(FIXSpec::Helpers.fixify_string(fix_str), !unvalidated)
37
- FIXSpec::Builder.message.should_not be_nil
38
- end
39
-
40
- Given /^I create a (?:fix|FIX|(FIXT?\.\d+\.\d+)) message(?: of type "(.*)")?$/ do |begin_string, msg_type|
41
- FIXSpec::Builder.message = new_message(msg_type, begin_string)
42
- end
43
-
44
- Given /^I create the following (?:fix|FIX|(FIXT?\.\d+\.\d+)) message(?: of type "(.*)")?:$/ do |begin_string, msg_type, table|
45
- FIXSpec::Builder.message = new_message(msg_type, begin_string)
46
- table.raw.each do |tag, value|
47
- steps %{And I set the FIX message at "#{tag}" to #{value}}
48
- end
49
- end
50
-
51
- Given /^I set the (?:FIX|fix) message at(?: tag)? "(.*?)" to (".*"|\-?\d+(?:\.\d+)?(?:[eE][\+\-]?\d+)?|\[.*\]|%?\{.*\}|true|false|null)$/ do |fieldName, fieldValue|
52
- FIXSpec::Builder.message.should_not be_nil
53
- set_fields(FIXSpec::Builder.message, fieldName.split('/'), fieldValue)
54
- end
55
-
56
- Given(/^I add the following "(.*?)" group:$/) do |grpType, table|
57
- FIXSpec::Builder.message.should_not be_nil
58
-
59
- list_field_order = []
60
- table.raw.each do |fieldName, fieldValue|
61
- list_field_order.push(FIXSpec::data_dictionary.getFieldTag(fieldName))
62
- end
63
-
64
- group = quickfix.Group.new(FIXSpec::data_dictionary.getFieldTag(grpType), list_field_order.first, (list_field_order.to_java :int))
65
-
66
- table.raw.each do |fieldName, fieldValue|
67
- add_field(group, fieldName, fieldValue)
68
- end
69
-
70
- FIXSpec::Builder.message.addGroup(group)
71
- end
72
-
73
- def set_fields msgPart, fieldName, fieldValue
74
- if fieldName.is_a? String
75
- add_field msgPart, fieldName, fieldValue
76
- elsif fieldName.is_a? Array
77
- if fieldName.length > 1
78
- add_array_field msgPart, fieldName, fieldValue
79
- else
80
- add_field msgPart, fieldName.first, fieldValue
81
- end
82
- end
83
- end
84
-
85
- def add_array_field msgPart, fieldArray, fieldValue
86
- if !FIXSpec::data_dictionary.nil?
87
- fieldName = fieldArray.shift
88
- tag = FIXSpec::data_dictionary.getFieldTag(fieldName)
89
- fail "#{fieldName} is not a valid field" if tag == -1
90
-
91
- arrayPosStr = fieldArray.shift
92
- arrayPos = arrayPosStr.to_i
93
- fail "#{arrayPos} is not a valid array index" unless arrayPos.to_s == arrayPosStr
94
- fail "You need to specify a field for group #{fieldName}" if fieldArray.empty?
95
-
96
- if msgPart.hasGroup(arrayPos+1, tag)
97
- set_fields msgPart.getGroup(arrayPos+1, tag), fieldArray, fieldValue
98
- else
99
- group = new_group(msgPart, fieldName)
100
- set_fields group, fieldArray, fieldValue
101
- msgPart.addGroup group
2
+ module Builder
3
+ def self.message
4
+ @message
102
5
  end
103
- else
104
- fail "no data dictionary set"
105
- end
106
- end
107
6
 
108
- def add_field msgPart, fieldName, fieldValue
109
- #kill quotes
110
- if fieldValue.match(/\"(.*)\"/)
111
- fieldValue=$1
112
- end
113
-
114
- tag = -1
115
- if !FIXSpec::data_dictionary.nil?
116
- tag = FIXSpec::data_dictionary.getFieldTag(fieldName)
117
- if FIXSpec::session_data_dictionary.is_header_field(tag)
118
- msgPart = msgPart.get_header
119
- elsif FIXSpec::session_data_dictionary.is_trailer_field(tag)
120
- msgPart = msgPart.get_trailer
7
+ def self.message= msg
8
+ @message=msg
121
9
  end
122
10
 
123
- case FIXSpec::data_dictionary.get_field_type_enum(tag).get_name
124
- when "INT","DAYOFMONTH" then
125
- msgPart.setInt(tag, fieldValue.to_i)
126
- when "PRICE","FLOAT","QTY" then
127
- msgPart.setDouble(tag, fieldValue.to_f)
128
- when "BOOLEAN" then
129
- msgPart.setBoolean(tag, fieldValue == "true")
130
- else
131
- #enum description => enum value
132
- #e.g. tag 54 "BUY"=>"1"
133
- fieldValue = FIXSpec::data_dictionary.get_reverse_value_name(tag, fieldValue)
134
- msgPart.setString(tag, fieldValue)
11
+ # Converts a FIX message string into a +quickfix.Message+.
12
+ #
13
+ # Params:
14
+ # +msg_string+:: the FIX message string
15
+ # +do_validation+:: if true, validation is performed using the DataDictionary
16
+ #
17
+ # Returns:
18
+ # +quickfix.Message+
19
+ #
20
+ # See also:
21
+ # +quickfix.MessageUtils#parse(Session, String)+
22
+ def self.parse_message msg_string, do_validation
23
+ begin_string = quickfix.MessageUtils.getStringField(msg_string, quickfix.field.BeginString::FIELD)
24
+ msg_type = quickfix.MessageUtils.getMessageType(msg_string)
25
+ payload_dict = quickfix.MessageUtils.isAdminMessage(msg_type) ? FIXSpec::session_data_dictionary : FIXSpec::application_data_dictionary
26
+ msg = quickfix.DefaultMessageFactory.new.create(begin_string, msg_type)
27
+ msg.parse(msg_string, FIXSpec::session_data_dictionary, payload_dict, do_validation)
28
+ msg
135
29
  end
136
- else
137
- tag = fieldName.to_i
138
- msgPart.setString(tag, fieldValue)
139
- end
140
- end
141
-
142
-
143
- # Tries to create a typed Message using a DefaultMessageFactory based on the given +msg_type+.
144
- #
145
- # This ensures that any repeating groups that are added to the Message will also be typed, and
146
- # therefore have the correct delimiter and field order.
147
- # Falls back to creating a base Message if +msg_type+ is nil.
148
- def new_message msg_type=nil, begin_string=nil
149
- if msg_type.nil?
150
- msg = quickfix.Message.new
151
- msg.get_header.setString(8, begin_string) unless begin_string.nil?
152
- msg
153
- else
154
- quickfix.DefaultMessageFactory.new.create(FIXSpec::session_data_dictionary.get_version, FIXSpec::data_dictionary.get_reverse_value_name(35, msg_type))
155
30
  end
156
31
  end
157
32
 
158
- # Tries to create a typed Group based on the name of the parent Message.
159
- #
160
- # This ensures that the correct delimiter and field order is used when serializing/deserializing the Group.
161
- # Falls back to creating a base Group if typed Group creation fails.
162
- #
163
- # Example:
164
- # If +msgPart+ is an instance of +Java::quickfix.fix50.MarketDataRequest+
165
- # And +fieldName+ is 'NoMDEntryTypes'
166
- # Then an instance of +Java::quickfix.fix50.MarketDataRequest::NoMDEntryTypes+ will be returned.
167
- def new_group msgPart, fieldName
168
- group_class = java_import("#{msgPart.getClass.getName}\$#{fieldName}").first
169
- group_class.new
170
- rescue
171
- quickfix.Group.new FIXSpec::data_dictionary.getFieldTag(fieldName), -1
172
- end
173
-
@@ -1,75 +1,11 @@
1
- require File.expand_path("../../fix_spec", __FILE__)
2
- require 'cuke_mem'
3
-
4
- World(JsonSpec::Helpers, JsonSpec::Matchers)
5
- World(FIXSpec::Matchers)
6
-
7
- Then /^the FIX message type should( not)? be "(.*?)"$/ do |negative, msg_type|
8
-
9
- unless FIXSpec::data_dictionary.nil?
10
- msg_type = FIXSpec::data_dictionary.get_msg_type(msg_type)
11
- end
12
-
13
- if negative
14
- last_fix.header.get_string(35).should_not == msg_type
15
- else
16
- last_fix.header.get_string(35).should == msg_type
17
- end
18
- end
19
-
20
- Then /^the (?:fix|FIX)(?: message)? at(?: tag)? "(.*?)" should( not)? be (".*"|\-?\d+(?:\.\d+)?(?:[eE][\+\-]?\d+)?|\[.*\]|%?\{.*\}|true|false|null)$/ do |tag, negative, exp_value|
21
- if negative
22
- last_fix.should_not be_fix_eql(CukeMem.remember(exp_value)).at_path(tag)
23
- else
24
- last_fix.should be_fix_eql(CukeMem.remember(exp_value)).at_path(tag)
25
- end
26
- end
27
-
28
- Then /^the (?:fix|FIX)(?: message)?(?: at(?: tag)? "(.*?)")? should( not)? be:$/ do |tag, negative, exp_value|
29
-
30
- # raw fix
31
- if tag.nil? and not exp_value.match(/{*}/)
32
- require 'fix_spec/builder'
33
- exp_message = FIXSpec::Builder.parse_message(FIXSpec::Helpers.fixify_string(exp_value), false)
34
- exp_value = FIXSpec::Helpers.message_to_unordered_json(exp_message)
35
- end
36
-
37
- if negative
38
- last_fix.should_not be_fix_eql(CukeMem.remember(exp_value)).at_path(tag)
39
- else
40
- last_fix.should be_fix_eql(CukeMem.remember(exp_value)).at_path(tag)
41
- end
42
-
43
- end
44
-
45
- Then /^the (?:fix|FIX)(?: message)? should( not)? be (".*"|\-?\d+(?:\.\d+)?(?:[eE][\+\-]?\d+)?|\[.*\]|%?\{.*\}|true|false|null)$/ do |negative, exp_value|
46
- if negative
47
- last_fix.should_not be_fix_eql(CukeMem.remember(exp_value))
48
- else
49
- last_fix.should be_fix_eql(CukeMem.remember(exp_value))
50
- end
51
- end
52
-
53
- Then /^the (?:FIX|fix)(?: message)?(?: at "(.*)")? should have the following:$/ do |base, table|
54
- table.raw.each do |path, value|
55
- path = [base, path].compact.join("/")
56
-
57
- if value
58
- step %(the fix at "#{path}" should be:), value
59
- else
60
- step %(the fix should have "#{path}")
61
- end
62
- end
63
- end
64
-
65
- Then /^the (?:fix|FIX)(?: message)? should( not)? have(?: tag)? "(.*)"$/ do |negative, path|
66
- if negative
67
- last_fix.should_not have_fix_path(path)
68
- else
69
- last_fix.should have_fix_path(path)
1
+ module FIXSpec
2
+ module Cucumber
3
+ require 'cucumber'
4
+ require 'cuke_mem'
5
+ require 'fix_spec/support/fix_helpers'
6
+ require 'fix_spec/step_definitions/fix_steps'
70
7
  end
71
8
  end
72
9
 
73
- When /^(?:I )?keep the (?:fix|FIX)(?: message)?(?: at(?: tag)? "(.*)")? as "(.*)"$/ do |path, key|
74
- CukeMem.memorize(key, normalize_json(FIXSpec::Helpers.message_to_unordered_json(last_fix), path))
75
- end
10
+ World(JsonSpec::Helpers, JsonSpec::Matchers)
11
+ World(FIXSpec::Matchers)
@@ -4,17 +4,21 @@ require 'rexml/document'
4
4
 
5
5
  module FIXSpec
6
6
  class DataDictionary < quickfix.DataDictionary
7
+ attr_reader :fileName
7
8
 
8
- def initialize fileName
9
- super fileName
10
- @reverse_lookup = Hash.new
9
+ def initialize(fileName)
10
+ @fileName = fileName
11
11
 
12
- parse_xml(fileName)
12
+ super(@fileName)
13
+ end
14
+
15
+ def reverse_lookup
16
+ @reverse_lookup ||= parse_xml
13
17
  end
14
18
 
15
19
  def get_reverse_value_name(tag, name)
16
- if(@reverse_lookup[tag].has_key?(name))
17
- @reverse_lookup[tag][name]
20
+ if(reverse_lookup[tag].has_key?(name))
21
+ reverse_lookup[tag][name]
18
22
  else
19
23
  name
20
24
  end
@@ -22,21 +26,26 @@ module FIXSpec
22
26
 
23
27
  private
24
28
 
25
- def parse_xml fileName
26
- doc = REXML::Document.new File.new(fileName)
27
- doc.elements.each("fix/fields/field") do |f|
29
+ def parse_xml
30
+ lookup = {}
31
+
32
+ doc = REXML::Document.new File.new(@fileName)
33
+
34
+ doc.elements.each("fix/fields/field") do |f|
28
35
  tag = f.attributes['number'].to_i
29
- @reverse_lookup[tag]||={}
36
+ lookup[tag]||={}
30
37
 
31
38
  f.elements.each("value") do |v|
32
- @reverse_lookup[ tag ][v.attributes['description'] ] = v.attributes['enum']
39
+ lookup[ tag ][v.attributes['description'] ] = v.attributes['enum']
33
40
  end
34
41
  end
35
42
 
36
43
  #also map pretty msg type names
37
- doc.elements.each("fix/messages/message") do |m|
38
- @reverse_lookup[35][m.attributes['name']] = m.attributes['msgtype']
44
+ doc.elements.each("fix/messages/message") do |m|
45
+ lookup[35][m.attributes['name']] = m.attributes['msgtype']
39
46
  end
47
+
48
+ lookup
40
49
  end
41
50
  end
42
51
  end
@@ -12,7 +12,3 @@ module FIXSpec
12
12
  end
13
13
  end
14
14
  end
15
-
16
- RSpec.configure do |config|
17
- config.include(FIXSpec::Matchers)
18
- end
@@ -2,6 +2,7 @@ module FIXSpec
2
2
  module Matchers
3
3
  class HaveFIXPath
4
4
  attr_reader :path
5
+
5
6
  def initialize path
6
7
  @path = path
7
8
  @json_matcher = JsonSpec::Matchers::HaveJsonPath.new path
@@ -0,0 +1,109 @@
1
+ #encoding ascii
2
+
3
+ Given(/^the following( unvalidated)? fix message:$/) do |unvalidated, fix_str|
4
+ FIXSpec::Builder.message = FIXSpec::Builder.parse_message(FIXSpec::Helpers.fixify_string(fix_str), !unvalidated)
5
+ FIXSpec::Builder.message.should_not be_nil
6
+ end
7
+
8
+ Given(/^I create a (?:fix|FIX|(FIXT?\.\d+\.\d+)) message(?: of type "(.*)")?$/) do |begin_string, msg_type|
9
+ FIXSpec::Builder.message = new_message(msg_type, begin_string)
10
+ end
11
+
12
+ Given(/^I create the following (?:fix|FIX|(FIXT?\.\d+\.\d+)) message(?: of type "(.*)")?:$/) do |begin_string, msg_type, table|
13
+ FIXSpec::Builder.message = new_message(msg_type, begin_string)
14
+ table.raw.each do |tag, value|
15
+ steps %{And I set the FIX message at "#{tag}" to #{value}}
16
+ end
17
+ end
18
+
19
+ Given(/^I set the (?:FIX|fix) message at(?: tag)? "(.*?)" to (".*"|\-?\d+(?:\.\d+)?(?:[eE][\+\-]?\d+)?|\[.*\]|%?\{.*\}|true|false|null)$/) do |fieldName, fieldValue|
20
+ FIXSpec::Builder.message.should_not be_nil
21
+ set_fields(FIXSpec::Builder.message, fieldName.split('/'), fieldValue)
22
+ end
23
+
24
+ Given(/^I add the following "(.*?)" group:$/) do |grpType, table|
25
+ FIXSpec::Builder.message.should_not be_nil
26
+
27
+ list_field_order = []
28
+ table.raw.each do |fieldName, fieldValue|
29
+ list_field_order.push(FIXSpec::data_dictionary.getFieldTag(fieldName))
30
+ end
31
+
32
+ group = quickfix.Group.new(FIXSpec::data_dictionary.getFieldTag(grpType), list_field_order.first, (list_field_order.to_java :int))
33
+
34
+ table.raw.each do |fieldName, fieldValue|
35
+ add_field(group, fieldName, fieldValue)
36
+ end
37
+
38
+ FIXSpec::Builder.message.addGroup(group)
39
+ end
40
+
41
+ Then(/^the FIX message type should( not)? be "(.*?)"$/) do |negative, msg_type|
42
+
43
+ unless FIXSpec::data_dictionary.nil?
44
+ msg_type = FIXSpec::data_dictionary.get_msg_type(msg_type)
45
+ end
46
+
47
+ if negative
48
+ last_fix.header.get_string(35).should_not == msg_type
49
+ else
50
+ last_fix.header.get_string(35).should == msg_type
51
+ end
52
+ end
53
+
54
+ Then(/^the (?:fix|FIX)(?: message)? at(?: tag)? "(.*?)" should( not)? be (".*"|\-?\d+(?:\.\d+)?(?:[eE][\+\-]?\d+)?|\[.*\]|%?\{.*\}|true|false|null)$/) do |tag, negative, exp_value|
55
+ if negative
56
+ last_fix.should_not be_fix_eql(CukeMem.remember(exp_value)).at_path(tag)
57
+ else
58
+ last_fix.should be_fix_eql(CukeMem.remember(exp_value)).at_path(tag)
59
+ end
60
+ end
61
+
62
+ Then(/^the (?:fix|FIX)(?: message)?(?: at(?: tag)? "(.*?)")? should( not)? be:$/) do |tag, negative, exp_value|
63
+
64
+ # raw fix
65
+ if tag.nil? and not exp_value.match(/{*}/)
66
+ require 'fix_spec/builder'
67
+ exp_message = FIXSpec::Builder.parse_message(FIXSpec::Helpers.fixify_string(exp_value), false)
68
+ exp_value = FIXSpec::Helpers.message_to_unordered_json(exp_message)
69
+ end
70
+
71
+ if negative
72
+ last_fix.should_not be_fix_eql(CukeMem.remember(exp_value)).at_path(tag)
73
+ else
74
+ last_fix.should be_fix_eql(CukeMem.remember(exp_value)).at_path(tag)
75
+ end
76
+
77
+ end
78
+
79
+ Then(/^the (?:fix|FIX)(?: message)? should( not)? be (".*"|\-?\d+(?:\.\d+)?(?:[eE][\+\-]?\d+)?|\[.*\]|%?\{.*\}|true|false|null)$/) do |negative, exp_value|
80
+ if negative
81
+ last_fix.should_not be_fix_eql(CukeMem.remember(exp_value))
82
+ else
83
+ last_fix.should be_fix_eql(CukeMem.remember(exp_value))
84
+ end
85
+ end
86
+
87
+ Then(/^the (?:FIX|fix)(?: message)?(?: at "(.*)")? should have the following:$/) do |base, table|
88
+ table.raw.each do |path, value|
89
+ path = [base, path].compact.join("/")
90
+
91
+ if value
92
+ step %(the fix at "#{path}" should be:), value
93
+ else
94
+ step %(the fix should have "#{path}")
95
+ end
96
+ end
97
+ end
98
+
99
+ Then(/^the (?:fix|FIX)(?: message)? should( not)? have(?: tag)? "(.*)"$/) do |negative, path|
100
+ if negative
101
+ last_fix.should_not have_fix_path(path)
102
+ else
103
+ last_fix.should have_fix_path(path)
104
+ end
105
+ end
106
+
107
+ When(/^(?:I )?keep the (?:fix|FIX)(?: message)?(?: at(?: tag)? "(.*)")? as "(.*)"$/) do |path, key|
108
+ CukeMem.memorize(key, normalize_json(FIXSpec::Helpers.message_to_unordered_json(last_fix), path))
109
+ end
@@ -0,0 +1,100 @@
1
+ def set_fields msgPart, fieldName, fieldValue
2
+ if fieldName.is_a? String
3
+ add_field msgPart, fieldName, fieldValue
4
+ elsif fieldName.is_a? Array
5
+ if fieldName.length > 1
6
+ add_array_field msgPart, fieldName, fieldValue
7
+ else
8
+ add_field msgPart, fieldName.first, fieldValue
9
+ end
10
+ end
11
+ end
12
+
13
+ def add_array_field msgPart, fieldArray, fieldValue
14
+ if !FIXSpec::data_dictionary.nil?
15
+ fieldName = fieldArray.shift
16
+ tag = FIXSpec::data_dictionary.getFieldTag(fieldName)
17
+ fail "#{fieldName} is not a valid field" if tag == -1
18
+
19
+ arrayPosStr = fieldArray.shift
20
+ arrayPos = arrayPosStr.to_i
21
+ fail "#{arrayPos} is not a valid array index" unless arrayPos.to_s == arrayPosStr
22
+ fail "You need to specify a field for group #{fieldName}" if fieldArray.empty?
23
+
24
+ if msgPart.hasGroup(arrayPos+1, tag)
25
+ set_fields msgPart.getGroup(arrayPos+1, tag), fieldArray, fieldValue
26
+ else
27
+ group = new_group(msgPart, fieldName)
28
+ set_fields group, fieldArray, fieldValue
29
+ msgPart.addGroup group
30
+ end
31
+ else
32
+ fail "no data dictionary set"
33
+ end
34
+ end
35
+
36
+ def add_field msgPart, fieldName, fieldValue
37
+ #kill quotes
38
+ if fieldValue.match(/\"(.*)\"/)
39
+ fieldValue=$1
40
+ end
41
+
42
+ tag = -1
43
+ if !FIXSpec::data_dictionary.nil?
44
+ tag = FIXSpec::data_dictionary.getFieldTag(fieldName)
45
+ if FIXSpec::session_data_dictionary.is_header_field(tag)
46
+ msgPart = msgPart.get_header
47
+ elsif FIXSpec::session_data_dictionary.is_trailer_field(tag)
48
+ msgPart = msgPart.get_trailer
49
+ end
50
+
51
+ case FIXSpec::data_dictionary.get_field_type_enum(tag).get_name
52
+ when "INT","DAYOFMONTH" then
53
+ msgPart.setInt(tag, fieldValue.to_i)
54
+ when "PRICE","FLOAT","QTY" then
55
+ msgPart.setDouble(tag, fieldValue.to_f)
56
+ when "BOOLEAN" then
57
+ msgPart.setBoolean(tag, fieldValue == "true")
58
+ else
59
+ #enum description => enum value
60
+ #e.g. tag 54 "BUY"=>"1"
61
+ fieldValue = FIXSpec::data_dictionary.get_reverse_value_name(tag, fieldValue)
62
+ msgPart.setString(tag, fieldValue)
63
+ end
64
+ else
65
+ tag = fieldName.to_i
66
+ msgPart.setString(tag, fieldValue)
67
+ end
68
+ end
69
+
70
+
71
+ # Tries to create a typed Message using a DefaultMessageFactory based on the given +msg_type+.
72
+ #
73
+ # This ensures that any repeating groups that are added to the Message will also be typed, and
74
+ # therefore have the correct delimiter and field order.
75
+ # Falls back to creating a base Message if +msg_type+ is nil.
76
+ def new_message msg_type=nil, begin_string=nil
77
+ if msg_type.nil?
78
+ msg = quickfix.Message.new
79
+ msg.get_header.setString(8, begin_string) unless begin_string.nil?
80
+ msg
81
+ else
82
+ quickfix.DefaultMessageFactory.new.create(FIXSpec::session_data_dictionary.get_version, FIXSpec::data_dictionary.get_reverse_value_name(35, msg_type))
83
+ end
84
+ end
85
+
86
+ # Tries to create a typed Group based on the name of the parent Message.
87
+ #
88
+ # This ensures that the correct delimiter and field order is used when serializing/deserializing the Group.
89
+ # Falls back to creating a base Group if typed Group creation fails.
90
+ #
91
+ # Example:
92
+ # If +msgPart+ is an instance of +Java::quickfix.fix50.MarketDataRequest+
93
+ # And +fieldName+ is 'NoMDEntryTypes'
94
+ # Then an instance of +Java::quickfix.fix50.MarketDataRequest::NoMDEntryTypes+ will be returned.
95
+ def new_group msgPart, fieldName
96
+ group_class = java_import("#{msgPart.getClass.getName}\$#{fieldName}").first
97
+ group_class.new
98
+ rescue
99
+ quickfix.Group.new FIXSpec::data_dictionary.getFieldTag(fieldName), -1
100
+ end
@@ -41,11 +41,9 @@ describe FIXSpec::Helpers do
41
41
  msg="8=FIX.4.235=849=ITG56=SILO205=410=045"
42
42
  fixify_string(msg).should ==("8=FIX.4.2\0019=26\00135=8\00149=ITG\00156=SILO\001205=4\00110=084\001")
43
43
  end
44
-
45
-
46
44
  end
47
45
 
48
- describe "message-to-hash functions" do
46
+ describe "#message_to_hash" do
49
47
  let(:order) {
50
48
  ord = quickfix.fix42.NewOrderSingle.new
51
49
  ord.header.set(quickfix.field.TargetCompID.new "target")
@@ -57,21 +55,28 @@ describe FIXSpec::Helpers do
57
55
  ord
58
56
  }
59
57
 
60
- context "field_map_to_hash" do
58
+ before(:each) do
59
+ # calling message_to_hash with a set data dictionary converts ints -> field names
60
+ # this gets confused with random ordering of tests because FIXSpec::application_data_dictionary
61
+ # behaves like a singleton that doesn't get reset between test runs
62
+ FIXSpec::application_data_dictionary = nil
63
+ end
64
+
65
+ describe "#field_map_to_hash" do
61
66
  let(:hash) { field_map_to_hash order.get_header }
62
67
 
63
68
  it "should have unordered tags" do
64
- hash[8].should=="FIX.4.2"
65
- hash[35].should=="D"
69
+ hash[8].should=="FIX.4.2"
70
+ hash[35].should=="D"
66
71
  end
67
72
  end
68
73
 
69
- context "message_to_hash" do
70
- let(:hash) { message_to_hash order }
74
+ describe "#message_to_hash" do
75
+ let(:hash) { message_to_hash(order) }
71
76
 
72
77
  it "should have unordered tags from all message parts" do
73
- hash[8].should=="FIX.4.2"
74
- hash[35].should=="D"
78
+ hash[8].should=="FIX.4.2"
79
+ hash[35].should=="D"
75
80
  hash[1].should=="account"
76
81
  hash[44].should == "75"
77
82
  hash[38].should == "100"
@@ -79,7 +84,7 @@ describe FIXSpec::Helpers do
79
84
  end
80
85
  end
81
86
 
82
- describe "get-message-type function" do
87
+ describe "#extract_message_type" do
83
88
  let(:order) {
84
89
  ord = quickfix.fix42.NewOrderSingle.new
85
90
  ord
@@ -2,12 +2,15 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
  require 'rspec'
4
4
  require 'fix_spec'
5
+ require 'pry'
5
6
 
6
7
  # Requires supporting files with custom matchers and macros, etc,
7
8
  # in ./support/ and its subdirectories.
8
9
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
10
 
10
11
  RSpec.configure do |config|
11
-
12
+ config.filter_run_including :focus => true
13
+ config.run_all_when_everything_filtered = true
14
+ config.treat_symbols_as_metadata_keys_with_true_values = true
12
15
  end
13
16
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fix_spec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Busbey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-22 00:00:00.000000000 Z
11
+ date: 2016-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ~>
109
109
  - !ruby/object:Gem::Version
110
110
  version: '10.1'
111
+ - !ruby/object:Gem::Dependency
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ name: pry
118
+ prerelease: false
119
+ type: :development
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  description: Build and Inspect FIX Messages with RSpec and Cucumber steps
112
126
  email: info@connamara.com
113
127
  executables: []
@@ -118,6 +132,8 @@ extra_rdoc_files:
118
132
  files:
119
133
  - .document
120
134
  - .rspec
135
+ - .ruby-env
136
+ - .ruby-version
121
137
  - .travis.yml
122
138
  - CONTRIBUTION_GUIDELINES.md
123
139
  - Gemfile
@@ -142,13 +158,14 @@ files:
142
158
  - fix_spec.gemspec
143
159
  - lib/fix_spec.rb
144
160
  - lib/fix_spec/builder.rb
145
- - lib/fix_spec/configuration.rb
146
161
  - lib/fix_spec/cucumber.rb
147
162
  - lib/fix_spec/data_dictionary.rb
148
163
  - lib/fix_spec/helpers.rb
149
164
  - lib/fix_spec/matchers.rb
150
165
  - lib/fix_spec/matchers/be_fix_eql.rb
151
166
  - lib/fix_spec/matchers/have_fix_path.rb
167
+ - lib/fix_spec/step_definitions/fix_steps.rb
168
+ - lib/fix_spec/support/fix_helpers.rb
152
169
  - spec/fix_spec/data_dictionary_spec.rb
153
170
  - spec/fix_spec/helpers_spec.rb
154
171
  - spec/spec_helper.rb
@@ -172,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
189
  version: '0'
173
190
  requirements: []
174
191
  rubyforge_project:
175
- rubygems_version: 2.1.9
192
+ rubygems_version: 2.4.5
176
193
  signing_key:
177
194
  specification_version: 4
178
195
  summary: Build and Inspect FIX Messages
@@ -1,33 +0,0 @@
1
- module FIXSpec
2
- module Configuration
3
-
4
- def data_dictionary=(dd)
5
- self.application_data_dictionary=dd
6
- self.session_data_dictionary=dd
7
- end
8
-
9
- def data_dictionary
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
27
- end
28
-
29
- def reset
30
- instance_variables.each{|ivar| remove_instance_variable(ivar)}
31
- end
32
- end
33
- end