예제 #1
0
        // 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']");
                        }
                    });
                }
            }
        }
예제 #2
0
        [Ignore] // test case issue, request uri and service root in this case is null.
        public void RequestQueryParserTestBasicTests()
        {
            using (OpenWebDataServiceHelper.AcceptReplaceFunctionInQuery.Restore())
            {
                OpenWebDataServiceHelper.AcceptReplaceFunctionInQuery.Value = true;
                TestUtil.ClearConfiguration();

                // Repro Protocol: Filter - replace not implemented?
                // Repro Protocol: Can't cast simple primitive value in filter expression
                CombinatorialEngine engine = CombinatorialEngine.FromDimensions(
                    new Dimension("ServiceModelData", ServiceModelData.Values));

                TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values)
                {
                    ServiceModelData modelData = (ServiceModelData)values["ServiceModelData"];
                    object service             = Activator.CreateInstance(typeof(OpenWebDataService <>).MakeGenericType(modelData.ServiceModelType));
                    service.GetType().GetMethod("AttachHost", BindingFlags.Public | BindingFlags.Instance).Invoke(service, new object[] { new TestServiceHost2() });
                    object context  = ServiceModelData.InitializeAndGetContext(service);
                    object provider = ServiceModelData.CreateProvider(context, service);

                    if (!modelData.ContainerNames.Contains("Customers"))
                    {
                        return;
                    }

                    string customerNameProperty = modelData.IsUnitTestProvider ? "Name" : "CompanyName";
                    string integerProperty      = modelData.IsUnitTestProvider ? "ID" : "1";

                    string[] predicates = new string[]
                    {
                        "1 eq 1",
                        "1 add 1 eq 2",
                        "2 eq 1 add 1",
                        "3.5 eq 3 add 0.5",
                        "3.5 eq 3 add 0.5",
                        "1 add 2 mul 2 eq 5",
                        "(1 add 2) mul 2 eq 6",
                        "2 sub 1 eq 1",
                        "2 sub 1 add 1 ne 1",
                        "1 add 1 lt 5",
                        "1 add 1 le 2",
                        "1 add 1 ge 2",
                        "1 add 1 gt 1",
                        "1 lt " + Int64.MaxValue + "L",
                        "1 gt " + Int64.MinValue + "L",
                        ///TODO: these 2 should succeed, (double, double, single) shouldn't get -1 from
                        ///private static int CompareConversions(Type source, Type targetA, Type targetB) , this method needs some fixing.
                        ///"1 lt " + decimal.MaxValue + "00",
                        ///"1 gt " + decimal.MinValue + "00",
                        "not (1 add 1 eq 1)",
                        "1 eq 1 or 2 eq 1",
                        "1 eq 1 and 2 eq 1 add 1",
                        "1 eq 1 and not not (2 eq 1 add 1)",
                        "1 eq 0 sub -1",
                        "1 eq 0 sub - 1",
                        "0 sub 3 eq -(3)",
                        "'a' eq 'a'",
                        "'abc' eq 'abc'",
                        "'''' eq ''''",
                        "-" + integerProperty + " eq 1 sub 2",
                        customerNameProperty + " eq 'John' or 1 eq 1",
                        "10 div 2 eq 5",
                        "3 mod 2 eq 1",
                        "1 gt " + XmlConvert.ToString(10.1E-9),
                        "1 lt " + XmlConvert.ToString(10.1E+3),
                        "binary'12AABBff' eq Binary'12aabbFF'",
                        "binary'000102030405060708090A0B0C0D0E0F' eq BINARY'000102030405060708090a0b0c0d0e0f'",
                        "binary'12AABBff' ne binary'22aabbFF'",

                        // String functions.
                        "endswith('abc', 'bc')",
                        "startswith('abc', 'ab')",
                        "not startswith('abc', 'aab')",
                        "contains('abc','b')",
                        "indexof('abc', 'b') ge 1",
                        "replace('foo','o','g') eq 'fgg'",
                        "substring('123', 1) eq '23'",
                        "substring('123', 1, 1) eq '2'",
                        "tolower('ABC') eq 'abc'",
                        "toupper('AbC') eq 'ABC'",
                        "length(toupper('aBc')) eq length(tolower('aBc'))",
                        "concat('a', 'b') eq 'ab'",
                        "'a' lt 'b'",
                        "'a' le 'a'",
                        "'a' ge 'a'",
                        "'b' ge 'a'",
                        // "'a' add 'b' eq 'ab'",
                        // Repro Protocol: can't call date function in filter expressions on LinqToSql
                        "startswith(" + customerNameProperty + ", 'C')",
                        "endswith(concat(" + customerNameProperty + ", 'b'), 'b')",
                        "contains(" + customerNameProperty + ",'C')",
                        "trim(" + customerNameProperty + ") eq substring(" + customerNameProperty + ", 0)",

                        // DateTime functions.
                        "year(2007-08-08) eq 2007",
                        "month(2007-08-10) eq 08",
                        "day(2007-08-10) eq 10",
                        "hour(2007-08-10T14:11:12Z) eq 14",
                        "minute(2007-08-10T14:11:12Z) eq 11",
                        "second(2007-08-10T14:11:12Z) eq 12",

                        // Math functions.
                        "round(1.1) eq 1",
                        "round(42) eq 42",
                        "floor(1.1M) eq 1",
                        "ceiling(1.1f) eq 2",
                    };

                    if (modelData.IsUnitTestProvider)
                    {
                        // Refer to some specific types.
                        string[] customDataContextPredicates = new string[]
                        {
                            //   "(BestFriend ne null and BestFriend/Name eq 'John') or 1 eq 1",
                            "GuidValue ne 5dc82c04-570a-41f5-b48f-c8a4e436f716",
                            "GuidValue ne 5dc82c04-570a-41f5-b48f-c8a4e436f716",
                            "GuidValue ne 5dc82c04-570a-41f5-b48f-c8a4e436f716 and GuidValue ne 5dc82c04-570a-41f5-b48f-c8a4e436f716",
                            // Type functions.
                            "ID eq cast(1, 'Edm.Int32')",
                            String.Format("not isof(1, '{0}')", UnitTestsUtil.ConvertTypeNames("AstoriaUnitTests.Stubs.Customer", context)),
                            String.Format("isof('{0}')", UnitTestsUtil.ConvertTypeNames("AstoriaUnitTests.Stubs.Customer", context)),
                            String.Format("isof('{0}') and cast('{0}')/Birthday gt 1960-01-01", UnitTestsUtil.ConvertTypeNames("AstoriaUnitTests.Stubs.CustomerWithBirthday", context))
                        };

                        if (!(context is CustomRowBasedOpenTypesContext))
                        {
                            predicates = predicates.Concat(new string[] {
                                "ID eq cast(1, 'Edm.Int64')",
                                "ID eq 1L"
                            }).ToArray();
                        }

                        predicates = predicates.Concat(customDataContextPredicates).ToArray();
                    }
                    else if (context is NorthwindModel.NorthwindContext)
                    {
                        string[] northwindPredicates = new string[]
                        {
                            // Repro 602210 - Exception when filter expression contains null
                            "((((CustomerID) eq ('ALFKI')) and ((CustomerID) eq ('ANATR')))) or ((Region) ne (null))"
                        };
                        predicates = predicates.Concat(northwindPredicates).ToArray();
                    }
                    else if (context is AstoriaUnitTests.Stubs.Sql.SqlNorthwindDataContext)
                    {
                        string[] sqlNorthwindPredicates = new string[]
                        {
                            // Repro Protocol: Can't compare properties to null in LinqToSql filter expression
                            "Categories|CategoryName eq null or 1 add 1 eq 2",
                            "Categories|null eq CategoryName or 1 add 1 eq 2",

                            // Repro Protocol: error trying to use Link property in filter expression (LinqToSql)
                            //"Categories|contains('Beer',CategoryName)",
                            //"Products|contains('Beer',Categories/CategoryName)",

                            // Repro Protocol: can't call date function in filter expressions on LinqToSql
                            //"Employees|month(HireDate) eq 5",
                        };
                        predicates = sqlNorthwindPredicates;
                        // predicates = predicates.Concat(sqlNorthwindPredicates).ToArray();
                    }

                    VerifyResultsExistForWhere(service, context, "Customers", predicates);
                });
            }
        }
