Esempio n. 1
0
        public void GetValue_Returns_SetValue()
        {
            // Arrange
            ETag etag = new ETag();

            // Act & Assert
            etag["Name"] = "Name1";
            Assert.Equal("Name1", etag["Name"]);
        }
Esempio n. 2
0
        public void DynamicGetValue_Returns_DynamicSetValue()
        {
            // Arrange
            dynamic etag = new ETag();

            // Act & Assert
            etag.Name = "Name1";
            Assert.Equal("Name1", etag.Name);
        }
Esempio n. 3
0
        public void GetValue_ThrowsInvalidOperation_IfNotWellFormed()
        {
            // Arrange
            ETag etag = new ETag();
            etag["Name"] = "Name1";
            etag.IsWellFormed = false;

            // Act && Assert
            Assert.Throws<InvalidOperationException>(() => etag["Name"], "The ETag is not well-formed.");
        }
Esempio n. 4
0
        public void ApplyToNonGenericThrows_IfPassedAnIQueryableOfTheWrongType()
        {
            // Arrange
            ETag <Customer> etagCustomer = new ETag <Customer> {
                IsIfNoneMatch = true
            };
            IQueryable query = Enumerable.Empty <int>().AsQueryable();

            // Act & Assert
            Assert.Throws <ArgumentException>(
                () => etagCustomer.ApplyTo(query),
                "Cannot apply ETag of 'System.Web.OData.Formatter.Serialization.Models.Customer' to IQueryable of " +
                "'System.Int32'.\r\nParameter name: query");
        }
Esempio n. 5
0
        public void ApplyTo_SameQueryReturned_GivenQueryableAndETagAny()
        {
            // Arrange
            var any = new ETag {
                IsAny = true
            };
            var customers = _customers.AsQueryable();

            // Act
            var queryable = any.ApplyTo(customers);

            // Assert
            Assert.NotNull(queryable);
            Assert.Same(queryable, customers);
        }
        public void ApplyTo_NewQueryReturned_GivenQueryable()
        {
            // Arrange
            ETag<Customer> etagCustomer = new ETag<Customer>();
            dynamic etag = etagCustomer;
            etag.FirstName = "Foo";

            // Act
            IQueryable queryable = etagCustomer.ApplyTo(_customers.AsQueryable());

            // Assert
            Assert.NotNull(queryable);
            IEnumerable<Customer> actualCustomers = Assert.IsAssignableFrom<IEnumerable<Customer>>(queryable);
            Assert.Equal(
                new[] { 1 },
                actualCustomers.Select(customer => customer.ID));
        }
        public void ApplyTo_NewQueryReturned_GivenQueryable()
        {
            // Arrange
            ETag<Customer> etagCustomer = new ETag<Customer>();
            dynamic etag = etagCustomer;
            etag.FirstName = "Foo";

            // Act
            IQueryable queryable = etagCustomer.ApplyTo(_customers.AsQueryable());

            // Assert
            Assert.NotNull(queryable);
            IEnumerable<Customer> actualCustomers = Assert.IsAssignableFrom<IEnumerable<Customer>>(queryable);
            Assert.Equal(
                new[] { 1 },
                actualCustomers.Select(customer => customer.ID));
            MethodCallExpression methodCall = queryable.Expression as MethodCallExpression;
            Assert.NotNull(methodCall);
            Assert.Equal(2, methodCall.Arguments.Count);
            Assert.Equal(@"Param_0 => (Param_0.FirstName == value(System.Web.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty)",
                methodCall.Arguments[1].ToString());
        }
Esempio n. 8
0
        public void ApplyTo_SameQueryReturned_GivenQueryableAndETagAny()
        {
            // Arrange
            var any = new ETag { IsAny = true };
            var customers = _customers.AsQueryable();

            // Act
            var queryable = any.ApplyTo(customers);

            // Assert
            Assert.NotNull(queryable);
            Assert.Same(queryable, customers);
        }
