1 // UnixMarshalTests.cs - NUnit2 Test Cases for Mono.Unix.UnixMarshal class
2 //
3 // Authors:
4 //  Jonathan Pryor (jonpryor@vt.edu)
5 //
6 // (c) 2005 Jonathan Pryor
7 //
8 
9 using NUnit.Framework;
10 using System;
11 using System.Collections.Generic;
12 using System.IO;
13 using System.Runtime.InteropServices;
14 using System.Text;
15 using Mono.Unix;
16 
17 namespace MonoTests.Mono.Unix {
18 
19 	class RandomEncoding : UTF8Encoding {
RandomEncoding()20 		public RandomEncoding ()
21 			: base (false, true)
22 		{
23 		}
24 
GetMaxByteCount(int value)25 		public override int GetMaxByteCount (int value)
26 		{
27 			return value*6;
28 		}
29 	}
30 
31 	[TestFixture, Category ("NotOnWindows")]
32 	public class UnixMarshalTest {
33 #if false
Main()34 		public static void Main ()
35 		{
36 			string s = UnixMarshal.GetErrorDescription (Errno.ERANGE);
37 			Console.WriteLine ("ERANGE={0}", s);
38 			s = UnixMarshal.GetErrorDescription ((Errno) 999999);
39 			Console.WriteLine ("Invalid={0}", s);
40 		}
41 #endif
42 
43 		[Test]
BXC10074()44 		public void BXC10074 ()
45 		{
46 			var result = UnixMarshal.StringToHeap (null, Encoding.ASCII);
47 			Assert.AreEqual (IntPtr.Zero, result, "This used to crash due to a NullReferenceException");
48 		}
49 
50 		[Test]
TestStringToHeap()51 		public void TestStringToHeap ()
52 		{
53 			object[] data = {
54 				"Hello, world!", true, true,
55 				"MS Pゴシック", false, true,
56 			};
57 
58 			for (int i = 0; i < data.Length; i += 3) {
59 				string s           = (string) data [i+0];
60 				bool valid_ascii   = (bool)   data [i+1];
61 				bool valid_unicode = (bool)   data [i+2];
62 
63 				StringToHeap (s, valid_ascii, valid_unicode);
64 			}
65 		}
66 
StringToHeap(string s, bool validAscii, bool validUnicode)67 		private static void StringToHeap (string s, bool validAscii, bool validUnicode)
68 		{
69 			StringToHeap (s, Encoding.ASCII, validAscii);
70 			StringToHeap (s, Encoding.UTF7, validUnicode);
71 			StringToHeap (s, Encoding.UTF8, validUnicode);
72 			StringToHeap (s, Encoding.Unicode, validUnicode);
73 			StringToHeap (s, Encoding.BigEndianUnicode, validUnicode);
74 			StringToHeap (s, new RandomEncoding (), validUnicode);
75 		}
76 
StringToHeap(string s, Encoding e, bool mustBeEqual)77 		private static void StringToHeap (string s, Encoding e, bool mustBeEqual)
78 		{
79 			IntPtr p = UnixMarshal.StringToHeap (s, e);
80 			try {
81 				string _s = UnixMarshal.PtrToString (p, e);
82 				if (mustBeEqual)
83 					Assert.AreEqual (s, _s, "#TSTA (" + e.GetType() + ")");
84 			}
85 			finally {
86 				UnixMarshal.FreeHeap (p);
87 			}
88 		}
89 
90 		[Test]
TestPtrToString()91 		public void TestPtrToString ()
92 		{
93 			IntPtr p = UnixMarshal.AllocHeap (1);
94 			Marshal.WriteByte (p, 0);
95 			string s = UnixMarshal.PtrToString (p);
96 			UnixMarshal.FreeHeap (p);
97 		}
98 
99 		[Test]
TestUtf32PtrToString()100 		public void TestUtf32PtrToString ()
101 		{
102 			var utf32NativeEndianNoBom = new UTF32Encoding(
103 				bigEndian: !BitConverter.IsLittleEndian,
104 				byteOrderMark: false,
105 				throwOnInvalidCharacters: true
106 			);
107 
108 			// assemble a buffer that contains:
109 			// 1. eight garbage bytes
110 			// 2. the native-endian UTF-32 string "Hello, World" without BOM
111 			// 3. four 0 bytes (as a C wide string terminator)
112 			// 4. the native-endian UTF-32 string "broken" without BOM
113 			// 5. eight 0 bytes
114 			// 6. four garbage bytes
115 			var buf = new List<byte>();
116 			for (int i = 0; i < 2; ++i) {
117 				buf.Add((byte)0x12);
118 				buf.Add((byte)0x34);
119 				buf.Add((byte)0x56);
120 				buf.Add((byte)0x78);
121 			}
122 
123 			buf.AddRange(utf32NativeEndianNoBom.GetBytes("Hello, World"));
124 
125 			for (int i = 0; i < 4; ++i) {
126 				buf.Add((byte)0x00);
127 			}
128 
129 			buf.AddRange(utf32NativeEndianNoBom.GetBytes("broken"));
130 
131 			for (int i = 0; i < 8; ++i) {
132 				buf.Add((byte)0x00);
133 			}
134 
135 			buf.Add((byte)0x12);
136 			buf.Add((byte)0x34);
137 			buf.Add((byte)0x56);
138 			buf.Add((byte)0x78);
139 
140 			// get the array version of this
141 			var bufArr = buf.ToArray();
142 
143 			// allocate a buffer that will contain this string
144 			IntPtr bufPtr = UnixMarshal.AllocHeap(bufArr.Length);
145 			string returned;
146 			try
147 			{
148 				// copy it in
149 				Marshal.Copy(bufArr, 0, bufPtr, bufArr.Length);
150 
151 				// try getting it back
152 				returned = UnixMarshal.PtrToString(bufPtr + 8, utf32NativeEndianNoBom);
153 			}
154 			finally
155 			{
156 				UnixMarshal.FreeHeap(bufPtr);
157 			}
158 
159 			Assert.AreEqual("Hello, World", returned);
160 		}
161 	}
162 }
163 
164