#region Copyright notice and license

// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://github.com/jskeet/dotnet-protobufs/
// Original C++/Java/Python code:
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#endregion

using System;
using System.Collections.Generic;
using System.IO;
using Google.Protobuf.Collections;
using Google.Protobuf.Descriptors;
using Google.Protobuf.TestProtos;
using NUnit.Framework;

namespace Google.Protobuf
{
    public class CodedInputStreamTest
    {
        /// <summary>
        /// Helper to construct a byte array from a bunch of bytes.  The inputs are
        /// actually ints so that I can use hex notation and not get stupid errors
        /// about precision.
        /// </summary>
        private static byte[] Bytes(params int[] bytesAsInts)
        {
            byte[] bytes = new byte[bytesAsInts.Length];
            for (int i = 0; i < bytesAsInts.Length; i++)
            {
                bytes[i] = (byte) bytesAsInts[i];
            }
            return bytes;
        }

        /// <summary>
        /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
        /// </summary>
        private static void AssertReadVarint(byte[] data, ulong value)
        {
            CodedInputStream input = CodedInputStream.CreateInstance(data);
            Assert.AreEqual((uint) value, input.ReadRawVarint32());

            input = CodedInputStream.CreateInstance(data);
            Assert.AreEqual(value, input.ReadRawVarint64());
            Assert.IsTrue(input.IsAtEnd);

            // Try different block sizes.
            for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
            {
                input = CodedInputStream.CreateInstance(new SmallBlockInputStream(data, bufferSize));
                Assert.AreEqual((uint) value, input.ReadRawVarint32());

                input = CodedInputStream.CreateInstance(new SmallBlockInputStream(data, bufferSize));
                Assert.AreEqual(value, input.ReadRawVarint64());
                Assert.IsTrue(input.IsAtEnd);
            }

            // Try reading directly from a MemoryStream. We want to verify that it
            // doesn't read past the end of the input, so write an extra byte - this
            // lets us test the position at the end.
            MemoryStream memoryStream = new MemoryStream();
            memoryStream.Write(data, 0, data.Length);
            memoryStream.WriteByte(0);
            memoryStream.Position = 0;
            Assert.AreEqual((uint) value, CodedInputStream.ReadRawVarint32(memoryStream));
            Assert.AreEqual(data.Length, memoryStream.Position);
        }

        /// <summary>
        /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
        /// expects them to fail with an InvalidProtocolBufferException whose
        /// description matches the given one.
        /// </summary>
        private static void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
        {
            CodedInputStream input = CodedInputStream.CreateInstance(data);
            var exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint32());
            Assert.AreEqual(expected.Message, exception.Message);

            input = CodedInputStream.CreateInstance(data);
            exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint64());
            Assert.AreEqual(expected.Message, exception.Message);

