Skip to content

Commit

Permalink
Added a FieldCount property.
Browse files Browse the repository at this point in the history
  • Loading branch information
mgnsm committed May 10, 2022
1 parent 2c178b2 commit 6894e25
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,9 @@ public void AddListBytes()
[Benchmark]
public int GetActiveCount() => _message.ActiveCount;

[Benchmark]
public int GetFieldCount() => _message.FieldCount;

[Benchmark]
public void SetUtf8Validation() => _message.Utf8Validation = false;

Expand Down
5 changes: 5 additions & 0 deletions Source/Millistream.Streaming/IMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public interface IMessage
/// </summary>
int ActiveCount { get; }

/// <summary>
/// The number of added fields to the current message.
/// </summary>
int FieldCount { get; }

/// <summary>
/// Enables or disables the UTF-8 validation performed in <see cref="AddString(uint, string)"/> and <see cref="AddString(uint, string, int)"/>. It's enabled by default.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions Source/Millistream.Streaming/Interop/NativeImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ unsafe internal sealed class NativeImplementation
internal readonly delegate* unmanaged[Cdecl]<IntPtr, ref IntPtr, int> mdf_message_serialize;
internal readonly delegate* unmanaged[Cdecl]<IntPtr, IntPtr, int> mdf_message_deserialize;
internal readonly delegate* unmanaged[Cdecl]<IntPtr, MDF_MSG_OPTION, int, int> mdf_message_set_property;
internal readonly delegate* unmanaged[Cdecl]<IntPtr, int> mdf_message_get_num_fields;

internal NativeImplementation(string libraryPath)
{
Expand Down Expand Up @@ -112,6 +113,8 @@ internal NativeImplementation(string libraryPath)
mdf_message_deserialize = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, int>)address;
if (nativeLibrary.TryGetExport(lib, nameof(mdf_message_set_property), out address))
mdf_message_set_property = (delegate* unmanaged[Cdecl]<IntPtr, MDF_MSG_OPTION, int, int>)address;
if (nativeLibrary.TryGetExport(lib, nameof(mdf_message_get_num_fields), out address))
mdf_message_get_num_fields = (delegate* unmanaged[Cdecl]<IntPtr, int>)address;
}

internal static NativeImplementation Default => s_defaultImplementation ??= new(null);
Expand Down
15 changes: 15 additions & 0 deletions Source/Millistream.Streaming/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,21 @@ public int ActiveCount
}
}

/// <summary>
/// The number of added fields to the current message.
/// </summary>
/// <exception cref="InvalidOperationException">The installed version of the native library doesn't include the mdf_message_get_num_fields function.</exception>
/// <exception cref="ObjectDisposedException">The <see cref="Message"/> instance has been disposed.</exception>
public int FieldCount
{
get
{
ThrowIfDisposed();
ThrowIfNativeFunctionIsMissing(_nativeImplementation.mdf_message_get_num_fields, nameof(_nativeImplementation.mdf_message_get_num_fields));
return _nativeImplementation.mdf_message_get_num_fields(Handle);
}
}

/// <summary>
/// Enables or disables the UTF-8 validation performed in <see cref="AddString(uint, string)"/> and <see cref="AddString(uint, string, int)"/>. It's enabled by default.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,20 +256,24 @@ public void SendMultipleMessagesTest()
Assert.IsTrue(message.AddNumeric(Field.MDF_F_REQUESTTYPE, StringConstants.RequestTypes.MDF_RT_IMAGE));
Assert.IsTrue(message.AddString(Field.MDF_F_INSREFLIST, "772"));
Assert.IsTrue(message.AddString(Field.MDF_F_REQUESTID, requestIds[0]));
Assert.AreEqual(1, message.ActiveCount);
Assert.AreEqual(4, message.FieldCount);