예제 #3
0
            [Ignore] // Remove Atom
            // [TestMethod]
            public void SecurityMaxResultsTest()
            {
                CombinatorialEngine engine = CombinatorialEngine.FromDimensions(
                    new Dimension("SerializationFormatData", SerializationFormatData.StructuredValues),
                    new Dimension("Expand", new bool[] { true, false }),
                    new Dimension("LinksOnly", new bool[] { true, false }),
                    new Dimension("OrderCount", new int[] { 0, 1, 2, 3 }),
                    new Dimension("CustomerCount", new int[] { 0, 1, 2, 3 }),
                    new Dimension("MaxResultsPerCollection", new int[] { Int32.MaxValue, 0, 1, 2, 3 }));

                TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values)
                {
                    SerializationFormatData format = (SerializationFormatData)values["SerializationFormatData"];
                    bool expand                 = (bool)values["Expand"];
                    int customerCount           = (int)values["CustomerCount"];
                    int orderCount              = (int)values["OrderCount"];
                    bool linksOnly              = (bool)values["LinksOnly"];
                    int maxResultsPerCollection = (int)values["MaxResultsPerCollection"];

                    // $ref only makes sense if we want to bring down the related items.
                    if (linksOnly && !expand)
                    {
                        return;
                    }

                    TestUtil.ClearConfiguration();
                    using (var request = TestWebRequest.CreateForInProcess())
                    {
                        request.TestArguments = new Hashtable();
                        request.TestArguments[CustomDataContext.CustomerCountArgument] = customerCount;
                        request.TestArguments[CustomDataContext.OrderCountArgument]    = orderCount;
                        request.ServiceType      = typeof(AuthorizationTest.WebDataServiceA);
                        request.Accept           = format.MimeTypes[0];
                        request.RequestUriString = expand ?
                                                   (linksOnly ? "/Customers(0)/Orders/$ref" : "/Customers?$expand=Orders") :
                                                   "/Customers";
                        if (linksOnly && format == SerializationFormatData.Atom)
                        {
                            request.Accept = "*/*";
                        }

                        using (AuthorizationTest.InitializationCallbackManager.RegisterStatic((sender, args) =>
                        {
                            args.Configuration.MaxResultsPerCollection = maxResultsPerCollection;
                            args.Configuration.SetEntitySetAccessRule("*", EntitySetRights.All);
                        }))
                        {
                            Exception exception = TestUtil.RunCatching(delegate()
                            {
                                request.SendRequest();
                                string response = request.GetResponseStreamAsText();
                                if (response.Contains("<m:error") || response.Contains("\"error\":"))
                                {
                                    throw new Exception(response);
                                }
                            });

                            TestUtil.AssertExceptionExpected(exception,
                                                             customerCount > maxResultsPerCollection && !linksOnly,
                                                             expand && orderCount > maxResultsPerCollection && customerCount > 0);
                        }
                    }
                });
            }
