fix_spec 0.4.1 → 1.0.1

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 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