Assert.IsTrue(message.Add(0, MessageReference.MDF_M_REQUEST));
Assert.IsTrue(message.AddNumeric(Field.MDF_F_REQUESTCLASS, StringConstants.RequestClasses.MDF_RC_QUOTE));
Assert.IsTrue(message.AddNumeric(Field.MDF_F_REQUESTTYPE, StringConstants.RequestTypes.MDF_RT_IMAGE));
Assert.IsTrue(message.AddString(Field.MDF_F_INSREFLIST, "1146"));
Assert.IsTrue(message.AddString(Field.MDF_F_REQUESTID, requestIds[1]));
Assert.AreEqual(2, message.ActiveCount);
Assert.AreEqual(4, message.FieldCount);

Assert.IsTrue(message.Add(0, MessageReference.MDF_M_REQUEST));
Assert.IsTrue(message.AddNumeric(Field.MDF_F_REQUESTCLASS, StringConstants.RequestClasses.MDF_RC_TRADE));
Assert.IsTrue(message.AddNumeric(Field.MDF_F_REQUESTTYPE, StringConstants.RequestTypes.MDF_RT_IMAGE));
Assert.IsTrue(message.AddString(Field.MDF_F_INSREFLIST, "105"));
Assert.IsTrue(message.AddString(Field.MDF_F_REQUESTID, requestIds[2]));

Assert.AreEqual(3, message.ActiveCount);
Assert.AreEqual(4, message.FieldCount);

//send a request with 3 messages
Assert.IsTrue(mdf.Send(message));
Expand All @@ -278,6 +282,7 @@ public void SendMultipleMessagesTest()

message.Reset();
Assert.AreEqual(0, message.ActiveCount);
Assert.AreEqual(0, message.FieldCount);

Assert.IsTrue(message.Add(0, MessageReference.MDF_M_REQUEST));
Assert.IsTrue(message.AddNumeric(Field.MDF_F_REQUESTCLASS, StringConstants.RequestClasses.MDF_RC_ORDER));
Expand All @@ -286,6 +291,7 @@ public void SendMultipleMessagesTest()
string requestId = Guid.NewGuid().ToString();
Assert.IsTrue(message.AddString(Field.MDF_F_REQUESTID, requestId));
Assert.AreEqual(1, message.ActiveCount);
Assert.AreEqual(4, message.FieldCount);

//send another request with a single message
Assert.IsTrue(mdf.Send(message));
Expand Down
19 changes: 19 additions & 0 deletions Tests/Millistream.Streaming.IntegrationTests/MessageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,10 @@ public void ResetTest()
using Message message = new Message();
Assert.IsTrue(message.Add(0, MessageReference.MDF_M_QUOTE));
Assert.AreEqual(1, message.ActiveCount);
Assert.AreEqual(0, message.FieldCount);
message.Reset();
Assert.AreEqual(0, message.ActiveCount);
Assert.AreEqual(0, message.FieldCount);
}

[TestMethod]
Expand All @@ -316,12 +318,16 @@ public void DeleteTest()
Assert.IsTrue(message.Add(0, MessageReference.MDF_M_QUOTE));
Assert.IsTrue(message.AddNumeric(Field.MDF_F_REQUESTCLASS, StringConstants.RequestClasses.MDF_RC_BASICDATA));
Assert.AreEqual(1, message.ActiveCount);
Assert.AreEqual(1, message.FieldCount);
Assert.IsTrue(message.Add(0, MessageReference.MDF_M_QUOTE));
Assert.AreEqual(2, message.ActiveCount);
Assert.AreEqual(0, message.FieldCount);
message.Delete();
Assert.AreEqual(1, message.ActiveCount);
Assert.AreEqual(1, message.FieldCount);
message.Delete();
Assert.AreEqual(0, message.ActiveCount);
Assert.AreEqual(0, message.FieldCount);
}