예제 #4
0
            [Ignore] // Remove Atom
            // [TestMethod]
            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");
                                }
                            }
                });
            }
예제 #5
0
        public void RequestQueryParserOperatorsReferences()
        {
            // AllTypesWithReferences
            var referenceTypes = new Type[]
            {
                typeof(object),                                 // an open property
                null                                            // a null literal
            };
            CombinatorialEngine engine = CombinatorialEngine.FromDimensions(
                new Dimension("Operator", OperatorData.Values),
                new Dimension("LeftType", referenceTypes),
                new Dimension("RightType", TypeData.Values));

            OpenTypeContextWithReflection <AllTypesWithReferences> .ClearHandlers();

            try
            {
                OpenTypeContextWithReflection <AllTypesWithReferences> .ValuesRequested += (x, y) =>
                {
                    ((OpenTypeContextWithReflection <AllTypesWithReferences>)x).SetValues(new object[] { new AllTypesWithReferences() });
                };

                using (TestWebRequest request = TestWebRequest.CreateForInProcess())
                {
                    request.DataServiceType = typeof(OpenTypeContextWithReflection <AllTypesWithReferences>);
                    TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values)
                    {
                        Type left      = (Type)values["LeftType"];
                        TypeData right = (TypeData)values["RightType"];

                        if (!right.IsTypeSupported)
                        {
                            return;
                        }

                        string leftName          = AllTypesWithReferences.PropertyNameForReferenceType(left);
                        string rightName         = AllTypesWithReferences.PropertyNameForType(right.ClrType);
                        OperatorData o           = (OperatorData)values["Operator"];
                        string requestText       = "/Values?$filter=" + leftName + "%20" + o.Token + "%20" + rightName;
                        request.RequestUriString = requestText;
                        Trace.WriteLine("Sending request " + requestText);
                        Exception exception = TestUtil.RunCatching(request.SendRequest);
                        if (left == null)
                        {
                            // Anything can be compared to null (but only for equality, no ordering supported).
                            TestUtil.AssertExceptionExpected(exception, !o.IsEqualityComparison);
                        }
                        else if (left == typeof(object))
                        {
                            // Anything can be compared to an open property for anything at parse time.
                            // At execution time, ordering will only be supported for types which can be
                            // ordered as well.
                            //
                            // NOTE: because the sample values are null, reference checks will succeed at runtime.
                            //       (we normally would just fail this at parse time, but because these are reference
                            //       types and provides the open type comparer, it passes; that's probably OK, in case
                            //       a back-end does provider order for these types)
                            TestUtil.AssertExceptionExpected(exception,
                                                             !o.IsEqualityComparison && !right.IsOrderComparableTo(right) &&
                                                             right.ClrType != typeof(byte[]) && right.ClrType != typeof(System.Data.Linq.Binary) &&
                                                             right.ClrType != typeof(System.Xml.Linq.XElement) &&
                                                             !(null != Nullable.GetUnderlyingType(right.ClrType)));
                        }
                    });
                }
            }
            finally
            {
                OpenTypeContextWithReflection <AllTypesWithReferences> .ClearHandlers();
            }
        }
