1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Linq;
6 using System.Text;
7 using Xunit;
8 
9 namespace System.Tests
10 {
11     public static partial class BitConverterTests
12     {
13         [Fact]
IsLittleEndian()14         public static unsafe void IsLittleEndian()
15         {
16             short s = 1;
17             Assert.Equal(BitConverter.IsLittleEndian, *((byte*)&s) == 1);
18         }
19 
20         [Fact]
ValueArgumentNull()21         public static void ValueArgumentNull()
22         {
23             AssertExtensions.Throws<ArgumentNullException>("value", () => BitConverter.ToBoolean(null, 0));
24             AssertExtensions.Throws<ArgumentNullException>("value", () => BitConverter.ToChar(null, 0));
25             AssertExtensions.Throws<ArgumentNullException>("value", () => BitConverter.ToDouble(null, 0));
26             AssertExtensions.Throws<ArgumentNullException>("value", () => BitConverter.ToInt16(null, 0));
27             AssertExtensions.Throws<ArgumentNullException>("value", () => BitConverter.ToInt32(null, 0));
28             AssertExtensions.Throws<ArgumentNullException>("value", () => BitConverter.ToInt64(null, 0));
29             AssertExtensions.Throws<ArgumentNullException>("value", () => BitConverter.ToSingle(null, 0));
30             AssertExtensions.Throws<ArgumentNullException>("value", () => BitConverter.ToUInt16(null, 0));
31             AssertExtensions.Throws<ArgumentNullException>("value", () => BitConverter.ToUInt32(null, 0));
32             AssertExtensions.Throws<ArgumentNullException>("value", () => BitConverter.ToUInt64(null, 0));
33             AssertExtensions.Throws<ArgumentNullException>("value", () => BitConverter.ToString(null));
34             AssertExtensions.Throws<ArgumentNullException>("value", () => BitConverter.ToString(null, 0));
35             AssertExtensions.Throws<ArgumentNullException>("value", null /* param name varies in NETFX */, () => BitConverter.ToString(null, 0, 0));
36         }
37 
38         [Fact]
StartIndexBeyondLength()39         public static void StartIndexBeyondLength()
40         {
41             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToBoolean(new byte[1], -1));
42             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToBoolean(new byte[1], 1));
43             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToBoolean(new byte[1], 2));
44 
45             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToChar(new byte[2], -1));
46             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToChar(new byte[2], 2));
47             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToChar(new byte[2], 3));
48 
49             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToDouble(new byte[8], -1));
50             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToDouble(new byte[8], 8));
51             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToDouble(new byte[8], 9));
52 
53             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToInt16(new byte[2], -1));
54             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToInt16(new byte[2], 2));
55             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToInt16(new byte[2], 3));
56 
57             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToInt32(new byte[4], -1));
58             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToInt32(new byte[4], 4));
59             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToInt32(new byte[4], 5));
60 
61             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToInt64(new byte[8], -1));
62             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToInt64(new byte[8], 8));
63             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToInt64(new byte[8], 9));
64 
65             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToSingle(new byte[4], -1));
66             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToSingle(new byte[4], 4));
67             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToSingle(new byte[4], 5));
68 
69             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToUInt16(new byte[2], -1));
70             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToUInt16(new byte[2], 2));
71             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToUInt16(new byte[2], 3));
72 
73             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToUInt32(new byte[4], -1));
74             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToUInt32(new byte[4], 4));
75             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToUInt32(new byte[4], 5));
76 
77             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToUInt64(new byte[8], -1));
78             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToUInt64(new byte[8], 8));
79             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToUInt64(new byte[8], 9));
80 
81             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToString(new byte[1], -1));
82             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToString(new byte[1], 1));
83             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToString(new byte[1], 2));
84 
85             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToString(new byte[1], -1, 0));
86             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToString(new byte[1], 1, 0));
87             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToString(new byte[1], 2, 0));
88 
89             AssertExtensions.Throws<ArgumentOutOfRangeException>("length", () => BitConverter.ToString(new byte[1], 0, -1));
90         }
91 
92         [Fact]
StartIndexPlusNeededLengthTooLong()93         public static void StartIndexPlusNeededLengthTooLong()
94         {
95             AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => BitConverter.ToBoolean(new byte[0], 0));
96             AssertExtensions.Throws<ArgumentException>("value", null, () => BitConverter.ToChar(new byte[2], 1));
97             AssertExtensions.Throws<ArgumentException>("value", null, () => BitConverter.ToDouble(new byte[8], 1));
98             AssertExtensions.Throws<ArgumentException>("value", null, () => BitConverter.ToInt16(new byte[2], 1));
99             AssertExtensions.Throws<ArgumentException>("value", null, () => BitConverter.ToInt32(new byte[4], 1));
100             AssertExtensions.Throws<ArgumentException>("value", null, () => BitConverter.ToInt64(new byte[8], 1));
101             AssertExtensions.Throws<ArgumentException>("value", null, () => BitConverter.ToSingle(new byte[4], 1));
102             AssertExtensions.Throws<ArgumentException>("value", null, () => BitConverter.ToUInt16(new byte[2], 1));
103             AssertExtensions.Throws<ArgumentException>("value", null, () => BitConverter.ToUInt32(new byte[4], 1));
104             AssertExtensions.Throws<ArgumentException>("value", null, () => BitConverter.ToUInt64(new byte[8], 1));
105             AssertExtensions.Throws<ArgumentException>("value", null, () => BitConverter.ToString(new byte[2], 1, 2));
106         }
107 
108         [Fact]
DoubleToInt64Bits()109         public static void DoubleToInt64Bits()
110         {
111             double input = 123456.3234;
112             long result = BitConverter.DoubleToInt64Bits(input);
113             Assert.Equal(4683220267154373240L, result);
114             double roundtripped = BitConverter.Int64BitsToDouble(result);
115             Assert.Equal(input, roundtripped);
116         }
117 
118         [Fact]
RoundtripBoolean()119         public static void RoundtripBoolean()
120         {
121             byte[] bytes = BitConverter.GetBytes(true);
122             Assert.Equal(1, bytes.Length);
123             Assert.Equal(1, bytes[0]);
124             Assert.True(BitConverter.ToBoolean(bytes, 0));
125 
126             bytes = BitConverter.GetBytes(false);
127             Assert.Equal(1, bytes.Length);
128             Assert.Equal(0, bytes[0]);
129             Assert.False(BitConverter.ToBoolean(bytes, 0));
130         }
131 
132         [Fact]
RoundtripChar()133         public static void RoundtripChar()
134         {
135             char input = 'A';
136             byte[] expected = { 0x41, 0 };
137             VerifyRoundtrip(BitConverter.GetBytes, BitConverter.ToChar, input, expected);
138         }
139 
140         [Fact]
RoundtripDouble()141         public static void RoundtripDouble()
142         {
143             double input = 123456.3234;
144             byte[] expected = { 0x78, 0x7a, 0xa5, 0x2c, 0x05, 0x24, 0xfe, 0x40 };
145             VerifyRoundtrip(BitConverter.GetBytes, BitConverter.ToDouble, input, expected);
146         }
147 
148         [Fact]
RoundtripSingle()149         public static void RoundtripSingle()
150         {
151             float input = 8392.34f;
152             byte[] expected = { 0x5c, 0x21, 0x03, 0x46 };
153             VerifyRoundtrip(BitConverter.GetBytes, BitConverter.ToSingle, input, expected);
154         }
155 
156         [Fact]
RoundtripInt16()157         public static void RoundtripInt16()
158         {
159             short input = 0x1234;
160             byte[] expected = { 0x34, 0x12 };
161             VerifyRoundtrip(BitConverter.GetBytes, BitConverter.ToInt16, input, expected);
162         }
163 
164         [Fact]
RoundtripInt32()165         public static void RoundtripInt32()
166         {
167             int input = 0x12345678;
168             byte[] expected = { 0x78, 0x56, 0x34, 0x12 };
169             VerifyRoundtrip(BitConverter.GetBytes, BitConverter.ToInt32, input, expected);
170         }
171 
172         [Fact]
RoundtripInt64()173         public static void RoundtripInt64()
174         {
175             long input = 0x0123456789abcdef;
176             byte[] expected = { 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01 };
177             VerifyRoundtrip(BitConverter.GetBytes, BitConverter.ToInt64, input, expected);
178         }
179 
180         [Fact]
RoundtripUInt16()181         public static void RoundtripUInt16()
182         {
183             ushort input = 0x1234;
184             byte[] expected = { 0x34, 0x12 };
185             VerifyRoundtrip(BitConverter.GetBytes, BitConverter.ToUInt16, input, expected);
186         }
187 
188         [Fact]
RoundtripUInt32()189         public static void RoundtripUInt32()
190         {
191             uint input = 0x12345678;
192             byte[] expected = { 0x78, 0x56, 0x34, 0x12 };
193             VerifyRoundtrip(BitConverter.GetBytes, BitConverter.ToUInt32, input, expected);
194         }
195 
196         [Fact]
RoundtripUInt64()197         public static void RoundtripUInt64()
198         {
199             ulong input = 0x0123456789abcdef;
200             byte[] expected = { 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01 };
201             VerifyRoundtrip(BitConverter.GetBytes, BitConverter.ToUInt64, input, expected);
202         }
203 
204         [Fact]
RoundtripString()205         public static void RoundtripString()
206         {
207             byte[] bytes = { 0x12, 0x34, 0x56, 0x78, 0x9a };
208 
209             Assert.Equal("12-34-56-78-9A", BitConverter.ToString(bytes));
210             Assert.Equal("56-78-9A", BitConverter.ToString(bytes, 2));
211             Assert.Equal("56", BitConverter.ToString(bytes, 2, 1));
212 
213             Assert.Same(string.Empty, BitConverter.ToString(new byte[0]));
214             Assert.Same(string.Empty, BitConverter.ToString(new byte[3], 1, 0));
215         }
216 
217         [Fact]
ToString_ByteArray_Long()218         public static void ToString_ByteArray_Long()
219         {
220             byte[] bytes = Enumerable.Range(0, 256 * 4).Select(i => unchecked((byte)i)).ToArray();
221 
222             string expected = string.Join("-", bytes.Select(b => b.ToString("X2")));
223 
224             Assert.Equal(expected, BitConverter.ToString(bytes));
225             Assert.Equal(expected.Substring(3, expected.Length - 6), BitConverter.ToString(bytes, 1, bytes.Length - 2));
226         }
227 
228         [Fact]
ToString_ByteArrayTooLong_Throws()229         public static void ToString_ByteArrayTooLong_Throws()
230         {
231             byte[] arr;
232             try
233             {
234                 arr = new byte[int.MaxValue / 3 + 1];
235             }
236             catch (OutOfMemoryException)
237             {
238                 // Exit out of the test if we don't have an enough contiguous memory
239                 // available to create a big enough array.
240                 return;
241             }
242 
243             AssertExtensions.Throws<ArgumentOutOfRangeException>("length", () => BitConverter.ToString(arr));
244         }
245 
VerifyRoundtrip(Func<TInput, Byte[]> getBytes, Func<Byte[], int, TInput> convertBack, TInput input, Byte[] expectedBytes)246         private static void VerifyRoundtrip<TInput>(Func<TInput, Byte[]> getBytes, Func<Byte[], int, TInput> convertBack, TInput input, Byte[] expectedBytes)
247         {
248             byte[] bytes = getBytes(input);
249             Assert.Equal(expectedBytes.Length, bytes.Length);
250 
251             if (!BitConverter.IsLittleEndian)
252             {
253                 Array.Reverse(expectedBytes);
254             }
255 
256             Assert.Equal(expectedBytes, bytes);
257             Assert.Equal(input, convertBack(bytes, 0));
258 
259             // Also try unaligned startIndex
260             byte[] longerBytes = new byte[bytes.Length + 1];
261             longerBytes[0] = 0;
262             Array.Copy(bytes, 0, longerBytes, 1, bytes.Length);
263             Assert.Equal(input, convertBack(longerBytes, 1));
264         }
265     }
266 }
267