public void OpenTypeIncorrectPropertyNameTest() { string[] invalidNames = new string[] { null, "", " ", "1", "@for", //"a.", "a;", "a`", "a,", //"a-", "a+", "a\'", "a[", "a]", "a ", " a", }; using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { foreach (string name in invalidNames) { using (StaticCallbackManager <PopulatingValuesEventArgs <OpenElement> > .RegisterStatic((sender, args) => { var o = new OpenElement(); o.Properties[name] = 1; args.Values.Add(o); })) { request.DataServiceType = typeof(OpenTypeContextWithReflection <OpenElement>); request.Accept = "application/atom+xml,application/xml"; request.RequestUriString = "/Values"; Exception exception = TestUtil.RunCatching(request.SendRequest); TestUtil.AssertExceptionExpected(exception, true); } } } }
public void OpenTypeBasicTest() { CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("TypeData", TypeData.Values)); using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(OpenTypeContextWithReflection <OpenElement>); request.RequestUriString = "/Values"; TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { TypeData data = (TypeData)values["TypeData"]; foreach (object sampleValue in data.SampleValues) { using (StaticCallbackManager <PopulatingValuesEventArgs <OpenElement> > .RegisterStatic((sender, args) => { var o = new OpenElement(); o.Properties.Add("sampleValue", sampleValue); args.Values.Add(o); })) { Exception exception = TestUtil.RunCatching(request.SendRequest); // If we choose to throw when an open property is, say, IntPtr, use this: // Also check for null, since when the value is null, there is no way to know the datatype of the property TestUtil.AssertExceptionExpected(exception, !data.IsTypeSupported && sampleValue != null); } } }); } }
public void OpenTypeOrderByTest() { string[][] queries = new string[][] { new string[] { "/Values?$orderby=sampleValue1", "abc", "ABC" }, new string[] { "/Values?$orderby=sampleValue1 desc", "ABC", "abc" }, new string[] { "/Values?$orderby=sampleValue1,sampleValue2", "abc", "ABC" }, new string[] { "/Values('101')/sampleValue4()?$orderby=ID", "101", "102" }, }; using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(OpenTypeContextWithReflection <OpenElement>); using (StaticCallbackManager <PopulatingValuesEventArgs <OpenElement> > .RegisterStatic((sender, args) => { var o = new OpenElement(); o.ID = "101"; o.Properties.Add("sampleValue1", "abc"); o.Properties.Add("sampleValue2", 12345); o.Properties.Add("sampleValue3", true); args.Values.Add(o); o = new OpenElement(); o.Properties.Add("sampleValue1", "ABC"); o.Properties.Add("sampleValue2", 1); o.Properties.Add("sampleValue3", false); args.Values.Add(o); })) { int i = 0; foreach (string[] queryParts in queries) { string query = queryParts[0]; Trace.WriteLine("Running " + query); request.RequestUriString = query; Exception exception = TestUtil.RunCatching(request.SendRequest); TestUtil.AssertExceptionExpected(exception, i == queries.Length - 1); if (exception == null) { string response = request.GetResponseStreamAsText(); int firstOffset = response.IndexOf(queryParts[1]); int secondOffset = response.IndexOf(queryParts[2]); if (firstOffset >= secondOffset) { Assert.Fail( "For '" + query + "' the offset for " + queryParts[1] + " (" + firstOffset + ") should be less than " + "the offset for " + queryParts[2] + " (" + secondOffset + ") in '" + response + "'"); } } i++; } } } }
public void OpenTypeUrlTest() { string[] queries = new string[] { "/Values", "/Values('100')/sampleValue2", "/Values('100')/sampleValue4", // no () after sample value 4, it's an array, gets rejected "/Values('100')/notfound", // This should be bad query since we expect to return 404 for open-properties not found }; string[] badQueries = new string[] { "/Values/sampleValue1", // no () after Values "/Values('100')/sampleValue4()", "/Values('100')/sampleValue4('101')", "/Values('100')/sampleValue4('101')/ID", "/Values('100')/sampleValue4(101)", // Since we don't detect types during runtime, this queries will fail "/Values('100')/sampleValue3/Identity/Name", "/Values('100')/sampleValue3/Identity", }; using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(OpenTypeContextWithReflection <OpenElement>); int i = 0; using (StaticCallbackManager <PopulatingValuesEventArgs <OpenElement> > .RegisterStatic((sender, args) => { var o = new OpenElement(); o.ID = "100"; o.Properties.Add("sampleValue1", "abc"); o.Properties.Add("sampleValue2", 12345); args.Values.Add(o); })) { foreach (string query in queries) { i++; Trace.WriteLine(query); request.RequestUriString = query; request.SendRequest(); Trace.WriteLine(request.GetResponseStreamAsText()); } foreach (string query in badQueries) { i++; Trace.WriteLine(query); request.RequestUriString = query; Exception exception = TestUtil.RunCatching(request.SendRequest); TestUtil.AssertExceptionExpected(exception, true); } } } }
public void SecurityCallbacksFilterTest() { CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("option", "$filter,$orderby".Split(','))); TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { string option = (string)values["option"]; int callCount = 0; using (AstoriaUnitTests.Tests.UnitTestModule.AuthorizationTest.InitializationCallbackManager.RegisterStatic((s, e) => { e.Configuration.SetEntitySetAccessRule("*", EntitySetRights.All); })) using (StaticCallbackManager <AstoriaUnitTests.Tests.UnitTestModule.AuthorizationTest.ComposeQueryEventArgs> .RegisterStatic((s, e) => { System.Linq.Expressions.Expression <Func <Customer, bool> > notZero = c => c.ID != 0; e.Filter = notZero; callCount++; })) using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.ServiceType = typeof(AstoriaUnitTests.Tests.UnitTestModule.AuthorizationTest.WebDataServiceA); request.RequestUriString = "/Customers?" + ((option == "$filter") ? "$filter=BestFriend/ID%20gt%200" : "$orderby=BestFriend/ID%20desc"); request.Accept = "application/atom+xml,application/xml"; request.SendRequest(); var document = request.GetResponseStreamAsXmlDocument(); Assert.AreEqual(2, callCount, "Callback is called twice (once for URI, once for best friend."); // Customer with ID #2 has best friend with ID #1 and thus it's returned. TestUtil.AssertSelectSingleElement(document, "/atom:feed/atom:entry/atom:id[text()='http://host/Customers(2)']"); if (option == "$filter") { // Customer #0 is not returned because of the filter (on the segment), and // customer #1 is not returned because of the filter (on the navigation property). TestUtil.AssertSelectSingleElement(document, "/atom:feed[0 = count(//atom:id[text()='http://host/Customers(0)'])]"); TestUtil.AssertSelectSingleElement(document, "/atom:feed[0 = count(//atom:id[text()='http://host/Customers(1)'])]"); } else { // Customer #0 is not returned because of the filter (on the segment). TestUtil.AssertSelectSingleElement(document, "/atom:feed[0 = count(//atom:id[text()='http://host/Customers(0)'])]"); TestUtil.AssertSelectSingleElement(document, "/atom:feed[1 = count(//atom:id[text()='http://host/Customers(1)'])]"); } } }); }
public void RequestQueryRecursionLimitReached() { using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { using (StaticCallbackManager <PopulatingValuesEventArgs <OpenElement> > .RegisterStatic((sender, args) => { var o = new OpenElement(); o.Properties["Foo"] = null; args.Values.Add(o); })) { request.DataServiceType = typeof(OpenTypeContextWithReflection <OpenElement>); request.RequestUriString = "/Values?$filter=length(length(length(length(length(length(length(length(length(length(length(length(length(length(length(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((Foo))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) gt 5"; Exception exception = TestUtil.RunCatching(request.SendRequest); Assert.IsTrue(exception != null, "Exception must be thrown"); Assert.IsTrue(exception.InnerException.Message.Contains("Recursion")); } } }
public void OpenTypeGetOpenPropertyValuesWithNull() { using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { using (TestUtil.RestoreStaticValueOnDispose(typeof(OpenTypeContextWithReflectionConfig), "NullOnGetOpenPropertyValues")) using (StaticCallbackManager <PopulatingValuesEventArgs <OpenElement> > .RegisterStatic((sender, args) => { var o = new OpenElement(); o.Properties["Foo"] = 1; args.Values.Add(o); })) { OpenTypeContextWithReflectionConfig.NullOnGetOpenPropertyValues = true; request.DataServiceType = typeof(OpenTypeContextWithReflection <OpenElement>); request.RequestUriString = "/Values"; Exception exception = TestUtil.RunCatching(request.SendRequest); Assert.IsTrue(exception == null, "GetOpenPropertyValues should handle null as an empty collection."); } } }
public void OpenTypeJsonWithNulls() { using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { using (StaticCallbackManager <PopulatingValuesEventArgs <OpenElement> > .RegisterStatic((sender, args) => { var o = new OpenElement(); o.Properties["Foo"] = null; args.Values.Add(o); })) { request.DataServiceType = typeof(OpenTypeContextWithReflection <OpenElement>); request.RequestUriString = "/Values"; request.Accept = UnitTestsUtil.JsonLightMimeType; Exception exception = TestUtil.RunCatching(request.SendRequest); String response = request.GetResponseStreamAsText(); Assert.AreEqual(exception, null); Assert.IsTrue(response.Contains("\"Foo\":null")); } } }
public void SecurityCallbacksFilterEdmTest() { ServiceModelData.Northwind.EnsureDependenciesAvailable(); CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("option", "$filter,$orderby".Split(','))); TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { string option = (string)values["option"]; int callCount = 0; using (AstoriaUnitTests.Tests.UnitTestModule.AuthorizationTest.InitializationCallbackManager.RegisterStatic((s, e) => { e.Configuration.SetEntitySetAccessRule("*", EntitySetRights.All); })) using (StaticCallbackManager <AstoriaUnitTests.Tests.UnitTestModule.AuthorizationTest.ComposeQueryEventArgs> .RegisterStatic((s, e) => { System.Linq.Expressions.Expression <Func <NorthwindModel.Customers, bool> > notAnatr = c => c.CustomerID != "ANATR"; e.Filter = notAnatr; callCount++; })) using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { // In Northwind, the two first customers are 'ALFKI' and 'ANATR'. // 'ALFKI' has these orders: 10643, 10692, 10702, 10835, 10952, 11011. // 'ANATR' has these orders: 10308, 10625, 10759, 10926. request.ServiceType = typeof(AstoriaUnitTests.Tests.UnitTestModule.AuthorizationTest.WebDataServiceEdmCustomerCallback); request.RequestUriString = "/Orders?" + ((option == "$filter") ? "$filter=startswith(Customers/CustomerID, 'A')" : "$filter=startswith(Customers/CustomerID,%20'A')%20or%20Customers%20eq%20null&$orderby=Customers/CustomerID"); request.Accept = "application/atom+xml,application/xml"; request.SendRequest(); var document = request.GetResponseStreamAsXmlDocument(); if (option == "$filter") { Assert.AreEqual(1, callCount, "Callback is called a single time (for the navigation property."); // The orders for 'ANATR' should not be returned TestUtil.AssertSelectSingleElement(document, "/atom:feed[0 = count(atom:entry/atom:id[text()='http://host/Orders(10308)'])]"); TestUtil.AssertSelectSingleElement(document, "/atom:feed[0 = count(atom:entry/atom:id[text()='http://host/Orders(10625)'])]"); // ALFKI is OK. TestUtil.AssertSelectSingleElement(document, "/atom:feed[1 = count(atom:entry/atom:id[text()='http://host/Orders(10643)'])]"); } else { Assert.AreEqual(3, callCount, "Callback is called a three tims (for the navigation property)"); // ANATR will come before ALFKI System.Xml.XmlElement alfkiOrder = TestUtil.AssertSelectSingleElement(document, "/atom:feed/atom:entry[atom:id/text()='http://host/Orders(10643)']"); System.Xml.XmlElement anatrOrder = TestUtil.AssertSelectSingleElement(document, "/atom:feed/atom:entry[atom:id/text()='http://host/Orders(10308)']"); bool found = false; System.Xml.XmlNode node = alfkiOrder; while (node != null) { if (node == anatrOrder) { found = true; break; } else { node = node.PreviousSibling; } } Assert.IsTrue(found, "ANATR orders sort after ALFKI"); } } }); }
[Ignore] // Remove Atom // [TestCategory("Partition2"), TestMethod, Variation] public void ConfigurationBatchTest() { CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("MaxBatchCount", new int[] { -1, 0, 1, 2, 10 }), new Dimension("MaxChangeSetCount", new int[] { -1, 0, 1, 2, 10 }), new Dimension("BatchCount", new int[] { 0, 1, 2 }), new Dimension("ChangeSetCount", new int[] { 0, 1, 2 }) ); TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { int maxBatchCount = (int)values["MaxBatchCount"]; int maxChangeSetCount = (int)values["MaxChangeSetCount"]; int batchCount = (int)values["BatchCount"]; int changeSetCount = (int)values["ChangeSetCount"]; TestUtil.ClearConfiguration(); using (CustomDataContext.CreateChangeScope()) using (TestWebRequest request = TestWebRequest.CreateForInProcess()) using (StaticCallbackManager <InitializeServiceArgs> .RegisterStatic((sender, args) => { args.Config.SetEntitySetAccessRule("*", EntitySetRights.All); args.Config.MaxBatchCount = maxBatchCount; args.Config.MaxChangesetCount = maxChangeSetCount; args.Config.UseVerboseErrors = true; })) { request.ServiceType = typeof(TypedDataService <CustomDataContext>); request.RequestUriString = "/$batch"; request.HttpMethod = "POST"; request.Accept = "*/*"; string boundary = "boundary"; request.RequestContentType = String.Format("{0}; boundary={1}", UnitTestsUtil.MimeMultipartMixed, boundary); int customerId = 1000; int contentId = 0; StringBuilder payload = new StringBuilder(); for (int i = 0; i < batchCount; i++) { StringBuilder batchElement = new StringBuilder(); if (i % 2 == 0) { string changesetBoundary = "cs"; for (int j = 0; j < changeSetCount; j++) { StringBuilder changeSetElement = new StringBuilder(); changeSetElement.AppendLine("<entry " + TestUtil.CommonPayloadNamespaces + ">"); changeSetElement.AppendLine(AtomUpdatePayloadBuilder.GetCategoryXml("AstoriaUnitTests.Stubs.Customer")); changeSetElement.AppendLine(" <content type='application/xml'><adsm:properties>"); changeSetElement.AppendLine(" <ads:Name>A New Customer</ads:Name>"); changeSetElement.AppendLine(" <ads:ID>" + customerId++ + "</ads:ID>"); changeSetElement.AppendLine(" </adsm:properties></content></entry>"); int length = changeSetElement.Length; changeSetElement.Insert(0, "--" + changesetBoundary + "\r\n" + "Content-Type: application/http\r\n" + "Content-Transfer-Encoding: binary\r\n" + "Content-ID: " + (++contentId).ToString() + "\r\n" + "\r\n" + "POST /Customers HTTP/1.1\r\n" + "Content-Type: application/atom+xml;type=entry\r\n" + "Content-Length: " + length + "\r\n" + "\r\n"); batchElement.Append(changeSetElement.ToString()); } batchElement.AppendLine("--" + changesetBoundary + "--"); int batchLength = batchElement.Length; batchElement.Insert(0, "--" + boundary + "\r\n" + "Content-Type: multipart/mixed; boundary=" + changesetBoundary + "\r\n" + "Content-Length: " + batchLength + "\r\n" + "\r\n"); } else { // Do a GET request. batchElement.AppendLine("--" + boundary); batchElement.AppendLine("Content-Type: application/http"); batchElement.AppendLine("Content-Transfer-Encoding: binary"); batchElement.AppendLine(); batchElement.AppendLine("GET /Customers HTTP/1.1"); batchElement.AppendLine("Content-Length: 0"); batchElement.AppendLine(); } payload.Append(batchElement.ToString()); } payload.AppendLine("--" + boundary + "--"); string payloadText = payload.ToString(); Trace.WriteLine("Payload text:"); Trace.WriteLine(payloadText); request.SetRequestStreamAsText(payloadText); // Build a payload. Exception exception = TestUtil.RunCatching(request.SendRequest); TestUtil.AssertExceptionExpected(exception, maxBatchCount < 0, maxChangeSetCount < 0); if (exception == null) { string text = request.GetResponseStreamAsText(); if (maxBatchCount < batchCount || (batchCount > 0 && maxChangeSetCount < changeSetCount)) { TestUtil.AssertContains(text, "error"); } else { TestUtil.AssertContainsFalse(text, "error"); } } } }); }
[Ignore] // Remove Atom // [TestCategory("Partition2"), TestMethod, Variation] public void TestExceedMaxBatchCount() { // Astoria Server: Assert on Batch Request after configuring MaxBatchCount TestUtil.ClearConfiguration(); try { using (CustomDataContext.CreateChangeScope()) using (TestWebRequest request = TestWebRequest.CreateForInProcess()) using (StaticCallbackManager <InitializeServiceArgs> .RegisterStatic((sender, args) => { args.Config.SetEntitySetAccessRule("*", EntitySetRights.All); args.Config.MaxBatchCount = 1; args.Config.UseVerboseErrors = true; })) { request.ServiceType = typeof(TypedDataService <CustomDataContext>); request.HttpMethod = "POST"; request.RequestUriString = "/$batch"; request.RequestContentType = "multipart/mixed;boundary=boundary1"; request.SetRequestStreamAsText( "--boundary1\r\n" + "Content-Type: multipart/mixed; boundary=cs\r\n" + "\r\n" + "--cs\r\n" + "Content-Type: application/http\r\n" + "Content-Transfer-Encoding: binary\r\n" + "\r\n" + "POST /Customers HTTP/1.1\r\n" + "Content-Type: application/atom+xml\r\n" + "Accept: application/atom+xml\r\n" + "Content-ID : 2\r\n" + "\r\n" + "<entry xmlns:ads='http://docs.oasis-open.org/odata/ns/data' xmlns:adsm='http://docs.oasis-open.org/odata/ns/metadata' xmlns='http://www.w3.org/2005/Atom' adsm:type='#AstoriaUnitTests.Stubs.Customer'>\r\n" + "<content type='application/xml'>\r\n" + "<adsm:properties>\r\n" + "<ads:ID ads:type='Edm.Int32'>10</ads:ID>\r\n" + "</adsm:properties>\r\n" + "</content></entry>\r\n" + "--cs--\r\n" + "--boundary1\r\n" + "Content-Type: multipart/mixed; boundary=cs\r\n" + "\r\n" + "--cs\r\n" + "Content-Type: application/http\r\n" + "Content-Transfer-Encoding: binary\r\n" + "\r\n" + "POST /Customers HTTP/1.1\r\n" + "Content-Type: application/atom+xml\r\n" + "Accept: application/atom+xml\r\n" + "Content-ID : 2\r\n" + "\r\n" + "<entry xmlns:ads='http://docs.oasis-open.org/odata/ns/data' xmlns:adsm='http://docs.oasis-open.org/odata/ns/metadata' xmlns='http://www.w3.org/2005/Atom' adsm:type='#AstoriaUnitTests.Stubs.Customer'>\r\n" + "<content type='application/xml'>\r\n" + "<adsm:properties>\r\n" + "<ads:ID ads:type='Edm.Int32'>10</ads:ID>\r\n" + "</adsm:properties>\r\n" + "</content></entry>\r\n" + "--cs--\r\n" + "--boundary1--"); Exception exception = TestUtil.RunCatching(request.SendRequest); TestUtil.AssertExceptionExpected(exception, false); string response = request.GetResponseStreamAsText(); TestUtil.AssertContains(response, "exceeds"); } } finally { TestUtil.ClearMetadataCache(); } }
// TODO: enable this once we have support for expanding open properties //[TestMethod] public void OpenTypeExpandTest() { CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("SerializationFormatData", SerializationFormatData.StructuredValues)); using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(TypedCustomDataContext <OpenElement>); using (StaticCallbackManager <PopulatingValuesEventArgs <OpenElement> > .RegisterStatic((sender, args) => { var o = new OpenElement(); o.ID = "100"; o.Properties.Add("sampleValue1", new OpenElement() { ID = "101" }); o.Properties.Add("sampleValue2", new OpenElement[] { new OpenElement() { ID = "102" } }); o.Properties.Add("address", new Address() { StreetAddress = "L1", City = "City", State = "S1", PostalCode = "98052" }); o.Properties.Add("primitive", "abc"); o.Properties.Add("thenull", null); args.Values.Add(o); })) { TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { SerializationFormatData format = (SerializationFormatData)values["SerializationFormatData"]; request.Accept = format.MimeTypes[0]; XmlDocument document; string[] validation; request.RequestUriString = "/Values('100')"; request.SendRequest(); document = format.LoadXmlDocumentFromStream(request.GetResponseStream()); if (format == SerializationFormatData.Atom) { validation = new string[] { "/atom:entry/atom:link[@title='OpenTypes_OpenElement']", "/atom:entry/atom:content/adsm:properties/ads:ID[text()='100']", "/atom:entry/atom:link[@title='sampleValue1' and @type='application/atom+xml;type=entry']", "/atom:entry/atom:link[@title='sampleValue2' and @type='application/atom+xml;type=feed']", //"/atom:entry/atom:content/ads:address/ads:Line1[text()='L1']", //"/atom:entry/atom:content/ads:address/ads:Line2[@adsm:null='true']", "/atom:entry/atom:content/adsm:properties/ads:primitive[text()='abc']" }; } else { Debug.Assert(format == SerializationFormatData.Json); validation = new string[] { "/Object/__metadata/type[text()='AstoriaUnitTests.Tests.OpenTypes_OpenElement']", "/Object/ID[text()='100']", "/Object/sampleValue1/__deferred", "/Object/sampleValue2/__deferred", //"/Object/address/Line1[text()='L1']", //"/Object/address/Line2[@IsNull='true']", "/Object/primitive[text()='abc']" }; } TestUtil.TraceXml(document); foreach (string v in validation) { TestUtil.AssertSelectSingleElement(document, v); } request.RequestUriString = "/Values('100')?$expand=sampleValue1"; request.SendRequest(); document = format.LoadXmlDocumentFromStream(request.GetResponseStream()); TestUtil.TraceXml(document); if (format == SerializationFormatData.Atom) { TestUtil.AssertSelectSingleElement( document, "/atom:entry/atom:link[@title='sampleValue1']/*/atom:entry/atom:content/adsm:properties/ads:ID[text()='101']"); } else { TestUtil.AssertSelectSingleElement( document, "/Object/sampleValue1/__metadata/type[text()='AstoriaUnitTests.Tests.OpenTypes_OpenElement']"); } request.RequestUriString = "/Values('100')?$expand=sampleValue2"; request.SendRequest(); document = format.LoadXmlDocumentFromStream(request.GetResponseStream()); TestUtil.TraceXml(document); if (format == SerializationFormatData.Atom) { TestUtil.AssertSelectSingleElement( document, "/atom:entry/atom:link[@title='sampleValue2']/*/atom:feed/atom:entry/atom:content/adsm:properties/ads:ID[text()='102']"); } else { TestUtil.AssertSelectSingleElement( document, "/Object/sampleValue2/Array/Object/__metadata/type[text()='AstoriaUnitTests.Tests.OpenTypes_OpenElement']"); } }); } } }