/*
 * 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.IO;
using Apache.NMS.Util;
using NUnit.Framework;

namespace Apache.NMS.Test
{
	[TestFixture]
	public class EndianBinaryReaderTest
	{
		public void readString16Helper(byte[] input, char[] expect)
		{
			MemoryStream stream = new MemoryStream(input);
			EndianBinaryReader reader = new EndianBinaryReader(stream);

			char[] result = reader.ReadString16().ToCharArray();

			for(int i = 0; i < expect.Length; ++i)
			{
				Assert.AreEqual(expect[i], result[i]);
			}
		}

		[Test]
		public void testReadString16_1byteUTF8encoding()
		{
			// Test data with 1-byte UTF8 encoding.
			char[] expect = { '\u0000', '\u000B', '\u0048', '\u0065', '\u006C', '\u006C', '\u006F', '\u0020', '\u0057', '\u006F', '\u0072', '\u006C', '\u0064' };
			byte[] input = { 0x00, 0x0E, 0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 };

			readString16Helper(input, expect);
		}

		[Test]
		public void testReadString16_2byteUTF8encoding()
		{
			// Test data with 2-byte UT8 encoding.
			char[] expect = { '\u0000', '\u00C2', '\u00A9', '\u00C3', '\u00A6' };
			byte[] input = { 0x00, 0x0A, 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
			readString16Helper(input, expect);
		}

		[Test]
		public void testReadString16_1byteAnd2byteEmbeddedNULLs()
		{
			// Test data with 1-byte and 2-byte encoding with embedded NULL's.
			char[] expect = { '\u0000', '\u0004', '\u00C2', '\u00A9', '\u00C3', '\u0000', '\u00A6' };
			byte[] input = { 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };

			readString16Helper(input, expect);
		}

		[Test]
		[ExpectedException(typeof(IOException))]
		public void testReadString16_UTF8Missing2ndByte()
		{
			// Test with bad UTF-8 encoding, missing 2nd byte of two byte value
			byte[] input = { 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };

			MemoryStream stream = new MemoryStream(input);
			EndianBinaryReader reader = new EndianBinaryReader(stream);

			reader.ReadString16();
		}

		[Test]
		[ExpectedException(typeof(IOException))]
		public void testReadString16_3byteEncodingMissingLastByte()
		{
			// Test with three byte encode that's missing a last byte.
			byte[] input = { 0x00, 0x02, 0xE8, 0xA8 };

			MemoryStream stream = new MemoryStream(input);
			EndianBinaryReader reader = new EndianBinaryReader(stream);

			reader.ReadString16();
		}

		public void readString32Helper(byte[] input, char[] expect)
		{
			MemoryStream stream = new MemoryStream(input);
			EndianBinaryReader reader = new EndianBinaryReader(stream);

			char[] result = reader.ReadString32().ToCharArray();

			for(int i = 0; i < expect.Length; ++i)
			{
				Assert.AreEqual(expect[i], result[i]);
			}
		}

		[Test]
		public void testReadString32_1byteUTF8encoding()
		{
			// Test data with 1-byte UTF8 encoding.
			char[] expect = { '\u0000', '\u000B', '\u0048', '\u0065', '\u006C', '\u006C', '\u006F', '\u0020', '\u0057', '\u006F', '\u0072', '\u006C', '\u0064' };
			byte[] input = { 0x00, 0x00, 0x00, 0x0E, 0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 };

			readString32Helper(input, expect);
		}

		[Test]
		public void testReadString32_2byteUTF8encoding()
		{
			// Test data with 2-byte UT8 encoding.
			char[] expect = { '\u0000', '\u00C2', '\u00A9', '\u00C3', '\u00A6' };
			byte[] input = { 0x00, 0x00, 0x00, 0x0A, 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
			readString32Helper(input, expect);
		}

		[Test]
		public void testReadString32_1byteAnd2byteEmbeddedNULLs()
		{
			// Test data with 1-byte and 2-byte encoding with embedded NULL's.
			char[] expect = { '\u0000', '\u0004', '\u00C2', '\u00A9', '\u00C3', '\u0000', '\u00A6' };
			byte[] input = { 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };

			readString32Helper(input, expect);
		}

		[Test]
		[ExpectedException(typeof(IOException))]
		public void testReadString32_UTF8Missing2ndByte()
		{
			// Test with bad UTF-8 encoding, missing 2nd byte of two byte value
			byte[] input = { 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };

			MemoryStream stream = new MemoryStream(input);
			EndianBinaryReader reader = new EndianBinaryReader(stream);

			reader.ReadString32();
		}

		[Test]
		[ExpectedException(typeof(IOException))]
		public void testReadString32_3byteEncodingMissingLastByte()
		{
			// Test with three byte encode that's missing a last byte.
			byte[] input = { 0x00, 0x00, 0x00, 0x02, 0xE8, 0xA8 };

			MemoryStream stream = new MemoryStream(input);
			EndianBinaryReader reader = new EndianBinaryReader(stream);

			reader.ReadString32();
		}
	}
}