Esempio n. 9
0
        public void ApplyTo_NewQueryReturned_IsIfNoneMatchWithMultipleConcurrencyProperties()
        {
            // Arrange
            ETag etagCustomer = new ETag { EntityType = typeof(Customer), IsIfNoneMatch = true };
            dynamic etag = etagCustomer;
            etag.FirstName = "Def";
            etag.LastName = "Xyz";

            // Act
            IQueryable queryable = etagCustomer.ApplyTo(_customers.AsQueryable());

            // Assert
            Assert.NotNull(queryable);
            IEnumerable<Customer> actualCustomers = Assert.IsAssignableFrom<IEnumerable<Customer>>(queryable);
            Assert.Equal(
                new[] { 1, 2 },
                actualCustomers.Select(customer => customer.ID));
            MethodCallExpression methodCall = queryable.Expression as MethodCallExpression;
            Assert.NotNull(methodCall);
            Assert.Equal(2, methodCall.Arguments.Count);
            Assert.Equal(
                @"Param_0 => Not(((Param_0.FirstName == value(System.Web.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty) "
                + "AndAlso (Param_0.LastName == value(System.Web.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty)))",
                methodCall.Arguments[1].ToString());
        }
        public void ApplyToNonGenericThrows_IfPassedAnIQueryableOfTheWrongType()
        {
            // Arrange
            ETag<Customer> etagCustomer = new ETag<Customer> { IsIfNoneMatch = true };
            IQueryable query = Enumerable.Empty<int>().AsQueryable();

            // Act & Assert
            Assert.Throws<ArgumentException>(
                () => etagCustomer.ApplyTo(query),
                "Cannot apply ETag of 'System.Web.OData.Formatter.Serialization.Models.Customer' to IQueryable of " +
                "'System.Int32'.\r\nParameter name: query");
        }
Esempio n. 11
0
        public void ApplyTo_NewQueryReturned_ForInteger(sbyte byteVal, short shortVal, bool ifMatch, IList <int> expect)
        {
            // Arrange
            var mycustomers = new List <MyETagOrder>
            {
                new MyETagOrder
                {
                    ID       = 1,
                    ByteVal  = 7,
                    ShortVal = 8
                },
                new MyETagOrder
                {
                    ID       = 2,
                    ByteVal  = SByte.MaxValue,
                    ShortVal = Int16.MaxValue
                },
                new MyETagOrder
                {
                    ID       = 3,
                    ByteVal  = SByte.MinValue,
                    ShortVal = Int16.MinValue
                },
            };
            IETagHandler handerl = new DefaultODataETagHandler();
            Dictionary <string, object> properties = new Dictionary <string, object>
            {
                { "ByteVal", byteVal },
                { "ShortVal", shortVal }
            };
            EntityTagHeaderValue etagHeaderValue = handerl.CreateETag(properties);

            HttpRequestMessage request      = new HttpRequestMessage();
            HttpConfiguration  cofiguration = new HttpConfiguration();

            request.SetConfiguration(cofiguration);

            var builder = new ODataConventionModelBuilder();

            builder.EntitySet <MyETagOrder>("Orders");
            IEdmModel               model       = builder.GetEdmModel();
            IEdmEntityType          order       = model.SchemaElements.OfType <IEdmEntityType>().FirstOrDefault(e => e.Name == "MyETagOrder");
            IEdmEntitySet           orders      = model.FindDeclaredEntitySet("Orders");
            Mock <ODataPathSegment> mockSegment = new Mock <ODataPathSegment> {
                CallBase = true
            };

            mockSegment.Setup(s => s.GetEdmType(null)).Returns(order);
            mockSegment.Setup(s => s.GetNavigationSource(null)).Returns(orders);
            ODataPath odataPath = new ODataPath(new[] { mockSegment.Object });

            request.ODataProperties().Path  = odataPath;
            request.ODataProperties().Model = model;

            ETag etagCustomer = request.GetETag(etagHeaderValue);

            etagCustomer.EntityType    = typeof(MyETagOrder);
            etagCustomer.IsIfNoneMatch = !ifMatch;

            // Act
            IQueryable queryable = etagCustomer.ApplyTo(mycustomers.AsQueryable());

            // Assert
            Assert.NotNull(queryable);
            IEnumerable <MyETagOrder> actualOrders = Assert.IsAssignableFrom <IEnumerable <MyETagOrder> >(queryable);

            Assert.Equal(expect, actualOrders.Select(c => c.ID));
            MethodCallExpression methodCall = queryable.Expression as MethodCallExpression;

            Assert.NotNull(methodCall);
            Assert.Equal(2, methodCall.Arguments.Count);

            if (ifMatch)
            {
                Assert.Equal(
                    "Param_0 => ((Param_0.ByteVal == value(System.Web.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.SByte]).TypedProperty) " +
                    "AndAlso (Param_0.ShortVal == value(System.Web.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.Int16]).TypedProperty))",
                    methodCall.Arguments[1].ToString());
            }
            else
            {
                Assert.Equal(
                    "Param_0 => Not(((Param_0.ByteVal == value(System.Web.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.SByte]).TypedProperty) " +
                    "AndAlso (Param_0.ShortVal == value(System.Web.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.Int16]).TypedProperty)))",
                    methodCall.Arguments[1].ToString());
            }
        }