예제 #6
0
        public void EncodingFromAcceptCharsetTest()
        {
            // It takes over a minute to run all combinations.
            CombinatorialEngine engine = CombinatorialEngine.FromDimensions(
                new Dimension("EncodingData", EncodingData.Values),
                new Dimension("StringData", StringData.Values),
                new Dimension("SerializationFormatData", SerializationFormatData.StructuredValues),
                new Dimension("WebServerLocation", new object[] { WebServerLocation.InProcess }));

            engine.Mode = CombinatorialEngineMode.EveryElement;

            TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable table)
            {
                EncodingData encodingData      = (EncodingData)table["EncodingData"];
                StringData stringData          = (StringData)table["StringData"];
                WebServerLocation location     = (WebServerLocation)table["WebServerLocation"];
                SerializationFormatData format = (SerializationFormatData)table["SerializationFormatData"];

                if (encodingData.Encoding == null)
                {
                    return;
                }

                if (!EncodingHandlesString(encodingData.Encoding, "<>#&;\r\n"))
                {
                    return;
                }

                // Transliteration of ISCII characters and Unicode is possible, but round-tripping from
                // Unicode will not work because all phonetic sounds share an ISCII value, but have
                // distinct Unicode points depending on the language.
                if (encodingData.Name.StartsWith("x-iscii") && stringData.TextScript != null && stringData.TextScript.SupportsIscii)
                {
                    return;
                }

                using (CustomDataContext.CreateChangeScope())
                    using (TestWebRequest request = TestWebRequest.CreateForLocation(location))
                    {
                        request.DataServiceType    = typeof(CustomDataContext);
                        request.HttpMethod         = "POST";
                        request.RequestUriString   = "/Customers";
                        request.RequestContentType = UnitTestsUtil.JsonLightMimeType;
                        request.SetRequestStreamAsText("{ " +
                                                       "@odata.type : \"AstoriaUnitTests.Stubs.Customer\" ," +
                                                       "ID: 100," +
                                                       "Name: " +
                                                       System.Data.Test.Astoria.Util.JsonPrimitiveTypesUtil.PrimitiveToString(stringData.Value, typeof(string)) +
                                                       " }");
                        request.SendRequest();

                        request.HttpMethod       = "GET";
                        request.AcceptCharset    = encodingData.Name;
                        request.Accept           = format.MimeTypes[0];
                        request.RequestUriString = "/Customers(100)";

                        bool encoderCanHandleData = EncodingHandlesString(encodingData.Encoding, stringData.Value);
                        Trace.WriteLine("Encoding handles string: " + encoderCanHandleData);

                        Exception exception = TestUtil.RunCatching(request.SendRequest);

                        XmlDocument document = null;
                        Stream byteStream    = new MemoryStream();
                        if (exception == null)
                        {
                            using (Stream stream = request.GetResponseStream())
                            {
                                IOUtil.CopyStream(stream, byteStream);
                            }

                            byteStream.Position = 0;
                            Trace.WriteLine(TestUtil.BuildHexDump(byteStream));
                            byteStream.Position = 0;

                            if (format == SerializationFormatData.Atom)
                            {
                                document = new XmlDocument(TestUtil.TestNameTable);
                                using (StreamReader reader = new StreamReader(byteStream, encodingData.Encoding))
                                {
                                    document.Load(reader);
                                }

                                TestUtil.TraceXml(document);

                                XmlElement nameElement = TestUtil.AssertSelectSingleElement(document, "//ads:Name");
                                if (stringData.Value == null)
                                {
                                    Assert.IsTrue(UnitTestsUtil.HasElementNullValue(nameElement,
                                                                                    new System.Net.Mime.ContentType(request.ResponseContentType).MediaType));
                                }
                                else
                                {
                                    Assert.AreEqual(stringData.Value, nameElement.InnerText);
                                }
                            }
                        }
                        else
                        {
                            TestUtil.AssertExceptionExpected(exception, !encoderCanHandleData);
                        }
                    }
            });
        }
예제 #7
0
        public void RequestUriProcessorKeySpecialCharsTest()
        {
            ServiceModelData.Northwind.EnsureDependenciesAvailable();

            CombinatorialEngine engine = CombinatorialEngine.FromDimensions(
                new Dimension("WebServerLocation", TestWebRequest.LocalWebServerLocations));

            TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values)
            {
                WebServerLocation location = (WebServerLocation)values["WebServerLocation"];
                using (TestWebRequest request = TestWebRequest.CreateForLocation(location))
                {
                    Exception exception;
                    request.DataServiceType = typeof(NorthwindContext);

                    int expectedStatusCode;
                    if (location == WebServerLocation.InProcess)
                    {
                        expectedStatusCode = 404;
                    }
                    else
                    {
                        // See http://support.microsoft.com/kb/820129 for more information,
                        // including how to apply the changes.
                        // HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\HTTP\Parameters
                        int keyValue;
                        using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Services\HTTP\Parameters"))
                        {
                            keyValue = (int)key.GetValue("AllowRestrictedChars", 0);
                        }

                        expectedStatusCode = (keyValue == 0) ? 400 : 404;
                    }

                    // Check that control characters are accepted.
                    request.RequestUriString = "/Customers('\x003')";
                    exception = TestUtil.RunCatching(request.SendRequest);
                    TestUtil.AssertExceptionStatusCode(exception, expectedStatusCode, "404 expected for not-found entity with control character in key");

                    // Check that other special characters are accepted.
                    if (location == WebServerLocation.InProcess || location == WebServerLocation.InProcessWcf)
                    {
                        expectedStatusCode = 404;
                    }
                    else
                    {
                        // NOTE: this would work on IIS, but Cassini doesn't use this registry key.
                        // See http://support.microsoft.com/kb/932552 for more information,
                        // including how to apply the changes.
                        // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET
                        //int keyValue;
                        //using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\ASP.NET"))
                        //{
                        //    keyValue = (int)key.GetValue("VerificationCompatibility", 0);
                        //}

                        //expectedStatusCode = (keyValue == 0) ? 400 : 404;
                        expectedStatusCode = 400;
                    }

                    request.RequestUriString = "/Customers('.:')";
                    exception = TestUtil.RunCatching(request.SendRequest);
                    TestUtil.AssertExceptionStatusCode(exception, expectedStatusCode, "404 expected for not-found entity with special characters in key");
                }
            });
        }
예제 #8
0
            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");
                                    }
                                }
                            }
                });
            }
