blob: f0aea74b53bd5148eef1a5192a2ede1931e60667 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Collections.Generic;
using System.IO;
using Apache.Qpid.Proton.Test.Driver.Codec.Security;
using Apache.Qpid.Proton.Test.Driver.Codec.Transport;
using Apache.Qpid.Proton.Test.Driver.Exceptions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using NUnit.Framework;
namespace Apache.Qpid.Proton.Test.Driver
{
[TestFixture, Timeout(20000)]
public class frameHandlerTests
{
[Test]
public void TestDecodeMultipleEmptyFrames()
{
// http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#doc-idp124752
// Description: 2x '8byte sized' empty AMQP frames
byte[] emptyFrames = new byte[] { 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00 };
MemoryStream stream = new MemoryStream(emptyFrames);
TestFrameHandler handler = new TestFrameHandler();
FrameDecoder decoder = new FrameDecoder(handler);
decoder.Ingest(new MemoryStream(AMQPHeader.Header.Buffer));
Assert.AreEqual(1, handler.HeaderCount);
do
{
Assert.DoesNotThrow(() => decoder.Ingest(stream));
}
while (stream.Position < stream.Length);
Assert.AreEqual(2, handler.EmptyFrameCount);
}
[Test]
public void TestInputOfFrameWithInvalidSizeBelowMinimumPossible()
{
// http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#doc-idp124752
// Description: '7byte sized' AMQP frame header
byte[] undersizedFrameHeader = new byte[] { (byte)0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0x00 };
MemoryStream stream = new MemoryStream(undersizedFrameHeader);
TestFrameHandler handler = new TestFrameHandler();
FrameDecoder decoder = new FrameDecoder(handler);
decoder.Ingest(new MemoryStream(AMQPHeader.Header.Buffer));
Assert.AreEqual(1, handler.HeaderCount);
Assert.Throws<AssertionError>(() => decoder.Ingest(stream));
}
[Test]
public void TestInputOfFrameWithInvalidDoffBelowMinimumPossible()
{
// http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#doc-idp124752
// Description: '8byte sized' AMQP frame header with invalid doff of 1[*4 = 4bytes]
byte[] underMinDoffFrameHeader = new byte[] { (byte)0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00 };
MemoryStream stream = new MemoryStream(underMinDoffFrameHeader);
TestFrameHandler handler = new TestFrameHandler();
FrameDecoder decoder = new FrameDecoder(handler);
decoder.Ingest(new MemoryStream(AMQPHeader.Header.Buffer));
Assert.AreEqual(1, handler.HeaderCount);
Assert.Throws<AssertionError>(() => decoder.Ingest(stream));
}
[Test]
public void TestInputOfFrameWithInvalidDoffAboveMaximumPossible()
{
// http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#doc-idp124752
// Description: '8byte sized' AMQP frame header with invalid doff of 3[*4 = 12bytes]
byte[] overFrameSizeDoffFrameHeader = new byte[] { (byte)0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00 };
MemoryStream stream = new MemoryStream(overFrameSizeDoffFrameHeader);
TestFrameHandler handler = new TestFrameHandler();
FrameDecoder decoder = new FrameDecoder(handler);
decoder.Ingest(new MemoryStream(AMQPHeader.Header.Buffer));
Assert.AreEqual(1, handler.HeaderCount);
Assert.Throws<AssertionError>(() => decoder.Ingest(stream));
}
[Test]
public void TestFrameSizeThatExceedsMaximumFrameSizeLimitTriggersError()
{
byte[] overFrameSizeLimitFrameHeader = new byte[] { (byte)0xA0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 };
MemoryStream stream = new MemoryStream(overFrameSizeLimitFrameHeader);
TestFrameHandler handler = new TestFrameHandler();
handler.InboundMaxFrameSize = 16384;
FrameDecoder decoder = new FrameDecoder(handler);
decoder.Ingest(new MemoryStream(AMQPHeader.Header.Buffer));
Assert.AreEqual(1, handler.HeaderCount);
Assert.Throws<AssertionError>(() => decoder.Ingest(stream));
}
private class TestFrameHandler : IFrameHandler
{
private uint inboundMaxFrameSize = int.MaxValue;
private IList<AMQPHeader> headers = new List<AMQPHeader>();
private IList<PerformativeDescribedType> performatives = new List<PerformativeDescribedType>();
private IList<SaslDescribedType> saslPerformatives = new List<SaslDescribedType>();
private uint emptyFrameCount;
public uint InboundMaxFrameSize
{
get => inboundMaxFrameSize;
set => inboundMaxFrameSize = value;
}
public uint HeaderCount => (uint)headers.Count;
public uint EmptyFrameCount => emptyFrameCount;
public uint PerformativeCount => (uint)performatives.Count;
public uint SaslPerformativeCount => (uint)saslPerformatives.Count;
public string Name => "TestFrameHandler";
public ILoggerFactory LoggerFactory => new NullLoggerFactory();
public void HandleHeader(AMQPHeader header)
{
headers.Add(header);
}
public void HandleHeartbeat(uint frameSize, ushort channel)
{
emptyFrameCount++;
}
public void HandlePerformative(uint frameSize, PerformativeDescribedType amqp, ushort channel, byte[] payload)
{
performatives.Add(amqp);
}
public void HandleSaslPerformative(uint frameSize, SaslDescribedType sasl, ushort channel, byte[] payload)
{
saslPerformatives.Add(sasl);
}
}
}
}