Esempio n. 12
0
        private IQueryable ApplyQueryOptions(
            IQueryable queryable, ODataPath path, bool applyCount, out bool isIfNoneMatch, out ETag etag)
        {
            // ETAG IsIfNoneMatch is changed to public access, this flag can be removed.
            isIfNoneMatch = false;
            etag = null;

            if (this.shouldWriteRawValue)
            {
                // Query options don't apply to $value.
                return queryable;
            }

            HttpRequestMessageProperties properties = this.Request.ODataProperties();
            var model = Api.GetModelAsync().Result;
            ODataQueryContext queryContext =
                new ODataQueryContext(model, queryable.ElementType, path);
            ODataQueryOptions queryOptions = new ODataQueryOptions(queryContext, this.Request);

            // Get etag for query request
            if (queryOptions.IfMatch != null)
            {
                etag = queryOptions.IfMatch;
            }
            else if (queryOptions.IfNoneMatch != null)
            {
                isIfNoneMatch = true;
                etag = queryOptions.IfNoneMatch;
            }

            // TODO GitHubIssue#41 : Ensure stable ordering for query
            ODataQuerySettings settings = Api.Context.GetApiService<ODataQuerySettings>();

            if (this.shouldReturnCount)
            {
                // Query options other than $filter and $search don't apply to $count.
                queryable = queryOptions.ApplyTo(
                    queryable, settings, AllowedQueryOptions.All ^ AllowedQueryOptions.Filter);
                return queryable;
            }

            if (queryOptions.Count != null && !applyCount)
            {
                RestierQueryExecutorOptions queryExecutorOptions =
                    Api.Context.GetApiService<RestierQueryExecutorOptions>();
                queryExecutorOptions.IncludeTotalCount = queryOptions.Count.Value;
                queryExecutorOptions.SetTotalCount = value => properties.TotalCount = value;
            }

            // Validate query before apply, and query setting like MaxExpansionDepth can be customized here
            ODataValidationSettings validationSettings = Api.Context.GetApiService<ODataValidationSettings>();
            queryOptions.Validate(validationSettings);

            // Entity count can NOT be evaluated at this point of time because the source
            // expression is just a placeholder to be replaced by the expression sourcer.
            if (!applyCount)
            {
                queryable = queryOptions.ApplyTo(queryable, settings, AllowedQueryOptions.Count);
            }
            else
            {
                queryable = queryOptions.ApplyTo(queryable, settings);
            }

            return queryable;
        }
Esempio n. 13
0
        private HttpResponseMessage CreateQueryResponse(
            IQueryable query, IEdmType edmType, bool isIfNoneMatch, ETag etag)
        {
            IEdmTypeReference typeReference = GetTypeReference(edmType);
            BaseSingleResult singleResult = null;
            HttpResponseMessage response = null;

            if (typeReference.IsPrimitive())
            {
                if (this.shouldReturnCount || this.shouldWriteRawValue)
                {
                    var rawResult = new RawResult(query, typeReference, this.Api.Context);
                    singleResult = rawResult;
                    response = this.Request.CreateResponse(HttpStatusCode.OK, rawResult);
                }
                else
                {
                    var primitiveResult = new PrimitiveResult(query, typeReference, this.Api.Context);
                    singleResult = primitiveResult;
                    response = this.Request.CreateResponse(HttpStatusCode.OK, primitiveResult);
                }
            }

            if (typeReference.IsComplex())
            {
                var complexResult = new ComplexResult(query, typeReference, this.Api.Context);
                singleResult = complexResult;
                response = this.Request.CreateResponse(HttpStatusCode.OK, complexResult);
            }

            if (typeReference.IsEnum())
            {
                if (this.shouldWriteRawValue)
                {
                    var rawResult = new RawResult(query, typeReference, this.Api.Context);
                    singleResult = rawResult;
                    response = this.Request.CreateResponse(HttpStatusCode.OK, rawResult);
                }
                else
                {
                    var enumResult = new EnumResult(query, typeReference, this.Api.Context);
                    singleResult = enumResult;
                    response = this.Request.CreateResponse(HttpStatusCode.OK, enumResult);
                }
            }

            if (singleResult != null)
            {
                if (singleResult.Result == null)
                {
                    // Per specification, If the property is single-valued and has the null value,
                    // the service responds with 204 No Content.
                    return this.Request.CreateResponse(HttpStatusCode.NoContent);
                }

                return response;
            }

            if (typeReference.IsCollection())
            {
                var elementType = typeReference.AsCollection().ElementType();
                if (elementType.IsPrimitive() || elementType.IsEnum())
                {
                    return this.Request.CreateResponse(
                        HttpStatusCode.OK, new NonResourceCollectionResult(query, typeReference, this.Api.Context));
                }

                return this.Request.CreateResponse(
                    HttpStatusCode.OK, new ResourceSetResult(query, typeReference, this.Api.Context));
            }

            var entityResult = query.SingleOrDefault();
            if (entityResult == null)
            {
                return this.Request.CreateResponse(HttpStatusCode.NoContent);
            }

            // Check the ETag here
            if (etag != null)
            {
                // request with If-Match header, if match, then should return whole content
                // request with If-Match header, if not match, then should return 412
                // request with If-None-Match header, if match, then should return 304
                // request with If-None-Match header, if not match, then should return whole content
                etag.EntityType = query.ElementType;
                query = etag.ApplyTo(query);
                entityResult = query.SingleOrDefault();
                if (entityResult == null && !isIfNoneMatch)
                {
                    return this.Request.CreateResponse(HttpStatusCode.PreconditionFailed);
                }
                else if (entityResult == null)
                {
                    return this.Request.CreateResponse(HttpStatusCode.NotModified);
                }
            }

            // Using reflection to create response for single entity so passed in parameter is not object type,
            // but will be type of real entity type, then EtagMessageHandler can be used to set ETAG header
            // when response is single entity.
            // There are three HttpRequestMessageExtensions class defined in different assembles
            var genericMethod = typeof(System.Net.Http.HttpRequestMessageExtensions).GetMethods()
                .Where(m => m.Name == "CreateResponse" && m.GetParameters().Length == 3);
            var method = genericMethod.FirstOrDefault().MakeGenericMethod(query.ElementType);
            response = method.Invoke(null, new object[] { this.Request, HttpStatusCode.OK, entityResult })
                as HttpResponseMessage;
            return response;
        }