예제 #9
0
        public void RequestUriNamedKeyTest()
        {
            CombinatorialEngine engine = CombinatorialEngine.FromDimensions(
                new Dimension("TypeData", TypeData.Values),
                new Dimension("UseSmallCasing", new bool[] { true, false }),
                new Dimension("UseDoublePostfix", new bool[] { true, false }));

            bool syntaxErrorTested = false;

            TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values)
            {
                TypeData typeData = (TypeData)values["TypeData"];
                if (!typeData.IsTypeSupportedAsKey)
                {
                    return;
                }

                // TODO: when System.Uri handles '/' correctly, re-enable.
                if (typeData.ClrType == typeof(System.Xml.Linq.XElement))
                {
                    return;
                }

                Type entityType = typeof(DoubleKeyTypedEntity <, ,>).MakeGenericType(typeData.ClrType, typeData.ClrType, typeof(int));
                CustomDataContextSetup setup = new CustomDataContextSetup(entityType);
                object idValue = typeData.NonNullValue;
                if (idValue is byte[])
                {
                    // idValue = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
                    return;
                }

                bool useSmallCasing   = (bool)values["UseSmallCasing"];
                bool useDoublePostFix = (bool)values["UseDoublePostfix"];

                if (!(idValue is double) && useDoublePostFix)
                {
                    return;
                }

                string valueAsString = TypeData.FormatForKey(idValue, useSmallCasing, useDoublePostFix);

                TestUtil.ClearMetadataCache();
                using (TestWebRequest request = TestWebRequest.CreateForLocation(WebServerLocation.InProcess))
                {
                    Trace.WriteLine("Running with value: [" + valueAsString + "] for [" + typeData.ToString() + "]");
                    setup.Id          = idValue;
                    setup.SecondId    = idValue;
                    setup.MemberValue = 1;

                    request.DataServiceType  = setup.DataServiceType;
                    request.Accept           = "application/atom+xml,application/xml";
                    request.RequestUriString = "/Values(FirstKey=" + valueAsString + ",SecondKey=" + valueAsString + ")";
                    request.SendRequest();
                    string response = request.GetResponseStreamAsText();
                    TestUtil.AssertContains(response, "/Values(FirstKey=");
                    TestUtil.AssertContains(response, ",SecondKey=");
                    if (!syntaxErrorTested)
                    {
                        syntaxErrorTested = true;
                        VerifyRequestSyntaxError(request,
                                                 "/Values(" + valueAsString + "," + valueAsString + ")");
                        VerifyRequestSyntaxError(request,
                                                 "/Values(SecondKey == " + valueAsString + " , FirstKey = " + valueAsString + " )");
                        VerifyRequestSyntaxError(request,
                                                 "/Values(ASecondKey = " + valueAsString + " , FirstKey = " + valueAsString + " )");
                        VerifyRequestSyntaxError(request,
                                                 "/Values(SecondKey = " + valueAsString + ")");
                        VerifyRequestSyntaxError(request,
                                                 "/Values(SecondKey = " + valueAsString + ",,FirstKey=" + valueAsString + ")");
                        VerifyRequestSyntaxError(request,
                                                 "/Values(SecondKey)");
                        VerifyRequestSyntaxError(request,
                                                 "/Values(SecondKey=,FirstKey=)");
                        VerifyRequestSyntaxError(request,
                                                 "/Values(SecondKey = " + valueAsString + ",FirstKey=" + valueAsString +
                                                 ",ThirdKey=" + valueAsString + ")");
                    }
                }
                setup.Cleanup();
            });
        }
