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.Collections.Generic;
6 using System.Text;
7 using Xunit;
8 
9 namespace System.Text.Encodings.Tests
10 {
11     public class EncoderMiscTests
12     {
13         [Fact]
ConvertTest()14         public static unsafe void ConvertTest()
15         {
16             string s1 = "This is simple ascii string";
17             string s2 = "\uD800\uDC00\u0200";           // non ascii letters
18             string s3 = s1 + s2;
19 
20             Encoding utf8 = Encoding.UTF8;
21             Encoder encoder = utf8.GetEncoder();
22 
23             byte [] bytes1 = utf8.GetBytes(s1);
24             byte [] bytes2 = utf8.GetBytes(s2);
25             byte [] bytes3 = utf8.GetBytes(s3);
26 
27             byte [] bytes = new byte[50];
28 
29 	        int bytesUsed;
30 	        int charsUsed;
31 	        bool completed;
32 
33             fixed (char *pChars1 = s1)
34             fixed (char *pChars2 = s2)
35             fixed (char *pChars3 = s3)
36             fixed (byte *pBytes = bytes)
37             {
38                 encoder.Convert(pChars1, s1.Length, pBytes, bytes.Length, true, out charsUsed, out bytesUsed, out completed);
39                 Assert.Equal(s1.Length, charsUsed);
40                 Assert.Equal(bytes1.Length, bytesUsed);
41                 Assert.True(completed, "Expected to have the full operation compeleted with bytes1");
42                 for (int i=0; i<bytes1.Length; i++) { Assert.Equal(bytes1[i], pBytes[i]); }
43 
44                 encoder.Convert(pChars2, s2.Length, pBytes, bytes.Length, true, out charsUsed, out bytesUsed, out completed);
45                 Assert.Equal(s2.Length, charsUsed);
46                 Assert.Equal(bytes2.Length, bytesUsed);
47                 Assert.True(completed, "Expected to have the full operation compeleted with bytes2");
48                 for (int i=0; i<bytes2.Length; i++) { Assert.Equal(bytes2[i], pBytes[i]); }
49 
50                 encoder.Convert(pChars3, s3.Length, pBytes, bytes.Length, true, out charsUsed, out bytesUsed, out completed);
51                 Assert.Equal(s3.Length, charsUsed);
52                 Assert.Equal(bytes3.Length, bytesUsed);
53                 Assert.True(completed, "Expected to have the full operation compeleted with bytes3");
54                 for (int i=0; i<bytes3.Length; i++) { Assert.Equal(bytes3[i], pBytes[i]); }
55 
56                 encoder.Convert(pChars3 + s1.Length, s3.Length - s1.Length, pBytes, bytes.Length, true, out charsUsed, out bytesUsed, out completed);
57                 Assert.Equal(s2.Length, charsUsed);
58                 Assert.Equal(bytes2.Length, bytesUsed);
59                 Assert.True(completed, "Expected to have the full operation compeleted with bytes3+bytes1.Length");
60                 for (int i=0; i<bytes2.Length; i++) { Assert.Equal(bytes2[i], pBytes[i]); }
61 
62                 encoder.Convert(pChars3 + s1.Length, s3.Length - s1.Length, pBytes, 4, true, out charsUsed, out bytesUsed, out completed);
63                 Assert.Equal(2, charsUsed);
64                 Assert.True(bytes2.Length > bytesUsed, "Expected to use less bytes when there is not enough char buffer");
65                 Assert.False(completed, "Expected to have the operation not fully completed");
66                 for (int i=0; i<bytesUsed; i++) { Assert.Equal(bytes2[i], pBytes[i]); }
67 
68                 encoder.Convert(pChars3 + s3.Length - 1, 1, pBytes, 2, true, out charsUsed, out bytesUsed, out completed);
69                 Assert.Equal(1, charsUsed);
70                 Assert.Equal(2, bytesUsed);
71                 Assert.True(completed, "expected to flush the remaining character");
72                 Assert.Equal(bytes2[bytes2.Length - 2], pBytes[0]);
73                 Assert.Equal(bytes2[bytes2.Length - 1], pBytes[1]);
74             }
75         }
76 
77         [Fact]
ConvertNegativeTest()78         public static unsafe void ConvertNegativeTest()
79         {
80             Encoder encoder = Encoding.UTF8.GetEncoder();
81 	        int bytesUsed;
82 	        int charsUsed;
83 	        bool completed;
84 
85             string chars = "\u0D800\uDC00";
86             byte [] bytes = new byte[4];
87 
88             fixed (byte *bytesPtr = bytes)
89             fixed (char *charsPtr = chars)
90             {
91                 byte *pBytes = bytesPtr;
92                 char *pChars = charsPtr;
93 
94                 AssertExtensions.Throws<ArgumentNullException>("chars", () => encoder.Convert(null, chars.Length, pBytes, bytes.Length, true, out charsUsed, out bytesUsed, out completed));
95                 AssertExtensions.Throws<ArgumentNullException>("bytes", () => encoder.Convert(pChars, chars.Length, null, bytes.Length, true, out charsUsed, out bytesUsed, out completed));
96 
97                 AssertExtensions.Throws<ArgumentOutOfRangeException>("byteCount", () => encoder.Convert(pChars, chars.Length, pBytes, -1, true, out charsUsed, out bytesUsed, out completed));
98                 AssertExtensions.Throws<ArgumentOutOfRangeException>("charCount", () => encoder.Convert(pChars, -1, pBytes, bytes.Length, true, out charsUsed, out bytesUsed, out completed));
99 
100                 AssertExtensions.Throws<ArgumentException>("bytes", () => encoder.Convert(pChars, chars.Length, pBytes, 0, true, out charsUsed, out bytesUsed, out completed));
101             }
102 
103             encoder = Encoding.GetEncoding("us-ascii", new EncoderExceptionFallback(), new DecoderExceptionFallback()).GetEncoder();
104 
105             fixed (char *charsPtr = "\uFFFF")
106             fixed (byte *bytesPtr = new byte [2])
107             {
108                 byte *pBytes = bytesPtr;
109                 char *pChars = charsPtr;
110 
111                 Assert.Throws<EncoderFallbackException>(() => encoder.Convert(pChars, 1, pBytes, 2, true, out charsUsed, out bytesUsed, out completed));
112             }
113         }
114 
115         [Fact]
GetBytesTest()116         public static unsafe void GetBytesTest()
117         {
118             string s1 = "This is simple ascii string";
119             string s2 = "\uD800\uDC00\u0200";           // non ascii letters
120             string s3 = s1 + s2;
121 
122             Encoding utf8 = Encoding.UTF8;
123             Encoder encoder = utf8.GetEncoder();
124             byte [] bytes = new byte[200];
125 
126             byte [] bytes1 = utf8.GetBytes(s1);
127             byte [] bytes2 = utf8.GetBytes(s2);
128             byte [] bytes3 = utf8.GetBytes(s3);
129 
130             fixed (char *pChars1 = s1)
131             fixed (char *pChars2 = s2)
132             fixed (char *pChars3 = s3)
133             fixed (byte *pBytes = bytes)
134             {
135                 int bytesUsed = encoder.GetBytes(pChars1, s1.Length, pBytes, bytes.Length, true);
136                 Assert.Equal(bytes1.Length, bytesUsed);
137                 Assert.Equal(bytes1.Length, encoder.GetByteCount(pChars1, s1.Length, true));
138                 for (int i=0; i<bytesUsed; i++) { Assert.Equal(bytes1[i], pBytes[i]); }
139 
140                 bytesUsed = encoder.GetBytes(pChars2, s2.Length, pBytes, bytes.Length, true);
141                 Assert.Equal(bytes2.Length, bytesUsed);
142                 Assert.Equal(bytes2.Length, encoder.GetByteCount(pChars2, s2.Length, true));
143                 for (int i=0; i<bytesUsed; i++) { Assert.Equal(bytes2[i], pBytes[i]); }
144 
145                 bytesUsed = encoder.GetBytes(pChars3, s3.Length, pBytes, bytes.Length, true);
146                 Assert.Equal(bytes3.Length, bytesUsed);
147                 Assert.Equal(bytes3.Length, encoder.GetByteCount(pChars3, s3.Length, true));
148                 for (int i=0; i<bytesUsed; i++) { Assert.Equal(bytes3[i], pBytes[i]); }
149 
150                 bytesUsed = encoder.GetBytes(pChars3 + s1.Length, s3.Length - s1.Length, pBytes, bytes.Length, true);
151                 Assert.Equal(bytes2.Length, bytesUsed);
152                 Assert.Equal(bytes2.Length, encoder.GetByteCount(pChars3 + s1.Length, s3.Length - s1.Length, true));
153                 for (int i=0; i<bytesUsed; i++) { Assert.Equal(bytes2[i], pBytes[i]); }
154             }
155         }
156 
157         [Fact]
GetBytesNegativeTest()158         public static unsafe void GetBytesNegativeTest()
159         {
160             Encoder encoder = Encoding.UTF8.GetEncoder();
161             string s = "\u0D800\uDC00";
162 
163             fixed (char *charsPtr = s)
164             fixed (byte *bytesPtr = new byte [4])
165             {
166                 byte *pBytes = bytesPtr;
167                 char *pChars = charsPtr;
168 
169                 AssertExtensions.Throws<ArgumentNullException>("bytes", () => encoder.GetBytes(pChars, s.Length, null, 1, true));
170                 AssertExtensions.Throws<ArgumentNullException>("chars", () => encoder.GetBytes(null, s.Length, pBytes, 4, true));
171                 AssertExtensions.Throws<ArgumentNullException>("chars", () => encoder.GetByteCount(null, s.Length, true));
172 
173                 AssertExtensions.Throws<ArgumentOutOfRangeException>("charCount", () => encoder.GetBytes(pChars, -1, pBytes, 4, true));
174                 AssertExtensions.Throws<ArgumentOutOfRangeException>("byteCount", () => encoder.GetBytes(pChars, s.Length, pBytes, -1, true));
175                 AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => encoder.GetByteCount(pChars, -1, true));
176 
177                 AssertExtensions.Throws<ArgumentException>("bytes", () => encoder.GetBytes(pChars, s.Length, pBytes, 1, true));
178             }
179 
180             encoder = Encoding.GetEncoding("us-ascii", new EncoderExceptionFallback(), new DecoderExceptionFallback()).GetEncoder();
181 
182             fixed (char *charsPtr = "\uFFFF")
183             fixed (byte *bytesPtr = new byte [2])
184             {
185                 byte *pBytes = bytesPtr;
186                 char *pChars = charsPtr;
187 
188                 Assert.Throws<EncoderFallbackException>(() => encoder.GetBytes(pChars, 1, pBytes, 2, true));
189                 Assert.Throws<EncoderFallbackException>(() => encoder.GetByteCount(pChars, 1, true));
190             }
191         }
192 
193         [Fact]
EncoderExceptionFallbackBufferTest()194         public static void EncoderExceptionFallbackBufferTest()
195         {
196             Encoder encoder = Encoding.GetEncoding("us-ascii", new EncoderExceptionFallback(), new DecoderExceptionFallback()).GetEncoder();
197 
198             char [] chars = new char[] { '\uFFFF' };
199             byte [] bytes = new byte[2];
200 
201             Assert.Throws<EncoderFallbackException>(() => encoder.GetBytes(chars, 0, 1, bytes, 0, true));
202 
203             EncoderFallbackBuffer fallbackBuffer = encoder.FallbackBuffer;
204             Assert.True(fallbackBuffer is EncoderExceptionFallbackBuffer, "Expected to get EncoderExceptionFallbackBuffer type");
205             Assert.Throws<EncoderFallbackException>(() => fallbackBuffer.Fallback(chars[0], 0));
206             Assert.Throws<EncoderFallbackException>(() => fallbackBuffer.Fallback('\u0040', 0));
207             Assert.Throws<EncoderFallbackException>(() => fallbackBuffer.Fallback('\uD800', '\uDC00', 0));
208 
209             Assert.Equal(0, fallbackBuffer.Remaining);
210             Assert.Equal('\u0000', fallbackBuffer.GetNextChar());
211 
212             Assert.False(fallbackBuffer.MovePrevious(), "MovePrevious expected to always return false");
213 
214             fallbackBuffer.Reset();
215 
216             Assert.Equal(0, fallbackBuffer.Remaining);
217             Assert.Equal('\u0000', fallbackBuffer.GetNextChar());
218 
219         }
220 
221         [Fact]
EncoderReplacementFallbackBufferTest()222         public static void EncoderReplacementFallbackBufferTest()
223         {
224             Encoder encoder = Encoding.GetEncoding("us-ascii", new EncoderReplacementFallback(), new DecoderReplacementFallback()).GetEncoder();
225 
226             char [] chars = new char [] { '\uFFFF' };
227             byte [] bytes = new byte [2];
228 
229             EncoderFallbackBuffer fallbackBuffer = encoder.FallbackBuffer;
230             Assert.True(fallbackBuffer is EncoderReplacementFallbackBuffer, "Expected to get EncoderReplacementFallbackBuffer type");
231             Assert.True(fallbackBuffer.Fallback(chars[0], 0), "Expected we fallback on the given buffer");
232             Assert.Equal(1, fallbackBuffer.Remaining);
233             Assert.False(fallbackBuffer.MovePrevious(), "Expected we cannot move back on the replacement buffer as we are at the Beginning of the buffer");
234             Assert.Equal('?', fallbackBuffer.GetNextChar());
235             Assert.True(fallbackBuffer.MovePrevious(), "Expected we can move back on the replacement buffer");
236             Assert.Equal('?', fallbackBuffer.GetNextChar());
237 
238             fallbackBuffer.Reset();
239             Assert.Equal(0, fallbackBuffer.Remaining);
240             Assert.Equal('\u0000', fallbackBuffer.GetNextChar());
241             Assert.False(fallbackBuffer.MovePrevious(), "Expected we cannot move back on the replacement buffer as we are rest the buffer");
242         }
243     }
244 }
245