1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.IO;
5 using System.Runtime.Serialization;
6 using System.ServiceModel;
7 using System.ServiceModel.Channels;
8 using System.Text;
9 using System.Xml;
10 using NUnit.Framework;
11 
12 namespace MonoTests.System.ServiceModel.Channels
13 {
14 	[TestFixture]
15 	public class MessageHeadersTest
16 	{
17 		string wsa1 = "http://www.w3.org/2005/08/addressing";
18 
19 		[Test] // it is somehow allowed ...
AddDuplicate()20 		public void AddDuplicate ()
21 		{
22 			MessageHeaders headers = new MessageHeaders (MessageVersion.Default);
23 			headers.Add (MessageHeader.CreateHeader ("Action", wsa1, "urn:foo"));
24 			headers.Add (MessageHeader.CreateHeader ("Action", wsa1, "urn:bar"));
25 		}
26 
27 		[Test]
AddDuplicate2()28 		public void AddDuplicate2 ()
29 		{
30 			MessageHeaders headers = new MessageHeaders (MessageVersion.Default);
31 			headers.Add (MessageHeader.CreateHeader ("Action", wsa1, "urn:foo", true, "whoa"));
32 			headers.Add (MessageHeader.CreateHeader ("Action", wsa1, "urn:bar", true, "whee"));
33 		}
34 
35 		[Test]
TestConstructor()36 		public void TestConstructor ()
37 		{
38 			MessageHeaders headers = new MessageHeaders (MessageVersion.Soap12WSAddressing10);
39 			Assert.AreEqual (0, headers.Count);
40 
41 			headers = new MessageHeaders (MessageVersion.Default);
42 			Assert.AreEqual (0, headers.Count);
43 		}
44 
45 		[Test]
TestFindHeader()46 		public void TestFindHeader ()
47 		{
48 			// <a:Action mU="true">test</a:Action>
49 			Message m = Message.CreateMessage (MessageVersion.Default, "test", 1);
50 			Assert.AreEqual (1, m.Headers.Count, "#0");
51 
52 			// <MyHeader xmlns="bar">1</MyHeader>
53 			m.Headers.Add (MessageHeader.CreateHeader ("MyHeader", "bar", 1));
54 			// <MyHeader xmlns="baz" role="john">1</MyHeader>
55 			m.Headers.Add (MessageHeader.CreateHeader ("MyHeader", "baz", 1, false, "john"));
56 
57 			MessageHeaders headers = m.Headers;
58 			// The first header is at 0
59 			Assert.AreEqual (0, headers.FindHeader ("Action", wsa1), "#1");
60 
61 			// The return value of FindHeader maps to its places in the headers
62 			Assert.AreEqual (1, headers.FindHeader ("MyHeader", "bar"), "#2");
63 
64 			// If a header has actor (role) specified, then it must be provided
65 			Assert.AreEqual (-1, headers.FindHeader ("MyHeader", "baz"), "#3");
66 			Assert.AreEqual (2, headers.FindHeader ("MyHeader", "baz", "john"), "#4");
67 		}
68 
69 		[Test]
TestFindHeaderWithMultipleIdenticalHeaders()70 		public void TestFindHeaderWithMultipleIdenticalHeaders ()
71 		{
72 			Message m = Message.CreateMessage (MessageVersion.Default, "test", 1);
73 			m.Headers.Add (MessageHeader.CreateHeader (
74 				"Action", "http://schemas.xmlsoap.org/ws/2004/08/addressing", 1));
75 
76 			MessageHeaders headers = m.Headers;
77 
78 			headers.FindHeader ("Action", "http://schemas.xmlsoap.org/ws/2004/08/addressing");
79 		}
80 
81 		[Test]
TestGetHeader()82 		public void TestGetHeader ()
83 		{
84 			Message m = Message.CreateMessage (MessageVersion.Default, "test", 1);
85 			MessageHeaders headers = m.Headers;
86 
87 			Assert.AreEqual ("test", headers.GetHeader<string> (0));
88 		}
89 
90 		[Test, ExpectedException (typeof (ArgumentOutOfRangeException))]
TestGetHeaderOutOfRange()91 		public void TestGetHeaderOutOfRange ()
92 		{
93 			Message m = Message.CreateMessage (MessageVersion.Default, "test", 1);
94 			MessageHeaders headers = m.Headers;
95 
96 			Assert.AreEqual ("test", headers.GetHeader<int> (1));
97 		}
98 
99 		[Test]
100 		[ExpectedException (typeof (ArgumentNullException))]
GetHeaderNullSerializer()101 		public void GetHeaderNullSerializer ()
102 		{
103 			MessageHeaders headers = new MessageHeaders (MessageVersion.Default);
104 			string ns = "http://schemas.xmlsoap.org/ws/2004/08/addressing";
105 			headers.Add (MessageHeader.CreateHeader ("Action", ns, "urn:foo"));
106 			headers.GetHeader<string> (0, null);
107 		}
108 
109 		[Test]
110 		[ExpectedException (typeof (ArgumentNullException))]
GetHeaderNullSerializer2()111 		public void GetHeaderNullSerializer2 ()
112 		{
113 			MessageHeaders headers = new MessageHeaders (MessageVersion.Default);
114 			string ns = "http://schemas.xmlsoap.org/ws/2004/08/addressing";
115 			headers.Add (MessageHeader.CreateHeader ("Action", ns, "urn:foo"));
116 			headers.GetHeader<string> ("Action", ns, (XmlObjectSerializer) null);
117 		}
118 
119 		[Test, ExpectedException (typeof (MessageHeaderException))]
TestGetHeaderNonexistent()120 		public void TestGetHeaderNonexistent ()
121 		{
122 			Message m = Message.CreateMessage (MessageVersion.Default, "test", 1);
123 			MessageHeaders headers = m.Headers;
124 
125 			headers.GetHeader<string>("name", "namespace");
126 		}
127 
128 		[Test]
SetWSAddressingHeadersNullToNonSoap()129 		public void SetWSAddressingHeadersNullToNonSoap ()
130 		{
131 			Message m = Message.CreateMessage (MessageVersion.None, "test", 1);
132 			m.Headers.From = null;
133 			m.Headers.MessageId = null;
134 			m.Headers.ReplyTo = null;
135 			m.Headers.FaultTo = null;
136 			m.Headers.RelatesTo = null;
137 		}
138 
139 		[Test]
TestInsert()140 		public void TestInsert ()
141 		{
142 			Message m = Message.CreateMessage (MessageVersion.Default, "test", 1);
143 
144 			m.Headers.Add (MessageHeader.CreateHeader ("FirstHeader", "ns", "first"));
145 			Assert.AreEqual (1, m.Headers.FindHeader ("FirstHeader", "ns"));
146 
147 			m.Headers.Insert (1, MessageHeader.CreateHeader ("InsertedHeader", "ns", "insert"));
148 
149  			Assert.AreEqual (1, m.Headers.FindHeader ("InsertedHeader", "ns"));
150  			Assert.AreEqual (2, m.Headers.FindHeader ("FirstHeader", "ns"));
151 		}
152 
153 		[Test]
TestWriteStartHeaderSimple()154 		public void TestWriteStartHeaderSimple ()
155 		{
156 			Message m = Message.CreateMessage (MessageVersion.Default, "test", 1);
157 			MessageHeader h = MessageHeader.CreateHeader ("FirstHeader", "ns", "first");
158 			m.Headers.Add (h);
159 
160 			StringBuilder sb = new StringBuilder ();
161 			XmlWriterSettings s = new XmlWriterSettings ();
162 			s.ConformanceLevel = ConformanceLevel.Fragment;
163 			XmlWriter w = XmlWriter.Create (sb, s);
164 			XmlDictionaryWriter dw = XmlDictionaryWriter.CreateDictionaryWriter (w);
165 			m.Headers.WriteStartHeader (1, dw);
166 			dw.Close ();
167 			w.Close ();
168 			string actual = sb.ToString ();
169 
170 			sb = new StringBuilder ();
171 			w = XmlWriter.Create (sb, s);
172 			dw = XmlDictionaryWriter.CreateDictionaryWriter (w);
173 			h.WriteStartHeader (dw, MessageVersion.Soap12WSAddressing10);
174 			dw.Close ();
175 			w.Close ();
176 			string expected = sb.ToString ();
177 
178 
179 			Assert.AreEqual (expected, actual);
180 		}
181 
182 		[Test]
TestWriteStartHeaderWithActor()183 		public void TestWriteStartHeaderWithActor ()
184 		{
185 			Message m = Message.CreateMessage (MessageVersion.Default, "test", 1);
186 			MessageHeader h = MessageHeader.CreateHeader ("FirstHeader", "ns", "first", true, "actor");
187 			m.Headers.Add (h);
188 
189 			StringBuilder sb = new StringBuilder ();
190 			XmlWriterSettings s = new XmlWriterSettings ();
191 			s.ConformanceLevel = ConformanceLevel.Fragment;
192 			XmlWriter w = XmlWriter.Create (sb, s);
193 			XmlDictionaryWriter dw = XmlDictionaryWriter.CreateDictionaryWriter (w);
194 			m.Headers.WriteStartHeader (1, dw);
195 			dw.Close ();
196 			w.Close ();
197 			string actual = sb.ToString ();
198 
199 			sb = new StringBuilder ();
200 			w = XmlWriter.Create (sb, s);
201 			dw = XmlDictionaryWriter.CreateDictionaryWriter (w);
202 			h.WriteStartHeader (dw, MessageVersion.Soap12WSAddressing10);
203 			dw.Close ();
204 			w.Close ();
205 			string expected = sb.ToString ();
206 
207 			Assert.AreEqual (expected, actual);
208 		}
209 
210 		[Test]
TestWriteHeaderContents()211 		public void TestWriteHeaderContents ()
212 		{
213 			Message m = Message.CreateMessage (MessageVersion.Default, "test", 1);
214 
215 			m.Headers.Add (MessageHeader.CreateHeader ("FirstHeader", "ns", "first"));
216 			Assert.AreEqual (1, m.Headers.FindHeader ("FirstHeader", "ns"));
217 
218 			m.Headers.Add (MessageHeader.CreateHeader ("SecondHeader", "ns", 2));
219 
220 			StringBuilder sb = new StringBuilder ();
221 			// Even if XmlWriter is allowed to write fragment,
222 			// DataContractSerializer never allows it to write
223 			// content in contentOnly mode.
224 			XmlWriterSettings settings = new XmlWriterSettings ();
225 			settings.OmitXmlDeclaration = true;
226 			//settings.ConformanceLevel = ConformanceLevel.Fragment;
227 			XmlWriter w = XmlWriter.Create (sb, settings);
228 			w.WriteStartElement ("root");
229 			w.WriteStartElement ("HEADER1");
230 			m.Headers.WriteHeaderContents (1, w);
231 			w.WriteEndElement ();
232 			w.WriteStartElement ("HEADER2");
233 			m.Headers.WriteHeaderContents (2, w);
234 			w.WriteEndElement ();
235 			w.WriteEndElement ();
236 			w.Close ();
237 
238 			Assert.AreEqual ("<root><HEADER1>first</HEADER1><HEADER2>2</HEADER2></root>", sb.ToString ());
239 		}
240 
241 		[Test]
242 		[Ignore ("I believe that with AddressingVersion.None it should not output any mustUnderstand addressing headers.")]
WriteHeaderContentsAddressingNone()243 		public void WriteHeaderContentsAddressingNone ()
244 		{
245 			// This Action header is IMO extraneous.
246 			string xml = "<?xml version=\"1.0\" encoding=\"utf-16\"?><s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\"><s:Header><Action s:mustUnderstand=\"1\" xmlns=\"http://schemas.microsoft.com/ws/2005/05/addressing/none\">Echo</Action></s:Header><s:Body><z:anyType i:nil=\"true\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:z=\"http://schemas.microsoft.com/2003/10/Serialization/\"/></s:Body></s:Envelope>";
247 			Message m = Message.CreateMessage (MessageVersion.Soap12, "Echo", (object) null);
248 			StringWriter sw = new StringWriter ();
249 			using (XmlWriter w = XmlWriter.Create (sw)) {
250 				m.WriteMessage (w);
251 			}
252 			Assert.AreEqual (xml, sw.ToString ());
253 		}
254 
255 		[Test]
TestAction()256 		public void TestAction ()
257 		{
258 			Message m = Message.CreateMessage (MessageVersion.Default, "test", 1);
259 			m.Headers.Add (MessageHeader.CreateHeader ("FirstHeader", "ns", "first"));
260 			Assert.AreEqual ("test", m.Headers.Action, "#1");
261 
262 			MessageHeaders headers = new MessageHeaders (MessageVersion.Default, 1);
263 			Assert.AreEqual (null, headers.Action, "#2");
264 			headers.Add (MessageHeader.CreateHeader ("Action", "http://www.w3.org/2005/08/addressing", "test"));
265 
266 			MessageHeaderInfo info = headers [0];
267 			Assert.AreEqual ("Action", info.Name, "#2-1");
268 			Assert.AreEqual ("http://www.w3.org/2005/08/addressing", info.Namespace, "#2-2");
269 			Assert.AreEqual (false, info.MustUnderstand, "#2-3");
270 			Assert.AreEqual (String.Empty, info.Actor, "#2-4");
271 
272 			Assert.AreEqual ("test", headers.Action, "#3");
273 			headers.Clear ();
274 			Assert.AreEqual (null, headers.Action, "#4");
275 		}
276 
277 		[Test]
MessageCreateAddsAction()278 		public void MessageCreateAddsAction ()
279 		{
280 			Message m = Message.CreateMessage (MessageVersion.Default, "test", 1);
281 			MessageHeaderInfo info = m.Headers [0];
282 			Assert.AreEqual ("Action", info.Name, "#1");
283 			Assert.AreEqual ("http://www.w3.org/2005/08/addressing", info.Namespace, "#2");
284 			Assert.AreEqual (true, info.MustUnderstand, "#3");
285 			Assert.AreEqual (String.Empty, info.Actor, "#4");
286 		}
287 
288 		[Test]
GetReaderAtHeader()289 		public void GetReaderAtHeader ()
290 		{
291 			Message m = Message.CreateMessage (MessageVersion.Default, "test", 1);
292 			XmlDictionaryReader r = m.Headers.GetReaderAtHeader (0);
293 
294 			XmlDictionaryReader r2 = m.Headers.GetReaderAtHeader (0);
295 			using (XmlWriter x = XmlWriter.Create (TextWriter.Null)) {
296 				r2.MoveToContent ();
297 				while (!r2.EOF)
298 					x.WriteNode (r2, false);
299 			}
300 
301 			/*
302 			// Seems like there is some attribute order differences
303 			// in XmlDictionaryReader or XmlWriter, so don't compare
304 			// XML in raw strings.
305 
306 			StringWriter sw = new StringWriter ();
307 			XmlWriterSettings settings = new XmlWriterSettings ();
308 			settings.OmitXmlDeclaration = true;
309 			settings.ConformanceLevel = ConformanceLevel.Fragment;
310 			XmlWriter w = XmlWriter.Create (sw, settings);
311 			Assert.AreEqual (ReadState.Interactive, r.ReadState, "#1-1");
312 			Assert.AreEqual (XmlNodeType.Element, r.NodeType, "#1-2");
313 			while (!r.EOF)
314 				w.WriteNode (r, false);
315 			w.Flush ();
316 			Assert.AreEqual ("<Action a:mustUnderstand=\"1\" xmlns=\"http://www.w3.org/2005/08/addressing\" xmlns:a=\"http://www.w3.org/2003/05/soap-envelope\">test</Action>", sw.ToString (), "#2");
317 			*/
318 			Assert.AreEqual (ReadState.Interactive, r.ReadState, "#1-1");
319 			Assert.AreEqual (XmlNodeType.Element, r.NodeType, "#1-2");
320 			Assert.AreEqual ("Action", r.LocalName, "#1-3");
321 			Assert.AreEqual ("http://www.w3.org/2005/08/addressing", r.NamespaceURI, "#1-4");
322 			Assert.AreEqual ("1", r.GetAttribute ("mustUnderstand", "http://www.w3.org/2003/05/soap-envelope"), "#1-5");
323 			Assert.AreEqual ("test", r.ReadElementContentAsString (), "#1-6");
324 		}
325 
326 		[Test]
327 		[ExpectedException (typeof (ArgumentOutOfRangeException))]
GetReaderAtHeaderOutOfRange()328 		public void GetReaderAtHeaderOutOfRange ()
329 		{
330 			MessageHeaders h = new MessageHeaders (MessageVersion.Default, 1);
331 			h.GetReaderAtHeader (0);
332 		}
333 
334 		[Test]
335 		[ExpectedException (typeof (MessageHeaderException))] // multiple headers: "Action"
CopyHeadersFrom()336 		public void CopyHeadersFrom ()
337 		{
338 			Message msg = Message.CreateMessage (MessageVersion.Default, "urn:myaction");
339 			Message msg2 = Message.CreateMessage (MessageVersion.Default, "urn:myaction2");
340 			msg2.Headers.CopyHeadersFrom (msg);
341 			Assert.AreEqual ("urn:myaction2", msg2.Headers.Action);
342 		}
343 
344 		[Test]
CopyHeadersFrom2()345 		public void CopyHeadersFrom2 ()
346 		{
347 			Message msg = Message.CreateMessage (MessageVersion.Default, "urn:myaction");
348 			Message msg2 = Message.CreateMessage (MessageVersion.Default, "urn:myaction2");
349 			msg2.Headers.Action = null;
350 			msg2.Headers.CopyHeadersFrom (msg);
351 			Assert.AreEqual ("urn:myaction", msg2.Headers.Action);
352 		}
353 
354 		[Test]
AddressingNoneAndAction()355 		public void AddressingNoneAndAction ()
356 		{
357 			MessageHeaders h = new MessageHeaders (MessageVersion.Soap12);
358 			h.Action = "urn:foo";
359 		}
360 
361 		[Test]
362 		[ExpectedException (typeof (InvalidOperationException))]
AddressingNoneAndFrom()363 		public void AddressingNoneAndFrom ()
364 		{
365 			MessageHeaders h = new MessageHeaders (MessageVersion.Soap12);
366 			h.From = new EndpointAddress ("http://localhost:8080");
367 		}
368 
369 		[Test]
370 		[ExpectedException (typeof (InvalidOperationException))]
AddressingNoneAndFaultTo()371 		public void AddressingNoneAndFaultTo ()
372 		{
373 			MessageHeaders h = new MessageHeaders (MessageVersion.Soap12);
374 			h.FaultTo = new EndpointAddress ("http://localhost:8080");
375 		}
376 
377 		[Test]
378 		[ExpectedException (typeof (InvalidOperationException))]
AddressingNoneAndMessageId()379 		public void AddressingNoneAndMessageId ()
380 		{
381 			MessageHeaders h = new MessageHeaders (MessageVersion.Soap12);
382 			h.MessageId = new UniqueId (Guid.NewGuid ());
383 		}
384 
385 		[Test]
386 		[ExpectedException (typeof (InvalidOperationException))]
AddressingNoneAndRelatesTo()387 		public void AddressingNoneAndRelatesTo ()
388 		{
389 			MessageHeaders h = new MessageHeaders (MessageVersion.Soap12);
390 			h.RelatesTo = new UniqueId (Guid.NewGuid ());
391 		}
392 
393 		[Test]
394 		[ExpectedException (typeof (InvalidOperationException))]
AddressingNoneAndReplyTo()395 		public void AddressingNoneAndReplyTo ()
396 		{
397 			MessageHeaders h = new MessageHeaders (MessageVersion.Soap12);
398 			h.ReplyTo = new EndpointAddress ("http://localhost:8080");
399 		}
400 
401 		[Test]
AddressingNoneAndTo()402 		public void AddressingNoneAndTo ()
403 		{
404 			MessageHeaders h = new MessageHeaders (MessageVersion.Soap12);
405 			h.To = new Uri ("http://localhost:8080");
406 		}
407 
408 		[Test]
409 		[ExpectedException (typeof (MessageHeaderException))]
DuplicateActionFindError()410 		public void DuplicateActionFindError ()
411 		{
412 			MessageHeaders headers = new MessageHeaders (MessageVersion.Default);
413 			headers.Add (MessageHeader.CreateHeader ("Action", wsa1, "urn:foo"));
414 			headers.Add (MessageHeader.CreateHeader ("Action", wsa1, "urn:bar"));
415 			Assert.Fail (String.Format ("Action should not be caught", headers.Action)); // access to Action results in an error. If it does not, then simply assert fail.
416 		}
417 
418 		[Test]
419 		[ExpectedException (typeof (MessageHeaderException))]
CopyHeadersFrom_Merge()420 		public void CopyHeadersFrom_Merge ()
421 		{
422 			var h1 = new MessageHeaders (MessageVersion.Default);
423 			var h2 = new MessageHeaders (MessageVersion.Default);
424 			h1.Add (MessageHeader.CreateHeader ("Action", wsa1, "urn:foo"));
425 			h2.Add (MessageHeader.CreateHeader ("Action", wsa1, "urn:bar"));
426 			h1.CopyHeadersFrom (h2); // it somehow allow dups!
427 			Assert.Fail (String.Format ("Action should not be caught", h1.Action)); // access to Action results in an error. If it does not, then simply assert fail.
428 		}
429 
430 	}
431 }
432