Skip to content

Commit

Permalink
Merge pull request #913 from gbirchmeier/rebase-741-ReadGroups
Browse files Browse the repository at this point in the history
rebase and improve PR #741 - ReadGroups
  • Loading branch information
gbirchmeier authored Dec 20, 2024
2 parents dc3614d + 10c4c44 commit 8f4f5c9
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 7 deletions.
31 changes: 24 additions & 7 deletions QuickFIXn/Message/FieldMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -657,22 +657,39 @@ public List<int> GetGroupTags()
return new List<int>(_groups.Keys);
}

#region IEnumerable<KeyValuePair<int,IField>> Members
/// <summary>
/// Read groups via IEnumerable.
/// </summary>
/// <typeparam name="TGroup">The group class type retrieved by groupCountTag</typeparam>
/// <param name="groupCountTag">The FIX group tag</param>
/// <returns>retrieved enumerable groups</returns>
/// <exception cref="InvalidCastException">If groupCountTag retreives a group that can't be cast to TGroup</exception>
public IEnumerable<TGroup> ReadGroups<TGroup>(int groupCountTag) where TGroup : Group
{
if (IsSetField(groupCountTag) && GetGroupTags().Contains(groupCountTag))
{
int grpCount = GetInt(groupCountTag);

for (int grpIndex = 1; grpIndex <= grpCount; grpIndex += 1)
{
Group group = GetGroup(grpIndex, groupCountTag);
if(group is not TGroup tgroup)
throw new InvalidCastException($"Can't cast {group.GetType()} to {typeof(TGroup)}");
yield return tgroup;
}
}
}

// IEnumerable<KeyValuePair<int,IField>> Member
public IEnumerator<KeyValuePair<int, IField>> GetEnumerator()
{
return _fields.GetEnumerator();
}

#endregion

#region IEnumerable Members

// IEnumerable Member
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _fields.GetEnumerator();
}

#endregion
}
}
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ What's New
* #907 - A fix to make body-less messages work, specifically 35=n aka XMLnonFIX (gbirchmeier)
* #910 - faster Message.GetMsgType that doesn't use Regex (jkulubya)
* #516 - remove ability to toggle Session-enable via HttpServer because it never really worked (gbirchmeier)
* #913/#741 - new FieldMap.ReadGroups for iterating on groups (NoviProg/gbirchmeier)

### v1.12.0

Expand Down
71 changes: 71 additions & 0 deletions UnitTests/FieldMap_ReadGroupsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using System.Linq;
using NUnit.Framework;
using QuickFix.FIX42;
using QuickFix.Fields;

namespace UnitTests;

[TestFixture]
public class FieldMap_ReadGroupsTests {
public class GroupExtensionTest
{
private static News CreateNewsForTest(int numberOfLines) {
News msg = new();
msg.Headline = new Headline("Blah headline");
for (int i = 0; i < numberOfLines; i++) {
News.LinesOfTextGroup grp = new();
grp.SetField(new Text($"OHHAI_{i}"));
msg.AddGroup(grp);
}
return msg;
}

[Test]
public void ReadGroups_NormalScenario() {
News msg = CreateNewsForTest(10);
int iterCount = 0;
foreach (News.LinesOfTextGroup item in msg.ReadGroups<News.LinesOfTextGroup>(Tags.NoLinesOfText))
Assert.That(item.Text.Value, Is.EqualTo($"OHHAI_{iterCount++}"));
Assert.That(iterCount == 10);
}

[Test]
public void ReadGroups_ZeroCount() {
News msg = new();
Assert.That(msg.ReadGroups<News.LinesOfTextGroup>(Tags.NoLinesOfText).ToList(), Is.Empty);
}

[Test]
public void ReadGroups_WrongTag() {
// Tag doesn't match the templated group
// case 1: incorrect tag is not present in message
News msg = CreateNewsForTest(3);
Assert.That(msg.IsSetField(Tags.Account), Is.False);
Assert.That(msg.ReadGroups<News.LinesOfTextGroup>(Tags.Account).ToList(), Is.Empty);

// case 2: incorrect tag present but value isn't an int (like a group counter would be)
Assert.That(msg.IsSetHeadline());
Assert.That(msg.ReadGroups<News.LinesOfTextGroup>(Tags.Headline).ToList(), Is.Empty);

// case 3: incorrect tag present and an int, but isn't group counter at all
msg.SetField(new RawDataLength(100));
Assert.That(msg.ReadGroups<News.LinesOfTextGroup>(Tags.RawDataLength).ToList(), Is.Empty);
}

[Test]
public void ReadGroups_WrongGroup() {
// The tag is good, but the template type is incorrect
// Case 1: The tag's group is empty, so the templated type doesn't matter.
News msg = CreateNewsForTest(0);
Assert.That(msg.ReadGroups<QuickFix.FIX44.ExecutionReport.NoLegsGroup>(Tags.NoLinesOfText).ToList(),
Is.Empty);

// Case 2: Group is not empty, so InvalidCastException will occur
msg = CreateNewsForTest(1);
var ex = Assert.Throws<InvalidCastException>(
() => msg.ReadGroups<QuickFix.FIX44.ExecutionReport.NoLegsGroup>(Tags.NoLinesOfText).ToList());
Assert.That(ex!.Message, Is.EqualTo("Can't cast QuickFix.FIX42.News+LinesOfTextGroup to QuickFix.FIX44.ExecutionReport+NoLegsGroup"));
}
}
}

0 comments on commit 8f4f5c9

Please sign in to comment.