[TestMethod]
Expand Down Expand Up @@ -381,18 +387,26 @@ public void MoveTest()
const ulong SourceInsRef = 1;
Assert.IsTrue(source.Add(SourceInsRef, MessageReference.MDF_M_REQUEST));
Assert.IsTrue(source.AddNumeric(Field.MDF_F_REQUESTTYPE, StringConstants.RequestTypes.MDF_RT_IMAGE));
Assert.AreEqual(1, source.ActiveCount);
Assert.AreEqual(1, source.FieldCount);
Assert.IsTrue(source.Add(SourceInsRef, MessageReference.MDF_M_BASICDATA));
Assert.IsTrue(source.AddNumeric(Field.MDF_F_REQUESTTYPE, StringConstants.RequestTypes.MDF_RT_IMAGE));
Assert.AreEqual(2, source.ActiveCount);
Assert.AreEqual(1, source.FieldCount);
Assert.IsTrue(source.Add(SourceInsRef, MessageReference.MDF_M_QUOTE));
Assert.IsTrue(source.AddNumeric(Field.MDF_F_REQUESTTYPE, StringConstants.RequestTypes.MDF_RT_IMAGE));
Assert.AreEqual(3, source.ActiveCount);
Assert.AreEqual(1, source.FieldCount);

using Message destination = new Message();
Assert.AreEqual(0, destination.ActiveCount);
Assert.AreEqual(0, destination.FieldCount);

Assert.IsTrue(Message.Move(source, destination, 1, 10));
Assert.AreEqual(0, source.ActiveCount);
Assert.AreEqual(0, source.FieldCount);
Assert.AreEqual(3, destination.ActiveCount);
Assert.AreEqual(1, destination.FieldCount);

Assert.IsFalse(Message.Move(source, null, 1, 10));
Assert.IsTrue(Message.Move(destination, null, 10, 11));
Expand All @@ -419,16 +433,21 @@ public void SerializeAndDeserializeTest()
using Message message2 = new Message();
Assert.IsTrue(message2.Deserialize(s));
Assert.AreEqual(2, message2.ActiveCount);
Assert.AreEqual(1, message2.FieldCount);
Assert.IsTrue(message.Deserialize(s));
message2.Reset();
Assert.AreEqual(0, message2.ActiveCount);
Assert.AreEqual(0, message2.FieldCount);
Assert.IsTrue(message2.Deserialize(result));
Assert.AreEqual(2, message2.ActiveCount);
Assert.AreEqual(1, message2.FieldCount);
message2.Reset();
Assert.AreEqual(0, message2.ActiveCount);
Assert.AreEqual(0, message2.FieldCount);
byte[] bytes = Encoding.ASCII.GetBytes(s);
Assert.IsTrue(message2.Deserialize(bytes));
Assert.AreEqual(2, message2.ActiveCount);
Assert.AreEqual(1, message2.FieldCount);
}
}
}
33 changes: 23 additions & 10 deletions Tests/Millistream.Streaming.UnitTests/MessageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,28 @@ public void GetAndSetCompressionLevelTest()
[TestMethod]
public void GetCountTest()
{
const int Num = 11;
_nativeImplementation.Setup(x => x.mdf_message_get_num(It.IsAny<IntPtr>())).Returns(Num);
const int Count = 11;
_nativeImplementation.Setup(x => x.mdf_message_get_num(It.IsAny<IntPtr>())).Returns(Count);
using Message message = new();
Assert.AreEqual(Num, message.Count);
Assert.AreEqual(Count, message.Count);
}

[TestMethod]
public void GetCountActiveTest()
public void GetActiveCountTest()
{
const int NumActive = 5;
_nativeImplementation.Setup(x => x.mdf_message_get_num_active(It.IsAny<IntPtr>())).Returns(NumActive);
const int Count = 5;
_nativeImplementation.Setup(x => x.mdf_message_get_num_active(It.IsAny<IntPtr>())).Returns(Count);
using Message message = new();
Assert.AreEqual(NumActive, message.ActiveCount);
Assert.AreEqual(Count, message.ActiveCount);
}

[TestMethod]
public void GetFieldCountTest()
{
const int Count = 6;
_nativeImplementation.Setup(x => x.mdf_message_get_num_fields(It.IsAny<IntPtr>())).Returns(Count);
using Message message = new();
Assert.AreEqual(Count, message.FieldCount);
}

[TestMethod]
Expand Down Expand Up @@ -417,6 +426,10 @@ public void DeserializeEmptyStringTest() =>
[ExpectedException(typeof(ObjectDisposedException))]
public void CannotGetActiveCountAfterDisposeTest() => _ = GetDisposedMessage().ActiveCount;