예제 #10
0
        [Ignore] // Remove Atom
        // [TestMethod]
        public void ProcessExceptionTest()
        {
            Type[] exceptionTypes = new Type[]
            {
                typeof(OutOfMemoryException),
                typeof(DataServiceException),
                typeof(FormatException),
                typeof(DataServiceException),
            };

            // At-End is currently always true, because the IQueryable caching
            // doesn't give us a good point to fail before content is written out.
            CombinatorialEngine engine = CombinatorialEngine.FromDimensions(
                new Dimension(CustomDataContext.ExceptionTypeArgument, exceptionTypes),
                new Dimension(CustomDataContext.ExceptionAtEndArgument, new object[] { true }),
                new Dimension("Format", SerializationFormatData.Values),
                new Dimension("WebServerLocation", new object[] { WebServerLocation.InProcess, WebServerLocation.Local }));

            TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values)
            {
                Type exceptionType             = (Type)values[CustomDataContext.ExceptionTypeArgument];
                bool exceptionAtEnd            = (bool)values[CustomDataContext.ExceptionAtEndArgument];
                SerializationFormatData format = (SerializationFormatData)values["Format"];
                WebServerLocation location     = (WebServerLocation)values["WebServerLocation"];

                // The local web server doesn't handle OOF gracefully - skip that case.
                if (exceptionType == typeof(OutOfMemoryException) &&
                    location == WebServerLocation.Local)
                {
                    return;
                }

                // No binary properties in the model.
                if (format.Name == "Binary")
                {
                    return;
                }

                // We need at least 1024 bytes to be written out for the default
                // StreamWriter used by the XmlTextWriter to flush out (at which point
                // we can assume that throwing at the end of the stream caused
                // a "partial send").
                //
                // However the implementation ends up using an XmlUtf8RawTextWriterIndent
                // object, with a BUFSIZE of 0x1800 as declared on XmlUtf8RawTextWriter.
                //
                // (0x1800 / "Customer 1".Length) + 1 is ideal, but we can make do with much less.
                int customerCount = (0xA0 / "Customer 1".Length) + 1;
                values[CustomDataContext.CustomerCountArgument] = customerCount;

                using (TestWebRequest request = TestWebRequest.CreateForLocation(location))
                {
                    request.DataServiceType  = typeof(CustomDataContext);
                    request.TestArguments    = values;
                    request.Accept           = format.MimeTypes[0];
                    request.RequestUriString =
                        (format.Name == "Text") ? "/Customers(" + customerCount + ")/ID/$value" : "/Customers";

                    Trace.WriteLine("Requesting " + request.RequestUriString);
                    Stream response           = new MemoryStream();
                    Exception thrownException = null;
                    try
                    {
                        request.SendRequest();
                        thrownException = new ApplicationException("No exception actually thrown.");
                    }
                    catch (Exception exception)
                    {
                        thrownException = exception;
                    }

                    // InProcess always throws WebException. Look in the inner exception for the right exception type.
                    if (location == WebServerLocation.InProcess && !format.IsPrimitive && exceptionType != typeof(OutOfMemoryException))
                    {
                        Assert.AreEqual(typeof(WebException), thrownException.GetType(), "InProcess should always throw WebException - Look in TestServiceHost.ProcessException");
                        thrownException = thrownException.InnerException;
                    }

                    // Exception may be wrapped by TargetInvocationException.
                    if (thrownException is TargetInvocationException)
                    {
                        thrownException = thrownException.InnerException;
                    }

                    TestUtil.CopyStream(request.GetResponseStream(), response);

                    response.Position = 0;
                    if (exceptionAtEnd && !format.IsPrimitive)
                    {
                        // for inprocess, there will be no exception in the payload
                        if (location == WebServerLocation.InProcess)
                        {
                            // Verify the exception type
                            Assert.AreEqual(exceptionType, thrownException.GetType(), "Exception type did not match");
                            return;
                        }

                        Assert.IsTrue(HasContent(response), "HasContent(response)");
                        Assert.IsTrue(String.Equals(request.Accept, TestUtil.GetMediaType(request.ResponseContentType), StringComparison.OrdinalIgnoreCase));
                        if (exceptionType != typeof(OutOfMemoryException))
                        {
                            string responseText = new StreamReader(response).ReadToEnd();
                            TestUtil.AssertContains(responseText, "error");
                            TestUtil.AssertContains(responseText, "message");
                        }

                        Assert.IsTrue(thrownException is ApplicationException, "No exception thrown.");
                    }
                    else
                    {
                        if (exceptionType == typeof(OutOfMemoryException))
                        {
                            if (location == WebServerLocation.InProcess)
                            {
                                Assert.IsTrue(thrownException is OutOfMemoryException, "thrownException is OutOfMemoryException");
                                Assert.IsTrue(exceptionAtEnd || !HasContent(response), "exceptionAtEnd || !HasContent(response)");
                            }
                            else
                            {
                                Assert.IsTrue(thrownException is WebException, "thrownException is WebException");
                            }
                        }
                        else
                        {
                            Assert.IsTrue(thrownException is WebException, "thrownException is WebException");
                            Assert.IsTrue(HasContent(response), "HasContent(response)");
                            string expected =
                                (location == WebServerLocation.InProcess) ? "text/plain" : "application/xml";
                            Assert.AreEqual(expected, TestUtil.GetMediaType(request.ResponseContentType));
                        }
                    }
                }
            });
        }
예제 #11
0
        public void AtomMaterializerLogTryResolve()
        {
            ReadOnlyTestContext.AddBaselineIncludes(typeof(Team), "Players");
            string players = FeedStart +
                             AnyEntry("p1", "<d:ID>10</d:ID>", null) +
                             AnyEntry("p2", "<d:ID>20</d:ID>", null) +
                             "</feed>";
            string playersTweaked = FeedStart +
                                    AnyEntry("p1", "<d:ID>100</d:ID>", null) +
                                    AnyEntry("p2", "<d:ID>200</d:ID>", null) +
                                    "</feed>";
            string xml = FeedStart +
                         AnyEntry("t1", "<d:TeamID>1</d:TeamID>", LinkFeed("Players", players)) +
                         AnyEntry("t2", "<d:TeamID>2</d:TeamID>", LinkFeed("Players", playersTweaked)) +
                         "</feed>";

            CombinatorialEngine engine = CombinatorialEngine.FromDimensions(
                new Dimension("MergeOption", Enum.GetValues(typeof(MergeOption))),
                new Dimension("ChangeBetweenReads", new bool[] { true, false }));

            using (TestUtil.RestoreStaticMembersOnDispose(typeof(Player)))
                TestUtil.RunCombinatorialEngineFail(engine, (values) =>
                {
                    Player.EqualsUsesReferences = true;

                    MergeOption option       = (MergeOption)values["MergeOption"];
                    bool changeBetweenReads  = (bool)values["ChangeBetweenReads"];
                    this.context             = new DataServiceContext(serviceRoot);
                    this.context.EnableAtom  = true;
                    this.context.MergeOption = option;

                    var q = from t in context.CreateQuery <Team>("T").Expand("Players")
                            select t;

                    bool firstTeam = true;
                    foreach (var item in CreateTestMaterializeAtom(xml, q))
                    {
                        if (firstTeam)
                        {
                            Assert.AreEqual(1, item.TeamID, "item.TeamID");
                            Assert.IsNotNull(item.Players, "item.Players");

                            Assert.AreEqual(2, item.Players.Count, "item.Players.Count");
                            Assert.AreEqual(10, item.Players[0].ID, "item.Players[0].ID");
                            Assert.AreEqual(20, item.Players[1].ID, "item.Players[1].ID");

                            if (changeBetweenReads && option != MergeOption.NoTracking)
                            {
                                context.UpdateObject(item.Players[0]);
                                context.UpdateObject(item.Players[1]);
                            }
                        }
                        else
                        {
                            Assert.AreEqual(2, item.TeamID, "item.TeamID");
                            Assert.IsNotNull(item.Players, "item.Players");

                            Assert.AreEqual(2, item.Players.Count, "item.Players.Count");

                            // The players will have changed if:
                            // - In NoTracking: always
                            // - In PreserveClient: only if unchanged
                            // - In AppendOnly: only if unchanged
                            // - In OverwriteChanged: always
                            if (option == MergeOption.NoTracking || option == MergeOption.OverwriteChanges || !changeBetweenReads)
                            {
                                Assert.AreEqual(100, item.Players[0].ID, "item.Players[0].ID");
                                Assert.AreEqual(200, item.Players[1].ID, "item.Players[1].ID");
                            }
                            else
                            {
                                Assert.AreEqual(10, item.Players[0].ID, "item.Players[0].ID");
                                Assert.AreEqual(20, item.Players[1].ID, "item.Players[1].ID");
                            }
                        }

                        firstTeam = false;
                    }

                    if (option == MergeOption.NoTracking)
                    {
                        AssertEntityCount(0, "nothing tracked for NoTracking");
                        AssertLinkCount(0, "nothing tracked for NoTracking");
                    }
                    else
                    {
                        AssertEntityCount(4, "two teams, two players");
                        AssertLinkCount(4, "each team to each player");
                    }
                });
        }