Esempio n. 14
0
        public void ApplyTo_NewQueryReturned_ForDouble(double value, bool ifMatch, IList <int> expect)
        {
            // Arrange
            var myCustomers = new List <MyETagCustomer>
            {
                new MyETagCustomer
                {
                    ID         = 1,
                    DoubleETag = 1.0,
                },
                new MyETagCustomer
                {
                    ID         = 2,
                    DoubleETag = 1.1,
                },
                new MyETagCustomer
                {
                    ID         = 3,
                    DoubleETag = 1.0,
                },
            };

            IETagHandler handerl = new DefaultODataETagHandler();
            Dictionary <string, object> properties = new Dictionary <string, object> {
                { "DoubleETag", value }
            };
            EntityTagHeaderValue etagHeaderValue = handerl.CreateETag(properties);

            HttpRequestMessage request = new HttpRequestMessage();

            var builder = new ODataConventionModelBuilder();

            builder.EntitySet <MyETagCustomer>("Customers");
            IEdmModel      model     = builder.GetEdmModel();
            IEdmEntityType customer  = model.SchemaElements.OfType <IEdmEntityType>().FirstOrDefault(e => e.Name == "MyEtagCustomer");
            IEdmEntitySet  customers = model.FindDeclaredEntitySet("Customers");
            ODataPath      odataPath = new ODataPath(new[] { new EntitySetSegment(customers) });

            request.EnableHttpDependencyInjectionSupport(model);
            request.ODataProperties().Path = odataPath;

            ETag etagCustomer = request.GetETag(etagHeaderValue);

            etagCustomer.EntityType    = typeof(MyETagCustomer);
            etagCustomer.IsIfNoneMatch = !ifMatch;

            // Act
            IQueryable queryable = etagCustomer.ApplyTo(myCustomers.AsQueryable());

            // Assert
            Assert.NotNull(queryable);
            IList <MyETagCustomer> actualCustomers = Assert.IsAssignableFrom <IEnumerable <MyETagCustomer> >(queryable).ToList();

            if (expect != null)
            {
                Assert.Equal(expect, actualCustomers.Select(c => c.ID));
            }

            MethodCallExpression methodCall = queryable.Expression as MethodCallExpression;

            Assert.NotNull(methodCall);
            Assert.Equal(2, methodCall.Arguments.Count);
            if (ifMatch)
            {
                Assert.Equal(
                    "Param_0 => (Param_0.DoubleETag == value(System.Web.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.Double]).TypedProperty)",
                    methodCall.Arguments[1].ToString());
            }
            else
            {
                Assert.Equal(
                    "Param_0 => Not((Param_0.DoubleETag == value(System.Web.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.Double]).TypedProperty))",
                    methodCall.Arguments[1].ToString());
            }
        }