public void Length_field_based_framing_must_work_with_various_byte_orders_frame_lengths_and_offsets() { IEnumerable <Task <(IEnumerable <ByteString>, List <ByteString>, (ByteOrder, int, int))> > GetFutureResults() { foreach (var byteOrder in ByteOrders) { foreach (var fieldOffset in FieldOffsets) { foreach (var fieldLength in FieldLengths) { var encodedFrames = FrameLengths.Where(x => x < 1L << (fieldLength * 8)).Select(length => { var payload = ReferenceChunk.Slice(0, length); return(Encode(payload, fieldOffset, fieldLength, byteOrder)); }).ToList(); yield return(Source.From(encodedFrames) .Via(Rechunk) .Via(Framing.LengthField(fieldLength, int.MaxValue, fieldOffset, byteOrder)) .Grouped(10000) .RunWith(Sink.First <IEnumerable <ByteString> >(), Materializer) .ContinueWith(t => (t.Result, encodedFrames, (byteOrder, fieldOffset, fieldLength)))); } } } } Parallel.ForEach(GetFutureResults(), async futureResult => { var(result, encodedFrames, (byteOrder, fieldOffset, fieldLength)) = await futureResult; result.ShouldBeSame(encodedFrames, $"byteOrder: {byteOrder}, fieldOffset: {fieldOffset}, fieldLength: {fieldLength}"); }); }
public void Length_field_based_framing_must_report_truncated_frames() { foreach (var byteOrder in ByteOrders) { foreach (var fieldOffset in FieldOffsets) { foreach (var fieldLength in FieldLengths) { foreach (var frameLength in FrameLengths.Where(f => f < 1 << (fieldLength * 8) && f != 0)) { var fullFrame = Encode(ReferenceChunk.Slice(0, frameLength), fieldOffset, fieldLength, byteOrder); var partialFrame = fullFrame.Slice(0, fullFrame.Count - 1); // dropRight equivalent Action action = () => { Source.From(new[] { fullFrame, partialFrame }) .Via(Rechunk) .Via(Framing.LengthField(fieldLength, int.MaxValue, fieldOffset, byteOrder)) .Grouped(10000) .RunWith(Sink.First <IEnumerable <ByteString> >(), Materializer) .Wait(TimeSpan.FromSeconds(5)) .ShouldBeTrue("Stream should complete withing 5 seconds"); }; action.ShouldThrow <Framing.FramingException>(); } } } } }
public void Length_field_based_framing_must_work_with_various_byte_orders_frame_lengths_and_offsets() { var counter = 1; foreach (var byteOrder in ByteOrders) { foreach (var fieldOffset in FieldOffsets) { foreach (var fieldLength in FieldLengths) { var encodedFrames = FrameLengths.Where(x => x < 1L << (fieldLength * 8)).Select(length => { var payload = ReferenceChunk.Slice(0, length); return(Encode(payload, fieldOffset, fieldLength, byteOrder)); }).ToList(); var task = Source.From(encodedFrames) .Via(Rechunk) .Via(Framing.LengthField(fieldLength, int.MaxValue, fieldOffset, byteOrder)) .Grouped(10000) .RunWith(Sink.First <IEnumerable <ByteString> >(), Materializer); task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); task.Result.ShouldAllBeEquivalentTo(encodedFrames); _helper.WriteLine($"{counter++} from 80 passed"); } } } }
public void Length_field_based_framing_must_work_with_various_byte_orders_frame_lengths_and_offsets_using_ComputeFrameSize() { IEnumerable <Task <(IEnumerable <ByteString>, List <ByteString>, (ByteOrder, int, int))> > GetFutureResults() { foreach (var byteOrder in ByteOrders) { foreach (var fieldOffset in FieldOffsets) { foreach (var fieldLength in FieldLengths) { int ComputeFrameSize(IReadOnlyList <byte> offset, int length) { var sizeWithoutTail = offset.Count + fieldLength + length; return(offset.Count > 0 ? offset[0] + sizeWithoutTail : sizeWithoutTail); } var random = new Random(); byte[] Offset() { var arr = new byte[fieldOffset]; if (arr.Length > 0) { arr[0] = Convert.ToByte(random.Next(128)); } return(arr); } var encodedFrames = FrameLengths.Where(x => x < 1L << (fieldLength * 8)).Select(length => { var payload = ReferenceChunk.Slice(0, length); var offsetBytes = Offset(); var tailBytes = offsetBytes.Length > 0 ? new byte[offsetBytes[0]] : Array.Empty <byte>(); return(EncodeComplexFrame(payload, fieldLength, byteOrder, ByteString.FromBytes(offsetBytes), ByteString.FromBytes(tailBytes))); }).ToList(); yield return(Source.From(encodedFrames) .Via(Rechunk) .Via(Framing.LengthField(fieldLength, fieldOffset, int.MaxValue, byteOrder, ComputeFrameSize)) .Grouped(10000) .RunWith(Sink.First <IEnumerable <ByteString> >(), Materializer) .ContinueWith(t => (t.Result, encodedFrames, (byteOrder, fieldOffset, fieldLength)))); } } } } Parallel.ForEach(GetFutureResults(), async futureResult => { var(result, encodedFrames, (byteOrder, fieldOffset, fieldLength)) = await futureResult; result.ShouldBeSame(encodedFrames, $"byteOrder: {byteOrder}, fieldOffset: {fieldOffset}, fieldLength: {fieldLength}"); }); }
public void Length_field_based_framing_must_work_with_empty_streams() { var task = Source.Empty <ByteString>() .Via(Framing.LengthField(4, int.MaxValue, 0, ByteOrder.BigEndian)) .RunAggregate(new List <ByteString>(), (list, s) => { list.Add(s); return(list); }, Materializer); task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); task.Result.Should().BeEmpty(); }
public void Length_field_based_framing_must_let_zero_length_field_values_pass_through() { // Interleave empty frames with a frame with data var b = ByteString.FromBytes(BitConverter.GetBytes(42).ToArray()); var encodedPayload = Encode(b, 0, 4, ByteOrder.LittleEndian); var emptyFrame = Encode(ByteString.Empty, 0, 4, ByteOrder.LittleEndian); var bytes = new[] { emptyFrame, encodedPayload, emptyFrame }; var result = Source.From(bytes) .Via(Flow.Create <ByteString>().Via(Framing.LengthField(4, 1000))) .RunWith(Sink.Seq <ByteString>(), Materializer); result.AwaitResult().Should().BeEquivalentTo(bytes.ToImmutableList()); }
public void Length_field_based_framing_must_fail_the_stage_on_negative_length_field_values() { // A 4-byte message containing only an Int specifying the length of the payload // The issue shows itself if length in message is less than or equal // to -4 (if expected length field is length 4) var bytes = ByteString.FromBytes(BitConverter.GetBytes(-4).ToArray()); var result = Source.Single(bytes) .Via(Flow.Create <ByteString>().Via(Framing.LengthField(4, 1000))) .RunWith(Sink.Seq <ByteString>(), Materializer); result.Invoking(t => t.AwaitResult()) .ShouldThrow <Framing.FramingException>() .WithMessage("Decoded frame header reported negative size -4"); }
public void Length_field_based_framing_must_fail_the_stage_on_computeFrameSize_values_less_than_minimum_chunk_size() { int ComputeFrameSize(IReadOnlyList <byte> offset, int length) => 3; // A 4-byte message containing only an Int specifying the length of the payload var bytes = ByteString.FromBytes(BitConverter.GetBytes(4)); var result = Source.Single(bytes) .Via(Flow.Create <ByteString>().Via(Framing.LengthField(4, 0, 1000, ByteOrder.LittleEndian, ComputeFrameSize))) .RunWith(Sink.Seq <ByteString>(), Materializer); result.Invoking(t => t.AwaitResult()) .Should().Throw <Framing.FramingException>() .WithMessage("Computed frame size 3 is less than minimum chunk size 4"); }
public void Length_field_based_framing_must_ignore_length_field_value_when_provided_computeFrameSize() { int ComputeFrameSize(IReadOnlyList <byte> offset, int length) => 8; var tempArray = new byte[4].PutInt(unchecked ((int)0xFF010203), order: ByteOrder.LittleEndian); Array.Resize(ref tempArray, 8); var bs = ByteString.FromBytes(tempArray.PutInt(checked (0x04050607), order: ByteOrder.LittleEndian)); var result = Source.Single(bs) .Via(Flow.Create <ByteString>().Via(Framing.LengthField(4, 0, 1000, ByteOrder.LittleEndian, ComputeFrameSize))) .RunWith(Sink.Seq <ByteString>(), Materializer); result.AwaitResult().Should().BeEquivalentTo(ImmutableArray.Create(bs)); }
public void Length_field_based_framing_must_report_oversized_frames() { var task1 = Source.Single(Encode(ReferenceChunk.Slice(0, 100), 0, 1, ByteOrder.BigEndian)) .Via(Framing.LengthField(1, 99, 0, ByteOrder.BigEndian)) .RunAggregate(new List<ByteString>(), (list, s) => { list.Add(s); return list; }, Materializer); task1.Invoking(t => t.Wait(TimeSpan.FromSeconds(3))).ShouldThrow<Framing.FramingException>(); var task2 = Source.Single(Encode(ReferenceChunk.Slice(0, 100), 49, 1, ByteOrder.BigEndian)) .Via(Framing.LengthField(1, 100, 0, ByteOrder.BigEndian)) .RunAggregate(new List<ByteString>(), (list, s) => { list.Add(s); return list; }, Materializer); task2.Invoking(t => t.Wait(TimeSpan.FromSeconds(3))).ShouldThrow<Framing.FramingException>(); }
public static Flow <ByteString, ByteString, NotUsed> Decode(int frameLengthBytes = 4, int maxFrameLength = DefaultMaxFrameLength, ByteOrder byteOrder = ByteOrder.LittleEndian) { return(Framing.LengthField(frameLengthBytes, maxFrameLength, 0, byteOrder) .Select(m => m.Slice(frameLengthBytes, m.Count - frameLengthBytes))); // strip the header }