Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rebase and improve PR #741 - ReadGroups #913

Merged
merged 4 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"));
}
}
}
Loading