예제 #12
0
        public void AtomMaterializerInitializeEntity()
        {
            CombinatorialEngine engine = CombinatorialEngine.FromDimensions(
                new Dimension("EntryIsNull", new bool[] { true, false }),
                new Dimension("AlreadyResolved", new bool[] { true, false }),
                new Dimension("UpdateLocal", new bool[] { true, false }),
                new Dimension("MergeOption", Enum.GetValues(typeof(MergeOption))),
                new Dimension("TypeChange", new bool[] { true, false }),
                new Dimension("HasContinuation", new bool[] { true, false }));

            TestUtil.RunCombinatorialEngineFail(engine, (values) =>
            {
                bool entryIsNull     = (bool)values["EntryIsNull"];
                bool alreadyResolved = (bool)values["AlreadyResolved"];
                MergeOption option   = (MergeOption)values["MergeOption"];
                bool typeChange      = (bool)values["TypeChange"];
                bool hasContinuation = (bool)values["HasContinuation"];
                bool updateLocal     = (bool)values["UpdateLocal"];

                context.ResolveType = null;

                string continuationXml = hasContinuation ? "<link rel='next' href='http://next/' />" : "";
                string leafEntry       = AnyEntry("l1", "<d:ID>10</d:ID><d:Member>10</d:Member>", null);
                string collectionEntry = alreadyResolved ? leafEntry : leafEntry.Replace('1', '2');
                string collection      = FeedStart + collectionEntry + continuationXml + "</feed>";
                string entry           = AnyEntry("e1", "<d:ID>1</d:ID>",
                                                  "<category scheme='http://docs.oasis-open.org/odata/ns/scheme' term='foo' />" +
                                                  LinkEntry("Member", entryIsNull ? "" : leafEntry) + LinkFeed("Member2", collection));
                string xml = FeedStart + entry + "</feed>";
                bool resolveTypeInvoked = false;

                if (typeChange)
                {
                    context.ResolveType += (n) =>
                    {
                        resolveTypeInvoked = true;
                        return(typeof(DoubleMemberTypedEntity <int, TypedEntity <int, int>, List <TypedEntity <int, int> > >));
                    };
                }

                this.context.MergeOption = MergeOption.AppendOnly;
                var q = from t in this.context.CreateQuery <DoubleMemberTypedEntity <int, TypedEntity <int, int>, List <TypedEntity <int, int> > > >("T")
                        select new DoubleMemberTypedEntity <int, TypedEntity <int, int>, List <TypedEntity <int, int> > >()
                {
                    ID     = t.ID,
                    Member = (t.Member == null) ? null : new TypedEntity <int, int>()
                    {
                        ID     = t.Member.ID,
                        Member = t.Member.Member
                    },
                    Member2 = t.Member2
                };

                foreach (var item in CreateTestMaterializeAtom(xml, q))
                {
                    Assert.IsNotNull(item, "item");
                    Assert.AreEqual(1, item.ID, "item.ID");
                    if (entryIsNull)
                    {
                        Assert.IsNull(item.Member, "item.Member");
                    }
                    else
                    {
                        Assert.IsNotNull(item.Member, "item.Member");
                        Assert.AreEqual(10, item.Member.ID, "item.Member.ID");
                    }

                    Assert.IsNotNull(item.Member2, "item.Member2");

                    Assert.AreEqual(1, item.Member2.Count, "item.Member2.Count");
                    Assert.AreEqual((alreadyResolved) ? 10 : 20, item.Member2[0].ID, "item.Member2[0].ID");

                    if (updateLocal && !entryIsNull)
                    {
                        this.context.UpdateObject(item.Member);
                    }

                    Assert.IsTrue(resolveTypeInvoked == typeChange, "resolveTypeInvoked == typeChange");
                }

                int expectedEntities = alreadyResolved ? 2 : 3;
                if (entryIsNull && !alreadyResolved)
                {
                    expectedEntities--;
                }

                AssertEntityCount(expectedEntities, "already resolved (an item is duplicate) is " + alreadyResolved + ", expecting root + child(ren)");
                AssertLinkCount(2, "root to each item, one through each property");

                resolveTypeInvoked       = false;
                this.context.MergeOption = option;
                xml = xml.Replace("<d:ID>10</d:ID>", "<d:ID>100</d:ID>");
                foreach (var item in CreateTestMaterializeAtom(xml, q))
                {
                    Assert.IsNotNull(item, "item");
                    Assert.AreEqual(1, item.ID, "item.ID");

                    int expectedItemId;
                    if (option == MergeOption.AppendOnly ||
                        (option == MergeOption.PreserveChanges && updateLocal && !entryIsNull))
                    {
                        expectedItemId = 10;
                    }
                    else
                    {
                        expectedItemId = 100;
                    }

                    if (entryIsNull)
                    {
                        Assert.IsNull(item.Member, "item.Member");
                    }
                    else
                    {
                        Assert.IsNotNull(item.Member, "item.Member");
                        Assert.AreEqual(expectedItemId, item.Member.ID, "item.Member.ID");
                    }

                    Assert.IsNotNull(item.Member2, "item.Member2");

                    Assert.AreEqual(1, item.Member2.Count, "item.Member2.Count");
                    Assert.AreEqual((alreadyResolved) ? expectedItemId : 20, item.Member2[0].ID, "item.Member2[0].ID");

                    Assert.IsTrue(resolveTypeInvoked == typeChange, "resolveTypeInvoked == typeChange");
                }

                AssertEntityCount(expectedEntities, "When already resolved (an item is duplicate) is " + alreadyResolved + ", expecting root + child(ren)");
                AssertLinkCount(2, "Root to each item, one through each property");

                context.ResolveType = null;
                this.ClearContext();
            });
        }