[TestMethod]
[ExpectedException(typeof(ObjectDisposedException))]
public void CannotGetFieldCountAfterDisposeTest() => _ = GetDisposedMessage().FieldCount;

[TestMethod]
[ExpectedException(typeof(ObjectDisposedException))]
public void CannotGetUtf8ValidationAfterDisposeTest() => _ = GetDisposedMessage().Utf8Validation;
Expand Down Expand Up @@ -504,7 +517,7 @@ static void CatchObjectDisposedException(Action action)
}

[TestMethod]
public unsafe void CannotSetPropertyWhenNativeFunctionIsMissingTest()
public unsafe void MemberThrowsWhenNativeFunctionIsMissingTest()
{
NativeImplementation nativeImplementation = new(default);
nativeImplementation.mdf_message_set_property = default;
Expand All @@ -517,6 +530,7 @@ public unsafe void CannotSetPropertyWhenNativeFunctionIsMissingTest()
nativeImplementation.mdf_message_move = default;
nativeImplementation.mdf_message_serialize = default;
nativeImplementation.mdf_message_deserialize = default;
nativeImplementation.mdf_message_get_num_fields = default;

using Message message = new(nativeImplementation);
CatchInvalidOperationException(() => message.CompressionLevel = CompressionLevel.Z_BEST_COMPRESSION, nameof(nativeImplementation.mdf_message_set_property));
Expand All @@ -539,8 +553,7 @@ public unsafe void CannotSetPropertyWhenNativeFunctionIsMissingTest()
CatchInvalidOperationException(() => message.Serialize(out _), nameof(nativeImplementation.mdf_message_serialize));
CatchInvalidOperationException(() => message.Deserialize("..."), nameof(nativeImplementation.mdf_message_deserialize));
CatchInvalidOperationException(() => message.Deserialize(default(ReadOnlySpan<byte>)), nameof(nativeImplementation.mdf_message_deserialize));


CatchInvalidOperationException(() => _ = message.FieldCount, nameof(nativeImplementation.mdf_message_get_num_fields));

static void CatchInvalidOperationException(Action action, string missingFunctionName)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public interface INativeImplementation
int mdf_message_serialize(IntPtr message, ref IntPtr result);
int mdf_message_deserialize(IntPtr message, IntPtr data);
int mdf_message_set_property(IntPtr message, int option, int value);
int mdf_message_get_num_fields(IntPtr message);
#pragma warning restore IDE1006
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ internal unsafe class NativeImplementation
internal delegate*<IntPtr, ref IntPtr, int> mdf_message_serialize;
internal delegate*<IntPtr, IntPtr, int> mdf_message_deserialize;
internal delegate*<IntPtr, MDF_MSG_OPTION, int, int> mdf_message_set_property;
internal delegate*<IntPtr, int> mdf_message_get_num_fields;

internal static NativeImplementation Default => s_defaultImplementation ??= new(null);
internal static INativeImplementation Implementation { get; set; }
Expand Down Expand Up @@ -85,6 +86,7 @@ internal NativeImplementation(string _)
mdf_message_serialize = &MdfMessageSerialize;
mdf_message_deserialize = &MdfMessageDeserialize;
mdf_message_set_property = &MdfMessageSetProperty;
mdf_message_get_num_fields = &MdfMessageGetNumFields;
}

private static IntPtr MdfCreate() => Implementation.mdf_create();
Expand Down Expand Up @@ -122,5 +124,6 @@ internal NativeImplementation(string _)
private static int MdfMessageSerialize(IntPtr message, ref IntPtr result) => Implementation.mdf_message_serialize(message, ref result);
private static int MdfMessageDeserialize(IntPtr message, IntPtr data) => Implementation.mdf_message_deserialize(message, data);
private static int MdfMessageSetProperty(IntPtr message, MDF_MSG_OPTION option, int value) => Implementation.mdf_message_set_property(message, (int)option, value);
private static int MdfMessageGetNumFields(IntPtr message) => Implementation.mdf_message_get_num_fields(message);
}
}

0 comments on commit 6894e25

Please sign in to comment.