// Copyright (c) quickfixengine.org All rights reserved. // // This file may be distributed under the terms of the quickfixengine.org // license as defined by quickfixengine.org and appearing in the file // LICENSE included in the packaging of this file. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING // THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A // PARTICULAR PURPOSE. // // See http://www.quickfixengine.org/LICENSE for licensing information. // // Contact ask@quickfixengine.org if any conditions of this licensing // are not clear to you. 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{ {value: []byte("1")}, {tag: Tag(2), value: []byte("not in template")}, {tag: Tag(1), value: []byte("hello")}, }, 0}, { []TagValue{ {value: []byte("2")}, {tag: Tag(1), value: []byte("hello")}, {tag: Tag(2), value: []byte("not in template")}, {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{{value: []byte("0")}}, [][]TagValue{}}, {singleFieldTemplate, []TagValue{{value: []byte("1")}, {tag: Tag(1), value: []byte("hello")}}, [][]TagValue{{TagValue{tag: Tag(1), value: []byte("hello")}}}}, {singleFieldTemplate, []TagValue{{value: []byte("1")}, {tag: Tag(1), value: []byte("hello")}, {tag: Tag(2), value: []byte("not in group")}}, [][]TagValue{ {TagValue{tag: Tag(1), value: []byte("hello")}}}}, {singleFieldTemplate, []TagValue{{value: []byte("2")}, {tag: Tag(1), value: []byte("hello")}, {tag: Tag(1), value: []byte("world")}}, [][]TagValue{ {TagValue{tag: Tag(1), value: []byte("hello")}}, {TagValue{tag: Tag(1), value: []byte("world")}}, }}, {multiFieldTemplate, []TagValue{ {value: []byte("2")}, {tag: Tag(1), value: []byte("hello")}, {tag: Tag(1), value: []byte("goodbye")}, {tag: Tag(2), value: []byte("cruel")}, {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{ {value: []byte("3")}, {tag: Tag(1), value: []byte("hello")}, {tag: Tag(1), value: []byte("goodbye")}, {tag: Tag(2), value: []byte("cruel")}, {tag: Tag(3), value: []byte("world")}, {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)) require.NotNil(t, group.tags) require.Equal(t, len(group.tags), len(group.tagLookup)) 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{ {value: []byte("2")}, {tag: Tag(2), value: []byte("hello")}, {tag: 3, value: []byte("1")}, {tag: 4, value: []byte("foo")}, {tag: Tag(2), value: []byte("world")}, {tag: 3, value: []byte("2")}, {tag: 4, value: []byte("foo")}, {tag: 4, value: []byte("bar")}, {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) } } } }