            // Make sure we get the same error when reading directly from a Stream.
            exception = Assert.Throws<InvalidProtocolBufferException>(() => CodedInputStream.ReadRawVarint32(new MemoryStream(data)));
            Assert.AreEqual(expected.Message, exception.Message);
        }

        [Test]
        public void ReadVarint()
        {
            AssertReadVarint(Bytes(0x00), 0);
            AssertReadVarint(Bytes(0x01), 1);
            AssertReadVarint(Bytes(0x7f), 127);
            // 14882
            AssertReadVarint(Bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
            // 2961488830
            AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
                             (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
                             (0x0bL << 28));

            // 64-bit
            // 7256456126
            AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
                             (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
                             (0x1bL << 28));
            // 41256202580718336
            AssertReadVarint(Bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
                             (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
                             (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
            // 11964378330978735131
            AssertReadVarint(Bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
                             (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
                             (0x3bUL << 28) | (0x56UL << 35) | (0x00UL << 42) |
                             (0x05UL << 49) | (0x26UL << 56) | (0x01UL << 63));

            // Failures
            AssertReadVarintFailure(
                InvalidProtocolBufferException.MalformedVarint(),
                Bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
                      0x00));
            AssertReadVarintFailure(
                InvalidProtocolBufferException.TruncatedMessage(),
                Bytes(0x80));
        }

        /// <summary>
        /// Parses the given bytes using ReadRawLittleEndian32() and checks
        /// that the result matches the given value.
        /// </summary>
        private static void AssertReadLittleEndian32(byte[] data, uint value)
        {
            CodedInputStream input = CodedInputStream.CreateInstance(data);
            Assert.AreEqual(value, input.ReadRawLittleEndian32());
            Assert.IsTrue(input.IsAtEnd);

            // Try different block sizes.
            for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
            {
                input = CodedInputStream.CreateInstance(
                    new SmallBlockInputStream(data, blockSize));
                Assert.AreEqual(value, input.ReadRawLittleEndian32());
                Assert.IsTrue(input.IsAtEnd);
            }
        }

        /// <summary>
        /// Parses the given bytes using ReadRawLittleEndian64() and checks
        /// that the result matches the given value.
        /// </summary>
        private static void AssertReadLittleEndian64(byte[] data, ulong value)
        {
            CodedInputStream input = CodedInputStream.CreateInstance(data);
            Assert.AreEqual(value, input.ReadRawLittleEndian64());
            Assert.IsTrue(input.IsAtEnd);

            // Try different block sizes.
            for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
            {
                input = CodedInputStream.CreateInstance(
                    new SmallBlockInputStream(data, blockSize));
                Assert.AreEqual(value, input.ReadRawLittleEndian64());
                Assert.IsTrue(input.IsAtEnd);
            }
        }

        [Test]
        public void ReadLittleEndian()
        {
            AssertReadLittleEndian32(Bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
            AssertReadLittleEndian32(Bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);

            AssertReadLittleEndian64(Bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
                                     0x123456789abcdef0L);
            AssertReadLittleEndian64(
                Bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678UL);
        }

        [Test]
        public void DecodeZigZag32()
        {
            Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(0));
            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1));
            Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(2));
            Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3));
            Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE));
            Assert.AreEqual(unchecked((int) 0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF));
            Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE));
            Assert.AreEqual(unchecked((int) 0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF));
        }

        [Test]
        public void DecodeZigZag64()
        {
            Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(0));
            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1));
            Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(2));
            Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3));
            Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL));
            Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL));
            Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL));
            Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL));
            Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL));
            Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL));
        }
        /*
        [Test]
        public void ReadWholeMessage()
        {
            TestAllTypes message = TestUtil.GetAllSet();

            byte[] rawBytes = message.ToByteArray();
            Assert.AreEqual(rawBytes.Length, message.SerializedSize);
            TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
            TestUtil.AssertAllFieldsSet(message2);

            // Try different block sizes.
            for (int blockSize = 1; blockSize < 256; blockSize *= 2)
            {
                message2 = TestAllTypes.ParseFrom(new SmallBlockInputStream(rawBytes, blockSize));
                TestUtil.AssertAllFieldsSet(message2);
            }
        }

        [Test]
        public void SkipWholeMessage()
        {
            TestAllTypes message = TestUtil.GetAllSet();
            byte[] rawBytes = message.ToByteArray();

            // Create two parallel inputs.  Parse one as unknown fields while using
            // skipField() to skip each field on the other.  Expect the same tags.
            CodedInputStream input1 = CodedInputStream.CreateInstance(rawBytes);
            CodedInputStream input2 = CodedInputStream.CreateInstance(rawBytes);
            UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder();

            uint tag;
            string name;
            while (input1.ReadTag(out tag, out name))
            {
                uint tag2;
                Assert.IsTrue(input2.ReadTag(out tag2, out name));
                Assert.AreEqual(tag, tag2);

                unknownFields.MergeFieldFrom(tag, input1);
                input2.SkipField();
            }
        }*/

        /// <summary>
        /// Test that a bug in SkipRawBytes has been fixed: if the skip
        /// skips exactly up to a limit, this should bnot break things
        /// </summary>
        [Test]
        public void SkipRawBytesBug()
        {
            byte[] rawBytes = new byte[] {1, 2};
            CodedInputStream input = CodedInputStream.CreateInstance(rawBytes);

            int limit = input.PushLimit(1);
            input.SkipRawBytes(1);
            input.PopLimit(limit);
            Assert.AreEqual(2, input.ReadRawByte());
        }
        /*
        public void ReadHugeBlob()
        {
            // Allocate and initialize a 1MB blob.
            byte[] blob = new byte[1 << 20];
            for (int i = 0; i < blob.Length; i++)
            {
                blob[i] = (byte) i;
            }

            // Make a message containing it.
            TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
            TestUtil.SetAllFields(builder);
            builder.SetOptionalBytes(ByteString.CopyFrom(blob));
            TestAllTypes message = builder.Build();

            // Serialize and parse it.  Make sure to parse from an InputStream, not
            // directly from a ByteString, so that CodedInputStream uses buffered
            // reading.
            TestAllTypes message2 = TestAllTypes.ParseFrom(message.ToByteString().CreateCodedInput());

            Assert.AreEqual(message.OptionalBytes, message2.OptionalBytes);

            // Make sure all the other fields were parsed correctly.
            TestAllTypes message3 = TestAllTypes.CreateBuilder(message2)
                .SetOptionalBytes(TestUtil.GetAllSet().OptionalBytes)
                .Build();
            TestUtil.AssertAllFieldsSet(message3);
        }*/

        [Test]
        public void ReadMaliciouslyLargeBlob()
        {
            MemoryStream ms = new MemoryStream();
            CodedOutputStream output = CodedOutputStream.CreateInstance(ms);

            uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
            output.WriteRawVarint32(tag);
            output.WriteRawVarint32(0x7FFFFFFF);
            output.WriteRawBytes(new byte[32]); // Pad with a few random bytes.
            output.Flush();
            ms.Position = 0;

            CodedInputStream input = CodedInputStream.CreateInstance(ms);
            uint testtag;
            Assert.IsTrue(input.ReadTag(out testtag));
            Assert.AreEqual(tag, testtag);

            // TODO(jonskeet): Should this be ArgumentNullException instead?
            Assert.Throws<InvalidProtocolBufferException>(() => input.ReadBytes());
        }

        private static TestRecursiveMessage MakeRecursiveMessage(int depth)
        {
            if (depth == 0)
            {
                return new TestRecursiveMessage { I = 5 };
            }
            else
            {
                return new TestRecursiveMessage { A = MakeRecursiveMessage(depth - 1) };
            }
        }

        private static void AssertMessageDepth(TestRecursiveMessage message, int depth)
        {
            if (depth == 0)
            {
                Assert.IsNull(message.A);
                Assert.AreEqual(5, message.I);
            }
            else
            {
                Assert.IsNotNull(message.A);
                AssertMessageDepth(message.A, depth - 1);
            }
        }

        [Test]
        public void MaliciousRecursion()
        {
            ByteString data64 = MakeRecursiveMessage(64).ToByteString();
            ByteString data65 = MakeRecursiveMessage(65).ToByteString();

            AssertMessageDepth(TestRecursiveMessage.Parser.ParseFrom(data64), 64);

            Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(data65));

            CodedInputStream input = data64.CreateCodedInput();
            input.SetRecursionLimit(8);
            Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(input));
        }

        /*
        [Test]
        public void SizeLimit()
        {
            // Have to use a Stream rather than ByteString.CreateCodedInput as SizeLimit doesn't
            // apply to the latter case.
            MemoryStream ms = new MemoryStream(TestUtil.GetAllSet().ToByteString().ToByteArray());
            CodedInputStream input = CodedInputStream.CreateInstance(ms);
            input.SetSizeLimit(16);

            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.ParseFrom(input));
        }*/

        [Test]
        public void ResetSizeCounter()
        {
            CodedInputStream input = CodedInputStream.CreateInstance(
                new SmallBlockInputStream(new byte[256], 8));
            input.SetSizeLimit(16);
            input.ReadRawBytes(16);

            Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawByte());

            input.ResetSizeCounter();
            input.ReadRawByte(); // No exception thrown.

            Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawBytes(16));
        }

        /// <summary>
        /// Tests that if we read an string that contains invalid UTF-8, no exception
        /// is thrown.  Instead, the invalid bytes are replaced with the Unicode
        /// "replacement character" U+FFFD.
        /// </summary>
        [Test]
        public void ReadInvalidUtf8()
        {
            MemoryStream ms = new MemoryStream();
            CodedOutputStream output = CodedOutputStream.CreateInstance(ms);

            uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
            output.WriteRawVarint32(tag);
            output.WriteRawVarint32(1);
            output.WriteRawBytes(new byte[] {0x80});
            output.Flush();
            ms.Position = 0;

            CodedInputStream input = CodedInputStream.CreateInstance(ms);

            uint actualTag;
            Assert.IsTrue(input.ReadTag(out actualTag));
            Assert.AreEqual(tag, actualTag);
            string text = input.ReadString();
            Assert.AreEqual('\ufffd', text[0]);
        }

        /// <summary>
        /// A stream which limits the number of bytes it reads at a time.
        /// We use this to make sure that CodedInputStream doesn't screw up when
        /// reading in small blocks.
        /// </summary>
        private sealed class SmallBlockInputStream : MemoryStream
        {
            private readonly int blockSize;

            public SmallBlockInputStream(byte[] data, int blockSize)
                : base(data)
            {
                this.blockSize = blockSize;
            }

            public override int Read(byte[] buffer, int offset, int count)
            {
                return base.Read(buffer, offset, Math.Min(count, blockSize));
            }
        }

        enum TestNegEnum { None = 0, Value = -2 }

        [Test]
        public void TestNegativeEnum()
        {
            byte[] bytes = new byte[10] { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 };
            CodedInputStream input = CodedInputStream.CreateInstance(bytes);
            Assert.AreEqual((int)TestNegEnum.Value, input.ReadEnum());
            Assert.IsTrue(input.IsAtEnd);
        }

        [Test]
        public void TestNegativeEnumPackedArray()
        {
            int arraySize = 1 + (10 * 5);
            int msgSize = 1 + 1 + arraySize;
            byte[] bytes = new byte[msgSize];
            CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
            output.WritePackedInt32Array(8, new RepeatedField<int> { 0, -1, -2, -3, -4, -5 });

            Assert.AreEqual(0, output.SpaceLeft);

            CodedInputStream input = CodedInputStream.CreateInstance(bytes);
            uint tag;
            Assert.IsTrue(input.ReadTag(out tag));

            List<TestNegEnum> values = new List<TestNegEnum>();
            input.ReadEnumArray(tag, values);

            Assert.AreEqual(6, values.Count);
            Assert.AreEqual(TestNegEnum.None, values[0]);
            Assert.AreEqual(TestNegEnum.Value, values[2]);
            // TODO(jonskeet): Test unknown value preservation
        }

        [Test]
        public void TestNegativeEnumArray()
        {
            int arraySize = 1 + 1 + (11 * 5);
            int msgSize = arraySize;
            byte[] bytes = new byte[msgSize];
            CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
            output.WriteInt32Array(8, new RepeatedField<int> { 0, -1, -2, -3, -4, -5 });

            Assert.AreEqual(0, output.SpaceLeft);

            CodedInputStream input = CodedInputStream.CreateInstance(bytes);
            uint tag;
            Assert.IsTrue(input.ReadTag(out tag));

            List<TestNegEnum> values = new List<TestNegEnum>();
            input.ReadEnumArray(tag, values);

            Assert.AreEqual(6, values.Count);
            Assert.AreEqual(TestNegEnum.None, values[0]);
            Assert.AreEqual(TestNegEnum.Value, values[2]);
            // TODO(jonskeet): Test unknown value preservation
        }

        //Issue 71:	CodedInputStream.ReadBytes go to slow path unnecessarily
        [Test]
        public void TestSlowPathAvoidance()
        {
            using (var ms = new MemoryStream())
            {
                CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
                output.WriteBytes(1, ByteString.CopyFrom(new byte[100]));
                output.WriteBytes(2, ByteString.CopyFrom(new byte[100]));
                output.Flush();

                ms.Position = 0;
                CodedInputStream input = CodedInputStream.CreateInstance(ms, new byte[ms.Length / 2]);

                uint tag;
                Assert.IsTrue(input.ReadTag(out tag));
                Assert.AreEqual(1, WireFormat.GetTagFieldNumber(tag));
                Assert.AreEqual(100, input.ReadBytes().Length);

                Assert.IsTrue(input.ReadTag(out tag));
                Assert.AreEqual(2, WireFormat.GetTagFieldNumber(tag));
                Assert.AreEqual(100, input.ReadBytes().Length);
            }
        }
    }
}