2 // SecureStringTest.cs - Unit tests for System.Security.SecureString
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Security;
33 using System.Runtime.InteropServices;
35 using NUnit.Framework;
37 namespace MonoTests.System.Security {
40 public class SecureStringTest {
42 private const string NotSupported = "Not supported before Windows 2000 Service Pack 3";
45 public void DefaultConstructor ()
48 SecureString ss = new SecureString ();
49 Assert.IsFalse (ss.IsReadOnly (), "IsReadOnly");
50 Assert.AreEqual (0, ss.Length, "0");
52 Assert.AreEqual (1, ss.Length, "1");
54 Assert.AreEqual (0, ss.Length, "0b");
56 Assert.AreEqual (1, ss.Length, "1b");
58 Assert.AreEqual (1, ss.Length, "1c");
59 Assert.AreEqual ("System.Security.SecureString", ss.ToString (), "ToString");
61 Assert.AreEqual (0, ss.Length, "0c");
64 catch (NotSupportedException) {
65 Assert.Ignore (NotSupported);
70 public unsafe void UnsafeConstructor ()
73 SecureString ss = null;
74 char[] data = new char[] { 'a', 'b', 'c' };
75 fixed (char* p = &data[0]) {
76 ss = new SecureString (p, data.Length);
78 Assert.IsFalse (ss.IsReadOnly (), "IsReadOnly");
79 Assert.AreEqual (3, ss.Length, "3");
81 Assert.AreEqual (4, ss.Length, "4");
83 Assert.AreEqual (0, ss.Length, "0b");
85 Assert.AreEqual (1, ss.Length, "1b");
87 Assert.AreEqual (1, ss.Length, "1c");
89 Assert.AreEqual (0, ss.Length, "0c");
92 catch (NotSupportedException) {
93 Assert.Ignore (NotSupported);
98 [ExpectedException (typeof (ArgumentNullException))]
99 public unsafe void UnsafeConstructor_Null ()
101 new SecureString (null, 0);
105 [ExpectedException (typeof (ArgumentOutOfRangeException))]
106 public unsafe void UnsafeConstructor_Negative ()
108 char[] data = new char[] { 'a', 'b', 'c' };
109 fixed (char* p = &data[0]) {
110 new SecureString (p, -1);
115 [ExpectedException (typeof (ArgumentOutOfRangeException))]
116 public unsafe void UnsafeConstructor_BiggerThanMax ()
118 char[] data = new char[] { 'a', 'b', 'c' };
119 fixed (char* p = &data[0]) {
120 new SecureString (p, UInt16.MaxValue + 2);
124 private SecureString max;
126 private unsafe SecureString GetMaxLength ()
129 int maxlength = UInt16.MaxValue + 1;
130 char[] data = new char[maxlength];
131 fixed (char* p = &data[0]) {
132 max = new SecureString (p, maxlength);
134 // note: don't try a loop of AppendChar with that size ;-)
140 [ExpectedException (typeof (ArgumentOutOfRangeException))]
141 public void AppendChar_BiggerThanMax ()
143 SecureString ss = GetMaxLength ();
148 public void Copy_Empty ()
150 SecureString empty = new SecureString ();
151 Assert.AreEqual (0, empty.Length, "Empty.Length");
152 SecureString empty_copy = empty.Copy ();
153 Assert.AreEqual (0, empty_copy.Length, "EmptyCopy.Length");
159 SecureString ss = new SecureString ();
161 Assert.AreEqual (1, ss.Length, "Length");
163 SecureString ss2 = ss.Copy();
164 Assert.AreEqual (1, ss2.Length, "Copy.Length");
165 Assert.IsFalse (ss2.IsReadOnly (), "Copy.IsReadOnly");
167 Assert.IsTrue (ss2.IsReadOnly (), "Copy.IsReadOnly-2");
169 SecureString ss3 = ss2.Copy ();
170 Assert.IsFalse (ss3.IsReadOnly (), "Copy.IsReadOnly-3");
174 [ExpectedException (typeof (ArgumentOutOfRangeException))]
175 public void InsertAt_Negative ()
177 SecureString ss = new SecureString ();
178 ss.InsertAt (-1, 'a');
182 [ExpectedException (typeof (ArgumentOutOfRangeException))]
183 public void InsertAt_BiggerThanLength ()
185 SecureString ss = new SecureString ();
186 ss.InsertAt (1, 'a');
190 public void InsertAt_UsedLikeAppendChar () // #350820
192 SecureString ss = new SecureString ();
194 Assert.AreEqual (1, ss.Length, "AppendChar");
195 ss.InsertAt (1, 'e');
196 Assert.AreEqual (2, ss.Length, "InsertAt");
200 [ExpectedException (typeof (ArgumentOutOfRangeException))]
201 public void SetAt_Negative ()
203 SecureString ss = new SecureString ();
208 [ExpectedException (typeof (ArgumentOutOfRangeException))]
209 public void SetAt_BiggerThanLength ()
211 SecureString ss = new SecureString ();
216 public void RemoveAt ()
218 string test_string = "test string";
219 string expected, actual;
220 SecureString ss = new SecureString ();
221 foreach (char c in test_string) {
226 expected = "est string";
227 actual = ReadSecureString (ss);
228 Assert.AreEqual (expected, actual, "RemoveAt begining");
231 expected = "est tring";
232 actual = ReadSecureString (ss);
233 Assert.AreEqual (expected, actual, "RemoveAt middle");
236 expected = "est trin";
237 actual = ReadSecureString (ss);
238 Assert.AreEqual (expected, actual, "RemoveAt end");
242 [ExpectedException (typeof (ArgumentOutOfRangeException))]
243 public void RemoveAt_Negative ()
245 SecureString ss = new SecureString ();
250 [ExpectedException (typeof (ArgumentOutOfRangeException))]
251 public void RemoveAt_BiggerThanLength ()
253 SecureString ss = new SecureString ();
258 [ExpectedException (typeof (ArgumentOutOfRangeException))]
259 public void InsertAt_BiggerThanMax ()
261 SecureString ss = GetMaxLength ();
262 ss.InsertAt (ss.Length, 'a');
265 private SecureString GetReadOnly ()
267 SecureString ss = new SecureString ();
273 public void ReadOnly ()
276 SecureString ss = GetReadOnly ();
277 Assert.IsTrue (ss.IsReadOnly (), "IsReadOnly");
278 Assert.AreEqual (0, ss.Length, "0");
281 catch (NotSupportedException) {
282 Assert.Ignore (NotSupported);
287 [ExpectedException (typeof (InvalidOperationException))]
288 public void ReadOnly_AppendChar ()
290 SecureString ss = GetReadOnly ();
295 [ExpectedException (typeof (InvalidOperationException))]
296 public void ReadOnly_Clear ()
298 SecureString ss = GetReadOnly ();
303 [ExpectedException (typeof (InvalidOperationException))]
304 public void ReadOnly_InsertAt ()
306 SecureString ss = GetReadOnly ();
307 ss.InsertAt (0, 'a');
311 [ExpectedException (typeof (InvalidOperationException))]
312 public void ReadOnly_SetAt ()
314 SecureString ss = GetReadOnly ();
319 [ExpectedException (typeof (InvalidOperationException))]
320 public void ReadOnly_RemoveAt ()
322 SecureString ss = GetReadOnly ();
326 private SecureString GetDisposed ()
328 SecureString ss = new SecureString ();
334 public void Disposed ()
337 SecureString ss = GetDisposed ();
340 catch (NotSupportedException) {
341 Assert.Ignore (NotSupported);
346 [ExpectedException (typeof (ObjectDisposedException))]
347 public void Disposed_AppendChar ()
349 SecureString ss = GetDisposed ();
354 [ExpectedException (typeof (ObjectDisposedException))]
355 public void Disposed_Clear ()
357 SecureString ss = GetDisposed ();
362 [ExpectedException (typeof (ObjectDisposedException))]
363 public void Disposed_InsertAt ()
365 SecureString ss = GetDisposed ();
366 ss.InsertAt (0, 'a');
370 [ExpectedException (typeof (ObjectDisposedException))]
371 public void Disposed_IsReadOnly ()
373 SecureString ss = GetDisposed ();
374 Assert.IsFalse (ss.IsReadOnly (), "IsReadOnly");
378 [ExpectedException (typeof (ObjectDisposedException))]
379 public void Disposed_Length ()
381 SecureString ss = GetDisposed ();
382 Assert.AreEqual (0, ss.Length, "Length");
386 [ExpectedException (typeof (ObjectDisposedException))]
387 public void Disposed_SetAt ()
389 SecureString ss = GetDisposed ();
394 [ExpectedException (typeof (ObjectDisposedException))]
395 public void Disposed_RemoveAt ()
397 SecureString ss = GetDisposed ();
402 private static string ReadSecureString(SecureString aSecureString)
404 var strPtr = Marshal.SecureStringToGlobalAllocUnicode (aSecureString);
405 var str = Marshal.PtrToStringUni(strPtr);
406 Marshal.ZeroFreeGlobalAllocUnicode (strPtr);