예제 #13
0
        [Ignore] // Remove Atom
        // [TestMethod]
        public void WebDataServiceCsdlMimeTypes()
        {
            object[] targets = new object[]
            {
                // BuiltInTypeKind.EdmFunction,
                // BuiltInTypeKind.ComplexType,
                // BuiltInTypeKind.EntityContainer,
                // BuiltInTypeKind.EntityType,
                BuiltInTypeKind.EdmProperty,
            };

            // Ensure the NorthwindModel service is ready to be used.
            Trace.WriteLine("NorthwindModel IsValid: " + ServiceModelData.Northwind.IsValid);

            CombinatorialEngine engine = CombinatorialEngine.FromDimensions(
                new Dimension("Target", targets),
                new Dimension("MimeType", new object[] { "", "text/html" }));
            int schemaCounter = 0;

            TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values)
            {
                BuiltInTypeKind target = (BuiltInTypeKind)values["Target"];
                string mimeType        = (string)values["MimeType"];

                // Create a copy of Northwind model files.
                schemaCounter++;
                const bool overwriteTrue = true;
                string sourceFileName    = Path.Combine(TestUtil.NorthwindMetadataDirectory, "Northwind.csdl");
                string destFileName      = sourceFileName + schemaCounter + ".csdl";
                File.Copy(sourceFileName, destFileName, overwriteTrue);
                File.SetAttributes(destFileName, FileAttributes.Normal);

                // Add an attribute at specific values.
                string csdlFileName  = destFileName;
                XmlDocument document = new XmlDocument();
                document.Load(csdlFileName);
                XmlElement element = GetElementForKind(document, target);
                element.SetAttribute("MimeType", "http://docs.oasis-open.org/odata/ns/metadata", mimeType);
                document.Save(csdlFileName);

                using (TestWebRequest request = TestWebRequest.CreateForInProcess())
                {
                    // Get the generated CSDL.
                    string connectionString = NorthwindModel.NorthwindContext.ContextConnectionString;
                    try
                    {
                        string northwindConnectionString = connectionString;
                        northwindConnectionString        = northwindConnectionString
                                                           .Replace("Northwind.csdl", "Northwind.csdl" + schemaCounter + ".csdl");
                        NorthwindModel.NorthwindContext.ContextConnectionString = northwindConnectionString;

                        request.DataServiceType  = typeof(NorthwindModel.NorthwindContext);
                        request.RequestUriString = "/$metadata";
                        Exception exception      = TestUtil.RunCatching(request.SendRequest);
                        TestUtil.AssertExceptionExpected(exception,
                                                         target != BuiltInTypeKind.EdmProperty,
                                                         mimeType == "");

                        if (exception != null)
                        {
                            return;
                        }

                        XmlDocument metadataResult = new XmlDocument(TestUtil.TestNameTable);
                        metadataResult.Load(request.GetResponseStream());
                        Trace.WriteLine(metadataResult.OuterXml);

                        // Get a value using a primitive serializer.
                        request.RequestUriString = "/Customers?$format=atom&$top=1";
                        request.SendRequest();
                        XmlDocument customerDocument = SerializationFormatData.Atom.LoadXmlDocumentFromStream(request.GetResponseStream());
                        XmlElement customerId        = TestUtil.AssertSelectSingleElement(customerDocument, "/atom:feed/atom:entry/atom:id");
                        request.FullRequestUriString = customerId.InnerText + "/CompanyName/$value";
                        request.SendRequest();
                        Assert.AreEqual(mimeType, TestUtil.GetMediaType(request.ResponseContentType));
                    }
                    finally
                    {
                        NorthwindModel.NorthwindContext.ContextConnectionString = connectionString;
                    }
                }
            });
        }