diff --git a/Makefile b/Makefile index 58b8cc94b..10b8e9871 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ fmt: go fmt ./... vet: - go vet $(go list ./... | grep -v /vendor) + go vet `go list ./... | grep -v /vendor | grep -v fix4 | grep -v fix5 | grep -v fixt` lint: go get github.com/golang/lint/golint @@ -17,7 +17,7 @@ test: go test -v -cover . ./datadictionary ./internal _build_all: - go build -v ./... + go build -v `go list ./... | grep -v /vendor` build_accept: cd _test; go build -o echo_server diff --git a/cmd/generate-fix/generate-fix.go b/cmd/generate-fix/generate-fix.go index c5ecdde6c..5ec5ff47a 100644 --- a/cmd/generate-fix/generate-fix.go +++ b/cmd/generate-fix/generate-fix.go @@ -10,6 +10,7 @@ import ( "strconv" "strings" "sync" + "text/template" "github.com/quickfixgo/quickfix/cmd/generate-fix/internal" "github.com/quickfixgo/quickfix/datadictionary" @@ -53,48 +54,28 @@ type component struct { } func genHeader(pkg string, spec *datadictionary.DataDictionary) { - defer waitGroup.Done() - writer := new(bytes.Buffer) c := component{ Package: pkg, Name: "Header", MessageDef: spec.Header, FIXSpec: spec, } - if err := internal.HeaderTemplate.Execute(writer, c); err != nil { - errors <- err - return - } - - if err := internal.WriteFile(path.Join(pkg, "header.generated.go"), writer.String()); err != nil { - errors <- err - } + gen(internal.HeaderTemplate, path.Join(pkg, "header.generated.go"), c) } func genTrailer(pkg string, spec *datadictionary.DataDictionary) { - defer waitGroup.Done() - writer := new(bytes.Buffer) c := component{ Package: pkg, Name: "Trailer", MessageDef: spec.Trailer, } - if err := internal.TrailerTemplate.Execute(writer, c); err != nil { - errors <- err - return - } - - if err := internal.WriteFile(path.Join(pkg, "trailer.generated.go"), writer.String()); err != nil { - errors <- err - } + gen(internal.TrailerTemplate, path.Join(pkg, "trailer.generated.go"), c) } func genMessage(fixPkg string, spec *datadictionary.DataDictionary, msg *datadictionary.MessageDef) { - defer waitGroup.Done() pkgName := strings.ToLower(msg.Name) transportPkg := getTransportPackageName(spec) - writer := new(bytes.Buffer) c := component{ Package: pkgName, FIXPackage: fixPkg, @@ -104,54 +85,31 @@ func genMessage(fixPkg string, spec *datadictionary.DataDictionary, msg *datadic MessageDef: msg, } - if err := internal.MessageTemplate.Execute(writer, c); err != nil { - errors <- err - return - } - - if err := internal.WriteFile(path.Join(fixPkg, pkgName, msg.Name+".generated.go"), writer.String()); err != nil { - errors <- err - } + gen(internal.MessageTemplate, path.Join(fixPkg, pkgName, msg.Name+".generated.go"), c) } func genTags() { - defer waitGroup.Done() - writer := new(bytes.Buffer) - - if err := internal.TagTemplate.Execute(writer, internal.GlobalFieldTypes); err != nil { - errors <- err - return - } - - if err := internal.WriteFile("tag/tag_numbers.generated.go", writer.String()); err != nil { - errors <- err - } + gen(internal.TagTemplate, "tag/tag_numbers.generated.go", internal.GlobalFieldTypes) } func genFields() { - defer waitGroup.Done() - writer := new(bytes.Buffer) - - if err := internal.FieldTemplate.Execute(writer, internal.GlobalFieldTypes); err != nil { - errors <- err - return - } - - if err := internal.WriteFile("field/fields.generated.go", writer.String()); err != nil { - errors <- err - } + gen(internal.FieldTemplate, "field/fields.generated.go", internal.GlobalFieldTypes) } func genEnums() { + gen(internal.EnumTemplate, "enum/enums.generated.go", internal.GlobalFieldTypes) +} + +func gen(t *template.Template, fileOut string, data interface{}) { defer waitGroup.Done() writer := new(bytes.Buffer) - if err := internal.EnumTemplate.Execute(writer, internal.GlobalFieldTypes); err != nil { + if err := t.Execute(writer, data); err != nil { errors <- err return } - if err := internal.WriteFile("enum/enums.generated.go", writer.String()); err != nil { + if err := internal.WriteFile(fileOut, writer.String()); err != nil { errors <- err } } diff --git a/fix_decimal.go b/fix_decimal.go new file mode 100644 index 000000000..d6f8ab1cd --- /dev/null +++ b/fix_decimal.go @@ -0,0 +1,20 @@ +package quickfix + +import "github.com/shopspring/decimal" + +//FIXDecimal is a FIX Float Value that implements an arbitrary precision fixed-point decimal. Implements FieldValue +type FIXDecimal struct { + decimal.Decimal + + //Scale is the number of digits after the decimal point when Writing the field value as a FIX value + Scale int32 +} + +func (d FIXDecimal) Write() []byte { + return []byte(d.Decimal.StringFixed(d.Scale)) +} + +func (d *FIXDecimal) Read(bytes []byte) (err error) { + d.Decimal, err = decimal.NewFromString(string(bytes)) + return +} diff --git a/fix_decimal_test.go b/fix_decimal_test.go new file mode 100644 index 000000000..1785d6e67 --- /dev/null +++ b/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/fix_float_test.go b/fix_float_test.go index e34fa7d38..b31bdbb60 100644 --- a/fix_float_test.go +++ b/fix_float_test.go @@ -51,6 +51,6 @@ func BenchmarkFloatRead(b *testing.B) { val := []byte("15.1234") for i := 0; i < b.N; i++ { var field FIXFloat - field.Read(val) + _ = field.Read(val) } }