diff --git a/.travis.yml b/.travis.yml index 2760d93..9489e44 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: go sudo: false go: - - 1.7 + - 1.9 - tip matrix: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9c27de8..d87ed08 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,6 +11,6 @@ Before proposing a large change, please discuss your change by raising an issue. ## Notes -* If you report a bug and don not include a fix, please include a failing test +* If you report a bug and do not include a fix, please include a failing test * Generally, contributions without tests will not be accepted * Contributions that fail the automated build will not be accepted diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..8a748b7 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,81 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/quickfixgo/enum" + packages = ["."] + revision = "6f7d7044e7b9c208e831839bb6e785156733c656" + +[[projects]] + branch = "master" + name = "github.com/quickfixgo/field" + packages = ["."] + revision = "9a80eadddd16bb2799c5878b753d8f2ad1371694" + +[[projects]] + branch = "master" + name = "github.com/quickfixgo/fix40" + packages = [".","executionreport","newordersingle","ordercancelrequest"] + revision = "e067782c1aa4bb0ab0819b19348ef888ea26acb7" + +[[projects]] + branch = "master" + name = "github.com/quickfixgo/fix41" + packages = [".","executionreport","newordersingle","ordercancelrequest"] + revision = "7c62df84c7a215524a9f8292ea1d06923eeacb6c" + +[[projects]] + branch = "master" + name = "github.com/quickfixgo/fix42" + packages = [".","executionreport","marketdatarequest","newordersingle","ordercancelrequest"] + revision = "0524454fdb3ffb4052b040aacbb9579021dec912" + +[[projects]] + branch = "master" + name = "github.com/quickfixgo/fix43" + packages = [".","executionreport","marketdatarequest","newordersingle","ordercancelrequest"] + revision = "68f15729340433303ea787c3b18f51a3d7db6b2c" + +[[projects]] + branch = "master" + name = "github.com/quickfixgo/fix44" + packages = [".","executionreport","marketdatarequest","newordersingle","ordercancelrequest"] + revision = "4018d8b3e12a1056ecc21442df29c8dd940ff567" + +[[projects]] + branch = "master" + name = "github.com/quickfixgo/fix50" + packages = ["executionreport","marketdatarequest","newordersingle","ordercancelrequest"] + revision = "8edfb1517a2213fcaba5b15c447aa64edcb43ed2" + +[[projects]] + branch = "master" + name = "github.com/quickfixgo/fixt11" + packages = ["."] + revision = "943f69cfc9d27b7b3423014673f5d7c90f63e79f" + +[[projects]] + branch = "master" + name = "github.com/quickfixgo/quickfix" + packages = [".","config","datadictionary","internal"] + revision = "d202ca98b53283d304d787bda0d782969c25d0cb" + +[[projects]] + branch = "master" + name = "github.com/quickfixgo/tag" + packages = ["."] + revision = "97164cfff31adf3f70978a76daafcce13e8288af" + +[[projects]] + branch = "master" + name = "github.com/shopspring/decimal" + packages = ["."] + revision = "aed1bfe463fa3c9cc268d60dcc1491db613bff7e" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "25e2fa23e613a129e477e79c65f944eea851770902d3eb115d1d02e3317817c9" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..586ceff --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,30 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + name = "github.com/quickfixgo/quickfix" + branch = "master" + +[[constraint]] + branch = "master" + name = "github.com/shopspring/decimal" diff --git a/cmd/executor/executor.go b/cmd/executor/executor.go index 190b481..f1ea8b1 100644 --- a/cmd/executor/executor.go +++ b/cmd/executor/executor.go @@ -5,25 +5,25 @@ import ( "fmt" "path" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" "github.com/shopspring/decimal" - fix40nos "github.com/quickfixgo/quickfix/fix40/newordersingle" - fix41nos "github.com/quickfixgo/quickfix/fix41/newordersingle" - fix42nos "github.com/quickfixgo/quickfix/fix42/newordersingle" - fix43nos "github.com/quickfixgo/quickfix/fix43/newordersingle" - fix44nos "github.com/quickfixgo/quickfix/fix44/newordersingle" - fix50nos "github.com/quickfixgo/quickfix/fix50/newordersingle" + fix40nos "github.com/quickfixgo/fix40/newordersingle" + fix41nos "github.com/quickfixgo/fix41/newordersingle" + fix42nos "github.com/quickfixgo/fix42/newordersingle" + fix43nos "github.com/quickfixgo/fix43/newordersingle" + fix44nos "github.com/quickfixgo/fix44/newordersingle" + fix50nos "github.com/quickfixgo/fix50/newordersingle" - fix40er "github.com/quickfixgo/quickfix/fix40/executionreport" - fix41er "github.com/quickfixgo/quickfix/fix41/executionreport" - fix42er "github.com/quickfixgo/quickfix/fix42/executionreport" - fix43er "github.com/quickfixgo/quickfix/fix43/executionreport" - fix44er "github.com/quickfixgo/quickfix/fix44/executionreport" - fix50er "github.com/quickfixgo/quickfix/fix50/executionreport" + fix40er "github.com/quickfixgo/fix40/executionreport" + fix41er "github.com/quickfixgo/fix41/executionreport" + fix42er "github.com/quickfixgo/fix42/executionreport" + fix43er "github.com/quickfixgo/fix43/executionreport" + fix44er "github.com/quickfixgo/fix44/executionreport" + fix50er "github.com/quickfixgo/fix50/executionreport" "os" "os/signal" @@ -59,17 +59,17 @@ func (e *executor) genExecID() field.ExecIDField { } //quickfix.Application interface -func (e executor) OnCreate(sessionID quickfix.SessionID) { return } -func (e executor) OnLogon(sessionID quickfix.SessionID) { return } -func (e executor) OnLogout(sessionID quickfix.SessionID) { return } -func (e executor) ToAdmin(msg quickfix.Message, sessionID quickfix.SessionID) { return } -func (e executor) ToApp(msg quickfix.Message, sessionID quickfix.SessionID) error { return nil } -func (e executor) FromAdmin(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { +func (e executor) OnCreate(sessionID quickfix.SessionID) { return } +func (e executor) OnLogon(sessionID quickfix.SessionID) { return } +func (e executor) OnLogout(sessionID quickfix.SessionID) { return } +func (e executor) ToAdmin(msg *quickfix.Message, sessionID quickfix.SessionID) { return } +func (e executor) ToApp(msg *quickfix.Message, sessionID quickfix.SessionID) error { return nil } +func (e executor) FromAdmin(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return nil } //Use Message Cracker on Incoming Application Messages -func (e *executor) FromApp(msg quickfix.Message, sessionID quickfix.SessionID) (reject quickfix.MessageRejectError) { +func (e *executor) FromApp(msg *quickfix.Message, sessionID quickfix.SessionID) (reject quickfix.MessageRejectError) { return e.Route(msg, sessionID) } diff --git a/cmd/ordermatch/internal/market.go b/cmd/ordermatch/internal/market.go index 5815d24..f17da56 100644 --- a/cmd/ordermatch/internal/market.go +++ b/cmd/ordermatch/internal/market.go @@ -5,7 +5,7 @@ import ( "sort" "time" - "github.com/quickfixgo/quickfix/enum" + "github.com/quickfixgo/enum" ) type orderList struct { diff --git a/cmd/ordermatch/internal/order.go b/cmd/ordermatch/internal/order.go index e95f8b8..396b1a4 100644 --- a/cmd/ordermatch/internal/order.go +++ b/cmd/ordermatch/internal/order.go @@ -3,7 +3,7 @@ package internal import ( "time" - "github.com/quickfixgo/quickfix/enum" + "github.com/quickfixgo/enum" "github.com/shopspring/decimal" ) diff --git a/cmd/ordermatch/internal/ordermatcher.go b/cmd/ordermatch/internal/ordermatcher.go index 3d995c4..3d9811f 100644 --- a/cmd/ordermatch/internal/ordermatcher.go +++ b/cmd/ordermatch/internal/ordermatcher.go @@ -3,7 +3,7 @@ package internal import ( "fmt" - "github.com/quickfixgo/quickfix/enum" + "github.com/quickfixgo/enum" ) type OrderMatcher struct { diff --git a/cmd/ordermatch/ordermatch.go b/cmd/ordermatch/ordermatch.go index fa63c20..4ccf805 100644 --- a/cmd/ordermatch/ordermatch.go +++ b/cmd/ordermatch/ordermatch.go @@ -9,14 +9,14 @@ import ( "path" "strconv" + "github.com/quickfixgo/enum" "github.com/quickfixgo/examples/cmd/ordermatch/internal" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix42/executionreport" + "github.com/quickfixgo/fix42/marketdatarequest" + "github.com/quickfixgo/fix42/newordersingle" + "github.com/quickfixgo/fix42/ordercancelrequest" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix42/executionreport" - "github.com/quickfixgo/quickfix/fix42/marketdatarequest" - "github.com/quickfixgo/quickfix/fix42/newordersingle" - "github.com/quickfixgo/quickfix/fix42/ordercancelrequest" ) //Application implements the quickfix.Application interface @@ -48,20 +48,20 @@ func (a Application) OnLogon(sessionID quickfix.SessionID) { return } func (a Application) OnLogout(sessionID quickfix.SessionID) { return } //ToAdmin implemented as part of Application interface -func (a Application) ToAdmin(msg quickfix.Message, sessionID quickfix.SessionID) { return } +func (a Application) ToAdmin(msg *quickfix.Message, sessionID quickfix.SessionID) { return } //ToApp implemented as part of Application interface -func (a Application) ToApp(msg quickfix.Message, sessionID quickfix.SessionID) error { +func (a Application) ToApp(msg *quickfix.Message, sessionID quickfix.SessionID) error { return nil } //FromAdmin implemented as part of Application interface -func (a Application) FromAdmin(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { +func (a Application) FromAdmin(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return nil } //FromApp implemented as part of Application interface, uses Router on incoming application messages -func (a *Application) FromApp(msg quickfix.Message, sessionID quickfix.SessionID) (reject quickfix.MessageRejectError) { +func (a *Application) FromApp(msg *quickfix.Message, sessionID quickfix.SessionID) (reject quickfix.MessageRejectError) { return a.Route(msg, sessionID) } diff --git a/cmd/tradeclient/internal/console.go b/cmd/tradeclient/internal/console.go index d3c72ea..241550a 100644 --- a/cmd/tradeclient/internal/console.go +++ b/cmd/tradeclient/internal/console.go @@ -5,33 +5,33 @@ import ( "fmt" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" "github.com/shopspring/decimal" "os" "strconv" "strings" - fix40nos "github.com/quickfixgo/quickfix/fix40/newordersingle" - fix41nos "github.com/quickfixgo/quickfix/fix41/newordersingle" - fix42nos "github.com/quickfixgo/quickfix/fix42/newordersingle" - fix43nos "github.com/quickfixgo/quickfix/fix43/newordersingle" - fix44nos "github.com/quickfixgo/quickfix/fix44/newordersingle" - fix50nos "github.com/quickfixgo/quickfix/fix50/newordersingle" - - fix40cxl "github.com/quickfixgo/quickfix/fix40/ordercancelrequest" - fix41cxl "github.com/quickfixgo/quickfix/fix41/ordercancelrequest" - fix42cxl "github.com/quickfixgo/quickfix/fix42/ordercancelrequest" - fix43cxl "github.com/quickfixgo/quickfix/fix43/ordercancelrequest" - fix44cxl "github.com/quickfixgo/quickfix/fix44/ordercancelrequest" - fix50cxl "github.com/quickfixgo/quickfix/fix50/ordercancelrequest" - - fix42mdr "github.com/quickfixgo/quickfix/fix42/marketdatarequest" - fix43mdr "github.com/quickfixgo/quickfix/fix43/marketdatarequest" - fix44mdr "github.com/quickfixgo/quickfix/fix44/marketdatarequest" - fix50mdr "github.com/quickfixgo/quickfix/fix50/marketdatarequest" + fix40nos "github.com/quickfixgo/fix40/newordersingle" + fix41nos "github.com/quickfixgo/fix41/newordersingle" + fix42nos "github.com/quickfixgo/fix42/newordersingle" + fix43nos "github.com/quickfixgo/fix43/newordersingle" + fix44nos "github.com/quickfixgo/fix44/newordersingle" + fix50nos "github.com/quickfixgo/fix50/newordersingle" + + fix40cxl "github.com/quickfixgo/fix40/ordercancelrequest" + fix41cxl "github.com/quickfixgo/fix41/ordercancelrequest" + fix42cxl "github.com/quickfixgo/fix42/ordercancelrequest" + fix43cxl "github.com/quickfixgo/fix43/ordercancelrequest" + fix44cxl "github.com/quickfixgo/fix44/ordercancelrequest" + fix50cxl "github.com/quickfixgo/fix50/ordercancelrequest" + + fix42mdr "github.com/quickfixgo/fix42/marketdatarequest" + fix43mdr "github.com/quickfixgo/fix43/marketdatarequest" + fix44mdr "github.com/quickfixgo/fix44/marketdatarequest" + fix50mdr "github.com/quickfixgo/fix50/marketdatarequest" ) func queryString(fieldName string) string { @@ -100,17 +100,17 @@ func queryVersion() (string, error) { switch scanner.Text() { case "1": - return enum.BeginStringFIX40, nil + return quickfix.BeginStringFIX40, nil case "2": - return enum.BeginStringFIX41, nil + return quickfix.BeginStringFIX41, nil case "3": - return enum.BeginStringFIX42, nil + return quickfix.BeginStringFIX42, nil case "4": - return enum.BeginStringFIX43, nil + return quickfix.BeginStringFIX43, nil case "5": - return enum.BeginStringFIX44, nil + return quickfix.BeginStringFIX44, nil case "6": - return enum.BeginStringFIXT11, nil + return quickfix.BeginStringFIXT11, nil } return "", fmt.Errorf("unknown BeginString choice: %v", scanner.Text()) @@ -225,7 +225,7 @@ func queryConfirm(prompt string) bool { } type header interface { - Set(f quickfix.FieldWriter) quickfix.FieldMap + Set(f quickfix.FieldWriter) *quickfix.FieldMap } func queryHeader(h header) { @@ -258,7 +258,7 @@ func queryNewOrderSingle40() fix40nos.NewOrderSingle { return order } -func queryNewOrderSingle41() (msg quickfix.Message) { +func queryNewOrderSingle41() (msg *quickfix.Message) { var ordType field.OrdTypeField order := fix41nos.New(queryClOrdID(), field.NewHandlInst("1"), querySymbol(), querySide(), queryOrdType(&ordType)) order.Set(queryOrderQty()) @@ -275,12 +275,12 @@ func queryNewOrderSingle41() (msg quickfix.Message) { order.Set(queryTimeInForce()) msg = order.ToMessage() - queryHeader(msg.Header) + queryHeader(&msg.Header) return } -func queryNewOrderSingle42() (msg quickfix.Message) { +func queryNewOrderSingle42() (msg *quickfix.Message) { var ordType field.OrdTypeField order := fix42nos.New(queryClOrdID(), field.NewHandlInst("1"), querySymbol(), querySide(), field.NewTransactTime(time.Now()), queryOrdType(&ordType)) order.Set(queryOrderQty()) @@ -297,11 +297,11 @@ func queryNewOrderSingle42() (msg quickfix.Message) { order.Set(queryTimeInForce()) msg = order.ToMessage() - queryHeader(msg.Header) + queryHeader(&msg.Header) return } -func queryNewOrderSingle43() (msg quickfix.Message) { +func queryNewOrderSingle43() (msg *quickfix.Message) { var ordType field.OrdTypeField order := fix43nos.New(queryClOrdID(), field.NewHandlInst("1"), querySide(), field.NewTransactTime(time.Now()), queryOrdType(&ordType)) order.Set(querySymbol()) @@ -319,12 +319,12 @@ func queryNewOrderSingle43() (msg quickfix.Message) { order.Set(queryTimeInForce()) msg = order.ToMessage() - queryHeader(msg.Header) + queryHeader(&msg.Header) return } -func queryNewOrderSingle44() (msg quickfix.Message) { +func queryNewOrderSingle44() (msg *quickfix.Message) { var ordType field.OrdTypeField order := fix44nos.New(queryClOrdID(), querySide(), field.NewTransactTime(time.Now()), queryOrdType(&ordType)) order.SetHandlInst("1") @@ -343,12 +343,12 @@ func queryNewOrderSingle44() (msg quickfix.Message) { order.Set(queryTimeInForce()) msg = order.ToMessage() - queryHeader(msg.Header) + queryHeader(&msg.Header) return } -func queryNewOrderSingle50() (msg quickfix.Message) { +func queryNewOrderSingle50() (msg *quickfix.Message) { var ordType field.OrdTypeField order := fix50nos.New(queryClOrdID(), querySide(), field.NewTransactTime(time.Now()), queryOrdType(&ordType)) order.SetHandlInst("1") @@ -367,59 +367,59 @@ func queryNewOrderSingle50() (msg quickfix.Message) { } msg = order.ToMessage() - queryHeader(msg.Header) + queryHeader(&msg.Header) return } -func queryOrderCancelRequest40() (msg quickfix.Message) { +func queryOrderCancelRequest40() (msg *quickfix.Message) { cancel := fix40cxl.New(queryOrigClOrdID(), queryClOrdID(), field.NewCxlType("F"), querySymbol(), querySide(), queryOrderQty()) msg = cancel.ToMessage() - queryHeader(msg.Header) + queryHeader(&msg.Header) return } -func queryOrderCancelRequest41() (msg quickfix.Message) { +func queryOrderCancelRequest41() (msg *quickfix.Message) { cancel := fix41cxl.New(queryOrigClOrdID(), queryClOrdID(), querySymbol(), querySide()) cancel.Set(queryOrderQty()) msg = cancel.ToMessage() - queryHeader(msg.Header) + queryHeader(&msg.Header) return } -func queryOrderCancelRequest42() (msg quickfix.Message) { +func queryOrderCancelRequest42() (msg *quickfix.Message) { cancel := fix42cxl.New(queryOrigClOrdID(), queryClOrdID(), querySymbol(), querySide(), field.NewTransactTime(time.Now())) cancel.Set(queryOrderQty()) msg = cancel.ToMessage() - queryHeader(msg.Header) + queryHeader(&msg.Header) return } -func queryOrderCancelRequest43() (msg quickfix.Message) { +func queryOrderCancelRequest43() (msg *quickfix.Message) { cancel := fix43cxl.New(queryOrigClOrdID(), queryClOrdID(), querySide(), field.NewTransactTime(time.Now())) cancel.Set(querySymbol()) cancel.Set(queryOrderQty()) msg = cancel.ToMessage() - queryHeader(msg.Header) + queryHeader(&msg.Header) return } -func queryOrderCancelRequest44() (msg quickfix.Message) { +func queryOrderCancelRequest44() (msg *quickfix.Message) { cancel := fix44cxl.New(queryOrigClOrdID(), queryClOrdID(), querySide(), field.NewTransactTime(time.Now())) cancel.Set(querySymbol()) cancel.Set(queryOrderQty()) msg = cancel.ToMessage() - queryHeader(msg.Header) + queryHeader(&msg.Header) return } -func queryOrderCancelRequest50() (msg quickfix.Message) { +func queryOrderCancelRequest50() (msg *quickfix.Message) { cancel := fix50cxl.New(queryOrigClOrdID(), queryClOrdID(), querySide(), field.NewTransactTime(time.Now())) cancel.Set(querySymbol()) cancel.Set(queryOrderQty()) msg = cancel.ToMessage() - queryHeader(msg.Header) + queryHeader(&msg.Header) return } @@ -510,22 +510,22 @@ func QueryEnterOrder() (err error) { var order quickfix.Messagable switch beginString { - case enum.BeginStringFIX40: + case quickfix.BeginStringFIX40: order = queryNewOrderSingle40() - case enum.BeginStringFIX41: + case quickfix.BeginStringFIX41: order = queryNewOrderSingle41() - case enum.BeginStringFIX42: + case quickfix.BeginStringFIX42: order = queryNewOrderSingle42() - case enum.BeginStringFIX43: + case quickfix.BeginStringFIX43: order = queryNewOrderSingle43() - case enum.BeginStringFIX44: + case quickfix.BeginStringFIX44: order = queryNewOrderSingle44() - case enum.BeginStringFIXT11: + case quickfix.BeginStringFIXT11: order = queryNewOrderSingle50() } @@ -545,24 +545,24 @@ func QueryCancelOrder() (err error) { return err } - var cxl quickfix.Message + var cxl *quickfix.Message switch beginString { - case enum.BeginStringFIX40: + case quickfix.BeginStringFIX40: cxl = queryOrderCancelRequest40() - case enum.BeginStringFIX41: + case quickfix.BeginStringFIX41: cxl = queryOrderCancelRequest41() - case enum.BeginStringFIX42: + case quickfix.BeginStringFIX42: cxl = queryOrderCancelRequest42() - case enum.BeginStringFIX43: + case quickfix.BeginStringFIX43: cxl = queryOrderCancelRequest43() - case enum.BeginStringFIX44: + case quickfix.BeginStringFIX44: cxl = queryOrderCancelRequest44() - case enum.BeginStringFIXT11: + case quickfix.BeginStringFIXT11: cxl = queryOrderCancelRequest50() } @@ -581,16 +581,16 @@ func QueryMarketDataRequest() error { var req quickfix.Messagable switch beginString { - case enum.BeginStringFIX42: + case quickfix.BeginStringFIX42: req = queryMarketDataRequest42() - case enum.BeginStringFIX43: + case quickfix.BeginStringFIX43: req = queryMarketDataRequest43() - case enum.BeginStringFIX44: + case quickfix.BeginStringFIX44: req = queryMarketDataRequest44() - case enum.BeginStringFIXT11: + case quickfix.BeginStringFIXT11: req = queryMarketDataRequest50() default: diff --git a/cmd/tradeclient/tradeclient.go b/cmd/tradeclient/tradeclient.go index cbc6c4f..d1941b0 100644 --- a/cmd/tradeclient/tradeclient.go +++ b/cmd/tradeclient/tradeclient.go @@ -30,24 +30,23 @@ func (e TradeClient) OnLogout(sessionID quickfix.SessionID) { } //FromAdmin implemented as part of Application interface -func (e TradeClient) FromAdmin(msg quickfix.Message, sessionID quickfix.SessionID) (reject quickfix.MessageRejectError) { +func (e TradeClient) FromAdmin(msg *quickfix.Message, sessionID quickfix.SessionID) (reject quickfix.MessageRejectError) { return } //ToAdmin implemented as part of Application interface -func (e TradeClient) ToAdmin(msg quickfix.Message, sessionID quickfix.SessionID) { +func (e TradeClient) ToAdmin(msg *quickfix.Message, sessionID quickfix.SessionID) { return } //ToApp implemented as part of Application interface -func (e TradeClient) ToApp(msg quickfix.Message, sessionID quickfix.SessionID) (err error) { - msg.Build() - fmt.Printf("Sending %s\n", &msg) +func (e TradeClient) ToApp(msg *quickfix.Message, sessionID quickfix.SessionID) (err error) { + fmt.Printf("Sending %s\n", msg) return } //FromApp implemented as part of Application interface. This is the callback for all Application level messages from the counter party. -func (e TradeClient) FromApp(msg quickfix.Message, sessionID quickfix.SessionID) (reject quickfix.MessageRejectError) { +func (e TradeClient) FromApp(msg *quickfix.Message, sessionID quickfix.SessionID) (reject quickfix.MessageRejectError) { fmt.Printf("FromApp: %s\n", msg.String()) return } diff --git a/vendor/github.com/quickfixgo/enum/README.md b/vendor/github.com/quickfixgo/enum/README.md new file mode 100644 index 0000000..accb5c2 --- /dev/null +++ b/vendor/github.com/quickfixgo/enum/README.md @@ -0,0 +1,4 @@ +Enum +=== + +enum is generated from `github.com/quickfixgo/quickfix/cmd/generate-fix` using the specs in `github.com/quickfixgo/quickfix/spec`. diff --git a/vendor/github.com/quickfixgo/quickfix/enum/enums.generated.go b/vendor/github.com/quickfixgo/enum/enums.generated.go similarity index 100% rename from vendor/github.com/quickfixgo/quickfix/enum/enums.generated.go rename to vendor/github.com/quickfixgo/enum/enums.generated.go diff --git a/vendor/github.com/quickfixgo/field/README.md b/vendor/github.com/quickfixgo/field/README.md new file mode 100644 index 0000000..f74d690 --- /dev/null +++ b/vendor/github.com/quickfixgo/field/README.md @@ -0,0 +1,4 @@ +Field +=== + +field is generated from `github.com/quickfixgo/quickfix/cmd/generate-fix` using the specs in `github.com/quickfixgo/quickfix/spec`. diff --git a/vendor/github.com/quickfixgo/quickfix/field/fields.generated.go b/vendor/github.com/quickfixgo/field/fields.generated.go similarity index 98% rename from vendor/github.com/quickfixgo/quickfix/field/fields.generated.go rename to vendor/github.com/quickfixgo/field/fields.generated.go index 4eec3ba..b41914c 100644 --- a/vendor/github.com/quickfixgo/quickfix/field/fields.generated.go +++ b/vendor/github.com/quickfixgo/field/fields.generated.go @@ -1,9 +1,9 @@ package field import ( + "github.com/quickfixgo/enum" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" "github.com/shopspring/decimal" "time" ) @@ -2351,12 +2351,17 @@ func (f ComplexEventEndDateField) Tag() quickfix.Tag { return tag.ComplexEventEn //NewComplexEventEndDate returns a new ComplexEventEndDateField initialized with val func NewComplexEventEndDate(val time.Time) ComplexEventEndDateField { - return ComplexEventEndDateField{quickfix.FIXUTCTimestamp{Time: val}} + return NewComplexEventEndDateWithPrecision(val, quickfix.Millis) } //NewComplexEventEndDateNoMillis returns a new ComplexEventEndDateField initialized with val without millisecs func NewComplexEventEndDateNoMillis(val time.Time) ComplexEventEndDateField { - return ComplexEventEndDateField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewComplexEventEndDateWithPrecision(val, quickfix.Seconds) +} + +//NewComplexEventEndDateWithPrecision returns a new ComplexEventEndDateField initialized with val of specified precision +func NewComplexEventEndDateWithPrecision(val time.Time, precision quickfix.TimestampPrecision) ComplexEventEndDateField { + return ComplexEventEndDateField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f ComplexEventEndDateField) Value() time.Time { return f.Time } @@ -2440,12 +2445,17 @@ func (f ComplexEventStartDateField) Tag() quickfix.Tag { return tag.ComplexEvent //NewComplexEventStartDate returns a new ComplexEventStartDateField initialized with val func NewComplexEventStartDate(val time.Time) ComplexEventStartDateField { - return ComplexEventStartDateField{quickfix.FIXUTCTimestamp{Time: val}} + return NewComplexEventStartDateWithPrecision(val, quickfix.Millis) } //NewComplexEventStartDateNoMillis returns a new ComplexEventStartDateField initialized with val without millisecs func NewComplexEventStartDateNoMillis(val time.Time) ComplexEventStartDateField { - return ComplexEventStartDateField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewComplexEventStartDateWithPrecision(val, quickfix.Seconds) +} + +//NewComplexEventStartDateWithPrecision returns a new ComplexEventStartDateField initialized with val of specified precision +func NewComplexEventStartDateWithPrecision(val time.Time, precision quickfix.TimestampPrecision) ComplexEventStartDateField { + return ComplexEventStartDateField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f ComplexEventStartDateField) Value() time.Time { return f.Time } @@ -2776,12 +2786,17 @@ func (f ContraTradeTimeField) Tag() quickfix.Tag { return tag.ContraTradeTime } //NewContraTradeTime returns a new ContraTradeTimeField initialized with val func NewContraTradeTime(val time.Time) ContraTradeTimeField { - return ContraTradeTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewContraTradeTimeWithPrecision(val, quickfix.Millis) } //NewContraTradeTimeNoMillis returns a new ContraTradeTimeField initialized with val without millisecs func NewContraTradeTimeNoMillis(val time.Time) ContraTradeTimeField { - return ContraTradeTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewContraTradeTimeWithPrecision(val, quickfix.Seconds) +} + +//NewContraTradeTimeWithPrecision returns a new ContraTradeTimeField initialized with val of specified precision +func NewContraTradeTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) ContraTradeTimeField { + return ContraTradeTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f ContraTradeTimeField) Value() time.Time { return f.Time } @@ -3627,12 +3642,17 @@ func (f DerivativeEventTimeField) Tag() quickfix.Tag { return tag.DerivativeEven //NewDerivativeEventTime returns a new DerivativeEventTimeField initialized with val func NewDerivativeEventTime(val time.Time) DerivativeEventTimeField { - return DerivativeEventTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewDerivativeEventTimeWithPrecision(val, quickfix.Millis) } //NewDerivativeEventTimeNoMillis returns a new DerivativeEventTimeField initialized with val without millisecs func NewDerivativeEventTimeNoMillis(val time.Time) DerivativeEventTimeField { - return DerivativeEventTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewDerivativeEventTimeWithPrecision(val, quickfix.Seconds) +} + +//NewDerivativeEventTimeWithPrecision returns a new DerivativeEventTimeField initialized with val of specified precision +func NewDerivativeEventTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) DerivativeEventTimeField { + return DerivativeEventTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f DerivativeEventTimeField) Value() time.Time { return f.Time } @@ -4811,12 +4831,17 @@ func (f EffectiveTimeField) Tag() quickfix.Tag { return tag.EffectiveTime } //NewEffectiveTime returns a new EffectiveTimeField initialized with val func NewEffectiveTime(val time.Time) EffectiveTimeField { - return EffectiveTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewEffectiveTimeWithPrecision(val, quickfix.Millis) } //NewEffectiveTimeNoMillis returns a new EffectiveTimeField initialized with val without millisecs func NewEffectiveTimeNoMillis(val time.Time) EffectiveTimeField { - return EffectiveTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewEffectiveTimeWithPrecision(val, quickfix.Seconds) +} + +//NewEffectiveTimeWithPrecision returns a new EffectiveTimeField initialized with val of specified precision +func NewEffectiveTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) EffectiveTimeField { + return EffectiveTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f EffectiveTimeField) Value() time.Time { return f.Time } @@ -5455,12 +5480,17 @@ func (f EventTimeField) Tag() quickfix.Tag { return tag.EventTime } //NewEventTime returns a new EventTimeField initialized with val func NewEventTime(val time.Time) EventTimeField { - return EventTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewEventTimeWithPrecision(val, quickfix.Millis) } //NewEventTimeNoMillis returns a new EventTimeField initialized with val without millisecs func NewEventTimeNoMillis(val time.Time) EventTimeField { - return EventTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewEventTimeWithPrecision(val, quickfix.Seconds) +} + +//NewEventTimeWithPrecision returns a new EventTimeField initialized with val of specified precision +func NewEventTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) EventTimeField { + return EventTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f EventTimeField) Value() time.Time { return f.Time } @@ -5702,12 +5732,17 @@ func (f ExecValuationPointField) Tag() quickfix.Tag { return tag.ExecValuationPo //NewExecValuationPoint returns a new ExecValuationPointField initialized with val func NewExecValuationPoint(val time.Time) ExecValuationPointField { - return ExecValuationPointField{quickfix.FIXUTCTimestamp{Time: val}} + return NewExecValuationPointWithPrecision(val, quickfix.Millis) } //NewExecValuationPointNoMillis returns a new ExecValuationPointField initialized with val without millisecs func NewExecValuationPointNoMillis(val time.Time) ExecValuationPointField { - return ExecValuationPointField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewExecValuationPointWithPrecision(val, quickfix.Seconds) +} + +//NewExecValuationPointWithPrecision returns a new ExecValuationPointField initialized with val of specified precision +func NewExecValuationPointWithPrecision(val time.Time, precision quickfix.TimestampPrecision) ExecValuationPointField { + return ExecValuationPointField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f ExecValuationPointField) Value() time.Time { return f.Time } @@ -5808,12 +5843,17 @@ func (f ExpireTimeField) Tag() quickfix.Tag { return tag.ExpireTime } //NewExpireTime returns a new ExpireTimeField initialized with val func NewExpireTime(val time.Time) ExpireTimeField { - return ExpireTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewExpireTimeWithPrecision(val, quickfix.Millis) } //NewExpireTimeNoMillis returns a new ExpireTimeField initialized with val without millisecs func NewExpireTimeNoMillis(val time.Time) ExpireTimeField { - return ExpireTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewExpireTimeWithPrecision(val, quickfix.Seconds) +} + +//NewExpireTimeWithPrecision returns a new ExpireTimeField initialized with val of specified precision +func NewExpireTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) ExpireTimeField { + return ExpireTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f ExpireTimeField) Value() time.Time { return f.Time } @@ -6225,12 +6265,17 @@ func (f HopSendingTimeField) Tag() quickfix.Tag { return tag.HopSendingTime } //NewHopSendingTime returns a new HopSendingTimeField initialized with val func NewHopSendingTime(val time.Time) HopSendingTimeField { - return HopSendingTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewHopSendingTimeWithPrecision(val, quickfix.Millis) } //NewHopSendingTimeNoMillis returns a new HopSendingTimeField initialized with val without millisecs func NewHopSendingTimeNoMillis(val time.Time) HopSendingTimeField { - return HopSendingTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewHopSendingTimeWithPrecision(val, quickfix.Seconds) +} + +//NewHopSendingTimeWithPrecision returns a new HopSendingTimeField initialized with val of specified precision +func NewHopSendingTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) HopSendingTimeField { + return HopSendingTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f HopSendingTimeField) Value() time.Time { return f.Time } @@ -6870,12 +6915,17 @@ func (f LastUpdateTimeField) Tag() quickfix.Tag { return tag.LastUpdateTime } //NewLastUpdateTime returns a new LastUpdateTimeField initialized with val func NewLastUpdateTime(val time.Time) LastUpdateTimeField { - return LastUpdateTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewLastUpdateTimeWithPrecision(val, quickfix.Millis) } //NewLastUpdateTimeNoMillis returns a new LastUpdateTimeField initialized with val without millisecs func NewLastUpdateTimeNoMillis(val time.Time) LastUpdateTimeField { - return LastUpdateTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewLastUpdateTimeWithPrecision(val, quickfix.Seconds) +} + +//NewLastUpdateTimeWithPrecision returns a new LastUpdateTimeField initialized with val of specified precision +func NewLastUpdateTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) LastUpdateTimeField { + return LastUpdateTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f LastUpdateTimeField) Value() time.Time { return f.Time } @@ -12075,12 +12125,17 @@ func (f OnBehalfOfSendingTimeField) Tag() quickfix.Tag { return tag.OnBehalfOfSe //NewOnBehalfOfSendingTime returns a new OnBehalfOfSendingTimeField initialized with val func NewOnBehalfOfSendingTime(val time.Time) OnBehalfOfSendingTimeField { - return OnBehalfOfSendingTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewOnBehalfOfSendingTimeWithPrecision(val, quickfix.Millis) } //NewOnBehalfOfSendingTimeNoMillis returns a new OnBehalfOfSendingTimeField initialized with val without millisecs func NewOnBehalfOfSendingTimeNoMillis(val time.Time) OnBehalfOfSendingTimeField { - return OnBehalfOfSendingTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewOnBehalfOfSendingTimeWithPrecision(val, quickfix.Seconds) +} + +//NewOnBehalfOfSendingTimeWithPrecision returns a new OnBehalfOfSendingTimeField initialized with val of specified precision +func NewOnBehalfOfSendingTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) OnBehalfOfSendingTimeField { + return OnBehalfOfSendingTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f OnBehalfOfSendingTimeField) Value() time.Time { return f.Time } @@ -12480,12 +12535,17 @@ func (f OrigOrdModTimeField) Tag() quickfix.Tag { return tag.OrigOrdModTime } //NewOrigOrdModTime returns a new OrigOrdModTimeField initialized with val func NewOrigOrdModTime(val time.Time) OrigOrdModTimeField { - return OrigOrdModTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewOrigOrdModTimeWithPrecision(val, quickfix.Millis) } //NewOrigOrdModTimeNoMillis returns a new OrigOrdModTimeField initialized with val without millisecs func NewOrigOrdModTimeNoMillis(val time.Time) OrigOrdModTimeField { - return OrigOrdModTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewOrigOrdModTimeWithPrecision(val, quickfix.Seconds) +} + +//NewOrigOrdModTimeWithPrecision returns a new OrigOrdModTimeField initialized with val of specified precision +func NewOrigOrdModTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) OrigOrdModTimeField { + return OrigOrdModTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f OrigOrdModTimeField) Value() time.Time { return f.Time } @@ -12524,12 +12584,17 @@ func (f OrigSendingTimeField) Tag() quickfix.Tag { return tag.OrigSendingTime } //NewOrigSendingTime returns a new OrigSendingTimeField initialized with val func NewOrigSendingTime(val time.Time) OrigSendingTimeField { - return OrigSendingTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewOrigSendingTimeWithPrecision(val, quickfix.Millis) } //NewOrigSendingTimeNoMillis returns a new OrigSendingTimeField initialized with val without millisecs func NewOrigSendingTimeNoMillis(val time.Time) OrigSendingTimeField { - return OrigSendingTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewOrigSendingTimeWithPrecision(val, quickfix.Seconds) +} + +//NewOrigSendingTimeWithPrecision returns a new OrigSendingTimeField initialized with val of specified precision +func NewOrigSendingTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) OrigSendingTimeField { + return OrigSendingTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f OrigSendingTimeField) Value() time.Time { return f.Time } @@ -12542,12 +12607,17 @@ func (f OrigTimeField) Tag() quickfix.Tag { return tag.OrigTime } //NewOrigTime returns a new OrigTimeField initialized with val func NewOrigTime(val time.Time) OrigTimeField { - return OrigTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewOrigTimeWithPrecision(val, quickfix.Millis) } //NewOrigTimeNoMillis returns a new OrigTimeField initialized with val without millisecs func NewOrigTimeNoMillis(val time.Time) OrigTimeField { - return OrigTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewOrigTimeWithPrecision(val, quickfix.Seconds) +} + +//NewOrigTimeWithPrecision returns a new OrigTimeField initialized with val of specified precision +func NewOrigTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) OrigTimeField { + return OrigTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f OrigTimeField) Value() time.Time { return f.Time } @@ -13976,12 +14046,17 @@ func (f QuoteSetValidUntilTimeField) Tag() quickfix.Tag { return tag.QuoteSetVal //NewQuoteSetValidUntilTime returns a new QuoteSetValidUntilTimeField initialized with val func NewQuoteSetValidUntilTime(val time.Time) QuoteSetValidUntilTimeField { - return QuoteSetValidUntilTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewQuoteSetValidUntilTimeWithPrecision(val, quickfix.Millis) } //NewQuoteSetValidUntilTimeNoMillis returns a new QuoteSetValidUntilTimeField initialized with val without millisecs func NewQuoteSetValidUntilTimeNoMillis(val time.Time) QuoteSetValidUntilTimeField { - return QuoteSetValidUntilTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewQuoteSetValidUntilTimeWithPrecision(val, quickfix.Seconds) +} + +//NewQuoteSetValidUntilTimeWithPrecision returns a new QuoteSetValidUntilTimeField initialized with val of specified precision +func NewQuoteSetValidUntilTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) QuoteSetValidUntilTimeField { + return QuoteSetValidUntilTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f QuoteSetValidUntilTimeField) Value() time.Time { return f.Time } @@ -14507,12 +14582,17 @@ func (f RelSymTransactTimeField) Tag() quickfix.Tag { return tag.RelSymTransactT //NewRelSymTransactTime returns a new RelSymTransactTimeField initialized with val func NewRelSymTransactTime(val time.Time) RelSymTransactTimeField { - return RelSymTransactTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewRelSymTransactTimeWithPrecision(val, quickfix.Millis) } //NewRelSymTransactTimeNoMillis returns a new RelSymTransactTimeField initialized with val without millisecs func NewRelSymTransactTimeNoMillis(val time.Time) RelSymTransactTimeField { - return RelSymTransactTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewRelSymTransactTimeWithPrecision(val, quickfix.Seconds) +} + +//NewRelSymTransactTimeWithPrecision returns a new RelSymTransactTimeField initialized with val of specified precision +func NewRelSymTransactTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) RelSymTransactTimeField { + return RelSymTransactTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f RelSymTransactTimeField) Value() time.Time { return f.Time } @@ -16742,12 +16822,17 @@ func (f SendingTimeField) Tag() quickfix.Tag { return tag.SendingTime } //NewSendingTime returns a new SendingTimeField initialized with val func NewSendingTime(val time.Time) SendingTimeField { - return SendingTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewSendingTimeWithPrecision(val, quickfix.Millis) } //NewSendingTimeNoMillis returns a new SendingTimeField initialized with val without millisecs func NewSendingTimeNoMillis(val time.Time) SendingTimeField { - return SendingTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewSendingTimeWithPrecision(val, quickfix.Seconds) +} + +//NewSendingTimeWithPrecision returns a new SendingTimeField initialized with val of specified precision +func NewSendingTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) SendingTimeField { + return SendingTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f SendingTimeField) Value() time.Time { return f.Time } @@ -17533,12 +17618,17 @@ func (f SideTimeInForceField) Tag() quickfix.Tag { return tag.SideTimeInForce } //NewSideTimeInForce returns a new SideTimeInForceField initialized with val func NewSideTimeInForce(val time.Time) SideTimeInForceField { - return SideTimeInForceField{quickfix.FIXUTCTimestamp{Time: val}} + return NewSideTimeInForceWithPrecision(val, quickfix.Millis) } //NewSideTimeInForceNoMillis returns a new SideTimeInForceField initialized with val without millisecs func NewSideTimeInForceNoMillis(val time.Time) SideTimeInForceField { - return SideTimeInForceField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewSideTimeInForceWithPrecision(val, quickfix.Seconds) +} + +//NewSideTimeInForceWithPrecision returns a new SideTimeInForceField initialized with val of specified precision +func NewSideTimeInForceWithPrecision(val time.Time, precision quickfix.TimestampPrecision) SideTimeInForceField { + return SideTimeInForceField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f SideTimeInForceField) Value() time.Time { return f.Time } @@ -17564,12 +17654,17 @@ func (f SideTrdRegTimestampField) Tag() quickfix.Tag { return tag.SideTrdRegTime //NewSideTrdRegTimestamp returns a new SideTrdRegTimestampField initialized with val func NewSideTrdRegTimestamp(val time.Time) SideTrdRegTimestampField { - return SideTrdRegTimestampField{quickfix.FIXUTCTimestamp{Time: val}} + return NewSideTrdRegTimestampWithPrecision(val, quickfix.Millis) } //NewSideTrdRegTimestampNoMillis returns a new SideTrdRegTimestampField initialized with val without millisecs func NewSideTrdRegTimestampNoMillis(val time.Time) SideTrdRegTimestampField { - return SideTrdRegTimestampField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewSideTrdRegTimestampWithPrecision(val, quickfix.Seconds) +} + +//NewSideTrdRegTimestampWithPrecision returns a new SideTrdRegTimestampField initialized with val of specified precision +func NewSideTrdRegTimestampWithPrecision(val time.Time, precision quickfix.TimestampPrecision) SideTrdRegTimestampField { + return SideTrdRegTimestampField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f SideTrdRegTimestampField) Value() time.Time { return f.Time } @@ -18155,12 +18250,17 @@ func (f StrikeTimeField) Tag() quickfix.Tag { return tag.StrikeTime } //NewStrikeTime returns a new StrikeTimeField initialized with val func NewStrikeTime(val time.Time) StrikeTimeField { - return StrikeTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewStrikeTimeWithPrecision(val, quickfix.Millis) } //NewStrikeTimeNoMillis returns a new StrikeTimeField initialized with val without millisecs func NewStrikeTimeNoMillis(val time.Time) StrikeTimeField { - return StrikeTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewStrikeTimeWithPrecision(val, quickfix.Seconds) +} + +//NewStrikeTimeWithPrecision returns a new StrikeTimeField initialized with val of specified precision +func NewStrikeTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) StrikeTimeField { + return StrikeTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f StrikeTimeField) Value() time.Time { return f.Time } @@ -18881,12 +18981,17 @@ func (f TradSesCloseTimeField) Tag() quickfix.Tag { return tag.TradSesCloseTime //NewTradSesCloseTime returns a new TradSesCloseTimeField initialized with val func NewTradSesCloseTime(val time.Time) TradSesCloseTimeField { - return TradSesCloseTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewTradSesCloseTimeWithPrecision(val, quickfix.Millis) } //NewTradSesCloseTimeNoMillis returns a new TradSesCloseTimeField initialized with val without millisecs func NewTradSesCloseTimeNoMillis(val time.Time) TradSesCloseTimeField { - return TradSesCloseTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewTradSesCloseTimeWithPrecision(val, quickfix.Seconds) +} + +//NewTradSesCloseTimeWithPrecision returns a new TradSesCloseTimeField initialized with val of specified precision +func NewTradSesCloseTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) TradSesCloseTimeField { + return TradSesCloseTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f TradSesCloseTimeField) Value() time.Time { return f.Time } @@ -18899,12 +19004,17 @@ func (f TradSesEndTimeField) Tag() quickfix.Tag { return tag.TradSesEndTime } //NewTradSesEndTime returns a new TradSesEndTimeField initialized with val func NewTradSesEndTime(val time.Time) TradSesEndTimeField { - return TradSesEndTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewTradSesEndTimeWithPrecision(val, quickfix.Millis) } //NewTradSesEndTimeNoMillis returns a new TradSesEndTimeField initialized with val without millisecs func NewTradSesEndTimeNoMillis(val time.Time) TradSesEndTimeField { - return TradSesEndTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewTradSesEndTimeWithPrecision(val, quickfix.Seconds) +} + +//NewTradSesEndTimeWithPrecision returns a new TradSesEndTimeField initialized with val of specified precision +func NewTradSesEndTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) TradSesEndTimeField { + return TradSesEndTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f TradSesEndTimeField) Value() time.Time { return f.Time } @@ -18953,12 +19063,17 @@ func (f TradSesOpenTimeField) Tag() quickfix.Tag { return tag.TradSesOpenTime } //NewTradSesOpenTime returns a new TradSesOpenTimeField initialized with val func NewTradSesOpenTime(val time.Time) TradSesOpenTimeField { - return TradSesOpenTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewTradSesOpenTimeWithPrecision(val, quickfix.Millis) } //NewTradSesOpenTimeNoMillis returns a new TradSesOpenTimeField initialized with val without millisecs func NewTradSesOpenTimeNoMillis(val time.Time) TradSesOpenTimeField { - return TradSesOpenTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewTradSesOpenTimeWithPrecision(val, quickfix.Seconds) +} + +//NewTradSesOpenTimeWithPrecision returns a new TradSesOpenTimeField initialized with val of specified precision +func NewTradSesOpenTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) TradSesOpenTimeField { + return TradSesOpenTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f TradSesOpenTimeField) Value() time.Time { return f.Time } @@ -18971,12 +19086,17 @@ func (f TradSesPreCloseTimeField) Tag() quickfix.Tag { return tag.TradSesPreClos //NewTradSesPreCloseTime returns a new TradSesPreCloseTimeField initialized with val func NewTradSesPreCloseTime(val time.Time) TradSesPreCloseTimeField { - return TradSesPreCloseTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewTradSesPreCloseTimeWithPrecision(val, quickfix.Millis) } //NewTradSesPreCloseTimeNoMillis returns a new TradSesPreCloseTimeField initialized with val without millisecs func NewTradSesPreCloseTimeNoMillis(val time.Time) TradSesPreCloseTimeField { - return TradSesPreCloseTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewTradSesPreCloseTimeWithPrecision(val, quickfix.Seconds) +} + +//NewTradSesPreCloseTimeWithPrecision returns a new TradSesPreCloseTimeField initialized with val of specified precision +func NewTradSesPreCloseTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) TradSesPreCloseTimeField { + return TradSesPreCloseTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f TradSesPreCloseTimeField) Value() time.Time { return f.Time } @@ -19002,12 +19122,17 @@ func (f TradSesStartTimeField) Tag() quickfix.Tag { return tag.TradSesStartTime //NewTradSesStartTime returns a new TradSesStartTimeField initialized with val func NewTradSesStartTime(val time.Time) TradSesStartTimeField { - return TradSesStartTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewTradSesStartTimeWithPrecision(val, quickfix.Millis) } //NewTradSesStartTimeNoMillis returns a new TradSesStartTimeField initialized with val without millisecs func NewTradSesStartTimeNoMillis(val time.Time) TradSesStartTimeField { - return TradSesStartTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewTradSesStartTimeWithPrecision(val, quickfix.Seconds) +} + +//NewTradSesStartTimeWithPrecision returns a new TradSesStartTimeField initialized with val of specified precision +func NewTradSesStartTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) TradSesStartTimeField { + return TradSesStartTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f TradSesStartTimeField) Value() time.Time { return f.Time } @@ -19426,12 +19551,17 @@ func (f TransBkdTimeField) Tag() quickfix.Tag { return tag.TransBkdTime } //NewTransBkdTime returns a new TransBkdTimeField initialized with val func NewTransBkdTime(val time.Time) TransBkdTimeField { - return TransBkdTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewTransBkdTimeWithPrecision(val, quickfix.Millis) } //NewTransBkdTimeNoMillis returns a new TransBkdTimeField initialized with val without millisecs func NewTransBkdTimeNoMillis(val time.Time) TransBkdTimeField { - return TransBkdTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewTransBkdTimeWithPrecision(val, quickfix.Seconds) +} + +//NewTransBkdTimeWithPrecision returns a new TransBkdTimeField initialized with val of specified precision +func NewTransBkdTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) TransBkdTimeField { + return TransBkdTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f TransBkdTimeField) Value() time.Time { return f.Time } @@ -19444,12 +19574,17 @@ func (f TransactTimeField) Tag() quickfix.Tag { return tag.TransactTime } //NewTransactTime returns a new TransactTimeField initialized with val func NewTransactTime(val time.Time) TransactTimeField { - return TransactTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewTransactTimeWithPrecision(val, quickfix.Millis) } //NewTransactTimeNoMillis returns a new TransactTimeField initialized with val without millisecs func NewTransactTimeNoMillis(val time.Time) TransactTimeField { - return TransactTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewTransactTimeWithPrecision(val, quickfix.Seconds) +} + +//NewTransactTimeWithPrecision returns a new TransactTimeField initialized with val of specified precision +func NewTransactTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) TransactTimeField { + return TransactTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f TransactTimeField) Value() time.Time { return f.Time } @@ -19488,12 +19623,17 @@ func (f TrdRegTimestampField) Tag() quickfix.Tag { return tag.TrdRegTimestamp } //NewTrdRegTimestamp returns a new TrdRegTimestampField initialized with val func NewTrdRegTimestamp(val time.Time) TrdRegTimestampField { - return TrdRegTimestampField{quickfix.FIXUTCTimestamp{Time: val}} + return NewTrdRegTimestampWithPrecision(val, quickfix.Millis) } //NewTrdRegTimestampNoMillis returns a new TrdRegTimestampField initialized with val without millisecs func NewTrdRegTimestampNoMillis(val time.Time) TrdRegTimestampField { - return TrdRegTimestampField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewTrdRegTimestampWithPrecision(val, quickfix.Seconds) +} + +//NewTrdRegTimestampWithPrecision returns a new TrdRegTimestampField initialized with val of specified precision +func NewTrdRegTimestampWithPrecision(val time.Time, precision quickfix.TimestampPrecision) TrdRegTimestampField { + return TrdRegTimestampField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f TrdRegTimestampField) Value() time.Time { return f.Time } @@ -21386,12 +21526,17 @@ func (f ValidUntilTimeField) Tag() quickfix.Tag { return tag.ValidUntilTime } //NewValidUntilTime returns a new ValidUntilTimeField initialized with val func NewValidUntilTime(val time.Time) ValidUntilTimeField { - return ValidUntilTimeField{quickfix.FIXUTCTimestamp{Time: val}} + return NewValidUntilTimeWithPrecision(val, quickfix.Millis) } //NewValidUntilTimeNoMillis returns a new ValidUntilTimeField initialized with val without millisecs func NewValidUntilTimeNoMillis(val time.Time) ValidUntilTimeField { - return ValidUntilTimeField{quickfix.FIXUTCTimestamp{Time: val, NoMillis: true}} + return NewValidUntilTimeWithPrecision(val, quickfix.Seconds) +} + +//NewValidUntilTimeWithPrecision returns a new ValidUntilTimeField initialized with val of specified precision +func NewValidUntilTimeWithPrecision(val time.Time, precision quickfix.TimestampPrecision) ValidUntilTimeField { + return ValidUntilTimeField{quickfix.FIXUTCTimestamp{Time: val, Precision: precision}} } func (f ValidUntilTimeField) Value() time.Time { return f.Time } diff --git a/vendor/github.com/quickfixgo/quickfix/fix40/executionreport/ExecutionReport.generated.go b/vendor/github.com/quickfixgo/fix40/executionreport/ExecutionReport.generated.go similarity index 96% rename from vendor/github.com/quickfixgo/quickfix/fix40/executionreport/ExecutionReport.generated.go rename to vendor/github.com/quickfixgo/fix40/executionreport/ExecutionReport.generated.go index 9e66133..ef91e8d 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix40/executionreport/ExecutionReport.generated.go +++ b/vendor/github.com/quickfixgo/fix40/executionreport/ExecutionReport.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix40" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix40" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //ExecutionReport is the fix40 ExecutionReport type, MsgType = 8 type ExecutionReport struct { fix40.Header - quickfix.Body + *quickfix.Body fix40.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a ExecutionReport from a quickfix.Message instance -func FromMessage(m quickfix.Message) ExecutionReport { +func FromMessage(m *quickfix.Message) ExecutionReport { return ExecutionReport{ - Header: fix40.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix40.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix40.Header{&m.Header}, + Body: &m.Body, + Trailer: fix40.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m ExecutionReport) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m ExecutionReport) ToMessage() *quickfix.Message { + return m.Message } //New returns a ExecutionReport initialized with the required fields for ExecutionReport func New(orderid field.OrderIDField, execid field.ExecIDField, exectranstype field.ExecTransTypeField, ordstatus field.OrdStatusField, symbol field.SymbolField, side field.SideField, orderqty field.OrderQtyField, lastshares field.LastSharesField, lastpx field.LastPxField, cumqty field.CumQtyField, avgpx field.AvgPxField) (m ExecutionReport) { - m.Header = fix40.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix40.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("8")) m.Set(orderid) @@ -67,7 +62,7 @@ type RouteOut func(msg ExecutionReport, sessionID quickfix.SessionID) quickfix.M //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.0", "8", r @@ -928,7 +923,7 @@ func (m ExecutionReport) HasNoMiscFees() bool { //NoMiscFees is a repeating group element, Tag 136 type NoMiscFees struct { - quickfix.Group + *quickfix.Group } //SetMiscFeeAmt sets MiscFeeAmt, Tag 137 diff --git a/vendor/github.com/quickfixgo/quickfix/fix40/header.generated.go b/vendor/github.com/quickfixgo/fix40/header.generated.go similarity index 98% rename from vendor/github.com/quickfixgo/quickfix/fix40/header.generated.go rename to vendor/github.com/quickfixgo/fix40/header.generated.go index cf7c1e2..95986dd 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix40/header.generated.go +++ b/vendor/github.com/quickfixgo/fix40/header.generated.go @@ -3,20 +3,20 @@ package fix40 import ( "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //Header is the fix40 Header type type Header struct { - quickfix.Header + *quickfix.Header } //NewHeader returns a new, initialized Header instance -func NewHeader() (h Header) { - h.Init() +func NewHeader(header *quickfix.Header) (h Header) { + h.Header = header h.SetBeginString("FIX.4.0") return } diff --git a/vendor/github.com/quickfixgo/quickfix/fix40/newordersingle/NewOrderSingle.generated.go b/vendor/github.com/quickfixgo/fix40/newordersingle/NewOrderSingle.generated.go similarity index 95% rename from vendor/github.com/quickfixgo/quickfix/fix40/newordersingle/NewOrderSingle.generated.go rename to vendor/github.com/quickfixgo/fix40/newordersingle/NewOrderSingle.generated.go index 48dd210..6759454 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix40/newordersingle/NewOrderSingle.generated.go +++ b/vendor/github.com/quickfixgo/fix40/newordersingle/NewOrderSingle.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix40" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix40" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //NewOrderSingle is the fix40 NewOrderSingle type, MsgType = D type NewOrderSingle struct { fix40.Header - quickfix.Body + *quickfix.Body fix40.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a NewOrderSingle from a quickfix.Message instance -func FromMessage(m quickfix.Message) NewOrderSingle { +func FromMessage(m *quickfix.Message) NewOrderSingle { return NewOrderSingle{ - Header: fix40.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix40.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix40.Header{&m.Header}, + Body: &m.Body, + Trailer: fix40.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m NewOrderSingle) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m NewOrderSingle) ToMessage() *quickfix.Message { + return m.Message } //New returns a NewOrderSingle initialized with the required fields for NewOrderSingle func New(clordid field.ClOrdIDField, handlinst field.HandlInstField, symbol field.SymbolField, side field.SideField, orderqty field.OrderQtyField, ordtype field.OrdTypeField) (m NewOrderSingle) { - m.Header = fix40.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix40.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("D")) m.Set(clordid) @@ -62,7 +57,7 @@ type RouteOut func(msg NewOrderSingle, sessionID quickfix.SessionID) quickfix.Me //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.0", "D", r diff --git a/vendor/github.com/quickfixgo/quickfix/fix40/ordercancelrequest/OrderCancelRequest.generated.go b/vendor/github.com/quickfixgo/fix40/ordercancelrequest/OrderCancelRequest.generated.go similarity index 91% rename from vendor/github.com/quickfixgo/quickfix/fix40/ordercancelrequest/OrderCancelRequest.generated.go rename to vendor/github.com/quickfixgo/fix40/ordercancelrequest/OrderCancelRequest.generated.go index 064ea5a..9724107 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix40/ordercancelrequest/OrderCancelRequest.generated.go +++ b/vendor/github.com/quickfixgo/fix40/ordercancelrequest/OrderCancelRequest.generated.go @@ -2,49 +2,43 @@ package ordercancelrequest import ( "github.com/shopspring/decimal" - "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix40" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix40" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //OrderCancelRequest is the fix40 OrderCancelRequest type, MsgType = F type OrderCancelRequest struct { fix40.Header - quickfix.Body + *quickfix.Body fix40.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a OrderCancelRequest from a quickfix.Message instance -func FromMessage(m quickfix.Message) OrderCancelRequest { +func FromMessage(m *quickfix.Message) OrderCancelRequest { return OrderCancelRequest{ - Header: fix40.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix40.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix40.Header{&m.Header}, + Body: &m.Body, + Trailer: fix40.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m OrderCancelRequest) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m OrderCancelRequest) ToMessage() *quickfix.Message { + return m.Message } //New returns a OrderCancelRequest initialized with the required fields for OrderCancelRequest func New(origclordid field.OrigClOrdIDField, clordid field.ClOrdIDField, cxltype field.CxlTypeField, symbol field.SymbolField, side field.SideField, orderqty field.OrderQtyField) (m OrderCancelRequest) { - m.Header = fix40.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix40.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("F")) m.Set(origclordid) @@ -62,7 +56,7 @@ type RouteOut func(msg OrderCancelRequest, sessionID quickfix.SessionID) quickfi //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.0", "F", r diff --git a/vendor/github.com/quickfixgo/quickfix/fix40/trailer.generated.go b/vendor/github.com/quickfixgo/fix40/trailer.generated.go similarity index 94% rename from vendor/github.com/quickfixgo/quickfix/fix40/trailer.generated.go rename to vendor/github.com/quickfixgo/fix40/trailer.generated.go index 8e1494c..0398a96 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix40/trailer.generated.go +++ b/vendor/github.com/quickfixgo/fix40/trailer.generated.go @@ -1,14 +1,14 @@ package fix40 import ( + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //Trailer is the fix40 Trailer type type Trailer struct { - quickfix.Trailer + *quickfix.Trailer } //SetCheckSum sets CheckSum, Tag 10 diff --git a/vendor/github.com/quickfixgo/quickfix/fix41/executionreport/ExecutionReport.generated.go b/vendor/github.com/quickfixgo/fix41/executionreport/ExecutionReport.generated.go similarity index 97% rename from vendor/github.com/quickfixgo/quickfix/fix41/executionreport/ExecutionReport.generated.go rename to vendor/github.com/quickfixgo/fix41/executionreport/ExecutionReport.generated.go index 0cc558b..f26e252 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix41/executionreport/ExecutionReport.generated.go +++ b/vendor/github.com/quickfixgo/fix41/executionreport/ExecutionReport.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix41" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix41" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //ExecutionReport is the fix41 ExecutionReport type, MsgType = 8 type ExecutionReport struct { fix41.Header - quickfix.Body + *quickfix.Body fix41.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a ExecutionReport from a quickfix.Message instance -func FromMessage(m quickfix.Message) ExecutionReport { +func FromMessage(m *quickfix.Message) ExecutionReport { return ExecutionReport{ - Header: fix41.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix41.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix41.Header{&m.Header}, + Body: &m.Body, + Trailer: fix41.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m ExecutionReport) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m ExecutionReport) ToMessage() *quickfix.Message { + return m.Message } //New returns a ExecutionReport initialized with the required fields for ExecutionReport func New(orderid field.OrderIDField, execid field.ExecIDField, exectranstype field.ExecTransTypeField, exectype field.ExecTypeField, ordstatus field.OrdStatusField, symbol field.SymbolField, side field.SideField, orderqty field.OrderQtyField, lastshares field.LastSharesField, lastpx field.LastPxField, leavesqty field.LeavesQtyField, cumqty field.CumQtyField, avgpx field.AvgPxField) (m ExecutionReport) { - m.Header = fix41.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix41.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("8")) m.Set(orderid) @@ -69,7 +64,7 @@ type RouteOut func(msg ExecutionReport, sessionID quickfix.SessionID) quickfix.M //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.1", "8", r diff --git a/vendor/github.com/quickfixgo/quickfix/fix41/header.generated.go b/vendor/github.com/quickfixgo/fix41/header.generated.go similarity index 98% rename from vendor/github.com/quickfixgo/quickfix/fix41/header.generated.go rename to vendor/github.com/quickfixgo/fix41/header.generated.go index c65bb45..f8f6aa9 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix41/header.generated.go +++ b/vendor/github.com/quickfixgo/fix41/header.generated.go @@ -3,20 +3,20 @@ package fix41 import ( "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //Header is the fix41 Header type type Header struct { - quickfix.Header + *quickfix.Header } //NewHeader returns a new, initialized Header instance -func NewHeader() (h Header) { - h.Init() +func NewHeader(header *quickfix.Header) (h Header) { + h.Header = header h.SetBeginString("FIX.4.1") return } diff --git a/vendor/github.com/quickfixgo/quickfix/fix41/newordersingle/NewOrderSingle.generated.go b/vendor/github.com/quickfixgo/fix41/newordersingle/NewOrderSingle.generated.go similarity index 96% rename from vendor/github.com/quickfixgo/quickfix/fix41/newordersingle/NewOrderSingle.generated.go rename to vendor/github.com/quickfixgo/fix41/newordersingle/NewOrderSingle.generated.go index c66b69a..42504d9 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix41/newordersingle/NewOrderSingle.generated.go +++ b/vendor/github.com/quickfixgo/fix41/newordersingle/NewOrderSingle.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix41" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix41" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //NewOrderSingle is the fix41 NewOrderSingle type, MsgType = D type NewOrderSingle struct { fix41.Header - quickfix.Body + *quickfix.Body fix41.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a NewOrderSingle from a quickfix.Message instance -func FromMessage(m quickfix.Message) NewOrderSingle { +func FromMessage(m *quickfix.Message) NewOrderSingle { return NewOrderSingle{ - Header: fix41.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix41.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix41.Header{&m.Header}, + Body: &m.Body, + Trailer: fix41.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m NewOrderSingle) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m NewOrderSingle) ToMessage() *quickfix.Message { + return m.Message } //New returns a NewOrderSingle initialized with the required fields for NewOrderSingle func New(clordid field.ClOrdIDField, handlinst field.HandlInstField, symbol field.SymbolField, side field.SideField, ordtype field.OrdTypeField) (m NewOrderSingle) { - m.Header = fix41.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix41.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("D")) m.Set(clordid) @@ -61,7 +56,7 @@ type RouteOut func(msg NewOrderSingle, sessionID quickfix.SessionID) quickfix.Me //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.1", "D", r diff --git a/vendor/github.com/quickfixgo/quickfix/fix41/ordercancelrequest/OrderCancelRequest.generated.go b/vendor/github.com/quickfixgo/fix41/ordercancelrequest/OrderCancelRequest.generated.go similarity index 93% rename from vendor/github.com/quickfixgo/quickfix/fix41/ordercancelrequest/OrderCancelRequest.generated.go rename to vendor/github.com/quickfixgo/fix41/ordercancelrequest/OrderCancelRequest.generated.go index 5b291f4..76f9e7e 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix41/ordercancelrequest/OrderCancelRequest.generated.go +++ b/vendor/github.com/quickfixgo/fix41/ordercancelrequest/OrderCancelRequest.generated.go @@ -2,49 +2,43 @@ package ordercancelrequest import ( "github.com/shopspring/decimal" - "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix41" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix41" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //OrderCancelRequest is the fix41 OrderCancelRequest type, MsgType = F type OrderCancelRequest struct { fix41.Header - quickfix.Body + *quickfix.Body fix41.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a OrderCancelRequest from a quickfix.Message instance -func FromMessage(m quickfix.Message) OrderCancelRequest { +func FromMessage(m *quickfix.Message) OrderCancelRequest { return OrderCancelRequest{ - Header: fix41.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix41.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix41.Header{&m.Header}, + Body: &m.Body, + Trailer: fix41.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m OrderCancelRequest) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m OrderCancelRequest) ToMessage() *quickfix.Message { + return m.Message } //New returns a OrderCancelRequest initialized with the required fields for OrderCancelRequest func New(origclordid field.OrigClOrdIDField, clordid field.ClOrdIDField, symbol field.SymbolField, side field.SideField) (m OrderCancelRequest) { - m.Header = fix41.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix41.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("F")) m.Set(origclordid) @@ -60,7 +54,7 @@ type RouteOut func(msg OrderCancelRequest, sessionID quickfix.SessionID) quickfi //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.1", "F", r diff --git a/vendor/github.com/quickfixgo/quickfix/fix41/trailer.generated.go b/vendor/github.com/quickfixgo/fix41/trailer.generated.go similarity index 94% rename from vendor/github.com/quickfixgo/quickfix/fix41/trailer.generated.go rename to vendor/github.com/quickfixgo/fix41/trailer.generated.go index 3ca0697..b0856ab 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix41/trailer.generated.go +++ b/vendor/github.com/quickfixgo/fix41/trailer.generated.go @@ -1,14 +1,14 @@ package fix41 import ( + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //Trailer is the fix41 Trailer type type Trailer struct { - quickfix.Trailer + *quickfix.Trailer } //SetCheckSum sets CheckSum, Tag 10 diff --git a/vendor/github.com/quickfixgo/quickfix/fix42/executionreport/ExecutionReport.generated.go b/vendor/github.com/quickfixgo/fix42/executionreport/ExecutionReport.generated.go similarity index 98% rename from vendor/github.com/quickfixgo/quickfix/fix42/executionreport/ExecutionReport.generated.go rename to vendor/github.com/quickfixgo/fix42/executionreport/ExecutionReport.generated.go index 12b6abe..eb84ef2 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix42/executionreport/ExecutionReport.generated.go +++ b/vendor/github.com/quickfixgo/fix42/executionreport/ExecutionReport.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix42" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix42" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //ExecutionReport is the fix42 ExecutionReport type, MsgType = 8 type ExecutionReport struct { fix42.Header - quickfix.Body + *quickfix.Body fix42.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a ExecutionReport from a quickfix.Message instance -func FromMessage(m quickfix.Message) ExecutionReport { +func FromMessage(m *quickfix.Message) ExecutionReport { return ExecutionReport{ - Header: fix42.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix42.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix42.Header{&m.Header}, + Body: &m.Body, + Trailer: fix42.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m ExecutionReport) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m ExecutionReport) ToMessage() *quickfix.Message { + return m.Message } //New returns a ExecutionReport initialized with the required fields for ExecutionReport func New(orderid field.OrderIDField, execid field.ExecIDField, exectranstype field.ExecTransTypeField, exectype field.ExecTypeField, ordstatus field.OrdStatusField, symbol field.SymbolField, side field.SideField, leavesqty field.LeavesQtyField, cumqty field.CumQtyField, avgpx field.AvgPxField) (m ExecutionReport) { - m.Header = fix42.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix42.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("8")) m.Set(orderid) @@ -66,7 +61,7 @@ type RouteOut func(msg ExecutionReport, sessionID quickfix.SessionID) quickfix.M //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.2", "8", r @@ -1820,7 +1815,7 @@ func (m ExecutionReport) HasMultiLegReportingType() bool { //NoContraBrokers is a repeating group element, Tag 382 type NoContraBrokers struct { - quickfix.Group + *quickfix.Group } //SetContraBroker sets ContraBroker, Tag 375 diff --git a/vendor/github.com/quickfixgo/quickfix/fix42/header.generated.go b/vendor/github.com/quickfixgo/fix42/header.generated.go similarity index 98% rename from vendor/github.com/quickfixgo/quickfix/fix42/header.generated.go rename to vendor/github.com/quickfixgo/fix42/header.generated.go index 378cfe3..dd0e7ca 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix42/header.generated.go +++ b/vendor/github.com/quickfixgo/fix42/header.generated.go @@ -3,20 +3,20 @@ package fix42 import ( "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //Header is the fix42 Header type type Header struct { - quickfix.Header + *quickfix.Header } //NewHeader returns a new, initialized Header instance -func NewHeader() (h Header) { - h.Init() +func NewHeader(header *quickfix.Header) (h Header) { + h.Header = header h.SetBeginString("FIX.4.2") return } diff --git a/vendor/github.com/quickfixgo/quickfix/fix42/marketdatarequest/MarketDataRequest.generated.go b/vendor/github.com/quickfixgo/fix42/marketdatarequest/MarketDataRequest.generated.go similarity index 95% rename from vendor/github.com/quickfixgo/quickfix/fix42/marketdatarequest/MarketDataRequest.generated.go rename to vendor/github.com/quickfixgo/fix42/marketdatarequest/MarketDataRequest.generated.go index 36e0743..72a23da 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix42/marketdatarequest/MarketDataRequest.generated.go +++ b/vendor/github.com/quickfixgo/fix42/marketdatarequest/MarketDataRequest.generated.go @@ -2,49 +2,43 @@ package marketdatarequest import ( "github.com/shopspring/decimal" - "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix42" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix42" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //MarketDataRequest is the fix42 MarketDataRequest type, MsgType = V type MarketDataRequest struct { fix42.Header - quickfix.Body + *quickfix.Body fix42.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a MarketDataRequest from a quickfix.Message instance -func FromMessage(m quickfix.Message) MarketDataRequest { +func FromMessage(m *quickfix.Message) MarketDataRequest { return MarketDataRequest{ - Header: fix42.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix42.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix42.Header{&m.Header}, + Body: &m.Body, + Trailer: fix42.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m MarketDataRequest) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m MarketDataRequest) ToMessage() *quickfix.Message { + return m.Message } //New returns a MarketDataRequest initialized with the required fields for MarketDataRequest func New(mdreqid field.MDReqIDField, subscriptionrequesttype field.SubscriptionRequestTypeField, marketdepth field.MarketDepthField) (m MarketDataRequest) { - m.Header = fix42.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix42.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("V")) m.Set(mdreqid) @@ -59,7 +53,7 @@ type RouteOut func(msg MarketDataRequest, sessionID quickfix.SessionID) quickfix //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.2", "V", r @@ -196,7 +190,7 @@ func (m MarketDataRequest) HasNoMDEntryTypes() bool { //NoRelatedSym is a repeating group element, Tag 146 type NoRelatedSym struct { - quickfix.Group + *quickfix.Group } //SetSymbol sets Symbol, Tag 55 @@ -604,7 +598,7 @@ func (m NoRelatedSymRepeatingGroup) Get(i int) NoRelatedSym { //NoMDEntryTypes is a repeating group element, Tag 267 type NoMDEntryTypes struct { - quickfix.Group + *quickfix.Group } //SetMDEntryType sets MDEntryType, Tag 269 diff --git a/vendor/github.com/quickfixgo/quickfix/fix42/newordersingle/NewOrderSingle.generated.go b/vendor/github.com/quickfixgo/fix42/newordersingle/NewOrderSingle.generated.go similarity index 97% rename from vendor/github.com/quickfixgo/quickfix/fix42/newordersingle/NewOrderSingle.generated.go rename to vendor/github.com/quickfixgo/fix42/newordersingle/NewOrderSingle.generated.go index d3caf1b..b9f5f5b 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix42/newordersingle/NewOrderSingle.generated.go +++ b/vendor/github.com/quickfixgo/fix42/newordersingle/NewOrderSingle.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix42" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix42" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //NewOrderSingle is the fix42 NewOrderSingle type, MsgType = D type NewOrderSingle struct { fix42.Header - quickfix.Body + *quickfix.Body fix42.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a NewOrderSingle from a quickfix.Message instance -func FromMessage(m quickfix.Message) NewOrderSingle { +func FromMessage(m *quickfix.Message) NewOrderSingle { return NewOrderSingle{ - Header: fix42.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix42.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix42.Header{&m.Header}, + Body: &m.Body, + Trailer: fix42.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m NewOrderSingle) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m NewOrderSingle) ToMessage() *quickfix.Message { + return m.Message } //New returns a NewOrderSingle initialized with the required fields for NewOrderSingle func New(clordid field.ClOrdIDField, handlinst field.HandlInstField, symbol field.SymbolField, side field.SideField, transacttime field.TransactTimeField, ordtype field.OrdTypeField) (m NewOrderSingle) { - m.Header = fix42.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix42.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("D")) m.Set(clordid) @@ -62,7 +57,7 @@ type RouteOut func(msg NewOrderSingle, sessionID quickfix.SessionID) quickfix.Me //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.2", "D", r @@ -1415,7 +1410,7 @@ func (m NewOrderSingle) HasClearingAccount() bool { //NoAllocs is a repeating group element, Tag 78 type NoAllocs struct { - quickfix.Group + *quickfix.Group } //SetAllocAccount sets AllocAccount, Tag 79 @@ -1481,7 +1476,7 @@ func (m NoAllocsRepeatingGroup) Get(i int) NoAllocs { //NoTradingSessions is a repeating group element, Tag 386 type NoTradingSessions struct { - quickfix.Group + *quickfix.Group } //SetTradingSessionID sets TradingSessionID, Tag 336 diff --git a/vendor/github.com/quickfixgo/quickfix/fix42/ordercancelrequest/OrderCancelRequest.generated.go b/vendor/github.com/quickfixgo/fix42/ordercancelrequest/OrderCancelRequest.generated.go similarity index 95% rename from vendor/github.com/quickfixgo/quickfix/fix42/ordercancelrequest/OrderCancelRequest.generated.go rename to vendor/github.com/quickfixgo/fix42/ordercancelrequest/OrderCancelRequest.generated.go index ab4cccd..b2142ed 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix42/ordercancelrequest/OrderCancelRequest.generated.go +++ b/vendor/github.com/quickfixgo/fix42/ordercancelrequest/OrderCancelRequest.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix42" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix42" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //OrderCancelRequest is the fix42 OrderCancelRequest type, MsgType = F type OrderCancelRequest struct { fix42.Header - quickfix.Body + *quickfix.Body fix42.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a OrderCancelRequest from a quickfix.Message instance -func FromMessage(m quickfix.Message) OrderCancelRequest { +func FromMessage(m *quickfix.Message) OrderCancelRequest { return OrderCancelRequest{ - Header: fix42.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix42.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix42.Header{&m.Header}, + Body: &m.Body, + Trailer: fix42.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m OrderCancelRequest) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m OrderCancelRequest) ToMessage() *quickfix.Message { + return m.Message } //New returns a OrderCancelRequest initialized with the required fields for OrderCancelRequest func New(origclordid field.OrigClOrdIDField, clordid field.ClOrdIDField, symbol field.SymbolField, side field.SideField, transacttime field.TransactTimeField) (m OrderCancelRequest) { - m.Header = fix42.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix42.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("F")) m.Set(origclordid) @@ -61,7 +56,7 @@ type RouteOut func(msg OrderCancelRequest, sessionID quickfix.SessionID) quickfi //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.2", "F", r diff --git a/vendor/github.com/quickfixgo/quickfix/fix42/trailer.generated.go b/vendor/github.com/quickfixgo/fix42/trailer.generated.go similarity index 94% rename from vendor/github.com/quickfixgo/quickfix/fix42/trailer.generated.go rename to vendor/github.com/quickfixgo/fix42/trailer.generated.go index 32fabb5..9dcfa70 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix42/trailer.generated.go +++ b/vendor/github.com/quickfixgo/fix42/trailer.generated.go @@ -1,14 +1,14 @@ package fix42 import ( + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //Trailer is the fix42 Trailer type type Trailer struct { - quickfix.Trailer + *quickfix.Trailer } //SetCheckSum sets CheckSum, Tag 10 diff --git a/vendor/github.com/quickfixgo/quickfix/fix43/executionreport/ExecutionReport.generated.go b/vendor/github.com/quickfixgo/fix43/executionreport/ExecutionReport.generated.go similarity index 99% rename from vendor/github.com/quickfixgo/quickfix/fix43/executionreport/ExecutionReport.generated.go rename to vendor/github.com/quickfixgo/fix43/executionreport/ExecutionReport.generated.go index 79c8472..0d07dbc 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix43/executionreport/ExecutionReport.generated.go +++ b/vendor/github.com/quickfixgo/fix43/executionreport/ExecutionReport.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix43" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix43" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //ExecutionReport is the fix43 ExecutionReport type, MsgType = 8 type ExecutionReport struct { fix43.Header - quickfix.Body + *quickfix.Body fix43.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a ExecutionReport from a quickfix.Message instance -func FromMessage(m quickfix.Message) ExecutionReport { +func FromMessage(m *quickfix.Message) ExecutionReport { return ExecutionReport{ - Header: fix43.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix43.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix43.Header{&m.Header}, + Body: &m.Body, + Trailer: fix43.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m ExecutionReport) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m ExecutionReport) ToMessage() *quickfix.Message { + return m.Message } //New returns a ExecutionReport initialized with the required fields for ExecutionReport func New(orderid field.OrderIDField, execid field.ExecIDField, exectype field.ExecTypeField, ordstatus field.OrdStatusField, side field.SideField, leavesqty field.LeavesQtyField, cumqty field.CumQtyField, avgpx field.AvgPxField) (m ExecutionReport) { - m.Header = fix43.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix43.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("8")) m.Set(orderid) @@ -64,7 +59,7 @@ type RouteOut func(msg ExecutionReport, sessionID quickfix.SessionID) quickfix.M //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.3", "8", r @@ -3081,7 +3076,7 @@ func (m ExecutionReport) HasUnderlyingLastQty() bool { //NoStipulations is a repeating group element, Tag 232 type NoStipulations struct { - quickfix.Group + *quickfix.Group } //SetStipulationType sets StipulationType, Tag 233 @@ -3147,7 +3142,7 @@ func (m NoStipulationsRepeatingGroup) Get(i int) NoStipulations { //NoContraBrokers is a repeating group element, Tag 382 type NoContraBrokers struct { - quickfix.Group + *quickfix.Group } //SetContraBroker sets ContraBroker, Tag 375 @@ -3270,7 +3265,7 @@ func (m NoContraBrokersRepeatingGroup) Get(i int) NoContraBrokers { //NoPartyIDs is a repeating group element, Tag 453 type NoPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetPartyID sets PartyID, Tag 448 @@ -3374,7 +3369,7 @@ func (m NoPartyIDsRepeatingGroup) Get(i int) NoPartyIDs { //NoSecurityAltID is a repeating group element, Tag 454 type NoSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetSecurityAltID sets SecurityAltID, Tag 455 @@ -3440,7 +3435,7 @@ func (m NoSecurityAltIDRepeatingGroup) Get(i int) NoSecurityAltID { //NoContAmts is a repeating group element, Tag 518 type NoContAmts struct { - quickfix.Group + *quickfix.Group } //SetContAmtType sets ContAmtType, Tag 519 @@ -3525,7 +3520,7 @@ func (m NoContAmtsRepeatingGroup) Get(i int) NoContAmts { //NoLegs is a repeating group element, Tag 555 type NoLegs struct { - quickfix.Group + *quickfix.Group } //SetLegSymbol sets LegSymbol, Tag 600 @@ -4343,7 +4338,7 @@ func (m NoLegs) HasLegLastPx() bool { //NoLegSecurityAltID is a repeating group element, Tag 604 type NoLegSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetLegSecurityAltID sets LegSecurityAltID, Tag 605 @@ -4409,7 +4404,7 @@ func (m NoLegSecurityAltIDRepeatingGroup) Get(i int) NoLegSecurityAltID { //NoNestedPartyIDs is a repeating group element, Tag 539 type NoNestedPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetNestedPartyID sets NestedPartyID, Tag 524 diff --git a/vendor/github.com/quickfixgo/quickfix/fix43/header.generated.go b/vendor/github.com/quickfixgo/fix43/header.generated.go similarity index 98% rename from vendor/github.com/quickfixgo/quickfix/fix43/header.generated.go rename to vendor/github.com/quickfixgo/fix43/header.generated.go index f50e797..e466cb7 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix43/header.generated.go +++ b/vendor/github.com/quickfixgo/fix43/header.generated.go @@ -3,20 +3,20 @@ package fix43 import ( "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //Header is the fix43 Header type type Header struct { - quickfix.Header + *quickfix.Header } //NewHeader returns a new, initialized Header instance -func NewHeader() (h Header) { - h.Init() +func NewHeader(header *quickfix.Header) (h Header) { + h.Header = header h.SetBeginString("FIX.4.3") return } @@ -553,7 +553,7 @@ func (h Header) HasNoHops() bool { //NoHops is a repeating group element, Tag 627 type NoHops struct { - quickfix.Group + *quickfix.Group } //SetHopCompID sets HopCompID, Tag 628 diff --git a/vendor/github.com/quickfixgo/quickfix/fix43/marketdatarequest/MarketDataRequest.generated.go b/vendor/github.com/quickfixgo/fix43/marketdatarequest/MarketDataRequest.generated.go similarity index 97% rename from vendor/github.com/quickfixgo/quickfix/fix43/marketdatarequest/MarketDataRequest.generated.go rename to vendor/github.com/quickfixgo/fix43/marketdatarequest/MarketDataRequest.generated.go index bea7ba5..ba6f003 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix43/marketdatarequest/MarketDataRequest.generated.go +++ b/vendor/github.com/quickfixgo/fix43/marketdatarequest/MarketDataRequest.generated.go @@ -2,49 +2,43 @@ package marketdatarequest import ( "github.com/shopspring/decimal" - "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix43" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix43" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //MarketDataRequest is the fix43 MarketDataRequest type, MsgType = V type MarketDataRequest struct { fix43.Header - quickfix.Body + *quickfix.Body fix43.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a MarketDataRequest from a quickfix.Message instance -func FromMessage(m quickfix.Message) MarketDataRequest { +func FromMessage(m *quickfix.Message) MarketDataRequest { return MarketDataRequest{ - Header: fix43.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix43.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix43.Header{&m.Header}, + Body: &m.Body, + Trailer: fix43.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m MarketDataRequest) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m MarketDataRequest) ToMessage() *quickfix.Message { + return m.Message } //New returns a MarketDataRequest initialized with the required fields for MarketDataRequest func New(mdreqid field.MDReqIDField, subscriptionrequesttype field.SubscriptionRequestTypeField, marketdepth field.MarketDepthField) (m MarketDataRequest) { - m.Header = fix43.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix43.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("V")) m.Set(mdreqid) @@ -59,7 +53,7 @@ type RouteOut func(msg MarketDataRequest, sessionID quickfix.SessionID) quickfix //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.3", "V", r @@ -270,7 +264,7 @@ func (m MarketDataRequest) HasMDImplicitDelete() bool { //NoRelatedSym is a repeating group element, Tag 146 type NoRelatedSym struct { - quickfix.Group + *quickfix.Group } //SetSymbol sets Symbol, Tag 55 @@ -900,7 +894,7 @@ func (m NoRelatedSym) HasEncodedSecurityDesc() bool { //NoSecurityAltID is a repeating group element, Tag 454 type NoSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetSecurityAltID sets SecurityAltID, Tag 455 @@ -989,7 +983,7 @@ func (m NoRelatedSymRepeatingGroup) Get(i int) NoRelatedSym { //NoMDEntryTypes is a repeating group element, Tag 267 type NoMDEntryTypes struct { - quickfix.Group + *quickfix.Group } //SetMDEntryType sets MDEntryType, Tag 269 @@ -1036,7 +1030,7 @@ func (m NoMDEntryTypesRepeatingGroup) Get(i int) NoMDEntryTypes { //NoTradingSessions is a repeating group element, Tag 386 type NoTradingSessions struct { - quickfix.Group + *quickfix.Group } //SetTradingSessionID sets TradingSessionID, Tag 336 diff --git a/vendor/github.com/quickfixgo/quickfix/fix43/newordersingle/NewOrderSingle.generated.go b/vendor/github.com/quickfixgo/fix43/newordersingle/NewOrderSingle.generated.go similarity index 98% rename from vendor/github.com/quickfixgo/quickfix/fix43/newordersingle/NewOrderSingle.generated.go rename to vendor/github.com/quickfixgo/fix43/newordersingle/NewOrderSingle.generated.go index fde839a..c1aaf4c 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix43/newordersingle/NewOrderSingle.generated.go +++ b/vendor/github.com/quickfixgo/fix43/newordersingle/NewOrderSingle.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix43" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix43" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //NewOrderSingle is the fix43 NewOrderSingle type, MsgType = D type NewOrderSingle struct { fix43.Header - quickfix.Body + *quickfix.Body fix43.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a NewOrderSingle from a quickfix.Message instance -func FromMessage(m quickfix.Message) NewOrderSingle { +func FromMessage(m *quickfix.Message) NewOrderSingle { return NewOrderSingle{ - Header: fix43.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix43.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix43.Header{&m.Header}, + Body: &m.Body, + Trailer: fix43.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m NewOrderSingle) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m NewOrderSingle) ToMessage() *quickfix.Message { + return m.Message } //New returns a NewOrderSingle initialized with the required fields for NewOrderSingle func New(clordid field.ClOrdIDField, handlinst field.HandlInstField, side field.SideField, transacttime field.TransactTimeField, ordtype field.OrdTypeField) (m NewOrderSingle) { - m.Header = fix43.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix43.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("D")) m.Set(clordid) @@ -61,7 +56,7 @@ type RouteOut func(msg NewOrderSingle, sessionID quickfix.SessionID) quickfix.Me //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.3", "D", r @@ -2244,7 +2239,7 @@ func (m NewOrderSingle) HasPrice2() bool { //NoAllocs is a repeating group element, Tag 78 type NoAllocs struct { - quickfix.Group + *quickfix.Group } //SetAllocAccount sets AllocAccount, Tag 79 @@ -2323,7 +2318,7 @@ func (m NoAllocs) HasAllocQty() bool { //NoNestedPartyIDs is a repeating group element, Tag 539 type NoNestedPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetNestedPartyID sets NestedPartyID, Tag 524 @@ -2450,7 +2445,7 @@ func (m NoAllocsRepeatingGroup) Get(i int) NoAllocs { //NoStipulations is a repeating group element, Tag 232 type NoStipulations struct { - quickfix.Group + *quickfix.Group } //SetStipulationType sets StipulationType, Tag 233 @@ -2516,7 +2511,7 @@ func (m NoStipulationsRepeatingGroup) Get(i int) NoStipulations { //NoTradingSessions is a repeating group element, Tag 386 type NoTradingSessions struct { - quickfix.Group + *quickfix.Group } //SetTradingSessionID sets TradingSessionID, Tag 336 @@ -2582,7 +2577,7 @@ func (m NoTradingSessionsRepeatingGroup) Get(i int) NoTradingSessions { //NoPartyIDs is a repeating group element, Tag 453 type NoPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetPartyID sets PartyID, Tag 448 @@ -2686,7 +2681,7 @@ func (m NoPartyIDsRepeatingGroup) Get(i int) NoPartyIDs { //NoSecurityAltID is a repeating group element, Tag 454 type NoSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetSecurityAltID sets SecurityAltID, Tag 455 diff --git a/vendor/github.com/quickfixgo/quickfix/fix43/ordercancelrequest/OrderCancelRequest.generated.go b/vendor/github.com/quickfixgo/fix43/ordercancelrequest/OrderCancelRequest.generated.go similarity index 97% rename from vendor/github.com/quickfixgo/quickfix/fix43/ordercancelrequest/OrderCancelRequest.generated.go rename to vendor/github.com/quickfixgo/fix43/ordercancelrequest/OrderCancelRequest.generated.go index 35a786b..2d44cc2 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix43/ordercancelrequest/OrderCancelRequest.generated.go +++ b/vendor/github.com/quickfixgo/fix43/ordercancelrequest/OrderCancelRequest.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix43" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix43" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //OrderCancelRequest is the fix43 OrderCancelRequest type, MsgType = F type OrderCancelRequest struct { fix43.Header - quickfix.Body + *quickfix.Body fix43.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a OrderCancelRequest from a quickfix.Message instance -func FromMessage(m quickfix.Message) OrderCancelRequest { +func FromMessage(m *quickfix.Message) OrderCancelRequest { return OrderCancelRequest{ - Header: fix43.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix43.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix43.Header{&m.Header}, + Body: &m.Body, + Trailer: fix43.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m OrderCancelRequest) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m OrderCancelRequest) ToMessage() *quickfix.Message { + return m.Message } //New returns a OrderCancelRequest initialized with the required fields for OrderCancelRequest func New(origclordid field.OrigClOrdIDField, clordid field.ClOrdIDField, side field.SideField, transacttime field.TransactTimeField) (m OrderCancelRequest) { - m.Header = fix43.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix43.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("F")) m.Set(origclordid) @@ -60,7 +55,7 @@ type RouteOut func(msg OrderCancelRequest, sessionID quickfix.SessionID) quickfi //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.3", "F", r @@ -1090,7 +1085,7 @@ func (m OrderCancelRequest) HasOrigOrdModTime() bool { //NoPartyIDs is a repeating group element, Tag 453 type NoPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetPartyID sets PartyID, Tag 448 @@ -1194,7 +1189,7 @@ func (m NoPartyIDsRepeatingGroup) Get(i int) NoPartyIDs { //NoSecurityAltID is a repeating group element, Tag 454 type NoSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetSecurityAltID sets SecurityAltID, Tag 455 diff --git a/vendor/github.com/quickfixgo/quickfix/fix43/trailer.generated.go b/vendor/github.com/quickfixgo/fix43/trailer.generated.go similarity index 94% rename from vendor/github.com/quickfixgo/quickfix/fix43/trailer.generated.go rename to vendor/github.com/quickfixgo/fix43/trailer.generated.go index eb6c80a..b09be02 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix43/trailer.generated.go +++ b/vendor/github.com/quickfixgo/fix43/trailer.generated.go @@ -1,14 +1,14 @@ package fix43 import ( + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //Trailer is the fix43 Trailer type type Trailer struct { - quickfix.Trailer + *quickfix.Trailer } //SetCheckSum sets CheckSum, Tag 10 diff --git a/vendor/github.com/quickfixgo/quickfix/fix44/executionreport/ExecutionReport.generated.go b/vendor/github.com/quickfixgo/fix44/executionreport/ExecutionReport.generated.go similarity index 99% rename from vendor/github.com/quickfixgo/quickfix/fix44/executionreport/ExecutionReport.generated.go rename to vendor/github.com/quickfixgo/fix44/executionreport/ExecutionReport.generated.go index ec06eed..c005d68 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix44/executionreport/ExecutionReport.generated.go +++ b/vendor/github.com/quickfixgo/fix44/executionreport/ExecutionReport.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix44" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix44" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //ExecutionReport is the fix44 ExecutionReport type, MsgType = 8 type ExecutionReport struct { fix44.Header - quickfix.Body + *quickfix.Body fix44.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a ExecutionReport from a quickfix.Message instance -func FromMessage(m quickfix.Message) ExecutionReport { +func FromMessage(m *quickfix.Message) ExecutionReport { return ExecutionReport{ - Header: fix44.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix44.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix44.Header{&m.Header}, + Body: &m.Body, + Trailer: fix44.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m ExecutionReport) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m ExecutionReport) ToMessage() *quickfix.Message { + return m.Message } //New returns a ExecutionReport initialized with the required fields for ExecutionReport func New(orderid field.OrderIDField, execid field.ExecIDField, exectype field.ExecTypeField, ordstatus field.OrdStatusField, side field.SideField, leavesqty field.LeavesQtyField, cumqty field.CumQtyField, avgpx field.AvgPxField) (m ExecutionReport) { - m.Header = fix44.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix44.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("8")) m.Set(orderid) @@ -64,7 +59,7 @@ type RouteOut func(msg ExecutionReport, sessionID quickfix.SessionID) quickfix.M //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.4", "8", r @@ -4177,7 +4172,7 @@ func (m ExecutionReport) HasStrikeCurrency() bool { //NoMiscFees is a repeating group element, Tag 136 type NoMiscFees struct { - quickfix.Group + *quickfix.Group } //SetMiscFeeAmt sets MiscFeeAmt, Tag 137 @@ -4281,7 +4276,7 @@ func (m NoMiscFeesRepeatingGroup) Get(i int) NoMiscFees { //NoStipulations is a repeating group element, Tag 232 type NoStipulations struct { - quickfix.Group + *quickfix.Group } //SetStipulationType sets StipulationType, Tag 233 @@ -4347,7 +4342,7 @@ func (m NoStipulationsRepeatingGroup) Get(i int) NoStipulations { //NoContraBrokers is a repeating group element, Tag 382 type NoContraBrokers struct { - quickfix.Group + *quickfix.Group } //SetContraBroker sets ContraBroker, Tag 375 @@ -4470,7 +4465,7 @@ func (m NoContraBrokersRepeatingGroup) Get(i int) NoContraBrokers { //NoPartyIDs is a repeating group element, Tag 453 type NoPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetPartyID sets PartyID, Tag 448 @@ -4549,7 +4544,7 @@ func (m NoPartyIDs) HasNoPartySubIDs() bool { //NoPartySubIDs is a repeating group element, Tag 802 type NoPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetPartySubID sets PartySubID, Tag 523 @@ -4638,7 +4633,7 @@ func (m NoPartyIDsRepeatingGroup) Get(i int) NoPartyIDs { //NoSecurityAltID is a repeating group element, Tag 454 type NoSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetSecurityAltID sets SecurityAltID, Tag 455 @@ -4704,7 +4699,7 @@ func (m NoSecurityAltIDRepeatingGroup) Get(i int) NoSecurityAltID { //NoContAmts is a repeating group element, Tag 518 type NoContAmts struct { - quickfix.Group + *quickfix.Group } //SetContAmtType sets ContAmtType, Tag 519 @@ -4789,7 +4784,7 @@ func (m NoContAmtsRepeatingGroup) Get(i int) NoContAmts { //NoLegs is a repeating group element, Tag 555 type NoLegs struct { - quickfix.Group + *quickfix.Group } //SetLegSymbol sets LegSymbol, Tag 600 @@ -5795,7 +5790,7 @@ func (m NoLegs) HasLegLastPx() bool { //NoLegSecurityAltID is a repeating group element, Tag 604 type NoLegSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetLegSecurityAltID sets LegSecurityAltID, Tag 605 @@ -5861,7 +5856,7 @@ func (m NoLegSecurityAltIDRepeatingGroup) Get(i int) NoLegSecurityAltID { //NoLegStipulations is a repeating group element, Tag 683 type NoLegStipulations struct { - quickfix.Group + *quickfix.Group } //SetLegStipulationType sets LegStipulationType, Tag 688 @@ -5927,7 +5922,7 @@ func (m NoLegStipulationsRepeatingGroup) Get(i int) NoLegStipulations { //NoNestedPartyIDs is a repeating group element, Tag 539 type NoNestedPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetNestedPartyID sets NestedPartyID, Tag 524 @@ -6006,7 +6001,7 @@ func (m NoNestedPartyIDs) HasNoNestedPartySubIDs() bool { //NoNestedPartySubIDs is a repeating group element, Tag 804 type NoNestedPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetNestedPartySubID sets NestedPartySubID, Tag 545 @@ -6118,7 +6113,7 @@ func (m NoLegsRepeatingGroup) Get(i int) NoLegs { //NoUnderlyings is a repeating group element, Tag 711 type NoUnderlyings struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSymbol sets UnderlyingSymbol, Tag 311 @@ -6993,7 +6988,7 @@ func (m NoUnderlyings) HasNoUnderlyingStips() bool { //NoUnderlyingSecurityAltID is a repeating group element, Tag 457 type NoUnderlyingSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSecurityAltID sets UnderlyingSecurityAltID, Tag 458 @@ -7059,7 +7054,7 @@ func (m NoUnderlyingSecurityAltIDRepeatingGroup) Get(i int) NoUnderlyingSecurity //NoUnderlyingStips is a repeating group element, Tag 887 type NoUnderlyingStips struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingStipType sets UnderlyingStipType, Tag 888 @@ -7148,7 +7143,7 @@ func (m NoUnderlyingsRepeatingGroup) Get(i int) NoUnderlyings { //NoEvents is a repeating group element, Tag 864 type NoEvents struct { - quickfix.Group + *quickfix.Group } //SetEventType sets EventType, Tag 865 diff --git a/vendor/github.com/quickfixgo/quickfix/fix44/header.generated.go b/vendor/github.com/quickfixgo/fix44/header.generated.go similarity index 98% rename from vendor/github.com/quickfixgo/quickfix/fix44/header.generated.go rename to vendor/github.com/quickfixgo/fix44/header.generated.go index 1e00691..5df6a19 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix44/header.generated.go +++ b/vendor/github.com/quickfixgo/fix44/header.generated.go @@ -3,20 +3,20 @@ package fix44 import ( "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //Header is the fix44 Header type type Header struct { - quickfix.Header + *quickfix.Header } //NewHeader returns a new, initialized Header instance -func NewHeader() (h Header) { - h.Init() +func NewHeader(header *quickfix.Header) (h Header) { + h.Header = header h.SetBeginString("FIX.4.4") return } @@ -534,7 +534,7 @@ func (h Header) HasNoHops() bool { //NoHops is a repeating group element, Tag 627 type NoHops struct { - quickfix.Group + *quickfix.Group } //SetHopCompID sets HopCompID, Tag 628 diff --git a/vendor/github.com/quickfixgo/quickfix/fix44/marketdatarequest/MarketDataRequest.generated.go b/vendor/github.com/quickfixgo/fix44/marketdatarequest/MarketDataRequest.generated.go similarity index 99% rename from vendor/github.com/quickfixgo/quickfix/fix44/marketdatarequest/MarketDataRequest.generated.go rename to vendor/github.com/quickfixgo/fix44/marketdatarequest/MarketDataRequest.generated.go index 0f81e15..95093a9 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix44/marketdatarequest/MarketDataRequest.generated.go +++ b/vendor/github.com/quickfixgo/fix44/marketdatarequest/MarketDataRequest.generated.go @@ -2,49 +2,43 @@ package marketdatarequest import ( "github.com/shopspring/decimal" - "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix44" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix44" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //MarketDataRequest is the fix44 MarketDataRequest type, MsgType = V type MarketDataRequest struct { fix44.Header - quickfix.Body + *quickfix.Body fix44.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a MarketDataRequest from a quickfix.Message instance -func FromMessage(m quickfix.Message) MarketDataRequest { +func FromMessage(m *quickfix.Message) MarketDataRequest { return MarketDataRequest{ - Header: fix44.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix44.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix44.Header{&m.Header}, + Body: &m.Body, + Trailer: fix44.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m MarketDataRequest) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m MarketDataRequest) ToMessage() *quickfix.Message { + return m.Message } //New returns a MarketDataRequest initialized with the required fields for MarketDataRequest func New(mdreqid field.MDReqIDField, subscriptionrequesttype field.SubscriptionRequestTypeField, marketdepth field.MarketDepthField) (m MarketDataRequest) { - m.Header = fix44.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix44.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("V")) m.Set(mdreqid) @@ -59,7 +53,7 @@ type RouteOut func(msg MarketDataRequest, sessionID quickfix.SessionID) quickfix //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.4", "V", r @@ -253,7 +247,7 @@ func (m MarketDataRequest) HasMDImplicitDelete() bool { //NoRelatedSym is a repeating group element, Tag 146 type NoRelatedSym struct { - quickfix.Group + *quickfix.Group } //SetSymbol sets Symbol, Tag 55 @@ -1141,7 +1135,7 @@ func (m NoRelatedSym) HasApplQueueMax() bool { //NoSecurityAltID is a repeating group element, Tag 454 type NoSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetSecurityAltID sets SecurityAltID, Tag 455 @@ -1207,7 +1201,7 @@ func (m NoSecurityAltIDRepeatingGroup) Get(i int) NoSecurityAltID { //NoEvents is a repeating group element, Tag 864 type NoEvents struct { - quickfix.Group + *quickfix.Group } //SetEventType sets EventType, Tag 865 @@ -1311,7 +1305,7 @@ func (m NoEventsRepeatingGroup) Get(i int) NoEvents { //NoUnderlyings is a repeating group element, Tag 711 type NoUnderlyings struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSymbol sets UnderlyingSymbol, Tag 311 @@ -2186,7 +2180,7 @@ func (m NoUnderlyings) HasNoUnderlyingStips() bool { //NoUnderlyingSecurityAltID is a repeating group element, Tag 457 type NoUnderlyingSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSecurityAltID sets UnderlyingSecurityAltID, Tag 458 @@ -2252,7 +2246,7 @@ func (m NoUnderlyingSecurityAltIDRepeatingGroup) Get(i int) NoUnderlyingSecurity //NoUnderlyingStips is a repeating group element, Tag 887 type NoUnderlyingStips struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingStipType sets UnderlyingStipType, Tag 888 @@ -2341,7 +2335,7 @@ func (m NoUnderlyingsRepeatingGroup) Get(i int) NoUnderlyings { //NoLegs is a repeating group element, Tag 555 type NoLegs struct { - quickfix.Group + *quickfix.Group } //SetLegSymbol sets LegSymbol, Tag 600 @@ -3142,7 +3136,7 @@ func (m NoLegs) HasLegInterestAccrualDate() bool { //NoLegSecurityAltID is a repeating group element, Tag 604 type NoLegSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetLegSecurityAltID sets LegSecurityAltID, Tag 605 @@ -3231,7 +3225,7 @@ func (m NoLegsRepeatingGroup) Get(i int) NoLegs { //NoTradingSessions is a repeating group element, Tag 386 type NoTradingSessions struct { - quickfix.Group + *quickfix.Group } //SetTradingSessionID sets TradingSessionID, Tag 336 @@ -3320,7 +3314,7 @@ func (m NoRelatedSymRepeatingGroup) Get(i int) NoRelatedSym { //NoMDEntryTypes is a repeating group element, Tag 267 type NoMDEntryTypes struct { - quickfix.Group + *quickfix.Group } //SetMDEntryType sets MDEntryType, Tag 269 diff --git a/vendor/github.com/quickfixgo/quickfix/fix44/newordersingle/NewOrderSingle.generated.go b/vendor/github.com/quickfixgo/fix44/newordersingle/NewOrderSingle.generated.go similarity index 99% rename from vendor/github.com/quickfixgo/quickfix/fix44/newordersingle/NewOrderSingle.generated.go rename to vendor/github.com/quickfixgo/fix44/newordersingle/NewOrderSingle.generated.go index 7f02320..b9ba34c 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix44/newordersingle/NewOrderSingle.generated.go +++ b/vendor/github.com/quickfixgo/fix44/newordersingle/NewOrderSingle.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix44" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix44" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //NewOrderSingle is the fix44 NewOrderSingle type, MsgType = D type NewOrderSingle struct { fix44.Header - quickfix.Body + *quickfix.Body fix44.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a NewOrderSingle from a quickfix.Message instance -func FromMessage(m quickfix.Message) NewOrderSingle { +func FromMessage(m *quickfix.Message) NewOrderSingle { return NewOrderSingle{ - Header: fix44.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix44.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix44.Header{&m.Header}, + Body: &m.Body, + Trailer: fix44.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m NewOrderSingle) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m NewOrderSingle) ToMessage() *quickfix.Message { + return m.Message } //New returns a NewOrderSingle initialized with the required fields for NewOrderSingle func New(clordid field.ClOrdIDField, side field.SideField, transacttime field.TransactTimeField, ordtype field.OrdTypeField) (m NewOrderSingle) { - m.Header = fix44.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix44.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("D")) m.Set(clordid) @@ -60,7 +55,7 @@ type RouteOut func(msg NewOrderSingle, sessionID quickfix.SessionID) quickfix.Me //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.4", "D", r @@ -2999,7 +2994,7 @@ func (m NewOrderSingle) HasStrikeCurrency() bool { //NoAllocs is a repeating group element, Tag 78 type NoAllocs struct { - quickfix.Group + *quickfix.Group } //SetAllocAccount sets AllocAccount, Tag 79 @@ -3116,7 +3111,7 @@ func (m NoAllocs) HasAllocQty() bool { //NoNestedPartyIDs is a repeating group element, Tag 539 type NoNestedPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetNestedPartyID sets NestedPartyID, Tag 524 @@ -3195,7 +3190,7 @@ func (m NoNestedPartyIDs) HasNoNestedPartySubIDs() bool { //NoNestedPartySubIDs is a repeating group element, Tag 804 type NoNestedPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetNestedPartySubID sets NestedPartySubID, Tag 545 @@ -3307,7 +3302,7 @@ func (m NoAllocsRepeatingGroup) Get(i int) NoAllocs { //NoStipulations is a repeating group element, Tag 232 type NoStipulations struct { - quickfix.Group + *quickfix.Group } //SetStipulationType sets StipulationType, Tag 233 @@ -3373,7 +3368,7 @@ func (m NoStipulationsRepeatingGroup) Get(i int) NoStipulations { //NoTradingSessions is a repeating group element, Tag 386 type NoTradingSessions struct { - quickfix.Group + *quickfix.Group } //SetTradingSessionID sets TradingSessionID, Tag 336 @@ -3439,7 +3434,7 @@ func (m NoTradingSessionsRepeatingGroup) Get(i int) NoTradingSessions { //NoPartyIDs is a repeating group element, Tag 453 type NoPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetPartyID sets PartyID, Tag 448 @@ -3518,7 +3513,7 @@ func (m NoPartyIDs) HasNoPartySubIDs() bool { //NoPartySubIDs is a repeating group element, Tag 802 type NoPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetPartySubID sets PartySubID, Tag 523 @@ -3607,7 +3602,7 @@ func (m NoPartyIDsRepeatingGroup) Get(i int) NoPartyIDs { //NoSecurityAltID is a repeating group element, Tag 454 type NoSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetSecurityAltID sets SecurityAltID, Tag 455 @@ -3673,7 +3668,7 @@ func (m NoSecurityAltIDRepeatingGroup) Get(i int) NoSecurityAltID { //NoUnderlyings is a repeating group element, Tag 711 type NoUnderlyings struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSymbol sets UnderlyingSymbol, Tag 311 @@ -4548,7 +4543,7 @@ func (m NoUnderlyings) HasNoUnderlyingStips() bool { //NoUnderlyingSecurityAltID is a repeating group element, Tag 457 type NoUnderlyingSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSecurityAltID sets UnderlyingSecurityAltID, Tag 458 @@ -4614,7 +4609,7 @@ func (m NoUnderlyingSecurityAltIDRepeatingGroup) Get(i int) NoUnderlyingSecurity //NoUnderlyingStips is a repeating group element, Tag 887 type NoUnderlyingStips struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingStipType sets UnderlyingStipType, Tag 888 @@ -4703,7 +4698,7 @@ func (m NoUnderlyingsRepeatingGroup) Get(i int) NoUnderlyings { //NoEvents is a repeating group element, Tag 864 type NoEvents struct { - quickfix.Group + *quickfix.Group } //SetEventType sets EventType, Tag 865 diff --git a/vendor/github.com/quickfixgo/quickfix/fix44/ordercancelrequest/OrderCancelRequest.generated.go b/vendor/github.com/quickfixgo/fix44/ordercancelrequest/OrderCancelRequest.generated.go similarity index 98% rename from vendor/github.com/quickfixgo/quickfix/fix44/ordercancelrequest/OrderCancelRequest.generated.go rename to vendor/github.com/quickfixgo/fix44/ordercancelrequest/OrderCancelRequest.generated.go index adaf4bf..5befdcc 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix44/ordercancelrequest/OrderCancelRequest.generated.go +++ b/vendor/github.com/quickfixgo/fix44/ordercancelrequest/OrderCancelRequest.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix44" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fix44" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //OrderCancelRequest is the fix44 OrderCancelRequest type, MsgType = F type OrderCancelRequest struct { fix44.Header - quickfix.Body + *quickfix.Body fix44.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a OrderCancelRequest from a quickfix.Message instance -func FromMessage(m quickfix.Message) OrderCancelRequest { +func FromMessage(m *quickfix.Message) OrderCancelRequest { return OrderCancelRequest{ - Header: fix44.Header{Header: m.Header}, - Body: m.Body, - Trailer: fix44.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fix44.Header{&m.Header}, + Body: &m.Body, + Trailer: fix44.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m OrderCancelRequest) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m OrderCancelRequest) ToMessage() *quickfix.Message { + return m.Message } //New returns a OrderCancelRequest initialized with the required fields for OrderCancelRequest func New(origclordid field.OrigClOrdIDField, clordid field.ClOrdIDField, side field.SideField, transacttime field.TransactTimeField) (m OrderCancelRequest) { - m.Header = fix44.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fix44.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("F")) m.Set(origclordid) @@ -60,7 +55,7 @@ type RouteOut func(msg OrderCancelRequest, sessionID quickfix.SessionID) quickfi //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "FIX.4.4", "F", r @@ -1466,7 +1461,7 @@ func (m OrderCancelRequest) HasStrikeCurrency() bool { //NoPartyIDs is a repeating group element, Tag 453 type NoPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetPartyID sets PartyID, Tag 448 @@ -1545,7 +1540,7 @@ func (m NoPartyIDs) HasNoPartySubIDs() bool { //NoPartySubIDs is a repeating group element, Tag 802 type NoPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetPartySubID sets PartySubID, Tag 523 @@ -1634,7 +1629,7 @@ func (m NoPartyIDsRepeatingGroup) Get(i int) NoPartyIDs { //NoSecurityAltID is a repeating group element, Tag 454 type NoSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetSecurityAltID sets SecurityAltID, Tag 455 @@ -1700,7 +1695,7 @@ func (m NoSecurityAltIDRepeatingGroup) Get(i int) NoSecurityAltID { //NoUnderlyings is a repeating group element, Tag 711 type NoUnderlyings struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSymbol sets UnderlyingSymbol, Tag 311 @@ -2575,7 +2570,7 @@ func (m NoUnderlyings) HasNoUnderlyingStips() bool { //NoUnderlyingSecurityAltID is a repeating group element, Tag 457 type NoUnderlyingSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSecurityAltID sets UnderlyingSecurityAltID, Tag 458 @@ -2641,7 +2636,7 @@ func (m NoUnderlyingSecurityAltIDRepeatingGroup) Get(i int) NoUnderlyingSecurity //NoUnderlyingStips is a repeating group element, Tag 887 type NoUnderlyingStips struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingStipType sets UnderlyingStipType, Tag 888 @@ -2730,7 +2725,7 @@ func (m NoUnderlyingsRepeatingGroup) Get(i int) NoUnderlyings { //NoEvents is a repeating group element, Tag 864 type NoEvents struct { - quickfix.Group + *quickfix.Group } //SetEventType sets EventType, Tag 865 diff --git a/vendor/github.com/quickfixgo/quickfix/fix44/trailer.generated.go b/vendor/github.com/quickfixgo/fix44/trailer.generated.go similarity index 94% rename from vendor/github.com/quickfixgo/quickfix/fix44/trailer.generated.go rename to vendor/github.com/quickfixgo/fix44/trailer.generated.go index a2b4c88..f3cae4d 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix44/trailer.generated.go +++ b/vendor/github.com/quickfixgo/fix44/trailer.generated.go @@ -1,14 +1,14 @@ package fix44 import ( + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //Trailer is the fix44 Trailer type type Trailer struct { - quickfix.Trailer + *quickfix.Trailer } //SetCheckSum sets CheckSum, Tag 10 diff --git a/vendor/github.com/quickfixgo/quickfix/fix50/executionreport/ExecutionReport.generated.go b/vendor/github.com/quickfixgo/fix50/executionreport/ExecutionReport.generated.go similarity index 99% rename from vendor/github.com/quickfixgo/quickfix/fix50/executionreport/ExecutionReport.generated.go rename to vendor/github.com/quickfixgo/fix50/executionreport/ExecutionReport.generated.go index 954879a..c577d17 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix50/executionreport/ExecutionReport.generated.go +++ b/vendor/github.com/quickfixgo/fix50/executionreport/ExecutionReport.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fixt11" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fixt11" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //ExecutionReport is the fix50 ExecutionReport type, MsgType = 8 type ExecutionReport struct { fixt11.Header - quickfix.Body + *quickfix.Body fixt11.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a ExecutionReport from a quickfix.Message instance -func FromMessage(m quickfix.Message) ExecutionReport { +func FromMessage(m *quickfix.Message) ExecutionReport { return ExecutionReport{ - Header: fixt11.Header{Header: m.Header}, - Body: m.Body, - Trailer: fixt11.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fixt11.Header{&m.Header}, + Body: &m.Body, + Trailer: fixt11.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m ExecutionReport) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m ExecutionReport) ToMessage() *quickfix.Message { + return m.Message } //New returns a ExecutionReport initialized with the required fields for ExecutionReport func New(orderid field.OrderIDField, execid field.ExecIDField, exectype field.ExecTypeField, ordstatus field.OrdStatusField, side field.SideField, leavesqty field.LeavesQtyField, cumqty field.CumQtyField) (m ExecutionReport) { - m.Header = fixt11.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fixt11.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("8")) m.Set(orderid) @@ -63,7 +58,7 @@ type RouteOut func(msg ExecutionReport, sessionID quickfix.SessionID) quickfix.M //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "7", "8", r @@ -5291,7 +5286,7 @@ func (m ExecutionReport) HasDisplayQty() bool { //NoMiscFees is a repeating group element, Tag 136 type NoMiscFees struct { - quickfix.Group + *quickfix.Group } //SetMiscFeeAmt sets MiscFeeAmt, Tag 137 @@ -5395,7 +5390,7 @@ func (m NoMiscFeesRepeatingGroup) Get(i int) NoMiscFees { //NoStipulations is a repeating group element, Tag 232 type NoStipulations struct { - quickfix.Group + *quickfix.Group } //SetStipulationType sets StipulationType, Tag 233 @@ -5461,7 +5456,7 @@ func (m NoStipulationsRepeatingGroup) Get(i int) NoStipulations { //NoContraBrokers is a repeating group element, Tag 382 type NoContraBrokers struct { - quickfix.Group + *quickfix.Group } //SetContraBroker sets ContraBroker, Tag 375 @@ -5584,7 +5579,7 @@ func (m NoContraBrokersRepeatingGroup) Get(i int) NoContraBrokers { //NoPartyIDs is a repeating group element, Tag 453 type NoPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetPartyID sets PartyID, Tag 448 @@ -5663,7 +5658,7 @@ func (m NoPartyIDs) HasNoPartySubIDs() bool { //NoPartySubIDs is a repeating group element, Tag 802 type NoPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetPartySubID sets PartySubID, Tag 523 @@ -5752,7 +5747,7 @@ func (m NoPartyIDsRepeatingGroup) Get(i int) NoPartyIDs { //NoSecurityAltID is a repeating group element, Tag 454 type NoSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetSecurityAltID sets SecurityAltID, Tag 455 @@ -5818,7 +5813,7 @@ func (m NoSecurityAltIDRepeatingGroup) Get(i int) NoSecurityAltID { //NoContAmts is a repeating group element, Tag 518 type NoContAmts struct { - quickfix.Group + *quickfix.Group } //SetContAmtType sets ContAmtType, Tag 519 @@ -5903,7 +5898,7 @@ func (m NoContAmtsRepeatingGroup) Get(i int) NoContAmts { //NoLegs is a repeating group element, Tag 555 type NoLegs struct { - quickfix.Group + *quickfix.Group } //SetLegSymbol sets LegSymbol, Tag 600 @@ -7042,7 +7037,7 @@ func (m NoLegs) HasLegGrossTradeAmt() bool { //NoLegSecurityAltID is a repeating group element, Tag 604 type NoLegSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetLegSecurityAltID sets LegSecurityAltID, Tag 605 @@ -7108,7 +7103,7 @@ func (m NoLegSecurityAltIDRepeatingGroup) Get(i int) NoLegSecurityAltID { //NoLegStipulations is a repeating group element, Tag 683 type NoLegStipulations struct { - quickfix.Group + *quickfix.Group } //SetLegStipulationType sets LegStipulationType, Tag 688 @@ -7174,7 +7169,7 @@ func (m NoLegStipulationsRepeatingGroup) Get(i int) NoLegStipulations { //NoNestedPartyIDs is a repeating group element, Tag 539 type NoNestedPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetNestedPartyID sets NestedPartyID, Tag 524 @@ -7253,7 +7248,7 @@ func (m NoNestedPartyIDs) HasNoNestedPartySubIDs() bool { //NoNestedPartySubIDs is a repeating group element, Tag 804 type NoNestedPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetNestedPartySubID sets NestedPartySubID, Tag 545 @@ -7365,7 +7360,7 @@ func (m NoLegsRepeatingGroup) Get(i int) NoLegs { //NoUnderlyings is a repeating group element, Tag 711 type NoUnderlyings struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSymbol sets UnderlyingSymbol, Tag 311 @@ -8466,7 +8461,7 @@ func (m NoUnderlyings) HasUnderlyingFXRateCalc() bool { //NoUnderlyingSecurityAltID is a repeating group element, Tag 457 type NoUnderlyingSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSecurityAltID sets UnderlyingSecurityAltID, Tag 458 @@ -8532,7 +8527,7 @@ func (m NoUnderlyingSecurityAltIDRepeatingGroup) Get(i int) NoUnderlyingSecurity //NoUnderlyingStips is a repeating group element, Tag 887 type NoUnderlyingStips struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingStipType sets UnderlyingStipType, Tag 888 @@ -8598,7 +8593,7 @@ func (m NoUnderlyingStipsRepeatingGroup) Get(i int) NoUnderlyingStips { //NoUndlyInstrumentParties is a repeating group element, Tag 1058 type NoUndlyInstrumentParties struct { - quickfix.Group + *quickfix.Group } //SetUndlyInstrumentPartyID sets UndlyInstrumentPartyID, Tag 1059 @@ -8677,7 +8672,7 @@ func (m NoUndlyInstrumentParties) HasNoUndlyInstrumentPartySubIDs() bool { //NoUndlyInstrumentPartySubIDs is a repeating group element, Tag 1062 type NoUndlyInstrumentPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetUndlyInstrumentPartySubID sets UndlyInstrumentPartySubID, Tag 1063 @@ -8789,7 +8784,7 @@ func (m NoUnderlyingsRepeatingGroup) Get(i int) NoUnderlyings { //NoTrdRegTimestamps is a repeating group element, Tag 768 type NoTrdRegTimestamps struct { - quickfix.Group + *quickfix.Group } //SetTrdRegTimestamp sets TrdRegTimestamp, Tag 769 @@ -8931,7 +8926,7 @@ func (m NoTrdRegTimestampsRepeatingGroup) Get(i int) NoTrdRegTimestamps { //NoEvents is a repeating group element, Tag 864 type NoEvents struct { - quickfix.Group + *quickfix.Group } //SetEventType sets EventType, Tag 865 @@ -9035,7 +9030,7 @@ func (m NoEventsRepeatingGroup) Get(i int) NoEvents { //NoStrategyParameters is a repeating group element, Tag 957 type NoStrategyParameters struct { - quickfix.Group + *quickfix.Group } //SetStrategyParameterName sets StrategyParameterName, Tag 958 @@ -9120,7 +9115,7 @@ func (m NoStrategyParametersRepeatingGroup) Get(i int) NoStrategyParameters { //NoInstrumentParties is a repeating group element, Tag 1018 type NoInstrumentParties struct { - quickfix.Group + *quickfix.Group } //SetInstrumentPartyID sets InstrumentPartyID, Tag 1019 @@ -9199,7 +9194,7 @@ func (m NoInstrumentParties) HasNoInstrumentPartySubIDs() bool { //NoInstrumentPartySubIDs is a repeating group element, Tag 1052 type NoInstrumentPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetInstrumentPartySubID sets InstrumentPartySubID, Tag 1053 diff --git a/vendor/github.com/quickfixgo/quickfix/fix50/marketdatarequest/MarketDataRequest.generated.go b/vendor/github.com/quickfixgo/fix50/marketdatarequest/MarketDataRequest.generated.go similarity index 99% rename from vendor/github.com/quickfixgo/quickfix/fix50/marketdatarequest/MarketDataRequest.generated.go rename to vendor/github.com/quickfixgo/fix50/marketdatarequest/MarketDataRequest.generated.go index 0826ff5..f34afed 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix50/marketdatarequest/MarketDataRequest.generated.go +++ b/vendor/github.com/quickfixgo/fix50/marketdatarequest/MarketDataRequest.generated.go @@ -2,49 +2,43 @@ package marketdatarequest import ( "github.com/shopspring/decimal" - "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fixt11" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fixt11" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //MarketDataRequest is the fix50 MarketDataRequest type, MsgType = V type MarketDataRequest struct { fixt11.Header - quickfix.Body + *quickfix.Body fixt11.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a MarketDataRequest from a quickfix.Message instance -func FromMessage(m quickfix.Message) MarketDataRequest { +func FromMessage(m *quickfix.Message) MarketDataRequest { return MarketDataRequest{ - Header: fixt11.Header{Header: m.Header}, - Body: m.Body, - Trailer: fixt11.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fixt11.Header{&m.Header}, + Body: &m.Body, + Trailer: fixt11.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m MarketDataRequest) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m MarketDataRequest) ToMessage() *quickfix.Message { + return m.Message } //New returns a MarketDataRequest initialized with the required fields for MarketDataRequest func New(mdreqid field.MDReqIDField, subscriptionrequesttype field.SubscriptionRequestTypeField, marketdepth field.MarketDepthField) (m MarketDataRequest) { - m.Header = fixt11.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fixt11.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("V")) m.Set(mdreqid) @@ -59,7 +53,7 @@ type RouteOut func(msg MarketDataRequest, sessionID quickfix.SessionID) quickfix //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "7", "V", r @@ -327,7 +321,7 @@ func (m MarketDataRequest) HasMDQuoteType() bool { //NoRelatedSym is a repeating group element, Tag 146 type NoRelatedSym struct { - quickfix.Group + *quickfix.Group } //SetSymbol sets Symbol, Tag 55 @@ -1481,7 +1475,7 @@ func (m NoRelatedSym) HasMDEntrySize() bool { //NoSecurityAltID is a repeating group element, Tag 454 type NoSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetSecurityAltID sets SecurityAltID, Tag 455 @@ -1547,7 +1541,7 @@ func (m NoSecurityAltIDRepeatingGroup) Get(i int) NoSecurityAltID { //NoEvents is a repeating group element, Tag 864 type NoEvents struct { - quickfix.Group + *quickfix.Group } //SetEventType sets EventType, Tag 865 @@ -1651,7 +1645,7 @@ func (m NoEventsRepeatingGroup) Get(i int) NoEvents { //NoInstrumentParties is a repeating group element, Tag 1018 type NoInstrumentParties struct { - quickfix.Group + *quickfix.Group } //SetInstrumentPartyID sets InstrumentPartyID, Tag 1019 @@ -1730,7 +1724,7 @@ func (m NoInstrumentParties) HasNoInstrumentPartySubIDs() bool { //NoInstrumentPartySubIDs is a repeating group element, Tag 1052 type NoInstrumentPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetInstrumentPartySubID sets InstrumentPartySubID, Tag 1053 @@ -1819,7 +1813,7 @@ func (m NoInstrumentPartiesRepeatingGroup) Get(i int) NoInstrumentParties { //NoUnderlyings is a repeating group element, Tag 711 type NoUnderlyings struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSymbol sets UnderlyingSymbol, Tag 311 @@ -2920,7 +2914,7 @@ func (m NoUnderlyings) HasUnderlyingFXRateCalc() bool { //NoUnderlyingSecurityAltID is a repeating group element, Tag 457 type NoUnderlyingSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSecurityAltID sets UnderlyingSecurityAltID, Tag 458 @@ -2986,7 +2980,7 @@ func (m NoUnderlyingSecurityAltIDRepeatingGroup) Get(i int) NoUnderlyingSecurity //NoUnderlyingStips is a repeating group element, Tag 887 type NoUnderlyingStips struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingStipType sets UnderlyingStipType, Tag 888 @@ -3052,7 +3046,7 @@ func (m NoUnderlyingStipsRepeatingGroup) Get(i int) NoUnderlyingStips { //NoUndlyInstrumentParties is a repeating group element, Tag 1058 type NoUndlyInstrumentParties struct { - quickfix.Group + *quickfix.Group } //SetUndlyInstrumentPartyID sets UndlyInstrumentPartyID, Tag 1059 @@ -3131,7 +3125,7 @@ func (m NoUndlyInstrumentParties) HasNoUndlyInstrumentPartySubIDs() bool { //NoUndlyInstrumentPartySubIDs is a repeating group element, Tag 1062 type NoUndlyInstrumentPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetUndlyInstrumentPartySubID sets UndlyInstrumentPartySubID, Tag 1063 @@ -3243,7 +3237,7 @@ func (m NoUnderlyingsRepeatingGroup) Get(i int) NoUnderlyings { //NoLegs is a repeating group element, Tag 555 type NoLegs struct { - quickfix.Group + *quickfix.Group } //SetLegSymbol sets LegSymbol, Tag 600 @@ -4082,7 +4076,7 @@ func (m NoLegs) HasLegTimeUnit() bool { //NoLegSecurityAltID is a repeating group element, Tag 604 type NoLegSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetLegSecurityAltID sets LegSecurityAltID, Tag 605 @@ -4194,7 +4188,7 @@ func (m NoRelatedSymRepeatingGroup) Get(i int) NoRelatedSym { //NoMDEntryTypes is a repeating group element, Tag 267 type NoMDEntryTypes struct { - quickfix.Group + *quickfix.Group } //SetMDEntryType sets MDEntryType, Tag 269 @@ -4241,7 +4235,7 @@ func (m NoMDEntryTypesRepeatingGroup) Get(i int) NoMDEntryTypes { //NoTradingSessions is a repeating group element, Tag 386 type NoTradingSessions struct { - quickfix.Group + *quickfix.Group } //SetTradingSessionID sets TradingSessionID, Tag 336 diff --git a/vendor/github.com/quickfixgo/quickfix/fix50/newordersingle/NewOrderSingle.generated.go b/vendor/github.com/quickfixgo/fix50/newordersingle/NewOrderSingle.generated.go similarity index 99% rename from vendor/github.com/quickfixgo/quickfix/fix50/newordersingle/NewOrderSingle.generated.go rename to vendor/github.com/quickfixgo/fix50/newordersingle/NewOrderSingle.generated.go index d2cca5b..ee040d2 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix50/newordersingle/NewOrderSingle.generated.go +++ b/vendor/github.com/quickfixgo/fix50/newordersingle/NewOrderSingle.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fixt11" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fixt11" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //NewOrderSingle is the fix50 NewOrderSingle type, MsgType = D type NewOrderSingle struct { fixt11.Header - quickfix.Body + *quickfix.Body fixt11.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a NewOrderSingle from a quickfix.Message instance -func FromMessage(m quickfix.Message) NewOrderSingle { +func FromMessage(m *quickfix.Message) NewOrderSingle { return NewOrderSingle{ - Header: fixt11.Header{Header: m.Header}, - Body: m.Body, - Trailer: fixt11.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fixt11.Header{&m.Header}, + Body: &m.Body, + Trailer: fixt11.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m NewOrderSingle) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m NewOrderSingle) ToMessage() *quickfix.Message { + return m.Message } //New returns a NewOrderSingle initialized with the required fields for NewOrderSingle func New(clordid field.ClOrdIDField, side field.SideField, transacttime field.TransactTimeField, ordtype field.OrdTypeField) (m NewOrderSingle) { - m.Header = fixt11.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fixt11.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("D")) m.Set(clordid) @@ -60,7 +55,7 @@ type RouteOut func(msg NewOrderSingle, sessionID quickfix.SessionID) quickfix.Me //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "7", "D", r @@ -4019,7 +4014,7 @@ func (m NewOrderSingle) HasDisplayQty() bool { //NoAllocs is a repeating group element, Tag 78 type NoAllocs struct { - quickfix.Group + *quickfix.Group } //SetAllocAccount sets AllocAccount, Tag 79 @@ -4136,7 +4131,7 @@ func (m NoAllocs) HasAllocQty() bool { //NoNestedPartyIDs is a repeating group element, Tag 539 type NoNestedPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetNestedPartyID sets NestedPartyID, Tag 524 @@ -4215,7 +4210,7 @@ func (m NoNestedPartyIDs) HasNoNestedPartySubIDs() bool { //NoNestedPartySubIDs is a repeating group element, Tag 804 type NoNestedPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetNestedPartySubID sets NestedPartySubID, Tag 545 @@ -4327,7 +4322,7 @@ func (m NoAllocsRepeatingGroup) Get(i int) NoAllocs { //NoStipulations is a repeating group element, Tag 232 type NoStipulations struct { - quickfix.Group + *quickfix.Group } //SetStipulationType sets StipulationType, Tag 233 @@ -4393,7 +4388,7 @@ func (m NoStipulationsRepeatingGroup) Get(i int) NoStipulations { //NoTradingSessions is a repeating group element, Tag 386 type NoTradingSessions struct { - quickfix.Group + *quickfix.Group } //SetTradingSessionID sets TradingSessionID, Tag 336 @@ -4459,7 +4454,7 @@ func (m NoTradingSessionsRepeatingGroup) Get(i int) NoTradingSessions { //NoPartyIDs is a repeating group element, Tag 453 type NoPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetPartyID sets PartyID, Tag 448 @@ -4538,7 +4533,7 @@ func (m NoPartyIDs) HasNoPartySubIDs() bool { //NoPartySubIDs is a repeating group element, Tag 802 type NoPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetPartySubID sets PartySubID, Tag 523 @@ -4627,7 +4622,7 @@ func (m NoPartyIDsRepeatingGroup) Get(i int) NoPartyIDs { //NoSecurityAltID is a repeating group element, Tag 454 type NoSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetSecurityAltID sets SecurityAltID, Tag 455 @@ -4693,7 +4688,7 @@ func (m NoSecurityAltIDRepeatingGroup) Get(i int) NoSecurityAltID { //NoUnderlyings is a repeating group element, Tag 711 type NoUnderlyings struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSymbol sets UnderlyingSymbol, Tag 311 @@ -5794,7 +5789,7 @@ func (m NoUnderlyings) HasUnderlyingFXRateCalc() bool { //NoUnderlyingSecurityAltID is a repeating group element, Tag 457 type NoUnderlyingSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSecurityAltID sets UnderlyingSecurityAltID, Tag 458 @@ -5860,7 +5855,7 @@ func (m NoUnderlyingSecurityAltIDRepeatingGroup) Get(i int) NoUnderlyingSecurity //NoUnderlyingStips is a repeating group element, Tag 887 type NoUnderlyingStips struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingStipType sets UnderlyingStipType, Tag 888 @@ -5926,7 +5921,7 @@ func (m NoUnderlyingStipsRepeatingGroup) Get(i int) NoUnderlyingStips { //NoUndlyInstrumentParties is a repeating group element, Tag 1058 type NoUndlyInstrumentParties struct { - quickfix.Group + *quickfix.Group } //SetUndlyInstrumentPartyID sets UndlyInstrumentPartyID, Tag 1059 @@ -6005,7 +6000,7 @@ func (m NoUndlyInstrumentParties) HasNoUndlyInstrumentPartySubIDs() bool { //NoUndlyInstrumentPartySubIDs is a repeating group element, Tag 1062 type NoUndlyInstrumentPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetUndlyInstrumentPartySubID sets UndlyInstrumentPartySubID, Tag 1063 @@ -6117,7 +6112,7 @@ func (m NoUnderlyingsRepeatingGroup) Get(i int) NoUnderlyings { //NoTrdRegTimestamps is a repeating group element, Tag 768 type NoTrdRegTimestamps struct { - quickfix.Group + *quickfix.Group } //SetTrdRegTimestamp sets TrdRegTimestamp, Tag 769 @@ -6259,7 +6254,7 @@ func (m NoTrdRegTimestampsRepeatingGroup) Get(i int) NoTrdRegTimestamps { //NoEvents is a repeating group element, Tag 864 type NoEvents struct { - quickfix.Group + *quickfix.Group } //SetEventType sets EventType, Tag 865 @@ -6363,7 +6358,7 @@ func (m NoEventsRepeatingGroup) Get(i int) NoEvents { //NoStrategyParameters is a repeating group element, Tag 957 type NoStrategyParameters struct { - quickfix.Group + *quickfix.Group } //SetStrategyParameterName sets StrategyParameterName, Tag 958 @@ -6448,7 +6443,7 @@ func (m NoStrategyParametersRepeatingGroup) Get(i int) NoStrategyParameters { //NoInstrumentParties is a repeating group element, Tag 1018 type NoInstrumentParties struct { - quickfix.Group + *quickfix.Group } //SetInstrumentPartyID sets InstrumentPartyID, Tag 1019 @@ -6527,7 +6522,7 @@ func (m NoInstrumentParties) HasNoInstrumentPartySubIDs() bool { //NoInstrumentPartySubIDs is a repeating group element, Tag 1052 type NoInstrumentPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetInstrumentPartySubID sets InstrumentPartySubID, Tag 1053 diff --git a/vendor/github.com/quickfixgo/quickfix/fix50/ordercancelrequest/OrderCancelRequest.generated.go b/vendor/github.com/quickfixgo/fix50/ordercancelrequest/OrderCancelRequest.generated.go similarity index 99% rename from vendor/github.com/quickfixgo/quickfix/fix50/ordercancelrequest/OrderCancelRequest.generated.go rename to vendor/github.com/quickfixgo/fix50/ordercancelrequest/OrderCancelRequest.generated.go index 0f0d59a..31b1715 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix50/ordercancelrequest/OrderCancelRequest.generated.go +++ b/vendor/github.com/quickfixgo/fix50/ordercancelrequest/OrderCancelRequest.generated.go @@ -4,47 +4,42 @@ import ( "github.com/shopspring/decimal" "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fixt11" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/fixt11" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //OrderCancelRequest is the fix50 OrderCancelRequest type, MsgType = F type OrderCancelRequest struct { fixt11.Header - quickfix.Body + *quickfix.Body fixt11.Trailer - //ReceiveTime is the time that this message was read from the socket connection - ReceiveTime time.Time + Message *quickfix.Message } //FromMessage creates a OrderCancelRequest from a quickfix.Message instance -func FromMessage(m quickfix.Message) OrderCancelRequest { +func FromMessage(m *quickfix.Message) OrderCancelRequest { return OrderCancelRequest{ - Header: fixt11.Header{Header: m.Header}, - Body: m.Body, - Trailer: fixt11.Trailer{Trailer: m.Trailer}, - ReceiveTime: m.ReceiveTime, + Header: fixt11.Header{&m.Header}, + Body: &m.Body, + Trailer: fixt11.Trailer{&m.Trailer}, + Message: m, } } //ToMessage returns a quickfix.Message instance -func (m OrderCancelRequest) ToMessage() quickfix.Message { - return quickfix.Message{ - Header: m.Header.Header, - Body: m.Body, - Trailer: m.Trailer.Trailer, - ReceiveTime: m.ReceiveTime, - } +func (m OrderCancelRequest) ToMessage() *quickfix.Message { + return m.Message } //New returns a OrderCancelRequest initialized with the required fields for OrderCancelRequest func New(origclordid field.OrigClOrdIDField, clordid field.ClOrdIDField, side field.SideField, transacttime field.TransactTimeField) (m OrderCancelRequest) { - m.Header = fixt11.NewHeader() - m.Init() - m.Trailer.Init() + m.Message = quickfix.NewMessage() + m.Header = fixt11.NewHeader(&m.Message.Header) + m.Body = &m.Message.Body + m.Trailer.Trailer = &m.Message.Trailer m.Header.Set(field.NewMsgType("F")) m.Set(origclordid) @@ -60,7 +55,7 @@ type RouteOut func(msg OrderCancelRequest, sessionID quickfix.SessionID) quickfi //Route returns the beginstring, message type, and MessageRoute for this Message type func Route(router RouteOut) (string, string, quickfix.MessageRoute) { - r := func(msg quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + r := func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { return router(FromMessage(msg), sessionID) } return "7", "F", r @@ -1692,7 +1687,7 @@ func (m OrderCancelRequest) HasMaturityTime() bool { //NoPartyIDs is a repeating group element, Tag 453 type NoPartyIDs struct { - quickfix.Group + *quickfix.Group } //SetPartyID sets PartyID, Tag 448 @@ -1771,7 +1766,7 @@ func (m NoPartyIDs) HasNoPartySubIDs() bool { //NoPartySubIDs is a repeating group element, Tag 802 type NoPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetPartySubID sets PartySubID, Tag 523 @@ -1860,7 +1855,7 @@ func (m NoPartyIDsRepeatingGroup) Get(i int) NoPartyIDs { //NoSecurityAltID is a repeating group element, Tag 454 type NoSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetSecurityAltID sets SecurityAltID, Tag 455 @@ -1926,7 +1921,7 @@ func (m NoSecurityAltIDRepeatingGroup) Get(i int) NoSecurityAltID { //NoUnderlyings is a repeating group element, Tag 711 type NoUnderlyings struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSymbol sets UnderlyingSymbol, Tag 311 @@ -3027,7 +3022,7 @@ func (m NoUnderlyings) HasUnderlyingFXRateCalc() bool { //NoUnderlyingSecurityAltID is a repeating group element, Tag 457 type NoUnderlyingSecurityAltID struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingSecurityAltID sets UnderlyingSecurityAltID, Tag 458 @@ -3093,7 +3088,7 @@ func (m NoUnderlyingSecurityAltIDRepeatingGroup) Get(i int) NoUnderlyingSecurity //NoUnderlyingStips is a repeating group element, Tag 887 type NoUnderlyingStips struct { - quickfix.Group + *quickfix.Group } //SetUnderlyingStipType sets UnderlyingStipType, Tag 888 @@ -3159,7 +3154,7 @@ func (m NoUnderlyingStipsRepeatingGroup) Get(i int) NoUnderlyingStips { //NoUndlyInstrumentParties is a repeating group element, Tag 1058 type NoUndlyInstrumentParties struct { - quickfix.Group + *quickfix.Group } //SetUndlyInstrumentPartyID sets UndlyInstrumentPartyID, Tag 1059 @@ -3238,7 +3233,7 @@ func (m NoUndlyInstrumentParties) HasNoUndlyInstrumentPartySubIDs() bool { //NoUndlyInstrumentPartySubIDs is a repeating group element, Tag 1062 type NoUndlyInstrumentPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetUndlyInstrumentPartySubID sets UndlyInstrumentPartySubID, Tag 1063 @@ -3350,7 +3345,7 @@ func (m NoUnderlyingsRepeatingGroup) Get(i int) NoUnderlyings { //NoEvents is a repeating group element, Tag 864 type NoEvents struct { - quickfix.Group + *quickfix.Group } //SetEventType sets EventType, Tag 865 @@ -3454,7 +3449,7 @@ func (m NoEventsRepeatingGroup) Get(i int) NoEvents { //NoInstrumentParties is a repeating group element, Tag 1018 type NoInstrumentParties struct { - quickfix.Group + *quickfix.Group } //SetInstrumentPartyID sets InstrumentPartyID, Tag 1019 @@ -3533,7 +3528,7 @@ func (m NoInstrumentParties) HasNoInstrumentPartySubIDs() bool { //NoInstrumentPartySubIDs is a repeating group element, Tag 1052 type NoInstrumentPartySubIDs struct { - quickfix.Group + *quickfix.Group } //SetInstrumentPartySubID sets InstrumentPartySubID, Tag 1053 diff --git a/vendor/github.com/quickfixgo/quickfix/fixt11/header.generated.go b/vendor/github.com/quickfixgo/fixt11/header.generated.go similarity index 98% rename from vendor/github.com/quickfixgo/quickfix/fixt11/header.generated.go rename to vendor/github.com/quickfixgo/fixt11/header.generated.go index 8e34c46..794f18c 100644 --- a/vendor/github.com/quickfixgo/quickfix/fixt11/header.generated.go +++ b/vendor/github.com/quickfixgo/fixt11/header.generated.go @@ -3,20 +3,20 @@ package fixt11 import ( "time" + "github.com/quickfixgo/enum" + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/enum" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //Header is the fixt11 Header type type Header struct { - quickfix.Header + *quickfix.Header } //NewHeader returns a new, initialized Header instance -func NewHeader() (h Header) { - h.Init() +func NewHeader(header *quickfix.Header) (h Header) { + h.Header = header h.SetBeginString("FIXT.1.1") return } @@ -572,7 +572,7 @@ func (h Header) HasCstmApplVerID() bool { //NoHops is a repeating group element, Tag 627 type NoHops struct { - quickfix.Group + *quickfix.Group } //SetHopCompID sets HopCompID, Tag 628 diff --git a/vendor/github.com/quickfixgo/quickfix/fixt11/trailer.generated.go b/vendor/github.com/quickfixgo/fixt11/trailer.generated.go similarity index 94% rename from vendor/github.com/quickfixgo/quickfix/fixt11/trailer.generated.go rename to vendor/github.com/quickfixgo/fixt11/trailer.generated.go index c3b1876..98557ed 100644 --- a/vendor/github.com/quickfixgo/quickfix/fixt11/trailer.generated.go +++ b/vendor/github.com/quickfixgo/fixt11/trailer.generated.go @@ -1,14 +1,14 @@ package fixt11 import ( + "github.com/quickfixgo/field" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/field" - "github.com/quickfixgo/quickfix/tag" + "github.com/quickfixgo/tag" ) //Trailer is the fixt11 Trailer type type Trailer struct { - quickfix.Trailer + *quickfix.Trailer } //SetCheckSum sets CheckSum, Tag 10 diff --git a/vendor/github.com/quickfixgo/quickfix/.gitignore b/vendor/github.com/quickfixgo/quickfix/.gitignore new file mode 100644 index 0000000..8e48ebb --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/.gitignore @@ -0,0 +1,8 @@ +*~ +*.swp +*.swo +vendor/*/ +_test/test +_test/echo_server +_test/tmp +_vendor* diff --git a/vendor/github.com/quickfixgo/quickfix/.travis.yml b/vendor/github.com/quickfixgo/quickfix/.travis.yml new file mode 100644 index 0000000..6945eea --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/.travis.yml @@ -0,0 +1,27 @@ +language: go +sudo: false + +go: + - 1.9 + - tip + +env: + - FIX_TEST= + - FIX_TEST=fix40 + - FIX_TEST=fix41 + - FIX_TEST=fix42 + - FIX_TEST=fix43 + - FIX_TEST=fix44 + - FIX_TEST=fix50 + - FIX_TEST=fix50sp1 + - FIX_TEST=fix50sp2 + +matrix: + allow_failures: + - go: tip + +install: + - go get -u github.com/golang/dep/cmd/dep + - dep ensure + +script: if [ -z "$FIX_TEST" ]; then make generate && make build && make; else make build_accept && make $FIX_TEST; fi diff --git a/vendor/github.com/quickfixgo/quickfix/CHANGELOG.md b/vendor/github.com/quickfixgo/quickfix/CHANGELOG.md index 7c2b0ab..dcc6352 100644 --- a/vendor/github.com/quickfixgo/quickfix/CHANGELOG.md +++ b/vendor/github.com/quickfixgo/quickfix/CHANGELOG.md @@ -1,3 +1,29 @@ +## 0.6.0 (August 14, 2017) + +FEATURES + +* CheckLatency [GH 241, 266] +* ResendRequestChunkSize [GH 243, 245] +* EnableLastMsgSeqNumProcessed [GH 253, 256] + +ENHANCEMENTS + +* config.SocketTLSForTesting(bool) [GH 235] +* API Interface Enhancements [GH 251, 252, 254, 255, 257, 258, 259] +* Misc. Performance Optimizations [GH 260, 261, 263, 264, 265, 268, 270, 271, 272, 273, 274, 275] +* TLS Configuration [GH 279, 280] +* Use data dictionary for parsing fix messages [GH 281] + +BUG FIXES + +* Resend logon fix [GH 244] +* PossDup messages with seqnum too low should not be sent to FromCallbacks [GH 246, 247] +* Router should not reject admin messages or business rejects [GH 249, 250] +* Fixes file log output for incoming, outgoing [GH 262] +* message.String() returns rawMessage if set, builds otherwise [GH 269] +* Use timestamp with time zone for postgres sql [GH 286] + + ## 0.5.0 (September 1, 2016) FEATURES diff --git a/vendor/github.com/quickfixgo/quickfix/Gopkg.lock b/vendor/github.com/quickfixgo/quickfix/Gopkg.lock new file mode 100644 index 0000000..156d40f --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/Gopkg.lock @@ -0,0 +1,51 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + name = "github.com/mattn/go-sqlite3" + packages = ["."] + revision = "ca5e3819723d8eeaf170ad510e7da1d6d2e94a08" + version = "v1.2.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/shopspring/decimal" + packages = ["."] + revision = "aed1bfe463fa3c9cc268d60dcc1491db613bff7e" + +[[projects]] + branch = "master" + name = "github.com/stretchr/objx" + packages = ["."] + revision = "1a9d0bb9f541897e62256577b352fdbc1fb4fd94" + +[[projects]] + name = "github.com/stretchr/testify" + packages = ["assert","mock","require","suite"] + revision = "69483b4bd14f5845b5a1e55bca19e954e827f1d0" + version = "v1.1.4" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = ["context"] + revision = "a04bdaca5b32abe1c069418fb7088ae607de5bd0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "6efc9f467166be5af0c9b9f4b98d7860ba12b50ce641a2fba765049bd1ea4f27" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/quickfixgo/quickfix/Gopkg.toml b/vendor/github.com/quickfixgo/quickfix/Gopkg.toml new file mode 100644 index 0000000..3385a5e --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/Gopkg.toml @@ -0,0 +1,34 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + name = "github.com/mattn/go-sqlite3" + version = "1.2.0" + +[[constraint]] + name = "github.com/shopspring/decimal" + branch = "master" + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.1.4" diff --git a/vendor/github.com/quickfixgo/quickfix/README.md b/vendor/github.com/quickfixgo/quickfix/README.md index 985dab7..c0812a8 100644 --- a/vendor/github.com/quickfixgo/quickfix/README.md +++ b/vendor/github.com/quickfixgo/quickfix/README.md @@ -47,16 +47,16 @@ Next, using [Git](https://git-scm.com/), clone this repository into `$GOPATH/src ### Installing Dependencies -QuickFIX/Go uses [govendor](https://github.com/kardianos/govendor) to manage the vendored dependencies. Install govendor with `go get`: +QuickFIX/Go uses [dep](https://github.com/golang/dep) to manage the vendored dependencies. Install dep with `go get`: ```sh -$ go get github.com/kardianos/govendor +$ go get -u github.com/golang/dep/cmd/dep ``` -Run `govendor sync` to install the correct versioned dependencies into `vendor/, which Go 1.6+ automatically recognizes and loads. +Run `dep ensure` to install the correct versioned dependencies into `vendor/`, which Go 1.6+ automatically recognizes and loads. ```sh -$ $GOPATH/bin/govendor sync +$ $GOPATH/bin/dep ensure ``` **Note:** No vendored dependencies are included in the QuickFIX/Go source. @@ -101,37 +101,34 @@ If you are developing QuickFIX/Go, there are a few tasks you might need to perfo #### Adding a dependency -If you are adding a dependency, you will need update the govendor manifest in the same Pull Request as the code that depends on it. You should do this in a separate commit from your code, as this makes PR review easier and Git history simpler to read in the future. +If you are adding a dependency, you will need to update the dep manifest in the same Pull Request as the code that depends on it. You should do this in a separate commit from your code, as this makes PR review easier and Git history simpler to read in the future. To add a dependency: -Assuming your work is on a branch called `my-feature-branch`, the steps look like this: - -1. Add the new package to your GOPATH: - - ```bash - go get github.com/quickfixgo/my-project - ``` - -2. Add the new package to your vendor/ directory: - - ```bash - govendor add github.com/quickfixgo/my-project - ``` - -3. Review the changes in git and commit them. +1. Add the dependency using `dep`: +```bash +$ dep ensure -add github.com/foo/bar +``` +2. Review the changes in git and commit them. #### Updating a dependency -To update a dependency: +To update a dependency to the latest version allowed by constraints in `Gopkg.toml`: -1. Fetch the dependency: +1. Run: +```bash +$ dep ensure -update github.com/foo/bar +``` +2. Review the changes in git and commit them. - ```bash - govendor fetch github.com/quickfixgo/my-project - ``` +To change the allowed version/branch/revision of a dependency: -2. Review the changes in git and commit them. +1. Manually edit `Gopkg.toml` +2. Run: +```bash +$ dep ensure +``` +3. Review the changes in git and commit them. Licensing --------- diff --git a/vendor/github.com/quickfixgo/quickfix/acceptor.go b/vendor/github.com/quickfixgo/quickfix/acceptor.go index 957ecc2..c913835 100644 --- a/vendor/github.com/quickfixgo/quickfix/acceptor.go +++ b/vendor/github.com/quickfixgo/quickfix/acceptor.go @@ -2,8 +2,11 @@ package quickfix import ( "bufio" + "bytes" "crypto/tls" + "io" "net" + "runtime/debug" "strconv" "sync" @@ -98,11 +101,8 @@ func NewAcceptor(app Application, storeFactory MessageStoreFactory, settings *Se } for sessionID, sessionSettings := range settings.SessionSettings() { - sessID := SessionID{ - BeginString: sessionID.BeginString, - TargetCompID: sessionID.TargetCompID, - SenderCompID: sessionID.SenderCompID, - } + sessID := sessionID + sessID.Qualifier = "" if _, dup := a.sessions[sessID]; dup { return a, errDuplicateSessionID @@ -131,14 +131,14 @@ func (a *Acceptor) listenForConnections() { } } -func (a *Acceptor) invalidMessage(msg []byte, err error) { - a.globalLog.OnEventf("Invalid Message: %s, %v", msg, err.Error()) +func (a *Acceptor) invalidMessage(msg *bytes.Buffer, err error) { + a.globalLog.OnEventf("Invalid Message: %s, %v", msg.Bytes(), err.Error()) } func (a *Acceptor) handleConnection(netConn net.Conn) { defer func() { if err := recover(); err != nil { - a.globalLog.OnEventf("Connection Terminated: %v", err) + a.globalLog.OnEventf("Connection Terminated with Panic: %s", debug.Stack()) } if err := netConn.Close(); err != nil { @@ -151,11 +151,16 @@ func (a *Acceptor) handleConnection(netConn net.Conn) { msgBytes, err := parser.ReadMessage() if err != nil { - a.globalLog.OnEvent(err.Error()) + if err == io.EOF { + a.globalLog.OnEvent("Connection Terminated") + } else { + a.globalLog.OnEvent(err.Error()) + } return } - msg, err := ParseMessage(msgBytes) + msg := NewMessage() + err = ParseMessage(msg, msgBytes) if err != nil { a.invalidMessage(msgBytes, err) return @@ -173,13 +178,48 @@ func (a *Acceptor) handleConnection(netConn net.Conn) { return } + var senderSubID FIXString + if msg.Header.Has(tagSenderSubID) { + if err := msg.Header.GetField(tagSenderSubID, &senderSubID); err != nil { + a.invalidMessage(msgBytes, err) + return + } + } + + var senderLocationID FIXString + if msg.Header.Has(tagSenderLocationID) { + if err := msg.Header.GetField(tagSenderLocationID, &senderLocationID); err != nil { + a.invalidMessage(msgBytes, err) + return + } + } + var targetCompID FIXString if err := msg.Header.GetField(tagTargetCompID, &targetCompID); err != nil { a.invalidMessage(msgBytes, err) return } - sessID := SessionID{BeginString: string(beginString), SenderCompID: string(targetCompID), TargetCompID: string(senderCompID)} + var targetSubID FIXString + if msg.Header.Has(tagTargetSubID) { + if err := msg.Header.GetField(tagTargetSubID, &targetSubID); err != nil { + a.invalidMessage(msgBytes, err) + return + } + } + + var targetLocationID FIXString + if msg.Header.Has(tagTargetLocationID) { + if err := msg.Header.GetField(tagTargetLocationID, &targetLocationID); err != nil { + a.invalidMessage(msgBytes, err) + return + } + } + + sessID := SessionID{BeginString: string(beginString), + SenderCompID: string(targetCompID), SenderSubID: string(targetSubID), SenderLocationID: string(targetLocationID), + TargetCompID: string(senderCompID), TargetSubID: string(senderSubID), TargetLocationID: string(senderLocationID), + } session, ok := a.sessions[sessID] if !ok { a.globalLog.OnEventf("Session %v not found for incoming message: %s", sessID, msgBytes) diff --git a/vendor/github.com/quickfixgo/quickfix/application.go b/vendor/github.com/quickfixgo/quickfix/application.go index 0bdb7dd..09b3b49 100644 --- a/vendor/github.com/quickfixgo/quickfix/application.go +++ b/vendor/github.com/quickfixgo/quickfix/application.go @@ -13,14 +13,14 @@ type Application interface { OnLogout(sessionID SessionID) //Notification of admin message being sent to target. - ToAdmin(message Message, sessionID SessionID) + ToAdmin(message *Message, sessionID SessionID) //Notification of app message being sent to target. - ToApp(message Message, sessionID SessionID) error + ToApp(message *Message, sessionID SessionID) error //Notification of admin message being received from target. - FromAdmin(message Message, sessionID SessionID) MessageRejectError + FromAdmin(message *Message, sessionID SessionID) MessageRejectError //Notification of app message being received from target. - FromApp(message Message, sessionID SessionID) MessageRejectError + FromApp(message *Message, sessionID SessionID) MessageRejectError } diff --git a/vendor/github.com/quickfixgo/quickfix/enum/begin_string.go b/vendor/github.com/quickfixgo/quickfix/begin_string.go similarity index 93% rename from vendor/github.com/quickfixgo/quickfix/enum/begin_string.go rename to vendor/github.com/quickfixgo/quickfix/begin_string.go index d8a2820..74c2a3d 100644 --- a/vendor/github.com/quickfixgo/quickfix/enum/begin_string.go +++ b/vendor/github.com/quickfixgo/quickfix/begin_string.go @@ -1,4 +1,4 @@ -package enum +package quickfix //FIX BeginString string values const ( diff --git a/vendor/github.com/quickfixgo/quickfix/config/configuration.go b/vendor/github.com/quickfixgo/quickfix/config/configuration.go index 9554e58..a8b5ae2 100644 --- a/vendor/github.com/quickfixgo/quickfix/config/configuration.go +++ b/vendor/github.com/quickfixgo/quickfix/config/configuration.go @@ -6,7 +6,11 @@ package config const ( BeginString string = "BeginString" SenderCompID string = "SenderCompID" + SenderSubID string = "SenderSubID" + SenderLocationID string = "SenderLocationID" TargetCompID string = "TargetCompID" + TargetSubID string = "TargetSubID" + TargetLocationID string = "TargetLocationID" SessionQualifier string = "SessionQualifier" SocketAcceptHost string = "SocketAcceptHost" SocketAcceptPort string = "SocketAcceptPort" @@ -16,6 +20,7 @@ const ( SocketCertificateFile string = "SocketCertificateFile" SocketCAFile string = "SocketCAFile" SocketInsecureSkipVerify string = "SocketInsecureSkipVerify" + SocketMinimumTLSVersion string = "SocketMinimumTLSVersion" DefaultApplVerID string = "DefaultApplVerID" StartTime string = "StartTime" EndTime string = "EndTime" @@ -28,6 +33,7 @@ const ( ResetOnLogon string = "ResetOnLogon" RefreshOnLogon string = "RefreshOnLogon" ResetOnLogout string = "ResetOnLogout" + ResetOnDisconnect string = "ResetOnDisconnect" ReconnectInterval string = "ReconnectInterval" HeartBtInt string = "HeartBtInt" FileLogPath string = "FileLogPath" @@ -38,4 +44,8 @@ const ( ValidateFieldsOutOfOrder string = "ValidateFieldsOutOfOrder" ResendRequestChunkSize string = "ResendRequestChunkSize" EnableLastMsgSeqNumProcessed string = "EnableLastMsgSeqNumProcessed" + CheckLatency string = "CheckLatency" + TimeStampPrecision string = "TimeStampPrecision" + MaxLatency string = "MaxLatency" + PersistMessages string = "PersistMessages" ) diff --git a/vendor/github.com/quickfixgo/quickfix/config/doc.go b/vendor/github.com/quickfixgo/quickfix/config/doc.go index 3157fb9..48b4113 100644 --- a/vendor/github.com/quickfixgo/quickfix/config/doc.go +++ b/vendor/github.com/quickfixgo/quickfix/config/doc.go @@ -16,10 +16,26 @@ SenderCompID Your ID as associated with this FIX session. Value is case-sensitive alpha-numeric string. +SenderSubID + +(Optional) Your subID as associated with this FIX session. Value is case-sensitive alpha-numeric string. + +SenderLocationID + +(Optional) Your locationID as associated with this FIX session. Value is case-sensitive alpha-numeric string. + TargetCompID Counter parties ID as associated with this FIX session. Value is case-sensitive alpha-numeric string. +TargetSubID + +(Optional) Counterparty's subID as associated with this FIX session. Value is case-sensitive alpha-numeric string. + +TargetLocationID + +(Optional) Counterparty's locationID as associated with this FIX session. Value is case-sensitive alpha-numeric string. + SessionQualifier Additional qualifier to disambiguate otherwise identical sessions. Value is case-sensitive alpha-numeric string. @@ -106,6 +122,14 @@ Determines if sequence numbers should be reset to 1 after a normal logout termin Defaults to N. +ResetOnDisconnect + +Determines if sequence numbers should be reset to 1 after an abnormal termination. Valid Values: + Y + N + +Defaults to N. + RefreshOnLogon Determines if session state should be restored from persistence layer when logging on. Useful for creating hot failover sessions. Valid Values: @@ -114,6 +138,15 @@ Determines if session state should be restored from persistence layer when loggi Defaults to N. +TimeStampPrecision + +Determines precision for timestamps in (Orig)SendingTime fields that are sent out. Only available for FIX.4.2 and greater, FIX versions earlier than FIX.4.2 will use timestamp resolution in seconds. Valid Values: + SECONDS + MILLIS + MICROS + NANOS + +Defaults to MILLIS. Validation @@ -169,6 +202,20 @@ If set to N, fields that are out of order (i.e. body fields in the header, or he Defaults to Y. +CheckLatency + +If set to Y, messages must be received from the counterparty within a defined number of seconds. It is useful to turn this off if a system uses localtime for it's timestamps instead of GMT. Valid Values: + Y + N + +Defaults to Y. + +MaxLatency + +If CheckLatency is set to Y, this defines the number of seconds latency allowed for a message to be processed. Value must be positive integer. + +Defaults to 120. + ReconnectInterval Time between reconnection attempts in seconds. Only used for initiators. Value must be positive integer. @@ -215,6 +262,18 @@ SocketCAFile Optional root CA to use for secure TLS connections. For acceptors, client certificates will be verified against this CA. For initiators, clients will use the CA to verify the server certificate. If not configurated, initiators will verify the server certificate using the host's root CA set. +SocketMinimumTLSVersion + +Specify the Minimum TLS version to use when creating a secure connection. The valid choices are SSL30, TLS10, TLS11, TLS12. Defaults to TLS12. + +PersistMessages + +If set to N, no messages will be persisted. This will force QuickFIX/Go to always send GapFills instead of resending messages. Use this if you know you never want to resend a message. Useful for market data streams. Valid Values: + Y + N + +Defaults to Y. + FileLogPath Directory to store logs. Value must be valid directory for storing files, application must have write access. diff --git a/vendor/github.com/quickfixgo/quickfix/connection_internal_test.go b/vendor/github.com/quickfixgo/quickfix/connection_internal_test.go new file mode 100644 index 0000000..54a9f34 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/connection_internal_test.go @@ -0,0 +1,58 @@ +package quickfix + +import ( + "bytes" + "strings" + "testing" +) + +func TestWriteLoop(t *testing.T) { + writer := bytes.NewBufferString("") + msgOut := make(chan []byte) + + go func() { + msgOut <- []byte("test msg 1 ") + msgOut <- []byte("test msg 2 ") + msgOut <- []byte("test msg 3") + close(msgOut) + }() + writeLoop(writer, msgOut, nullLog{}) + + expected := "test msg 1 test msg 2 test msg 3" + + if writer.String() != expected { + t.Errorf("expected %v got %v", expected, writer.String()) + } +} + +func TestReadLoop(t *testing.T) { + msgIn := make(chan fixIn) + stream := "hello8=FIX.4.09=5blah10=103garbage8=FIX.4.09=4foo10=103" + + parser := newParser(strings.NewReader(stream)) + go readLoop(parser, msgIn) + + var tests = []struct { + expectedMsg string + channelClosed bool + }{ + {expectedMsg: "8=FIX.4.09=5blah10=103"}, + {expectedMsg: "8=FIX.4.09=4foo10=103"}, + {channelClosed: true}, + } + + for _, test := range tests { + msg, ok := <-msgIn + switch { + case !ok && !test.channelClosed: + t.Error("Channel unexpectedly closed") + fallthrough + case !ok && test.channelClosed: + continue + } + + if msg.bytes.String() != test.expectedMsg { + t.Errorf("Expected %v got %v", test.expectedMsg, msg.bytes.String()) + } + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/datadictionary/build.go b/vendor/github.com/quickfixgo/quickfix/datadictionary/build.go index 9956580..6500a15 100644 --- a/vendor/github.com/quickfixgo/quickfix/datadictionary/build.go +++ b/vendor/github.com/quickfixgo/quickfix/datadictionary/build.go @@ -1,7 +1,9 @@ package datadictionary import ( + "errors" "fmt" + "strconv" ) type builder struct { @@ -11,14 +13,27 @@ type builder struct { } func (b *builder) build(doc *XMLDoc) (*DataDictionary, error) { + if doc.Type != "FIX" && doc.Type != "FIXT" { + return nil, errors.New("type attribute must be FIX or FIXT") + } + b.doc = doc + b.dict = &DataDictionary{FIXType: doc.Type, ServicePack: doc.ServicePack} + + var err error + if b.dict.Major, err = strconv.Atoi(doc.Major); err != nil { + return nil, errors.New("major attribute not valid on ") + } + + if b.dict.Minor, err = strconv.Atoi(doc.Minor); err != nil { + return nil, errors.New("minor attribute not valid on ") + } b.componentByName = make(map[string]*XMLComponent) for _, c := range doc.Components { b.componentByName[c.Name] = c } - b.dict = &DataDictionary{FIXType: doc.Type, Major: doc.Major, Minor: doc.Minor, ServicePack: doc.ServicePack} b.buildFieldTypes() if err := b.buildComponents(); err != nil { @@ -29,12 +44,16 @@ func (b *builder) build(doc *XMLDoc) (*DataDictionary, error) { return nil, err } - var err error - if b.dict.Header, err = b.buildMessageDef(b.doc.Header); err != nil { - return nil, err + if b.doc.Header != nil { + if b.dict.Header, err = b.buildMessageDef(b.doc.Header); err != nil { + return nil, err + } } - if b.dict.Trailer, err = b.buildMessageDef(b.doc.Trailer); err != nil { - return nil, err + + if b.doc.Trailer != nil { + if b.dict.Trailer, err = b.buildMessageDef(b.doc.Trailer); err != nil { + return nil, err + } } return b.dict, nil diff --git a/vendor/github.com/quickfixgo/quickfix/datadictionary/build_test.go b/vendor/github.com/quickfixgo/quickfix/datadictionary/build_test.go new file mode 100644 index 0000000..8e060ec --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/datadictionary/build_test.go @@ -0,0 +1,139 @@ +package datadictionary + +import ( + "encoding/xml" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +type BuildSuite struct { + suite.Suite + doc *XMLDoc + *builder +} + +func TestBuildSuite(t *testing.T) { + suite.Run(t, new(BuildSuite)) +} + +func (s *BuildSuite) SetupTest() { + s.doc = &XMLDoc{Type: "FIX", Major: "4", Minor: "5"} + s.builder = new(builder) +} + +func (s *BuildSuite) TestValidTypes() { + var tests = []string{ + "FIX", + "FIXT", + } + + for _, test := range tests { + s.doc.Type = test + dict, err := s.builder.build(s.doc) + + s.Nil(err) + s.NotNil(dict) + s.Equal(test, dict.FIXType) + } +} + +func (s *BuildSuite) TestInvalidTypes() { + var tests = []string{ + "", + "invalid", + } + + for _, test := range tests { + s.doc.Type = test + _, err := s.builder.build(s.doc) + + s.NotNil(err) + } +} + +func (s *BuildSuite) TestValidMajor() { + var tests = []int{ + 4, + 5, + } + + for _, test := range tests { + s.doc.Major = strconv.Itoa(test) + dict, err := s.builder.build(s.doc) + + s.Nil(err) + s.NotNil(dict) + s.Equal(test, dict.Major) + } +} + +func (s *BuildSuite) TestInvalidMajor() { + var tests = []string{ + "", + "notanumber", + } + + for _, test := range tests { + s.doc.Major = test + _, err := s.builder.build(s.doc) + + s.NotNil(err) + } +} + +func (s *BuildSuite) TestValidMinor() { + var tests = []int{ + 4, + 5, + } + + for _, test := range tests { + s.doc.Minor = strconv.Itoa(test) + dict, err := s.builder.build(s.doc) + + s.Nil(err) + s.NotNil(dict) + s.Equal(test, dict.Minor) + } +} + +func (s *BuildSuite) TestInvalidMinor() { + var tests = []string{ + "", + "notanumber", + } + + for _, test := range tests { + s.doc.Minor = test + _, err := s.builder.build(s.doc) + + s.NotNil(err) + } +} + +func TestBuildFieldDef(t *testing.T) { + var tests = []struct { + element string + }{ + {"field"}, + {"group"}, + } + + for _, test := range tests { + xmlField := &XMLComponentMember{XMLName: xml.Name{Local: test.element}, Name: "myfield", Members: []*XMLComponentMember{}} + + fieldTypeByName := make(map[string]*FieldType) + fieldTypeByName["myfield"] = NewFieldType("some field", 11, "INT") + dict := &DataDictionary{FieldTypeByName: fieldTypeByName} + + b := &builder{doc: nil, dict: dict} + f, err := b.buildFieldDef(xmlField) + + assert.Nil(t, err) + assert.Equal(t, 11, f.Tag()) + assert.Empty(t, f.childTags()) + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/datadictionary/component_type_test.go b/vendor/github.com/quickfixgo/quickfix/datadictionary/component_type_test.go new file mode 100644 index 0000000..6de2b34 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/datadictionary/component_type_test.go @@ -0,0 +1,79 @@ +package datadictionary_test + +import ( + "testing" + + "github.com/quickfixgo/quickfix/datadictionary" + "github.com/stretchr/testify/assert" +) + +func TestNewComponentType(t *testing.T) { + ft1 := datadictionary.NewFieldType("aname1", 11, "INT") + ft2 := datadictionary.NewFieldType("aname2", 12, "INT") + + optionalField1 := datadictionary.NewFieldDef(ft1, false) + requiredField1 := datadictionary.NewFieldDef(ft1, true) + + optionalField2 := datadictionary.NewFieldDef(ft2, false) + requiredField2 := datadictionary.NewFieldDef(ft2, true) + + requiredComp1 := datadictionary.NewComponent( + datadictionary.NewComponentType("comp1", []datadictionary.MessagePart{requiredField1}), + true) + + optionalComp1 := datadictionary.NewComponent( + datadictionary.NewComponentType("comp1", []datadictionary.MessagePart{requiredField1}), + false) + + var tests = []struct { + testName string + parts []datadictionary.MessagePart + expectedFields []*datadictionary.FieldDef + expectedRequiredParts []datadictionary.MessagePart + expectedRequiredFields []*datadictionary.FieldDef + }{ + { + testName: "test1", + parts: []datadictionary.MessagePart{optionalField1}, + expectedFields: []*datadictionary.FieldDef{optionalField1}, + }, + { + testName: "test2", + parts: []datadictionary.MessagePart{requiredField1}, + expectedFields: []*datadictionary.FieldDef{requiredField1}, + expectedRequiredFields: []*datadictionary.FieldDef{requiredField1}, + expectedRequiredParts: []datadictionary.MessagePart{requiredField1}, + }, + { + testName: "test3", + parts: []datadictionary.MessagePart{requiredField1, optionalField2}, + expectedFields: []*datadictionary.FieldDef{requiredField1, optionalField2}, + expectedRequiredFields: []*datadictionary.FieldDef{requiredField1}, + expectedRequiredParts: []datadictionary.MessagePart{requiredField1}, + }, + { + testName: "test4", + parts: []datadictionary.MessagePart{requiredField2, optionalComp1}, + expectedFields: []*datadictionary.FieldDef{requiredField2, requiredField1}, + expectedRequiredFields: []*datadictionary.FieldDef{requiredField2}, + expectedRequiredParts: []datadictionary.MessagePart{requiredField2}, + }, + { + testName: "test5", + parts: []datadictionary.MessagePart{requiredField2, requiredComp1}, + expectedFields: []*datadictionary.FieldDef{requiredField2, requiredField1}, + expectedRequiredFields: []*datadictionary.FieldDef{requiredField2, requiredField1}, + expectedRequiredParts: []datadictionary.MessagePart{requiredField2, requiredComp1}, + }, + } + + for _, test := range tests { + ct := datadictionary.NewComponentType("cname", test.parts) + assert.NotNil(t, ct, test.testName) + assert.Equal(t, "cname", ct.Name(), test.testName) + assert.Equal(t, test.expectedFields, ct.Fields(), test.testName) + assert.Equal(t, test.parts, ct.Parts(), test.testName) + assert.Equal(t, test.expectedRequiredFields, ct.RequiredFields(), test.testName) + assert.Equal(t, test.expectedRequiredParts, ct.RequiredParts(), test.testName) + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/datadictionary/datadictionary_test.go b/vendor/github.com/quickfixgo/quickfix/datadictionary/datadictionary_test.go new file mode 100644 index 0000000..4179716 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/datadictionary/datadictionary_test.go @@ -0,0 +1,191 @@ +package datadictionary + +import ( + "testing" +) + +func TestParseBadPath(t *testing.T) { + if _, err := Parse("../spec/bogus.xml"); err == nil { + t.Error("Expected err") + } +} + +func TestParseRecursiveComponents(t *testing.T) { + dict, err := Parse("../spec/FIX44.xml") + + if dict == nil { + t.Error("Dictionary is nil") + } + + if err != nil { + t.Errorf("Unexpected err: %v", err) + } +} + +var cachedDataDictionary *DataDictionary + +func dict() (*DataDictionary, error) { + if cachedDataDictionary != nil { + return cachedDataDictionary, nil + } + + var err error + cachedDataDictionary, err = Parse("../spec/FIX43.xml") + return cachedDataDictionary, err +} + +func TestComponents(t *testing.T) { + d, _ := dict() + if _, ok := d.ComponentTypes["SpreadOrBenchmarkCurveData"]; ok != true { + t.Error("Component not found") + } +} + +func TestFieldsByTag(t *testing.T) { + d, _ := dict() + + var tests = []struct { + Tag int + Name string + Type string + EnumsAreNil bool + }{ + {655, "ContraLegRefID", "STRING", true}, + {658, "QuoteRequestRejectReason", "INT", false}, + } + + for _, test := range tests { + f, ok := d.FieldTypeByTag[test.Tag] + + if !ok { + t.Errorf("%v not found", test.Tag) + } + + if f.Name() != test.Name { + t.Errorf("Expected %v got %v", test.Name, f.Name()) + } + + if f.Type != test.Type { + t.Errorf("Expected %v got %v", test.Type, f.Type) + } + + switch { + + case f.Enums != nil && test.EnumsAreNil: + t.Errorf("Expected no enums") + case f.Enums == nil && !test.EnumsAreNil: + t.Errorf("Expected enums") + } + } +} + +func TestEnumFieldsByTag(t *testing.T) { + + d, _ := dict() + f, _ := d.FieldTypeByTag[658] + + var tests = []struct { + Value string + Description string + }{ + {"1", "UNKNOWN_SYMBOL"}, + {"2", "EXCHANGE"}, + {"3", "QUOTE_REQUEST_EXCEEDS_LIMIT"}, + {"4", "TOO_LATE_TO_ENTER"}, + {"5", "INVALID_PRICE"}, + {"6", "NOT_AUTHORIZED_TO_REQUEST_QUOTE"}, + } + + if len(f.Enums) != len(tests) { + t.Errorf("Expected %v enums got %v", len(tests), len(f.Enums)) + } + + for _, test := range tests { + if enum, ok := f.Enums[test.Value]; !ok { + t.Errorf("Expected Enum %v", test.Value) + } else { + + if enum.Value != test.Value { + t.Errorf("Expected value %v got %v", test.Value, enum.Value) + } + + if enum.Description != test.Description { + t.Errorf("Expected description %v got %v", test.Description, enum.Description) + } + } + } +} + +func TestDataDictionaryMessages(t *testing.T) { + d, _ := dict() + _, ok := d.Messages["D"] + if !ok { + t.Error("Did not find message") + } +} + +func TestDataDictionaryHeader(t *testing.T) { + d, _ := dict() + if d.Header == nil { + t.Error("Did not find header") + } +} + +func TestDataDictionaryTrailer(t *testing.T) { + d, _ := dict() + if d.Trailer == nil { + t.Error("Did not find trailer") + } +} + +func TestMessageRequiredTags(t *testing.T) { + d, _ := dict() + + nos, _ := d.Messages["D"] + + var tests = []struct { + *MessageDef + Tag int + Required bool + }{ + {nos, 11, true}, + {nos, 526, false}, + {d.Header, 8, true}, + {d.Header, 115, false}, + {d.Trailer, 10, true}, + {d.Trailer, 89, false}, + } + + for _, test := range tests { + switch _, required := test.MessageDef.RequiredTags[test.Tag]; { + case required && !test.Required: + t.Errorf("%v should not be required", test.Tag) + case !required && test.Required: + t.Errorf("%v should not required", test.Tag) + } + } +} + +func TestMessageTags(t *testing.T) { + d, _ := dict() + + nos, _ := d.Messages["D"] + + var tests = []struct { + *MessageDef + Tag int + }{ + {nos, 11}, + {nos, 526}, + {d.Header, 8}, + {d.Header, 115}, + {d.Trailer, 10}, + {d.Trailer, 89}, + } + + for _, test := range tests { + if _, known := test.MessageDef.Tags[test.Tag]; !known { + t.Errorf("%v is not known", test.Tag) + } + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/datadictionary/field_def_test.go b/vendor/github.com/quickfixgo/quickfix/datadictionary/field_def_test.go new file mode 100644 index 0000000..9c0a68a --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/datadictionary/field_def_test.go @@ -0,0 +1,25 @@ +package datadictionary_test + +import ( + "testing" + + "github.com/quickfixgo/quickfix/datadictionary" + "github.com/stretchr/testify/assert" +) + +func TestNewFieldDef(t *testing.T) { + ft := datadictionary.NewFieldType("aname", 11, "INT") + + var tests = []struct { + required bool + }{ + {false}, + } + + for _, test := range tests { + fd := datadictionary.NewFieldDef(ft, test.required) + assert.False(t, fd.IsGroup(), "field def is not a group") + assert.Equal(t, "aname", fd.Name()) + assert.Equal(t, test.required, fd.Required()) + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/datadictionary/field_type_test.go b/vendor/github.com/quickfixgo/quickfix/datadictionary/field_type_test.go new file mode 100644 index 0000000..2a4328d --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/datadictionary/field_type_test.go @@ -0,0 +1,16 @@ +package datadictionary_test + +import ( + "testing" + + "github.com/quickfixgo/quickfix/datadictionary" + "github.com/stretchr/testify/assert" +) + +func TestNewFieldType(t *testing.T) { + ft := datadictionary.NewFieldType("myname", 10, "STRING") + assert.NotNil(t, ft) + assert.Equal(t, "myname", ft.Name()) + assert.Equal(t, 10, ft.Tag()) + assert.Equal(t, "STRING", ft.Type) +} diff --git a/vendor/github.com/quickfixgo/quickfix/datadictionary/group_field_def_test.go b/vendor/github.com/quickfixgo/quickfix/datadictionary/group_field_def_test.go new file mode 100644 index 0000000..e1e9632 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/datadictionary/group_field_def_test.go @@ -0,0 +1,16 @@ +package datadictionary_test + +import ( + "testing" + + "github.com/quickfixgo/quickfix/datadictionary" + "github.com/stretchr/testify/assert" +) + +func TestNewGroupField(t *testing.T) { + ft := datadictionary.NewFieldType("aname", 11, "INT") + fg := datadictionary.NewGroupFieldDef(ft, true, []datadictionary.MessagePart{}) + assert.NotNil(t, fg) + assert.Equal(t, "aname", fg.Name()) + assert.Equal(t, true, fg.Required()) +} diff --git a/vendor/github.com/quickfixgo/quickfix/datadictionary/message_def_test.go b/vendor/github.com/quickfixgo/quickfix/datadictionary/message_def_test.go new file mode 100644 index 0000000..666751f --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/datadictionary/message_def_test.go @@ -0,0 +1,84 @@ +package datadictionary_test + +import ( + "testing" + + "github.com/quickfixgo/quickfix/datadictionary" + "github.com/stretchr/testify/assert" +) + +func TestNewMessageDef(t *testing.T) { + + ft1 := datadictionary.NewFieldType("type1", 11, "STRING") + ft2 := datadictionary.NewFieldType("type2", 12, "STRING") + ft3 := datadictionary.NewFieldType("type3", 13, "INT") + + optionalfd1 := datadictionary.NewFieldDef(ft1, false) + requiredfd1 := datadictionary.NewFieldDef(ft1, true) + + optionalfd2 := datadictionary.NewFieldDef(ft2, false) + // requiredfd2 := datadictionary.NewFieldDef(ft2, true) + + optionalGroup1 := datadictionary.NewGroupFieldDef(ft3, false, []datadictionary.MessagePart{requiredfd1, optionalfd2}) + requiredGroup1 := datadictionary.NewGroupFieldDef(ft3, true, []datadictionary.MessagePart{requiredfd1, optionalfd2}) + + ct1 := datadictionary.NewComponentType("ct1", []datadictionary.MessagePart{requiredGroup1}) + + optionalComp1 := datadictionary.NewComponent(ct1, false) + + var tests = []struct { + parts []datadictionary.MessagePart + expectedTags datadictionary.TagSet + expectedRequiredTags datadictionary.TagSet + expectedRequiredParts []datadictionary.MessagePart + }{ + { + parts: []datadictionary.MessagePart{}, + expectedTags: datadictionary.TagSet{}, + expectedRequiredTags: datadictionary.TagSet{}, + expectedRequiredParts: []datadictionary.MessagePart(nil), + }, + { + parts: []datadictionary.MessagePart{optionalfd1}, + expectedTags: datadictionary.TagSet{11: struct{}{}}, + expectedRequiredTags: datadictionary.TagSet{}, + expectedRequiredParts: []datadictionary.MessagePart(nil), + }, + { + parts: []datadictionary.MessagePart{requiredfd1, optionalfd2}, + expectedTags: datadictionary.TagSet{11: struct{}{}, 12: struct{}{}}, + expectedRequiredTags: datadictionary.TagSet{11: struct{}{}}, + expectedRequiredParts: []datadictionary.MessagePart{requiredfd1}, + }, + { + parts: []datadictionary.MessagePart{optionalGroup1}, + expectedTags: datadictionary.TagSet{11: struct{}{}, 12: struct{}{}, 13: struct{}{}}, + expectedRequiredTags: datadictionary.TagSet{}, + expectedRequiredParts: []datadictionary.MessagePart(nil), + }, + { + parts: []datadictionary.MessagePart{requiredGroup1}, + expectedTags: datadictionary.TagSet{11: struct{}{}, 12: struct{}{}, 13: struct{}{}}, + expectedRequiredTags: datadictionary.TagSet{13: struct{}{}}, + expectedRequiredParts: []datadictionary.MessagePart{requiredGroup1}, + }, + { + parts: []datadictionary.MessagePart{optionalComp1}, + expectedTags: datadictionary.TagSet{11: struct{}{}, 12: struct{}{}, 13: struct{}{}}, + expectedRequiredTags: datadictionary.TagSet{}, + expectedRequiredParts: []datadictionary.MessagePart(nil), + }, + } + + for _, test := range tests { + md := datadictionary.NewMessageDef("some message", "X", test.parts) + + assert.NotNil(t, md) + assert.Equal(t, "some message", md.Name) + assert.Equal(t, "X", md.MsgType) + assert.Equal(t, test.expectedTags, md.Tags) + assert.Equal(t, test.expectedRequiredTags, md.RequiredTags) + assert.Equal(t, test.parts, md.Parts) + assert.Equal(t, test.expectedRequiredParts, md.RequiredParts()) + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/datadictionary/xml.go b/vendor/github.com/quickfixgo/quickfix/datadictionary/xml.go index 814d20f..7471a75 100644 --- a/vendor/github.com/quickfixgo/quickfix/datadictionary/xml.go +++ b/vendor/github.com/quickfixgo/quickfix/datadictionary/xml.go @@ -7,8 +7,8 @@ import ( //XMLDoc is the unmarshalled root of a FIX Dictionary. type XMLDoc struct { Type string `xml:"type,attr"` - Major int `xml:"major,attr"` - Minor int `xml:"minor,attr"` + Major string `xml:"major,attr"` + Minor string `xml:"minor,attr"` ServicePack int `xml:"servicepack,attr"` Header *XMLComponent `xml:"header"` diff --git a/vendor/github.com/quickfixgo/quickfix/datadictionary/xml_test.go b/vendor/github.com/quickfixgo/quickfix/datadictionary/xml_test.go new file mode 100644 index 0000000..2f0f0e4 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/datadictionary/xml_test.go @@ -0,0 +1,186 @@ +package datadictionary + +import ( + "encoding/xml" + "reflect" + "testing" +) + +var cachedXMLDoc *XMLDoc + +func xmlDoc() (*XMLDoc, error) { + if cachedXMLDoc != nil { + return cachedXMLDoc, nil + } + + data := ` + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ` + + cachedXMLDoc = new(XMLDoc) + err := xml.Unmarshal([]byte(data), cachedXMLDoc) + + return cachedXMLDoc, err +} + +func TestBoilerPlate(t *testing.T) { + doc, err := xmlDoc() + + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + + var tests = []struct { + Value interface{} + ExpectedValue interface{} + }{ + {doc.Type, "FIX"}, + {doc.Major, "4"}, + {doc.Minor, "3"}, + {doc.ServicePack, 0}, + } + + for _, test := range tests { + if !reflect.DeepEqual(test.Value, test.ExpectedValue) { + t.Errorf("Expected %v got %v", test.ExpectedValue, test.Value) + } + } +} + +func TestComponentMembers(t *testing.T) { + doc, err := xmlDoc() + + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + + if doc.Header == nil { + t.Fatal("Header is nil") + } + + var tests = []struct { + Value *XMLComponentMember + XMLNameLocal string + Name string + Required bool + }{ + {doc.Header.Members[0], "field", "BeginString", true}, + {doc.Header.Members[1], "group", "NoHops", false}, + {doc.Header.Members[1].Members[0], "field", "HopCompID", false}, + {doc.Trailer.Members[0], "field", "SignatureLength", false}, + {doc.Messages[0].Members[0], "field", "TestReqID", false}, + {doc.Messages[1].Members[3], "component", "Instrument", true}, + {doc.Messages[1].Members[4], "group", "NoRoutingIDs", false}, + {doc.Messages[1].Members[4].Members[0], "field", "RoutingType", false}, + {doc.Messages[1].Members[4].Members[1], "field", "RoutingID", false}, + } + + for _, test := range tests { + if test.Value.XMLName.Local != test.XMLNameLocal { + t.Errorf("%v: Expected XMLName Local %v got %v", test.Name, test.XMLNameLocal, test.Value.XMLName.Local) + } + + if test.Value.Name != test.Name { + t.Errorf("%v: Expected Name %v got %v", test.Name, test.Name, test.Value.Name) + } + + if test.Value.isRequired() != test.Required { + t.Errorf("%v: Expected Required %v got %v", test.Name, test.Required, test.Value.isRequired()) + } + } +} + +func TestMessages(t *testing.T) { + doc, err := xmlDoc() + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + + var tests = []struct { + Value *XMLComponent + Name string + MsgCat string + MsgType string + }{ + {doc.Messages[0], "Heartbeat", "admin", "0"}, + } + + for _, test := range tests { + if test.Value.Name != test.Name { + t.Errorf("Expected Name %v got %v", test.Name, test.Value.Name) + } + + if test.Value.MsgCat != test.MsgCat { + t.Errorf("Expected MsgCat %v got %v", test.MsgCat, test.Value.MsgCat) + } + + if test.Value.MsgType != test.MsgType { + t.Errorf("Expected MsgType %v got %v", test.MsgType, test.Value.MsgType) + } + + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/enum/enum.go b/vendor/github.com/quickfixgo/quickfix/enum/enum.go deleted file mode 100644 index 6e62a50..0000000 --- a/vendor/github.com/quickfixgo/quickfix/enum/enum.go +++ /dev/null @@ -1,2 +0,0 @@ -//Package enum declares standard FIX enum values. -package enum diff --git a/vendor/github.com/quickfixgo/quickfix/errors_test.go b/vendor/github.com/quickfixgo/quickfix/errors_test.go new file mode 100644 index 0000000..56554af --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/errors_test.go @@ -0,0 +1,255 @@ +package quickfix + +import ( + "fmt" + "strings" + "testing" +) + +func TestNewMessageRejectError(t *testing.T) { + var ( + expectedErrorString = "Custom error" + expectedRejectReason = 5 + expectedRefTagID Tag = 44 + expectedIsBusinessReject = false + ) + msgRej := NewMessageRejectError(expectedErrorString, expectedRejectReason, &expectedRefTagID) + + if strings.Compare(msgRej.Error(), expectedErrorString) != 0 { + t.Errorf("expected: %s, got: %s\n", expectedErrorString, msgRej.Error()) + } + if msgRej.RejectReason() != expectedRejectReason { + t.Errorf("expected: %d, got: %d\n", expectedRejectReason, msgRej.RejectReason()) + } + if *msgRej.RefTagID() != expectedRefTagID { + t.Errorf("expected: %d, got: %d\n", expectedRefTagID, msgRej.RefTagID()) + } + if msgRej.IsBusinessReject() != expectedIsBusinessReject { + t.Error("Expected IsBusinessReject to be false\n") + } +} + +func TestNewBusinessMessageRejectError(t *testing.T) { + var ( + expectedErrorString = "Custom error" + expectedRejectReason = 5 + expectedRefTagID Tag = 44 + expectedIsBusinessReject = true + ) + msgRej := NewBusinessMessageRejectError(expectedErrorString, expectedRejectReason, &expectedRefTagID) + + if strings.Compare(msgRej.Error(), expectedErrorString) != 0 { + t.Errorf("expected: %s, got: %s\n", expectedErrorString, msgRej.Error()) + } + if msgRej.RejectReason() != expectedRejectReason { + t.Errorf("expected: %d, got: %d\n", expectedRejectReason, msgRej.RejectReason()) + } + if *msgRej.RefTagID() != expectedRefTagID { + t.Errorf("expected: %d, got: %d\n", expectedRefTagID, msgRej.RefTagID()) + } + if msgRej.IsBusinessReject() != expectedIsBusinessReject { + t.Error("Expected IsBusinessReject to be true\n") + } +} + +func TestIncorrectDataFormatForValue(t *testing.T) { + var ( + expectedErrorString = "Incorrect data format for value" + expectedRejectReason = 6 + expectedRefTagID Tag = 44 + expectedIsBusinessReject = false + ) + msgRej := IncorrectDataFormatForValue(expectedRefTagID) + + if strings.Compare(msgRej.Error(), expectedErrorString) != 0 { + t.Errorf("expected: %s, got: %s\n", expectedErrorString, msgRej.Error()) + } + if msgRej.RejectReason() != expectedRejectReason { + t.Errorf("expected: %d, got: %d\n", expectedRejectReason, msgRej.RejectReason()) + } + if *msgRej.RefTagID() != expectedRefTagID { + t.Errorf("expected: %d, got: %d\n", expectedRefTagID, msgRej.RefTagID()) + } + if msgRej.IsBusinessReject() != expectedIsBusinessReject { + t.Error("Expected IsBusinessReject to be false\n") + } +} + +func TestValueIsIncorrect(t *testing.T) { + var ( + expectedErrorString = "Value is incorrect (out of range) for this tag" + expectedRejectReason = 5 + expectedRefTagID Tag = 44 + expectedIsBusinessReject = false + ) + msgRej := ValueIsIncorrect(expectedRefTagID) + if *msgRej.RefTagID() != expectedRefTagID { + t.Errorf("expected: %d, got: %d\n", expectedRefTagID, msgRej.RefTagID()) + } + if strings.Compare(msgRej.Error(), expectedErrorString) != 0 { + t.Errorf("expected: %s, got: %s\n", expectedErrorString, msgRej.Error()) + } + if msgRej.RejectReason() != expectedRejectReason { + t.Errorf("expected: %d, got: %d\n", expectedRejectReason, msgRej.RejectReason()) + } + if msgRej.IsBusinessReject() != expectedIsBusinessReject { + t.Error("Expected IsBusinessReject to be false\n") + } +} + +func TestConditionallyRequiredFieldMissing(t *testing.T) { + var ( + expectedRejectReason = 5 + expectedRefTagID Tag = 44 + expectedErrorString = fmt.Sprintf("Conditionally Required Field Missing (%d)", expectedRefTagID) + expectedIsBusinessReject = true + ) + msgRej := ConditionallyRequiredFieldMissing(expectedRefTagID) + if *msgRej.RefTagID() != expectedRefTagID { + t.Errorf("expected: %d, got: %d\n", expectedRefTagID, msgRej.RefTagID()) + } + if strings.Compare(msgRej.Error(), expectedErrorString) != 0 { + t.Errorf("expected: %s, got: %s\n", expectedErrorString, msgRej.Error()) + } + if msgRej.RejectReason() != expectedRejectReason { + t.Errorf("expected: %d, got: %d\n", expectedRejectReason, msgRej.RejectReason()) + } + if msgRej.IsBusinessReject() != expectedIsBusinessReject { + t.Error("Expected IsBusinessReject to be true\n") + } +} + +func TestInvalidMessageType(t *testing.T) { + var ( + expectedErrorString = "Invalid MsgType" + expectedRejectReason = 11 + expectedIsBusinessReject = false + ) + msgRej := InvalidMessageType() + + if strings.Compare(msgRej.Error(), expectedErrorString) != 0 { + t.Errorf("expected: %s, got: %s\n", expectedErrorString, msgRej.Error()) + } + if msgRej.RejectReason() != expectedRejectReason { + t.Errorf("expected: %d, got: %d\n", expectedRejectReason, msgRej.RejectReason()) + } + if msgRej.RefTagID() != nil { + t.Errorf("expected: nil, got: %d\n", msgRej.RefTagID()) + } + if msgRej.IsBusinessReject() != expectedIsBusinessReject { + t.Error("Expected IsBusinessReject to be false\n") + } +} + +func TestUnsupportedMessageType(t *testing.T) { + var ( + expectedRejectReason = 3 + expectedErrorString = "Unsupported Message Type" + expectedIsBusinessReject = true + ) + msgRej := UnsupportedMessageType() + if msgRej.RefTagID() != nil { + t.Errorf("expected: nil, got: %d\n", msgRej.RefTagID()) + } + if strings.Compare(msgRej.Error(), expectedErrorString) != 0 { + t.Errorf("expected: %s, got: %s\n", expectedErrorString, msgRej.Error()) + } + if msgRej.RejectReason() != expectedRejectReason { + t.Errorf("expected: %d, got: %d\n", expectedRejectReason, msgRej.RejectReason()) + } + if msgRej.IsBusinessReject() != expectedIsBusinessReject { + t.Error("Expected IsBusinessReject to be true\n") + } +} + +func TestTagNotDefinedForThisMessageType(t *testing.T) { + var ( + expectedErrorString = "Tag not defined for this message type" + expectedRejectReason = 2 + expectedRefTagID Tag = 44 + expectedIsBusinessReject = false + ) + msgRej := TagNotDefinedForThisMessageType(expectedRefTagID) + + if strings.Compare(msgRej.Error(), expectedErrorString) != 0 { + t.Errorf("expected: %s, got: %s\n", expectedErrorString, msgRej.Error()) + } + if msgRej.RejectReason() != expectedRejectReason { + t.Errorf("expected: %d, got: %d\n", expectedRejectReason, msgRej.RejectReason()) + } + if *msgRej.RefTagID() != expectedRefTagID { + t.Errorf("expected: %d, got: %d\n", expectedRefTagID, msgRej.RefTagID()) + } + if msgRej.IsBusinessReject() != expectedIsBusinessReject { + t.Error("Expected IsBusinessReject to be false\n") + } +} + +func TestRequiredTagMissing(t *testing.T) { + var ( + expectedErrorString = "Required tag missing" + expectedRejectReason = 1 + expectedRefTagID Tag = 44 + expectedIsBusinessReject = false + ) + msgRej := RequiredTagMissing(expectedRefTagID) + + if strings.Compare(msgRej.Error(), expectedErrorString) != 0 { + t.Errorf("expected: %s, got: %s\n", expectedErrorString, msgRej.Error()) + } + if msgRej.RejectReason() != expectedRejectReason { + t.Errorf("expected: %d, got: %d\n", expectedRejectReason, msgRej.RejectReason()) + } + if *msgRej.RefTagID() != expectedRefTagID { + t.Errorf("expected: %d, got: %d\n", expectedRefTagID, msgRej.RefTagID()) + } + if msgRej.IsBusinessReject() != expectedIsBusinessReject { + t.Error("Expected IsBusinessReject to be false\n") + } +} + +func TestTagSpecifiedWithoutAValue(t *testing.T) { + var ( + expectedErrorString = "Tag specified without a value" + expectedRejectReason = 4 + expectedRefTagID Tag = 44 + expectedIsBusinessReject = false + ) + msgRej := TagSpecifiedWithoutAValue(expectedRefTagID) + + if strings.Compare(msgRej.Error(), expectedErrorString) != 0 { + t.Errorf("expected: %s, got: %s\n", expectedErrorString, msgRej.Error()) + } + if msgRej.RejectReason() != expectedRejectReason { + t.Errorf("expected: %d, got: %d\n", expectedRejectReason, msgRej.RejectReason()) + } + if *msgRej.RefTagID() != expectedRefTagID { + t.Errorf("expected: %d, got: %d\n", expectedRefTagID, msgRej.RefTagID()) + } + if msgRej.IsBusinessReject() != expectedIsBusinessReject { + t.Error("Expected IsBusinessReject to be false\n") + } +} + +func TestInvalidTagNumber(t *testing.T) { + var ( + expectedErrorString = "Invalid tag number" + expectedRejectReason = 0 + expectedRefTagID Tag = 44 + expectedIsBusinessReject = false + ) + msgRej := InvalidTagNumber(expectedRefTagID) + + if strings.Compare(msgRej.Error(), expectedErrorString) != 0 { + t.Errorf("expected: %s, got: %s\n", expectedErrorString, msgRej.Error()) + } + if msgRej.RejectReason() != expectedRejectReason { + t.Errorf("expected: %d, got: %d\n", expectedRejectReason, msgRej.RejectReason()) + } + if *msgRej.RefTagID() != expectedRefTagID { + t.Errorf("expected: %d, got: %d\n", expectedRefTagID, msgRej.RefTagID()) + } + if msgRej.IsBusinessReject() != expectedIsBusinessReject { + t.Error("Expected IsBusinessReject to be false\n") + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/field.go b/vendor/github.com/quickfixgo/quickfix/field.go index 9df747e..044e314 100644 --- a/vendor/github.com/quickfixgo/quickfix/field.go +++ b/vendor/github.com/quickfixgo/quickfix/field.go @@ -33,18 +33,18 @@ type Field interface { //FieldGroupWriter is an interface for writing a FieldGroup type FieldGroupWriter interface { Tag() Tag - Write() TagValues + Write() []TagValue } //FieldGroupReader is an interface for reading a FieldGroup type FieldGroupReader interface { Tag() Tag - Read(TagValues) (TagValues, error) + Read([]TagValue) ([]TagValue, error) } //FieldGroup is the interface implemented by all typed Groups in a Message type FieldGroup interface { Tag() Tag - Write() TagValues - Read(TagValues) (TagValues, error) + Write() []TagValue + Read([]TagValue) ([]TagValue, error) } diff --git a/vendor/github.com/quickfixgo/quickfix/field/field.go b/vendor/github.com/quickfixgo/quickfix/field/field.go deleted file mode 100644 index da31e81..0000000 --- a/vendor/github.com/quickfixgo/quickfix/field/field.go +++ /dev/null @@ -1,2 +0,0 @@ -//Package field declares standard FIX fields. -package field diff --git a/vendor/github.com/quickfixgo/quickfix/field_map.go b/vendor/github.com/quickfixgo/quickfix/field_map.go index 82d8454..a5e08d4 100644 --- a/vendor/github.com/quickfixgo/quickfix/field_map.go +++ b/vendor/github.com/quickfixgo/quickfix/field_map.go @@ -3,12 +3,24 @@ package quickfix import ( "bytes" "sort" + "time" ) -//FieldMap is a collection of fix fields that make up a fix message. -type FieldMap struct { - tagLookup map[Tag]TagValues - tagOrder +//field stores a slice of TagValues +type field []TagValue + +func fieldTag(f field) Tag { + return f[0].tag +} + +func initField(f field, tag Tag, value []byte) { + f[0].init(tag, value) +} + +func writeField(f field, buffer *bytes.Buffer) { + for _, tv := range f { + buffer.Write(tv.bytes) + } } // tagOrder true if tag i should occur before tag j @@ -23,6 +35,12 @@ func (t tagSort) Len() int { return len(t.tags) } func (t tagSort) Swap(i, j int) { t.tags[i], t.tags[j] = t.tags[j], t.tags[i] } func (t tagSort) Less(i, j int) bool { return t.compare(t.tags[i], t.tags[j]) } +//FieldMap is a collection of fix fields that make up a fix message. +type FieldMap struct { + tagLookup map[Tag]field + tagSort +} + // ascending tags func normalFieldOrder(i, j Tag) bool { return i < j } @@ -31,8 +49,8 @@ func (m *FieldMap) init() { } func (m *FieldMap) initWithOrdering(ordering tagOrder) { - m.tagLookup = make(map[Tag]TagValues) - m.tagOrder = ordering + m.tagLookup = make(map[Tag]field) + m.compare = ordering } //Tags returns all of the Field Tags in this FieldMap @@ -58,18 +76,28 @@ func (m FieldMap) Has(tag Tag) bool { //GetField parses of a field with Tag tag. Returned reject may indicate the field is not present, or the field value is invalid. func (m FieldMap) GetField(tag Tag, parser FieldValueReader) MessageRejectError { - tagValues, ok := m.tagLookup[tag] + f, ok := m.tagLookup[tag] if !ok { return ConditionallyRequiredFieldMissing(tag) } - if err := parser.Read(tagValues[0].value); err != nil { + if err := parser.Read(f[0].value); err != nil { return IncorrectDataFormatForValue(tag) } return nil } +//GetBytes is a zero-copy GetField wrapper for []bytes fields +func (m FieldMap) GetBytes(tag Tag) ([]byte, MessageRejectError) { + f, ok := m.tagLookup[tag] + if !ok { + return nil, ConditionallyRequiredFieldMissing(tag) + } + + return f[0].value, nil +} + //GetBool is a GetField wrapper for bool fields func (m FieldMap) GetBool(tag Tag) (bool, MessageRejectError) { var val FIXBoolean @@ -81,11 +109,32 @@ func (m FieldMap) GetBool(tag Tag) (bool, MessageRejectError) { //GetInt is a GetField wrapper for int fields func (m FieldMap) GetInt(tag Tag) (int, MessageRejectError) { - var val FIXInt - if err := m.GetField(tag, &val); err != nil { + bytes, err := m.GetBytes(tag) + if err != nil { return 0, err } - return int(val), nil + + var val FIXInt + if val.Read(bytes) != nil { + err = IncorrectDataFormatForValue(tag) + } + + return int(val), err +} + +//GetTime is a GetField wrapper for utc timestamp fields +func (m FieldMap) GetTime(tag Tag) (t time.Time, err MessageRejectError) { + bytes, err := m.GetBytes(tag) + if err != nil { + return + } + + var val FIXUTCTimestamp + if val.Read(bytes) != nil { + err = IncorrectDataFormatForValue(tag) + } + + return val.Time, err } //GetString is a GetField wrapper for string fields @@ -99,12 +148,12 @@ func (m FieldMap) GetString(tag Tag) (string, MessageRejectError) { //GetGroup is a Get function specific to Group Fields. func (m FieldMap) GetGroup(parser FieldGroupReader) MessageRejectError { - tagValues, ok := m.tagLookup[parser.Tag()] + f, ok := m.tagLookup[parser.Tag()] if !ok { return ConditionallyRequiredFieldMissing(parser.Tag()) } - if _, err := parser.Read(tagValues); err != nil { + if _, err := parser.Read(f); err != nil { if msgRejErr, ok := err.(MessageRejectError); ok { return msgRejErr } @@ -115,65 +164,88 @@ func (m FieldMap) GetGroup(parser FieldGroupReader) MessageRejectError { } //SetField sets the field with Tag tag -func (m FieldMap) SetField(tag Tag, field FieldValueWriter) FieldMap { - tValues := make(TagValues, 1) - tValues[0].init(tag, field.Write()) - m.tagLookup[tag] = tValues +func (m *FieldMap) SetField(tag Tag, field FieldValueWriter) *FieldMap { + return m.SetBytes(tag, field.Write()) +} + +//SetBytes sets bytes +func (m *FieldMap) SetBytes(tag Tag, value []byte) *FieldMap { + f := m.getOrCreate(tag) + initField(f, tag, value) return m } //SetBool is a SetField wrapper for bool fields -func (m FieldMap) SetBool(tag Tag, value bool) FieldMap { +func (m *FieldMap) SetBool(tag Tag, value bool) *FieldMap { return m.SetField(tag, FIXBoolean(value)) } //SetInt is a SetField wrapper for int fields -func (m FieldMap) SetInt(tag Tag, value int) FieldMap { - return m.SetField(tag, FIXInt(value)) +func (m *FieldMap) SetInt(tag Tag, value int) *FieldMap { + v := FIXInt(value) + return m.SetBytes(tag, v.Write()) } //SetString is a SetField wrapper for string fields -func (m FieldMap) SetString(tag Tag, value string) FieldMap { - return m.SetField(tag, FIXString(value)) +func (m *FieldMap) SetString(tag Tag, value string) *FieldMap { + return m.SetBytes(tag, []byte(value)) } //Clear purges all fields from field map func (m *FieldMap) Clear() { - m.tagLookup = make(map[Tag]TagValues) + m.tags = m.tags[0:0] + for k := range m.tagLookup { + delete(m.tagLookup, k) + } +} + +func (m *FieldMap) add(f field) { + t := fieldTag(f) + if _, ok := m.tagLookup[t]; !ok { + m.tags = append(m.tags, t) + } + + m.tagLookup[t] = f +} + +func (m *FieldMap) getOrCreate(tag Tag) field { + if f, ok := m.tagLookup[tag]; ok { + f = f[:1] + return f + } + + f := make(field, 1) + m.tagLookup[tag] = f + m.tags = append(m.tags, tag) + return f } //Set is a setter for fields -func (m FieldMap) Set(field FieldWriter) FieldMap { - tValues := make(TagValues, 1) - tValues[0].init(field.Tag(), field.Write()) - m.tagLookup[field.Tag()] = tValues +func (m *FieldMap) Set(field FieldWriter) *FieldMap { + f := m.getOrCreate(field.Tag()) + initField(f, field.Tag(), field.Write()) return m } //SetGroup is a setter specific to group fields -func (m FieldMap) SetGroup(field FieldGroupWriter) FieldMap { +func (m *FieldMap) SetGroup(field FieldGroupWriter) *FieldMap { + _, ok := m.tagLookup[field.Tag()] + if !ok { + m.tags = append(m.tags, field.Tag()) + } m.tagLookup[field.Tag()] = field.Write() return m } -func (m FieldMap) sortedTags() []Tag { - sortedTags := make([]Tag, len(m.tagLookup)) - for tag := range m.tagLookup { - sortedTags = append(sortedTags, tag) - } - - sort.Sort(tagSort{sortedTags, m.tagOrder}) - return sortedTags +func (m *FieldMap) sortedTags() []Tag { + sort.Sort(m) + return m.tags } func (m FieldMap) write(buffer *bytes.Buffer) { - tags := m.sortedTags() - - for _, tag := range tags { - if fields, ok := m.tagLookup[tag]; ok { - for _, tv := range fields { - buffer.Write(tv.bytes) - } + for _, tag := range m.sortedTags() { + if f, ok := m.tagLookup[tag]; ok { + writeField(f, buffer) } } } diff --git a/vendor/github.com/quickfixgo/quickfix/field_map_test.go b/vendor/github.com/quickfixgo/quickfix/field_map_test.go new file mode 100644 index 0000000..ce6a791 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/field_map_test.go @@ -0,0 +1,127 @@ +package quickfix + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFieldMap_Clear(t *testing.T) { + var fMap FieldMap + fMap.init() + + fMap.SetField(1, FIXString("hello")) + fMap.SetField(2, FIXString("world")) + + fMap.Clear() + + if fMap.Has(1) || fMap.Has(2) { + t.Error("All fields should be cleared") + } +} + +func TestFieldMap_SetAndGet(t *testing.T) { + var fMap FieldMap + fMap.init() + + fMap.SetField(1, FIXString("hello")) + fMap.SetField(2, FIXString("world")) + + var testCases = []struct { + tag Tag + expectErr bool + expectValue string + }{ + {tag: 1, expectValue: "hello"}, + {tag: 2, expectValue: "world"}, + {tag: 44, expectErr: true}, + } + + for _, tc := range testCases { + var testField FIXString + err := fMap.GetField(tc.tag, &testField) + + if tc.expectErr { + assert.NotNil(t, err, "Expected Error") + continue + } + + assert.Nil(t, err, "Unexpected error") + assert.Equal(t, tc.expectValue, string(testField)) + } +} + +func TestFieldMap_Length(t *testing.T) { + var fMap FieldMap + fMap.init() + fMap.SetField(1, FIXString("hello")) + fMap.SetField(2, FIXString("world")) + fMap.SetField(8, FIXString("FIX.4.4")) + fMap.SetField(9, FIXInt(100)) + fMap.SetField(10, FIXString("100")) + assert.Equal(t, 16, fMap.length(), "Length should include all fields but beginString, bodyLength, and checkSum") +} + +func TestFieldMap_Total(t *testing.T) { + + var fMap FieldMap + fMap.init() + fMap.SetField(1, FIXString("hello")) + fMap.SetField(2, FIXString("world")) + fMap.SetField(8, FIXString("FIX.4.4")) + fMap.SetField(Tag(9), FIXInt(100)) + fMap.SetField(10, FIXString("100")) + + assert.Equal(t, 2116, fMap.total(), "Total should includes all fields but checkSum") +} + +func TestFieldMap_TypedSetAndGet(t *testing.T) { + var fMap FieldMap + fMap.init() + + fMap.SetString(1, "hello") + fMap.SetInt(2, 256) + + s, err := fMap.GetString(1) + assert.Nil(t, err) + assert.Equal(t, "hello", s) + + i, err := fMap.GetInt(2) + assert.Nil(t, err) + assert.Equal(t, 256, i) + + _, err = fMap.GetInt(1) + assert.NotNil(t, err, "Type mismatch should occur error") + + s, err = fMap.GetString(2) + assert.Nil(t, err) + assert.Equal(t, "256", s) + + b, err := fMap.GetBytes(1) + assert.Nil(t, err) + assert.True(t, bytes.Equal([]byte("hello"), b)) +} + +func TestFieldMap_BoolTypedSetAndGet(t *testing.T) { + var fMap FieldMap + fMap.init() + + fMap.SetBool(1, true) + v, err := fMap.GetBool(1) + assert.Nil(t, err) + assert.True(t, v) + + s, err := fMap.GetString(1) + assert.Nil(t, err) + assert.Equal(t, "Y", s) + + fMap.SetBool(2, false) + v, err = fMap.GetBool(2) + assert.Nil(t, err) + assert.False(t, v) + + s, err = fMap.GetString(2) + assert.Nil(t, err) + assert.Equal(t, "N", s) +} diff --git a/vendor/github.com/quickfixgo/quickfix/file_log.go b/vendor/github.com/quickfixgo/quickfix/file_log.go index 536792a..02f27b0 100644 --- a/vendor/github.com/quickfixgo/quickfix/file_log.go +++ b/vendor/github.com/quickfixgo/quickfix/file_log.go @@ -14,12 +14,12 @@ type fileLog struct { messageLogger *log.Logger } -func (l fileLog) OnIncoming(msg string) { - l.messageLogger.Print(msg) +func (l fileLog) OnIncoming(msg []byte) { + l.messageLogger.Print(string(msg)) } -func (l fileLog) OnOutgoing(msg string) { - l.messageLogger.Print(msg) +func (l fileLog) OnOutgoing(msg []byte) { + l.messageLogger.Print(string(msg)) } func (l fileLog) OnEvent(msg string) { diff --git a/vendor/github.com/quickfixgo/quickfix/file_log_test.go b/vendor/github.com/quickfixgo/quickfix/file_log_test.go new file mode 100644 index 0000000..b807dca --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/file_log_test.go @@ -0,0 +1,130 @@ +package quickfix + +import ( + "bufio" + "fmt" + "os" + "path" + "strings" + "testing" +) + +func TestFileLog_NewFileLogFactory(t *testing.T) { + + factory, err := NewFileLogFactory(NewSettings()) + + if err == nil { + t.Error("Should expect error when settings have no file log path") + } + + cfg := ` +# default settings for sessions +[DEFAULT] +ConnectionType=initiator +ReconnectInterval=60 +SenderCompID=TW +FileLogPath=. + +# session definition +[SESSION] +BeginString=FIX.4.1 +TargetCompID=ARCA +FileLogPath=mydir + +[SESSION] +BeginString=FIX.4.1 +TargetCompID=ARCA +SessionQualifier=BS +` + stringReader := strings.NewReader(cfg) + settings, _ := ParseSettings(stringReader) + + factory, err = NewFileLogFactory(settings) + + if err != nil { + t.Error("Did not expect error", err) + } + + if factory == nil { + t.Error("Should have returned factory") + } +} + +type fileLogHelper struct { + LogPath string + Prefix string + Log Log +} + +func newFileLogHelper(t *testing.T) *fileLogHelper { + prefix := "myprefix" + logPath := path.Join(os.TempDir(), fmt.Sprintf("TestLogStore-%d", os.Getpid())) + + log, err := newFileLog(prefix, logPath) + if err != nil { + t.Error("Unexpected error", err) + } + + return &fileLogHelper{ + LogPath: logPath, + Prefix: prefix, + Log: log, + } +} + +func TestNewFileLog(t *testing.T) { + helper := newFileLogHelper(t) + + tests := []struct { + expectedPath string + }{ + {path.Join(helper.LogPath, fmt.Sprintf("%v.messages.current.log", helper.Prefix))}, + {path.Join(helper.LogPath, fmt.Sprintf("%v.event.current.log", helper.Prefix))}, + } + + for _, test := range tests { + if _, err := os.Stat(test.expectedPath); os.IsNotExist(err) { + t.Errorf("%v does not exist", test.expectedPath) + } + } +} + +func TestFileLog_Append(t *testing.T) { + helper := newFileLogHelper(t) + + messageLogFile, err := os.Open(path.Join(helper.LogPath, fmt.Sprintf("%v.messages.current.log", helper.Prefix))) + if err != nil { + t.Error("Unexpected error", err) + } + defer messageLogFile.Close() + + eventLogFile, err := os.Open(path.Join(helper.LogPath, fmt.Sprintf("%v.event.current.log", helper.Prefix))) + if err != nil { + t.Error("Unexpected error", err) + } + defer eventLogFile.Close() + + messageScanner := bufio.NewScanner(messageLogFile) + eventScanner := bufio.NewScanner(eventLogFile) + + helper.Log.OnIncoming([]byte("incoming")) + if !messageScanner.Scan() { + t.Error("Unexpected EOF") + } + + helper.Log.OnEvent("Event") + if !eventScanner.Scan() { + t.Error("Unexpected EOF") + } + + newHelper := newFileLogHelper(t) + newHelper.Log.OnIncoming([]byte("incoming")) + if !messageScanner.Scan() { + t.Error("Unexpected EOF") + } + + newHelper.Log.OnEvent("Event") + if !eventScanner.Scan() { + t.Error("Unexpected EOF") + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/filestore_test.go b/vendor/github.com/quickfixgo/quickfix/filestore_test.go new file mode 100644 index 0000000..56fc8ec --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/filestore_test.go @@ -0,0 +1,49 @@ +package quickfix + +import ( + "fmt" + "os" + "path" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +// FileStoreTestSuite runs all tests in the MessageStoreTestSuite against the FileStore implementation +type FileStoreTestSuite struct { + MessageStoreTestSuite + fileStoreRootPath string +} + +func (suite *FileStoreTestSuite) SetupTest() { + suite.fileStoreRootPath = path.Join(os.TempDir(), fmt.Sprintf("FileStoreTestSuite-%d", os.Getpid())) + fileStorePath := path.Join(suite.fileStoreRootPath, fmt.Sprintf("%d", time.Now().UnixNano())) + sessionID := SessionID{BeginString: "FIX.4.4", SenderCompID: "SENDER", TargetCompID: "TARGET"} + + // create settings + settings, err := ParseSettings(strings.NewReader(fmt.Sprintf(` +[DEFAULT] +FileStorePath=%s + +[SESSION] +BeginString=%s +SenderCompID=%s +TargetCompID=%s`, fileStorePath, sessionID.BeginString, sessionID.SenderCompID, sessionID.TargetCompID))) + require.Nil(suite.T(), err) + + // create store + suite.msgStore, err = NewFileStoreFactory(settings).Create(sessionID) + require.Nil(suite.T(), err) +} + +func (suite *FileStoreTestSuite) TearDownTest() { + suite.msgStore.Close() + os.RemoveAll(suite.fileStoreRootPath) +} + +func TestFileStoreTestSuite(t *testing.T) { + suite.Run(t, new(FileStoreTestSuite)) +} diff --git a/vendor/github.com/quickfixgo/quickfix/fileutil_test.go b/vendor/github.com/quickfixgo/quickfix/fileutil_test.go new file mode 100644 index 0000000..4817c78 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/fileutil_test.go @@ -0,0 +1,65 @@ +package quickfix + +import ( + "fmt" + "os" + "path" + "testing" + + "github.com/stretchr/testify/require" +) + +func requireNotFileExists(t *testing.T, fname string) { + _, err := os.Stat(fname) + require.NotNil(t, err) + require.True(t, os.IsNotExist(err)) +} + +func requireFileExists(t *testing.T, fname string) { + _, err := os.Stat(fname) + require.Nil(t, err) +} + +func TestSessionIDFilename_MinimallyQualifiedSessionID(t *testing.T) { + // When the session ID is + sessionID := SessionID{BeginString: "FIX.4.4", SenderCompID: "SENDER", TargetCompID: "TARGET"} + + // Then the filename should be + require.Equal(t, "FIX.4.4-SENDER-TARGET", sessionIDFilenamePrefix(sessionID)) +} + +func TestSessionIDFilename_FullyQualifiedSessionID(t *testing.T) { + // When the session ID is + sessionID := SessionID{ + BeginString: "FIX.4.4", + SenderCompID: "A", + SenderSubID: "B", + SenderLocationID: "C", + TargetCompID: "D", + TargetSubID: "E", + TargetLocationID: "F", + Qualifier: "G", + } + + // Then the filename should be + require.Equal(t, "FIX.4.4-A_B_C-D_E_F-G", sessionIDFilenamePrefix(sessionID)) +} + +func TestOpenOrCreateFile(t *testing.T) { + // When the file doesn't exist yet + fname := path.Join(os.TempDir(), fmt.Sprintf("TestOpenOrCreateFile-%d", os.Getpid())) + requireNotFileExists(t, fname) + defer os.Remove(fname) + + // Then it should be created + f, err := openOrCreateFile(fname, 0664) + requireFileExists(t, fname) + + // When the file already exists + f.Close() + + // Then it should be opened + f, err = openOrCreateFile(fname, 0664) + require.Nil(t, err) + require.Nil(t, f.Close()) +} diff --git a/vendor/github.com/quickfixgo/quickfix/fix_boolean_test.go b/vendor/github.com/quickfixgo/quickfix/fix_boolean_test.go new file mode 100644 index 0000000..150d8c0 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/fix_boolean_test.go @@ -0,0 +1,44 @@ +package quickfix + +import ( + "bytes" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBooleanWrite(t *testing.T) { + var tests = []struct { + val FIXBoolean + expected []byte + }{ + {FIXBoolean(true), []byte("Y")}, + {FIXBoolean(false), []byte("N")}, + } + + for _, test := range tests { + b := test.val.Write() + assert.True(t, bytes.Equal(b, test.expected), fmt.Sprintf("got %v; want %v", b, test.expected)) + } +} + +func TestFIXBooleanRead(t *testing.T) { + var tests = []struct { + bytes []byte + expected bool + expectError bool + }{ + {[]byte("Y"), true, false}, + {[]byte("N"), false, false}, + {[]byte("blah"), false, true}, + } + + for _, test := range tests { + var val FIXBoolean + err := val.Read(test.bytes) + + assert.Equal(t, test.expectError, err != nil) + assert.Equal(t, test.expected, val.Bool()) + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/fix_bytes.go b/vendor/github.com/quickfixgo/quickfix/fix_bytes.go new file mode 100644 index 0000000..5e3bb13 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/fix_bytes.go @@ -0,0 +1,13 @@ +package quickfix + +//FIXBytes is a generic FIX field value, implements FieldValue. Enables zero copy read from a FieldMap +type FIXBytes []byte + +func (f *FIXBytes) Read(bytes []byte) (err error) { + *f = FIXBytes(bytes) + return +} + +func (f FIXBytes) Write() []byte { + return []byte(f) +} diff --git a/vendor/github.com/quickfixgo/quickfix/fix_bytes_test.go b/vendor/github.com/quickfixgo/quickfix/fix_bytes_test.go new file mode 100644 index 0000000..4dc94b5 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/fix_bytes_test.go @@ -0,0 +1,22 @@ +package quickfix + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFIXBytesWrite(t *testing.T) { + val := []byte("hello") + field := FIXBytes(val) + b := field.Write() + + assert.Equal(t, val, b) +} + +func TestFIXBytesRead(t *testing.T) { + val := []byte("world") + var field FIXBytes + assert.Nil(t, field.Read(val)) + assert.Equal(t, val, []byte(field)) +} diff --git a/vendor/github.com/quickfixgo/quickfix/fix_decimal_test.go b/vendor/github.com/quickfixgo/quickfix/fix_decimal_test.go new file mode 100644 index 0000000..1785d6e --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/fix_decimal_test.go @@ -0,0 +1,51 @@ +package quickfix + +import ( + "testing" + + "github.com/shopspring/decimal" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestFIXDecimalWrite(t *testing.T) { + var tests = []struct { + decimal FIXDecimal + expected string + }{ + {decimal: FIXDecimal{Decimal: decimal.New(-1243456, -4), Scale: 4}, expected: "-124.3456"}, + {decimal: FIXDecimal{Decimal: decimal.New(-1243456, -4), Scale: 5}, expected: "-124.34560"}, + {decimal: FIXDecimal{Decimal: decimal.New(-1243456, -4), Scale: 0}, expected: "-124"}, + } + + for _, test := range tests { + b := test.decimal.Write() + assert.Equal(t, test.expected, string(b)) + } +} + +func TestFIXDecimalRead(t *testing.T) { + var tests = []struct { + bytes string + expected decimal.Decimal + expectError bool + }{ + {bytes: "15", expected: decimal.New(15, 0)}, + {bytes: "15.000", expected: decimal.New(15, 0)}, + {bytes: "15.001", expected: decimal.New(15001, -3)}, + {bytes: "-15.001", expected: decimal.New(-15001, -3)}, + {bytes: "blah", expectError: true}, + {bytes: "+200.00", expected: decimal.New(200, 0)}, + } + + for _, test := range tests { + var field FIXDecimal + + err := field.Read([]byte(test.bytes)) + require.Equal(t, test.expectError, err != nil) + + if !test.expectError { + assert.True(t, test.expected.Equals(field.Decimal), "Expected %s got %s", test.expected, field.Decimal) + } + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/fix_float_test.go b/vendor/github.com/quickfixgo/quickfix/fix_float_test.go new file mode 100644 index 0000000..b31bdbb --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/fix_float_test.go @@ -0,0 +1,56 @@ +package quickfix + +import ( + "bytes" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFloatWrite(t *testing.T) { + var tests = []struct { + field FIXFloat + val []byte + }{ + {FIXFloat(5.0), []byte("5")}, + } + + for _, test := range tests { + b := test.field.Write() + + assert.True(t, bytes.Equal(b, test.val), fmt.Sprintf("got %v; want %v", b, test.val)) + } +} + +func TestFloatRead(t *testing.T) { + var tests = []struct { + bytes []byte + value float64 + expectError bool + }{ + {[]byte("15"), 15.0, false}, + {[]byte("99.9"), 99.9, false}, + {[]byte("0.00"), 0.0, false}, + {[]byte("-99.9"), -99.9, false}, + {[]byte("-99.9.9"), 0.0, true}, + {[]byte("blah"), 0.0, true}, + {[]byte("1.a1"), 0.0, true}, + {[]byte("+200.00"), 0.0, true}, + } + + for _, test := range tests { + var field FIXFloat + err := field.Read(test.bytes) + assert.Equal(t, test.expectError, err != nil) + assert.Equal(t, test.value, field.Float64()) + } +} + +func BenchmarkFloatRead(b *testing.B) { + val := []byte("15.1234") + for i := 0; i < b.N; i++ { + var field FIXFloat + _ = field.Read(val) + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/fix_int.go b/vendor/github.com/quickfixgo/quickfix/fix_int.go index 3185d6d..b369511 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix_int.go +++ b/vendor/github.com/quickfixgo/quickfix/fix_int.go @@ -59,5 +59,5 @@ func (f *FIXInt) Read(bytes []byte) error { } func (f FIXInt) Write() []byte { - return []byte(strconv.Itoa(int(f))) + return strconv.AppendInt(nil, int64(f), 10) } diff --git a/vendor/github.com/quickfixgo/quickfix/fix_int_test.go b/vendor/github.com/quickfixgo/quickfix/fix_int_test.go new file mode 100644 index 0000000..173cb5e --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/fix_int_test.go @@ -0,0 +1,37 @@ +package quickfix + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFIXInt_Write(t *testing.T) { + field := FIXInt(5) + + assert.Equal(t, "5", string(field.Write())) +} + +func TestFIXInt_Read(t *testing.T) { + var field FIXInt + err := field.Read([]byte("15")) + assert.Nil(t, err, "Unexpected error") + assert.Equal(t, 15, int(field)) + + err = field.Read([]byte("blah")) + assert.NotNil(t, err, "Unexpected error") +} + +func TestFIXInt_Int(t *testing.T) { + f := FIXInt(4) + assert.Equal(t, 4, f.Int()) +} + +func BenchmarkFIXInt_Read(b *testing.B) { + intBytes := []byte("1500") + var field FIXInt + + for i := 0; i < b.N; i++ { + field.Read(intBytes) + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/fix_string_test.go b/vendor/github.com/quickfixgo/quickfix/fix_string_test.go new file mode 100644 index 0000000..f2672f3 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/fix_string_test.go @@ -0,0 +1,48 @@ +package quickfix + +import ( + "bytes" + "testing" +) + +func TestFIXStringWrite(t *testing.T) { + var tests = []struct { + field FIXString + val []byte + }{ + {"CWB", []byte("CWB")}, + } + + for _, test := range tests { + b := test.field.Write() + + if !bytes.Equal(b, test.val) { + t.Errorf("got %v; want %v", b, test.val) + } + } +} + +func TestFIXStringRead(t *testing.T) { + var tests = []struct { + bytes []byte + value string + expectError bool + }{ + {[]byte("blah"), "blah", false}, + } + + for _, test := range tests { + var field FIXString + err := field.Read(test.bytes) + + if test.expectError && err == nil { + t.Errorf("Expected error for %v", test.bytes) + } else if !test.expectError && err != nil { + t.Errorf("UnExpected '%v'", err) + } + + if string(field) != test.value { + t.Errorf("got %v want %v", field, test.value) + } + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/fix_utc_timestamp.go b/vendor/github.com/quickfixgo/quickfix/fix_utc_timestamp.go index 83b6559..82c2c2f 100644 --- a/vendor/github.com/quickfixgo/quickfix/fix_utc_timestamp.go +++ b/vendor/github.com/quickfixgo/quickfix/fix_utc_timestamp.go @@ -1,40 +1,71 @@ package quickfix import ( + "errors" "time" ) +//TimestampPrecision defines the precision used by FIXUTCTimestamp +type TimestampPrecision int + +//All TimestampPrecisions supported by FIX +const ( + Millis TimestampPrecision = iota + Seconds + Micros + Nanos +) + //FIXUTCTimestamp is a FIX UTC Timestamp value, implements FieldValue type FIXUTCTimestamp struct { time.Time - NoMillis bool + Precision TimestampPrecision } const ( - utcTimestampFormat = "20060102-15:04:05.000" - utcTimestampNoMillisFormat = "20060102-15:04:05" + utcTimestampMillisFormat = "20060102-15:04:05.000" + utcTimestampSecondsFormat = "20060102-15:04:05" + utcTimestampMicrosFormat = "20060102-15:04:05.000000" + utcTimestampNanosFormat = "20060102-15:04:05.000000000" ) -func (f *FIXUTCTimestamp) Read(bytes []byte) error { - var err error - //with millisecs - if f.Time, err = time.Parse(utcTimestampFormat, string(bytes)); err == nil { - return nil - } +func (f *FIXUTCTimestamp) Read(bytes []byte) (err error) { + switch len(bytes) { + //seconds + case 17: + f.Time, err = time.Parse(utcTimestampSecondsFormat, string(bytes)) + f.Precision = Seconds - //w/o millisecs - if f.Time, err = time.Parse(utcTimestampNoMillisFormat, string(bytes)); err != nil { - return err + //millis + case 21: + f.Time, err = time.Parse(utcTimestampMillisFormat, string(bytes)) + f.Precision = Millis + + // micros + case 24: + f.Time, err = time.Parse(utcTimestampMicrosFormat, string(bytes)) + f.Precision = Micros + + // nanos + case 27: + f.Time, err = time.Parse(utcTimestampNanosFormat, string(bytes)) + f.Precision = Nanos + + default: + err = errors.New("Invalid Value for Timestamp: " + string(bytes)) } - f.NoMillis = true - return nil + return } func (f FIXUTCTimestamp) Write() []byte { - if f.NoMillis { - return []byte(f.UTC().Format(utcTimestampNoMillisFormat)) + switch f.Precision { + case Seconds: + return []byte(f.UTC().Format(utcTimestampSecondsFormat)) + case Micros: + return []byte(f.UTC().Format(utcTimestampMicrosFormat)) + case Nanos: + return []byte(f.UTC().Format(utcTimestampNanosFormat)) } - - return []byte(f.UTC().Format(utcTimestampFormat)) + return []byte(f.UTC().Format(utcTimestampMillisFormat)) } diff --git a/vendor/github.com/quickfixgo/quickfix/fix_utc_timestamp_test.go b/vendor/github.com/quickfixgo/quickfix/fix_utc_timestamp_test.go new file mode 100644 index 0000000..b290395 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/fix_utc_timestamp_test.go @@ -0,0 +1,63 @@ +package quickfix_test + +import ( + "bytes" + "testing" + "time" + + "github.com/quickfixgo/quickfix" +) + +func TestFIXUTCTimestampWrite(t *testing.T) { + ts := time.Date(2016, time.February, 8, 22, 7, 16, 954123123, time.UTC) + + var tests = []struct { + precision quickfix.TimestampPrecision + val []byte + }{ + {quickfix.Millis, []byte("20160208-22:07:16.954")}, + {quickfix.Seconds, []byte("20160208-22:07:16")}, + {quickfix.Micros, []byte("20160208-22:07:16.954123")}, + {quickfix.Nanos, []byte("20160208-22:07:16.954123123")}, + } + + for _, test := range tests { + var f quickfix.FIXUTCTimestamp + f.Time = ts + f.Precision = test.precision + + b := f.Write() + + if !bytes.Equal(b, test.val) { + t.Errorf("got %s; want %s", b, test.val) + } + } +} + +func TestFIXUTCTimestampRead(t *testing.T) { + var tests = []struct { + timeStr string + expectedTime time.Time + expectedPrecision quickfix.TimestampPrecision + }{ + {"20160208-22:07:16.310", time.Date(2016, time.February, 8, 22, 7, 16, 310000000, time.UTC), quickfix.Millis}, + {"20160208-22:07:16", time.Date(2016, time.February, 8, 22, 7, 16, 0, time.UTC), quickfix.Seconds}, + {"20160208-22:07:16.123455", time.Date(2016, time.February, 8, 22, 7, 16, 123455000, time.UTC), quickfix.Micros}, + {"20160208-22:07:16.954123123", time.Date(2016, time.February, 8, 22, 7, 16, 954123123, time.UTC), quickfix.Nanos}, + } + + for _, test := range tests { + var f quickfix.FIXUTCTimestamp + if err := f.Read([]byte(test.timeStr)); err != nil { + t.Errorf("Unexpected error: %v", err) + } + + if !f.Time.Equal(test.expectedTime) { + t.Errorf("For Time expected %v got %v", test.expectedTime, f.Time) + } + + if f.Precision != test.expectedPrecision { + t.Errorf("For NoMillis expected %v got %v", test.expectedPrecision, f.Precision) + } + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/in_session.go b/vendor/github.com/quickfixgo/quickfix/in_session.go index e1bc49f..d4dfc70 100644 --- a/vendor/github.com/quickfixgo/quickfix/in_session.go +++ b/vendor/github.com/quickfixgo/quickfix/in_session.go @@ -1,9 +1,9 @@ package quickfix import ( + "bytes" "time" - "github.com/quickfixgo/quickfix/enum" "github.com/quickfixgo/quickfix/internal" ) @@ -11,29 +11,29 @@ type inSession struct{ loggedOn } func (state inSession) String() string { return "In Session" } -func (state inSession) FixMsgIn(session *session, msg Message) sessionState { - var msgType FIXString - if err := msg.Header.GetField(tagMsgType, &msgType); err != nil { +func (state inSession) FixMsgIn(session *session, msg *Message) sessionState { + msgType, err := msg.Header.GetBytes(tagMsgType) + if err != nil { return handleStateError(session, err) } - switch enum.MsgType(msgType) { - case enum.MsgType_LOGON: + switch { + case bytes.Equal(msgTypeLogon, msgType): if err := session.handleLogon(msg); err != nil { - if err := session.initiateLogoutInReplyTo("", &msg); err != nil { + if err := session.initiateLogoutInReplyTo("", msg); err != nil { return handleStateError(session, err) } return logoutState{} } return state - case enum.MsgType_LOGOUT: + case bytes.Equal(msgTypeLogout, msgType): return state.handleLogout(session, msg) - case enum.MsgType_RESEND_REQUEST: + case bytes.Equal(msgTypeResendRequest, msgType): return state.handleResendRequest(session, msg) - case enum.MsgType_SEQUENCE_RESET: + case bytes.Equal(msgTypeSequenceReset, msgType): return state.handleSequenceReset(session, msg) - case enum.MsgType_TEST_REQUEST: + case bytes.Equal(msgTypeTestRequest, msgType): return state.handleTestRequest(session, msg) default: if err := session.verify(msg); err != nil { @@ -71,7 +71,7 @@ func (state inSession) Timeout(session *session, event internal.Event) (nextStat return state } -func (state inSession) handleLogout(session *session, msg Message) (nextState sessionState) { +func (state inSession) handleLogout(session *session, msg *Message) (nextState sessionState) { if err := session.verifySelect(msg, false, false); err != nil { return state.processReject(session, msg, err) } @@ -80,7 +80,7 @@ func (state inSession) handleLogout(session *session, msg Message) (nextState se session.log.OnEvent("Received logout request") session.log.OnEvent("Sending logout response") - if err := session.sendLogoutInReplyTo("", &msg); err != nil { + if err := session.sendLogoutInReplyTo("", msg); err != nil { session.logError(err) } } else { @@ -100,7 +100,7 @@ func (state inSession) handleLogout(session *session, msg Message) (nextState se return latentState{} } -func (state inSession) handleTestRequest(session *session, msg Message) (nextState sessionState) { +func (state inSession) handleTestRequest(session *session, msg *Message) (nextState sessionState) { if err := session.verify(msg); err != nil { return state.processReject(session, msg, err) } @@ -111,7 +111,7 @@ func (state inSession) handleTestRequest(session *session, msg Message) (nextSta heartBt := NewMessage() heartBt.Header.SetField(tagMsgType, FIXString("0")) heartBt.Body.SetField(tagTestReqID, testReq) - if err := session.sendInReplyTo(heartBt, &msg); err != nil { + if err := session.sendInReplyTo(heartBt, msg); err != nil { return handleStateError(session, err) } } @@ -122,7 +122,7 @@ func (state inSession) handleTestRequest(session *session, msg Message) (nextSta return state } -func (state inSession) handleSequenceReset(session *session, msg Message) (nextState sessionState) { +func (state inSession) handleSequenceReset(session *session, msg *Message) (nextState sessionState) { var gapFillFlag FIXBoolean if msg.Body.Has(tagGapFillFlag) { if err := msg.Body.GetField(tagGapFillFlag, &gapFillFlag); err != nil { @@ -154,7 +154,7 @@ func (state inSession) handleSequenceReset(session *session, msg Message) (nextS return state } -func (state inSession) handleResendRequest(session *session, msg Message) (nextState sessionState) { +func (state inSession) handleResendRequest(session *session, msg *Message) (nextState sessionState) { if err := session.verifyIgnoreSeqNumTooHighOrLow(msg); err != nil { return state.processReject(session, msg, err) } @@ -177,13 +177,13 @@ func (state inSession) handleResendRequest(session *session, msg Message) (nextS session.log.OnEventf("Received ResendRequest FROM: %d TO: %d", beginSeqNo, endSeqNo) expectedSeqNum := session.store.NextSenderMsgSeqNum() - if (session.sessionID.BeginString >= enum.BeginStringFIX42 && endSeqNo == 0) || - (session.sessionID.BeginString <= enum.BeginStringFIX42 && endSeqNo == 999999) || + if (session.sessionID.BeginString >= BeginStringFIX42 && endSeqNo == 0) || + (session.sessionID.BeginString <= BeginStringFIX42 && endSeqNo == 999999) || (endSeqNo >= expectedSeqNum) { endSeqNo = expectedSeqNum - 1 } - if err := state.resendMessages(session, int(beginSeqNo), endSeqNo, msg); err != nil { + if err := state.resendMessages(session, int(beginSeqNo), endSeqNo, *msg); err != nil { return handleStateError(session, err) } @@ -202,6 +202,11 @@ func (state inSession) handleResendRequest(session *session, msg Message) (nextS } func (state inSession) resendMessages(session *session, beginSeqNo, endSeqNo int, inReplyTo Message) (err error) { + if session.DisableMessagePersist { + err = state.generateSequenceReset(session, beginSeqNo, endSeqNo+1, inReplyTo) + return + } + msgs, err := session.store.GetMessages(beginSeqNo, endSeqNo) if err != nil { session.log.OnEventf("error retrieving messages from store: %s", err.Error()) @@ -210,9 +215,10 @@ func (state inSession) resendMessages(session *session, beginSeqNo, endSeqNo int seqNum := beginSeqNo nextSeqNum := seqNum + msg := NewMessage() for _, msgBytes := range msgs { - msg, _ := ParseMessage(msgBytes) - msgType, _ := msg.Header.GetString(tagMsgType) + _ = ParseMessageWithDataDictionary(msg, bytes.NewBuffer(msgBytes), session.transportDataDictionary, session.appDataDictionary) + msgType, _ := msg.Header.GetBytes(tagMsgType) sentMessageSeqNum, _ := msg.Header.GetInt(tagMsgSeqNum) if isAdminMessageType(msgType) { @@ -232,10 +238,8 @@ func (state inSession) resendMessages(session *session, beginSeqNo, endSeqNo int } session.log.OnEventf("Resending Message: %v", sentMessageSeqNum) - if _, err := msg.Build(); err != nil { - return err - } - session.sendBytes(msg.rawMessage) + msgBytes = msg.build() + session.sendBytes(msgBytes) seqNum = sentMessageSeqNum + 1 nextSeqNum = seqNum @@ -250,7 +254,7 @@ func (state inSession) resendMessages(session *session, beginSeqNo, endSeqNo int return } -func (state inSession) processReject(session *session, msg Message, rej MessageRejectError) sessionState { +func (state inSession) processReject(session *session, msg *Message, rej MessageRejectError) sessionState { switch TypedError := rej.(type) { case targetTooHigh: @@ -267,10 +271,12 @@ func (state inSession) processReject(session *session, msg Message, rej MessageR } if nextState.messageStash == nil { - nextState.messageStash = make(map[int]Message) + nextState.messageStash = make(map[int]*Message) } nextState.messageStash[TypedError.ReceivedTarget] = msg + //do not reclaim stashed message + msg.keepMessage = true return nextState @@ -305,7 +311,7 @@ func (state inSession) processReject(session *session, msg Message, rej MessageR } } -func (state inSession) doTargetTooLow(session *session, msg Message, rej targetTooLow) (nextState sessionState) { +func (state inSession) doTargetTooLow(session *session, msg *Message, rej targetTooLow) (nextState sessionState) { var posDupFlag FIXBoolean if msg.Header.Has(tagPossDupFlag) { if err := msg.Header.GetField(tagPossDupFlag, &posDupFlag); err != nil { @@ -374,10 +380,7 @@ func (state *inSession) generateSequenceReset(session *session, beginSeqNo int, session.application.ToAdmin(sequenceReset, session.sessionID) - msgBytes, err := sequenceReset.Build() - if err != nil { - return - } + msgBytes := sequenceReset.build() session.sendBytes(msgBytes) session.log.OnEventf("Sent SequenceReset TO: %v", endSeqNo) diff --git a/vendor/github.com/quickfixgo/quickfix/in_session_test.go b/vendor/github.com/quickfixgo/quickfix/in_session_test.go new file mode 100644 index 0000000..c8c0b15 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/in_session_test.go @@ -0,0 +1,377 @@ +package quickfix + +import ( + "testing" + "time" + + "github.com/quickfixgo/quickfix/internal" + "github.com/stretchr/testify/suite" +) + +type InSessionTestSuite struct { + SessionSuiteRig +} + +func TestInSessionTestSuite(t *testing.T) { + suite.Run(t, new(InSessionTestSuite)) +} + +func (s *InSessionTestSuite) SetupTest() { + s.Init() + s.session.State = inSession{} +} + +func (s *InSessionTestSuite) TestPreliminary() { + s.True(s.session.IsLoggedOn()) + s.True(s.session.IsConnected()) + s.True(s.session.IsSessionTime()) +} + +func (s *InSessionTestSuite) TestLogout() { + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("ToAdmin") + s.MockApp.On("OnLogout") + s.session.fixMsgIn(s.session, s.Logout()) + + s.MockApp.AssertExpectations(s.T()) + s.State(latentState{}) + + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogout), s.MockApp.lastToAdmin) + s.NextTargetMsgSeqNum(2) + s.NextSenderMsgSeqNum(2) +} + +func (s *InSessionTestSuite) TestLogoutEnableLastMsgSeqNumProcessed() { + s.session.EnableLastMsgSeqNumProcessed = true + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("ToAdmin") + s.MockApp.On("OnLogout") + s.session.fixMsgIn(s.session, s.Logout()) + + s.MockApp.AssertExpectations(s.T()) + s.LastToAdminMessageSent() + + s.MessageType(string(msgTypeLogout), s.MockApp.lastToAdmin) + s.FieldEquals(tagLastMsgSeqNumProcessed, 1, s.MockApp.lastToAdmin.Header) +} + +func (s *InSessionTestSuite) TestLogoutResetOnLogout() { + s.session.ResetOnLogout = true + + s.MockApp.On("ToApp").Return(nil) + s.Nil(s.queueForSend(s.NewOrderSingle())) + s.MockApp.AssertExpectations(s.T()) + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("ToAdmin") + s.MockApp.On("OnLogout") + s.session.fixMsgIn(s.session, s.Logout()) + + s.MockApp.AssertExpectations(s.T()) + s.State(latentState{}) + s.LastToAppMessageSent() + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogout), s.MockApp.lastToAdmin) + + s.NextTargetMsgSeqNum(1) + s.NextSenderMsgSeqNum(1) + s.NoMessageQueued() +} + +func (s *InSessionTestSuite) TestTimeoutNeedHeartbeat() { + s.MockApp.On("ToAdmin").Return(nil) + s.session.Timeout(s.session, internal.NeedHeartbeat) + + s.MockApp.AssertExpectations(s.T()) + s.State(inSession{}) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeHeartbeat), s.MockApp.lastToAdmin) + s.NextSenderMsgSeqNum(2) +} + +func (s *InSessionTestSuite) TestTimeoutPeerTimeout() { + s.MockApp.On("ToAdmin").Return(nil) + s.session.Timeout(s.session, internal.PeerTimeout) + + s.MockApp.AssertExpectations(s.T()) + s.State(pendingTimeout{inSession{}}) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeTestRequest), s.MockApp.lastToAdmin) + s.NextSenderMsgSeqNum(2) +} + +func (s *InSessionTestSuite) TestDisconnected() { + s.MockApp.On("OnLogout").Return(nil) + s.session.Disconnected(s.session) + s.MockApp.AssertExpectations(s.T()) + s.State(latentState{}) +} + +func (s *InSessionTestSuite) TestStop() { + s.MockApp.On("ToAdmin") + s.session.Stop(s.session) + + s.MockApp.AssertExpectations(s.T()) + s.State(logoutState{}) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogout), s.MockApp.lastToAdmin) + + s.MockApp.On("OnLogout") + s.session.Timeout(s.session, <-s.sessionEvent) + s.MockApp.AssertExpectations(s.T()) + s.Stopped() + s.Disconnected() +} + +func (s *InSessionTestSuite) TestFIXMsgInTargetTooHighEnableLastMsgSeqNumProcessed() { + s.session.EnableLastMsgSeqNumProcessed = true + s.MessageFactory.seqNum = 5 + + s.MockApp.On("ToAdmin") + msgSeqNumTooHigh := s.NewOrderSingle() + s.fixMsgIn(s.session, msgSeqNumTooHigh) + + s.MockApp.AssertExpectations(s.T()) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeResendRequest), s.MockApp.lastToAdmin) + s.FieldEquals(tagLastMsgSeqNumProcessed, 0, s.MockApp.lastToAdmin.Header) +} + +func (s *InSessionTestSuite) TestFIXMsgInTargetTooHigh() { + s.MessageFactory.seqNum = 5 + + s.MockApp.On("ToAdmin") + msgSeqNumTooHigh := s.NewOrderSingle() + s.fixMsgIn(s.session, msgSeqNumTooHigh) + + s.MockApp.AssertExpectations(s.T()) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeResendRequest), s.MockApp.lastToAdmin) + s.FieldEquals(tagBeginSeqNo, 1, s.MockApp.lastToAdmin.Body) + s.FieldEquals(tagEndSeqNo, 0, s.MockApp.lastToAdmin.Body) + + resendState, ok := s.session.State.(resendState) + s.True(ok) + s.NextTargetMsgSeqNum(1) + + stashedMsg, ok := resendState.messageStash[6] + s.True(ok) + + rawMsg := msgSeqNumTooHigh.build() + stashedRawMsg := stashedMsg.build() + s.Equal(string(rawMsg), string(stashedRawMsg)) +} +func (s *InSessionTestSuite) TestFIXMsgInTargetTooHighResendRequestChunkSize() { + var tests = []struct { + chunkSize int + expectedEndSeqNo int + }{ + {0, 0}, + {10, 0}, + {5, 0}, + {2, 2}, + {3, 3}, + } + + for _, test := range tests { + s.SetupTest() + s.MessageFactory.seqNum = 5 + s.session.ResendRequestChunkSize = test.chunkSize + + s.MockApp.On("ToAdmin") + msgSeqNumTooHigh := s.NewOrderSingle() + s.fixMsgIn(s.session, msgSeqNumTooHigh) + + s.MockApp.AssertExpectations(s.T()) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeResendRequest), s.MockApp.lastToAdmin) + s.FieldEquals(tagBeginSeqNo, 1, s.MockApp.lastToAdmin.Body) + s.FieldEquals(tagEndSeqNo, test.expectedEndSeqNo, s.MockApp.lastToAdmin.Body) + + resendState, ok := s.session.State.(resendState) + s.True(ok) + s.NextTargetMsgSeqNum(1) + + stashedMsg, ok := resendState.messageStash[6] + s.True(ok) + + rawMsg := msgSeqNumTooHigh.build() + stashedRawMsg := stashedMsg.build() + s.Equal(string(rawMsg), string(stashedRawMsg)) + } +} + +func (s *InSessionTestSuite) TestFIXMsgInResendRequestAllAdminExpectGapFill() { + s.MockApp.On("ToAdmin") + s.session.Timeout(s.session, internal.NeedHeartbeat) + s.LastToAdminMessageSent() + + s.session.Timeout(s.session, internal.NeedHeartbeat) + s.LastToAdminMessageSent() + + s.session.Timeout(s.session, internal.NeedHeartbeat) + s.LastToAdminMessageSent() + + s.MockApp.AssertNumberOfCalls(s.T(), "ToAdmin", 3) + s.NextSenderMsgSeqNum(4) + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("ToAdmin") + s.fixMsgIn(s.session, s.ResendRequest(1)) + + s.MockApp.AssertExpectations(s.T()) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeSequenceReset), s.MockApp.lastToAdmin) + s.FieldEquals(tagMsgSeqNum, 1, s.MockApp.lastToAdmin.Header) + s.FieldEquals(tagPossDupFlag, true, s.MockApp.lastToAdmin.Header) + s.FieldEquals(tagNewSeqNo, 4, s.MockApp.lastToAdmin.Body) + s.FieldEquals(tagGapFillFlag, true, s.MockApp.lastToAdmin.Body) + + s.NextSenderMsgSeqNum(4) + s.State(inSession{}) +} + +func (s *InSessionTestSuite) TestFIXMsgInResendRequestAllAdminThenApp() { + s.MockApp.On("ToAdmin") + s.session.Timeout(s.session, internal.NeedHeartbeat) + s.LastToAdminMessageSent() + + s.session.Timeout(s.session, internal.NeedHeartbeat) + s.LastToAdminMessageSent() + + s.MockApp.On("ToApp").Return(nil) + s.Require().Nil(s.session.send(s.NewOrderSingle())) + s.LastToAppMessageSent() + + s.MockApp.AssertNumberOfCalls(s.T(), "ToAdmin", 2) + s.MockApp.AssertNumberOfCalls(s.T(), "ToApp", 1) + s.NextSenderMsgSeqNum(4) + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("ToAdmin") + s.MockApp.On("ToApp").Return(nil) + s.fixMsgIn(s.session, s.ResendRequest(1)) + + s.MockApp.AssertNumberOfCalls(s.T(), "ToAdmin", 3) + s.MockApp.AssertNumberOfCalls(s.T(), "ToApp", 2) + + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeSequenceReset), s.MockApp.lastToAdmin) + s.FieldEquals(tagMsgSeqNum, 1, s.MockApp.lastToAdmin.Header) + s.FieldEquals(tagPossDupFlag, true, s.MockApp.lastToAdmin.Header) + s.FieldEquals(tagNewSeqNo, 3, s.MockApp.lastToAdmin.Body) + s.FieldEquals(tagGapFillFlag, true, s.MockApp.lastToAdmin.Body) + + s.LastToAppMessageSent() + s.MessageType("D", s.MockApp.lastToApp) + s.FieldEquals(tagMsgSeqNum, 3, s.MockApp.lastToApp.Header) + s.FieldEquals(tagPossDupFlag, true, s.MockApp.lastToApp.Header) + + s.NextSenderMsgSeqNum(4) + s.State(inSession{}) +} + +func (s *InSessionTestSuite) TestFIXMsgInResendRequestNoMessagePersist() { + s.session.DisableMessagePersist = true + + s.MockApp.On("ToApp").Return(nil) + s.Require().Nil(s.session.send(s.NewOrderSingle())) + s.LastToAppMessageSent() + + s.MockApp.AssertNumberOfCalls(s.T(), "ToApp", 1) + s.NextSenderMsgSeqNum(2) + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("ToAdmin") + s.fixMsgIn(s.session, s.ResendRequest(1)) + + s.MockApp.AssertNumberOfCalls(s.T(), "ToAdmin", 1) + s.MockApp.AssertNumberOfCalls(s.T(), "ToApp", 1) + + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeSequenceReset), s.MockApp.lastToAdmin) + s.FieldEquals(tagMsgSeqNum, 1, s.MockApp.lastToAdmin.Header) + s.FieldEquals(tagPossDupFlag, true, s.MockApp.lastToAdmin.Header) + s.FieldEquals(tagNewSeqNo, 2, s.MockApp.lastToAdmin.Body) + s.FieldEquals(tagGapFillFlag, true, s.MockApp.lastToAdmin.Body) + + s.NextSenderMsgSeqNum(2) + s.State(inSession{}) +} + +func (s *InSessionTestSuite) TestFIXMsgInResendRequestDoNotSendApp() { + s.MockApp.On("ToAdmin") + s.session.Timeout(s.session, internal.NeedHeartbeat) + s.LastToAdminMessageSent() + + s.MockApp.On("ToApp").Return(nil) + s.Require().Nil(s.session.send(s.NewOrderSingle())) + s.LastToAppMessageSent() + + s.session.Timeout(s.session, internal.NeedHeartbeat) + s.LastToAdminMessageSent() + + s.MockApp.AssertNumberOfCalls(s.T(), "ToAdmin", 2) + s.MockApp.AssertNumberOfCalls(s.T(), "ToApp", 1) + s.NextSenderMsgSeqNum(4) + + //NOTE: a cheat here, need to reset mock + s.MockApp = MockApp{} + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("ToApp").Return(ErrDoNotSend) + s.MockApp.On("ToAdmin") + s.fixMsgIn(s.session, s.ResendRequest(1)) + + s.MockApp.AssertNumberOfCalls(s.T(), "ToAdmin", 1) + s.MockApp.AssertNumberOfCalls(s.T(), "ToApp", 1) + + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeSequenceReset), s.MockApp.lastToAdmin) + s.FieldEquals(tagMsgSeqNum, 1, s.MockApp.lastToAdmin.Header) + s.FieldEquals(tagPossDupFlag, true, s.MockApp.lastToAdmin.Header) + s.FieldEquals(tagNewSeqNo, 4, s.MockApp.lastToAdmin.Body) + s.FieldEquals(tagGapFillFlag, true, s.MockApp.lastToAdmin.Body) + + s.NoMessageSent() + + s.NextSenderMsgSeqNum(4) + s.State(inSession{}) +} + +func (s *InSessionTestSuite) TestFIXMsgInTargetTooLow() { + s.IncrNextTargetMsgSeqNum() + + s.MockApp.On("ToAdmin") + s.fixMsgIn(s.session, s.NewOrderSingle()) + s.MockApp.AssertExpectations(s.T()) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogout), s.MockApp.lastToAdmin) + s.FieldEquals(tagText, "MsgSeqNum too low, expecting 2 but received 1", s.MockApp.lastToAdmin.Body) + s.State(logoutState{}) +} + +func (s *InSessionTestSuite) TestFIXMsgInTargetTooLowPossDup() { + s.IncrNextTargetMsgSeqNum() + + s.MockApp.On("ToAdmin") + nos := s.NewOrderSingle() + nos.Header.SetField(tagPossDupFlag, FIXBoolean(true)) + + s.fixMsgIn(s.session, nos) + s.MockApp.AssertExpectations(s.T()) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeReject), s.MockApp.lastToAdmin) + s.FieldEquals(tagText, "Required tag missing", s.MockApp.lastToAdmin.Body) + s.FieldEquals(tagRefTagID, int(tagOrigSendingTime), s.MockApp.lastToAdmin.Body) + s.State(inSession{}) + + nos.Header.SetField(tagOrigSendingTime, FIXUTCTimestamp{Time: time.Now().Add(time.Duration(-1) * time.Minute)}) + nos.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: time.Now()}) + s.fixMsgIn(s.session, nos) + s.MockApp.AssertExpectations(s.T()) + s.NoMessageSent() + s.State(inSession{}) + s.NextTargetMsgSeqNum(2) +} diff --git a/vendor/github.com/quickfixgo/quickfix/internal/buffer_pool.go b/vendor/github.com/quickfixgo/quickfix/internal/buffer_pool.go new file mode 100644 index 0000000..f0be7c7 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/internal/buffer_pool.go @@ -0,0 +1,37 @@ +package internal + +import ( + "bytes" + "sync" +) + +//BufferPool is an concurrently safe pool for byte buffers. Used to constructing inbound messages and writing outbound messages +type BufferPool struct { + b []*bytes.Buffer + sync.Mutex +} + +//Get returns a buffer from the pool, or creates a new buffer if the pool is empty +func (p *BufferPool) Get() (buf *bytes.Buffer) { + p.Lock() + if len(p.b) > 0 { + buf, p.b = p.b[len(p.b)-1], p.b[:len(p.b)-1] + } else { + buf = new(bytes.Buffer) + } + + p.Unlock() + + return +} + +//Put returns adds a buffer to the pool +func (p *BufferPool) Put(buf *bytes.Buffer) { + if buf == nil { + panic("Nil Buffer inserted into pool") + } + + p.Lock() + p.b = append(p.b, buf) + p.Unlock() +} diff --git a/vendor/github.com/quickfixgo/quickfix/internal/event_timer.go b/vendor/github.com/quickfixgo/quickfix/internal/event_timer.go index adb76a9..2913684 100644 --- a/vendor/github.com/quickfixgo/quickfix/internal/event_timer.go +++ b/vendor/github.com/quickfixgo/quickfix/internal/event_timer.go @@ -1,25 +1,65 @@ package internal import ( + "sync" "time" ) type EventTimer struct { - Task func() + f func() timer *time.Timer + reset chan time.Duration + wg sync.WaitGroup } -func (t *EventTimer) Stop() (ok bool) { - if t.timer != nil { - ok = t.timer.Stop() +func NewEventTimer(task func()) *EventTimer { + t := &EventTimer{ + f: task, + reset: make(chan time.Duration, 1), } - return + + t.wg.Add(1) + go func() { + defer t.wg.Done() + var c <-chan time.Time + + for { + select { + + case <-c: + t.f() + + case d, ok := <-t.reset: + if !ok { + return + } + + if t.timer != nil { + t.timer.Reset(d) + } else { + t.timer = time.NewTimer(d) + c = t.timer.C + } + } + } + }() + + return t } -func (t *EventTimer) Reset(timeout time.Duration) (ok bool) { - ok = t.Stop() - if t.Task != nil && timeout > 0 { - t.timer = time.AfterFunc(timeout, t.Task) +func (t *EventTimer) Stop() { + if t == nil { + return } - return + + close(t.reset) + t.wg.Wait() +} + +func (t *EventTimer) Reset(timeout time.Duration) { + if t == nil { + return + } + + t.reset <- timeout } diff --git a/vendor/github.com/quickfixgo/quickfix/internal/session_settings.go b/vendor/github.com/quickfixgo/quickfix/internal/session_settings.go index 451ee92..f5d7f9a 100644 --- a/vendor/github.com/quickfixgo/quickfix/internal/session_settings.go +++ b/vendor/github.com/quickfixgo/quickfix/internal/session_settings.go @@ -7,11 +7,15 @@ type SessionSettings struct { ResetOnLogon bool RefreshOnLogon bool ResetOnLogout bool + ResetOnDisconnect bool HeartBtInt time.Duration SessionTime *TimeRange InitiateLogon bool ResendRequestChunkSize int EnableLastMsgSeqNumProcessed bool + SkipCheckLatency bool + MaxLatency time.Duration + DisableMessagePersist bool //required on logon for FIX.T.1 messages DefaultApplVerID string diff --git a/vendor/github.com/quickfixgo/quickfix/internal/time_range_test.go b/vendor/github.com/quickfixgo/quickfix/internal/time_range_test.go new file mode 100644 index 0000000..df39211 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/internal/time_range_test.go @@ -0,0 +1,435 @@ +package internal + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestNewTimeOfDay(t *testing.T) { + to := NewTimeOfDay(12, 34, 4) + assert.Equal(t, 12, to.hour) + assert.Equal(t, 34, to.minute) + assert.Equal(t, 4, to.second) + assert.Equal(t, 45244*time.Second, to.d) +} + +func TestParseTime(t *testing.T) { + to, err := ParseTimeOfDay("12:34:04") + assert.Nil(t, err) + assert.Equal(t, NewTimeOfDay(12, 34, 4), to) + + _, err = ParseTimeOfDay("0:0:0") + assert.NotNil(t, err) + + _, err = ParseTimeOfDay("00:00") + assert.NotNil(t, err) + + _, err = ParseTimeOfDay("0000:00") + assert.NotNil(t, err) +} + +func TestNewUTCTimeRange(t *testing.T) { + r := NewUTCTimeRange(NewTimeOfDay(3, 0, 0), NewTimeOfDay(18, 0, 0)) + assert.Equal(t, NewTimeOfDay(3, 0, 0), r.startTime) + assert.Equal(t, NewTimeOfDay(18, 0, 0), r.endTime) + assert.Nil(t, r.startDay) + assert.Nil(t, r.endDay) + assert.Equal(t, time.UTC, r.loc) +} + +func TestNewTimeRangeInLocation(t *testing.T) { + r := NewTimeRangeInLocation(NewTimeOfDay(3, 0, 0), NewTimeOfDay(18, 0, 0), time.Local) + assert.Equal(t, NewTimeOfDay(3, 0, 0), r.startTime) + assert.Equal(t, NewTimeOfDay(18, 0, 0), r.endTime) + assert.Nil(t, r.startDay) + assert.Nil(t, r.endDay) + assert.Equal(t, time.Local, r.loc) +} + +func TestNewUTCWeekRange(t *testing.T) { + r := NewUTCWeekRange(NewTimeOfDay(3, 0, 0), NewTimeOfDay(18, 0, 0), time.Monday, time.Wednesday) + assert.Equal(t, NewTimeOfDay(3, 0, 0), r.startTime) + assert.Equal(t, NewTimeOfDay(18, 0, 0), r.endTime) + assert.NotNil(t, r.startDay) + assert.NotNil(t, r.endDay) + assert.Equal(t, time.Monday, *r.startDay) + assert.Equal(t, time.Wednesday, *r.endDay) + assert.Equal(t, time.UTC, r.loc) +} + +func TestNewWeekRangeInLocation(t *testing.T) { + r := NewWeekRangeInLocation(NewTimeOfDay(3, 0, 0), NewTimeOfDay(18, 0, 0), time.Monday, time.Wednesday, time.Local) + assert.Equal(t, NewTimeOfDay(3, 0, 0), r.startTime) + assert.Equal(t, NewTimeOfDay(18, 0, 0), r.endTime) + assert.NotNil(t, r.startDay) + assert.NotNil(t, r.endDay) + assert.Equal(t, time.Monday, *r.startDay) + assert.Equal(t, time.Wednesday, *r.endDay) + assert.Equal(t, time.Local, r.loc) +} + +func BenchmarkInRange(b *testing.B) { + start := NewTimeOfDay(3, 0, 0) + end := NewTimeOfDay(18, 0, 0) + tr := NewUTCTimeRange(start, end) + + now := time.Date(2016, time.August, 10, 10, 0, 0, 0, time.UTC) + for n := 0; n < b.N; n++ { + tr.IsInRange(now) + } +} + +func TestTimeRangeIsInRange(t *testing.T) { + start := NewTimeOfDay(3, 0, 0) + end := NewTimeOfDay(18, 0, 0) + + now := time.Date(2016, time.August, 10, 10, 0, 0, 0, time.UTC) + assert.True(t, NewUTCTimeRange(start, end).IsInRange(now)) + + now = time.Date(2016, time.August, 10, 18, 0, 0, 0, time.UTC) + assert.True(t, NewUTCTimeRange(start, end).IsInRange(now)) + + now = time.Date(2016, time.August, 10, 2, 0, 0, 0, time.UTC) + assert.False(t, NewUTCTimeRange(start, end).IsInRange(now)) + + now = time.Date(2016, time.August, 10, 19, 0, 0, 0, time.UTC) + assert.False(t, NewUTCTimeRange(start, end).IsInRange(now)) + + now = time.Date(2016, time.August, 10, 18, 0, 1, 0, time.UTC) + assert.False(t, NewUTCTimeRange(start, end).IsInRange(now)) + + start = NewTimeOfDay(18, 0, 0) + end = NewTimeOfDay(3, 0, 0) + now = time.Date(2016, time.August, 10, 18, 0, 0, 0, time.UTC) + assert.True(t, NewUTCTimeRange(start, end).IsInRange(now)) + + now = time.Date(2016, time.August, 10, 3, 0, 0, 0, time.UTC) + assert.True(t, NewUTCTimeRange(start, end).IsInRange(now)) + + now = time.Date(2016, time.August, 10, 4, 0, 0, 0, time.UTC) + assert.False(t, NewUTCTimeRange(start, end).IsInRange(now)) + + now = time.Date(2016, time.August, 10, 17, 0, 0, 0, time.UTC) + assert.False(t, NewUTCTimeRange(start, end).IsInRange(now)) + + var tr *TimeRange + assert.True(t, tr.IsInRange(now), "always in range if time range is nil") + + loc := time.FixedZone("myzone", -60) + start = NewTimeOfDay(3, 0, 0) + end = NewTimeOfDay(5, 0, 0) + + now = time.Date(2016, time.August, 10, 3, 0, 0, 0, time.UTC) + assert.False(t, NewTimeRangeInLocation(start, end, loc).IsInRange(now)) + + now = time.Date(2016, time.August, 10, 3, 1, 0, 0, time.UTC) + assert.True(t, NewTimeRangeInLocation(start, end, loc).IsInRange(now)) + + start = NewTimeOfDay(0, 0, 0) + end = NewTimeOfDay(0, 0, 0) + now = time.Date(2016, time.August, 10, 18, 0, 0, 0, time.UTC) + assert.True(t, NewUTCTimeRange(start, end).IsInRange(now)) + +} + +func TestTimeRangeIsInRangeWithDay(t *testing.T) { + + startTime := NewTimeOfDay(3, 0, 0) + endTime := NewTimeOfDay(18, 0, 0) + startDay := time.Monday + endDay := time.Thursday + + now := time.Date(2004, time.July, 28, 2, 0, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2004, time.July, 27, 18, 0, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2004, time.July, 27, 3, 0, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2004, time.July, 26, 2, 59, 59, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2004, time.July, 29, 18, 0, 1, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + startDay = time.Thursday + endDay = time.Monday + + now = time.Date(2004, time.July, 24, 2, 0, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2004, time.July, 28, 2, 0, 0, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2004, time.July, 22, 3, 0, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2004, time.July, 26, 18, 0, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2004, time.July, 22, 2, 59, 59, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2004, time.July, 26, 18, 0, 1, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + startTime = NewTimeOfDay(9, 1, 0) + endTime = NewTimeOfDay(8, 59, 0) + startDay = time.Sunday + endDay = time.Sunday + + now = time.Date(2006, time.December, 3, 8, 59, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2006, time.December, 3, 8, 59, 1, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2006, time.December, 3, 9, 1, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + now = time.Date(2006, time.December, 3, 9, 0, 0, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2006, time.December, 4, 8, 59, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2006, time.December, 4, 8, 59, 1, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2006, time.December, 4, 9, 1, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2006, time.December, 4, 9, 0, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + startTime = NewTimeOfDay(8, 59, 0) + endTime = NewTimeOfDay(9, 1, 0) + startDay = time.Sunday + endDay = time.Sunday + + now = time.Date(2006, time.December, 3, 8, 59, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2006, time.December, 3, 9, 1, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) + + now = time.Date(2006, time.December, 4, 8, 59, 0, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInRange(now)) +} + +func TestTimeRangeIsInSameRange(t *testing.T) { + + // start time is less than end time + start := NewTimeOfDay(3, 0, 0) + end := NewTimeOfDay(18, 0, 0) + + // same time + time1 := time.Date(2016, time.August, 10, 10, 0, 0, 0, time.UTC) + time2 := time.Date(2016, time.August, 10, 10, 0, 0, 0, time.UTC) + + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + // time 2 in same session but greater + time1 = time.Date(2016, time.August, 10, 10, 0, 0, 0, time.UTC) + time2 = time.Date(2016, time.August, 10, 11, 0, 0, 0, time.UTC) + + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + + // time 2 in same session but less + time1 = time.Date(2016, time.August, 10, 11, 0, 0, 0, time.UTC) + time2 = time.Date(2016, time.August, 10, 10, 0, 0, 0, time.UTC) + + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + + // time 1 not in session + time1 = time.Date(2016, time.August, 10, 19, 0, 0, 0, time.UTC) + time2 = time.Date(2016, time.August, 10, 10, 0, 0, 0, time.UTC) + + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + + // time 2 not in session + time1 = time.Date(2016, time.August, 10, 10, 0, 0, 0, time.UTC) + time2 = time.Date(2016, time.August, 10, 2, 0, 0, 0, time.UTC) + + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + + // start time is greater than end time + start = NewTimeOfDay(18, 0, 0) + end = NewTimeOfDay(3, 0, 0) + + // same session same day + time1 = time.Date(2016, time.August, 10, 19, 0, 0, 0, time.UTC) + time2 = time.Date(2016, time.August, 10, 20, 0, 0, 0, time.UTC) + + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + + // same session time 2 is in next day + time1 = time.Date(2016, time.August, 10, 19, 0, 0, 0, time.UTC) + time2 = time.Date(2016, time.August, 11, 2, 0, 0, 0, time.UTC) + + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + + // same session time 1 is in next day + time1 = time.Date(2016, time.August, 11, 2, 0, 0, 0, time.UTC) + time2 = time.Date(2016, time.August, 10, 19, 0, 0, 0, time.UTC) + + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + + // time 1 is 25 hours greater (han time 2 + time1 = time.Date(2016, time.August, 11, 21, 0, 0, 0, time.UTC) + time2 = time.Date(2016, time.August, 10, 20, 0, 0, 0, time.UTC) + + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + + // start time is greater than end time + start = NewTimeOfDay(6, 0, 0) + end = NewTimeOfDay(6, 0, 0) + + time1 = time.Date(2016, time.January, 13, 19, 10, 0, 0, time.UTC) + time2 = time.Date(2016, time.January, 14, 19, 6, 0, 0, time.UTC) + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + + start = NewTimeOfDay(0, 0, 0) + end = NewTimeOfDay(2, 0, 0) + loc := time.FixedZone("myzone", -60) + + time1 = time.Date(2016, time.August, 10, 0, 1, 0, 0, time.UTC) + time2 = time.Date(2016, time.August, 10, 0, 1, 0, 0, time.UTC) + assert.True(t, NewTimeRangeInLocation(start, end, loc).IsInSameRange(time1, time2)) + assert.True(t, NewTimeRangeInLocation(start, end, loc).IsInSameRange(time2, time1)) + + start = NewTimeOfDay(2, 0, 0) + end = NewTimeOfDay(0, 0, 0) + time1 = time.Date(2016, time.August, 10, 2, 1, 0, 0, time.UTC) + time2 = time.Date(2016, time.August, 10, 2, 1, 0, 0, time.UTC) + assert.True(t, NewTimeRangeInLocation(start, end, loc).IsInSameRange(time1, time2)) + assert.True(t, NewTimeRangeInLocation(start, end, loc).IsInSameRange(time2, time1)) + + var tr *TimeRange + assert.True(t, tr.IsInSameRange(time1, time2), "always in same range if time range is nil") + + start = NewTimeOfDay(0, 0, 0) + end = NewTimeOfDay(0, 0, 0) + time1 = time.Date(2016, time.August, 10, 0, 0, 0, 0, time.UTC) + time2 = time.Date(2016, time.August, 11, 0, 0, 0, 0, time.UTC) + assert.False(t, NewTimeRangeInLocation(start, end, loc).IsInSameRange(time1, time2)) + assert.False(t, NewTimeRangeInLocation(start, end, loc).IsInSameRange(time2, time1)) + + time1 = time.Date(2016, time.August, 10, 23, 59, 59, 0, time.UTC) + time2 = time.Date(2016, time.August, 11, 0, 0, 0, 0, time.UTC) + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + + start = NewTimeOfDay(1, 49, 0) + end = NewTimeOfDay(1, 49, 0) + time1 = time.Date(2016, time.August, 16, 1, 48, 21, 0, time.UTC) + time2 = time.Date(2016, time.August, 16, 1, 49, 02, 0, time.UTC) + + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + + start = NewTimeOfDay(1, 49, 0) + end = NewTimeOfDay(1, 49, 0) + time1 = time.Date(2016, time.August, 16, 13, 48, 21, 0, time.UTC) + time2 = time.Date(2016, time.August, 16, 13, 49, 02, 0, time.UTC) + + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.True(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) + + start = NewTimeOfDay(13, 49, 0) + end = NewTimeOfDay(13, 49, 0) + time1 = time.Date(2016, time.August, 16, 13, 48, 21, 0, time.UTC) + time2 = time.Date(2016, time.August, 16, 13, 49, 02, 0, time.UTC) + + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time1, time2)) + assert.False(t, NewUTCTimeRange(start, end).IsInSameRange(time2, time1)) +} + +func TestTimeRangeIsInSameRangeWithDay(t *testing.T) { + + startTime := NewTimeOfDay(3, 0, 0) + endTime := NewTimeOfDay(18, 0, 0) + startDay := time.Monday + endDay := time.Thursday + + time1 := time.Date(2004, time.July, 27, 3, 0, 0, 0, time.UTC) + time2 := time.Date(2004, time.July, 25, 3, 0, 0, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) + + time1 = time.Date(2004, time.July, 31, 3, 0, 0, 0, time.UTC) + time2 = time.Date(2004, time.July, 27, 3, 0, 0, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) + + time1 = time.Date(2004, time.July, 27, 3, 0, 0, 0, time.UTC) + time2 = time.Date(2004, time.July, 27, 3, 0, 0, 0, time.UTC) + + time1 = time.Date(2004, time.July, 26, 10, 0, 0, 0, time.UTC) + time2 = time.Date(2004, time.July, 27, 3, 0, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) + + time1 = time.Date(2004, time.July, 27, 10, 0, 0, 0, time.UTC) + time2 = time.Date(2004, time.July, 29, 2, 0, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) + + time1 = time.Date(2004, time.July, 27, 10, 0, 0, 0, time.UTC) + time2 = time.Date(2004, time.July, 20, 3, 0, 0, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) + + time1 = time.Date(2004, time.July, 27, 2, 0, 0, 0, time.UTC) + time2 = time.Date(2004, time.July, 20, 3, 0, 0, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) + + time1 = time.Date(2004, time.July, 26, 2, 0, 0, 0, time.UTC) + time2 = time.Date(2004, time.July, 19, 3, 0, 0, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) + + // Reset start/end time so that they fall within an hour of midnight + startTime = NewTimeOfDay(0, 5, 0) + endTime = NewTimeOfDay(23, 45, 0) + + // Make it a week-long session + startDay = time.Sunday + endDay = time.Saturday + + // Check that ST-->DST (Sunday is missing one hour) is handled + time1 = time.Date(2006, time.April, 4, 0, 0, 0, 0, time.UTC) + time2 = time.Date(2006, time.April, 3, 1, 0, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) + + // Check that DST-->ST (Sunday has an extra hour) is handled + time1 = time.Date(2006, time.October, 30, 0, 0, 0, 0, time.UTC) + time2 = time.Date(2006, time.October, 31, 1, 0, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) + + // Check that everything works across a year boundary + time1 = time.Date(2006, time.December, 31, 10, 10, 10, 0, time.UTC) + time2 = time.Date(2007, time.January, 1, 10, 10, 10, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) + + // Session days are the same + startDay = time.Sunday + endDay = time.Sunday + startTime = NewTimeOfDay(9, 1, 0) + endTime = NewTimeOfDay(8, 59, 0) + time1 = time.Date(2006, time.December, 3, 9, 1, 0, 0, time.UTC) + time2 = time.Date(2006, time.December, 3, 9, 1, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) + + time2 = time.Date(2006, time.December, 10, 9, 1, 0, 0, time.UTC) + assert.False(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) + + time2 = time.Date(2006, time.December, 4, 9, 1, 0, 0, time.UTC) + assert.True(t, NewUTCWeekRange(startTime, endTime, startDay, endDay).IsInSameRange(time1, time2)) +} diff --git a/vendor/github.com/quickfixgo/quickfix/latent_state.go b/vendor/github.com/quickfixgo/quickfix/latent_state.go index 3140ecd..e6e5bec 100644 --- a/vendor/github.com/quickfixgo/quickfix/latent_state.go +++ b/vendor/github.com/quickfixgo/quickfix/latent_state.go @@ -8,7 +8,7 @@ func (state latentState) String() string { return "Latent State" } func (state latentState) IsLoggedOn() bool { return false } func (state latentState) IsConnected() bool { return false } -func (state latentState) FixMsgIn(session *session, msg Message) (nextState sessionState) { +func (state latentState) FixMsgIn(session *session, msg *Message) (nextState sessionState) { session.log.OnEventf("Invalid Session State: Unexpected Msg %v while in Latent state", msg) return state } diff --git a/vendor/github.com/quickfixgo/quickfix/latent_state_test.go b/vendor/github.com/quickfixgo/quickfix/latent_state_test.go new file mode 100644 index 0000000..db6e925 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/latent_state_test.go @@ -0,0 +1,36 @@ +package quickfix + +import ( + "testing" + + "github.com/stretchr/testify/suite" +) + +type LatentStateTestSuite struct { + SessionSuiteRig +} + +func TestLatentStateTestSuite(t *testing.T) { + suite.Run(t, new(LatentStateTestSuite)) +} + +func (s *LatentStateTestSuite) SetupTest() { + s.Init() + s.session.State = latentState{} +} + +func (s *LatentStateTestSuite) TestPreliminary() { + s.False(s.session.IsLoggedOn()) + s.False(s.session.IsConnected()) + s.True(s.session.IsSessionTime()) +} + +func (s *LatentStateTestSuite) TestDisconnected() { + s.session.Disconnected(s.session) + s.State(latentState{}) +} + +func (s *LatentStateTestSuite) TestStop() { + s.session.Stop(s.session) + s.Stopped() +} diff --git a/vendor/github.com/quickfixgo/quickfix/log.go b/vendor/github.com/quickfixgo/quickfix/log.go index 78f3e7d..6527e92 100644 --- a/vendor/github.com/quickfixgo/quickfix/log.go +++ b/vendor/github.com/quickfixgo/quickfix/log.go @@ -3,10 +3,10 @@ package quickfix //Log is a generic interface for logging FIX messages and events. type Log interface { //log incoming fix message - OnIncoming(string) + OnIncoming([]byte) //log outgoing fix message - OnOutgoing(string) + OnOutgoing([]byte) //log fix event OnEvent(string) diff --git a/vendor/github.com/quickfixgo/quickfix/logon_state.go b/vendor/github.com/quickfixgo/quickfix/logon_state.go index 6027bb0..fc7fffd 100644 --- a/vendor/github.com/quickfixgo/quickfix/logon_state.go +++ b/vendor/github.com/quickfixgo/quickfix/logon_state.go @@ -1,7 +1,8 @@ package quickfix import ( - "github.com/quickfixgo/quickfix/enum" + "bytes" + "github.com/quickfixgo/quickfix/internal" ) @@ -9,13 +10,13 @@ type logonState struct{ connectedNotLoggedOn } func (s logonState) String() string { return "Logon State" } -func (s logonState) FixMsgIn(session *session, msg Message) (nextState sessionState) { - var msgType FIXString - if err := msg.Header.GetField(tagMsgType, &msgType); err != nil { +func (s logonState) FixMsgIn(session *session, msg *Message) (nextState sessionState) { + msgType, err := msg.Header.GetBytes(tagMsgType) + if err != nil { return handleStateError(session, err) } - if enum.MsgType(msgType) != enum.MsgType_LOGON { + if !bytes.Equal(msgType, msgTypeLogon) { session.log.OnEventf("Invalid Session State: Received Msg %s while waiting for Logon", msg) return latentState{} } @@ -26,7 +27,7 @@ func (s logonState) FixMsgIn(session *session, msg Message) (nextState sessionSt session.log.OnEvent(err.Text) logout := session.buildLogout(err.Text) - if err := session.dropAndSendInReplyTo(logout, false, &msg); err != nil { + if err := session.dropAndSendInReplyTo(logout, false, msg); err != nil { session.logError(err) } diff --git a/vendor/github.com/quickfixgo/quickfix/logon_state_test.go b/vendor/github.com/quickfixgo/quickfix/logon_state_test.go new file mode 100644 index 0000000..08da2e7 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/logon_state_test.go @@ -0,0 +1,304 @@ +package quickfix + +import ( + "bytes" + "testing" + "time" + + "github.com/quickfixgo/quickfix/internal" + "github.com/stretchr/testify/suite" +) + +type LogonStateTestSuite struct { + SessionSuiteRig +} + +func TestLogonStateTestSuite(t *testing.T) { + suite.Run(t, new(LogonStateTestSuite)) +} + +func (s *LogonStateTestSuite) SetupTest() { + s.Init() + s.session.stateMachine.State = logonState{} +} + +func (s *LogonStateTestSuite) TestPreliminary() { + s.False(s.session.IsLoggedOn()) + s.True(s.session.IsConnected()) + s.True(s.session.IsSessionTime()) +} + +func (s *LogonStateTestSuite) TestTimeoutLogonTimeout() { + s.Timeout(s.session, internal.LogonTimeout) + s.State(latentState{}) +} + +func (s *LogonStateTestSuite) TestTimeoutLogonTimeoutInitiatedLogon() { + s.session.InitiateLogon = true + + s.MockApp.On("OnLogout") + s.Timeout(s.session, internal.LogonTimeout) + + s.MockApp.AssertExpectations(s.T()) + s.State(latentState{}) +} + +func (s *LogonStateTestSuite) TestTimeoutNotLogonTimeout() { + tests := []internal.Event{internal.PeerTimeout, internal.NeedHeartbeat, internal.LogoutTimeout} + + for _, test := range tests { + s.Timeout(s.session, test) + s.State(logonState{}) + } +} + +func (s *LogonStateTestSuite) TestDisconnected() { + s.session.Disconnected(s.session) + s.State(latentState{}) +} + +func (s *LogonStateTestSuite) TestFixMsgInNotLogon() { + s.fixMsgIn(s.session, s.NewOrderSingle()) + + s.MockApp.AssertExpectations(s.T()) + s.State(latentState{}) + s.NextTargetMsgSeqNum(1) +} + +func (s *LogonStateTestSuite) TestFixMsgInLogon() { + s.IncrNextSenderMsgSeqNum() + s.MessageFactory.seqNum = 1 + s.IncrNextTargetMsgSeqNum() + + logon := s.Logon() + logon.Body.SetField(tagHeartBtInt, FIXInt(32)) + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("OnLogon") + s.MockApp.On("ToAdmin") + s.fixMsgIn(s.session, logon) + + s.MockApp.AssertExpectations(s.T()) + + s.State(inSession{}) + s.Equal(32*time.Second, s.session.HeartBtInt) + + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogon), s.MockApp.lastToAdmin) + s.FieldEquals(tagHeartBtInt, 32, s.MockApp.lastToAdmin.Body) + + s.NextTargetMsgSeqNum(3) + s.NextSenderMsgSeqNum(3) +} + +func (s *LogonStateTestSuite) TestFixMsgInLogonEnableLastMsgSeqNumProcessed() { + s.session.EnableLastMsgSeqNumProcessed = true + + s.MessageFactory.SetNextSeqNum(2) + s.IncrNextSenderMsgSeqNum() + s.IncrNextTargetMsgSeqNum() + + logon := s.Logon() + logon.Body.SetField(tagHeartBtInt, FIXInt(32)) + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("OnLogon") + s.MockApp.On("ToAdmin") + s.fixMsgIn(s.session, logon) + + s.MockApp.AssertExpectations(s.T()) + + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogon), s.MockApp.lastToAdmin) + s.FieldEquals(tagLastMsgSeqNumProcessed, 2, s.MockApp.lastToAdmin.Header) +} + +func (s *LogonStateTestSuite) TestFixMsgInLogonResetSeqNum() { + s.IncrNextTargetMsgSeqNum() + + logon := s.Logon() + logon.Body.SetField(tagHeartBtInt, FIXInt(32)) + logon.Body.SetField(tagResetSeqNumFlag, FIXBoolean(true)) + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("OnLogon") + s.MockApp.On("ToAdmin") + s.fixMsgIn(s.session, logon) + + s.MockApp.AssertExpectations(s.T()) + + s.State(inSession{}) + s.Equal(32*time.Second, s.session.HeartBtInt) + + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogon), s.MockApp.lastToAdmin) + s.FieldEquals(tagHeartBtInt, 32, s.MockApp.lastToAdmin.Body) + s.FieldEquals(tagResetSeqNumFlag, true, s.MockApp.lastToAdmin.Body) + + s.NextTargetMsgSeqNum(2) + s.NextSenderMsgSeqNum(2) +} + +func (s *LogonStateTestSuite) TestFixMsgInLogonInitiateLogon() { + s.session.InitiateLogon = true + s.IncrNextSenderMsgSeqNum() + s.MessageFactory.seqNum = 1 + s.IncrNextTargetMsgSeqNum() + + logon := s.Logon() + logon.Body.SetField(tagHeartBtInt, FIXInt(32)) + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("OnLogon") + s.fixMsgIn(s.session, logon) + + s.MockApp.AssertExpectations(s.T()) + s.State(inSession{}) + + s.NextTargetMsgSeqNum(3) + s.NextSenderMsgSeqNum(2) +} + +func (s *LogonStateTestSuite) TestFixMsgInLogonInitiateLogonExpectResetSeqNum() { + s.session.InitiateLogon = true + s.session.sentReset = true + s.Require().Nil(s.store.IncrNextSenderMsgSeqNum()) + + logon := s.Logon() + logon.Body.SetField(tagHeartBtInt, FIXInt(32)) + logon.Body.SetField(tagResetSeqNumFlag, FIXBoolean(true)) + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("OnLogon") + s.fixMsgIn(s.session, logon) + + s.MockApp.AssertExpectations(s.T()) + s.State(inSession{}) + + s.NextTargetMsgSeqNum(2) + s.NextSenderMsgSeqNum(2) +} + +func (s *LogonStateTestSuite) TestFixMsgInLogonInitiateLogonUnExpectedResetSeqNum() { + s.session.InitiateLogon = true + s.session.sentReset = false + s.IncrNextTargetMsgSeqNum() + s.IncrNextSenderMsgSeqNum() + + logon := s.Logon() + logon.Body.SetField(tagHeartBtInt, FIXInt(32)) + logon.Body.SetField(tagResetSeqNumFlag, FIXBoolean(true)) + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("OnLogon") + s.fixMsgIn(s.session, logon) + + s.MockApp.AssertExpectations(s.T()) + s.State(inSession{}) + + s.NextTargetMsgSeqNum(2) + s.NextSenderMsgSeqNum(1) +} + +func (s *LogonStateTestSuite) TestFixMsgInLogonRefreshOnLogon() { + var tests = []bool{true, false} + + for _, doRefresh := range tests { + s.SetupTest() + s.session.RefreshOnLogon = doRefresh + + logon := s.Logon() + logon.Body.SetField(tagHeartBtInt, FIXInt(32)) + + if doRefresh { + s.MockStore.On("Refresh").Return(nil) + } + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("OnLogon") + s.MockApp.On("ToAdmin") + s.fixMsgIn(s.session, logon) + + s.MockStore.AssertExpectations(s.T()) + } +} + +func (s *LogonStateTestSuite) TestStop() { + var tests = []bool{true, false} + + for _, doInitiateLogon := range tests { + s.SetupTest() + s.session.InitiateLogon = doInitiateLogon + + if doInitiateLogon { + s.MockApp.On("OnLogout") + } + + s.session.Stop(s.session) + s.MockApp.AssertExpectations(s.T()) + s.Disconnected() + s.Stopped() + } +} + +func (s *LogonStateTestSuite) TestFixMsgInLogonRejectLogon() { + s.IncrNextSenderMsgSeqNum() + s.MessageFactory.seqNum = 1 + s.IncrNextTargetMsgSeqNum() + + logon := s.Logon() + logon.Body.SetField(tagHeartBtInt, FIXInt(32)) + + s.MockApp.On("FromAdmin").Return(RejectLogon{"reject message"}) + s.MockApp.On("ToAdmin") + s.fixMsgIn(s.session, logon) + + s.MockApp.AssertExpectations(s.T()) + + s.State(latentState{}) + + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogout), s.MockApp.lastToAdmin) + s.FieldEquals(tagText, "reject message", s.MockApp.lastToAdmin.Body) + + s.NextTargetMsgSeqNum(3) + s.NextSenderMsgSeqNum(3) +} + +func (s *LogonStateTestSuite) TestFixMsgInLogonSeqNumTooHigh() { + s.MessageFactory.SetNextSeqNum(6) + logon := s.Logon() + logon.Body.SetField(tagHeartBtInt, FIXInt(32)) + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("OnLogon") + s.MockApp.On("ToAdmin") + s.fixMsgIn(s.session, logon) + + s.State(resendState{}) + s.NextTargetMsgSeqNum(1) + + //session should send logon, and then queues resend request for send + s.MockApp.AssertNumberOfCalls(s.T(), "ToAdmin", 2) + msgBytesSent, ok := s.Receiver.LastMessage() + s.Require().True(ok) + sentMessage := NewMessage() + err := ParseMessage(sentMessage, bytes.NewBuffer(msgBytesSent)) + s.Require().Nil(err) + s.MessageType(string(msgTypeLogon), sentMessage) + + s.session.sendQueued() + s.MessageType(string(msgTypeResendRequest), s.MockApp.lastToAdmin) + s.FieldEquals(tagBeginSeqNo, 1, s.MockApp.lastToAdmin.Body) + + s.MockApp.On("FromAdmin").Return(nil) + s.MessageFactory.SetNextSeqNum(1) + s.fixMsgIn(s.session, s.SequenceReset(3)) + s.State(resendState{}) + s.NextTargetMsgSeqNum(3) + + s.MessageFactory.SetNextSeqNum(3) + s.MockApp.On("FromAdmin").Return(nil) + s.fixMsgIn(s.session, s.SequenceReset(7)) + s.State(inSession{}) + s.NextTargetMsgSeqNum(7) +} diff --git a/vendor/github.com/quickfixgo/quickfix/logout_state.go b/vendor/github.com/quickfixgo/quickfix/logout_state.go index 3619546..071512c 100644 --- a/vendor/github.com/quickfixgo/quickfix/logout_state.go +++ b/vendor/github.com/quickfixgo/quickfix/logout_state.go @@ -6,7 +6,7 @@ type logoutState struct{ connectedNotLoggedOn } func (state logoutState) String() string { return "Logout State" } -func (state logoutState) FixMsgIn(session *session, msg Message) (nextState sessionState) { +func (state logoutState) FixMsgIn(session *session, msg *Message) (nextState sessionState) { nextState = inSession{}.FixMsgIn(session, msg) if nextState, ok := nextState.(latentState); ok { return nextState diff --git a/vendor/github.com/quickfixgo/quickfix/logout_state_test.go b/vendor/github.com/quickfixgo/quickfix/logout_state_test.go new file mode 100644 index 0000000..ce1ae84 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/logout_state_test.go @@ -0,0 +1,112 @@ +package quickfix + +import ( + "testing" + + "github.com/quickfixgo/quickfix/internal" + "github.com/stretchr/testify/suite" +) + +type LogoutStateTestSuite struct { + SessionSuiteRig +} + +func TestLogoutStateTestSuite(t *testing.T) { + suite.Run(t, new(LogoutStateTestSuite)) +} + +func (s *LogoutStateTestSuite) SetupTest() { + s.Init() + s.session.State = logoutState{} +} + +func (s *LogoutStateTestSuite) TestPreliminary() { + s.False(s.session.IsLoggedOn()) + s.True(s.session.IsConnected()) + s.True(s.session.IsSessionTime()) +} + +func (s *LogoutStateTestSuite) TestTimeoutLogoutTimeout() { + s.MockApp.On("OnLogout").Return(nil) + s.Timeout(s.session, internal.LogoutTimeout) + + s.MockApp.AssertExpectations(s.T()) + s.State(latentState{}) +} + +func (s *LogoutStateTestSuite) TestTimeoutNotLogoutTimeout() { + tests := []internal.Event{internal.PeerTimeout, internal.NeedHeartbeat, internal.LogonTimeout} + + for _, test := range tests { + s.Timeout(s.session, test) + s.State(logoutState{}) + } +} + +func (s *LogoutStateTestSuite) TestDisconnected() { + s.MockApp.On("OnLogout").Return(nil) + s.session.Disconnected(s.session) + + s.MockApp.AssertExpectations(s.T()) + s.State(latentState{}) +} + +func (s *LogoutStateTestSuite) TestFixMsgInNotLogout() { + s.MockApp.On("FromApp").Return(nil) + s.fixMsgIn(s.session, s.NewOrderSingle()) + + s.MockApp.AssertExpectations(s.T()) + s.State(logoutState{}) + s.NextTargetMsgSeqNum(2) +} + +func (s *LogoutStateTestSuite) TestFixMsgInNotLogoutReject() { + s.MockApp.On("FromApp").Return(ConditionallyRequiredFieldMissing(Tag(11))) + s.MockApp.On("ToApp").Return(nil) + s.fixMsgIn(s.session, s.NewOrderSingle()) + + s.MockApp.AssertExpectations(s.T()) + s.State(logoutState{}) + s.NextTargetMsgSeqNum(2) + s.NextSenderMsgSeqNum(2) + + s.NoMessageSent() +} + +func (s *LogoutStateTestSuite) TestFixMsgInLogout() { + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("OnLogout").Return(nil) + s.fixMsgIn(s.session, s.Logout()) + + s.MockApp.AssertExpectations(s.T()) + s.State(latentState{}) + s.NextTargetMsgSeqNum(2) + s.NextSenderMsgSeqNum(1) + s.NoMessageSent() +} + +func (s *LogoutStateTestSuite) TestFixMsgInLogoutResetOnLogout() { + s.session.ResetOnLogout = true + + s.MockApp.On("ToApp").Return(nil) + s.Nil(s.queueForSend(s.NewOrderSingle())) + s.MockApp.AssertExpectations(s.T()) + + s.MockApp.On("FromAdmin").Return(nil) + s.MockApp.On("OnLogout").Return(nil) + s.fixMsgIn(s.session, s.Logout()) + + s.MockApp.AssertExpectations(s.T()) + s.State(latentState{}) + s.NextTargetMsgSeqNum(1) + s.NextSenderMsgSeqNum(1) + + s.NoMessageSent() + s.NoMessageQueued() +} + +func (s *LogoutStateTestSuite) TestStop() { + s.session.Stop(s.session) + s.State(logoutState{}) + s.NotStopped() +} diff --git a/vendor/github.com/quickfixgo/quickfix/message.go b/vendor/github.com/quickfixgo/quickfix/message.go index 756ce29..8d67c47 100644 --- a/vendor/github.com/quickfixgo/quickfix/message.go +++ b/vendor/github.com/quickfixgo/quickfix/message.go @@ -6,41 +6,43 @@ import ( "math" "time" - "github.com/quickfixgo/quickfix/enum" + "github.com/quickfixgo/quickfix/datadictionary" ) //Header is first section of a FIX Message type Header struct{ FieldMap } -//Init initializes the Header instance -func (h *Header) Init() { - //in the message header, the first 3 tags in the message header must be 8,9,35 - h.initWithOrdering(func(i, j Tag) bool { - var ordering = func(t Tag) uint32 { - switch t { - case tagBeginString: - return 1 - case tagBodyLength: - return 2 - case tagMsgType: - return 3 - } - - return math.MaxUint32 +//in the message header, the first 3 tags in the message header must be 8,9,35 +func headerFieldOrdering(i, j Tag) bool { + var ordering = func(t Tag) uint32 { + switch t { + case tagBeginString: + return 1 + case tagBodyLength: + return 2 + case tagMsgType: + return 3 } - orderi := ordering(i) - orderj := ordering(j) + return math.MaxUint32 + } - switch { - case orderi < orderj: - return true - case orderi > orderj: - return false - } + orderi := ordering(i) + orderj := ordering(j) - return i < j - }) + switch { + case orderi < orderj: + return true + case orderi > orderj: + return false + } + + return i < j +} + +//Init initializes the Header instance +func (h *Header) Init() { + h.initWithOrdering(headerFieldOrdering) } //Body is the primary application section of a FIX message @@ -54,19 +56,21 @@ func (b *Body) Init() { //Trailer is the last section of a FIX message type Trailer struct{ FieldMap } +// In the trailer, CheckSum (tag 10) must be last +func trailerFieldOrdering(i, j Tag) bool { + switch { + case i == tagCheckSum: + return false + case j == tagCheckSum: + return true + } + + return i < j +} + //Init initializes the FIX message func (t *Trailer) Init() { - // In the trailer, CheckSum (tag 10) must be last - t.initWithOrdering(func(i, j Tag) bool { - switch { - case i == tagCheckSum: - return false - case j == tagCheckSum: - return true - } - - return i < j - }) + t.initWithOrdering(trailerFieldOrdering) } //Message is a FIX Message abstraction. @@ -78,17 +82,20 @@ type Message struct { //ReceiveTime is the time that this message was read from the socket connection ReceiveTime time.Time - rawMessage []byte + rawMessage *bytes.Buffer //slice of Bytes corresponding to the message body bodyBytes []byte //field bytes as they appear in the raw message - fields TagValues + fields []TagValue + + //flag is true if this message should not be returned to pool after use + keepMessage bool } //ToMessage returns the message itself -func (m Message) ToMessage() Message { return m } +func (m *Message) ToMessage() *Message { return m } //parseError is returned when bytes cannot be parsed as a FIX message. type parseError struct { @@ -98,80 +105,103 @@ type parseError struct { func (e parseError) Error() string { return fmt.Sprintf("error parsing message: %s", e.OrigError) } //NewMessage returns a newly initialized Message instance -func NewMessage() (m Message) { +func NewMessage() *Message { + m := new(Message) m.Header.Init() m.Body.Init() m.Trailer.Init() - return + return m } //ParseMessage constructs a Message from a byte slice wrapping a FIX message. -func ParseMessage(rawMessage []byte) (Message, error) { - msg := NewMessage() +func ParseMessage(msg *Message, rawMessage *bytes.Buffer) (err error) { + return ParseMessageWithDataDictionary(msg, rawMessage, nil, nil) +} + +//ParseMessageWithDataDictionary constructs a Message from a byte slice wrapping a FIX message using an optional session and application DataDictionary for reference. +func ParseMessageWithDataDictionary( + msg *Message, + rawMessage *bytes.Buffer, + transportDataDictionary *datadictionary.DataDictionary, + applicationDataDictionary *datadictionary.DataDictionary, +) (err error) { + msg.Header.Clear() + msg.Body.Clear() + msg.Trailer.Clear() msg.rawMessage = rawMessage + rawBytes := rawMessage.Bytes() + //allocate fields in one chunk fieldCount := 0 - for _, b := range rawMessage { + for _, b := range rawBytes { if b == '\001' { fieldCount++ } } - msg.fields = make(TagValues, fieldCount) + + if fieldCount == 0 { + return parseError{OrigError: fmt.Sprintf("No Fields detected in %s", string(rawBytes))} + } + + if cap(msg.fields) < fieldCount { + msg.fields = make([]TagValue, fieldCount) + } else { + msg.fields = msg.fields[0:fieldCount] + } fieldIndex := 0 - var err error //message must start with begin string, body length, msg type - if rawMessage, err = extractSpecificField(&msg.fields[fieldIndex], tagBeginString, rawMessage); err != nil { - return msg, err + if rawBytes, err = extractSpecificField(&msg.fields[fieldIndex], tagBeginString, rawBytes); err != nil { + return } - msg.Header.tagLookup[msg.fields[fieldIndex].tag] = msg.fields[fieldIndex : fieldIndex+1] + msg.Header.add(msg.fields[fieldIndex : fieldIndex+1]) fieldIndex++ parsedFieldBytes := &msg.fields[fieldIndex] - if rawMessage, err = extractSpecificField(parsedFieldBytes, tagBodyLength, rawMessage); err != nil { - return msg, err + if rawBytes, err = extractSpecificField(parsedFieldBytes, tagBodyLength, rawBytes); err != nil { + return } - msg.Header.tagLookup[parsedFieldBytes.tag] = msg.fields[fieldIndex : fieldIndex+1] + msg.Header.add(msg.fields[fieldIndex : fieldIndex+1]) fieldIndex++ parsedFieldBytes = &msg.fields[fieldIndex] - if rawMessage, err = extractSpecificField(parsedFieldBytes, tagMsgType, rawMessage); err != nil { - return msg, err + if rawBytes, err = extractSpecificField(parsedFieldBytes, tagMsgType, rawBytes); err != nil { + return } - msg.Header.tagLookup[parsedFieldBytes.tag] = msg.fields[fieldIndex : fieldIndex+1] + msg.Header.add(msg.fields[fieldIndex : fieldIndex+1]) fieldIndex++ trailerBytes := []byte{} foundBody := false for { parsedFieldBytes = &msg.fields[fieldIndex] - rawMessage, err = extractField(parsedFieldBytes, rawMessage) + rawBytes, err = extractField(parsedFieldBytes, rawBytes) if err != nil { - return msg, err + return } switch { - case parsedFieldBytes.tag.IsHeader(): - msg.Header.tagLookup[parsedFieldBytes.tag] = msg.fields[fieldIndex : fieldIndex+1] - case parsedFieldBytes.tag.IsTrailer(): - msg.Trailer.tagLookup[parsedFieldBytes.tag] = msg.fields[fieldIndex : fieldIndex+1] + case isHeaderField(parsedFieldBytes.tag, transportDataDictionary): + msg.Header.add(msg.fields[fieldIndex : fieldIndex+1]) + case isTrailerField(parsedFieldBytes.tag, transportDataDictionary): + msg.Trailer.add(msg.fields[fieldIndex : fieldIndex+1]) default: foundBody = true - trailerBytes = rawMessage - msg.Body.tagLookup[parsedFieldBytes.tag] = msg.fields[fieldIndex : fieldIndex+1] + trailerBytes = rawBytes + msg.Body.add(msg.fields[fieldIndex : fieldIndex+1]) } if parsedFieldBytes.tag == tagCheckSum { break } if !foundBody { - msg.bodyBytes = rawMessage + msg.bodyBytes = rawBytes } fieldIndex++ @@ -191,20 +221,58 @@ func ParseMessage(rawMessage []byte) (Message, error) { } } - var bodyLength FIXInt - if err := msg.Header.GetField(tagBodyLength, &bodyLength); err != nil { - return msg, parseError{OrigError: err.Error()} + bodyLength, err := msg.Header.GetInt(tagBodyLength) + if err != nil { + err = parseError{OrigError: err.Error()} + } else if length != bodyLength { + err = parseError{OrigError: fmt.Sprintf("Incorrect Message Length, expected %d, got %d", bodyLength, length)} + } + + return + +} + +func isHeaderField(tag Tag, dataDict *datadictionary.DataDictionary) bool { + if tag.IsHeader() { + return true } - if length != int(bodyLength) { - return msg, parseError{OrigError: fmt.Sprintf("Incorrect Message Length, expected %d, got %d", bodyLength, length)} + if dataDict == nil { + return false } - return msg, nil + _, ok := dataDict.Header.Fields[int(tag)] + return ok +} + +func isTrailerField(tag Tag, dataDict *datadictionary.DataDictionary) bool { + if tag.IsTrailer() { + return true + } + + if dataDict == nil { + return false + } + + _, ok := dataDict.Trailer.Fields[int(tag)] + return ok +} + +// MsgType returns MsgType (tag 35) field's value +func (m *Message) MsgType() (string, MessageRejectError) { + return m.Header.GetString(tagMsgType) +} + +// IsMsgTypeOf returns true if the Header contains MsgType (tag 35) field and its value is the specified one. +func (m *Message) IsMsgTypeOf(msgType string) bool { + if v, err := m.MsgType(); err == nil { + return v == msgType + } + return false } //reverseRoute returns a message builder with routing header fields initialized as the reverse of this message. -func (m Message) reverseRoute() Message { +func (m *Message) reverseRoute() *Message { reverseMsg := NewMessage() copy := func(src Tag, dest Tag) { @@ -232,7 +300,7 @@ func (m Message) reverseRoute() Message { //tags added in 4.1 var beginString FIXString if m.Header.GetField(tagBeginString, &beginString) == nil { - if string(beginString) != enum.BeginStringFIX40 { + if string(beginString) != BeginStringFIX40 { copy(tagOnBehalfOfLocationID, tagDeliverToLocationID) copy(tagDeliverToLocationID, tagOnBehalfOfLocationID) } @@ -267,30 +335,31 @@ func extractField(parsedFieldBytes *TagValue, buffer []byte) (remBytes []byte, e } func (m *Message) String() string { - return string(m.rawMessage) + if m.rawMessage != nil { + return m.rawMessage.String() + } + + return string(m.build()) } -func newCheckSum(value int) FIXString { - return FIXString(fmt.Sprintf("%03d", value)) +func formatCheckSum(value int) string { + return fmt.Sprintf("%03d", value) } //Build constructs a []byte from a Message instance -func (m *Message) Build() ([]byte, error) { +func (m *Message) build() []byte { m.cook() var b bytes.Buffer m.Header.write(&b) m.Body.write(&b) m.Trailer.write(&b) - - m.rawMessage = b.Bytes() - - return m.rawMessage, nil + return b.Bytes() } -func (m Message) cook() { +func (m *Message) cook() { bodyLength := m.Header.length() + m.Body.length() + m.Trailer.length() - m.Header.SetField(tagBodyLength, FIXInt(bodyLength)) + m.Header.SetInt(tagBodyLength, bodyLength) checkSum := (m.Header.total() + m.Body.total() + m.Trailer.total()) % 256 - m.Trailer.SetField(tagCheckSum, newCheckSum(checkSum)) + m.Trailer.SetString(tagCheckSum, formatCheckSum(checkSum)) } diff --git a/vendor/github.com/quickfixgo/quickfix/message_pool.go b/vendor/github.com/quickfixgo/quickfix/message_pool.go new file mode 100644 index 0000000..5190625 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/message_pool.go @@ -0,0 +1,26 @@ +package quickfix + +type messagePool struct { + m []*Message +} + +func (p *messagePool) New() *Message { + msg := NewMessage() + return msg +} + +func (p *messagePool) Get() (msg *Message) { + if len(p.m) > 0 { + msg, p.m = p.m[len(p.m)-1], p.m[:len(p.m)-1] + } else { + msg = p.New() + } + + msg.keepMessage = false + + return +} + +func (p *messagePool) Put(msg *Message) { + p.m = append(p.m, msg) +} diff --git a/vendor/github.com/quickfixgo/quickfix/message_router.go b/vendor/github.com/quickfixgo/quickfix/message_router.go index 25c4994..8cc76bf 100644 --- a/vendor/github.com/quickfixgo/quickfix/message_router.go +++ b/vendor/github.com/quickfixgo/quickfix/message_router.go @@ -1,16 +1,26 @@ package quickfix -import ( - "github.com/quickfixgo/quickfix/enum" -) - type routeKey struct { FIXVersion string MsgType string } +//FIX ApplVerID string values +const ( + ApplVerIDFIX27 = "0" + ApplVerIDFIX30 = "1" + ApplVerIDFIX40 = "2" + ApplVerIDFIX41 = "3" + ApplVerIDFIX42 = "4" + ApplVerIDFIX43 = "5" + ApplVerIDFIX44 = "6" + ApplVerIDFIX50 = "7" + ApplVerIDFIX50SP1 = "8" + ApplVerIDFIX50SP2 = "9" +) + //A MessageRoute is a function that can process a fromApp/fromAdmin callback -type MessageRoute func(msg Message, sessionID SessionID) MessageRejectError +type MessageRoute func(msg *Message, sessionID SessionID) MessageRejectError //A MessageRouter is a mutex for MessageRoutes type MessageRouter struct { @@ -28,40 +38,42 @@ func (c MessageRouter) AddRoute(beginString string, msgType string, router Messa } //Route may be called from the fromApp/fromAdmin callbacks. Messages that cannot be routed will be rejected with UnsupportedMessageType. -func (c MessageRouter) Route(msg Message, sessionID SessionID) MessageRejectError { - var beginString FIXString - if err := msg.Header.GetField(tagBeginString, &beginString); err != nil { +func (c MessageRouter) Route(msg *Message, sessionID SessionID) MessageRejectError { + beginString, err := msg.Header.GetBytes(tagBeginString) + if err != nil { return nil } - var msgType FIXString - if err := msg.Header.GetField(tagMsgType, &msgType); err != nil { + msgType, err := msg.Header.GetBytes(tagMsgType) + if err != nil { return err } return c.tryRoute(string(beginString), string(msgType), msg, sessionID) } -func (c MessageRouter) tryRoute(beginString string, msgType string, msg Message, sessionID SessionID) MessageRejectError { +func (c MessageRouter) tryRoute(beginString string, msgType string, msg *Message, sessionID SessionID) MessageRejectError { fixVersion := beginString - if beginString == enum.BeginStringFIXT11 && !isAdminMessageType(msgType) { + isAdminMsg := isAdminMessageType([]byte(msgType)) + + if beginString == BeginStringFIXT11 && !isAdminMsg { var applVerID FIXString if err := msg.Header.GetField(tagApplVerID, &applVerID); err != nil { session, _ := lookupSession(sessionID) applVerID = FIXString(session.TargetDefaultApplicationVersionID()) } - switch enum.ApplVerID(applVerID) { - case enum.ApplVerID_FIX40: - fixVersion = enum.BeginStringFIX40 - case enum.ApplVerID_FIX41: - fixVersion = enum.BeginStringFIX41 - case enum.ApplVerID_FIX42: - fixVersion = enum.BeginStringFIX42 - case enum.ApplVerID_FIX43: - fixVersion = enum.BeginStringFIX43 - case enum.ApplVerID_FIX44: - fixVersion = enum.BeginStringFIX44 + switch applVerID { + case ApplVerIDFIX40: + fixVersion = BeginStringFIX40 + case ApplVerIDFIX41: + fixVersion = BeginStringFIX41 + case ApplVerIDFIX42: + fixVersion = BeginStringFIX42 + case ApplVerIDFIX43: + fixVersion = BeginStringFIX43 + case ApplVerIDFIX44: + fixVersion = BeginStringFIX44 default: fixVersion = string(applVerID) } @@ -72,7 +84,7 @@ func (c MessageRouter) tryRoute(beginString string, msgType string, msg Message, } switch { - case isAdminMessageType(msgType) || msgType == "j": + case isAdminMsg || msgType == "j": return nil } diff --git a/vendor/github.com/quickfixgo/quickfix/message_router_test.go b/vendor/github.com/quickfixgo/quickfix/message_router_test.go new file mode 100644 index 0000000..93779b4 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/message_router_test.go @@ -0,0 +1,192 @@ +package quickfix + +import ( + "bytes" + "fmt" + "testing" + + "github.com/stretchr/testify/suite" +) + +type MessageRouterTestSuite struct { + suite.Suite + *MessageRouter + msg *Message + sessionID SessionID + returnReject MessageRejectError + routedBy string + routedSessionID SessionID + routedMessage *Message +} + +func TestMessageRouterTestSuite(t *testing.T) { + suite.Run(t, new(MessageRouterTestSuite)) +} + +func (suite *MessageRouterTestSuite) givenTheRoute(beginString, msgType string) { + suite.AddRoute( + beginString, + msgType, + func(msg *Message, sessionID SessionID) MessageRejectError { + suite.routedBy = fmt.Sprintf("%v:%v", beginString, msgType) + suite.routedSessionID = sessionID + suite.routedMessage = msg + + return suite.returnReject + }, + ) +} + +func (suite *MessageRouterTestSuite) givenTheMessage(msgBytes []byte) { + err := ParseMessage(suite.msg, bytes.NewBuffer(msgBytes)) + suite.Nil(err) + + var beginString FIXString + suite.Require().Nil(suite.msg.Header.GetField(tagBeginString, &beginString)) + var senderCompID FIXString + suite.Require().Nil(suite.msg.Header.GetField(tagSenderCompID, &senderCompID)) + var targetCompID FIXString + suite.Require().Nil(suite.msg.Header.GetField(tagTargetCompID, &targetCompID)) + suite.sessionID = SessionID{BeginString: string(beginString), SenderCompID: string(targetCompID), TargetCompID: string(senderCompID)} +} + +func (suite *MessageRouterTestSuite) givenTargetDefaultApplVerIDForSession(defaultApplVerID string, sessionID SessionID) { + s := &session{ + sessionID: sessionID, + targetDefaultApplVerID: defaultApplVerID, + } + suite.Nil(registerSession(s)) +} + +func (suite *MessageRouterTestSuite) givenAFIX42NewOrderSingle() { + suite.givenTheMessage([]byte("8=FIX.4.29=8735=D49=TW34=356=ISLD52=20160421-14:43:5040=160=20160421-14:43:5054=121=311=id10=235")) +} + +func (suite *MessageRouterTestSuite) givenAFIXTLogonMessage() { + suite.givenTheMessage([]byte("8=FIXT.1.19=6335=A34=149=TW52=20160420-21:21:4956=ISLD98=0108=21137=810=105")) +} + +func (suite *MessageRouterTestSuite) anticipateReject(rej MessageRejectError) { + suite.returnReject = rej +} + +func (suite *MessageRouterTestSuite) verifyMessageNotRouted() { + suite.Equal("", suite.routedBy, "Message should not be routed") +} + +func (suite *MessageRouterTestSuite) verifyMessageRoutedBy(beginString, msgType string) { + suite.NotEqual("", suite.routedBy, "Message expected to be routed") + + suite.Equal(fmt.Sprintf("%v:%v", beginString, msgType), suite.routedBy) + suite.Equal(suite.sessionID, suite.routedSessionID) + suite.Equal(suite.msg.String(), suite.routedMessage.String()) +} + +func (suite *MessageRouterTestSuite) resetRouter() { + suite.MessageRouter = NewMessageRouter() + suite.routedBy = "" + suite.routedSessionID = SessionID{} + suite.routedMessage = &Message{} + suite.returnReject = nil +} + +func (suite *MessageRouterTestSuite) SetupTest() { + suite.resetRouter() + sessionsLock.Lock() + defer sessionsLock.Unlock() + + sessions = make(map[SessionID]*session) + suite.msg = NewMessage() +} + +func (suite *MessageRouterTestSuite) TestNoRoute() { + suite.givenTheMessage([]byte("8=FIX.4.39=8735=D49=TW34=356=ISLD52=20160421-14:43:5040=160=20160421-14:43:5054=121=311=id10=235")) + + rej := suite.Route(suite.msg, suite.sessionID) + suite.verifyMessageNotRouted() + suite.Equal(NewBusinessMessageRejectError("Unsupported Message Type", 3, nil), rej) +} + +func (suite *MessageRouterTestSuite) TestNoRouteWhitelistedMessageTypes() { + var tests = []string{"0", "A", "1", "2", "3", "4", "5", "j"} + + for _, test := range tests { + suite.SetupTest() + + msg := fmt.Sprintf("8=FIX.4.39=8735=%v49=TW34=356=ISLD52=20160421-14:43:5040=160=20160421-14:43:5054=121=311=id10=235", test) + suite.givenTheMessage([]byte(msg)) + + rej := suite.Route(suite.msg, suite.sessionID) + suite.verifyMessageNotRouted() + suite.Nil(rej, "Message type '%v' should not be rejected by the MessageRouter", test) + } +} + +func (suite *MessageRouterTestSuite) TestSimpleRoute() { + suite.givenTheRoute(string(BeginStringFIX42), "D") + suite.givenTheRoute(string(BeginStringFIXT11), "A") + + suite.givenAFIX42NewOrderSingle() + rej := suite.Route(suite.msg, suite.sessionID) + + suite.verifyMessageRoutedBy(string(BeginStringFIX42), "D") + suite.Nil(rej) +} + +func (suite *MessageRouterTestSuite) TestSimpleRouteWithReject() { + suite.givenTheRoute(string(BeginStringFIX42), "D") + suite.givenTheRoute(string(BeginStringFIXT11), "A") + suite.anticipateReject(NewMessageRejectError("some error", 5, nil)) + + suite.givenAFIX42NewOrderSingle() + rej := suite.Route(suite.msg, suite.sessionID) + suite.verifyMessageRoutedBy(string(BeginStringFIX42), "D") + suite.Equal(suite.returnReject, rej) +} + +func (suite *MessageRouterTestSuite) TestRouteFIXTAdminMessage() { + suite.givenTheRoute(string(BeginStringFIX42), "D") + suite.givenTheRoute(string(BeginStringFIXT11), "A") + suite.givenAFIXTLogonMessage() + + rej := suite.Route(suite.msg, suite.sessionID) + suite.verifyMessageRoutedBy(string(BeginStringFIXT11), "A") + suite.Nil(rej) +} + +func (suite *MessageRouterTestSuite) TestRouteFIXT50AppWithApplVerID() { + suite.givenTheRoute(BeginStringFIX42, "D") + suite.givenTheRoute(ApplVerIDFIX50, "D") + suite.givenTheRoute(ApplVerIDFIX50SP1, "D") + + suite.givenTheMessage([]byte("8=FIXT.1.19=8935=D49=TW34=356=ISLD52=20160424-16:48:261128=740=160=20160424-16:48:2611=id21=310=120")) + rej := suite.Route(suite.msg, suite.sessionID) + suite.verifyMessageRoutedBy(ApplVerIDFIX50, "D") + suite.Nil(rej) +} + +func (suite *MessageRouterTestSuite) TestRouteFIXTAppWithApplVerID() { + suite.givenTheRoute(BeginStringFIX42, "D") + suite.givenTheRoute(ApplVerIDFIX50, "D") + suite.givenTheRoute(ApplVerIDFIX50SP1, "D") + + suite.givenTheMessage([]byte("8=FIXT.1.19=8935=D49=TW34=356=ISLD52=20160424-16:48:261128=840=160=20160424-16:48:2611=id21=310=120")) + rej := suite.Route(suite.msg, suite.sessionID) + suite.verifyMessageRoutedBy(ApplVerIDFIX50SP1, "D") + suite.Nil(rej) +} + +func (suite *MessageRouterTestSuite) TestRouteFIXTAppWithDefaultApplVerID() { + suite.givenTheRoute(BeginStringFIX42, "D") + suite.givenTheRoute(ApplVerIDFIX50, "D") + suite.givenTheRoute(ApplVerIDFIX50SP1, "D") + suite.givenTargetDefaultApplVerIDForSession( + "8", + SessionID{BeginString: string(BeginStringFIXT11), SenderCompID: "ISLD", TargetCompID: "TW"}, + ) + + suite.givenTheMessage([]byte("8=FIXT.1.19=8235=D49=TW34=356=ISLD52=20160424-16:48:2640=160=20160424-16:48:2611=id21=310=120")) + rej := suite.Route(suite.msg, suite.sessionID) + suite.verifyMessageRoutedBy(ApplVerIDFIX50SP1, "D") + suite.Nil(rej) +} diff --git a/vendor/github.com/quickfixgo/quickfix/message_test.go b/vendor/github.com/quickfixgo/quickfix/message_test.go new file mode 100644 index 0000000..fb7caf9 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/message_test.go @@ -0,0 +1,168 @@ +package quickfix + +import ( + "bytes" + "testing" + + "github.com/quickfixgo/quickfix/datadictionary" + "github.com/stretchr/testify/suite" +) + +func BenchmarkParseMessage(b *testing.B) { + rawMsg := bytes.NewBufferString("8=FIX.4.29=10435=D34=249=TW52=20140515-19:49:56.65956=ISLD11=10021=140=154=155=TSLA60=00010101-00:00:00.00010=039") + + var msg Message + for i := 0; i < b.N; i++ { + _ = ParseMessage(&msg, rawMsg) + } +} + +type MessageSuite struct { + QuickFIXSuite + msg *Message +} + +func TestMessageSuite(t *testing.T) { + suite.Run(t, new(MessageSuite)) +} + +func (s *MessageSuite) SetupTest() { + s.msg = NewMessage() +} + +func (s *MessageSuite) TestParseMessageEmpty() { + rawMsg := bytes.NewBufferString("") + + err := ParseMessage(s.msg, rawMsg) + s.NotNil(err) +} + +func (s *MessageSuite) TestParseMessage() { + rawMsg := bytes.NewBufferString("8=FIX.4.29=10435=D34=249=TW52=20140515-19:49:56.65956=ISLD11=10021=140=154=155=TSLA60=00010101-00:00:00.00010=039") + + err := ParseMessage(s.msg, rawMsg) + s.Nil(err) + + s.True(bytes.Equal(rawMsg.Bytes(), s.msg.rawMessage.Bytes()), "Expected msg bytes to equal raw bytes") + + expectedBodyBytes := []byte("11=10021=140=154=155=TSLA60=00010101-00:00:00.000") + + s.True(bytes.Equal(s.msg.bodyBytes, expectedBodyBytes), "Incorrect body bytes, got %s", string(s.msg.bodyBytes)) + + s.Equal(14, len(s.msg.fields)) + + msgType, err := s.msg.MsgType() + s.Nil(err) + + s.Equal("D", msgType) + s.True(s.msg.IsMsgTypeOf("D")) + + s.False(s.msg.IsMsgTypeOf("A")) +} + +func (s *MessageSuite) TestParseMessageWithDataDictionary() { + dict := new(datadictionary.DataDictionary) + dict.Header = &datadictionary.MessageDef{ + Fields: map[int]*datadictionary.FieldDef{ + 10030: nil, + }, + } + dict.Trailer = &datadictionary.MessageDef{ + Fields: map[int]*datadictionary.FieldDef{ + 5050: nil, + }, + } + rawMsg := bytes.NewBufferString("8=FIX.4.29=12635=D34=249=TW52=20140515-19:49:56.65956=ISLD10030=CUST11=10021=140=154=155=TSLA60=00010101-00:00:00.0005050=HELLO10=039") + + err := ParseMessageWithDataDictionary(s.msg, rawMsg, dict, dict) + s.Nil(err) + s.FieldEquals(Tag(10030), "CUST", s.msg.Header) + s.FieldEquals(Tag(5050), "HELLO", s.msg.Trailer) +} + +func (s *MessageSuite) TestParseOutOfOrder() { + //allow fields out of order, save for validation + rawMsg := bytes.NewBufferString("8=FIX.4.09=8135=D11=id21=338=10040=154=155=MSFT34=249=TW52=20140521-22:07:0956=ISLD10=250") + s.Nil(ParseMessage(s.msg, rawMsg)) +} + +func (s *MessageSuite) TestBuild() { + s.msg.Header.SetField(tagBeginString, FIXString(BeginStringFIX44)) + s.msg.Header.SetField(tagMsgType, FIXString("A")) + s.msg.Header.SetField(tagSendingTime, FIXString("20140615-19:49:56")) + + s.msg.Body.SetField(Tag(553), FIXString("my_user")) + s.msg.Body.SetField(Tag(554), FIXString("secret")) + + expectedBytes := []byte("8=FIX.4.49=4935=A52=20140615-19:49:56553=my_user554=secret10=072") + result := s.msg.build() + s.True(bytes.Equal(expectedBytes, result), "Unexpected bytes, got %s", string(result)) +} + +func (s *MessageSuite) TestReBuild() { + rawMsg := bytes.NewBufferString("8=FIX.4.29=10435=D34=249=TW52=20140515-19:49:56.65956=ISLD11=10021=140=154=155=TSLA60=00010101-00:00:00.00010=039") + + s.Nil(ParseMessage(s.msg, rawMsg)) + + s.msg.Header.SetField(tagOrigSendingTime, FIXString("20140515-19:49:56.659")) + s.msg.Header.SetField(tagSendingTime, FIXString("20140615-19:49:56")) + + rebuildBytes := s.msg.build() + + expectedBytes := []byte("8=FIX.4.29=12635=D34=249=TW52=20140615-19:49:5656=ISLD122=20140515-19:49:56.65911=10021=140=154=155=TSLA60=00010101-00:00:00.00010=128") + + s.True(bytes.Equal(expectedBytes, rebuildBytes), "Unexpected bytes,\n +%s\n-%s", rebuildBytes, expectedBytes) + + expectedBodyBytes := []byte("11=10021=140=154=155=TSLA60=00010101-00:00:00.000") + + s.True(bytes.Equal(s.msg.bodyBytes, expectedBodyBytes), "Incorrect body bytes, got %s", string(s.msg.bodyBytes)) +} + +func (s *MessageSuite) TestReverseRoute() { + s.Nil(ParseMessage(s.msg, bytes.NewBufferString("8=FIX.4.29=17135=D34=249=TW50=KK52=20060102-15:04:0556=ISLD57=AP144=BB115=JCD116=CS128=MG129=CB142=JV143=RY145=BH11=ID21=338=10040=w54=155=INTC60=20060102-15:04:0510=123"))) + + builder := s.msg.reverseRoute() + + var testCases = []struct { + tag Tag + expectedValue string + }{ + {tagTargetCompID, "TW"}, + {tagTargetSubID, "KK"}, + {tagTargetLocationID, "JV"}, + {tagSenderCompID, "ISLD"}, + {tagSenderSubID, "AP"}, + {tagSenderLocationID, "RY"}, + {tagDeliverToCompID, "JCD"}, + {tagDeliverToSubID, "CS"}, + {tagDeliverToLocationID, "BB"}, + {tagOnBehalfOfCompID, "MG"}, + {tagOnBehalfOfSubID, "CB"}, + {tagOnBehalfOfLocationID, "BH"}, + } + + for _, tc := range testCases { + var field FIXString + s.Nil(builder.Header.GetField(tc.tag, &field)) + + s.Equal(tc.expectedValue, string(field)) + } +} + +func (s *MessageSuite) TestReverseRouteIgnoreEmpty() { + s.Nil(ParseMessage(s.msg, bytes.NewBufferString("8=FIX.4.09=12835=D34=249=TW52=20060102-15:04:0556=ISLD115=116=CS128=MG129=CB11=ID21=338=10040=w54=155=INTC60=20060102-15:04:0510=123"))) + builder := s.msg.reverseRoute() + + s.False(builder.Header.Has(tagDeliverToCompID), "Should not reverse if empty") +} + +func (s *MessageSuite) TestReverseRouteFIX40() { + //onbehalfof/deliverto location id not supported in fix 4.0 + s.Nil(ParseMessage(s.msg, bytes.NewBufferString("8=FIX.4.09=17135=D34=249=TW50=KK52=20060102-15:04:0556=ISLD57=AP144=BB115=JCD116=CS128=MG129=CB142=JV143=RY145=BH11=ID21=338=10040=w54=155=INTC60=20060102-15:04:0510=123"))) + + builder := s.msg.reverseRoute() + + s.False(builder.Header.Has(tagDeliverToLocationID), "delivertolocation id not supported in fix40") + + s.False(builder.Header.Has(tagOnBehalfOfLocationID), "onbehalfof location id not supported in fix40") +} diff --git a/vendor/github.com/quickfixgo/quickfix/msg_type.go b/vendor/github.com/quickfixgo/quickfix/msg_type.go index e1d8aad..03faed6 100644 --- a/vendor/github.com/quickfixgo/quickfix/msg_type.go +++ b/vendor/github.com/quickfixgo/quickfix/msg_type.go @@ -1,9 +1,25 @@ package quickfix -//IsAdminMessageType returns true if the message type is a sesion level message. -func isAdminMessageType(m string) bool { - switch m { - case "0", "A", "1", "2", "3", "4", "5": +import "bytes" + +var msgTypeHeartbeat = []byte("0") +var msgTypeLogon = []byte("A") +var msgTypeTestRequest = []byte("1") +var msgTypeResendRequest = []byte("2") +var msgTypeReject = []byte("3") +var msgTypeSequenceReset = []byte("4") +var msgTypeLogout = []byte("5") + +//isAdminMessageType returns true if the message type is a session level message. +func isAdminMessageType(m []byte) bool { + switch { + case bytes.Equal(msgTypeHeartbeat, m), + bytes.Equal(msgTypeLogon, m), + bytes.Equal(msgTypeTestRequest, m), + bytes.Equal(msgTypeResendRequest, m), + bytes.Equal(msgTypeReject, m), + bytes.Equal(msgTypeSequenceReset, m), + bytes.Equal(msgTypeLogout, m): return true } diff --git a/vendor/github.com/quickfixgo/quickfix/not_session_time.go b/vendor/github.com/quickfixgo/quickfix/not_session_time.go index e9b589d..2e3b04c 100644 --- a/vendor/github.com/quickfixgo/quickfix/not_session_time.go +++ b/vendor/github.com/quickfixgo/quickfix/not_session_time.go @@ -7,7 +7,7 @@ type notSessionTime struct{ latentState } func (notSessionTime) String() string { return "Not session time" } func (notSessionTime) IsSessionTime() bool { return false } -func (state notSessionTime) FixMsgIn(session *session, msg Message) (nextState sessionState) { +func (state notSessionTime) FixMsgIn(session *session, msg *Message) (nextState sessionState) { session.log.OnEventf("Invalid Session State: Unexpected Msg %v while in Latent state", msg) return state } diff --git a/vendor/github.com/quickfixgo/quickfix/not_session_time_test.go b/vendor/github.com/quickfixgo/quickfix/not_session_time_test.go new file mode 100644 index 0000000..21a2c8f --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/not_session_time_test.go @@ -0,0 +1,36 @@ +package quickfix + +import ( + "testing" + + "github.com/stretchr/testify/suite" +) + +type NotSessionTimeTestSuite struct { + SessionSuiteRig +} + +func TestNotSessionTime(t *testing.T) { + suite.Run(t, new(NotSessionTimeTestSuite)) +} + +func (s *NotSessionTimeTestSuite) SetupTest() { + s.Init() + s.session.State = notSessionTime{} +} + +func (s *NotSessionTimeTestSuite) TestPreliminary() { + s.False(s.session.IsLoggedOn()) + s.False(s.session.IsConnected()) + s.False(s.session.IsSessionTime()) +} + +func (s *NotSessionTimeTestSuite) TestDisconnected() { + s.session.Disconnected(s.session) + s.State(notSessionTime{}) +} + +func (s *NotSessionTimeTestSuite) TestStop() { + s.session.Stop(s.session) + s.Stopped() +} diff --git a/vendor/github.com/quickfixgo/quickfix/null_log.go b/vendor/github.com/quickfixgo/quickfix/null_log.go index 10ff2c2..3d6f02b 100644 --- a/vendor/github.com/quickfixgo/quickfix/null_log.go +++ b/vendor/github.com/quickfixgo/quickfix/null_log.go @@ -2,9 +2,9 @@ package quickfix type nullLog struct{} -func (l nullLog) OnIncoming(s string) {} -func (l nullLog) OnOutgoing(s string) {} -func (l nullLog) OnEvent(s string) {} +func (l nullLog) OnIncoming([]byte) {} +func (l nullLog) OnOutgoing([]byte) {} +func (l nullLog) OnEvent(string) {} func (l nullLog) OnEventf(format string, a ...interface{}) {} type nullLogFactory struct{} diff --git a/vendor/github.com/quickfixgo/quickfix/parser.go b/vendor/github.com/quickfixgo/quickfix/parser.go index 33fa419..8816345 100644 --- a/vendor/github.com/quickfixgo/quickfix/parser.go +++ b/vendor/github.com/quickfixgo/quickfix/parser.go @@ -2,18 +2,24 @@ package quickfix import ( "bytes" + "errors" "io" "time" + + "github.com/quickfixgo/quickfix/internal" ) const ( defaultBufSize = 4096 ) +var bufferPool internal.BufferPool + type parser struct { - buffer []byte - reader io.Reader - lastRead time.Time + //buffer is a slice of bigBuffer + bigBuffer, buffer []byte + reader io.Reader + lastRead time.Time } func newParser(reader io.Reader) *parser { @@ -22,7 +28,23 @@ func newParser(reader io.Reader) *parser { func (p *parser) readMore() (int, error) { if len(p.buffer) == cap(p.buffer) { - newBuffer := make([]byte, len(p.buffer), len(p.buffer)+defaultBufSize) + var newBuffer []byte + switch { + //initialize the parser + case len(p.bigBuffer) == 0: + p.bigBuffer = make([]byte, defaultBufSize) + newBuffer = p.bigBuffer[0:0] + + //shift buffer back to the start of bigBuffer + case 2*len(p.buffer) <= len(p.bigBuffer): + newBuffer = p.bigBuffer[0:len(p.buffer)] + + //reallocate big buffer with enough space to shift buffer + default: + p.bigBuffer = make([]byte, 2*len(p.buffer)) + newBuffer = p.bigBuffer[0:len(p.buffer)] + } + copy(newBuffer, p.buffer) p.buffer = newBuffer } @@ -90,32 +112,43 @@ func (p *parser) jumpLength() (int, error) { return 0, err } + if offset == lengthIndex { + return 0, errors.New("No length given") + } + length, err := atoi(p.buffer[lengthIndex:offset]) if err != nil { return length, err } + + if length <= 0 { + return length, errors.New("Invalid length") + } + return offset + length, nil } -func (p *parser) ReadMessage() ([]byte, error) { +func (p *parser) ReadMessage() (msgBytes *bytes.Buffer, err error) { start, err := p.findStart() if err != nil { - return []byte{}, err + return } p.buffer = p.buffer[start:] index, err := p.jumpLength() if err != nil { - return []byte{}, err + return } index, err = p.findEndAfterOffset(index) if err != nil { - return []byte{}, err + return } - msgBytes := p.buffer[:index:index] + msgBytes = bufferPool.Get() + msgBytes.Reset() + msgBytes.Write(p.buffer[:index]) p.buffer = p.buffer[index:] - return msgBytes, nil + return } diff --git a/vendor/github.com/quickfixgo/quickfix/parser_test.go b/vendor/github.com/quickfixgo/quickfix/parser_test.go new file mode 100644 index 0000000..ab9c086 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/parser_test.go @@ -0,0 +1,173 @@ +package quickfix + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/suite" +) + +func BenchmarkParser_ReadMessage(b *testing.B) { + stream := "8=FIXT.1.19=11135=D34=449=TW52=20140511-23:10:3456=ISLD11=ID21=340=154=155=INTC60=20140511-23:10:3410=2348=FIXT.1.19=9535=D34=549=TW52=20140511-23:10:3456=ISLD11=ID21=340=154=155=INTC60=20140511-23:10:3410=198" + + for i := 0; i < b.N; i++ { + reader := strings.NewReader(stream) + parser := newParser(reader) + parser.ReadMessage() + } +} + +type ParserSuite struct { + suite.Suite + *parser +} + +func TestParserSuite(t *testing.T) { + suite.Run(t, new(ParserSuite)) +} + +func (s *ParserSuite) SetupTest() { + s.parser = new(parser) +} + +func (s *ParserSuite) TestInvalidNilLength() { + stream := "8=\x019=\x01" + s.reader = strings.NewReader(stream) + _, err := s.ReadMessage() + s.NotNil(err) +} + +func (s *ParserSuite) TestOverflowLength() { + stream := "8=\x019=9300000000000000000\x01" + s.reader = strings.NewReader(stream) + _, err := s.ReadMessage() + s.NotNil(err) +} + +func (s *ParserSuite) TestJumpLength() { + stream := "8=FIXT.1.19=11135=D34=449=TW52=20140511-23:10:3456=ISLD11=ID21=340=154=155=INTC60=20140511-23:10:3410=2348=FIXT.1.19=9535=D34=549=TW52=20140511-23:10:3456=ISLD11=ID21=340=154=155=INTC60=20140511-23:10:3410=198" + + s.reader = strings.NewReader(stream) + index, err := s.parser.jumpLength() + s.Nil(err) + + expectedIndex := 111 + 17 - 1 + s.Equal(expectedIndex, index) +} + +func (s *ParserSuite) TestBadLength() { + stream := "8=FIXT.1.19=11135=D34=449=TW52=20140511-23:10:3456=ISLD11=ID21=340=154=155=INTC60=20140511-23:10:3410=2348=FIXT.1.19=9535=D34=549=TW52=20140511-23:10:3456=ISLD11=ID21=340=154=155=INTC60=20140511-23:10:3410=198" + + s.reader = strings.NewReader(stream) + bytes, _ := s.parser.ReadMessage() + + s.Equal(stream, bytes.String()) +} + +func (s *ParserSuite) TestFindStart() { + var testCases = []struct { + stream string + expectError bool + expectedStart int + }{ + {stream: "", expectError: true}, + {stream: "nostarthere", expectError: true}, + {stream: "hello8=FIX.4.0", expectedStart: 5}, + } + for _, tc := range testCases { + s.SetupTest() + + s.reader = strings.NewReader(tc.stream) + + start, err := s.parser.findStart() + if tc.expectError { + s.NotNil(err) + continue + } + + s.Nil(err) + s.Equal(tc.expectedStart, start) + } +} + +func (s *ParserSuite) TestReadEOF() { + var testCases = []struct { + stream string + }{ + {""}, + {"hello8=FIX.4.0"}, + } + + for _, tc := range testCases { + s.SetupTest() + + s.reader = strings.NewReader(tc.stream) + bytes, err := s.parser.ReadMessage() + s.Nil(bytes) + + s.NotNil(err) + s.Equal("EOF", err.Error()) + } +} + +func (s *ParserSuite) TestReadMessage() { + stream := "hello8=FIX.4.09=5blah10=1038=FIX.4.09=4foo10=103" + s.reader = strings.NewReader(stream) + + var testCases = []struct { + expectedBytes string + expectedBufferLen int + expectedBufferCap int + }{ + {expectedBytes: "8=FIX.4.09=5blah10=103", expectedBufferCap: defaultBufSize - 31, expectedBufferLen: len(stream) - 31}, + {expectedBytes: "8=FIX.4.09=4foo10=103", expectedBufferCap: defaultBufSize - 31 - 25, expectedBufferLen: 0}, + } + + for _, tc := range testCases { + msg, err := s.parser.ReadMessage() + s.Nil(err) + + s.Equal(tc.expectedBytes, msg.String()) + s.Equal(tc.expectedBufferCap, cap(s.parser.buffer)) + s.Equal(tc.expectedBufferLen, len(s.parser.buffer)) + } +} + +func (s *ParserSuite) TestReadMessageGrowBuffer() { + stream := "hello8=FIX.4.09=5blah10=1038=FIX.4.09=4foo10=103" + + var testCases = []struct { + initialBufCap int + expectedBytes string + expectedBufferLen int + expectedBufferCap int + expectedBigBufferLen int + }{ + {initialBufCap: 0, expectedBufferCap: defaultBufSize - 31, expectedBufferLen: len(stream) - 31, expectedBigBufferLen: defaultBufSize}, + {initialBufCap: 4, expectedBufferCap: 6, expectedBufferLen: 6, expectedBigBufferLen: 32}, + {initialBufCap: 8, expectedBufferCap: 6, expectedBufferLen: 6, expectedBigBufferLen: 32}, + {initialBufCap: 14, expectedBufferCap: 10, expectedBufferLen: 10, expectedBigBufferLen: 36}, + {initialBufCap: 16, expectedBufferCap: 18, expectedBufferLen: 18, expectedBigBufferLen: 44}, + {initialBufCap: 23, expectedBufferCap: 10, expectedBufferLen: 10, expectedBigBufferLen: 36}, + {initialBufCap: 30, expectedBufferCap: 24, expectedBufferLen: 24, expectedBigBufferLen: 50}, + {initialBufCap: 31, expectedBufferCap: 0, expectedBufferLen: 0, expectedBigBufferLen: 31}, + {initialBufCap: 40, expectedBufferCap: 9, expectedBufferLen: 9, expectedBigBufferLen: 40}, + {initialBufCap: 60, expectedBufferCap: 29, expectedBufferLen: 25, expectedBigBufferLen: 60}, + {initialBufCap: 80, expectedBufferCap: 49, expectedBufferLen: 25, expectedBigBufferLen: 80}, + } + + for _, tc := range testCases { + s.SetupTest() + + s.reader = strings.NewReader(stream) + s.parser.bigBuffer = make([]byte, tc.initialBufCap) + s.parser.buffer = s.parser.bigBuffer[0:0] + msg, err := s.parser.ReadMessage() + + s.Nil(err) + s.Equal("8=FIX.4.09=5blah10=103", msg.String()) + s.Equal(tc.expectedBigBufferLen, len(s.parser.bigBuffer)) + s.Equal(tc.expectedBufferCap, cap(s.parser.buffer)) + s.Equal(tc.expectedBufferLen, len(s.parser.buffer)) + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/pending_timeout_test.go b/vendor/github.com/quickfixgo/quickfix/pending_timeout_test.go new file mode 100644 index 0000000..a9e4bf8 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/pending_timeout_test.go @@ -0,0 +1,87 @@ +package quickfix + +import ( + "testing" + + "github.com/quickfixgo/quickfix/internal" + "github.com/stretchr/testify/suite" +) + +type PendingTimeoutTestSuite struct { + SessionSuiteRig +} + +func TestPendingTimeoutTestSuite(t *testing.T) { + suite.Run(t, new(PendingTimeoutTestSuite)) +} + +func (s *PendingTimeoutTestSuite) SetupTest() { + s.Init() +} + +func (s *PendingTimeoutTestSuite) TestIsConnectedIsLoggedOn() { + tests := []pendingTimeout{ + {inSession{}}, + {resendState{}}, + } + + for _, state := range tests { + s.session.State = state + + s.True(s.session.IsConnected()) + s.True(s.session.IsLoggedOn()) + } +} + +func (s *PendingTimeoutTestSuite) TestSessionTimeout() { + tests := []pendingTimeout{ + {inSession{}}, + {resendState{}}, + } + + for _, state := range tests { + s.session.State = state + + s.MockApp.On("OnLogout").Return(nil) + s.session.Timeout(s.session, internal.PeerTimeout) + + s.MockApp.AssertExpectations(s.T()) + s.State(latentState{}) + } +} + +func (s *PendingTimeoutTestSuite) TestTimeoutUnchangedState() { + tests := []pendingTimeout{ + {inSession{}}, + {resendState{}}, + } + + testEvents := []internal.Event{internal.NeedHeartbeat, internal.LogonTimeout, internal.LogoutTimeout} + + for _, state := range tests { + s.session.State = state + + for _, event := range testEvents { + s.session.Timeout(s.session, event) + s.State(state) + } + } +} + +func (s *PendingTimeoutTestSuite) TestDisconnected() { + tests := []pendingTimeout{ + {inSession{}}, + {resendState{}}, + } + + for _, state := range tests { + s.SetupTest() + s.session.State = state + + s.MockApp.On("OnLogout").Return(nil) + s.session.Disconnected(s.session) + + s.MockApp.AssertExpectations(s.T()) + s.State(latentState{}) + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/quickfix_test.go b/vendor/github.com/quickfixgo/quickfix/quickfix_test.go new file mode 100644 index 0000000..2f511b7 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/quickfix_test.go @@ -0,0 +1,290 @@ +package quickfix + +import ( + "time" + + "github.com/quickfixgo/quickfix/internal" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +type QuickFIXSuite struct { + suite.Suite +} + +type KnowsFieldMap interface { + Has(Tag) bool + GetString(Tag) (string, MessageRejectError) + GetInt(Tag) (int, MessageRejectError) + GetField(Tag, FieldValueReader) MessageRejectError +} + +func (s *QuickFIXSuite) MessageType(msgType string, msg *Message) { + s.FieldEquals(tagMsgType, msgType, msg.Header) +} + +func (s *QuickFIXSuite) FieldEquals(tag Tag, expectedValue interface{}, fieldMap KnowsFieldMap) { + s.Require().True(fieldMap.Has(tag), "Tag %v not set", tag) + + switch expected := expectedValue.(type) { + case string: + val, err := fieldMap.GetString(tag) + s.Nil(err) + s.Equal(expected, val) + case int: + val, err := fieldMap.GetInt(tag) + s.Nil(err) + s.Equal(expected, val) + case bool: + var val FIXBoolean + err := fieldMap.GetField(tag, &val) + s.Nil(err) + s.Equal(expected, val.Bool()) + default: + s.FailNow("Field type not handled") + } +} + +func (s *QuickFIXSuite) MessageEqualsBytes(expectedBytes []byte, msg *Message) { + actualBytes := msg.build() + s.Equal(string(actualBytes), string(expectedBytes)) +} + +//MockStore wraps a memory store and mocks Refresh for convenience +type MockStore struct { + mock.Mock + memoryStore +} + +func (s *MockStore) Refresh() error { + return s.Called().Error(0) +} + +type MockApp struct { + mock.Mock + + decorateToAdmin func(*Message) + lastToAdmin *Message + lastToApp *Message +} + +func (e *MockApp) OnCreate(sessionID SessionID) { +} + +func (e *MockApp) OnLogon(sessionID SessionID) { + e.Called() +} + +func (e *MockApp) OnLogout(sessionID SessionID) { + e.Called() +} + +func (e *MockApp) FromAdmin(msg *Message, sessionID SessionID) (reject MessageRejectError) { + if err, ok := e.Called().Get(0).(MessageRejectError); ok { + return err + } + + return nil +} + +func (e *MockApp) ToAdmin(msg *Message, sessionID SessionID) { + e.Called() + + if e.decorateToAdmin != nil { + e.decorateToAdmin(msg) + } + + e.lastToAdmin = msg +} + +func (e *MockApp) ToApp(msg *Message, sessionID SessionID) (err error) { + e.lastToApp = msg + return e.Called().Error(0) +} + +func (e *MockApp) FromApp(msg *Message, sessionID SessionID) (reject MessageRejectError) { + if err, ok := e.Called().Get(0).(MessageRejectError); ok { + return err + } + + return nil +} + +type MessageFactory struct { + seqNum int +} + +func (m *MessageFactory) SetNextSeqNum(next int) { + m.seqNum = next - 1 +} + +func (m *MessageFactory) buildMessage(msgType string) *Message { + m.seqNum++ + msg := NewMessage() + msg.Header. + SetField(tagBeginString, FIXString(string(BeginStringFIX42))). + SetField(tagSenderCompID, FIXString("TW")). + SetField(tagTargetCompID, FIXString("ISLD")). + SetField(tagSendingTime, FIXUTCTimestamp{Time: time.Now()}). + SetField(tagMsgSeqNum, FIXInt(m.seqNum)). + SetField(tagMsgType, FIXString(msgType)) + return msg +} + +func (m *MessageFactory) Logout() *Message { + return m.buildMessage(string(msgTypeLogout)) +} + +func (m *MessageFactory) NewOrderSingle() *Message { + return m.buildMessage("D") +} + +func (m *MessageFactory) Heartbeat() *Message { + return m.buildMessage(string(msgTypeHeartbeat)) +} + +func (m *MessageFactory) Logon() *Message { + return m.buildMessage(string(msgTypeLogon)) +} + +func (m *MessageFactory) ResendRequest(beginSeqNo int) *Message { + msg := m.buildMessage(string(msgTypeResendRequest)) + msg.Body.SetField(tagBeginSeqNo, FIXInt(beginSeqNo)) + msg.Body.SetField(tagEndSeqNo, FIXInt(0)) + + return msg +} + +func (m *MessageFactory) SequenceReset(seqNo int) *Message { + msg := m.buildMessage(string(msgTypeSequenceReset)) + msg.Body.SetField(tagNewSeqNo, FIXInt(seqNo)) + + return msg +} + +type MockSessionReceiver struct { + sendChannel chan []byte +} + +func newMockSessionReceiver() MockSessionReceiver { + return MockSessionReceiver{ + sendChannel: make(chan []byte, 10), + } +} + +func (p *MockSessionReceiver) LastMessage() (msg []byte, ok bool) { + select { + case msg, ok = <-p.sendChannel: + default: + ok = true + } + + return +} + +type SessionSuiteRig struct { + QuickFIXSuite + MessageFactory + MockApp MockApp + MockStore MockStore + *session + Receiver MockSessionReceiver +} + +func (s *SessionSuiteRig) Init() { + s.MockApp = MockApp{} + s.MockStore = MockStore{} + s.MessageFactory = MessageFactory{} + s.Receiver = newMockSessionReceiver() + s.session = &session{ + sessionID: SessionID{BeginString: "FIX.4.2", TargetCompID: "TW", SenderCompID: "ISLD"}, + store: &s.MockStore, + application: &s.MockApp, + log: nullLog{}, + messageOut: s.Receiver.sendChannel, + sessionEvent: make(chan internal.Event), + } + s.MaxLatency = 120 * time.Second +} + +func (s *SessionSuiteRig) State(state sessionState) { + s.IsType(state, s.session.State, "session state should be %v", state) +} + +func (s *SessionSuiteRig) MessageSentEquals(msg *Message) { + msgBytes, ok := s.Receiver.LastMessage() + s.True(ok, "Should be connected") + s.NotNil(msgBytes, "Message should have been sent") + s.MessageEqualsBytes(msgBytes, msg) +} + +func (s *SessionSuiteRig) LastToAppMessageSent() { + s.MessageSentEquals(s.MockApp.lastToApp) +} + +func (s *SessionSuiteRig) LastToAdminMessageSent() { + require.NotNil(s.T(), s.MockApp.lastToAdmin, "No ToAdmin received") + s.MessageSentEquals(s.MockApp.lastToAdmin) +} + +func (s *SessionSuiteRig) NotStopped() { + s.False(s.session.Stopped(), "session should not be stopped") +} + +func (s *SessionSuiteRig) Stopped() { + s.True(s.session.Stopped(), "session should be stopped") +} + +func (s *SessionSuiteRig) Disconnected() { + msg, ok := s.Receiver.LastMessage() + s.Nil(msg, "Expect disconnect, not message") + s.False(ok, "Expect disconnect") +} + +func (s *SessionSuiteRig) NoMessageSent() { + msg, _ := s.Receiver.LastMessage() + s.Nil(msg, "no message should be sent but got %s", msg) +} + +func (s *SessionSuiteRig) NoMessageQueued() { + s.Empty(s.session.toSend, "no messages should be queueud") +} + +func (s *SessionSuiteRig) ExpectStoreReset() { + s.NextSenderMsgSeqNum(1) + s.NextTargetMsgSeqNum(1) +} + +func (s *SessionSuiteRig) NextTargetMsgSeqNum(expected int) { + s.Equal(expected, s.session.store.NextTargetMsgSeqNum(), "NextTargetMsgSeqNum should be %v ", expected) +} + +func (s *SessionSuiteRig) NextSenderMsgSeqNum(expected int) { + s.Equal(expected, s.session.store.NextSenderMsgSeqNum(), "NextSenderMsgSeqNum should be %v", expected) +} + +func (s *SessionSuiteRig) IncrNextSenderMsgSeqNum() { + s.Require().Nil(s.session.store.IncrNextSenderMsgSeqNum()) +} + +func (s *SessionSuiteRig) IncrNextTargetMsgSeqNum() { + s.Require().Nil(s.session.store.IncrNextTargetMsgSeqNum()) +} + +func (s *SessionSuiteRig) NoMessagePersisted(seqNum int) { + persistedMessages, err := s.session.store.GetMessages(seqNum, seqNum) + s.Nil(err) + s.Empty(persistedMessages, "The message should not be persisted") +} + +func (s *SessionSuiteRig) MessagePersisted(msg *Message) { + var err error + seqNum, err := msg.Header.GetInt(tagMsgSeqNum) + s.Nil(err, "message should have seq num") + + persistedMessages, err := s.session.store.GetMessages(seqNum, seqNum) + s.Nil(err) + s.Len(persistedMessages, 1, "a message should be stored at %v", seqNum) + s.MessageEqualsBytes(persistedMessages[0], msg) +} diff --git a/vendor/github.com/quickfixgo/quickfix/registry.go b/vendor/github.com/quickfixgo/quickfix/registry.go index 87d55d4..ac074d2 100644 --- a/vendor/github.com/quickfixgo/quickfix/registry.go +++ b/vendor/github.com/quickfixgo/quickfix/registry.go @@ -12,7 +12,7 @@ var errUnknownSession = errors.New("Unknown session") //Messagable is a Message or something that can be converted to a Message type Messagable interface { - ToMessage() Message + ToMessage() *Message } //Send determines the session to send Messagable using header fields BeginString, TargetCompID, SenderCompID diff --git a/vendor/github.com/quickfixgo/quickfix/repeating_group.go b/vendor/github.com/quickfixgo/quickfix/repeating_group.go index e9fcbb8..d3bc4a5 100644 --- a/vendor/github.com/quickfixgo/quickfix/repeating_group.go +++ b/vendor/github.com/quickfixgo/quickfix/repeating_group.go @@ -17,7 +17,7 @@ type GroupItem interface { // //The Read function returns the remaining tagValues not processed by the GroupItem. If there was a //problem reading the field, an error may be returned - Read(TagValues) (TagValues, error) + Read([]TagValue) ([]TagValue, error) //Clone makes a copy of this GroupItem Clone() GroupItem @@ -28,7 +28,7 @@ type protoGroupElement struct { } func (t protoGroupElement) Tag() Tag { return t.tag } -func (t protoGroupElement) Read(tv TagValues) (TagValues, error) { +func (t protoGroupElement) Read(tv []TagValue) ([]TagValue, error) { if tv[0].tag == t.tag { return tv[1:], nil } @@ -63,7 +63,7 @@ type Group struct{ FieldMap } type RepeatingGroup struct { tag Tag template GroupTemplate - groups []Group + groups []*Group } //NewRepeatingGroup returns an initilized RepeatingGroup instance @@ -93,13 +93,13 @@ func (f RepeatingGroup) Len() int { } //Get returns the ith group in this RepeatingGroup -func (f RepeatingGroup) Get(i int) Group { +func (f RepeatingGroup) Get(i int) *Group { return f.groups[i] } //Add appends a new group to the RepeatingGroup and returns the new Group -func (f *RepeatingGroup) Add() Group { - var g Group +func (f *RepeatingGroup) Add() *Group { + g := new(Group) g.initWithOrdering(f.groupTagOrder()) f.groups = append(f.groups, g) @@ -108,8 +108,8 @@ func (f *RepeatingGroup) Add() Group { //Write returns tagValues for all Items in the repeating group ordered by //Group sequence and Group template order -func (f RepeatingGroup) Write() TagValues { - tvs := make(TagValues, 1, 1) +func (f RepeatingGroup) Write() []TagValue { + tvs := make([]TagValue, 1, 1) tvs[0].init(f.tag, []byte(strconv.Itoa(len(f.groups)))) for _, group := range f.groups { @@ -167,7 +167,7 @@ func (f RepeatingGroup) isDelimiter(t Tag) bool { return t == f.delimiter() } -func (f *RepeatingGroup) Read(tv TagValues) (TagValues, error) { +func (f *RepeatingGroup) Read(tv []TagValue) ([]TagValue, error) { expectedGroupSize, err := atoi(tv[0].value) if err != nil { return tv, err @@ -179,21 +179,21 @@ func (f *RepeatingGroup) Read(tv TagValues) (TagValues, error) { tv = tv[1:cap(tv)] tagOrdering := f.groupTagOrder() - var group Group + group := new(Group) group.initWithOrdering(tagOrdering) for len(tv) > 0 { - field, ok := f.findItemInGroupTemplate(tv[0].tag) + gi, ok := f.findItemInGroupTemplate(tv[0].tag) if !ok { break } tvRange := tv - if tv, err = field.Read(tv); err != nil { + if tv, err = gi.Read(tv); err != nil { return tv, err } - if f.isDelimiter(field.Tag()) { - group = Group{} + if f.isDelimiter(gi.Tag()) { + group = new(Group) group.initWithOrdering(tagOrdering) f.groups = append(f.groups, group) diff --git a/vendor/github.com/quickfixgo/quickfix/repeating_group_test.go b/vendor/github.com/quickfixgo/quickfix/repeating_group_test.go new file mode 100644 index 0000000..d43d38d --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/repeating_group_test.go @@ -0,0 +1,276 @@ +package quickfix + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestRepeatingGroup_Add(t *testing.T) { + f := RepeatingGroup{template: GroupTemplate{GroupElement(1)}} + + var tests = []struct { + expectedLen int + }{ + {1}, + {2}, + } + + for _, test := range tests { + g := f.Add() + if f.Len() != test.expectedLen { + t.Errorf("Expected %v groups, got %v", test.expectedLen, f.Len()) + } + + g.SetField(Tag(1), FIXString("hello")) + + if !f.groups[test.expectedLen-1].Has(Tag(1)) { + t.Errorf("expected tag in group %v", test.expectedLen) + } + + var v FIXString + require.Nil(t, f.groups[test.expectedLen-1].GetField(Tag(1), &v)) + + if string(v) != "hello" { + t.Errorf("expected hello in group %v", test.expectedLen) + } + } +} + +func TestRepeatingGroup_Write(t *testing.T) { + f1 := RepeatingGroup{tag: 10, template: GroupTemplate{ + GroupElement(1), + GroupElement(2), + }} + + f1.Add().SetField(Tag(1), FIXString("hello")) + + f2 := RepeatingGroup{tag: 11, template: GroupTemplate{ + GroupElement(1), + GroupElement(2), + }} + f2.Add().SetField(Tag(1), FIXString("hello")).SetField(Tag(2), FIXString("world")) + + f3 := RepeatingGroup{tag: 12, template: GroupTemplate{ + GroupElement(1), + GroupElement(2), + }} + f3.Add().SetField(Tag(1), FIXString("hello")) + f3.Add().SetField(Tag(1), FIXString("world")) + + f4 := RepeatingGroup{tag: 13, template: GroupTemplate{ + GroupElement(1), + GroupElement(2), + }} + f4.Add().SetField(Tag(1), FIXString("hello")).SetField(Tag(2), FIXString("world")) + f4.Add().SetField(Tag(1), FIXString("goodbye")) + + var tests = []struct { + f RepeatingGroup + expected []byte + }{ + {f1, []byte("10=11=hello")}, + {f2, []byte("11=11=hello2=world")}, + {f3, []byte("12=21=hello1=world")}, + {f4, []byte("13=21=hello2=world1=goodbye")}, + } + + for _, test := range tests { + tvbytes := []byte{} + for _, tv := range test.f.Write() { + tvbytes = append(tvbytes, tv.bytes...) + } + + if !bytes.Equal(test.expected, tvbytes) { + t.Errorf("expected %s got %s", test.expected, tvbytes) + } + } +} + +func TestRepeatingGroup_ReadError(t *testing.T) { + singleFieldTemplate := GroupTemplate{GroupElement(1)} + tests := []struct { + tv []TagValue + expectedGroupNum int + }{ + { + []TagValue{ + TagValue{value: []byte("1")}, + TagValue{tag: Tag(2), value: []byte("not in template")}, + TagValue{tag: Tag(1), value: []byte("hello")}, + }, 0}, + { + []TagValue{ + TagValue{value: []byte("2")}, + TagValue{tag: Tag(1), value: []byte("hello")}, + TagValue{tag: Tag(2), value: []byte("not in template")}, + TagValue{tag: Tag(1), value: []byte("hello")}, + }, 1}} + + for _, s := range tests { + f := RepeatingGroup{template: singleFieldTemplate} + _, err := f.Read(s.tv) + if err == nil || len(f.groups) != s.expectedGroupNum { + t.Errorf("Should have raised an error because expected group number is wrong: %v instead of %v", len(f.groups), s.expectedGroupNum) + } + } +} + +func TestRepeatingGroup_Read(t *testing.T) { + + singleFieldTemplate := GroupTemplate{GroupElement(1)} + multiFieldTemplate := GroupTemplate{GroupElement(1), GroupElement(2), GroupElement(3)} + + tests := []struct { + groupTemplate GroupTemplate + tv []TagValue + expectedGroupTvs [][]TagValue + }{ + {singleFieldTemplate, []TagValue{TagValue{value: []byte("0")}}, + [][]TagValue{}}, + {singleFieldTemplate, []TagValue{TagValue{value: []byte("1")}, TagValue{tag: Tag(1), value: []byte("hello")}}, + [][]TagValue{{TagValue{tag: Tag(1), value: []byte("hello")}}}}, + {singleFieldTemplate, + []TagValue{TagValue{value: []byte("1")}, + TagValue{tag: Tag(1), value: []byte("hello")}, + TagValue{tag: Tag(2), value: []byte("not in group")}}, + [][]TagValue{ + {TagValue{tag: Tag(1), value: []byte("hello")}}}}, + {singleFieldTemplate, + []TagValue{TagValue{value: []byte("2")}, + TagValue{tag: Tag(1), value: []byte("hello")}, + TagValue{tag: Tag(1), value: []byte("world")}}, + [][]TagValue{ + {TagValue{tag: Tag(1), value: []byte("hello")}}, + {TagValue{tag: Tag(1), value: []byte("world")}}, + }}, + {multiFieldTemplate, + []TagValue{ + TagValue{value: []byte("2")}, + TagValue{tag: Tag(1), value: []byte("hello")}, + TagValue{tag: Tag(1), value: []byte("goodbye")}, TagValue{tag: Tag(2), value: []byte("cruel")}, TagValue{tag: Tag(3), value: []byte("world")}, + }, + [][]TagValue{ + {TagValue{tag: Tag(1), value: []byte("hello")}}, + {TagValue{tag: Tag(1), value: []byte("goodbye")}, TagValue{tag: Tag(2), value: []byte("cruel")}, TagValue{tag: Tag(3), value: []byte("world")}}, + }}, + {multiFieldTemplate, + []TagValue{ + TagValue{value: []byte("3")}, + TagValue{tag: Tag(1), value: []byte("hello")}, + TagValue{tag: Tag(1), value: []byte("goodbye")}, TagValue{tag: Tag(2), value: []byte("cruel")}, TagValue{tag: Tag(3), value: []byte("world")}, + TagValue{tag: Tag(1), value: []byte("another")}, + }, + [][]TagValue{ + {TagValue{tag: Tag(1), value: []byte("hello")}}, + {TagValue{tag: Tag(1), value: []byte("goodbye")}, TagValue{tag: Tag(2), value: []byte("cruel")}, TagValue{tag: Tag(3), value: []byte("world")}}, + {TagValue{tag: Tag(1), value: []byte("another")}}, + }}, + } + + for _, test := range tests { + f := RepeatingGroup{template: test.groupTemplate} + + _, err := f.Read(test.tv) + if err != nil { + t.Error(err) + } + if len(f.groups) != len(test.expectedGroupTvs) { + t.Errorf("expected %v groups, got %v", len(test.expectedGroupTvs), len(f.groups)) + } + + for g, group := range f.groups { + for _, expected := range test.expectedGroupTvs[g] { + var actual FIXString + require.Nil(t, group.GetField(expected.tag, &actual)) + + if !bytes.Equal(expected.value, []byte(actual)) { + t.Errorf("%v, %v: expected %s, got %s", g, expected.tag, expected.value, actual) + } + } + } + } +} + +func TestRepeatingGroup_ReadRecursive(t *testing.T) { + singleFieldTemplate := GroupTemplate{GroupElement(4)} + parentTemplate := GroupTemplate{GroupElement(2), NewRepeatingGroup(Tag(3), singleFieldTemplate), GroupElement(5)} + + f := NewRepeatingGroup(Tag(1), parentTemplate) + _, err := f.Read([]TagValue{ + TagValue{value: []byte("2")}, + TagValue{tag: Tag(2), value: []byte("hello")}, + TagValue{tag: 3, value: []byte("1")}, TagValue{tag: 4, value: []byte("foo")}, + TagValue{tag: Tag(2), value: []byte("world")}, + TagValue{tag: 3, value: []byte("2")}, TagValue{tag: 4, value: []byte("foo")}, TagValue{tag: 4, value: []byte("bar")}, TagValue{tag: 5, value: []byte("fubar")}, + }) + require.Nil(t, err) + + assert.Equal(t, 2, f.Len()) +} + +func TestRepeatingGroup_ReadComplete(t *testing.T) { + + rawMsg := bytes.NewBufferString("8=FIXT.1.19=26835=W34=711849=TEST52=20151027-18:41:52.69856=TST22=9948=TSTX15262=7268=4269=4270=0.07499272=20151027273=18:41:52.698269=7270=0.07501272=20151027273=18:41:52.698269=8270=0.07494272=20151027273=18:41:52.698269=B271=60272=20151027273=18:41:52.69810=163") + + msg := NewMessage() + err := ParseMessage(msg, rawMsg) + + if err != nil { + t.Error("Unexpected error, ", err) + } + + template := GroupTemplate{ + GroupElement(269), + GroupElement(270), + GroupElement(271), + GroupElement(272), + GroupElement(273), + } + + f := RepeatingGroup{tag: 268, template: template} + err = msg.Body.GetGroup(&f) + if err != nil { + t.Error("Unexpected error, ", err) + } + + if len(f.groups) != 4 { + t.Errorf("expected %v groups, got %v", 4, len(f.groups)) + } + + expectedGroupTags := [][]Tag{ + {Tag(269), Tag(270), Tag(272), Tag(273)}, + {Tag(269), Tag(270), Tag(272), Tag(273)}, + {Tag(269), Tag(270), Tag(272), Tag(273)}, + {Tag(269), Tag(271), Tag(272), Tag(273)}, + } + + expectedGroupValues := [][]FIXString{ + {FIXString("4"), FIXString("0.07499"), FIXString("20151027"), FIXString("18:41:52.698")}, + {FIXString("7"), FIXString("0.07501"), FIXString("20151027"), FIXString("18:41:52.698")}, + {FIXString("8"), FIXString("0.07494"), FIXString("20151027"), FIXString("18:41:52.698")}, + {FIXString("B"), FIXString("60"), FIXString("20151027"), FIXString("18:41:52.698")}, + } + + for i, group := range f.groups { + + for j, tag := range expectedGroupTags[i] { + if !group.Has(tag) { + t.Errorf("expected %v in group %v", expectedGroupTags[i][j], i) + continue + } + + var actual FIXString + if err := group.GetField(tag, &actual); err != nil { + t.Errorf("error getting field %v from group %v", tag, i) + continue + } + + if expectedGroupValues[i][j] != actual { + t.Errorf("Expected %v got %v", expectedGroupTags[i][j], actual) + } + } + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/resend_state.go b/vendor/github.com/quickfixgo/quickfix/resend_state.go index 60e62d7..a89d3f6 100644 --- a/vendor/github.com/quickfixgo/quickfix/resend_state.go +++ b/vendor/github.com/quickfixgo/quickfix/resend_state.go @@ -4,7 +4,7 @@ import "github.com/quickfixgo/quickfix/internal" type resendState struct { loggedOn - messageStash map[int]Message + messageStash map[int]*Message currentResendRangeEnd int resendRangeEnd int } @@ -25,7 +25,7 @@ func (s resendState) Timeout(session *session, event internal.Event) (nextState return } -func (s resendState) FixMsgIn(session *session, msg Message) (nextState sessionState) { +func (s resendState) FixMsgIn(session *session, msg *Message) (nextState sessionState) { nextState = inSession{}.FixMsgIn(session, msg) if !nextState.IsLoggedOn() { @@ -51,8 +51,12 @@ func (s resendState) FixMsgIn(session *session, msg Message) (nextState sessionS if !ok { break } + delete(s.messageStash, targetSeqNum) + //return stashed message to pool + session.returnToPool(msg) + nextState = inSession{}.FixMsgIn(session, msg) if !nextState.IsLoggedOn() { return diff --git a/vendor/github.com/quickfixgo/quickfix/resend_state_test.go b/vendor/github.com/quickfixgo/quickfix/resend_state_test.go new file mode 100644 index 0000000..aa13cc8 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/resend_state_test.go @@ -0,0 +1,175 @@ +package quickfix + +import ( + "testing" + + "github.com/quickfixgo/quickfix/internal" + "github.com/stretchr/testify/suite" +) + +type resendStateTestSuite struct { + SessionSuiteRig +} + +func TestResendStateTestSuite(t *testing.T) { + suite.Run(t, new(resendStateTestSuite)) +} + +func (s *resendStateTestSuite) SetupTest() { + s.Init() + s.session.State = resendState{} +} + +func (s *resendStateTestSuite) TestIsLoggedOn() { + s.True(s.session.IsLoggedOn()) +} + +func (s *resendStateTestSuite) TestIsConnected() { + s.True(s.session.IsConnected()) +} + +func (s *resendStateTestSuite) TestIsSessionTime() { + s.True(s.session.IsSessionTime()) +} + +func (s *resendStateTestSuite) TestTimeoutPeerTimeout() { + s.MockApp.On("ToAdmin") + s.session.Timeout(s.session, internal.PeerTimeout) + + s.MockApp.AssertExpectations(s.T()) + s.State(pendingTimeout{resendState{}}) +} + +func (s *resendStateTestSuite) TestTimeoutUnchangedIgnoreLogonLogoutTimeout() { + tests := []internal.Event{internal.LogonTimeout, internal.LogoutTimeout} + + for _, event := range tests { + s.session.Timeout(s.session, event) + s.State(resendState{}) + } +} + +func (s *resendStateTestSuite) TestTimeoutUnchangedNeedHeartbeat() { + s.MockApp.On("ToAdmin") + s.session.Timeout(s.session, internal.NeedHeartbeat) + + s.MockApp.AssertExpectations(s.T()) + s.State(resendState{}) +} + +func (s *resendStateTestSuite) TestFixMsgIn() { + s.session.State = inSession{} + + //in session expects seq number 1, send too high + s.MessageFactory.SetNextSeqNum(2) + s.MockApp.On("ToAdmin") + + msgSeqNum2 := s.NewOrderSingle() + s.fixMsgIn(s.session, msgSeqNum2) + + s.MockApp.AssertExpectations(s.T()) + s.State(resendState{}) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeResendRequest), s.MockApp.lastToAdmin) + s.FieldEquals(tagBeginSeqNo, 1, s.MockApp.lastToAdmin.Body) + s.NextTargetMsgSeqNum(1) + + msgSeqNum3 := s.NewOrderSingle() + s.fixMsgIn(s.session, msgSeqNum3) + s.State(resendState{}) + s.NextTargetMsgSeqNum(1) + + msgSeqNum4 := s.NewOrderSingle() + s.fixMsgIn(s.session, msgSeqNum4) + + s.State(resendState{}) + s.NextTargetMsgSeqNum(1) + + s.MessageFactory.SetNextSeqNum(1) + s.MockApp.On("FromApp").Return(nil) + s.fixMsgIn(s.session, s.NewOrderSingle()) + + s.MockApp.AssertNumberOfCalls(s.T(), "FromApp", 4) + s.State(inSession{}) + s.NextTargetMsgSeqNum(5) +} + +func (s *resendStateTestSuite) TestFixMsgInSequenceReset() { + s.session.State = inSession{} + + //in session expects seq number 1, send too high + s.MessageFactory.SetNextSeqNum(3) + s.MockApp.On("ToAdmin") + + msgSeqNum3 := s.NewOrderSingle() + s.fixMsgIn(s.session, msgSeqNum3) + + s.MockApp.AssertExpectations(s.T()) + s.State(resendState{}) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeResendRequest), s.MockApp.lastToAdmin) + s.FieldEquals(tagBeginSeqNo, 1, s.MockApp.lastToAdmin.Body) + s.NextTargetMsgSeqNum(1) + + s.MessageFactory.SetNextSeqNum(1) + s.MockApp.On("FromAdmin").Return(nil) + s.fixMsgIn(s.session, s.SequenceReset(2)) + s.NextTargetMsgSeqNum(2) + s.State(resendState{}) + + s.MockApp.On("FromApp").Return(nil) + s.fixMsgIn(s.session, s.NewOrderSingle()) + + s.MockApp.AssertNumberOfCalls(s.T(), "FromApp", 2) + s.NextTargetMsgSeqNum(4) + s.State(inSession{}) +} + +func (s *resendStateTestSuite) TestFixMsgInResendChunk() { + s.session.State = inSession{} + s.ResendRequestChunkSize = 2 + + //in session expects seq number 1, send too high + s.MessageFactory.SetNextSeqNum(4) + s.MockApp.On("ToAdmin") + + msgSeqNum4 := s.NewOrderSingle() + s.fixMsgIn(s.session, msgSeqNum4) + + s.MockApp.AssertExpectations(s.T()) + s.State(resendState{}) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeResendRequest), s.MockApp.lastToAdmin) + s.FieldEquals(tagBeginSeqNo, 1, s.MockApp.lastToAdmin.Body) + s.FieldEquals(tagEndSeqNo, 2, s.MockApp.lastToAdmin.Body) + s.NextTargetMsgSeqNum(1) + + msgSeqNum5 := s.NewOrderSingle() + s.fixMsgIn(s.session, msgSeqNum5) + s.State(resendState{}) + s.NextTargetMsgSeqNum(1) + + msgSeqNum6 := s.NewOrderSingle() + s.fixMsgIn(s.session, msgSeqNum6) + + s.State(resendState{}) + s.NextTargetMsgSeqNum(1) + + s.MessageFactory.SetNextSeqNum(1) + s.MockApp.On("FromApp").Return(nil) + s.fixMsgIn(s.session, s.NewOrderSingle()) + + s.MockApp.AssertNumberOfCalls(s.T(), "FromApp", 1) + s.State(resendState{}) + s.NextTargetMsgSeqNum(2) + + s.fixMsgIn(s.session, s.NewOrderSingle()) + s.MockApp.AssertNumberOfCalls(s.T(), "FromApp", 2) + s.State(resendState{}) + s.NextTargetMsgSeqNum(3) + + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeResendRequest), s.MockApp.lastToAdmin) + s.FieldEquals(tagBeginSeqNo, 3, s.MockApp.lastToAdmin.Body) + s.FieldEquals(tagEndSeqNo, 0, s.MockApp.lastToAdmin.Body) +} diff --git a/vendor/github.com/quickfixgo/quickfix/screen_log.go b/vendor/github.com/quickfixgo/quickfix/screen_log.go index a26e687..0fcd4eb 100644 --- a/vendor/github.com/quickfixgo/quickfix/screen_log.go +++ b/vendor/github.com/quickfixgo/quickfix/screen_log.go @@ -9,12 +9,12 @@ type screenLog struct { prefix string } -func (l screenLog) OnIncoming(s string) { +func (l screenLog) OnIncoming(s []byte) { logTime := time.Now().UTC() fmt.Printf("<%v, %s, incoming>\n (%s)\n", logTime, l.prefix, s) } -func (l screenLog) OnOutgoing(s string) { +func (l screenLog) OnOutgoing(s []byte) { logTime := time.Now().UTC() fmt.Printf("<%v, %s, outgoing>\n (%s)\n", logTime, l.prefix, s) } diff --git a/vendor/github.com/quickfixgo/quickfix/session.go b/vendor/github.com/quickfixgo/quickfix/session.go index 6ef0857..e6dde98 100644 --- a/vendor/github.com/quickfixgo/quickfix/session.go +++ b/vendor/github.com/quickfixgo/quickfix/session.go @@ -1,12 +1,13 @@ package quickfix import ( + "bytes" "errors" "fmt" "sync" "time" - "github.com/quickfixgo/quickfix/enum" + "github.com/quickfixgo/quickfix/datadictionary" "github.com/quickfixgo/quickfix/internal" ) @@ -21,7 +22,7 @@ type session struct { messageIn <-chan fixIn //application messages are queued up for send here - toSend []Message + toSend [][]byte //mutex for access to toSend sendMutex sync.Mutex @@ -31,14 +32,19 @@ type session struct { application Application validator stateMachine - stateTimer internal.EventTimer - peerTimer internal.EventTimer + stateTimer *internal.EventTimer + peerTimer *internal.EventTimer sentReset bool targetDefaultApplVerID string admin chan interface{} internal.SessionSettings + transportDataDictionary *datadictionary.DataDictionary + appDataDictionary *datadictionary.DataDictionary + + messagePool + timestampPrecision TimestampPrecision } func (s *session) logError(err error) { @@ -86,22 +92,33 @@ func (s *session) waitForInSessionTime() { } } -func (s *session) insertSendingTime(header Header) { +func (s *session) insertSendingTime(msg *Message) { sendingTime := time.Now().UTC() - if s.sessionID.BeginString >= enum.BeginStringFIX42 { - header.SetField(tagSendingTime, FIXUTCTimestamp{Time: sendingTime}) + if s.sessionID.BeginString >= BeginStringFIX42 { + msg.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: sendingTime, Precision: s.timestampPrecision}) } else { - header.SetField(tagSendingTime, FIXUTCTimestamp{Time: sendingTime, NoMillis: true}) + msg.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: sendingTime, Precision: Seconds}) } } -func (s *session) fillDefaultHeader(msg Message, inReplyTo *Message) { - msg.Header.SetField(tagBeginString, FIXString(s.sessionID.BeginString)) - msg.Header.SetField(tagSenderCompID, FIXString(s.sessionID.SenderCompID)) - msg.Header.SetField(tagTargetCompID, FIXString(s.sessionID.TargetCompID)) +func optionallySetID(msg *Message, field Tag, value string) { + if len(value) != 0 { + msg.Header.SetString(field, value) + } +} + +func (s *session) fillDefaultHeader(msg *Message, inReplyTo *Message) { + msg.Header.SetString(tagBeginString, s.sessionID.BeginString) + msg.Header.SetString(tagSenderCompID, s.sessionID.SenderCompID) + optionallySetID(msg, tagSenderSubID, s.sessionID.SenderSubID) + optionallySetID(msg, tagSenderLocationID, s.sessionID.SenderLocationID) + + msg.Header.SetString(tagTargetCompID, s.sessionID.TargetCompID) + optionallySetID(msg, tagTargetSubID, s.sessionID.TargetSubID) + optionallySetID(msg, tagTargetLocationID, s.sessionID.TargetLocationID) - s.insertSendingTime(msg.Header) + s.insertSendingTime(msg) if s.EnableLastMsgSeqNumProcessed { if inReplyTo != nil { @@ -144,7 +161,7 @@ func (s *session) sendLogonInReplyTo(resetStore, setResetSeqNum bool, inReplyTo return nil } -func (s *session) buildLogout(reason string) Message { +func (s *session) buildLogout(reason string) *Message { logout := NewMessage() logout.Header.SetField(tagMsgType, FIXString("5")) logout.Header.SetField(tagBeginString, FIXString(s.sessionID.BeginString)) @@ -166,7 +183,7 @@ func (s *session) sendLogoutInReplyTo(reason string, inReplyTo *Message) error { return s.sendInReplyTo(logout, inReplyTo) } -func (s *session) resend(msg Message) bool { +func (s *session) resend(msg *Message) bool { msg.Header.SetField(tagPossDupFlag, FIXBoolean(true)) var origSendingTime FIXString @@ -174,21 +191,22 @@ func (s *session) resend(msg Message) bool { msg.Header.SetField(tagOrigSendingTime, origSendingTime) } - s.insertSendingTime(msg.Header) + s.insertSendingTime(msg) return s.application.ToApp(msg, s.sessionID) == nil } //queueForSend will validate, persist, and queue the message for send -func (s *session) queueForSend(msg Message) error { +func (s *session) queueForSend(msg *Message) error { s.sendMutex.Lock() defer s.sendMutex.Unlock() - if err := s.prepMessageForSend(&msg, nil); err != nil { + msgBytes, err := s.prepMessageForSend(msg, nil) + if err != nil { return err } - s.toSend = append(s.toSend, msg) + s.toSend = append(s.toSend, msgBytes) select { case s.messageEvent <- true: @@ -199,10 +217,10 @@ func (s *session) queueForSend(msg Message) error { } //send will validate, persist, queue the message. If the session is logged on, send all messages in the queue -func (s *session) send(msg Message) error { +func (s *session) send(msg *Message) error { return s.sendInReplyTo(msg, nil) } -func (s *session) sendInReplyTo(msg Message, inReplyTo *Message) error { +func (s *session) sendInReplyTo(msg *Message, inReplyTo *Message) error { if !s.IsLoggedOn() { return s.queueForSend(msg) } @@ -210,11 +228,12 @@ func (s *session) sendInReplyTo(msg Message, inReplyTo *Message) error { s.sendMutex.Lock() defer s.sendMutex.Unlock() - if err := s.prepMessageForSend(&msg, inReplyTo); err != nil { + msgBytes, err := s.prepMessageForSend(msg, inReplyTo) + if err != nil { return err } - s.toSend = append(s.toSend, msg) + s.toSend = append(s.toSend, msgBytes) s.sendQueued() return nil @@ -230,10 +249,10 @@ func (s *session) dropAndReset() error { } //dropAndSend will optionally reset the store, validate and persist the message, then drops the send queue and sends the message. -func (s *session) dropAndSend(msg Message, resetStore bool) error { +func (s *session) dropAndSend(msg *Message, resetStore bool) error { return s.dropAndSendInReplyTo(msg, resetStore, nil) } -func (s *session) dropAndSendInReplyTo(msg Message, resetStore bool, inReplyTo *Message) error { +func (s *session) dropAndSendInReplyTo(msg *Message, resetStore bool, inReplyTo *Message) error { s.sendMutex.Lock() defer s.sendMutex.Unlock() @@ -243,41 +262,42 @@ func (s *session) dropAndSendInReplyTo(msg Message, resetStore bool, inReplyTo * } } - if err := s.prepMessageForSend(&msg, inReplyTo); err != nil { + msgBytes, err := s.prepMessageForSend(msg, inReplyTo) + if err != nil { return err } s.dropQueued() - s.toSend = append(s.toSend, msg) + s.toSend = append(s.toSend, msgBytes) s.sendQueued() return nil } -func (s *session) prepMessageForSend(msg, inReplyTo *Message) error { - s.fillDefaultHeader(*msg, inReplyTo) +func (s *session) prepMessageForSend(msg *Message, inReplyTo *Message) (msgBytes []byte, err error) { + s.fillDefaultHeader(msg, inReplyTo) seqNum := s.store.NextSenderMsgSeqNum() msg.Header.SetField(tagMsgSeqNum, FIXInt(seqNum)) - var msgType FIXString - if err := msg.Header.GetField(tagMsgType, &msgType); err != nil { - return err + msgType, err := msg.Header.GetBytes(tagMsgType) + if err != nil { + return } - if isAdminMessageType(string(msgType)) { - s.application.ToAdmin(*msg, s.sessionID) + if isAdminMessageType(msgType) { + s.application.ToAdmin(msg, s.sessionID) - if enum.MsgType(msgType) == enum.MsgType_LOGON { + if bytes.Equal(msgType, msgTypeLogon) { var resetSeqNumFlag FIXBoolean if msg.Body.Has(tagResetSeqNumFlag) { - if err := msg.Body.GetField(tagResetSeqNumFlag, &resetSeqNumFlag); err != nil { - return err + if err = msg.Body.GetField(tagResetSeqNumFlag, &resetSeqNumFlag); err != nil { + return } } if resetSeqNumFlag.Bool() { - if err := s.store.Reset(); err != nil { - return err + if err = s.store.Reset(); err != nil { + return } s.sentReset = true @@ -287,30 +307,30 @@ func (s *session) prepMessageForSend(msg, inReplyTo *Message) error { } } else { - if err := s.application.ToApp(*msg, s.sessionID); err != nil { - return err + if err = s.application.ToApp(msg, s.sessionID); err != nil { + return } } - msgBytes, err := msg.Build() - if err == nil { - err = s.persist(seqNum, msgBytes) - } + msgBytes = msg.build() + err = s.persist(seqNum, msgBytes) - return err + return } func (s *session) persist(seqNum int, msgBytes []byte) error { - if err := s.store.SaveMessage(seqNum, msgBytes); err != nil { - return err + if !s.DisableMessagePersist { + if err := s.store.SaveMessage(seqNum, msgBytes); err != nil { + return err + } } return s.store.IncrNextSenderMsgSeqNum() } func (s *session) sendQueued() { - for _, msg := range s.toSend { - s.sendBytes(msg.rawMessage) + for _, msgBytes := range s.toSend { + s.sendBytes(msgBytes) } s.dropQueued() @@ -321,7 +341,7 @@ func (s *session) dropQueued() { } func (s *session) sendBytes(msg []byte) { - s.log.OnOutgoing(string(msg)) + s.log.OnOutgoing(msg) s.messageOut <- msg s.stateTimer.Reset(s.HeartBtInt) } @@ -335,7 +355,7 @@ func (s *session) sendResendRequest(beginSeq, endSeq int) (nextState resendState nextState.resendRangeEnd = endSeq resend := NewMessage() - resend.Header.SetField(tagMsgType, FIXString(enum.MsgType_RESEND_REQUEST)) + resend.Header.SetBytes(tagMsgType, msgTypeResendRequest) resend.Body.SetField(tagBeginSeqNo, FIXInt(beginSeq)) var endSeqNo int @@ -348,7 +368,7 @@ func (s *session) sendResendRequest(beginSeq, endSeq int) (nextState resendState if endSeqNo < endSeq { nextState.currentResendRangeEnd = endSeqNo } else { - if s.sessionID.BeginString < enum.BeginStringFIX42 { + if s.sessionID.BeginString < BeginStringFIX42 { endSeqNo = 999999 } else { endSeqNo = 0 @@ -364,9 +384,9 @@ func (s *session) sendResendRequest(beginSeq, endSeq int) (nextState resendState return } -func (s *session) handleLogon(msg Message) error { +func (s *session) handleLogon(msg *Message) error { //Grab default app ver id from fixt.1.1 logon - if s.sessionID.BeginString == enum.BeginStringFIXT11 { + if s.sessionID.BeginString == BeginStringFIXT11 { var targetApplVerID FIXString if err := msg.Body.GetField(tagDefaultApplVerID, &targetApplVerID); err != nil { @@ -417,7 +437,7 @@ func (s *session) handleLogon(msg Message) error { } s.log.OnEvent("Responding to logon request") - if err := s.sendLogonInReplyTo(resetStore, resetSeqNumFlag.Bool(), &msg); err != nil { + if err := s.sendLogonInReplyTo(resetStore, resetSeqNumFlag.Bool(), msg); err != nil { return err } } @@ -448,19 +468,19 @@ func (s *session) initiateLogoutInReplyTo(reason string, inReplyTo *Message) (er return } -func (s *session) verify(msg Message) MessageRejectError { +func (s *session) verify(msg *Message) MessageRejectError { return s.verifySelect(msg, true, true) } -func (s *session) verifyIgnoreSeqNumTooHigh(msg Message) MessageRejectError { +func (s *session) verifyIgnoreSeqNumTooHigh(msg *Message) MessageRejectError { return s.verifySelect(msg, false, true) } -func (s *session) verifyIgnoreSeqNumTooHighOrLow(msg Message) MessageRejectError { +func (s *session) verifyIgnoreSeqNumTooHighOrLow(msg *Message) MessageRejectError { return s.verifySelect(msg, false, false) } -func (s *session) verifySelect(msg Message, checkTooHigh bool, checkTooLow bool) MessageRejectError { +func (s *session) verifySelect(msg *Message, checkTooHigh bool, checkTooLow bool) MessageRejectError { if reject := s.checkBeginString(msg); reject != nil { return reject } @@ -494,49 +514,56 @@ func (s *session) verifySelect(msg Message, checkTooHigh bool, checkTooLow bool) return s.fromCallback(msg) } -func (s *session) fromCallback(msg Message) MessageRejectError { - var msgType FIXString - if err := msg.Header.GetField(tagMsgType, &msgType); err != nil { +func (s *session) fromCallback(msg *Message) MessageRejectError { + msgType, err := msg.Header.GetBytes(tagMsgType) + if err != nil { return err } - if isAdminMessageType(string(msgType)) { + if isAdminMessageType(msgType) { return s.application.FromAdmin(msg, s.sessionID) } return s.application.FromApp(msg, s.sessionID) } -func (s *session) checkTargetTooLow(msg Message) MessageRejectError { - var seqNum FIXInt - switch err := msg.Header.GetField(tagMsgSeqNum, &seqNum); { - case err != nil: +func (s *session) checkTargetTooLow(msg *Message) MessageRejectError { + if !msg.Header.Has(tagMsgSeqNum) { return RequiredTagMissing(tagMsgSeqNum) - case int(seqNum) < s.store.NextTargetMsgSeqNum(): - return targetTooLow{ReceivedTarget: int(seqNum), ExpectedTarget: s.store.NextTargetMsgSeqNum()} + } + + seqNum, err := msg.Header.GetInt(tagMsgSeqNum) + if err != nil { + return err + } + + if seqNum < s.store.NextTargetMsgSeqNum() { + return targetTooLow{ReceivedTarget: seqNum, ExpectedTarget: s.store.NextTargetMsgSeqNum()} } return nil } -func (s *session) checkTargetTooHigh(msg Message) MessageRejectError { - var seqNum FIXInt - switch err := msg.Header.GetField(tagMsgSeqNum, &seqNum); { - case err != nil: +func (s *session) checkTargetTooHigh(msg *Message) MessageRejectError { + if !msg.Header.Has(tagMsgSeqNum) { return RequiredTagMissing(tagMsgSeqNum) - case int(seqNum) > s.store.NextTargetMsgSeqNum(): - return targetTooHigh{ReceivedTarget: int(seqNum), ExpectedTarget: s.store.NextTargetMsgSeqNum()} + } + + seqNum, err := msg.Header.GetInt(tagMsgSeqNum) + if err != nil { + return err + } + + if seqNum > s.store.NextTargetMsgSeqNum() { + return targetTooHigh{ReceivedTarget: seqNum, ExpectedTarget: s.store.NextTargetMsgSeqNum()} } return nil } -func (s *session) checkCompID(msg Message) MessageRejectError { - var senderCompID FIXString - var targetCompID FIXString - - haveSender := msg.Header.GetField(tagSenderCompID, &senderCompID) - haveTarget := msg.Header.GetField(tagTargetCompID, &targetCompID) +func (s *session) checkCompID(msg *Message) MessageRejectError { + senderCompID, haveSender := msg.Header.GetBytes(tagSenderCompID) + targetCompID, haveTarget := msg.Header.GetBytes(tagTargetCompID) switch { case haveSender != nil: @@ -554,26 +581,29 @@ func (s *session) checkCompID(msg Message) MessageRejectError { return nil } -func (s *session) checkSendingTime(msg Message) MessageRejectError { +func (s *session) checkSendingTime(msg *Message) MessageRejectError { + if s.SkipCheckLatency { + return nil + } + if ok := msg.Header.Has(tagSendingTime); !ok { return RequiredTagMissing(tagSendingTime) } - sendingTime := new(FIXUTCTimestamp) - if err := msg.Header.GetField(tagSendingTime, sendingTime); err != nil { + sendingTime, err := msg.Header.GetTime(tagSendingTime) + if err != nil { return err } - if delta := time.Since(sendingTime.Time); delta <= -1*time.Duration(120)*time.Second || delta >= time.Duration(120)*time.Second { + if delta := time.Since(sendingTime); delta <= -1*s.MaxLatency || delta >= s.MaxLatency { return sendingTimeAccuracyProblem() } return nil } -func (s *session) checkBeginString(msg Message) MessageRejectError { - var beginString FIXString - switch err := msg.Header.GetField(tagBeginString, &beginString); { +func (s *session) checkBeginString(msg *Message) MessageRejectError { + switch beginString, err := msg.Header.GetBytes(tagBeginString); { case err != nil: return RequiredTagMissing(tagBeginString) case s.sessionID.BeginString != string(beginString): @@ -583,10 +613,10 @@ func (s *session) checkBeginString(msg Message) MessageRejectError { return nil } -func (s *session) doReject(msg Message, rej MessageRejectError) error { +func (s *session) doReject(msg *Message, rej MessageRejectError) error { reply := msg.reverseRoute() - if s.sessionID.BeginString >= enum.BeginStringFIX42 { + if s.sessionID.BeginString >= BeginStringFIX42 { if rej.IsBusinessReject() { reply.Header.SetField(tagMsgType, FIXString("j")) @@ -596,7 +626,7 @@ func (s *session) doReject(msg Message, rej MessageRejectError) error { switch { default: reply.Body.SetField(tagSessionRejectReason, FIXInt(rej.RejectReason())) - case rej.RejectReason() > rejectReasonInvalidMsgType && s.sessionID.BeginString == enum.BeginStringFIX42: + case rej.RejectReason() > rejectReasonInvalidMsgType && s.sessionID.BeginString == BeginStringFIX42: //fix42 knows up to invalid msg type } @@ -626,16 +656,30 @@ func (s *session) doReject(msg Message, rej MessageRejectError) error { } s.log.OnEventf("Message Rejected: %v", rej.Error()) - return s.sendInReplyTo(reply, &msg) + return s.sendInReplyTo(reply, msg) } type fixIn struct { - bytes []byte + bytes *bytes.Buffer receiveTime time.Time } +func (s *session) returnToPool(msg *Message) { + s.messagePool.Put(msg) + if msg.rawMessage != nil { + bufferPool.Put(msg.rawMessage) + msg.rawMessage = nil + } +} + func (s *session) onDisconnect() { s.log.OnEvent("Disconnected") + if s.ResetOnDisconnect { + if err := s.dropAndReset(); err != nil { + s.logError(err) + } + } + if s.messageOut != nil { close(s.messageOut) s.messageOut = nil @@ -681,9 +725,14 @@ func (s *session) onAdmin(msg interface{}) { func (s *session) run() { s.Start(s) + s.stateTimer = internal.NewEventTimer(func() { s.sessionEvent <- internal.NeedHeartbeat }) + s.peerTimer = internal.NewEventTimer(func() { s.sessionEvent <- internal.PeerTimeout }) + ticker := time.NewTicker(time.Second) + defer func() { s.stateTimer.Stop() s.peerTimer.Stop() + ticker.Stop() }() for !s.Stopped() { @@ -705,7 +754,7 @@ func (s *session) run() { case evt := <-s.sessionEvent: s.Timeout(s, evt) - case now := <-time.After(time.Second): + case now := <-ticker.C: s.CheckSessionTime(s, now) } } diff --git a/vendor/github.com/quickfixgo/quickfix/session_factory.go b/vendor/github.com/quickfixgo/quickfix/session_factory.go index 338a6f6..90e1182 100644 --- a/vendor/github.com/quickfixgo/quickfix/session_factory.go +++ b/vendor/github.com/quickfixgo/quickfix/session_factory.go @@ -8,7 +8,6 @@ import ( "github.com/quickfixgo/quickfix/config" "github.com/quickfixgo/quickfix/datadictionary" - "github.com/quickfixgo/quickfix/enum" "github.com/quickfixgo/quickfix/internal" ) @@ -31,14 +30,14 @@ var dayLookup = map[string]time.Weekday{ } var applVerIDLookup = map[string]string{ - enum.BeginStringFIX40: "2", - enum.BeginStringFIX41: "3", - enum.BeginStringFIX42: "4", - enum.BeginStringFIX43: "5", - enum.BeginStringFIX44: "6", - "FIX.5.0": "7", - "FIX.5.0SP1": "8", - "FIX.5.0SP2": "9", + BeginStringFIX40: "2", + BeginStringFIX41: "3", + BeginStringFIX42: "4", + BeginStringFIX43: "5", + BeginStringFIX44: "6", + "FIX.5.0": "7", + "FIX.5.0SP1": "8", + "FIX.5.0SP2": "9", } type sessionFactory struct { @@ -97,16 +96,15 @@ func (f sessionFactory) newSession( return } - var transportDataDictionary, appDataDictionary *datadictionary.DataDictionary - if transportDataDictionary, err = datadictionary.Parse(transportDataDictionaryPath); err != nil { + if s.transportDataDictionary, err = datadictionary.Parse(transportDataDictionaryPath); err != nil { return } - if appDataDictionary, err = datadictionary.Parse(appDataDictionaryPath); err != nil { + if s.appDataDictionary, err = datadictionary.Parse(appDataDictionaryPath); err != nil { return } - s.validator = &fixtValidator{transportDataDictionary, appDataDictionary, validatorSettings} + s.validator = &fixtValidator{s.transportDataDictionary, s.appDataDictionary, validatorSettings} } } else if settings.HasSetting(config.DataDictionary) { var dataDictionaryPath string @@ -114,12 +112,11 @@ func (f sessionFactory) newSession( return } - var dataDictionary *datadictionary.DataDictionary - if dataDictionary, err = datadictionary.Parse(dataDictionaryPath); err != nil { + if s.appDataDictionary, err = datadictionary.Parse(dataDictionaryPath); err != nil { return } - s.validator = &fixValidator{dataDictionary, validatorSettings} + s.validator = &fixValidator{s.appDataDictionary, validatorSettings} } if settings.HasSetting(config.ResetOnLogon) { @@ -140,12 +137,43 @@ func (f sessionFactory) newSession( } } + if settings.HasSetting(config.ResetOnDisconnect) { + if s.ResetOnDisconnect, err = settings.BoolSetting(config.ResetOnDisconnect); err != nil { + return + } + } + if settings.HasSetting(config.EnableLastMsgSeqNumProcessed) { if s.EnableLastMsgSeqNumProcessed, err = settings.BoolSetting(config.EnableLastMsgSeqNumProcessed); err != nil { return } } + if settings.HasSetting(config.CheckLatency) { + var doCheckLatency bool + if doCheckLatency, err = settings.BoolSetting(config.CheckLatency); err != nil { + return + } + + s.SkipCheckLatency = !doCheckLatency + } + + if !settings.HasSetting(config.MaxLatency) { + s.MaxLatency = 120 * time.Second + } else { + var maxLatency int + if maxLatency, err = settings.IntSetting(config.MaxLatency); err != nil { + return + } + + if maxLatency <= 0 { + err = errors.New("MaxLatency must be a positive integer") + return + } + + s.MaxLatency = time.Duration(maxLatency) * time.Second + } + if settings.HasSetting(config.ResendRequestChunkSize) { if s.ResendRequestChunkSize, err = settings.IntSetting(config.ResendRequestChunkSize); err != nil { return @@ -217,6 +245,37 @@ func (f sessionFactory) newSession( } } + if settings.HasSetting(config.TimeStampPrecision) { + var precisionStr string + if precisionStr, err = settings.Setting(config.TimeStampPrecision); err != nil { + return + } + + switch precisionStr { + case "SECONDS": + s.timestampPrecision = Seconds + case "MILLIS": + s.timestampPrecision = Millis + case "MICROS": + s.timestampPrecision = Micros + case "NANOS": + s.timestampPrecision = Nanos + + default: + err = IncorrectFormatForSetting{Setting: config.TimeStampPrecision, Value: precisionStr} + return + } + } + + if settings.HasSetting(config.PersistMessages) { + var persistMessages bool + if persistMessages, err = settings.BoolSetting(config.PersistMessages); err != nil { + return + } + + s.DisableMessagePersist = !persistMessages + } + if f.BuildInitiators { if err = f.buildInitiatorSettings(s, settings); err != nil { return @@ -235,8 +294,6 @@ func (f sessionFactory) newSession( s.messageEvent = make(chan bool, 1) s.admin = make(chan interface{}) s.application = application - s.stateTimer = internal.EventTimer{Task: func() { s.sessionEvent <- internal.NeedHeartbeat }} - s.peerTimer = internal.EventTimer{Task: func() { s.sessionEvent <- internal.PeerTimeout }} return } diff --git a/vendor/github.com/quickfixgo/quickfix/session_factory_test.go b/vendor/github.com/quickfixgo/quickfix/session_factory_test.go new file mode 100644 index 0000000..7db6cfd --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/session_factory_test.go @@ -0,0 +1,527 @@ +package quickfix + +import ( + "testing" + "time" + + "github.com/quickfixgo/quickfix/config" + "github.com/quickfixgo/quickfix/internal" + "github.com/stretchr/testify/suite" +) + +type SessionFactorySuite struct { + suite.Suite + + sessionFactory + SessionID + MessageStoreFactory + *SessionSettings + LogFactory + App *MockApp +} + +func TestSessionFactorySuite(t *testing.T) { + suite.Run(t, new(SessionFactorySuite)) +} + +func (s *SessionFactorySuite) SetupTest() { + s.sessionFactory = sessionFactory{} + s.SessionID = SessionID{BeginString: "FIX.4.2", TargetCompID: "TW", SenderCompID: "ISLD"} + s.MessageStoreFactory = NewMemoryStoreFactory() + s.SessionSettings = NewSessionSettings() + s.LogFactory = nullLogFactory{} + s.App = new(MockApp) +} + +func (s *SessionFactorySuite) TestDefaults() { + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session) + + s.False(session.ResetOnLogon) + s.False(session.RefreshOnLogon) + s.False(session.ResetOnLogout) + s.False(session.ResetOnDisconnect) + s.Nil(session.SessionTime, "By default, start and end time unset") + s.Equal("", session.DefaultApplVerID) + s.False(session.InitiateLogon) + s.Equal(0, session.ResendRequestChunkSize) + s.False(session.EnableLastMsgSeqNumProcessed) + s.False(session.SkipCheckLatency) + s.Equal(Millis, session.timestampPrecision) + s.Equal(120*time.Second, session.MaxLatency) + s.False(session.DisableMessagePersist) +} + +func (s *SessionFactorySuite) TestResetOnLogon() { + var tests = []struct { + setting string + expected bool + }{{"Y", true}, {"N", false}} + + for _, test := range tests { + s.SetupTest() + s.SessionSettings.Set(config.ResetOnLogon, test.setting) + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session) + + s.Equal(test.expected, session.ResetOnLogon) + } +} + +func (s *SessionFactorySuite) TestRefreshOnLogon() { + var tests = []struct { + setting string + expected bool + }{{"Y", true}, {"N", false}} + + for _, test := range tests { + s.SetupTest() + s.SessionSettings.Set(config.RefreshOnLogon, test.setting) + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session) + + s.Equal(test.expected, session.RefreshOnLogon) + } +} + +func (s *SessionFactorySuite) TestResetOnLogout() { + var tests = []struct { + setting string + expected bool + }{{"Y", true}, {"N", false}} + + for _, test := range tests { + s.SetupTest() + s.SessionSettings.Set(config.ResetOnLogout, test.setting) + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session) + + s.Equal(test.expected, session.ResetOnLogout) + } +} + +func (s *SessionFactorySuite) TestResetOnDisconnect() { + var tests = []struct { + setting string + expected bool + }{{"Y", true}, {"N", false}} + + for _, test := range tests { + s.SetupTest() + s.SessionSettings.Set(config.ResetOnDisconnect, test.setting) + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session) + + s.Equal(test.expected, session.ResetOnDisconnect) + } +} + +func (s *SessionFactorySuite) TestResendRequestChunkSize() { + s.SessionSettings.Set(config.ResendRequestChunkSize, "2500") + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session) + s.Equal(2500, session.ResendRequestChunkSize) + + s.SessionSettings.Set(config.ResendRequestChunkSize, "notanint") + session, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err) +} + +func (s *SessionFactorySuite) TestEnableLastMsgSeqNumProcessed() { + var tests = []struct { + setting string + expected bool + }{{"Y", true}, {"N", false}} + + for _, test := range tests { + s.SetupTest() + s.SessionSettings.Set(config.EnableLastMsgSeqNumProcessed, test.setting) + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session) + + s.Equal(test.expected, session.EnableLastMsgSeqNumProcessed) + } +} + +func (s *SessionFactorySuite) TestCheckLatency() { + var tests = []struct { + setting string + expected bool + }{{"Y", false}, {"N", true}} + + for _, test := range tests { + s.SetupTest() + s.SessionSettings.Set(config.CheckLatency, test.setting) + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session) + + s.Equal(test.expected, session.SkipCheckLatency) + } +} + +func (s *SessionFactorySuite) TestStartAndEndTime() { + s.SessionSettings.Set(config.StartTime, "12:00:00") + s.SessionSettings.Set(config.EndTime, "14:00:00") + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session.SessionTime) + + s.Equal( + *internal.NewUTCTimeRange(internal.NewTimeOfDay(12, 0, 0), internal.NewTimeOfDay(14, 0, 0)), + *session.SessionTime, + ) +} + +func (s *SessionFactorySuite) TestStartAndEndTimeAndTimeZone() { + s.SessionSettings.Set(config.StartTime, "12:00:00") + s.SessionSettings.Set(config.EndTime, "14:00:00") + s.SessionSettings.Set(config.TimeZone, "Local") + + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session.SessionTime) + + s.Equal( + *internal.NewTimeRangeInLocation(internal.NewTimeOfDay(12, 0, 0), internal.NewTimeOfDay(14, 0, 0), time.Local), + *session.SessionTime, + ) +} + +func (s *SessionFactorySuite) TestStartAndEndTimeAndStartAndEndDay() { + var tests = []struct { + startDay, endDay string + }{ + {"Sunday", "Thursday"}, + {"Sun", "Thu"}, + } + + for _, test := range tests { + s.SetupTest() + + s.SessionSettings.Set(config.StartTime, "12:00:00") + s.SessionSettings.Set(config.EndTime, "14:00:00") + s.SessionSettings.Set(config.StartDay, test.startDay) + s.SessionSettings.Set(config.EndDay, test.endDay) + + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session.SessionTime) + + s.Equal( + *internal.NewUTCWeekRange( + internal.NewTimeOfDay(12, 0, 0), internal.NewTimeOfDay(14, 0, 0), + time.Sunday, time.Thursday, + ), + *session.SessionTime, + ) + } +} + +func (s *SessionFactorySuite) TestStartAndEndTimeAndStartAndEndDayAndTimeZone() { + s.SessionSettings.Set(config.StartTime, "12:00:00") + s.SessionSettings.Set(config.EndTime, "14:00:00") + s.SessionSettings.Set(config.StartDay, "Sunday") + s.SessionSettings.Set(config.EndDay, "Thursday") + s.SessionSettings.Set(config.TimeZone, "Local") + + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session.SessionTime) + + s.Equal( + *internal.NewWeekRangeInLocation( + internal.NewTimeOfDay(12, 0, 0), internal.NewTimeOfDay(14, 0, 0), + time.Sunday, time.Thursday, time.Local, + ), + *session.SessionTime, + ) +} + +func (s *SessionFactorySuite) TestMissingStartOrEndTime() { + s.SessionSettings.Set(config.StartTime, "12:00:00") + _, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err) + + s.SetupTest() + s.SessionSettings.Set(config.EndTime, "14:00:00") + _, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err) +} + +func (s *SessionFactorySuite) TestStartOrEndTimeParseError() { + s.SessionSettings.Set(config.StartTime, "1200:00") + s.SessionSettings.Set(config.EndTime, "14:00:00") + + _, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err) + + s.SessionSettings.Set(config.StartTime, "12:00:00") + s.SessionSettings.Set(config.EndTime, "") + + _, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err) +} + +func (s *SessionFactorySuite) TestInvalidTimeZone() { + s.SessionSettings.Set(config.StartTime, "12:00:00") + s.SessionSettings.Set(config.EndTime, "14:00:00") + s.SessionSettings.Set(config.TimeZone, "not valid") + + _, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err) +} + +func (s *SessionFactorySuite) TestMissingStartOrEndDay() { + s.SessionSettings.Set(config.StartTime, "12:00:00") + s.SessionSettings.Set(config.EndTime, "14:00:00") + s.SessionSettings.Set(config.StartDay, "Thursday") + _, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err) + + s.SetupTest() + s.SessionSettings.Set(config.StartTime, "12:00:00") + s.SessionSettings.Set(config.EndTime, "14:00:00") + s.SessionSettings.Set(config.EndDay, "Sunday") + _, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err) +} + +func (s *SessionFactorySuite) TestStartOrEndDayParseError() { + s.SessionSettings.Set(config.StartTime, "12:00:00") + s.SessionSettings.Set(config.EndTime, "14:00:00") + s.SessionSettings.Set(config.StartDay, "notvalid") + s.SessionSettings.Set(config.EndDay, "Sunday") + _, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err) + + s.SetupTest() + s.SessionSettings.Set(config.StartTime, "12:00:00") + s.SessionSettings.Set(config.EndTime, "14:00:00") + s.SessionSettings.Set(config.StartDay, "Sunday") + s.SessionSettings.Set(config.EndDay, "blah") + + _, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err) +} + +func (s *SessionFactorySuite) TestDefaultApplVerID() { + s.SessionID = SessionID{BeginString: BeginStringFIXT11, TargetCompID: "TW", SenderCompID: "ISLD"} + + var tests = []struct{ expected, config string }{ + {"2", "2"}, + {"2", "FIX.4.0"}, + {"3", "3"}, + {"3", "FIX.4.1"}, + {"4", "4"}, + {"4", "FIX.4.2"}, + {"5", "5"}, + {"5", "FIX.4.3"}, + {"6", "6"}, + {"6", "FIX.4.4"}, + {"7", "7"}, + {"7", "FIX.5.0"}, + {"8", "8"}, + {"8", "FIX.5.0SP1"}, + {"9", "9"}, + {"9", "FIX.5.0SP2"}, + } + + for _, test := range tests { + s.SessionSettings.Set(config.DefaultApplVerID, test.config) + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.Equal(test.expected, session.DefaultApplVerID) + } +} + +func (s *SessionFactorySuite) TestNewSessionBuildInitiators() { + s.sessionFactory.BuildInitiators = true + s.SessionSettings.Set(config.HeartBtInt, "34") + s.SessionSettings.Set(config.SocketConnectHost, "127.0.0.1") + s.SessionSettings.Set(config.SocketConnectPort, "5000") + + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.True(session.InitiateLogon) + s.Equal(34*time.Second, session.HeartBtInt) + s.Equal(30*time.Second, session.ReconnectInterval) + s.Equal("127.0.0.1:5000", session.SocketConnectAddress[0]) +} + +func (s *SessionFactorySuite) TestNewSessionBuildInitiatorsValidHeartBtInt() { + s.sessionFactory.BuildInitiators = true + + _, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err, "HeartBtInt should be required for initiators") + + s.SessionSettings.Set(config.HeartBtInt, "not a number") + _, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err, "HeartBtInt must be a number") + + s.SessionSettings.Set(config.HeartBtInt, "0") + _, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err, "HeartBtInt must be greater than zero") + + s.SessionSettings.Set(config.HeartBtInt, "-20") + _, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err, "HeartBtInt must be greater than zero") +} + +func (s *SessionFactorySuite) TestNewSessionBuildInitiatorsValidReconnectInterval() { + s.sessionFactory.BuildInitiators = true + s.SessionSettings.Set(config.HeartBtInt, "34") + s.SessionSettings.Set(config.SocketConnectHost, "127.0.0.1") + s.SessionSettings.Set(config.SocketConnectPort, "3000") + + s.SessionSettings.Set(config.ReconnectInterval, "45") + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.Equal(45*time.Second, session.ReconnectInterval) + + s.SessionSettings.Set(config.ReconnectInterval, "not a number") + _, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err, "ReconnectInterval must be a number") + + s.SessionSettings.Set(config.ReconnectInterval, "0") + _, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err, "ReconnectInterval must be greater than zero") + + s.SessionSettings.Set(config.ReconnectInterval, "-20") + _, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err, "ReconnectInterval must be greater than zero") +} + +func (s *SessionFactorySuite) TestConfigureSocketConnectAddress() { + sess := new(session) + err := s.configureSocketConnectAddress(sess, s.SessionSettings) + s.NotNil(err, "SocketConnectHost and SocketConnectPort should be required") + + s.SessionSettings.Set(config.SocketConnectHost, "127.0.0.1") + err = s.configureSocketConnectAddress(sess, s.SessionSettings) + s.NotNil(err, "SocketConnectHost and SocketConnectPort should be required") + + s.SessionSettings = NewSessionSettings() + s.SessionSettings.Set(config.SocketConnectPort, "5000") + err = s.configureSocketConnectAddress(sess, s.SessionSettings) + s.NotNil(err, "SocketConnectHost and SocketConnectPort should be required") + + var tests = []struct{ host, port, expected string }{ + {"127.0.0.1", "3000", "127.0.0.1:3000"}, + {"example.com", "5000", "example.com:5000"}, + {"2001:db8:a0b:12f0::1", "3001", "[2001:db8:a0b:12f0::1]:3001"}, + } + + for _, test := range tests { + sess = new(session) + s.SessionSettings.Set(config.SocketConnectHost, test.host) + s.SessionSettings.Set(config.SocketConnectPort, test.port) + err = s.configureSocketConnectAddress(sess, s.SessionSettings) + s.Nil(err) + s.Len(sess.SocketConnectAddress, 1) + s.Equal(test.expected, sess.SocketConnectAddress[0]) + } +} + +func (s *SessionFactorySuite) TestConfigureSocketConnectAddressMulti() { + session := new(session) + s.SessionSettings.Set(config.SocketConnectHost, "127.0.0.1") + s.SessionSettings.Set(config.SocketConnectPort, "3000") + + s.SessionSettings.Set(config.SocketConnectHost+"1", "127.0.0.2") + s.SessionSettings.Set(config.SocketConnectPort+"1", "4000") + + s.SessionSettings.Set(config.SocketConnectHost+"2", "127.0.0.3") + s.SessionSettings.Set(config.SocketConnectPort+"2", "5000") + + err := s.configureSocketConnectAddress(session, s.SessionSettings) + s.Require().Nil(err) + s.Require().Len(session.SocketConnectAddress, 3) + var tests = []string{ + "127.0.0.1:3000", + "127.0.0.2:4000", + "127.0.0.3:5000", + } + + for i, expected := range tests { + s.Equal(expected, session.SocketConnectAddress[i]) + } + + s.SessionSettings.Set(config.SocketConnectHost+"3", "127.0.0.4") + err = s.configureSocketConnectAddress(session, s.SessionSettings) + s.NotNil(err, "must have both host and port to be valid") + + s.SessionSettings.Set(config.SocketConnectPort+"3", "5000") + s.SessionSettings.Set(config.SocketConnectPort+"4", "5000") + + err = s.configureSocketConnectAddress(session, s.SessionSettings) + s.NotNil(err, "must have both host and port to be valid") +} + +func (s *SessionFactorySuite) TestNewSessionTimestampPrecision() { + s.SessionSettings.Set(config.TimeStampPrecision, "blah") + + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err) + + var tests = []struct { + config string + precision TimestampPrecision + }{ + {"SECONDS", Seconds}, + {"MILLIS", Millis}, + {"MICROS", Micros}, + {"NANOS", Nanos}, + } + + for _, test := range tests { + s.SessionSettings.Set(config.TimeStampPrecision, test.config) + session, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + + s.Equal(session.timestampPrecision, test.precision) + } +} + +func (s *SessionFactorySuite) TestNewSessionMaxLatency() { + s.SessionSettings.Set(config.MaxLatency, "not a number") + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err, "MaxLatency must be a number") + + s.SessionSettings.Set(config.MaxLatency, "-20") + session, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err, "MaxLatency must be positive") + + s.SessionSettings.Set(config.MaxLatency, "0") + session, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.NotNil(err, "MaxLatency must be positive") + + s.SessionSettings.Set(config.MaxLatency, "20") + session, err = s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.Equal(session.MaxLatency, 20*time.Second) +} + +func (s *SessionFactorySuite) TestPersistMessages() { + var tests = []struct { + setting string + expected bool + }{{"Y", false}, {"N", true}} + + for _, test := range tests { + s.SetupTest() + s.SessionSettings.Set(config.PersistMessages, test.setting) + session, err := s.newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App) + s.Nil(err) + s.NotNil(session) + + s.Equal(test.expected, session.DisableMessagePersist) + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/session_id.go b/vendor/github.com/quickfixgo/quickfix/session_id.go index 7dfc6d8..a261d37 100644 --- a/vendor/github.com/quickfixgo/quickfix/session_id.go +++ b/vendor/github.com/quickfixgo/quickfix/session_id.go @@ -1,9 +1,6 @@ package quickfix -import ( - "fmt" - "github.com/quickfixgo/quickfix/enum" -) +import "bytes" // SessionID is a unique identifer of a Session type SessionID struct { @@ -12,13 +9,33 @@ type SessionID struct { //IsFIXT returns true if the SessionID has a FIXT BeginString func (s SessionID) IsFIXT() bool { - return s.BeginString == enum.BeginStringFIXT11 + return s.BeginString == BeginStringFIXT11 } -func (s SessionID) String() string { - if len(s.Qualifier) > 0 { - return fmt.Sprintf("%s:%s->%s:%s", s.BeginString, s.SenderCompID, s.TargetCompID, s.Qualifier) +func appendOptional(b *bytes.Buffer, delim, v string) { + if len(v) == 0 { + return } - return fmt.Sprintf("%s:%s->%s", s.BeginString, s.SenderCompID, s.TargetCompID) + b.WriteString(delim) + b.WriteString(v) +} + +func (s SessionID) String() string { + b := new(bytes.Buffer) + b.WriteString(s.BeginString) + b.WriteString(":") + b.WriteString(s.SenderCompID) + + appendOptional(b, "/", s.SenderSubID) + appendOptional(b, "/", s.SenderLocationID) + + b.WriteString("->") + b.WriteString(s.TargetCompID) + + appendOptional(b, "/", s.TargetSubID) + appendOptional(b, "/", s.TargetLocationID) + + appendOptional(b, ":", s.Qualifier) + return b.String() } diff --git a/vendor/github.com/quickfixgo/quickfix/session_id_test.go b/vendor/github.com/quickfixgo/quickfix/session_id_test.go new file mode 100644 index 0000000..6c5eae3 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/session_id_test.go @@ -0,0 +1,28 @@ +package quickfix + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSessionID_String(t *testing.T) { + var testCases = []struct { + sessionID SessionID + expectedString string + }{ + {SessionID{BeginString: "FIX.4.2", SenderCompID: "SND", TargetCompID: "TAR"}, "FIX.4.2:SND->TAR"}, + {SessionID{BeginString: "FIX.4.2", SenderCompID: "SND", TargetCompID: "TAR", Qualifier: "BLAH"}, "FIX.4.2:SND->TAR:BLAH"}, + {SessionID{BeginString: "FIX.4.2", SenderCompID: "SND", SenderSubID: "SSUB", SenderLocationID: "SLOC", + TargetCompID: "TAR", TargetSubID: "TSUB", TargetLocationID: "TLOC", + Qualifier: "BLAH"}, "FIX.4.2:SND/SSUB/SLOC->TAR/TSUB/TLOC:BLAH"}, + {SessionID{BeginString: "FIX.4.2", SenderCompID: "SND", SenderLocationID: "SLOC", + TargetCompID: "TAR", TargetSubID: "TSUB", TargetLocationID: "TLOC", + }, "FIX.4.2:SND/SLOC->TAR/TSUB/TLOC"}, + } + + for _, tc := range testCases { + actual := tc.sessionID.String() + assert.Equal(t, tc.expectedString, actual) + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/session_settings_test.go b/vendor/github.com/quickfixgo/quickfix/session_settings_test.go new file mode 100644 index 0000000..a28f605 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/session_settings_test.go @@ -0,0 +1,157 @@ +package quickfix + +import ( + "github.com/quickfixgo/quickfix/config" + "testing" +) + +func TestSessionSettings_StringSettings(t *testing.T) { + s := NewSessionSettings() + if s == nil { + t.Error("NewSessionSettings returned nil") + } + + s.Set(config.BeginString, "foo") + s.Set(config.BeginString, "blah") + s.Set(config.SenderCompID, "bar") + + if ok := s.HasSetting("DoesNotExist"); ok { + t.Error("HasSetting returned true for setting that doesn't exist") + } + + if ok := s.HasSetting(config.BeginString); !ok { + t.Error("HasSetting returned false for setting that does exist") + } + + if val, err := s.Setting(config.BeginString); err != nil { + t.Error("Got error requesing setting", err) + } else { + if val != "blah" { + t.Errorf("Expected %v got %v", "blah", val) + } + } +} + +func TestSessionSettings_IntSettings(t *testing.T) { + s := NewSessionSettings() + if _, err := s.IntSetting(config.SocketAcceptPort); err == nil { + t.Error("Expected error for unknown setting") + } + + s.Set(config.SocketAcceptPort, "notanint") + if _, err := s.IntSetting(config.SocketAcceptPort); err == nil { + t.Error("Expected error for unparsable value") + } + + s.Set(config.SocketAcceptPort, "1005") + val, err := s.IntSetting(config.SocketAcceptPort) + if err != nil { + t.Error("Unexpected err", err) + } + + if val != 1005 { + t.Errorf("Expected %v, got %v", 1005, val) + } +} + +func TestSessionSettings_BoolSettings(t *testing.T) { + s := NewSessionSettings() + if _, err := s.BoolSetting(config.ResetOnLogon); err == nil { + t.Error("Expected error for unknown setting") + } + + s.Set(config.ResetOnLogon, "notabool") + if _, err := s.BoolSetting(config.ResetOnLogon); err == nil { + t.Error("Expected error for unparsable value") + } + + var boolTests = []struct { + input string + expected bool + }{ + {"Y", true}, + {"y", true}, + {"N", false}, + {"n", false}, + } + + for _, bt := range boolTests { + s.Set(config.ResetOnLogon, bt.input) + + actual, err := s.BoolSetting(config.ResetOnLogon) + if err != nil { + t.Error("Unexpected err", err) + } + + if actual != bt.expected { + t.Errorf("Expected %v, got %v", bt.expected, actual) + } + } +} + +func TestSessionSettings_Clone(t *testing.T) { + s := NewSessionSettings() + + var cloneTests = []struct { + input string + expected string + }{ + {config.SocketAcceptPort, "101"}, + {config.BeginString, "foo"}, + {config.ResetOnLogon, "N"}, + } + + for _, ct := range cloneTests { + s.Set(ct.input, ct.expected) + } + + cloned := s.clone() + if cloned == nil { + t.Error("clone returned nil") + } + + for _, ct := range cloneTests { + actual, err := cloned.Setting(ct.input) + + if err != nil { + t.Error("Unexpected Error", err) + } + + if ct.expected != actual { + t.Errorf("Expected %v got %v", ct.expected, actual) + } + } +} + +func TestSessionSettings_Overlay(t *testing.T) { + s := NewSessionSettings() + overlay := NewSessionSettings() + + s.Set(config.SocketAcceptPort, "101") + s.Set(config.BeginString, "foo") + + overlay.Set(config.SocketAcceptPort, "102") + overlay.Set(config.SenderCompID, "blah") + + var overlayTests = []struct { + input string + expected string + }{ + {config.SocketAcceptPort, "102"}, + {config.BeginString, "foo"}, + {config.SenderCompID, "blah"}, + } + + s.overlay(overlay) + + for _, ot := range overlayTests { + actual, err := s.Setting(ot.input) + if err != nil { + t.Error("Unexpected error", err) + } + + if actual != ot.expected { + t.Errorf("expected %v got %v", ot.expected, actual) + } + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/session_state.go b/vendor/github.com/quickfixgo/quickfix/session_state.go index 7645919..0d8263f 100644 --- a/vendor/github.com/quickfixgo/quickfix/session_state.go +++ b/vendor/github.com/quickfixgo/quickfix/session_state.go @@ -67,17 +67,23 @@ func (sm *stateMachine) Incoming(session *session, m fixIn) { return } - session.log.OnIncoming(string(m.bytes)) - if msg, err := ParseMessage(m.bytes); err != nil { + session.log.OnIncoming(m.bytes.Bytes()) + + msg := session.messagePool.Get() + if err := ParseMessageWithDataDictionary(msg, m.bytes, session.transportDataDictionary, session.appDataDictionary); err != nil { session.log.OnEventf("Msg Parse Error: %v, %q", err.Error(), m.bytes) } else { msg.ReceiveTime = m.receiveTime sm.fixMsgIn(session, msg) } + + if !msg.keepMessage { + session.returnToPool(msg) + } session.peerTimer.Reset(time.Duration(float64(1.2) * float64(session.HeartBtInt))) } -func (sm *stateMachine) fixMsgIn(session *session, m Message) { +func (sm *stateMachine) fixMsgIn(session *session, m *Message) { sm.setState(session, sm.State.FixMsgIn(session, m)) } @@ -193,7 +199,7 @@ func handleStateError(s *session, err error) sessionState { type sessionState interface { //FixMsgIn is called by the session on incoming messages from the counter party. The return type is the next session state //following message processing - FixMsgIn(*session, Message) (nextState sessionState) + FixMsgIn(*session, *Message) (nextState sessionState) //Timeout is called by the session on a timeout event. Timeout(*session, internal.Event) (nextState sessionState) diff --git a/vendor/github.com/quickfixgo/quickfix/session_test.go b/vendor/github.com/quickfixgo/quickfix/session_test.go new file mode 100644 index 0000000..bd2bd18 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/session_test.go @@ -0,0 +1,902 @@ +package quickfix + +import ( + "bytes" + "testing" + "time" + + "github.com/quickfixgo/quickfix/internal" + + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +func newFIXString(val string) *FIXString { + s := FIXString(val) + return &s +} + +type SessionSuite struct { + SessionSuiteRig +} + +func TestSessionSuite(t *testing.T) { + suite.Run(t, new(SessionSuite)) +} + +func (s *SessionSuite) SetupTest() { + s.Init() + s.Require().Nil(s.session.store.Reset()) + s.session.State = latentState{} +} + +func (s *SessionSuite) TestFillDefaultHeader() { + s.session.sessionID.BeginString = "FIX.4.2" + s.session.sessionID.TargetCompID = "TAR" + s.session.sessionID.SenderCompID = "SND" + + msg := NewMessage() + s.session.fillDefaultHeader(msg, nil) + s.FieldEquals(tagBeginString, "FIX.4.2", msg.Header) + s.FieldEquals(tagTargetCompID, "TAR", msg.Header) + s.FieldEquals(tagSenderCompID, "SND", msg.Header) + s.False(msg.Header.Has(tagSenderSubID)) + s.False(msg.Header.Has(tagSenderLocationID)) + s.False(msg.Header.Has(tagTargetSubID)) + s.False(msg.Header.Has(tagTargetLocationID)) + + s.session.sessionID.BeginString = "FIX.4.3" + s.session.sessionID.TargetCompID = "TAR" + s.session.sessionID.TargetSubID = "TARS" + s.session.sessionID.TargetLocationID = "TARL" + s.session.sessionID.SenderCompID = "SND" + s.session.sessionID.SenderSubID = "SNDS" + s.session.sessionID.SenderLocationID = "SNDL" + + msg = NewMessage() + s.session.fillDefaultHeader(msg, nil) + s.FieldEquals(tagBeginString, "FIX.4.3", msg.Header) + s.FieldEquals(tagTargetCompID, "TAR", msg.Header) + s.FieldEquals(tagTargetSubID, "TARS", msg.Header) + s.FieldEquals(tagTargetLocationID, "TARL", msg.Header) + s.FieldEquals(tagSenderCompID, "SND", msg.Header) + s.FieldEquals(tagSenderSubID, "SNDS", msg.Header) + s.FieldEquals(tagSenderLocationID, "SNDL", msg.Header) +} + +func (s *SessionSuite) TestInsertSendingTime() { + var tests = []struct { + BeginString string + Precision TimestampPrecision + ExpectedPrecision TimestampPrecision + }{ + {BeginStringFIX40, Millis, Seconds}, //config is ignored for fix < 4.2 + {BeginStringFIX41, Millis, Seconds}, + + {BeginStringFIX42, Millis, Millis}, + {BeginStringFIX42, Micros, Micros}, + {BeginStringFIX42, Nanos, Nanos}, + + {BeginStringFIX43, Nanos, Nanos}, + {BeginStringFIX44, Nanos, Nanos}, + {BeginStringFIXT11, Nanos, Nanos}, + } + + for _, test := range tests { + s.session.sessionID.BeginString = test.BeginString + s.timestampPrecision = test.Precision + + msg := NewMessage() + s.session.insertSendingTime(msg) + + var f FIXUTCTimestamp + s.Nil(msg.Header.GetField(tagSendingTime, &f)) + s.Equal(f.Precision, test.ExpectedPrecision) + } +} + +func (s *SessionSuite) TestCheckCorrectCompID() { + s.session.sessionID.TargetCompID = "TAR" + s.session.sessionID.SenderCompID = "SND" + + var testCases = []struct { + senderCompID *FIXString + targetCompID *FIXString + returnsError bool + rejectReason int + }{ + {returnsError: true, rejectReason: rejectReasonRequiredTagMissing}, + {senderCompID: newFIXString("TAR"), + returnsError: true, + rejectReason: rejectReasonRequiredTagMissing}, + {senderCompID: newFIXString("TAR"), + targetCompID: newFIXString("JCD"), + returnsError: true, + rejectReason: rejectReasonCompIDProblem}, + {senderCompID: newFIXString("JCD"), + targetCompID: newFIXString("SND"), + returnsError: true, + rejectReason: rejectReasonCompIDProblem}, + {senderCompID: newFIXString("TAR"), + targetCompID: newFIXString("SND"), + returnsError: false}, + } + + for _, tc := range testCases { + msg := NewMessage() + + if tc.senderCompID != nil { + msg.Header.SetField(tagSenderCompID, tc.senderCompID) + } + + if tc.targetCompID != nil { + msg.Header.SetField(tagTargetCompID, tc.targetCompID) + } + + rej := s.session.checkCompID(msg) + + if !tc.returnsError { + s.Require().Nil(rej) + continue + } + + s.NotNil(rej) + s.Equal(tc.rejectReason, rej.RejectReason()) + } +} + +func (s *SessionSuite) TestCheckBeginString() { + msg := NewMessage() + + msg.Header.SetField(tagBeginString, FIXString("FIX.4.4")) + err := s.session.checkBeginString(msg) + s.Require().NotNil(err, "wrong begin string should return error") + s.IsType(incorrectBeginString{}, err) + + msg.Header.SetField(tagBeginString, FIXString(s.session.sessionID.BeginString)) + s.Nil(s.session.checkBeginString(msg)) +} + +func (s *SessionSuite) TestCheckTargetTooHigh() { + msg := NewMessage() + s.Require().Nil(s.session.store.SetNextTargetMsgSeqNum(45)) + + err := s.session.checkTargetTooHigh(msg) + s.Require().NotNil(err, "missing sequence number should return error") + s.Equal(rejectReasonRequiredTagMissing, err.RejectReason()) + + msg.Header.SetField(tagMsgSeqNum, FIXInt(47)) + err = s.session.checkTargetTooHigh(msg) + s.Require().NotNil(err, "sequence number too high should return an error") + s.IsType(targetTooHigh{}, err) + + //spot on + msg.Header.SetField(tagMsgSeqNum, FIXInt(45)) + s.Nil(s.session.checkTargetTooHigh(msg)) +} + +func (s *SessionSuite) TestCheckSendingTime() { + s.session.MaxLatency = time.Duration(120) * time.Second + msg := NewMessage() + + err := s.session.checkSendingTime(msg) + s.Require().NotNil(err, "sending time is a required field") + s.Equal(rejectReasonRequiredTagMissing, err.RejectReason()) + + sendingTime := time.Now().Add(time.Duration(-200) * time.Second) + msg.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: sendingTime}) + + err = s.session.checkSendingTime(msg) + s.Require().NotNil(err, "sending time too late should give error") + s.Equal(rejectReasonSendingTimeAccuracyProblem, err.RejectReason()) + + sendingTime = time.Now().Add(time.Duration(200) * time.Second) + msg.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: sendingTime}) + + err = s.session.checkSendingTime(msg) + s.Require().NotNil(err, "future sending time should give error") + s.Equal(rejectReasonSendingTimeAccuracyProblem, err.RejectReason()) + + sendingTime = time.Now() + msg.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: sendingTime}) + + s.Nil(s.session.checkSendingTime(msg), "sending time should be ok") + + s.session.SkipCheckLatency = true + sendingTime = time.Now().Add(time.Duration(-200) * time.Second) + msg.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: sendingTime}) + err = s.session.checkSendingTime(msg) + s.Require().Nil(err, "should skip latency check") +} + +func (s *SessionSuite) TestCheckTargetTooLow() { + msg := NewMessage() + s.Require().Nil(s.session.store.SetNextTargetMsgSeqNum(45)) + + err := s.session.checkTargetTooLow(msg) + s.Require().NotNil(err, "sequence number is required") + s.Equal(rejectReasonRequiredTagMissing, err.RejectReason()) + + //too low + msg.Header.SetField(tagMsgSeqNum, FIXInt(43)) + err = s.session.checkTargetTooLow(msg) + s.NotNil(err, "sequence number too low should return error") + s.IsType(targetTooLow{}, err) + + //spot on + msg.Header.SetField(tagMsgSeqNum, FIXInt(45)) + s.Nil(s.session.checkTargetTooLow(msg)) +} + +func (s *SessionSuite) TestCheckSessionTimeNoStartTimeEndTime() { + var tests = []struct { + before, after sessionState + }{ + {before: latentState{}}, + {before: logonState{}}, + {before: logoutState{}}, + {before: inSession{}}, + {before: resendState{}}, + {before: pendingTimeout{resendState{}}}, + {before: pendingTimeout{inSession{}}}, + {before: notSessionTime{}, after: latentState{}}, + } + + for _, test := range tests { + s.SetupTest() + s.session.SessionTime = nil + s.session.State = test.before + + s.session.CheckSessionTime(s.session, time.Now()) + if test.after != nil { + s.State(test.after) + } else { + s.State(test.before) + } + } +} + +func (s *SessionSuite) TestCheckSessionTimeInRange() { + var tests = []struct { + before, after sessionState + expectReset bool + }{ + {before: latentState{}}, + {before: logonState{}}, + {before: logoutState{}}, + {before: inSession{}}, + {before: resendState{}}, + {before: pendingTimeout{resendState{}}}, + {before: pendingTimeout{inSession{}}}, + {before: notSessionTime{}, after: latentState{}, expectReset: true}, + } + + for _, test := range tests { + s.SetupTest() + s.session.State = test.before + + now := time.Now().UTC() + store := new(memoryStore) + if test.before.IsSessionTime() { + s.Require().Nil(store.Reset()) + } else { + store.creationTime = now.Add(time.Duration(-1) * time.Minute) + } + s.session.store = store + s.IncrNextSenderMsgSeqNum() + s.IncrNextTargetMsgSeqNum() + + s.session.SessionTime = internal.NewUTCTimeRange( + internal.NewTimeOfDay(now.Clock()), + internal.NewTimeOfDay(now.Add(time.Hour).Clock()), + ) + + s.session.CheckSessionTime(s.session, now) + if test.after != nil { + s.State(test.after) + } else { + s.State(test.before) + } + + if test.expectReset { + s.ExpectStoreReset() + } else { + s.NextSenderMsgSeqNum(2) + s.NextSenderMsgSeqNum(2) + } + } +} + +func (s *SessionSuite) TestCheckSessionTimeNotInRange() { + var tests = []struct { + before sessionState + initiateLogon bool + expectOnLogout bool + expectSendLogout bool + }{ + {before: latentState{}}, + {before: logonState{}}, + {before: logonState{}, initiateLogon: true, expectOnLogout: true}, + {before: logoutState{}, expectOnLogout: true}, + {before: inSession{}, expectOnLogout: true, expectSendLogout: true}, + {before: resendState{}, expectOnLogout: true, expectSendLogout: true}, + {before: pendingTimeout{resendState{}}, expectOnLogout: true, expectSendLogout: true}, + {before: pendingTimeout{inSession{}}, expectOnLogout: true, expectSendLogout: true}, + {before: notSessionTime{}}, + } + + for _, test := range tests { + s.SetupTest() + s.session.State = test.before + s.session.InitiateLogon = test.initiateLogon + s.IncrNextSenderMsgSeqNum() + s.IncrNextTargetMsgSeqNum() + + now := time.Now().UTC() + s.session.SessionTime = internal.NewUTCTimeRange( + internal.NewTimeOfDay(now.Add(time.Hour).Clock()), + internal.NewTimeOfDay(now.Add(time.Duration(2)*time.Hour).Clock()), + ) + + if test.expectOnLogout { + s.MockApp.On("OnLogout") + } + if test.expectSendLogout { + s.MockApp.On("ToAdmin") + } + s.session.CheckSessionTime(s.session, now) + + s.MockApp.AssertExpectations(s.T()) + s.State(notSessionTime{}) + + s.NextTargetMsgSeqNum(2) + if test.expectSendLogout { + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogout), s.MockApp.lastToAdmin) + s.NextSenderMsgSeqNum(3) + } else { + s.NextSenderMsgSeqNum(2) + } + } +} + +func (s *SessionSuite) TestCheckSessionTimeInRangeButNotSameRangeAsStore() { + var tests = []struct { + before sessionState + initiateLogon bool + expectOnLogout bool + expectSendLogout bool + }{ + {before: latentState{}}, + {before: logonState{}}, + {before: logonState{}, initiateLogon: true, expectOnLogout: true}, + {before: logoutState{}, expectOnLogout: true}, + {before: inSession{}, expectOnLogout: true, expectSendLogout: true}, + {before: resendState{}, expectOnLogout: true, expectSendLogout: true}, + {before: pendingTimeout{resendState{}}, expectOnLogout: true, expectSendLogout: true}, + {before: pendingTimeout{inSession{}}, expectOnLogout: true, expectSendLogout: true}, + {before: notSessionTime{}}, + } + + for _, test := range tests { + s.SetupTest() + s.session.State = test.before + s.session.InitiateLogon = test.initiateLogon + s.Require().Nil(s.store.Reset()) + s.IncrNextSenderMsgSeqNum() + s.IncrNextTargetMsgSeqNum() + + now := time.Now().UTC() + s.session.SessionTime = internal.NewUTCTimeRange( + internal.NewTimeOfDay(now.Add(time.Duration(-1)*time.Hour).Clock()), + internal.NewTimeOfDay(now.Add(time.Hour).Clock()), + ) + + if test.expectOnLogout { + s.MockApp.On("OnLogout") + } + if test.expectSendLogout { + s.MockApp.On("ToAdmin") + } + s.session.CheckSessionTime(s.session, now.AddDate(0, 0, 1)) + + s.MockApp.AssertExpectations(s.T()) + s.State(latentState{}) + if test.expectSendLogout { + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogout), s.MockApp.lastToAdmin) + s.FieldEquals(tagMsgSeqNum, 2, s.MockApp.lastToAdmin.Header) + } + s.ExpectStoreReset() + } +} + +func (s *SessionSuite) TestIncomingNotInSessionTime() { + var tests = []struct { + before sessionState + initiateLogon bool + expectOnLogout bool + expectSendLogout bool + }{ + {before: logonState{}}, + {before: logonState{}, initiateLogon: true, expectOnLogout: true}, + {before: logoutState{}, expectOnLogout: true}, + {before: inSession{}, expectOnLogout: true, expectSendLogout: true}, + {before: resendState{}, expectOnLogout: true, expectSendLogout: true}, + {before: pendingTimeout{resendState{}}, expectOnLogout: true, expectSendLogout: true}, + {before: pendingTimeout{inSession{}}, expectOnLogout: true, expectSendLogout: true}, + } + + for _, test := range tests { + s.SetupTest() + + s.session.State = test.before + s.session.InitiateLogon = test.initiateLogon + s.IncrNextSenderMsgSeqNum() + s.IncrNextTargetMsgSeqNum() + + now := time.Now().UTC() + s.session.SessionTime = internal.NewUTCTimeRange( + internal.NewTimeOfDay(now.Add(time.Hour).Clock()), + internal.NewTimeOfDay(now.Add(time.Duration(2)*time.Hour).Clock()), + ) + if test.expectOnLogout { + s.MockApp.On("OnLogout") + } + if test.expectSendLogout { + s.MockApp.On("ToAdmin") + } + + msg := s.NewOrderSingle() + msgBytes := msg.build() + + s.session.Incoming(s.session, fixIn{bytes: bytes.NewBuffer(msgBytes)}) + s.MockApp.AssertExpectations(s.T()) + s.State(notSessionTime{}) + } +} + +func (s *SessionSuite) TestSendAppMessagesNotInSessionTime() { + var tests = []struct { + before sessionState + initiateLogon bool + expectOnLogout bool + expectSendLogout bool + }{ + {before: logonState{}}, + {before: logonState{}, initiateLogon: true, expectOnLogout: true}, + {before: logoutState{}, expectOnLogout: true}, + {before: inSession{}, expectOnLogout: true, expectSendLogout: true}, + {before: resendState{}, expectOnLogout: true, expectSendLogout: true}, + {before: pendingTimeout{resendState{}}, expectOnLogout: true, expectSendLogout: true}, + {before: pendingTimeout{inSession{}}, expectOnLogout: true, expectSendLogout: true}, + } + + for _, test := range tests { + s.SetupTest() + + s.session.State = test.before + s.session.InitiateLogon = test.initiateLogon + s.IncrNextSenderMsgSeqNum() + s.IncrNextTargetMsgSeqNum() + + s.MockApp.On("ToApp").Return(nil) + s.Require().Nil(s.queueForSend(s.NewOrderSingle())) + s.MockApp.AssertExpectations(s.T()) + + now := time.Now().UTC() + s.session.SessionTime = internal.NewUTCTimeRange( + internal.NewTimeOfDay(now.Add(time.Hour).Clock()), + internal.NewTimeOfDay(now.Add(time.Duration(2)*time.Hour).Clock()), + ) + if test.expectOnLogout { + s.MockApp.On("OnLogout") + } + if test.expectSendLogout { + s.MockApp.On("ToAdmin") + } + + s.session.SendAppMessages(s.session) + s.MockApp.AssertExpectations(s.T()) + s.State(notSessionTime{}) + } +} + +func (s *SessionSuite) TestTimeoutNotInSessionTime() { + var tests = []struct { + before sessionState + initiateLogon bool + expectOnLogout bool + expectSendLogout bool + }{ + {before: logonState{}}, + {before: logonState{}, initiateLogon: true, expectOnLogout: true}, + {before: logoutState{}, expectOnLogout: true}, + {before: inSession{}, expectOnLogout: true, expectSendLogout: true}, + {before: resendState{}, expectOnLogout: true, expectSendLogout: true}, + {before: pendingTimeout{resendState{}}, expectOnLogout: true, expectSendLogout: true}, + {before: pendingTimeout{inSession{}}, expectOnLogout: true, expectSendLogout: true}, + } + + var events = []internal.Event{internal.PeerTimeout, internal.NeedHeartbeat, internal.LogonTimeout, internal.LogoutTimeout} + + for _, test := range tests { + for _, event := range events { + s.SetupTest() + + s.session.State = test.before + s.session.InitiateLogon = test.initiateLogon + s.IncrNextSenderMsgSeqNum() + s.IncrNextTargetMsgSeqNum() + + now := time.Now().UTC() + s.session.SessionTime = internal.NewUTCTimeRange( + internal.NewTimeOfDay(now.Add(time.Hour).Clock()), + internal.NewTimeOfDay(now.Add(time.Duration(2)*time.Hour).Clock()), + ) + if test.expectOnLogout { + s.MockApp.On("OnLogout") + } + if test.expectSendLogout { + s.MockApp.On("ToAdmin") + } + + s.session.Timeout(s.session, event) + s.MockApp.AssertExpectations(s.T()) + s.State(notSessionTime{}) + } + } +} + +func (s *SessionSuite) TestOnAdminConnectInitiateLogon() { + adminMsg := connect{ + messageOut: s.Receiver.sendChannel, + } + s.session.State = latentState{} + s.session.HeartBtInt = time.Duration(45) * time.Second + s.IncrNextSenderMsgSeqNum() + s.session.InitiateLogon = true + + s.MockApp.On("ToAdmin") + s.session.onAdmin(adminMsg) + + s.MockApp.AssertExpectations(s.T()) + s.True(s.session.InitiateLogon) + s.False(s.sentReset) + s.State(logonState{}) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogon), s.MockApp.lastToAdmin) + s.FieldEquals(tagHeartBtInt, 45, s.MockApp.lastToAdmin.Body) + s.FieldEquals(tagMsgSeqNum, 2, s.MockApp.lastToAdmin.Header) + s.NextSenderMsgSeqNum(3) +} + +func (s *SessionSuite) TestInitiateLogonResetSeqNumFlag() { + adminMsg := connect{ + messageOut: s.Receiver.sendChannel, + } + s.session.State = latentState{} + s.session.HeartBtInt = time.Duration(45) * time.Second + s.IncrNextTargetMsgSeqNum() + s.IncrNextSenderMsgSeqNum() + s.session.InitiateLogon = true + + s.MockApp.On("ToAdmin") + s.MockApp.decorateToAdmin = func(msg *Message) { + msg.Body.SetField(tagResetSeqNumFlag, FIXBoolean(true)) + } + s.session.onAdmin(adminMsg) + + s.MockApp.AssertExpectations(s.T()) + s.True(s.session.InitiateLogon) + s.True(s.sentReset) + s.State(logonState{}) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogon), s.MockApp.lastToAdmin) + s.FieldEquals(tagMsgSeqNum, 1, s.MockApp.lastToAdmin.Header) + s.FieldEquals(tagResetSeqNumFlag, true, s.MockApp.lastToAdmin.Body) + s.NextSenderMsgSeqNum(2) + s.NextTargetMsgSeqNum(1) +} + +func (s *SessionSuite) TestOnAdminConnectInitiateLogonFIXT11() { + s.session.sessionID.BeginString = string(BeginStringFIXT11) + s.session.DefaultApplVerID = "8" + s.session.InitiateLogon = true + + adminMsg := connect{ + messageOut: s.Receiver.sendChannel, + } + s.session.State = latentState{} + + s.MockApp.On("ToAdmin") + s.session.onAdmin(adminMsg) + + s.MockApp.AssertExpectations(s.T()) + s.True(s.session.InitiateLogon) + s.State(logonState{}) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeLogon), s.MockApp.lastToAdmin) + s.FieldEquals(tagDefaultApplVerID, "8", s.MockApp.lastToAdmin.Body) +} + +func (s *SessionSuite) TestOnAdminConnectRefreshOnLogon() { + var tests = []bool{true, false} + + for _, doRefresh := range tests { + s.SetupTest() + s.session.RefreshOnLogon = doRefresh + + adminMsg := connect{ + messageOut: s.Receiver.sendChannel, + } + s.session.State = latentState{} + s.session.InitiateLogon = true + + if doRefresh { + s.MockStore.On("Refresh").Return(nil) + } + s.MockApp.On("ToAdmin") + s.session.onAdmin(adminMsg) + + s.MockStore.AssertExpectations(s.T()) + } +} + +func (s *SessionSuite) TestOnAdminConnectAccept() { + adminMsg := connect{ + messageOut: s.Receiver.sendChannel, + } + s.session.State = latentState{} + s.IncrNextSenderMsgSeqNum() + + s.session.onAdmin(adminMsg) + s.False(s.session.InitiateLogon) + s.State(logonState{}) + s.NoMessageSent() + s.NextSenderMsgSeqNum(2) +} + +func (s *SessionSuite) TestOnAdminConnectNotInSession() { + var tests = []bool{true, false} + + for _, doInitiateLogon := range tests { + s.SetupTest() + s.session.State = notSessionTime{} + s.IncrNextSenderMsgSeqNum() + s.session.InitiateLogon = doInitiateLogon + + adminMsg := connect{ + messageOut: s.Receiver.sendChannel, + } + + s.session.onAdmin(adminMsg) + + s.State(notSessionTime{}) + s.NoMessageSent() + s.Disconnected() + s.NextSenderMsgSeqNum(2) + } +} + +func (s *SessionSuite) TestOnAdminStop() { + s.session.State = logonState{} + + s.session.onAdmin(stopReq{}) + s.Disconnected() + s.Stopped() +} + +func (s *SessionSuite) TestResetOnDisconnect() { + s.IncrNextSenderMsgSeqNum() + s.IncrNextTargetMsgSeqNum() + + s.session.ResetOnDisconnect = false + s.session.onDisconnect() + s.NextSenderMsgSeqNum(2) + s.NextTargetMsgSeqNum(2) + + s.session.ResetOnDisconnect = true + s.session.onDisconnect() + s.ExpectStoreReset() +} + +type SessionSendTestSuite struct { + SessionSuiteRig +} + +func TestSessionSendTestSuite(t *testing.T) { + suite.Run(t, new(SessionSendTestSuite)) +} + +func (suite *SessionSendTestSuite) SetupTest() { + suite.Init() + suite.session.State = inSession{} +} + +func (suite *SessionSendTestSuite) TestQueueForSendAppMessage() { + suite.MockApp.On("ToApp").Return(nil) + require.Nil(suite.T(), suite.queueForSend(suite.NewOrderSingle())) + + suite.MockApp.AssertExpectations(suite.T()) + suite.NoMessageSent() + suite.MessagePersisted(suite.MockApp.lastToApp) + suite.FieldEquals(tagMsgSeqNum, 1, suite.MockApp.lastToApp.Header) + suite.NextSenderMsgSeqNum(2) +} + +func (suite *SessionSendTestSuite) TestQueueForSendDoNotSendAppMessage() { + suite.MockApp.On("ToApp").Return(ErrDoNotSend) + suite.Equal(ErrDoNotSend, suite.queueForSend(suite.NewOrderSingle())) + + suite.MockApp.AssertExpectations(suite.T()) + suite.NoMessagePersisted(1) + suite.NoMessageSent() + suite.NextSenderMsgSeqNum(1) + + suite.MockApp.On("ToAdmin") + require.Nil(suite.T(), suite.send(suite.Heartbeat())) + + suite.MockApp.AssertExpectations(suite.T()) + suite.LastToAdminMessageSent() + suite.MessagePersisted(suite.MockApp.lastToAdmin) + suite.NextSenderMsgSeqNum(2) +} + +func (suite *SessionSendTestSuite) TestQueueForSendAdminMessage() { + suite.MockApp.On("ToAdmin") + require.Nil(suite.T(), suite.queueForSend(suite.Heartbeat())) + + suite.MockApp.AssertExpectations(suite.T()) + suite.MessagePersisted(suite.MockApp.lastToAdmin) + suite.NoMessageSent() + suite.NextSenderMsgSeqNum(2) +} + +func (suite *SessionSendTestSuite) TestSendAppMessage() { + suite.MockApp.On("ToApp").Return(nil) + require.Nil(suite.T(), suite.send(suite.NewOrderSingle())) + + suite.MockApp.AssertExpectations(suite.T()) + suite.MessagePersisted(suite.MockApp.lastToApp) + suite.LastToAppMessageSent() + suite.NextSenderMsgSeqNum(2) +} + +func (suite *SessionSendTestSuite) TestSendAppDoNotSendMessage() { + suite.MockApp.On("ToApp").Return(ErrDoNotSend) + suite.Equal(ErrDoNotSend, suite.send(suite.NewOrderSingle())) + + suite.MockApp.AssertExpectations(suite.T()) + suite.NextSenderMsgSeqNum(1) + suite.NoMessageSent() +} + +func (suite *SessionSendTestSuite) TestSendAdminMessage() { + suite.MockApp.On("ToAdmin") + require.Nil(suite.T(), suite.send(suite.Heartbeat())) + suite.MockApp.AssertExpectations(suite.T()) + + suite.LastToAdminMessageSent() + suite.MessagePersisted(suite.MockApp.lastToAdmin) +} + +func (suite *SessionSendTestSuite) TestSendFlushesQueue() { + suite.MockApp.On("ToApp").Return(nil) + suite.MockApp.On("ToAdmin") + require.Nil(suite.T(), suite.queueForSend(suite.NewOrderSingle())) + require.Nil(suite.T(), suite.queueForSend(suite.Heartbeat())) + + order1 := suite.MockApp.lastToApp + heartbeat := suite.MockApp.lastToAdmin + + suite.MockApp.AssertExpectations(suite.T()) + suite.NoMessageSent() + + suite.MockApp.On("ToApp").Return(nil) + require.Nil(suite.T(), suite.send(suite.NewOrderSingle())) + suite.MockApp.AssertExpectations(suite.T()) + order2 := suite.MockApp.lastToApp + suite.MessageSentEquals(order1) + suite.MessageSentEquals(heartbeat) + suite.MessageSentEquals(order2) + suite.NoMessageSent() +} + +func (suite *SessionSendTestSuite) TestSendNotLoggedOn() { + suite.MockApp.On("ToApp").Return(nil) + suite.MockApp.On("ToAdmin") + require.Nil(suite.T(), suite.queueForSend(suite.NewOrderSingle())) + require.Nil(suite.T(), suite.queueForSend(suite.Heartbeat())) + + suite.MockApp.AssertExpectations(suite.T()) + suite.NoMessageSent() + + var tests = []sessionState{logoutState{}, latentState{}, logonState{}} + + for _, test := range tests { + suite.MockApp.On("ToApp").Return(nil) + suite.session.State = test + require.Nil(suite.T(), suite.send(suite.NewOrderSingle())) + suite.MockApp.AssertExpectations(suite.T()) + suite.NoMessageSent() + } +} + +func (suite *SessionSendTestSuite) TestSendEnableLastMsgSeqNumProcessed() { + suite.session.State = inSession{} + suite.session.EnableLastMsgSeqNumProcessed = true + + suite.Require().Nil(suite.session.store.SetNextTargetMsgSeqNum(45)) + + suite.MockApp.On("ToApp").Return(nil) + require.Nil(suite.T(), suite.send(suite.NewOrderSingle())) + suite.MockApp.AssertExpectations(suite.T()) + suite.LastToAppMessageSent() + + suite.FieldEquals(tagLastMsgSeqNumProcessed, 44, suite.MockApp.lastToApp.Header) +} + +func (suite *SessionSendTestSuite) TestSendDisableMessagePersist() { + suite.session.State = inSession{} + suite.session.DisableMessagePersist = true + + suite.MockApp.On("ToApp").Return(nil) + require.Nil(suite.T(), suite.send(suite.NewOrderSingle())) + suite.MockApp.AssertExpectations(suite.T()) + suite.LastToAppMessageSent() + suite.NoMessagePersisted(1) + suite.NextSenderMsgSeqNum(2) +} + +func (suite *SessionSendTestSuite) TestDropAndSendAdminMessage() { + suite.MockApp.On("ToAdmin") + suite.Require().Nil(suite.dropAndSend(suite.Heartbeat(), false)) + suite.MockApp.AssertExpectations(suite.T()) + + suite.MessagePersisted(suite.MockApp.lastToAdmin) + suite.LastToAdminMessageSent() +} + +func (suite *SessionSendTestSuite) TestDropAndSendDropsQueue() { + suite.MockApp.On("ToApp").Return(nil) + suite.MockApp.On("ToAdmin") + require.Nil(suite.T(), suite.queueForSend(suite.NewOrderSingle())) + require.Nil(suite.T(), suite.queueForSend(suite.Heartbeat())) + suite.MockApp.AssertExpectations(suite.T()) + + suite.NoMessageSent() + + suite.MockApp.On("ToAdmin") + require.Nil(suite.T(), suite.dropAndSend(suite.Logon(), false)) + suite.MockApp.AssertExpectations(suite.T()) + + msg := suite.MockApp.lastToAdmin + suite.MessageType(string(msgTypeLogon), msg) + suite.FieldEquals(tagMsgSeqNum, 3, msg.Header) + + //only one message sent + suite.LastToAdminMessageSent() + suite.NoMessageSent() +} + +func (suite *SessionSendTestSuite) TestDropAndSendDropsQueueWithReset() { + suite.MockApp.On("ToApp").Return(nil) + suite.MockApp.On("ToAdmin") + require.Nil(suite.T(), suite.queueForSend(suite.NewOrderSingle())) + require.Nil(suite.T(), suite.queueForSend(suite.Heartbeat())) + suite.MockApp.AssertExpectations(suite.T()) + suite.NoMessageSent() + + suite.MockApp.On("ToAdmin") + require.Nil(suite.T(), suite.dropAndSend(suite.Logon(), true)) + suite.MockApp.AssertExpectations(suite.T()) + msg := suite.MockApp.lastToAdmin + + suite.MessageType(string(msgTypeLogon), msg) + suite.FieldEquals(tagMsgSeqNum, 1, msg.Header) + + //only one message sent + suite.LastToAdminMessageSent() + suite.NoMessageSent() +} diff --git a/vendor/github.com/quickfixgo/quickfix/settings.go b/vendor/github.com/quickfixgo/quickfix/settings.go index 97c9353..870cf3d 100644 --- a/vendor/github.com/quickfixgo/quickfix/settings.go +++ b/vendor/github.com/quickfixgo/quickfix/settings.go @@ -2,6 +2,7 @@ package quickfix import ( "bufio" + "errors" "fmt" "io" "regexp" @@ -46,10 +47,26 @@ func sessionIDFromSessionSettings(globalSettings *SessionSettings, sessionSettin sessionID.TargetCompID, _ = settings.Setting(config.TargetCompID) } + if settings.HasSetting(config.TargetSubID) { + sessionID.TargetSubID, _ = settings.Setting(config.TargetSubID) + } + + if settings.HasSetting(config.TargetLocationID) { + sessionID.TargetLocationID, _ = settings.Setting(config.TargetLocationID) + } + if settings.HasSetting(config.SenderCompID) { sessionID.SenderCompID, _ = settings.Setting(config.SenderCompID) } + if settings.HasSetting(config.SenderSubID) { + sessionID.SenderSubID, _ = settings.Setting(config.SenderSubID) + } + + if settings.HasSetting(config.SenderLocationID) { + sessionID.SenderLocationID, _ = settings.Setting(config.SenderLocationID) + } + if settings.HasSetting(config.SessionQualifier) { sessionID.Qualifier, _ = settings.Setting(config.SessionQualifier) } @@ -137,6 +154,18 @@ func (s *Settings) AddSession(sessionSettings *SessionSettings) (SessionID, erro s.lazyInit() sessionID := sessionIDFromSessionSettings(s.GlobalSettings(), sessionSettings) + + switch sessionID.BeginString { + case BeginStringFIX40: + case BeginStringFIX41: + case BeginStringFIX42: + case BeginStringFIX43: + case BeginStringFIX44: + case BeginStringFIXT11: + default: + return sessionID, errors.New("BeginString must be FIX.4.0 to FIX.4.4 or FIXT.1.1") + } + if _, dup := s.sessionSettings[sessionID]; dup { return sessionID, fmt.Errorf("duplicate session configured for %v", sessionID) } diff --git a/vendor/github.com/quickfixgo/quickfix/settings_test.go b/vendor/github.com/quickfixgo/quickfix/settings_test.go new file mode 100644 index 0000000..b9c2197 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/settings_test.go @@ -0,0 +1,373 @@ +package quickfix + +import ( + "strings" + "testing" + + "github.com/quickfixgo/quickfix/config" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +func TestSettings_New(t *testing.T) { + s := NewSettings() + assert.NotNil(t, s) + + globalSettings := s.GlobalSettings() + assert.NotNil(t, globalSettings) + + sessionSettings := s.SessionSettings() + assert.NotNil(t, sessionSettings) + assert.Empty(t, sessionSettings) +} + +type SettingsAddSessionSuite struct { + suite.Suite + settings *Settings +} + +func TestSettingsAddSessionSuite(t *testing.T) { + suite.Run(t, new(SettingsAddSessionSuite)) +} + +func (s *SettingsAddSessionSuite) SetupTest() { + s.settings = NewSettings() +} + +func (s *SettingsAddSessionSuite) TestBeginStringValidation() { + ss := NewSessionSettings() + ss.Set(config.SenderCompID, "CB") + ss.Set(config.TargetCompID, "SS") + + _, err := s.settings.AddSession(ss) + s.NotNil(err) + + ss.Set(config.BeginString, "NotAValidBeginString") + _, err = s.settings.AddSession(ss) + s.NotNil(err) + + var cases = []string{ + BeginStringFIX40, + BeginStringFIX41, + BeginStringFIX42, + BeginStringFIX43, + BeginStringFIX44, + BeginStringFIXT11, + } + + for _, beginString := range cases { + ss.Set(config.BeginString, beginString) + sid, err := s.settings.AddSession(ss) + s.Nil(err) + s.Equal(sid, SessionID{BeginString: beginString, SenderCompID: "CB", TargetCompID: "SS"}) + } +} + +func (s *SettingsAddSessionSuite) TestGlobalOverlay() { + globalSettings := s.settings.GlobalSettings() + globalSettings.Set(config.BeginString, "FIX.4.0") + globalSettings.Set(config.SocketAcceptPort, "1000") + + s1 := NewSessionSettings() + s1.Set(config.BeginString, "FIX.4.1") + s1.Set(config.SenderCompID, "CB") + s1.Set(config.TargetCompID, "SS") + + s2 := NewSessionSettings() + s2.Set(config.ResetOnLogon, "Y") + s2.Set(config.SenderCompID, "CB") + s2.Set(config.TargetCompID, "SS") + + sessionID1 := SessionID{BeginString: "FIX.4.1", SenderCompID: "CB", TargetCompID: "SS"} + sessionID2 := SessionID{BeginString: "FIX.4.0", SenderCompID: "CB", TargetCompID: "SS"} + + var addCases = []struct { + settings *SessionSettings + expectedSessionID SessionID + }{ + {s1, sessionID1}, + {s2, sessionID2}, + } + + for _, tc := range addCases { + sid, err := s.settings.AddSession(tc.settings) + s.Nil(err) + s.Equal(sid, tc.expectedSessionID) + } + + var cases = []struct { + sessionID SessionID + input string + expected string + }{ + {sessionID1, config.BeginString, "FIX.4.1"}, + {sessionID1, config.SocketAcceptPort, "1000"}, + {sessionID2, config.BeginString, "FIX.4.0"}, + {sessionID2, config.SocketAcceptPort, "1000"}, + {sessionID2, config.ResetOnLogon, "Y"}, + } + + sessionSettings := s.settings.SessionSettings() + s.Len(sessionSettings, 2) + for _, tc := range cases { + settings := sessionSettings[tc.sessionID] + + actual, err := settings.Setting(tc.input) + s.Nil(err) + s.Equal(actual, tc.expected) + } +} + +func (s *SettingsAddSessionSuite) TestRejectDuplicate() { + s1 := NewSessionSettings() + s1.Set(config.BeginString, "FIX.4.1") + s1.Set(config.SenderCompID, "CB") + s1.Set(config.TargetCompID, "SS") + + s2 := NewSessionSettings() + s2.Set(config.BeginString, "FIX.4.0") + s2.Set(config.SenderCompID, "CB") + s2.Set(config.TargetCompID, "SS") + + _, err := s.settings.AddSession(s1) + s.Nil(err) + _, err = s.settings.AddSession(s2) + s.Nil(err) + + s3 := NewSessionSettings() + s1.Set(config.BeginString, "FIX.4.0") + s3.Set(config.SenderCompID, "CB") + s3.Set(config.TargetCompID, "SS") + _, err = s.settings.AddSession(s3) + s.NotNil(err, "Expected error for adding duplicate session") + + sessionSettings := s.settings.SessionSettings() + s.Len(sessionSettings, 2) +} + +func TestSettings_ParseSettings(t *testing.T) { + cfg := ` +# default settings for sessions +[DEFAULT] +ConnectionType=initiator +ReconnectInterval=60 +SenderCompID=TW + + +# session definition +[SESSION] +# inherit ConnectionType, ReconnectInterval and SenderCompID from default + +BeginString=FIX.4.1 +TargetCompID=ARCA +StartTime=12:30:00 +EndTime=23:30:00 +HeartBtInt=20 +SocketConnectPort=9823 +SocketConnectHost=123.123.123.123 +DataDictionary=somewhere/FIX41.xml + + +[SESSION] +BeginString=FIX.4.0 +TargetCompID=ISLD +StartTime=12:00:00 +EndTime=23:00:00 +HeartBtInt=30 +SocketConnectPort=8323 +SocketConnectHost=23.23.23.23 +DataDictionary=somewhere/FIX40.xml + + +[SESSION] +BeginString=FIX.4.2 +SenderSubID=TWSub +SenderLocationID=TWLoc +TargetCompID=INCA +TargetSubID=INCASub +TargetLocationID=INCALoc +StartTime=12:30:00 +EndTime=21:30:00 +# overide default setting for RecconnectInterval +ReconnectInterval=30 +HeartBtInt=30 +SocketConnectPort=6523 +SocketConnectHost=3.3.3.3 +# (optional) alternate connection ports and hosts to cycle through on failover +SocketConnectPort1=8392 +SocketConnectHost1=8.8.8.8 +SocketConnectPort2=2932 +SocketConnectHost2=12.12.12.12 +DataDictionary=somewhere/FIX42.xml +` + + stringReader := strings.NewReader(cfg) + s, err := ParseSettings(stringReader) + assert.Nil(t, err) + assert.NotNil(t, s) + + var globalTCs = []struct { + setting string + expected string + }{ + {"ConnectionType", "initiator"}, + {"ReconnectInterval", "60"}, + {"SenderCompID", "TW"}, + } + + globalSettings := s.GlobalSettings() + for _, tc := range globalTCs { + actual, err := globalSettings.Setting(tc.setting) + assert.Nil(t, err) + + assert.Equal(t, tc.expected, actual) + } + + sessionSettings := s.SessionSettings() + assert.Len(t, sessionSettings, 3) + + sessionID1 := SessionID{BeginString: "FIX.4.1", SenderCompID: "TW", TargetCompID: "ARCA"} + sessionID2 := SessionID{BeginString: "FIX.4.0", SenderCompID: "TW", TargetCompID: "ISLD"} + sessionID3 := SessionID{ + BeginString: "FIX.4.2", + SenderCompID: "TW", SenderSubID: "TWSub", SenderLocationID: "TWLoc", + TargetCompID: "INCA", TargetSubID: "INCASub", TargetLocationID: "INCALoc"} + + var sessionTCs = []struct { + sessionID SessionID + setting string + expected string + }{ + {sessionID1, "ConnectionType", "initiator"}, + {sessionID1, "ReconnectInterval", "60"}, + {sessionID1, "SenderCompID", "TW"}, + {sessionID1, "BeginString", "FIX.4.1"}, + {sessionID1, "TargetCompID", "ARCA"}, + {sessionID1, "StartTime", "12:30:00"}, + {sessionID1, "EndTime", "23:30:00"}, + {sessionID1, "HeartBtInt", "20"}, + {sessionID1, "SocketConnectPort", "9823"}, + {sessionID1, "SocketConnectHost", "123.123.123.123"}, + {sessionID1, "DataDictionary", "somewhere/FIX41.xml"}, + + {sessionID2, "ConnectionType", "initiator"}, + {sessionID2, "ReconnectInterval", "60"}, + {sessionID2, "SenderCompID", "TW"}, + {sessionID2, "BeginString", "FIX.4.0"}, + {sessionID2, "TargetCompID", "ISLD"}, + {sessionID2, "StartTime", "12:00:00"}, + {sessionID2, "EndTime", "23:00:00"}, + {sessionID2, "HeartBtInt", "30"}, + {sessionID2, "SocketConnectPort", "8323"}, + {sessionID2, "SocketConnectHost", "23.23.23.23"}, + {sessionID2, "DataDictionary", "somewhere/FIX40.xml"}, + + {sessionID3, "ConnectionType", "initiator"}, + {sessionID3, "BeginString", "FIX.4.2"}, + {sessionID3, "SenderCompID", "TW"}, + {sessionID3, "TargetCompID", "INCA"}, + {sessionID3, "StartTime", "12:30:00"}, + {sessionID3, "EndTime", "21:30:00"}, + {sessionID3, "ReconnectInterval", "30"}, + {sessionID3, "HeartBtInt", "30"}, + {sessionID3, "SocketConnectPort", "6523"}, + {sessionID3, "SocketConnectHost", "3.3.3.3"}, + {sessionID3, "SocketConnectPort1", "8392"}, + {sessionID3, "SocketConnectHost1", "8.8.8.8"}, + {sessionID3, "SocketConnectPort2", "2932"}, + {sessionID3, "SocketConnectHost2", "12.12.12.12"}, + {sessionID3, "DataDictionary", "somewhere/FIX42.xml"}, + } + + for _, tc := range sessionTCs { + settings, ok := sessionSettings[tc.sessionID] + require.True(t, ok, "No Session recalled for %v", tc.sessionID) + actual, err := settings.Setting(tc.setting) + + assert.Nil(t, err) + assert.Equal(t, tc.expected, actual) + } +} + +func TestSettings_ParseSettings_WithEqualsSignInValue(t *testing.T) { + s, err := ParseSettings(strings.NewReader(` +[DEFAULT] +ConnectionType=initiator +SQLDriver=mysql +SQLDataSourceName=root:root@/quickfix?parseTime=true&loc=UTC + +[SESSION] +BeginString=FIX.4.2 +SenderCompID=SENDER +TargetCompID=TARGET`)) + + require.Nil(t, err) + require.NotNil(t, s) + + sessionSettings := s.SessionSettings()[SessionID{BeginString: "FIX.4.2", SenderCompID: "SENDER", TargetCompID: "TARGET"}] + val, err := sessionSettings.Setting("SQLDataSourceName") + assert.Nil(t, err) + assert.Equal(t, `root:root@/quickfix?parseTime=true&loc=UTC`, val) +} + +func TestSettings_SessionIDFromSessionSettings(t *testing.T) { + var testCases = []struct { + globalBeginString string + globalTargetCompID string + globalSenderCompID string + sessionBeginString string + sessionTargetCompID string + sessionSenderCompID string + sessionQualifier string + expectedSessionID SessionID + }{ + {globalBeginString: "FIX.4.0", globalTargetCompID: "CB", globalSenderCompID: "SS", + expectedSessionID: SessionID{BeginString: "FIX.4.0", TargetCompID: "CB", SenderCompID: "SS"}}, + + {sessionBeginString: "FIX.4.1", sessionTargetCompID: "GE", sessionSenderCompID: "LE", + expectedSessionID: SessionID{BeginString: "FIX.4.1", TargetCompID: "GE", SenderCompID: "LE"}}, + + {globalBeginString: "FIX.4.2", globalTargetCompID: "CB", sessionTargetCompID: "GE", sessionSenderCompID: "LE", sessionQualifier: "J", + expectedSessionID: SessionID{BeginString: "FIX.4.2", TargetCompID: "GE", SenderCompID: "LE", Qualifier: "J"}}, + } + + for _, tc := range testCases { + globalSettings := NewSessionSettings() + sessionSettings := NewSessionSettings() + + if tc.globalBeginString != "" { + globalSettings.Set(config.BeginString, tc.globalBeginString) + } + + if tc.sessionBeginString != "" { + sessionSettings.Set(config.BeginString, tc.sessionBeginString) + } + + if tc.globalTargetCompID != "" { + globalSettings.Set(config.TargetCompID, tc.globalTargetCompID) + } + + if tc.sessionTargetCompID != "" { + sessionSettings.Set(config.TargetCompID, tc.sessionTargetCompID) + } + + if tc.globalSenderCompID != "" { + globalSettings.Set(config.SenderCompID, tc.globalSenderCompID) + } + + if tc.sessionSenderCompID != "" { + sessionSettings.Set(config.SenderCompID, tc.sessionSenderCompID) + } + + if len(tc.sessionQualifier) > 0 { + sessionSettings.Set(config.SessionQualifier, tc.sessionQualifier) + } + + actualSessionID := sessionIDFromSessionSettings(globalSettings, sessionSettings) + + if tc.expectedSessionID != actualSessionID { + t.Errorf("Expected %v, got %v", tc.expectedSessionID, actualSessionID) + } + } +} diff --git a/vendor/github.com/quickfixgo/quickfix/sqlstore_test.go b/vendor/github.com/quickfixgo/quickfix/sqlstore_test.go new file mode 100644 index 0000000..b252b2c --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/sqlstore_test.go @@ -0,0 +1,70 @@ +package quickfix + +import ( + "database/sql" + "fmt" + "io/ioutil" + "os" + "path" + "path/filepath" + "strings" + "testing" + "time" + + _ "github.com/mattn/go-sqlite3" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +// SqlStoreTestSuite runs all tests in the MessageStoreTestSuite against the SqlStore implementation +type SQLStoreTestSuite struct { + MessageStoreTestSuite + sqlStoreRootPath string +} + +func (suite *SQLStoreTestSuite) SetupTest() { + suite.sqlStoreRootPath = path.Join(os.TempDir(), fmt.Sprintf("SqlStoreTestSuite-%d", os.Getpid())) + err := os.MkdirAll(suite.sqlStoreRootPath, os.ModePerm) + require.Nil(suite.T(), err) + sqlDriver := "sqlite3" + sqlDsn := path.Join(suite.sqlStoreRootPath, fmt.Sprintf("%d.db", time.Now().UnixNano())) + + // create tables + db, err := sql.Open(sqlDriver, sqlDsn) + require.Nil(suite.T(), err) + ddlFnames, err := filepath.Glob(fmt.Sprintf("_sql/%s/*.sql", sqlDriver)) + require.Nil(suite.T(), err) + for _, fname := range ddlFnames { + sqlBytes, err := ioutil.ReadFile(fname) + require.Nil(suite.T(), err) + _, err = db.Exec(string(sqlBytes)) + require.Nil(suite.T(), err) + } + + // create settings + sessionID := SessionID{BeginString: "FIX.4.4", SenderCompID: "SENDER", TargetCompID: "TARGET"} + settings, err := ParseSettings(strings.NewReader(fmt.Sprintf(` +[DEFAULT] +SQLStoreDriver=%s +SQLStoreDataSourceName=%s +SQLStoreConnMaxLifetime=14400s + +[SESSION] +BeginString=%s +SenderCompID=%s +TargetCompID=%s`, sqlDriver, sqlDsn, sessionID.BeginString, sessionID.SenderCompID, sessionID.TargetCompID))) + require.Nil(suite.T(), err) + + // create store + suite.msgStore, err = NewSQLStoreFactory(settings).Create(sessionID) + require.Nil(suite.T(), err) +} + +func (suite *SQLStoreTestSuite) TearDownTest() { + suite.msgStore.Close() + os.RemoveAll(suite.sqlStoreRootPath) +} + +func TestSqlStoreTestSuite(t *testing.T) { + suite.Run(t, new(SQLStoreTestSuite)) +} diff --git a/vendor/github.com/quickfixgo/quickfix/store_test.go b/vendor/github.com/quickfixgo/quickfix/store_test.go new file mode 100644 index 0000000..a61ccbb --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/store_test.go @@ -0,0 +1,174 @@ +package quickfix + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +// MessageStoreTestSuite is the suite of all tests that should be run against all MessageStore implementations +type MessageStoreTestSuite struct { + suite.Suite + msgStore MessageStore +} + +// MemoryStoreTestSuite runs all tests in the MessageStoreTestSuite against the MemoryStore implementation +type MemoryStoreTestSuite struct { + MessageStoreTestSuite +} + +func (suite *MemoryStoreTestSuite) SetupTest() { + var err error + suite.msgStore, err = NewMemoryStoreFactory().Create(SessionID{}) + require.Nil(suite.T(), err) +} + +func TestMemoryStoreTestSuite(t *testing.T) { + suite.Run(t, new(MemoryStoreTestSuite)) +} + +func (suite *MessageStoreTestSuite) TestMessageStore_SetNextMsgSeqNum_Refresh_IncrNextMsgSeqNum() { + t := suite.T() + + // Given a MessageStore with the following sender and target seqnums + suite.msgStore.SetNextSenderMsgSeqNum(867) + suite.msgStore.SetNextTargetMsgSeqNum(5309) + + // When the store is refreshed from its backing store + suite.msgStore.Refresh() + + // Then the sender and target seqnums should still be + assert.Equal(t, 867, suite.msgStore.NextSenderMsgSeqNum()) + assert.Equal(t, 5309, suite.msgStore.NextTargetMsgSeqNum()) + + // When the sender and target seqnums are incremented + require.Nil(t, suite.msgStore.IncrNextSenderMsgSeqNum()) + require.Nil(t, suite.msgStore.IncrNextTargetMsgSeqNum()) + + // Then the sender and target seqnums should be + assert.Equal(t, 868, suite.msgStore.NextSenderMsgSeqNum()) + assert.Equal(t, 5310, suite.msgStore.NextTargetMsgSeqNum()) + + // When the store is refreshed from its backing store + suite.msgStore.Refresh() + + // Then the sender and target seqnums should still be + assert.Equal(t, 868, suite.msgStore.NextSenderMsgSeqNum()) + assert.Equal(t, 5310, suite.msgStore.NextTargetMsgSeqNum()) +} + +func (suite *MessageStoreTestSuite) TestMessageStore_Reset() { + t := suite.T() + + // Given a MessageStore with the following sender and target seqnums + suite.msgStore.SetNextSenderMsgSeqNum(1234) + suite.msgStore.SetNextTargetMsgSeqNum(5678) + + // When the store is reset + require.Nil(t, suite.msgStore.Reset()) + + // Then the sender and target seqnums should be + assert.Equal(t, 1, suite.msgStore.NextSenderMsgSeqNum()) + assert.Equal(t, 1, suite.msgStore.NextTargetMsgSeqNum()) + + // When the store is refreshed from its backing store + suite.msgStore.Refresh() + + // Then the sender and target seqnums should still be + assert.Equal(t, 1, suite.msgStore.NextSenderMsgSeqNum()) + assert.Equal(t, 1, suite.msgStore.NextTargetMsgSeqNum()) +} + +func (suite *MessageStoreTestSuite) TestMessageStore_SaveMessage_GetMessage() { + t := suite.T() + + // Given the following saved messages + expectedMsgsBySeqNum := map[int]string{ + 1: "In the frozen land of Nador", + 2: "they were forced to eat Robin's minstrels", + 3: "and there was much rejoicing", + } + for seqNum, msg := range expectedMsgsBySeqNum { + require.Nil(t, suite.msgStore.SaveMessage(seqNum, []byte(msg))) + } + + // When the messages are retrieved from the MessageStore + actualMsgs, err := suite.msgStore.GetMessages(1, 3) + require.Nil(t, err) + + // Then the messages should be + require.Len(t, actualMsgs, 3) + assert.Equal(t, expectedMsgsBySeqNum[1], string(actualMsgs[0])) + assert.Equal(t, expectedMsgsBySeqNum[2], string(actualMsgs[1])) + assert.Equal(t, expectedMsgsBySeqNum[3], string(actualMsgs[2])) + + // When the store is refreshed from its backing store + suite.msgStore.Refresh() + + // And the messages are retrieved from the MessageStore + actualMsgs, err = suite.msgStore.GetMessages(1, 3) + require.Nil(t, err) + + // Then the messages should still be + require.Len(t, actualMsgs, 3) + assert.Equal(t, expectedMsgsBySeqNum[1], string(actualMsgs[0])) + assert.Equal(t, expectedMsgsBySeqNum[2], string(actualMsgs[1])) + assert.Equal(t, expectedMsgsBySeqNum[3], string(actualMsgs[2])) +} + +func (suite *MessageStoreTestSuite) TestMessageStore_GetMessages_EmptyStore() { + // When messages are retrieved from an empty store + messages, err := suite.msgStore.GetMessages(1, 2) + require.Nil(suite.T(), err) + + // Then no messages should be returned + require.Empty(suite.T(), messages, "Did not expect messages from empty store") +} + +func (suite *MessageStoreTestSuite) TestMessageStore_GetMessages_VariousRanges() { + t := suite.T() + + // Given the following saved messages + require.Nil(t, suite.msgStore.SaveMessage(1, []byte("hello"))) + require.Nil(t, suite.msgStore.SaveMessage(2, []byte("cruel"))) + require.Nil(t, suite.msgStore.SaveMessage(3, []byte("world"))) + + // When the following requests are made to the store + var testCases = []struct { + beginSeqNo, endSeqNo int + expectedBytes [][]byte + }{ + {beginSeqNo: 1, endSeqNo: 1, expectedBytes: [][]byte{[]byte("hello")}}, + {beginSeqNo: 1, endSeqNo: 2, expectedBytes: [][]byte{[]byte("hello"), []byte("cruel")}}, + {beginSeqNo: 1, endSeqNo: 3, expectedBytes: [][]byte{[]byte("hello"), []byte("cruel"), []byte("world")}}, + {beginSeqNo: 1, endSeqNo: 4, expectedBytes: [][]byte{[]byte("hello"), []byte("cruel"), []byte("world")}}, + {beginSeqNo: 2, endSeqNo: 3, expectedBytes: [][]byte{[]byte("cruel"), []byte("world")}}, + {beginSeqNo: 3, endSeqNo: 3, expectedBytes: [][]byte{[]byte("world")}}, + {beginSeqNo: 3, endSeqNo: 4, expectedBytes: [][]byte{[]byte("world")}}, + {beginSeqNo: 4, endSeqNo: 4, expectedBytes: [][]byte{}}, + {beginSeqNo: 4, endSeqNo: 10, expectedBytes: [][]byte{}}, + } + + // Then the returned messages should be + for _, tc := range testCases { + actualMsgs, err := suite.msgStore.GetMessages(tc.beginSeqNo, tc.endSeqNo) + require.Nil(t, err) + require.Len(t, actualMsgs, len(tc.expectedBytes)) + for i, expectedMsg := range tc.expectedBytes { + assert.Equal(t, string(expectedMsg), string(actualMsgs[i])) + } + } +} + +func (suite *MessageStoreTestSuite) TestMessageStore_CreationTime() { + assert.False(suite.T(), suite.msgStore.CreationTime().IsZero()) + + t0 := time.Now() + suite.msgStore.Reset() + t1 := time.Now() + require.True(suite.T(), suite.msgStore.CreationTime().After(t0)) + require.True(suite.T(), suite.msgStore.CreationTime().Before(t1)) +} diff --git a/vendor/github.com/quickfixgo/quickfix/tag_value.go b/vendor/github.com/quickfixgo/quickfix/tag_value.go index 3234168..762ea23 100644 --- a/vendor/github.com/quickfixgo/quickfix/tag_value.go +++ b/vendor/github.com/quickfixgo/quickfix/tag_value.go @@ -13,41 +13,37 @@ type TagValue struct { bytes []byte } -//TagValues is a slice of TagValue -type TagValues []TagValue - func (tv *TagValue) init(tag Tag, value []byte) { - var buf bytes.Buffer - buf.WriteString(strconv.Itoa(int(tag))) - buf.WriteString("=") - buf.Write(value) - buf.WriteString("") + tv.bytes = strconv.AppendInt(nil, int64(tag), 10) + tv.bytes = append(tv.bytes, []byte("=")...) + tv.bytes = append(tv.bytes, value...) + tv.bytes = append(tv.bytes, []byte("")...) tv.tag = tag - tv.bytes = buf.Bytes() tv.value = value } -func (tv *TagValue) parse(rawFieldBytes []byte) (err error) { +func (tv *TagValue) parse(rawFieldBytes []byte) error { sepIndex := bytes.IndexByte(rawFieldBytes, '=') - if sepIndex == -1 { - err = fmt.Errorf("tagValue.Parse: No '=' in '%s'", rawFieldBytes) - return + switch sepIndex { + case -1: + return fmt.Errorf("tagValue.Parse: No '=' in '%s'", rawFieldBytes) + case 0: + return fmt.Errorf("tagValue.Parse: No tag in '%s'", rawFieldBytes) } parsedTag, err := atoi(rawFieldBytes[:sepIndex]) - if err != nil { - err = fmt.Errorf("tagValue.Parse: %s", err.Error()) - return + return fmt.Errorf("tagValue.Parse: %s", err.Error()) } tv.tag = Tag(parsedTag) - tv.value = rawFieldBytes[(sepIndex + 1):(len(rawFieldBytes) - 1)] - tv.bytes = rawFieldBytes + n := len(rawFieldBytes) + tv.value = rawFieldBytes[(sepIndex + 1):(n - 1):(n - 1)] + tv.bytes = rawFieldBytes[:n:n] - return + return nil } func (tv TagValue) String() string { diff --git a/vendor/github.com/quickfixgo/quickfix/tag_value_test.go b/vendor/github.com/quickfixgo/quickfix/tag_value_test.go new file mode 100644 index 0000000..48883ed --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/tag_value_test.go @@ -0,0 +1,74 @@ +package quickfix + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestTagValue_init(t *testing.T) { + var tv TagValue + tv.init(Tag(8), []byte("blahblah")) + + expectedData := []byte("8=blahblah") + if !bytes.Equal(tv.bytes, expectedData) { + t.Errorf("Expected %v, got %v", expectedData, tv.bytes) + } + expectedValue := []byte("blahblah") + if !bytes.Equal(tv.value, expectedValue) { + t.Errorf("Expected %v, got %v", expectedValue, tv.value) + } +} + +func TestTagValue_parse(t *testing.T) { + stringField := "8=FIX.4.0" + tv := TagValue{} + err := tv.parse([]byte(stringField)) + assert.Nil(t, err) + assert.Equal(t, Tag(8), tv.tag) + + if !bytes.Equal(tv.bytes, []byte(stringField)) { + t.Errorf("Expected %v got %v", stringField, tv.bytes) + } + + if !bytes.Equal(tv.value, []byte("FIX.4.0")) { + t.Error("Unxpected value", tv.value) + } +} + +func TestTagValue_parseFail(t *testing.T) { + stringField := "not_tag_equal_value" + var tv TagValue + + assert.NotNil(t, tv.parse([]byte(stringField))) + + stringField = "tag_not_an_int=uhoh" + assert.NotNil(t, tv.parse([]byte(stringField))) + + stringField = "=notag" + assert.NotNil(t, tv.parse([]byte(stringField))) +} + +func TestTagValue_String(t *testing.T) { + stringField := "8=FIX.4.0" + var tv TagValue + + require.Nil(t, tv.parse([]byte(stringField))) + assert.Equal(t, "8=FIX.4.0", tv.String()) +} + +func TestTagValue_length(t *testing.T) { + stringField := "8=FIX.4.0" + var tv TagValue + require.Nil(t, tv.parse([]byte(stringField))) + assert.Equal(t, len(stringField), tv.length()) +} + +func TestTagValue_total(t *testing.T) { + stringField := "1=hello" + var tv TagValue + require.Nil(t, tv.parse([]byte(stringField))) + assert.Equal(t, 643, tv.total(), "Total is the summation of the ascii byte values of the field string") +} diff --git a/vendor/github.com/quickfixgo/quickfix/tls.go b/vendor/github.com/quickfixgo/quickfix/tls.go index 94ff89f..48cfe87 100644 --- a/vendor/github.com/quickfixgo/quickfix/tls.go +++ b/vendor/github.com/quickfixgo/quickfix/tls.go @@ -40,6 +40,26 @@ func loadTLSConfig(settings *SessionSettings) (tlsConfig *tls.Config, err error) tlsConfig.Certificates = make([]tls.Certificate, 1) tlsConfig.InsecureSkipVerify = insecureSkipVerify + minVersion := "TLS12" + if settings.HasSetting(config.SocketMinimumTLSVersion) { + minVersion, err = settings.Setting(config.SocketMinimumTLSVersion) + if err != nil { + return + } + + switch minVersion { + case "SSL30": + tlsConfig.MinVersion = tls.VersionSSL30 + case "TLS10": + tlsConfig.MinVersion = tls.VersionTLS10 + case "TLS11": + tlsConfig.MinVersion = tls.VersionTLS11 + case "TLS12": + tlsConfig.MinVersion = tls.VersionTLS12 + } + } + + if tlsConfig.Certificates[0], err = tls.LoadX509KeyPair(certificateFile, privateKeyFile); err != nil { return } diff --git a/vendor/github.com/quickfixgo/quickfix/tls_test.go b/vendor/github.com/quickfixgo/quickfix/tls_test.go new file mode 100644 index 0000000..322c452 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/tls_test.go @@ -0,0 +1,148 @@ +package quickfix + +import ( + "crypto/tls" + "testing" + + "github.com/quickfixgo/quickfix/config" + "github.com/stretchr/testify/suite" +) + +type TLSTestSuite struct { + suite.Suite + settings *Settings + PrivateKeyFile, CertificateFile, CAFile string +} + +func TestTLSTestSuite(t *testing.T) { + suite.Run(t, new(TLSTestSuite)) +} + +func (s *TLSTestSuite) SetupTest() { + s.settings = NewSettings() + s.PrivateKeyFile = "_test_data/localhost.key" + s.CertificateFile = "_test_data/localhost.crt" + s.CAFile = "_test_data/ca.crt" +} + +func (s *TLSTestSuite) TestLoadTLSNoSettings() { + tlsConfig, err := loadTLSConfig(s.settings.GlobalSettings()) + s.Nil(tlsConfig) + s.Nil(err) +} + +func (s *TLSTestSuite) TestLoadTLSMissingKeyOrCert() { + s.settings.GlobalSettings().Set(config.SocketPrivateKeyFile, s.PrivateKeyFile) + _, err := loadTLSConfig(s.settings.GlobalSettings()) + s.NotNil(err) + + s.SetupTest() + s.settings.GlobalSettings().Set(config.SocketCertificateFile, s.CertificateFile) + _, err = loadTLSConfig(s.settings.GlobalSettings()) + s.NotNil(err) +} + +func (s *TLSTestSuite) TestLoadTLSInvalidKeyOrCert() { + s.settings.GlobalSettings().Set(config.SocketPrivateKeyFile, "blah") + s.settings.GlobalSettings().Set(config.SocketCertificateFile, "foo") + _, err := loadTLSConfig(s.settings.GlobalSettings()) + s.NotNil(err) +} + +func (s *TLSTestSuite) TestLoadTLSNoCA() { + s.settings.GlobalSettings().Set(config.SocketPrivateKeyFile, s.PrivateKeyFile) + s.settings.GlobalSettings().Set(config.SocketCertificateFile, s.CertificateFile) + + tlsConfig, err := loadTLSConfig(s.settings.GlobalSettings()) + s.Nil(err) + s.NotNil(tlsConfig) + + s.Len(tlsConfig.Certificates, 1) + s.Nil(tlsConfig.RootCAs) + s.Nil(tlsConfig.ClientCAs) + s.Equal(tls.NoClientCert, tlsConfig.ClientAuth) +} + +func (s *TLSTestSuite) TestLoadTLSWithBadCA() { + s.settings.GlobalSettings().Set(config.SocketPrivateKeyFile, s.PrivateKeyFile) + s.settings.GlobalSettings().Set(config.SocketCertificateFile, s.CertificateFile) + s.settings.GlobalSettings().Set(config.SocketCAFile, "bar") + + _, err := loadTLSConfig(s.settings.GlobalSettings()) + s.NotNil(err) +} + +func (s *TLSTestSuite) TestLoadTLSWithCA() { + s.settings.GlobalSettings().Set(config.SocketPrivateKeyFile, s.PrivateKeyFile) + s.settings.GlobalSettings().Set(config.SocketCertificateFile, s.CertificateFile) + s.settings.GlobalSettings().Set(config.SocketCAFile, s.CAFile) + + tlsConfig, err := loadTLSConfig(s.settings.GlobalSettings()) + s.Nil(err) + s.NotNil(tlsConfig) + + s.Len(tlsConfig.Certificates, 1) + s.NotNil(tlsConfig.RootCAs) + s.NotNil(tlsConfig.ClientCAs) + s.Equal(tls.RequireAndVerifyClientCert, tlsConfig.ClientAuth) +} + +func (s *TLSTestSuite) TestInsecureSkipVerify() { + s.settings.GlobalSettings().Set(config.SocketInsecureSkipVerify, "Y") + + tlsConfig, err := loadTLSConfig(s.settings.GlobalSettings()) + s.Nil(err) + s.NotNil(tlsConfig) + + s.True(tlsConfig.InsecureSkipVerify) +} + +func (s *TLSTestSuite) TestInsecureSkipVerifyAndCerts() { + s.settings.GlobalSettings().Set(config.SocketPrivateKeyFile, s.PrivateKeyFile) + s.settings.GlobalSettings().Set(config.SocketCertificateFile, s.CertificateFile) + s.settings.GlobalSettings().Set(config.SocketInsecureSkipVerify, "Y") + + tlsConfig, err := loadTLSConfig(s.settings.GlobalSettings()) + s.Nil(err) + s.NotNil(tlsConfig) + + s.True(tlsConfig.InsecureSkipVerify) + s.Len(tlsConfig.Certificates, 1) +} + +func (s *TLSTestSuite) TestMinimumTLSVersion() { + s.settings.GlobalSettings().Set(config.SocketPrivateKeyFile, s.PrivateKeyFile) + s.settings.GlobalSettings().Set(config.SocketCertificateFile, s.CertificateFile) + + // SSL30 + s.settings.GlobalSettings().Set(config.SocketMinimumTLSVersion, "SSL30") + tlsConfig, err := loadTLSConfig(s.settings.GlobalSettings()) + + s.Nil(err) + s.NotNil(tlsConfig) + s.Equal(tlsConfig.MinVersion, uint16(tls.VersionSSL30)) + + // TLS10 + s.settings.GlobalSettings().Set(config.SocketMinimumTLSVersion, "TLS10") + tlsConfig, err = loadTLSConfig(s.settings.GlobalSettings()) + + s.Nil(err) + s.NotNil(tlsConfig) + s.Equal(tlsConfig.MinVersion, uint16(tls.VersionTLS10)) + + // TLS11 + s.settings.GlobalSettings().Set(config.SocketMinimumTLSVersion, "TLS11") + tlsConfig, err = loadTLSConfig(s.settings.GlobalSettings()) + + s.Nil(err) + s.NotNil(tlsConfig) + s.Equal(tlsConfig.MinVersion, uint16(tls.VersionTLS11)) + + // TLS12 + s.settings.GlobalSettings().Set(config.SocketMinimumTLSVersion, "TLS12") + tlsConfig, err = loadTLSConfig(s.settings.GlobalSettings()) + + s.Nil(err) + s.NotNil(tlsConfig) + s.Equal(tlsConfig.MinVersion, uint16(tls.VersionTLS12)) +} diff --git a/vendor/github.com/quickfixgo/quickfix/validation.go b/vendor/github.com/quickfixgo/quickfix/validation.go index 5c4013b..92aed28 100644 --- a/vendor/github.com/quickfixgo/quickfix/validation.go +++ b/vendor/github.com/quickfixgo/quickfix/validation.go @@ -5,7 +5,7 @@ import ( ) type validator interface { - Validate(Message) MessageRejectError + Validate(*Message) MessageRejectError } type validatorSettings struct { @@ -30,7 +30,7 @@ type fixtValidator struct { } //Validate tests the message against the provided data dictionary. -func (v *fixValidator) Validate(msg Message) MessageRejectError { +func (v *fixValidator) Validate(msg *Message) MessageRejectError { if !msg.Header.Has(tagMsgType) { return RequiredTagMissing(tagMsgType) } @@ -44,7 +44,7 @@ func (v *fixValidator) Validate(msg Message) MessageRejectError { //Validate tests the message against the provided transport and app data dictionaries. //If the message is an admin message, it will be validated against the transport data dictionary. -func (v *fixtValidator) Validate(msg Message) MessageRejectError { +func (v *fixtValidator) Validate(msg *Message) MessageRejectError { if !msg.Header.Has(tagMsgType) { return RequiredTagMissing(tagMsgType) } @@ -53,13 +53,13 @@ func (v *fixtValidator) Validate(msg Message) MessageRejectError { return err } - if isAdminMessageType(msgType) { + if isAdminMessageType([]byte(msgType)) { return validateFIX(v.transportDataDictionary, v.settings, msgType, msg) } return validateFIXT(v.transportDataDictionary, v.appDataDictionary, v.settings, msgType, msg) } -func validateFIX(d *datadictionary.DataDictionary, settings validatorSettings, msgType string, msg Message) MessageRejectError { +func validateFIX(d *datadictionary.DataDictionary, settings validatorSettings, msgType string, msg *Message) MessageRejectError { if err := validateMsgType(d, msgType, msg); err != nil { return err } @@ -85,7 +85,7 @@ func validateFIX(d *datadictionary.DataDictionary, settings validatorSettings, m return nil } -func validateFIXT(transportDD, appDD *datadictionary.DataDictionary, settings validatorSettings, msgType string, msg Message) MessageRejectError { +func validateFIXT(transportDD, appDD *datadictionary.DataDictionary, settings validatorSettings, msgType string, msg *Message) MessageRejectError { if err := validateMsgType(appDD, msgType, msg); err != nil { return err } @@ -111,14 +111,14 @@ func validateFIXT(transportDD, appDD *datadictionary.DataDictionary, settings va return nil } -func validateMsgType(d *datadictionary.DataDictionary, msgType string, msg Message) MessageRejectError { +func validateMsgType(d *datadictionary.DataDictionary, msgType string, msg *Message) MessageRejectError { if _, validMsgType := d.Messages[msgType]; validMsgType == false { return InvalidMessageType() } return nil } -func validateWalk(transportDD *datadictionary.DataDictionary, appDD *datadictionary.DataDictionary, msgType string, msg Message) MessageRejectError { +func validateWalk(transportDD *datadictionary.DataDictionary, appDD *datadictionary.DataDictionary, msgType string, msg *Message) MessageRejectError { remainingFields := msg.fields iteratedTags := make(datadictionary.TagSet) @@ -220,7 +220,7 @@ func validateVisitGroupField(fieldDef *datadictionary.FieldDef, fieldStack []Tag return fieldStack, nil } -func validateOrder(msg Message) MessageRejectError { +func validateOrder(msg *Message) MessageRejectError { inHeader := true inTrailer := false for _, field := range msg.fields { @@ -241,7 +241,7 @@ func validateOrder(msg Message) MessageRejectError { return nil } -func validateRequired(transportDD *datadictionary.DataDictionary, appDD *datadictionary.DataDictionary, msgType string, message Message) MessageRejectError { +func validateRequired(transportDD *datadictionary.DataDictionary, appDD *datadictionary.DataDictionary, msgType string, message *Message) MessageRejectError { if err := validateRequiredFieldMap(message, transportDD.Header.RequiredTags, message.Header.FieldMap); err != nil { return err } @@ -257,7 +257,7 @@ func validateRequired(transportDD *datadictionary.DataDictionary, appDD *datadic return nil } -func validateRequiredFieldMap(msg Message, requiredTags map[int]struct{}, fieldMap FieldMap) MessageRejectError { +func validateRequiredFieldMap(msg *Message, requiredTags map[int]struct{}, fieldMap FieldMap) MessageRejectError { for required := range requiredTags { requiredTag := Tag(required) if !fieldMap.Has(requiredTag) { @@ -268,7 +268,7 @@ func validateRequiredFieldMap(msg Message, requiredTags map[int]struct{}, fieldM return nil } -func validateFields(transportDD *datadictionary.DataDictionary, appDD *datadictionary.DataDictionary, msgType string, message Message) MessageRejectError { +func validateFields(transportDD *datadictionary.DataDictionary, appDD *datadictionary.DataDictionary, msgType string, message *Message) MessageRejectError { for _, field := range message.fields { switch { case field.tag.IsHeader(): diff --git a/vendor/github.com/quickfixgo/quickfix/validation_test.go b/vendor/github.com/quickfixgo/quickfix/validation_test.go new file mode 100644 index 0000000..1bc7c70 --- /dev/null +++ b/vendor/github.com/quickfixgo/quickfix/validation_test.go @@ -0,0 +1,544 @@ +package quickfix + +import ( + "bytes" + "testing" + "time" + + "github.com/quickfixgo/quickfix/datadictionary" + "github.com/stretchr/testify/assert" +) + +type validateTest struct { + TestName string + Validator validator + MessageBytes []byte + ExpectedRejectReason int + ExpectedRefTagID *Tag + DoNotExpectReject bool +} + +func TestValidate(t *testing.T) { + var tests = []validateTest{ + tcInvalidTagNumberHeader(), + tcInvalidTagNumberBody(), + tcInvalidTagNumberTrailer(), + tcTagSpecifiedWithoutAValue(), + tcInvalidMsgType(), + tcValueIsIncorrect(), + tcIncorrectDataFormatForValue(), + tcTagSpecifiedOutOfRequiredOrderHeader(), + tcTagSpecifiedOutOfRequiredOrderTrailer(), + tcTagSpecifiedOutOfRequiredOrderDisabledHeader(), + tcTagSpecifiedOutOfRequiredOrderDisabledTrailer(), + tcTagAppearsMoreThanOnce(), + tcFloatValidation(), + tcTagNotDefinedForMessage(), + tcTagIsDefinedForMessage(), + tcFieldNotFoundBody(), + tcFieldNotFoundHeader(), + } + + msg := NewMessage() + for _, test := range tests { + assert.Nil(t, ParseMessage(msg, bytes.NewBuffer(test.MessageBytes))) + reject := test.Validator.Validate(msg) + + switch { + case reject == nil && test.DoNotExpectReject: + continue + + case reject != nil && test.DoNotExpectReject: + t.Errorf("%v: Unexpected reject: %v", test.TestName, reject) + continue + + case reject == nil: + t.Errorf("%v: Expected reject", test.TestName) + continue + } + + if reject.RejectReason() != test.ExpectedRejectReason { + t.Errorf("%v: Expected reason %v got %v", test.TestName, test.ExpectedRejectReason, reject.RejectReason()) + } + + switch { + case reject.RefTagID() == nil && test.ExpectedRefTagID == nil: + //ok, expected and actual ref tag not set + case reject.RefTagID() != nil && test.ExpectedRefTagID == nil: + t.Errorf("%v: Unexpected RefTag '%v'", test.TestName, *reject.RefTagID()) + case reject.RefTagID() == nil && test.ExpectedRefTagID != nil: + t.Errorf("%v: Expected RefTag '%v'", test.TestName, *test.ExpectedRefTagID) + case *reject.RefTagID() == *test.ExpectedRefTagID: + //ok, tags equal + default: + t.Errorf("%v: Expected RefTag '%v' got '%v'", test.TestName, *test.ExpectedRefTagID, *reject.RefTagID()) + } + } +} + +func createFIX40NewOrderSingle() *Message { + msg := NewMessage() + msg.Header.SetField(tagMsgType, FIXString("D")) + msg.Header.SetField(tagBeginString, FIXString("FIX.4.0")) + msg.Header.SetField(tagBodyLength, FIXString("0")) + msg.Header.SetField(tagSenderCompID, FIXString("0")) + msg.Header.SetField(tagTargetCompID, FIXString("0")) + msg.Header.SetField(tagMsgSeqNum, FIXString("0")) + msg.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: time.Now()}) + + msg.Body.SetField(Tag(11), FIXString("A")) + msg.Body.SetField(Tag(21), FIXString("1")) + msg.Body.SetField(Tag(55), FIXString("A")) + msg.Body.SetField(Tag(54), FIXString("1")) + msg.Body.SetField(Tag(40), FIXString("1")) + msg.Body.SetField(Tag(38), FIXInt(5)) + msg.Body.SetField(Tag(100), FIXString("0")) + + msg.Trailer.SetField(tagCheckSum, FIXString("000")) + + return msg +} + +func createFIX43NewOrderSingle() *Message { + msg := NewMessage() + msg.Header.SetField(tagMsgType, FIXString("D")) + msg.Header.SetField(tagBeginString, FIXString("FIX.4.3")) + msg.Header.SetField(tagBodyLength, FIXString("0")) + msg.Header.SetField(tagSenderCompID, FIXString("0")) + msg.Header.SetField(tagTargetCompID, FIXString("0")) + msg.Header.SetField(tagMsgSeqNum, FIXString("0")) + msg.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: time.Now()}) + + msg.Body.SetField(Tag(11), FIXString("A")) + msg.Body.SetField(Tag(21), FIXString("1")) + msg.Body.SetField(Tag(55), FIXString("A")) + msg.Body.SetField(Tag(54), FIXString("1")) + msg.Body.SetField(Tag(38), FIXInt(5)) + msg.Body.SetField(Tag(40), FIXString("1")) + msg.Body.SetField(Tag(60), FIXUTCTimestamp{Time: time.Now()}) + + msg.Trailer.SetField(tagCheckSum, FIXString("000")) + + return msg +} + +func tcInvalidTagNumberHeader() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + invalidHeaderFieldMessage := createFIX40NewOrderSingle() + tag := Tag(9999) + invalidHeaderFieldMessage.Header.SetField(tag, FIXString("hello")) + msgBytes := invalidHeaderFieldMessage.build() + + return validateTest{ + TestName: "Invalid Tag Number Header", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonInvalidTagNumber, + ExpectedRefTagID: &tag, + } +} +func tcInvalidTagNumberBody() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + invalidBodyFieldMessage := createFIX40NewOrderSingle() + tag := Tag(9999) + invalidBodyFieldMessage.Body.SetField(tag, FIXString("hello")) + msgBytes := invalidBodyFieldMessage.build() + + return validateTest{ + TestName: "Invalid Tag Number Body", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonInvalidTagNumber, + ExpectedRefTagID: &tag, + } +} + +func tcInvalidTagNumberTrailer() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + invalidTrailerFieldMessage := createFIX40NewOrderSingle() + tag := Tag(9999) + invalidTrailerFieldMessage.Trailer.SetField(tag, FIXString("hello")) + msgBytes := invalidTrailerFieldMessage.build() + + return validateTest{ + TestName: "Invalid Tag Number Trailer", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonInvalidTagNumber, + ExpectedRefTagID: &tag, + } +} + +func tcTagNotDefinedForMessage() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + invalidMsg := createFIX40NewOrderSingle() + tag := Tag(41) + invalidMsg.Body.SetField(tag, FIXString("hello")) + msgBytes := invalidMsg.build() + + return validateTest{ + TestName: "Tag Not Defined For Message", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonTagNotDefinedForThisMessageType, + ExpectedRefTagID: &tag, + } +} + +func tcTagIsDefinedForMessage() validateTest { + //compare to tcTagIsNotDefinedForMessage + dict, _ := datadictionary.Parse("spec/FIX43.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + validMsg := createFIX43NewOrderSingle() + msgBytes := validMsg.build() + + return validateTest{ + TestName: "TagIsDefinedForMessage", + Validator: validator, + MessageBytes: msgBytes, + DoNotExpectReject: true, + } +} + +func tcFieldNotFoundBody() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + invalidMsg1 := NewMessage() + invalidMsg1.Header.SetField(tagMsgType, FIXString("D")). + SetField(tagBeginString, FIXString("FIX.4.0")). + SetField(tagBodyLength, FIXString("0")). + SetField(tagSenderCompID, FIXString("0")). + SetField(tagTargetCompID, FIXString("0")). + SetField(tagMsgSeqNum, FIXString("0")). + SetField(tagSendingTime, FIXUTCTimestamp{Time: time.Now()}) + invalidMsg1.Trailer.SetField(tagCheckSum, FIXString("000")) + + invalidMsg1.Body.SetField(Tag(11), FIXString("A")). + SetField(Tag(21), FIXString("A")). + SetField(Tag(55), FIXString("A")). + SetField(Tag(54), FIXString("A")). + SetField(Tag(38), FIXString("A")) + + tag := Tag(40) + //ord type is required + //invalidMsg1.Body.SetField(Tag(40), "A")) + + msgBytes := invalidMsg1.build() + + return validateTest{ + TestName: "FieldNotFoundBody", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonRequiredTagMissing, + ExpectedRefTagID: &tag, + } +} + +func tcFieldNotFoundHeader() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + + invalidMsg2 := NewMessage() + invalidMsg2.Trailer.SetField(tagCheckSum, FIXString("000")) + invalidMsg2.Body.SetField(Tag(11), FIXString("A")). + SetField(Tag(21), FIXString("A")). + SetField(Tag(55), FIXString("A")). + SetField(Tag(54), FIXString("A")). + SetField(Tag(38), FIXString("A")) + + invalidMsg2.Header.SetField(tagMsgType, FIXString("D")). + SetField(tagBeginString, FIXString("FIX.4.0")). + SetField(tagBodyLength, FIXString("0")). + SetField(tagSenderCompID, FIXString("0")). + SetField(tagTargetCompID, FIXString("0")). + SetField(tagMsgSeqNum, FIXString("0")) + //sending time is required + //invalidMsg2.Header.FieldMap.SetField(tag.SendingTime, "0")) + + tag := tagSendingTime + msgBytes := invalidMsg2.build() + + return validateTest{ + TestName: "FieldNotFoundHeader", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonRequiredTagMissing, + ExpectedRefTagID: &tag, + } +} + +func tcTagSpecifiedWithoutAValue() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + builder := createFIX40NewOrderSingle() + + bogusTag := Tag(109) + builder.Body.SetField(bogusTag, FIXString("")) + msgBytes := builder.build() + + return validateTest{ + TestName: "Tag SpecifiedWithoutAValue", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonTagSpecifiedWithoutAValue, + ExpectedRefTagID: &bogusTag, + } +} + +func tcInvalidMsgType() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + builder := createFIX40NewOrderSingle() + builder.Header.SetField(tagMsgType, FIXString("z")) + msgBytes := builder.build() + + return validateTest{ + TestName: "Invalid MsgType", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonInvalidMsgType, + } +} + +func tcValueIsIncorrect() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + + tag := Tag(21) + builder := createFIX40NewOrderSingle() + builder.Body.SetField(tag, FIXString("4")) + msgBytes := builder.build() + + return validateTest{ + TestName: "ValueIsIncorrect", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonValueIsIncorrect, + ExpectedRefTagID: &tag, + } +} + +func tcIncorrectDataFormatForValue() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + builder := createFIX40NewOrderSingle() + tag := Tag(38) + builder.Body.SetField(tag, FIXString("+200.00")) + msgBytes := builder.build() + + return validateTest{ + TestName: "IncorrectDataFormatForValue", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonIncorrectDataFormatForValue, + ExpectedRefTagID: &tag, + } +} + +func tcTagSpecifiedOutOfRequiredOrderHeader() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + + builder := createFIX40NewOrderSingle() + tag := tagOnBehalfOfCompID + //should be in header + builder.Body.SetField(tag, FIXString("CWB")) + msgBytes := builder.build() + + return validateTest{ + TestName: "Tag specified out of required order in Header", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonTagSpecifiedOutOfRequiredOrder, + ExpectedRefTagID: &tag, + } +} + +func tcTagSpecifiedOutOfRequiredOrderTrailer() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + + builder := createFIX40NewOrderSingle() + tag := tagSignature + //should be in trailer + builder.Body.SetField(tag, FIXString("SIG")) + msgBytes := builder.build() + + refTag := Tag(100) + return validateTest{ + TestName: "Tag specified out of required order in Trailer", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonTagSpecifiedOutOfRequiredOrder, + ExpectedRefTagID: &refTag, + } +} + +func tcTagSpecifiedOutOfRequiredOrderDisabledHeader() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + validator.settings.CheckFieldsOutOfOrder = false + + builder := createFIX40NewOrderSingle() + tag := tagOnBehalfOfCompID + //should be in header + builder.Body.SetField(tag, FIXString("CWB")) + msgBytes := builder.build() + + return validateTest{ + TestName: "Tag specified out of required order in Header - Disabled", + Validator: validator, + MessageBytes: msgBytes, + DoNotExpectReject: true, + } +} + +func tcTagSpecifiedOutOfRequiredOrderDisabledTrailer() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + validator.settings.CheckFieldsOutOfOrder = false + + builder := createFIX40NewOrderSingle() + tag := tagSignature + //should be in trailer + builder.Body.SetField(tag, FIXString("SIG")) + msgBytes := builder.build() + + return validateTest{ + TestName: "Tag specified out of required order in Trailer - Disabled", + Validator: validator, + MessageBytes: msgBytes, + DoNotExpectReject: true, + } +} + +func tcTagAppearsMoreThanOnce() validateTest { + dict, _ := datadictionary.Parse("spec/FIX40.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + tag := Tag(40) + + return validateTest{ + TestName: "Tag appears more than once", + Validator: validator, + MessageBytes: []byte("8=FIX.4.09=10735=D34=249=TW52=20060102-15:04:0556=ISLD11=ID21=140=140=254=138=20055=INTC60=20060102-15:04:0510=234"), + ExpectedRejectReason: rejectReasonTagAppearsMoreThanOnce, + ExpectedRefTagID: &tag, + } +} + +func tcFloatValidation() validateTest { + dict, _ := datadictionary.Parse("spec/FIX42.xml") + validator := &fixValidator{dict, defaultValidatorSettings} + tag := Tag(38) + return validateTest{ + TestName: "FloatValidation", + Validator: validator, + MessageBytes: []byte("8=FIX.4.29=10635=D34=249=TW52=20140329-22:38:4556=ISLD11=ID21=140=154=138=+200.0055=INTC60=20140329-22:38:4510=178"), + ExpectedRejectReason: rejectReasonIncorrectDataFormatForValue, + ExpectedRefTagID: &tag, + } +} + +func TestValidateVisitField(t *testing.T) { + fieldType0 := datadictionary.NewFieldType("myfield", 11, "STRING") + fieldDef0 := &datadictionary.FieldDef{FieldType: fieldType0} + + fieldType1 := datadictionary.NewFieldType("myfield", 2, "STRING") + fieldDef1 := &datadictionary.FieldDef{FieldType: fieldType1, Fields: []*datadictionary.FieldDef{}} + + fieldType2 := datadictionary.NewFieldType("myfield", 3, "STRING") + fieldDef2 := &datadictionary.FieldDef{FieldType: fieldType2, Fields: []*datadictionary.FieldDef{}} + + groupFieldType := datadictionary.NewFieldType("mygroupfield", 1, "INT") + groupFieldDef := &datadictionary.FieldDef{FieldType: groupFieldType, Fields: []*datadictionary.FieldDef{fieldDef1, fieldDef2}} + + var field TagValue + field.init(Tag(11), []byte("value")) + + var repField1 TagValue + var repField2 TagValue + repField1.init(Tag(2), []byte("a")) + repField2.init(Tag(3), []byte("a")) + + var groupID TagValue + groupID.init(Tag(1), []byte("1")) + + var groupID2 TagValue + groupID2.init(Tag(1), []byte("2")) + + var groupID3 TagValue + groupID3.init(Tag(1), []byte("3")) + + var tests = []struct { + fieldDef *datadictionary.FieldDef + fields []TagValue + expectedRemFields int + expectReject bool + expectedRejectReason int + }{ + //non-repeating + {expectedRemFields: 0, + fieldDef: fieldDef0, + fields: []TagValue{field}}, + //single field group + {expectedRemFields: 0, + fieldDef: groupFieldDef, + fields: []TagValue{groupID, repField1}}, + //multiple field group + {expectedRemFields: 0, + fieldDef: groupFieldDef, + fields: []TagValue{groupID, repField1, repField2}}, + //test with trailing tag not in group + {expectedRemFields: 1, + fieldDef: groupFieldDef, + fields: []TagValue{groupID, repField1, repField2, field}}, + //repeats + {expectedRemFields: 1, + fieldDef: groupFieldDef, + fields: []TagValue{groupID2, repField1, repField2, repField1, repField2, field}}, + //REJECT: group size declared > actual group size + {expectReject: true, + fieldDef: groupFieldDef, + fields: []TagValue{groupID3, repField1, repField2, repField1, repField2, field}, + expectedRejectReason: rejectReasonIncorrectNumInGroupCountForRepeatingGroup, + }, + {expectReject: true, + fieldDef: groupFieldDef, + fields: []TagValue{groupID3, repField1, repField1, field}, + expectedRejectReason: rejectReasonIncorrectNumInGroupCountForRepeatingGroup, + }, + //REJECT: group size declared < actual group size + {expectReject: true, + fieldDef: groupFieldDef, + fields: []TagValue{groupID, repField1, repField2, repField1, repField2, field}, + expectedRejectReason: rejectReasonIncorrectNumInGroupCountForRepeatingGroup, + }, + } + + for _, test := range tests { + remFields, reject := validateVisitField(test.fieldDef, test.fields) + + if test.expectReject { + if reject == nil { + t.Error("Expected Reject") + } + + if reject.RejectReason() != test.expectedRejectReason { + t.Errorf("Expected reject reason %v got %v", test.expectedRejectReason, reject.RejectReason()) + } + continue + } + + if reject != nil { + t.Errorf("Unexpected reject: %v", reject) + } + + if len(remFields) != test.expectedRemFields { + t.Errorf("Expected len %v got %v", test.expectedRemFields, len(remFields)) + } + } +} diff --git a/vendor/github.com/quickfixgo/tag/README.md b/vendor/github.com/quickfixgo/tag/README.md new file mode 100644 index 0000000..54fcce9 --- /dev/null +++ b/vendor/github.com/quickfixgo/tag/README.md @@ -0,0 +1,4 @@ +Tag +=== + +Tag is generated from `github.com/quickfixgo/quickfix/cmd/generate-fix` using the specs in `github.com/quickfixgo/quickfix/spec`. diff --git a/vendor/github.com/quickfixgo/quickfix/tag/tag_numbers.generated.go b/vendor/github.com/quickfixgo/tag/tag_numbers.generated.go similarity index 100% rename from vendor/github.com/quickfixgo/quickfix/tag/tag_numbers.generated.go rename to vendor/github.com/quickfixgo/tag/tag_numbers.generated.go diff --git a/vendor/github.com/shopspring/decimal/.gitignore b/vendor/github.com/shopspring/decimal/.gitignore new file mode 100644 index 0000000..5357942 --- /dev/null +++ b/vendor/github.com/shopspring/decimal/.gitignore @@ -0,0 +1,2 @@ +.git +*.swp diff --git a/vendor/github.com/shopspring/decimal/.travis.yml b/vendor/github.com/shopspring/decimal/.travis.yml new file mode 100644 index 0000000..d2d585c --- /dev/null +++ b/vendor/github.com/shopspring/decimal/.travis.yml @@ -0,0 +1,13 @@ +language: go + +go: + - 1.2 + - 1.3 + - 1.4 + - tip + +install: + - go build . + +script: + - go test -v diff --git a/vendor/github.com/shopspring/decimal/README.md b/vendor/github.com/shopspring/decimal/README.md index 7aaadae..be9cb5e 100644 --- a/vendor/github.com/shopspring/decimal/README.md +++ b/vendor/github.com/shopspring/decimal/README.md @@ -1,4 +1,6 @@ -# decimal [![Build Status](https://travis-ci.org/shopspring/decimal.png?branch=master)](https://travis-ci.org/shopspring/decimal) [![BADGINATOR](https://badginator.herokuapp.com/shopspring/decimal.svg?image_analysis=1)](https://github.com/defunctzombie/badginator) +# decimal + +[![Build Status](https://travis-ci.org/shopspring/decimal.png?branch=master)](https://travis-ci.org/shopspring/decimal) [![GoDoc](https://godoc.org/github.com/shopspring/decimal?status.svg)](https://godoc.org/github.com/shopspring/decimal) [![Go Report Card](https://goreportcard.com/badge/github.com/shopspring/decimal)](https://goreportcard.com/report/github.com/shopspring/decimal) Arbitrary-precision fixed-point decimal numbers in go. diff --git a/vendor/github.com/shopspring/decimal/decimal.go b/vendor/github.com/shopspring/decimal/decimal.go index 287f2c5..1729b61 100644 --- a/vendor/github.com/shopspring/decimal/decimal.go +++ b/vendor/github.com/shopspring/decimal/decimal.go @@ -19,6 +19,7 @@ package decimal import ( "database/sql/driver" + "encoding/binary" "fmt" "math" "math/big" @@ -43,6 +44,14 @@ import ( // var DivisionPrecision = 16 +// MarshalJSONWithoutQuotes should be set to true if you want the decimal to +// be JSON marshaled as a number, instead of as a string. +// WARNING: this is dangerous for decimals with many digits, since many JSON +// unmarshallers (ex: Javascript's) will unmarshal JSON numbers to IEEE 754 +// double-precision floating point numbers, which means you can potentially +// silently lose precision. +var MarshalJSONWithoutQuotes = false + // Zero constant, to make computations faster. var Zero = New(0, 1) @@ -72,6 +81,14 @@ func New(value int64, exp int32) Decimal { } } +// NewFromBigInt returns a new Decimal from a big.Int, value * 10 ^ exp +func NewFromBigInt(value *big.Int, exp int32) Decimal { + return Decimal{ + value: big.NewInt(0).Set(value), + exp: exp, + } +} + // NewFromString returns a new Decimal from a string representation. // // Example: @@ -104,8 +121,10 @@ func NewFromString(value string) (Decimal, error) { // an int intString = value } else if len(parts) == 2 { - intString = parts[0] + parts[1] - expInt := -len(parts[1]) + // strip the insignificant digits for more accurate comparisons. + decimalPart := strings.TrimRight(parts[1], "0") + intString = parts[0] + decimalPart + expInt := -len(decimalPart) exp += int64(expInt) } else { return Decimal{}, fmt.Errorf("can't convert %s to decimal: too many .s", value) @@ -251,6 +270,15 @@ func (d Decimal) Sub(d2 Decimal) Decimal { } } +// Neg returns -d. +func (d Decimal) Neg() Decimal { + val := new(big.Int).Neg(d.value) + return Decimal{ + value: val, + exp: d.exp, + } +} + // Mul returns d * d2. func (d Decimal) Mul(d2 Decimal) Decimal { d.ensureInitialized() @@ -273,18 +301,81 @@ func (d Decimal) Mul(d2 Decimal) Decimal { // Div returns d / d2. If it doesn't divide exactly, the result will have // DivisionPrecision digits after the decimal point. func (d Decimal) Div(d2 Decimal) Decimal { - // NOTE(vadim): division is hard, use Rat to do it - ratNum := d.Rat() - ratDenom := d2.Rat() - - quoRat := big.NewRat(0, 1).Quo(ratNum, ratDenom) + return d.DivRound(d2, int32(DivisionPrecision)) +} - // HACK(vadim): converting from Rat to Decimal inefficiently for now - ret, err := NewFromString(quoRat.FloatString(DivisionPrecision)) - if err != nil { - panic(err) // this should never happen - } - return ret +// QuoRem does divsion with remainder +// d.QuoRem(d2,precision) returns quotient q and remainder r such that +// d = d2 * q + r, q an integer multiple of 10^(-precision) +// 0 <= r < abs(d2) * 10 ^(-precision) if d>=0 +// 0 >= r > -abs(d2) * 10 ^(-precision) if d<0 +// Note that precision<0 is allowed as input. +func (d Decimal) QuoRem(d2 Decimal, precision int32) (Decimal, Decimal) { + d.ensureInitialized() + d2.ensureInitialized() + if d2.value.Sign() == 0 { + panic("decimal division by 0") + } + scale := -precision + e := int64(d.exp - d2.exp - scale) + if e > math.MaxInt32 || e < math.MinInt32 { + panic("overflow in decimal QuoRem") + } + var aa, bb, expo big.Int + var scalerest int32 + // d = a 10^ea + // d2 = b 10^eb + if e < 0 { + aa = *d.value + expo.SetInt64(-e) + bb.Exp(tenInt, &expo, nil) + bb.Mul(d2.value, &bb) + scalerest = d.exp + // now aa = a + // bb = b 10^(scale + eb - ea) + } else { + expo.SetInt64(e) + aa.Exp(tenInt, &expo, nil) + aa.Mul(d.value, &aa) + bb = *d2.value + scalerest = scale + d2.exp + // now aa = a ^ (ea - eb - scale) + // bb = b + } + var q, r big.Int + q.QuoRem(&aa, &bb, &r) + dq := Decimal{value: &q, exp: scale} + dr := Decimal{value: &r, exp: scalerest} + return dq, dr +} + +// DivRound divides and rounds to a given precision +// i.e. to an integer multiple of 10^(-precision) +// for a positive quotient digit 5 is rounded up, away from 0 +// if the quotient is negative then digit 5 is rounded down, away from 0 +// Note that precision<0 is allowed as input. +func (d Decimal) DivRound(d2 Decimal, precision int32) Decimal { + // QuoRem already checks initialization + q, r := d.QuoRem(d2, precision) + // the actual rounding decision is based on comparing r*10^precision and d2/2 + // instead compare 2 r 10 ^precision and d2 + var rv2 big.Int + rv2.Abs(r.value) + rv2.Lsh(&rv2, 1) + // now rv2 = abs(r.value) * 2 + r2 := Decimal{value: &rv2, exp: r.exp + precision} + // r2 is now 2 * r * 10 ^ precision + var c = r2.Cmp(d2.Abs()) + + if c < 0 { + return q + } + + if d.value.Sign()*d2.value.Sign() < 0 { + return q.Sub(New(1, -precision)) + } + + return q.Add(New(1, -precision)) } // Mod returns d % d2. @@ -293,6 +384,22 @@ func (d Decimal) Mod(d2 Decimal) Decimal { return d.Sub(d2.Mul(quo)) } +// Pow returns d to the power d2 +func (d Decimal) Pow(d2 Decimal) Decimal { + var temp Decimal + if d2.IntPart() == 0 { + return NewFromFloat(1) + } + temp = d.Pow(d2.Div(NewFromFloat(2))) + if d2.IntPart()%2 == 0 { + return temp.Mul(temp) + } + if d2.IntPart() > 0 { + return temp.Mul(temp).Mul(d) + } + return temp.Mul(temp).Div(d) +} + // Cmp compares the numbers represented by d and d2 and returns: // // -1 if d < d2 @@ -314,16 +421,63 @@ func (d Decimal) Cmp(d2 Decimal) int { return rd.value.Cmp(rd2.value) } -// Equals returns whether the numbers represented by d and d2 are equal. -func (d Decimal) Equals(d2 Decimal) bool { +// Equal returns whether the numbers represented by d and d2 are equal. +func (d Decimal) Equal(d2 Decimal) bool { return d.Cmp(d2) == 0 } +// Equals is deprecated, please use Equal method instead +func (d Decimal) Equals(d2 Decimal) bool { + return d.Equal(d2) +} + +// GreaterThan (GT) returns true when d is greater than d2. +func (d Decimal) GreaterThan(d2 Decimal) bool { + return d.Cmp(d2) == 1 +} + +// GreaterThanOrEqual (GTE) returns true when d is greater than or equal to d2. +func (d Decimal) GreaterThanOrEqual(d2 Decimal) bool { + cmp := d.Cmp(d2) + return cmp == 1 || cmp == 0 +} + +// LessThan (LT) returns true when d is less than d2. +func (d Decimal) LessThan(d2 Decimal) bool { + return d.Cmp(d2) == -1 +} + +// LessThanOrEqual (LTE) returns true when d is less than or equal to d2. +func (d Decimal) LessThanOrEqual(d2 Decimal) bool { + cmp := d.Cmp(d2) + return cmp == -1 || cmp == 0 +} + +// Sign returns: +// +// -1 if d < 0 +// 0 if d == 0 +// +1 if d > 0 +// +func (d Decimal) Sign() int { + if d.value == nil { + return 0 + } + return d.value.Sign() +} + // Exponent returns the exponent, or scale component of the decimal. func (d Decimal) Exponent() int32 { return d.exp } +// Coefficient returns the coefficient of the decimal. It is scaled by 10^Exponent() +func (d Decimal) Coefficient() *big.Int { + // we copy the coefficient so that mutating the result does not mutate the + // Decimal. + return big.NewInt(0).Set(d.value) +} + // IntPart returns the integer component of the decimal. func (d Decimal) IntPart() int64 { scaledD := d.rescale(0) @@ -337,11 +491,11 @@ func (d Decimal) Rat() *big.Rat { // NOTE(vadim): must negate after casting to prevent int32 overflow denom := new(big.Int).Exp(tenInt, big.NewInt(-int64(d.exp)), nil) return new(big.Rat).SetFrac(d.value, denom) - } else { - mul := new(big.Int).Exp(tenInt, big.NewInt(int64(d.exp)), nil) - num := new(big.Int).Mul(d.value, mul) - return new(big.Rat).SetFrac(num, oneInt) } + + mul := new(big.Int).Exp(tenInt, big.NewInt(int64(d.exp)), nil) + num := new(big.Int).Mul(d.value, mul) + return new(big.Rat).SetFrac(num, oneInt) } // Float64 returns the nearest float64 value for d and a bool indicating @@ -385,6 +539,24 @@ func (d Decimal) StringFixed(places int32) string { return rounded.string(false) } +// StringFixedBank returns a banker rounded fixed-point string with places digits +// after the decimal point. +// +// Example: +// +// NewFromFloat(0).StringFixed(2) // output: "0.00" +// NewFromFloat(0).StringFixed(0) // output: "0" +// NewFromFloat(5.45).StringFixed(0) // output: "5" +// NewFromFloat(5.45).StringFixed(1) // output: "5.4" +// NewFromFloat(5.45).StringFixed(2) // output: "5.45" +// NewFromFloat(5.45).StringFixed(3) // output: "5.450" +// NewFromFloat(545).StringFixed(-1) // output: "550" +// +func (d Decimal) StringFixedBank(places int32) string { + rounded := d.RoundBank(places) + return rounded.string(false) +} + // Round rounds the decimal to places decimal places. // If places < 0, it will round the integer part to the nearest 10^(-places). // @@ -406,7 +578,7 @@ func (d Decimal) Round(places int32) Decimal { // floor for positive numbers, ceil for negative numbers _, m := ret.value.DivMod(ret.value, tenInt, new(big.Int)) - ret.exp += 1 + ret.exp++ if ret.value.Sign() < 0 && m.Cmp(zeroInt) != 0 { ret.value.Add(ret.value, oneInt) } @@ -414,6 +586,37 @@ func (d Decimal) Round(places int32) Decimal { return ret } +// RoundBank rounds the decimal to places decimal places. +// If the final digit to round is equidistant from the nearest two integers the +// rounded value is taken as the even number +// +// If places < 0, it will round the integer part to the nearest 10^(-places). +// +// Examples: +// +// NewFromFloat(5.45).Round(1).String() // output: "5.4" +// NewFromFloat(545).Round(-1).String() // output: "540" +// NewFromFloat(5.46).Round(1).String() // output: "5.5" +// NewFromFloat(546).Round(-1).String() // output: "550" +// NewFromFloat(5.55).Round(1).String() // output: "5.6" +// NewFromFloat(555).Round(-1).String() // output: "560" +// +func (d Decimal) RoundBank(places int32) Decimal { + + round := d.Round(places) + remainder := d.Sub(round).Abs() + + if remainder.value.Cmp(fiveInt) == 0 && round.value.Bit(0) != 0 { + if round.value.Sign() < 0 { + round.value.Add(round.value, oneInt) + } else { + round.value.Sub(round.value, oneInt) + } + } + + return round +} + // Floor returns the nearest integer value less than or equal to d. func (d Decimal) Floor() Decimal { d.ensureInitialized() @@ -461,6 +664,10 @@ func (d Decimal) Truncate(precision int32) Decimal { // UnmarshalJSON implements the json.Unmarshaler interface. func (d *Decimal) UnmarshalJSON(decimalBytes []byte) error { + if string(decimalBytes) == "null" { + return nil + } + str, err := unquoteIfQuoted(decimalBytes) if err != nil { return fmt.Errorf("Error decoding string '%s': %s", decimalBytes, err) @@ -476,15 +683,52 @@ func (d *Decimal) UnmarshalJSON(decimalBytes []byte) error { // MarshalJSON implements the json.Marshaler interface. func (d Decimal) MarshalJSON() ([]byte, error) { - str := "\"" + d.String() + "\"" + var str string + if MarshalJSONWithoutQuotes { + str = d.String() + } else { + str = "\"" + d.String() + "\"" + } return []byte(str), nil } +// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. As a string representation +// is already used when encoding to text, this method stores that string as []byte +func (d *Decimal) UnmarshalBinary(data []byte) error { + // Extract the exponent + d.exp = int32(binary.BigEndian.Uint32(data[:4])) + + // Extract the value + d.value = new(big.Int) + return d.value.GobDecode(data[4:]) +} + +// MarshalBinary implements the encoding.BinaryMarshaler interface. +func (d Decimal) MarshalBinary() (data []byte, err error) { + // Write the exponent first since it's a fixed size + v1 := make([]byte, 4) + binary.BigEndian.PutUint32(v1, uint32(d.exp)) + + // Add the value + var v2 []byte + if v2, err = d.value.GobEncode(); err != nil { + return + } + + // Return the byte array + data = append(v1, v2...) + return +} + // Scan implements the sql.Scanner interface for database deserialization. func (d *Decimal) Scan(value interface{}) error { // first try to see if the data is stored in database as a Numeric datatype switch v := value.(type) { + case float32: + *d = NewFromFloat(float64(v)) + return nil + case float64: // numeric in sqlite3 sends us float64 *d = NewFromFloat(v) @@ -532,8 +776,18 @@ func (d Decimal) MarshalText() (text []byte, err error) { return []byte(d.String()), nil } -// NOTE: buggy, unintuitive, and DEPRECATED! Use StringFixed instead. +// GobEncode implements the gob.GobEncoder interface for gob serialization. +func (d Decimal) GobEncode() ([]byte, error) { + return d.MarshalBinary() +} + +// GobDecode implements the gob.GobDecoder interface for gob serialization. +func (d *Decimal) GobDecode(data []byte) error { + return d.UnmarshalBinary(data) +} + // StringScaled first scales the decimal then calls .String() on it. +// NOTE: buggy, unintuitive, and DEPRECATED! Use StringFixed instead. func (d Decimal) StringScaled(exp int32) string { return d.rescale(exp).String() } @@ -589,7 +843,7 @@ func (d *Decimal) ensureInitialized() { } } -// Returns the smallest Decimal that was passed in the arguments. +// Min returns the smallest Decimal that was passed in the arguments. // // To call this function with an array, you must do: // @@ -606,7 +860,7 @@ func Min(first Decimal, rest ...Decimal) Decimal { return ans } -// Returns the largest Decimal that was passed in the arguments. +// Max returns the largest Decimal that was passed in the arguments. // // To call this function with an array, you must do: // @@ -623,6 +877,23 @@ func Max(first Decimal, rest ...Decimal) Decimal { return ans } +// Sum returns the combined total of the provided first and rest Decimals +func Sum(first Decimal, rest ...Decimal) Decimal { + total := first + for _, item := range rest { + total = total.Add(item) + } + + return total +} + +// Avg returns the average value of the provided first and rest Decimals +func Avg(first Decimal, rest ...Decimal) Decimal { + count := New(int64(len(rest)+1), 0) + sum := Sum(first, rest...) + return sum.Div(count) +} + func min(x, y int32) int32 { if x >= y { return y @@ -638,10 +909,16 @@ func round(n float64) int64 { } func unquoteIfQuoted(value interface{}) (string, error) { - bytes, ok := value.([]byte) - if !ok { - return "", fmt.Errorf("Could not convert value '%+v' to byte array", - value) + var bytes []byte + + switch v := value.(type) { + case string: + bytes = []byte(v) + case []byte: + bytes = v + default: + return "", fmt.Errorf("Could not convert value '%+v' to byte array of type '%T'", + value, value) } // If the amount is quoted, strip the quotes @@ -650,3 +927,28 @@ func unquoteIfQuoted(value interface{}) (string, error) { } return string(bytes), nil } + +// NullDecimal represents a fixed-point decimal. It is immutable. +// number = value * 10 ^ exp +type NullDecimal struct { + Decimal Decimal + Valid bool +} + +// Scan implements the sql.Scanner interface for database deserialization. +func (d *NullDecimal) Scan(value interface{}) error { + if value == nil { + d.Valid = false + return nil + } + d.Valid = true + return d.Decimal.Scan(value) +} + +// Value implements the driver.Valuer interface for database serialization. +func (d NullDecimal) Value() (driver.Value, error) { + if !d.Valid { + return nil, nil + } + return d.Decimal.Value() +} diff --git a/vendor/github.com/shopspring/decimal/decimal_test.go b/vendor/github.com/shopspring/decimal/decimal_test.go new file mode 100644 index 0000000..d606dc9 --- /dev/null +++ b/vendor/github.com/shopspring/decimal/decimal_test.go @@ -0,0 +1,1846 @@ +package decimal + +import ( + "database/sql/driver" + "encoding/json" + "encoding/xml" + "math" + "math/big" + "reflect" + "sort" + "strconv" + "strings" + "testing" + "time" +) + +var testTable = map[float64]string{ + 3.141592653589793: "3.141592653589793", + 3: "3", + 1234567890123456: "1234567890123456", + 1234567890123456000: "1234567890123456000", + 1234.567890123456: "1234.567890123456", + .1234567890123456: "0.1234567890123456", + 0: "0", + .1111111111111110: "0.111111111111111", + .1111111111111111: "0.1111111111111111", + .1111111111111119: "0.1111111111111119", + .000000000000000001: "0.000000000000000001", + .000000000000000002: "0.000000000000000002", + .000000000000000003: "0.000000000000000003", + .000000000000000005: "0.000000000000000005", + .000000000000000008: "0.000000000000000008", + .1000000000000001: "0.1000000000000001", + .1000000000000002: "0.1000000000000002", + .1000000000000003: "0.1000000000000003", + .1000000000000005: "0.1000000000000005", + .1000000000000008: "0.1000000000000008", + 1e25: "10000000000000000000000000", +} + +var testTableScientificNotation = map[string]string{ + "1e9": "1000000000", + "2.41E-3": "0.00241", + "24.2E-4": "0.00242", + "243E-5": "0.00243", + "1e-5": "0.00001", + "245E3": "245000", + "1.2345E-1": "0.12345", + "0e5": "0", + "0e-5": "0", + "123.456e0": "123.456", + "123.456e2": "12345.6", + "123.456e10": "1234560000000", +} + +func init() { + // add negatives + for f, s := range testTable { + if f > 0 { + testTable[-f] = "-" + s + } + } + for e, s := range testTableScientificNotation { + if string(e[0]) != "-" && s != "0" { + testTableScientificNotation["-"+e] = "-" + s + } + } +} + +func TestNewFromFloat(t *testing.T) { + for f, s := range testTable { + d := NewFromFloat(f) + if d.String() != s { + t.Errorf("expected %s, got %s (%s, %d)", + s, d.String(), + d.value.String(), d.exp) + } + } + + shouldPanicOn := []float64{ + math.NaN(), + math.Inf(1), + math.Inf(-1), + } + + for _, n := range shouldPanicOn { + var d Decimal + if !didPanic(func() { d = NewFromFloat(n) }) { + t.Fatalf("Expected panic when creating a Decimal from %v, got %v instead", n, d.String()) + } + } +} + +func TestNewFromString(t *testing.T) { + for _, s := range testTable { + d, err := NewFromString(s) + if err != nil { + t.Errorf("error while parsing %s", s) + } else if d.String() != s { + t.Errorf("expected %s, got %s (%s, %d)", + s, d.String(), + d.value.String(), d.exp) + } + } + + for e, s := range testTableScientificNotation { + d, err := NewFromString(e) + if err != nil { + t.Errorf("error while parsing %s", e) + } else if d.String() != s { + t.Errorf("expected %s, got %s (%s, %d)", + s, d.String(), + d.value.String(), d.exp) + } + } +} + +func TestNewFromStringErrs(t *testing.T) { + tests := []string{ + "", + "qwert", + "-", + ".", + "-.", + ".-", + "234-.56", + "234-56", + "2-", + "..", + "2..", + "..2", + ".5.2", + "8..2", + "8.1.", + "1e", + "1-e", + "1e9e", + "1ee9", + "1ee", + "1eE", + "1e-", + "1e-.", + "1e1.2", + "123.456e1.3", + "1e-1.2", + "123.456e-1.3", + "123.456Easdf", + "123.456e" + strconv.FormatInt(math.MinInt64, 10), + "123.456e" + strconv.FormatInt(math.MinInt32, 10), + } + + for _, s := range tests { + _, err := NewFromString(s) + + if err == nil { + t.Errorf("error expected when parsing %s", s) + } + } +} + +func TestNewFromStringDeepEquals(t *testing.T) { + type StrCmp struct { + str1 string + str2 string + expected bool + } + tests := []StrCmp{ + {"1", "1", true}, + {"10", "10.0", true}, + {"1.1", "1.10", true}, + {"1.001", "1.01", false}, + } + + for _, cmp := range tests { + d1, err1 := NewFromString(cmp.str1) + d2, err2 := NewFromString(cmp.str2) + + if err1 != nil || err2 != nil { + t.Errorf("error parsing strings to decimals") + } + + if reflect.DeepEqual(d1, d2) != cmp.expected { + t.Errorf("comparison result is different from expected results for %s and %s", + cmp.str1, cmp.str2) + } + } +} + +func TestNewFromFloatWithExponent(t *testing.T) { + type Inp struct { + float float64 + exp int32 + } + tests := map[Inp]string{ + Inp{123.4, -3}: "123.4", + Inp{123.4, -1}: "123.4", + Inp{123.412345, 1}: "120", + Inp{123.412345, 0}: "123", + Inp{123.412345, -5}: "123.41235", + Inp{123.412345, -6}: "123.412345", + Inp{123.412345, -7}: "123.412345", + } + + // add negatives + for p, s := range tests { + if p.float > 0 { + tests[Inp{-p.float, p.exp}] = "-" + s + } + } + + for input, s := range tests { + d := NewFromFloatWithExponent(input.float, input.exp) + if d.String() != s { + t.Errorf("expected %s, got %s (%s, %d)", + s, d.String(), + d.value.String(), d.exp) + } + } + + shouldPanicOn := []float64{ + math.NaN(), + math.Inf(1), + math.Inf(-1), + } + + for _, n := range shouldPanicOn { + var d Decimal + if !didPanic(func() { d = NewFromFloatWithExponent(n, 0) }) { + t.Fatalf("Expected panic when creating a Decimal from %v, got %v instead", n, d.String()) + } + } +} + +func TestNewFromBigIntWithExponent(t *testing.T) { + type Inp struct { + val *big.Int + exp int32 + } + tests := map[Inp]string{ + Inp{big.NewInt(123412345), -3}: "123412.345", + Inp{big.NewInt(2234), -1}: "223.4", + Inp{big.NewInt(323412345), 1}: "3234123450", + Inp{big.NewInt(423412345), 0}: "423412345", + Inp{big.NewInt(52341235), -5}: "523.41235", + Inp{big.NewInt(623412345), -6}: "623.412345", + Inp{big.NewInt(723412345), -7}: "72.3412345", + } + + // add negatives + for p, s := range tests { + if p.val.Cmp(Zero.value) > 0 { + tests[Inp{p.val.Neg(p.val), p.exp}] = "-" + s + } + } + + for input, s := range tests { + d := NewFromBigInt(input.val, input.exp) + if d.String() != s { + t.Errorf("expected %s, got %s (%s, %d)", + s, d.String(), + d.value.String(), d.exp) + } + } +} + +func TestJSON(t *testing.T) { + for _, s := range testTable { + var doc struct { + Amount Decimal `json:"amount"` + } + docStr := `{"amount":"` + s + `"}` + docStrNumber := `{"amount":` + s + `}` + err := json.Unmarshal([]byte(docStr), &doc) + if err != nil { + t.Errorf("error unmarshaling %s: %v", docStr, err) + } else if doc.Amount.String() != s { + t.Errorf("expected %s, got %s (%s, %d)", + s, doc.Amount.String(), + doc.Amount.value.String(), doc.Amount.exp) + } + + out, err := json.Marshal(&doc) + if err != nil { + t.Errorf("error marshaling %+v: %v", doc, err) + } else if string(out) != docStr { + t.Errorf("expected %s, got %s", docStr, string(out)) + } + + // make sure unquoted marshalling works too + MarshalJSONWithoutQuotes = true + out, err = json.Marshal(&doc) + if err != nil { + t.Errorf("error marshaling %+v: %v", doc, err) + } else if string(out) != docStrNumber { + t.Errorf("expected %s, got %s", docStrNumber, string(out)) + } + MarshalJSONWithoutQuotes = false + } +} + +func TestUnmarshalJSONNull(t *testing.T) { + var doc struct { + Amount Decimal `json:"amount"` + } + docStr := `{"amount": null}` + err := json.Unmarshal([]byte(docStr), &doc) + if err != nil { + t.Errorf("error unmarshaling %s: %v", docStr, err) + } else if !doc.Amount.Equal(Zero) { + t.Errorf("expected Zero, got %s (%s, %d)", + doc.Amount.String(), + doc.Amount.value.String(), doc.Amount.exp) + } +} + +func TestBadJSON(t *testing.T) { + for _, testCase := range []string{ + "]o_o[", + "{", + `{"amount":""`, + `{"amount":""}`, + `{"amount":"nope"}`, + `0.333`, + } { + var doc struct { + Amount Decimal `json:"amount"` + } + err := json.Unmarshal([]byte(testCase), &doc) + if err == nil { + t.Errorf("expected error, got %+v", doc) + } + } +} + +func TestXML(t *testing.T) { + for _, s := range testTable { + var doc struct { + XMLName xml.Name `xml:"account"` + Amount Decimal `xml:"amount"` + } + docStr := `` + s + `` + err := xml.Unmarshal([]byte(docStr), &doc) + if err != nil { + t.Errorf("error unmarshaling %s: %v", docStr, err) + } else if doc.Amount.String() != s { + t.Errorf("expected %s, got %s (%s, %d)", + s, doc.Amount.String(), + doc.Amount.value.String(), doc.Amount.exp) + } + + out, err := xml.Marshal(&doc) + if err != nil { + t.Errorf("error marshaling %+v: %v", doc, err) + } else if string(out) != docStr { + t.Errorf("expected %s, got %s", docStr, string(out)) + } + } +} + +func TestBadXML(t *testing.T) { + for _, testCase := range []string{ + "o_o", + "7", + ``, + ``, + `nope`, + `0.333`, + } { + var doc struct { + XMLName xml.Name `xml:"account"` + Amount Decimal `xml:"amount"` + } + err := xml.Unmarshal([]byte(testCase), &doc) + if err == nil { + t.Errorf("expected error, got %+v", doc) + } + } +} + +func TestDecimal_rescale(t *testing.T) { + type Inp struct { + int int64 + exp int32 + rescale int32 + } + tests := map[Inp]string{ + Inp{1234, -3, -5}: "1.234", + Inp{1234, -3, 0}: "1", + Inp{1234, 3, 0}: "1234000", + Inp{1234, -4, -4}: "0.1234", + } + + // add negatives + for p, s := range tests { + if p.int > 0 { + tests[Inp{-p.int, p.exp, p.rescale}] = "-" + s + } + } + + for input, s := range tests { + d := New(input.int, input.exp).rescale(input.rescale) + + if d.String() != s { + t.Errorf("expected %s, got %s (%s, %d)", + s, d.String(), + d.value.String(), d.exp) + } + + // test StringScaled + s2 := New(input.int, input.exp).StringScaled(input.rescale) + if s2 != s { + t.Errorf("expected %s, got %s", s, s2) + } + } +} + +func TestDecimal_Floor(t *testing.T) { + type testData struct { + input string + expected string + } + tests := []testData{ + {"1.999", "1"}, + {"1", "1"}, + {"1.01", "1"}, + {"0", "0"}, + {"0.9", "0"}, + {"0.1", "0"}, + {"-0.9", "-1"}, + {"-0.1", "-1"}, + {"-1.00", "-1"}, + {"-1.01", "-2"}, + {"-1.999", "-2"}, + } + for _, test := range tests { + d, _ := NewFromString(test.input) + expected, _ := NewFromString(test.expected) + got := d.Floor() + if !got.Equal(expected) { + t.Errorf("Floor(%s): got %s, expected %s", d, got, expected) + } + } +} + +func TestDecimal_Ceil(t *testing.T) { + type testData struct { + input string + expected string + } + tests := []testData{ + {"1.999", "2"}, + {"1", "1"}, + {"1.01", "2"}, + {"0", "0"}, + {"0.9", "1"}, + {"0.1", "1"}, + {"-0.9", "0"}, + {"-0.1", "0"}, + {"-1.00", "-1"}, + {"-1.01", "-1"}, + {"-1.999", "-1"}, + } + for _, test := range tests { + d, _ := NewFromString(test.input) + expected, _ := NewFromString(test.expected) + got := d.Ceil() + if !got.Equal(expected) { + t.Errorf("Ceil(%s): got %s, expected %s", d, got, expected) + } + } +} + +func TestDecimal_RoundAndStringFixed(t *testing.T) { + type testData struct { + input string + places int32 + expected string + expectedFixed string + } + tests := []testData{ + {"1.454", 0, "1", ""}, + {"1.454", 1, "1.5", ""}, + {"1.454", 2, "1.45", ""}, + {"1.454", 3, "1.454", ""}, + {"1.454", 4, "1.454", "1.4540"}, + {"1.454", 5, "1.454", "1.45400"}, + {"1.554", 0, "2", ""}, + {"1.554", 1, "1.6", ""}, + {"1.554", 2, "1.55", ""}, + {"0.554", 0, "1", ""}, + {"0.454", 0, "0", ""}, + {"0.454", 5, "0.454", "0.45400"}, + {"0", 0, "0", ""}, + {"0", 1, "0", "0.0"}, + {"0", 2, "0", "0.00"}, + {"0", -1, "0", ""}, + {"5", 2, "5", "5.00"}, + {"5", 1, "5", "5.0"}, + {"5", 0, "5", ""}, + {"500", 2, "500", "500.00"}, + {"545", -1, "550", ""}, + {"545", -2, "500", ""}, + {"545", -3, "1000", ""}, + {"545", -4, "0", ""}, + {"499", -3, "0", ""}, + {"499", -4, "0", ""}, + } + + // add negative number tests + for _, test := range tests { + expected := test.expected + if expected != "0" { + expected = "-" + expected + } + expectedStr := test.expectedFixed + if strings.ContainsAny(expectedStr, "123456789") && expectedStr != "" { + expectedStr = "-" + expectedStr + } + tests = append(tests, + testData{"-" + test.input, test.places, expected, expectedStr}) + } + + for _, test := range tests { + d, err := NewFromString(test.input) + if err != nil { + panic(err) + } + + // test Round + expected, err := NewFromString(test.expected) + if err != nil { + panic(err) + } + got := d.Round(test.places) + if !got.Equal(expected) { + t.Errorf("Rounding %s to %d places, got %s, expected %s", + d, test.places, got, expected) + } + + // test StringFixed + if test.expectedFixed == "" { + test.expectedFixed = test.expected + } + gotStr := d.StringFixed(test.places) + if gotStr != test.expectedFixed { + t.Errorf("(%s).StringFixed(%d): got %s, expected %s", + d, test.places, gotStr, test.expectedFixed) + } + } +} + +func TestDecimal_BankRoundAndStringFixed(t *testing.T) { + type testData struct { + input string + places int32 + expected string + expectedFixed string + } + tests := []testData{ + {"1.454", 0, "1", ""}, + {"1.454", 1, "1.5", ""}, + {"1.454", 2, "1.45", ""}, + {"1.454", 3, "1.454", ""}, + {"1.454", 4, "1.454", "1.4540"}, + {"1.454", 5, "1.454", "1.45400"}, + {"1.554", 0, "2", ""}, + {"1.554", 1, "1.6", ""}, + {"1.554", 2, "1.55", ""}, + {"0.554", 0, "1", ""}, + {"0.454", 0, "0", ""}, + {"0.454", 5, "0.454", "0.45400"}, + {"0", 0, "0", ""}, + {"0", 1, "0", "0.0"}, + {"0", 2, "0", "0.00"}, + {"0", -1, "0", ""}, + {"5", 2, "5", "5.00"}, + {"5", 1, "5", "5.0"}, + {"5", 0, "5", ""}, + {"500", 2, "500", "500.00"}, + {"545", -2, "500", ""}, + {"545", -3, "1000", ""}, + {"545", -4, "0", ""}, + {"499", -3, "0", ""}, + {"499", -4, "0", ""}, + {"1.45", 1, "1.4", ""}, + {"1.55", 1, "1.6", ""}, + {"1.65", 1, "1.6", ""}, + {"545", -1, "540", ""}, + {"565", -1, "560", ""}, + {"555", -1, "560", ""}, + } + + // add negative number tests + for _, test := range tests { + expected := test.expected + if expected != "0" { + expected = "-" + expected + } + expectedStr := test.expectedFixed + if strings.ContainsAny(expectedStr, "123456789") && expectedStr != "" { + expectedStr = "-" + expectedStr + } + tests = append(tests, + testData{"-" + test.input, test.places, expected, expectedStr}) + } + + for _, test := range tests { + d, err := NewFromString(test.input) + if err != nil { + panic(err) + } + + // test Round + expected, err := NewFromString(test.expected) + if err != nil { + panic(err) + } + got := d.RoundBank(test.places) + if !got.Equal(expected) { + t.Errorf("Bank Rounding %s to %d places, got %s, expected %s", + d, test.places, got, expected) + } + + // test StringFixed + if test.expectedFixed == "" { + test.expectedFixed = test.expected + } + gotStr := d.StringFixedBank(test.places) + if gotStr != test.expectedFixed { + t.Errorf("(%s).StringFixed(%d): got %s, expected %s", + d, test.places, gotStr, test.expectedFixed) + } + } +} + +func TestDecimal_Uninitialized(t *testing.T) { + a := Decimal{} + b := Decimal{} + + decs := []Decimal{ + a, + a.rescale(10), + a.Abs(), + a.Add(b), + a.Sub(b), + a.Mul(b), + a.Div(New(1, -1)), + a.Round(2), + a.Floor(), + a.Ceil(), + a.Truncate(2), + } + + for _, d := range decs { + if d.String() != "0" { + t.Errorf("expected 0, got %s", d.String()) + } + if d.StringFixed(3) != "0.000" { + t.Errorf("expected 0, got %s", d.StringFixed(3)) + } + if d.StringScaled(-2) != "0" { + t.Errorf("expected 0, got %s", d.StringScaled(-2)) + } + } + + if a.Cmp(b) != 0 { + t.Errorf("a != b") + } + if a.Sign() != 0 { + t.Errorf("a.Sign() != 0") + } + if a.Exponent() != 0 { + t.Errorf("a.Exponent() != 0") + } + if a.IntPart() != 0 { + t.Errorf("a.IntPar() != 0") + } + f, _ := a.Float64() + if f != 0 { + t.Errorf("a.Float64() != 0") + } + if a.Rat().RatString() != "0" { + t.Errorf("a.Rat() != 0, got %s", a.Rat().RatString()) + } +} + +func TestDecimal_Add(t *testing.T) { + type Inp struct { + a string + b string + } + + inputs := map[Inp]string{ + Inp{"2", "3"}: "5", + Inp{"2454495034", "3451204593"}: "5905699627", + Inp{"24544.95034", ".3451204593"}: "24545.2954604593", + Inp{".1", ".1"}: "0.2", + Inp{".1", "-.1"}: "0", + Inp{"0", "1.001"}: "1.001", + } + + for inp, res := range inputs { + a, err := NewFromString(inp.a) + if err != nil { + t.FailNow() + } + b, err := NewFromString(inp.b) + if err != nil { + t.FailNow() + } + c := a.Add(b) + if c.String() != res { + t.Errorf("expected %s, got %s", res, c.String()) + } + } +} + +func TestDecimal_Sub(t *testing.T) { + type Inp struct { + a string + b string + } + + inputs := map[Inp]string{ + Inp{"2", "3"}: "-1", + Inp{"12", "3"}: "9", + Inp{"-2", "9"}: "-11", + Inp{"2454495034", "3451204593"}: "-996709559", + Inp{"24544.95034", ".3451204593"}: "24544.6052195407", + Inp{".1", "-.1"}: "0.2", + Inp{".1", ".1"}: "0", + Inp{"0", "1.001"}: "-1.001", + Inp{"1.001", "0"}: "1.001", + Inp{"2.3", ".3"}: "2", + } + + for inp, res := range inputs { + a, err := NewFromString(inp.a) + if err != nil { + t.FailNow() + } + b, err := NewFromString(inp.b) + if err != nil { + t.FailNow() + } + c := a.Sub(b) + if c.String() != res { + t.Errorf("expected %s, got %s", res, c.String()) + } + } +} + +func TestDecimal_Neg(t *testing.T) { + inputs := map[string]string{ + "0": "0", + "10": "-10", + "5.56": "-5.56", + "-10": "10", + "-5.56": "5.56", + } + + for inp, res := range inputs { + a, err := NewFromString(inp) + if err != nil { + t.FailNow() + } + b := a.Neg() + if b.String() != res { + t.Errorf("expected %s, got %s", res, b.String()) + } + } +} + +func TestDecimal_Mul(t *testing.T) { + type Inp struct { + a string + b string + } + + inputs := map[Inp]string{ + Inp{"2", "3"}: "6", + Inp{"2454495034", "3451204593"}: "8470964534836491162", + Inp{"24544.95034", ".3451204593"}: "8470.964534836491162", + Inp{".1", ".1"}: "0.01", + Inp{"0", "1.001"}: "0", + } + + for inp, res := range inputs { + a, err := NewFromString(inp.a) + if err != nil { + t.FailNow() + } + b, err := NewFromString(inp.b) + if err != nil { + t.FailNow() + } + c := a.Mul(b) + if c.String() != res { + t.Errorf("expected %s, got %s", res, c.String()) + } + } + + // positive scale + c := New(1234, 5).Mul(New(45, -1)) + if c.String() != "555300000" { + t.Errorf("Expected %s, got %s", "555300000", c.String()) + } +} + +func TestDecimal_Div(t *testing.T) { + type Inp struct { + a string + b string + } + + inputs := map[Inp]string{ + Inp{"6", "3"}: "2", + Inp{"10", "2"}: "5", + Inp{"2.2", "1.1"}: "2", + Inp{"-2.2", "-1.1"}: "2", + Inp{"12.88", "5.6"}: "2.3", + Inp{"1023427554493", "43432632"}: "23563.5628642767953828", // rounded + Inp{"1", "434324545566634"}: "0.0000000000000023", + Inp{"1", "3"}: "0.3333333333333333", + Inp{"2", "3"}: "0.6666666666666667", // rounded + Inp{"10000", "3"}: "3333.3333333333333333", + Inp{"10234274355545544493", "-3"}: "-3411424785181848164.3333333333333333", + Inp{"-4612301402398.4753343454", "23.5"}: "-196268144782.9138440146978723", + } + + for inp, expectedStr := range inputs { + num, err := NewFromString(inp.a) + if err != nil { + t.FailNow() + } + denom, err := NewFromString(inp.b) + if err != nil { + t.FailNow() + } + got := num.Div(denom) + expected, _ := NewFromString(expectedStr) + if !got.Equal(expected) { + t.Errorf("expected %v when dividing %v by %v, got %v", + expected, num, denom, got) + } + got2 := num.DivRound(denom, int32(DivisionPrecision)) + if !got2.Equal(expected) { + t.Errorf("expected %v on DivRound (%v,%v), got %v", expected, num, denom, got2) + } + } + + type Inp2 struct { + n int64 + exp int32 + n2 int64 + exp2 int32 + } + + // test code path where exp > 0 + inputs2 := map[Inp2]string{ + Inp2{124, 10, 3, 1}: "41333333333.3333333333333333", + Inp2{124, 10, 3, 0}: "413333333333.3333333333333333", + Inp2{124, 10, 6, 1}: "20666666666.6666666666666667", + Inp2{124, 10, 6, 0}: "206666666666.6666666666666667", + Inp2{10, 10, 10, 1}: "1000000000", + } + + for inp, expectedAbs := range inputs2 { + for i := -1; i <= 1; i += 2 { + for j := -1; j <= 1; j += 2 { + n := inp.n * int64(i) + n2 := inp.n2 * int64(j) + num := New(n, inp.exp) + denom := New(n2, inp.exp2) + expected := expectedAbs + if i != j { + expected = "-" + expectedAbs + } + got := num.Div(denom) + if got.String() != expected { + t.Errorf("expected %s when dividing %v by %v, got %v", + expected, num, denom, got) + } + } + } + } +} + +func TestDecimal_QuoRem(t *testing.T) { + type Inp4 struct { + d string + d2 string + exp int32 + q string + r string + } + cases := []Inp4{ + {"10", "1", 0, "10", "0"}, + {"1", "10", 0, "0", "1"}, + {"1", "4", 2, "0.25", "0"}, + {"1", "8", 2, "0.12", "0.04"}, + {"10", "3", 1, "3.3", "0.1"}, + {"100", "3", 1, "33.3", "0.1"}, + {"1000", "10", -3, "0", "1000"}, + {"1e-3", "2e-5", 0, "50", "0"}, + {"1e-3", "2e-3", 1, "0.5", "0"}, + {"4e-3", "0.8", 4, "5e-3", "0"}, + {"4.1e-3", "0.8", 3, "5e-3", "1e-4"}, + {"-4", "-3", 0, "1", "-1"}, + {"-4", "3", 0, "-1", "-1"}, + } + + for _, inp4 := range cases { + d, _ := NewFromString(inp4.d) + d2, _ := NewFromString(inp4.d2) + prec := inp4.exp + q, r := d.QuoRem(d2, prec) + expectedQ, _ := NewFromString(inp4.q) + expectedR, _ := NewFromString(inp4.r) + if !q.Equal(expectedQ) || !r.Equal(expectedR) { + t.Errorf("bad QuoRem division %s , %s , %d got %v, %v expected %s , %s", + inp4.d, inp4.d2, prec, q, r, inp4.q, inp4.r) + } + if !d.Equal(d2.Mul(q).Add(r)) { + t.Errorf("not fitting: d=%v, d2= %v, prec=%d, q=%v, r=%v", + d, d2, prec, q, r) + } + if !q.Equal(q.Truncate(prec)) { + t.Errorf("quotient wrong precision: d=%v, d2= %v, prec=%d, q=%v, r=%v", + d, d2, prec, q, r) + } + if r.Abs().Cmp(d2.Abs().Mul(New(1, -prec))) >= 0 { + t.Errorf("remainder too large: d=%v, d2= %v, prec=%d, q=%v, r=%v", + d, d2, prec, q, r) + } + if r.value.Sign()*d.value.Sign() < 0 { + t.Errorf("signum of divisor and rest do not match: d=%v, d2= %v, prec=%d, q=%v, r=%v", + d, d2, prec, q, r) + } + } +} + +type DivTestCase struct { + d Decimal + d2 Decimal + prec int32 +} + +func createDivTestCases() []DivTestCase { + res := make([]DivTestCase, 0) + var n int32 = 5 + a := []int{1, 2, 3, 6, 7, 10, 100, 14, 5, 400, 0, 1000000, 1000000 + 1, 1000000 - 1} + for s := -1; s < 2; s = s + 2 { // 2 + for s2 := -1; s2 < 2; s2 = s2 + 2 { // 2 + for e1 := -n; e1 <= n; e1++ { // 2n+1 + for e2 := -n; e2 <= n; e2++ { // 2n+1 + var prec int32 + for prec = -n; prec <= n; prec++ { // 2n+1 + for _, v1 := range a { // 11 + for _, v2 := range a { // 11, even if 0 is skipped + sign1 := New(int64(s), 0) + sign2 := New(int64(s2), 0) + d := sign1.Mul(New(int64(v1), int32(e1))) + d2 := sign2.Mul(New(int64(v2), int32(e2))) + res = append(res, DivTestCase{d, d2, prec}) + } + } + } + } + } + } + } + return res +} + +func TestDecimal_QuoRem2(t *testing.T) { + for _, tc := range createDivTestCases() { + d := tc.d + if sign(tc.d2) == 0 { + continue + } + d2 := tc.d2 + prec := tc.prec + q, r := d.QuoRem(d2, prec) + // rule 1: d = d2*q +r + if !d.Equal(d2.Mul(q).Add(r)) { + t.Errorf("not fitting, d=%v, d2=%v, prec=%d, q=%v, r=%v", + d, d2, prec, q, r) + } + // rule 2: q is integral multiple of 10^(-prec) + if !q.Equal(q.Truncate(prec)) { + t.Errorf("quotient wrong precision, d=%v, d2=%v, prec=%d, q=%v, r=%v", + d, d2, prec, q, r) + } + // rule 3: abs(r)= 0 { + t.Errorf("remainder too large, d=%v, d2=%v, prec=%d, q=%v, r=%v", + d, d2, prec, q, r) + } + // rule 4: r and d have the same sign + if r.value.Sign()*d.value.Sign() < 0 { + t.Errorf("signum of divisor and rest do not match, "+ + "d=%v, d2=%v, prec=%d, q=%v, r=%v", + d, d2, prec, q, r) + } + } +} + +// this is the old Div method from decimal +// Div returns d / d2. If it doesn't divide exactly, the result will have +// DivisionPrecision digits after the decimal point. +func (d Decimal) DivOld(d2 Decimal, prec int) Decimal { + // NOTE(vadim): division is hard, use Rat to do it + ratNum := d.Rat() + ratDenom := d2.Rat() + + quoRat := big.NewRat(0, 1).Quo(ratNum, ratDenom) + + // HACK(vadim): converting from Rat to Decimal inefficiently for now + ret, err := NewFromString(quoRat.FloatString(prec)) + if err != nil { + panic(err) // this should never happen + } + return ret +} + +func Benchmark_DivideOriginal(b *testing.B) { + tcs := createDivTestCases() + b.ResetTimer() + for i := 0; i < b.N; i++ { + for _, tc := range tcs { + d := tc.d + if sign(tc.d2) == 0 { + continue + } + d2 := tc.d2 + prec := tc.prec + a := d.DivOld(d2, int(prec)) + if sign(a) > 2 { + panic("dummy panic") + } + } + } +} + +func Benchmark_DivideNew(b *testing.B) { + tcs := createDivTestCases() + b.ResetTimer() + for i := 0; i < b.N; i++ { + for _, tc := range tcs { + d := tc.d + if sign(tc.d2) == 0 { + continue + } + d2 := tc.d2 + prec := tc.prec + a := d.DivRound(d2, prec) + if sign(a) > 2 { + panic("dummy panic") + } + } + } +} + +func sign(d Decimal) int { + return d.value.Sign() +} + +// rules for rounded divide, rounded to integer +// rounded_divide(d,d2) = q +// sign q * sign (d/d2) >= 0 +// for d and d2 >0 : +// q is already rounded +// q = d/d2 + r , with r > -0.5 and r <= 0.5 +// thus q-d/d2 = r, with r > -0.5 and r <= 0.5 +// and d2 q -d = r d2 with r d2 > -d2/2 and r d2 <= d2/2 +// and 2 (d2 q -d) = x with x > -d2 and x <= d2 +// if we factor in precision then x > -d2 * 10^(-precision) and x <= d2 * 10(-precision) + +func TestDecimal_DivRound(t *testing.T) { + cases := []struct { + d string + d2 string + prec int32 + result string + }{ + {"2", "2", 0, "1"}, + {"1", "2", 0, "1"}, + {"-1", "2", 0, "-1"}, + {"-1", "-2", 0, "1"}, + {"1", "-2", 0, "-1"}, + {"1", "-20", 1, "-0.1"}, + {"1", "-20", 2, "-0.05"}, + {"1", "20.0000000000000000001", 1, "0"}, + {"1", "19.9999999999999999999", 1, "0.1"}, + } + for _, s := range cases { + d, _ := NewFromString(s.d) + d2, _ := NewFromString(s.d2) + result, _ := NewFromString(s.result) + prec := s.prec + q := d.DivRound(d2, prec) + if sign(q)*sign(d)*sign(d2) < 0 { + t.Errorf("sign of quotient wrong, got: %v/%v is about %v", d, d2, q) + } + x := q.Mul(d2).Abs().Sub(d.Abs()).Mul(New(2, 0)) + if x.Cmp(d2.Abs().Mul(New(1, -prec))) > 0 { + t.Errorf("wrong rounding, got: %v/%v prec=%d is about %v", d, d2, prec, q) + } + if x.Cmp(d2.Abs().Mul(New(-1, -prec))) <= 0 { + t.Errorf("wrong rounding, got: %v/%v prec=%d is about %v", d, d2, prec, q) + } + if !q.Equal(result) { + t.Errorf("rounded division wrong %s / %s scale %d = %s, got %v", s.d, s.d2, prec, s.result, q) + } + } +} + +func TestDecimal_DivRound2(t *testing.T) { + for _, tc := range createDivTestCases() { + d := tc.d + if sign(tc.d2) == 0 { + continue + } + d2 := tc.d2 + prec := tc.prec + q := d.DivRound(d2, prec) + if sign(q)*sign(d)*sign(d2) < 0 { + t.Errorf("sign of quotient wrong, got: %v/%v is about %v", d, d2, q) + } + x := q.Mul(d2).Abs().Sub(d.Abs()).Mul(New(2, 0)) + if x.Cmp(d2.Abs().Mul(New(1, -prec))) > 0 { + t.Errorf("wrong rounding, got: %v/%v prec=%d is about %v", d, d2, prec, q) + } + if x.Cmp(d2.Abs().Mul(New(-1, -prec))) <= 0 { + t.Errorf("wrong rounding, got: %v/%v prec=%d is about %v", d, d2, prec, q) + } + } +} + +func TestDecimal_Mod(t *testing.T) { + type Inp struct { + a string + b string + } + + inputs := map[Inp]string{ + Inp{"3", "2"}: "1", + Inp{"3451204593", "2454495034"}: "996709559", + Inp{"24544.95034", ".3451204593"}: "0.3283950433", + Inp{".1", ".1"}: "0", + Inp{"0", "1.001"}: "0", + Inp{"-7.5", "2"}: "-1.5", + Inp{"7.5", "-2"}: "1.5", + Inp{"-7.5", "-2"}: "-1.5", + } + + for inp, res := range inputs { + a, err := NewFromString(inp.a) + if err != nil { + t.FailNow() + } + b, err := NewFromString(inp.b) + if err != nil { + t.FailNow() + } + c := a.Mod(b) + if c.String() != res { + t.Errorf("expected %s, got %s", res, c.String()) + } + } +} + +func TestDecimal_Overflow(t *testing.T) { + if !didPanic(func() { New(1, math.MinInt32).Mul(New(1, math.MinInt32)) }) { + t.Fatalf("should have gotten an overflow panic") + } + if !didPanic(func() { New(1, math.MaxInt32).Mul(New(1, math.MaxInt32)) }) { + t.Fatalf("should have gotten an overflow panic") + } +} + +func TestDecimal_ExtremeValues(t *testing.T) { + // NOTE(vadim): this test takes pretty much forever + if testing.Short() { + t.Skip() + } + + // NOTE(vadim): Seriously, the numbers involved are so large that this + // test will take way too long, so mark it as success if it takes over + // 1 second. The way this test typically fails (integer overflow) is that + // a wrong result appears quickly, so if it takes a long time then it is + // probably working properly. + // Why even bother testing this? Completeness, I guess. -Vadim + const timeLimit = 1 * time.Second + test := func(f func()) { + c := make(chan bool) + go func() { + f() + close(c) + }() + select { + case <-c: + case <-time.After(timeLimit): + } + } + + test(func() { + got := New(123, math.MinInt32).Floor() + if !got.Equal(NewFromFloat(0)) { + t.Errorf("Error: got %s, expected 0", got) + } + }) + test(func() { + got := New(123, math.MinInt32).Ceil() + if !got.Equal(NewFromFloat(1)) { + t.Errorf("Error: got %s, expected 1", got) + } + }) + test(func() { + got := New(123, math.MinInt32).Rat().FloatString(10) + expected := "0.0000000000" + if got != expected { + t.Errorf("Error: got %s, expected %s", got, expected) + } + }) +} + +func TestIntPart(t *testing.T) { + for _, testCase := range []struct { + Dec string + IntPart int64 + }{ + {"0.01", 0}, + {"12.1", 12}, + {"9999.999", 9999}, + {"-32768.01234", -32768}, + } { + d, err := NewFromString(testCase.Dec) + if err != nil { + t.Fatal(err) + } + if d.IntPart() != testCase.IntPart { + t.Errorf("expect %d, got %d", testCase.IntPart, d.IntPart()) + } + } +} + +func TestDecimal_Min(t *testing.T) { + // the first element in the array is the expected answer, rest are inputs + testCases := [][]float64{ + {0, 0}, + {1, 1}, + {-1, -1}, + {1, 1, 2}, + {-2, 1, 2, -2}, + {-3, 0, 2, -2, -3}, + } + + for _, test := range testCases { + expected, input := test[0], test[1:] + expectedDecimal := NewFromFloat(expected) + decimalInput := []Decimal{} + for _, inp := range input { + d := NewFromFloat(inp) + decimalInput = append(decimalInput, d) + } + got := Min(decimalInput[0], decimalInput[1:]...) + if !got.Equal(expectedDecimal) { + t.Errorf("Expected %v, got %v, input=%+v", expectedDecimal, got, + decimalInput) + } + } +} + +func TestDecimal_Max(t *testing.T) { + // the first element in the array is the expected answer, rest are inputs + testCases := [][]float64{ + {0, 0}, + {1, 1}, + {-1, -1}, + {2, 1, 2}, + {2, 1, 2, -2}, + {3, 0, 3, -2}, + {-2, -3, -2}, + } + + for _, test := range testCases { + expected, input := test[0], test[1:] + expectedDecimal := NewFromFloat(expected) + decimalInput := []Decimal{} + for _, inp := range input { + d := NewFromFloat(inp) + decimalInput = append(decimalInput, d) + } + got := Max(decimalInput[0], decimalInput[1:]...) + if !got.Equal(expectedDecimal) { + t.Errorf("Expected %v, got %v, input=%+v", expectedDecimal, got, + decimalInput) + } + } +} + +func TestDecimal_Scan(t *testing.T) { + // test the Scan method that implements the + // sql.Scanner interface + // check for the for different type of values + // that are possible to be received from the database + // drivers + + // in normal operations the db driver (sqlite at least) + // will return an int64 if you specified a numeric format + a := Decimal{} + dbvalue := float64(54.33) + expected := NewFromFloat(dbvalue) + + err := a.Scan(dbvalue) + if err != nil { + // Scan failed... no need to test result value + t.Errorf("a.Scan(54.33) failed with message: %s", err) + + } else { + // Scan succeeded... test resulting values + if !a.Equal(expected) { + t.Errorf("%s does not equal to %s", a, expected) + } + } + + // apparently MySQL 5.7.16 and returns these as float32 so we need + // to handle these as well + dbvalueFloat32 := float32(54.33) + expected = NewFromFloat(float64(dbvalueFloat32)) + + err = a.Scan(dbvalueFloat32) + if err != nil { + // Scan failed... no need to test result value + t.Errorf("a.Scan(54.33) failed with message: %s", err) + + } else { + // Scan succeeded... test resulting values + if !a.Equal(expected) { + t.Errorf("%s does not equal to %s", a, expected) + } + } + + // at least SQLite returns an int64 when 0 is stored in the db + // and you specified a numeric format on the schema + dbvalueInt := int64(0) + expected = New(dbvalueInt, 0) + + err = a.Scan(dbvalueInt) + if err != nil { + // Scan failed... no need to test result value + t.Errorf("a.Scan(0) failed with message: %s", err) + + } else { + // Scan succeeded... test resulting values + if !a.Equal(expected) { + t.Errorf("%s does not equal to %s", a, expected) + } + } + + // in case you specified a varchar in your SQL schema, + // the database driver will return byte slice []byte + valueStr := "535.666" + dbvalueStr := []byte(valueStr) + expected, err = NewFromString(valueStr) + if err != nil { + t.Fatal(err) + } + + err = a.Scan(dbvalueStr) + if err != nil { + // Scan failed... no need to test result value + t.Errorf("a.Scan('535.666') failed with message: %s", err) + + } else { + // Scan succeeded... test resulting values + if !a.Equal(expected) { + t.Errorf("%s does not equal to %s", a, expected) + } + } + + // lib/pq can also return strings + expected, err = NewFromString(valueStr) + if err != nil { + t.Fatal(err) + } + + err = a.Scan(valueStr) + if err != nil { + // Scan failed... no need to test result value + t.Errorf("a.Scan('535.666') failed with message: %s", err) + } else { + // Scan succeeded... test resulting values + if !a.Equal(expected) { + t.Errorf("%s does not equal to %s", a, expected) + } + } + + type foo struct{} + err = a.Scan(foo{}) + if err == nil { + t.Errorf("a.Scan(Foo{}) should have thrown an error but did not") + } +} + +func TestDecimal_Value(t *testing.T) { + // Make sure this does implement the database/sql's driver.Valuer interface + var d Decimal + if _, ok := interface{}(d).(driver.Valuer); !ok { + t.Error("Decimal does not implement driver.Valuer") + } + + // check that normal case is handled appropriately + a := New(1234, -2) + expected := "12.34" + value, err := a.Value() + if err != nil { + t.Errorf("Decimal(12.34).Value() failed with message: %s", err) + } else if value.(string) != expected { + t.Errorf("%s does not equal to %s", a, expected) + } +} + +// old tests after this line + +func TestDecimal_Scale(t *testing.T) { + a := New(1234, -3) + if a.Exponent() != -3 { + t.Errorf("error") + } +} + +func TestDecimal_Abs1(t *testing.T) { + a := New(-1234, -4) + b := New(1234, -4) + + c := a.Abs() + if c.Cmp(b) != 0 { + t.Errorf("error") + } +} + +func TestDecimal_Abs2(t *testing.T) { + a := New(-1234, -4) + b := New(1234, -4) + + c := b.Abs() + if c.Cmp(a) == 0 { + t.Errorf("error") + } +} + +func TestDecimal_Equalities(t *testing.T) { + a := New(1234, 3) + b := New(1234, 3) + c := New(1234, 4) + + if !a.Equal(b) { + t.Errorf("%q should equal %q", a, b) + } + if a.Equal(c) { + t.Errorf("%q should not equal %q", a, c) + } + + // note, this block should be deprecated, here for backwards compatibility + if !a.Equals(b) { + t.Errorf("%q should equal %q", a, b) + } + + if !c.GreaterThan(b) { + t.Errorf("%q should be greater than %q", c, b) + } + if b.GreaterThan(c) { + t.Errorf("%q should not be greater than %q", b, c) + } + if !a.GreaterThanOrEqual(b) { + t.Errorf("%q should be greater or equal %q", a, b) + } + if !c.GreaterThanOrEqual(b) { + t.Errorf("%q should be greater or equal %q", c, b) + } + if b.GreaterThanOrEqual(c) { + t.Errorf("%q should not be greater or equal %q", b, c) + } + if !b.LessThan(c) { + t.Errorf("%q should be less than %q", a, b) + } + if c.LessThan(b) { + t.Errorf("%q should not be less than %q", a, b) + } + if !a.LessThanOrEqual(b) { + t.Errorf("%q should be less than or equal %q", a, b) + } + if !b.LessThanOrEqual(c) { + t.Errorf("%q should be less than or equal %q", a, b) + } + if c.LessThanOrEqual(b) { + t.Errorf("%q should not be less than or equal %q", a, b) + } +} + +func TestDecimal_ScalesNotEqual(t *testing.T) { + a := New(1234, 2) + b := New(1234, 3) + if a.Equal(b) { + t.Errorf("%q should not equal %q", a, b) + } +} + +func TestDecimal_Cmp1(t *testing.T) { + a := New(123, 3) + b := New(-1234, 2) + + if a.Cmp(b) != 1 { + t.Errorf("Error") + } +} + +func TestDecimal_Cmp2(t *testing.T) { + a := New(123, 3) + b := New(1234, 2) + + if a.Cmp(b) != -1 { + t.Errorf("Error") + } +} + +func TestPow(t *testing.T) { + a := New(4, 0) + b := New(2, 0) + x := a.Pow(b) + if x.String() != "16" { + t.Errorf("Error, saw %s", x.String()) + } +} + +func TestNegativePow(t *testing.T) { + a := New(4, 0) + b := New(-2, 0) + x := a.Pow(b) + if x.String() != "0.0625" { + t.Errorf("Error, saw %s", x.String()) + } +} + +func TestDecimal_Sign(t *testing.T) { + if Zero.Sign() != 0 { + t.Errorf("%q should have sign 0", Zero) + } + + one := New(1, 0) + if one.Sign() != 1 { + t.Errorf("%q should have sign 1", one) + } + + mone := New(-1, 0) + if mone.Sign() != -1 { + t.Errorf("%q should have sign -1", mone) + } +} + +func didPanic(f func()) bool { + ret := false + func() { + + defer func() { + if message := recover(); message != nil { + ret = true + } + }() + + // call the target function + f() + + }() + + return ret + +} + +func TestDecimal_Coefficient(t *testing.T) { + d := New(123, 0) + co := d.Coefficient() + if co.Int64() != 123 { + t.Error("Coefficient should be 123; Got:", co) + } + co.Set(big.NewInt(0)) + if d.IntPart() != 123 { + t.Error("Modifying coefficient modified Decimal; Got:", d) + } +} + +type DecimalSlice []Decimal + +func (p DecimalSlice) Len() int { return len(p) } +func (p DecimalSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } +func (p DecimalSlice) Less(i, j int) bool { return p[i].Cmp(p[j]) < 0 } +func Benchmark_Cmp(b *testing.B) { + decimals := DecimalSlice([]Decimal{}) + for i := 0; i < 1000000; i++ { + decimals = append(decimals, New(int64(i), 0)) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + sort.Sort(decimals) + } +} + +func TestNullDecimal_Scan(t *testing.T) { + // test the Scan method that implements the + // sql.Scanner interface + // check for the for different type of values + // that are possible to be received from the database + // drivers + + // in normal operations the db driver (sqlite at least) + // will return an int64 if you specified a numeric format + + // Make sure handles nil values + a := NullDecimal{} + var dbvaluePtr interface{} + err := a.Scan(dbvaluePtr) + if err != nil { + // Scan failed... no need to test result value + t.Errorf("a.Scan(nil) failed with message: %s", err) + } else { + if a.Valid { + t.Errorf("%s is not null", a.Decimal) + } + } + + dbvalue := float64(54.33) + expected := NewFromFloat(dbvalue) + + err = a.Scan(dbvalue) + if err != nil { + // Scan failed... no need to test result value + t.Errorf("a.Scan(54.33) failed with message: %s", err) + + } else { + // Scan succeeded... test resulting values + if !a.Valid { + t.Errorf("%s is null", a.Decimal) + } else if !a.Decimal.Equals(expected) { + t.Errorf("%s does not equal to %s", a.Decimal, expected) + } + } + + // at least SQLite returns an int64 when 0 is stored in the db + // and you specified a numeric format on the schema + dbvalueInt := int64(0) + expected = New(dbvalueInt, 0) + + err = a.Scan(dbvalueInt) + if err != nil { + // Scan failed... no need to test result value + t.Errorf("a.Scan(0) failed with message: %s", err) + + } else { + // Scan succeeded... test resulting values + if !a.Valid { + t.Errorf("%s is null", a.Decimal) + } else if !a.Decimal.Equals(expected) { + t.Errorf("%v does not equal %v", a, expected) + } + } + + // in case you specified a varchar in your SQL schema, + // the database driver will return byte slice []byte + valueStr := "535.666" + dbvalueStr := []byte(valueStr) + expected, err = NewFromString(valueStr) + if err != nil { + t.Fatal(err) + } + + err = a.Scan(dbvalueStr) + if err != nil { + // Scan failed... no need to test result value + t.Errorf("a.Scan('535.666') failed with message: %s", err) + + } else { + // Scan succeeded... test resulting values + if !a.Valid { + t.Errorf("%s is null", a.Decimal) + } else if !a.Decimal.Equals(expected) { + t.Errorf("%v does not equal %v", a, expected) + } + } + + // lib/pq can also return strings + expected, err = NewFromString(valueStr) + if err != nil { + t.Fatal(err) + } + + err = a.Scan(valueStr) + if err != nil { + // Scan failed... no need to test result value + t.Errorf("a.Scan('535.666') failed with message: %s", err) + } else { + // Scan succeeded... test resulting values + if !a.Valid { + t.Errorf("%s is null", a.Decimal) + } else if !a.Decimal.Equals(expected) { + t.Errorf("%v does not equal %v", a, expected) + } + } +} + +func TestNullDecimal_Value(t *testing.T) { + // Make sure this does implement the database/sql's driver.Valuer interface + var nullDecimal NullDecimal + if _, ok := interface{}(nullDecimal).(driver.Valuer); !ok { + t.Error("NullDecimal does not implement driver.Valuer") + } + + // check that null is handled appropriately + value, err := nullDecimal.Value() + if err != nil { + t.Errorf("NullDecimal{}.Valid() failed with message: %s", err) + } else if value != nil { + t.Errorf("%v is not nil", value) + } + + // check that normal case is handled appropriately + a := NullDecimal{Decimal: New(1234, -2), Valid: true} + expected := "12.34" + value, err = a.Value() + if err != nil { + t.Errorf("NullDecimal(12.34).Value() failed with message: %s", err) + } else if value.(string) != expected { + t.Errorf("%v does not equal %v", a, expected) + } +} + +func TestBinary(t *testing.T) { + for x := range testTable { + + // Create the decimal + d1 := NewFromFloat(x) + + // Encode to binary + b, err := d1.MarshalBinary() + if err != nil { + t.Errorf("error marshalling %v to binary: %v", d1, err) + } + + // Restore from binary + var d2 Decimal + err = (&d2).UnmarshalBinary(b) + if err != nil { + t.Errorf("error unmarshalling from binary: %v", err) + } + + // The restored decimal should equal the original + if !d1.Equals(d2) { + t.Errorf("expected %v when restoring, got %v", d1, d2) + } + } +} + +func slicesEqual(a, b []byte) bool { + for i, val := range a { + if b[i] != val { + return false + } + } + return true +} + +func TestGobEncode(t *testing.T) { + for x := range testTable { + d1 := NewFromFloat(x) + + b1, err := d1.GobEncode() + if err != nil { + t.Errorf("error encoding %v to binary: %v", d1, err) + } + + d2 := NewFromFloat(x) + + b2, err := d2.GobEncode() + if err != nil { + t.Errorf("error encoding %v to binary: %v", d2, err) + } + + if !slicesEqual(b1, b2) { + t.Errorf("something about the gobencode is not working properly \n%v\n%v", b1, b2) + } + + var d3 Decimal + err = d3.GobDecode(b1) + if err != nil { + t.Errorf("Error gobdecoding %v, got %v", b1, d3) + } + var d4 Decimal + err = d4.GobDecode(b2) + if err != nil { + t.Errorf("Error gobdecoding %v, got %v", b2, d4) + } + + eq := d3.Equal(d4) + if eq != true { + t.Errorf("Encoding then decoding mutated Decimal") + } + + eq = d1.Equal(d3) + if eq != true { + t.Errorf("Error gobencoding/decoding %v, got %v", d1, d3) + } + } +} + +func TestSum(t *testing.T) { + vals := make([]Decimal, 10) + var i = int64(0) + + for key := range vals { + vals[key] = New(i, 0) + i++ + } + + sum := Sum(vals[0], vals[1:]...) + if !sum.Equal(New(45, 0)) { + t.Errorf("Failed to calculate sum, expected %s got %s", New(45, 0), sum) + } +} + +func TestAvg(t *testing.T) { + vals := make([]Decimal, 10) + var i = int64(0) + + for key := range vals { + vals[key] = New(i, 0) + i++ + } + + avg := Avg(vals[0], vals[1:]...) + if !avg.Equal(NewFromFloat(4.5)) { + t.Errorf("Failed to calculate average, expected %s got %s", NewFromFloat(4.5).String(), avg.String()) + } +} diff --git a/vendor/vendor.json b/vendor/vendor.json deleted file mode 100644 index 65eeed5..0000000 --- a/vendor/vendor.json +++ /dev/null @@ -1,223 +0,0 @@ -{ - "comment": "", - "ignore": "test", - "package": [ - { - "checksumSHA1": "DxlaH8a97aZfSv1dgzeWc7BKzg4=", - "path": "github.com/quickfixgo/quickfix", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "NQgdlqwOrvqucQgRp8ezqkWJEeo=", - "path": "github.com/quickfixgo/quickfix/config", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "xI+yIzVkLijTjZSLMj7FYjlYbJ4=", - "path": "github.com/quickfixgo/quickfix/datadictionary", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-08-16T20:57:37Z" - }, - { - "checksumSHA1": "NIh1muEqHUoO7Jcky+KDd5nElAQ=", - "path": "github.com/quickfixgo/quickfix/enum", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "TB2abZADXugxIkbseqFmnnS821E=", - "path": "github.com/quickfixgo/quickfix/field", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "v5pkXnW1+UzK2aEPyv7zKkqBub0=", - "path": "github.com/quickfixgo/quickfix/fix40", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-08-16T20:57:37Z" - }, - { - "checksumSHA1": "qyl5O2jnA30XF/h3wSe9lbp2N7s=", - "path": "github.com/quickfixgo/quickfix/fix40/executionreport", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "jHOKn15jML2XFGW9bQQoEOVu4hA=", - "path": "github.com/quickfixgo/quickfix/fix40/newordersingle", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "gsCkQFFG8teA6kmdvR0DaB3EQnw=", - "path": "github.com/quickfixgo/quickfix/fix40/ordercancelrequest", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "pdgeg/euHhaSXCYfLdSREydWUVg=", - "path": "github.com/quickfixgo/quickfix/fix41", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-08-16T20:57:37Z" - }, - { - "checksumSHA1": "KPhJqMf+x/7JJwdZc/apTjr3Iis=", - "path": "github.com/quickfixgo/quickfix/fix41/executionreport", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "Bk/sHSuahmFAZYSDM90GA6t0qgQ=", - "path": "github.com/quickfixgo/quickfix/fix41/newordersingle", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "Wrz4yIMed+ZlZiRDHIMliUwycFg=", - "path": "github.com/quickfixgo/quickfix/fix41/ordercancelrequest", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "UBMxVv8PBZ1SlEpQruRkiSvYlEo=", - "path": "github.com/quickfixgo/quickfix/fix42", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "XrCfGng+UQWnLFwgeXzxHXObSzo=", - "path": "github.com/quickfixgo/quickfix/fix42/executionreport", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "PJhVa3k+7brYbypZri3QvcXBiJM=", - "path": "github.com/quickfixgo/quickfix/fix42/marketdatarequest", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "Cfv6PFo3tlPXYHO4h6ppxoBhbbA=", - "path": "github.com/quickfixgo/quickfix/fix42/newordersingle", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "rkZ9PLSLksCvG0EBk6M2mpQShQQ=", - "path": "github.com/quickfixgo/quickfix/fix42/ordercancelrequest", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "YE/g1JwGQSPffl6gmZZuqjfHFvY=", - "path": "github.com/quickfixgo/quickfix/fix43", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-08-16T20:57:37Z" - }, - { - "checksumSHA1": "2hKxpurYYE3C+y4HabXxpv4GxQE=", - "path": "github.com/quickfixgo/quickfix/fix43/executionreport", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "r1O8TMQEkblkOCYxWNpD07Gt8Es=", - "path": "github.com/quickfixgo/quickfix/fix43/marketdatarequest", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "ptwlzVzF1mOrx/FfxT9JGexN6No=", - "path": "github.com/quickfixgo/quickfix/fix43/newordersingle", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "fh7oJWG2BcUq09oD0tZxeyhUXik=", - "path": "github.com/quickfixgo/quickfix/fix43/ordercancelrequest", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "CXBVLmKBh3snoOEue/LwBjaY0HU=", - "path": "github.com/quickfixgo/quickfix/fix44", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-08-16T20:57:37Z" - }, - { - "checksumSHA1": "78+mqxtmr/AZTXRulySEfeR0d7A=", - "path": "github.com/quickfixgo/quickfix/fix44/executionreport", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "onAJNAokw6+eX+cMjLQuMwNsEV0=", - "path": "github.com/quickfixgo/quickfix/fix44/marketdatarequest", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "4wnaJCZwKFoihRvtYE0nQl+CwPk=", - "path": "github.com/quickfixgo/quickfix/fix44/newordersingle", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "SDlnG9PH3gH8Fk82moeq+369r/c=", - "path": "github.com/quickfixgo/quickfix/fix44/ordercancelrequest", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "SNWTHW/S3crrIpp63W8F1jZ9I/g=", - "path": "github.com/quickfixgo/quickfix/fix50/executionreport", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "lDmrO4RnB31jM0FHBGS3p82c+u0=", - "path": "github.com/quickfixgo/quickfix/fix50/marketdatarequest", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "0J9d0UtGABVPLR2T7G24LOwOwqI=", - "path": "github.com/quickfixgo/quickfix/fix50/newordersingle", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "xE/Fvgs4x7CwgxL6YrucdNW+UmM=", - "path": "github.com/quickfixgo/quickfix/fix50/ordercancelrequest", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "i+KCM8Arx4+r2P8C3IGdqQL+8vM=", - "path": "github.com/quickfixgo/quickfix/fixt11", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-08-16T20:57:37Z" - }, - { - "checksumSHA1": "sUiOkXoI8ACn1tWZVtAKzB+kzSI=", - "path": "github.com/quickfixgo/quickfix/internal", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-09-13T19:11:26Z" - }, - { - "checksumSHA1": "N8Ite5SbLcV2jVE6uiuKuL4rNY4=", - "path": "github.com/quickfixgo/quickfix/tag", - "revision": "85bb337062cce43252a11af3142653af26828428", - "revisionTime": "2016-08-16T20:57:37Z" - }, - { - "checksumSHA1": "/o4h+zapTyKGjeZqcNhUWeikF0M=", - "path": "github.com/shopspring/decimal", - "revision": "74d668a796fa3734c552fb907d9b83146d0bebee", - "revisionTime": "2016-03-11T12:45:26Z" - } - ], - "rootPath": "github.com/quickfixgo/examples" -}