예제 #1
0
        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}");
            });
        }
예제 #2
0
        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>();
                        }
                    }
                }
            }
        }
예제 #3
0
        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");
                    }
                }
            }
        }
예제 #4
0
        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}");
            });
        }
예제 #5
0
        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();
        }
예제 #6
0
        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());
        }
예제 #7
0
        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");
        }
예제 #8
0
        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");
        }
예제 #9
0
        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));
        }
예제 #10
0
        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
 }