public void ContentTypeHeaderAppJsonVersioningTest()
        {
            IEdmModel model = Microsoft.Test.OData.Utils.Metadata.TestModels.BuildTestModel();

            this.CombinatorialEngineProvider.RunCombinations(
                new[] { ApplicationJson, ApplicationJsonODataLight },
                new[] { ODataPayloadKind.Entry, ODataPayloadKind.Feed },
                this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations,
                (contentType, payloadKind, testConfiguration) =>
            {
                ODataVersion version = testConfiguration.Version;

                if (IgnoreTestConfiguration(contentType, testConfiguration))
                {
                    return;
                }

                if (IgnoreTestCase(payloadKind, testConfiguration))
                {
                    return;
                }

                ExpectedException expectedException = null;

                ODataPayloadElement payloadElement             = CreatePayloadElement(model, payloadKind, testConfiguration);
                ReaderContentTypeTestDescriptor testDescriptor = new ReaderContentTypeTestDescriptor(this.Settings)
                {
                    PayloadElement    = payloadElement,
                    PayloadEdmModel   = model,
                    ExpectedFormat    = ComputeExpectedFormat(testConfiguration, contentType),
                    ContentType       = contentType,
                    ExpectedException = expectedException,
                };

                testDescriptor.RunTest(testConfiguration);
            });
        }
        public void ContentTypeHeaderParsingTest()
        {
            IEnumerable <ContentTypeTestCase> testCases = new ContentTypeTestCase[]
            {
                #region Atom test cases
                new ContentTypeTestCase
                {
                    // only reading an entry or feed should succeed
                    ContentType    = "application/atom+xml;type=feed",
                    ExpectedFormat = ODataFormat.Atom,
                },
                new ContentTypeTestCase
                {
                    // only reading an entry or feed should succeed
                    ContentType    = "application/atom+xml;type=entry",
                    ExpectedFormat = ODataFormat.Atom,
                },
                new ContentTypeTestCase
                {
                    // reading a feed, an entry, and metadata should succeed
                    ContentType    = "application/atom+xml",
                    ExpectedFormat = ODataFormat.Atom,
                },
                new ContentTypeTestCase
                {
                    // reading a property, an entity reference link, entity reference links, a collection, a service document, and an error should succeed
                    ContentType    = "application/xml",
                    ExpectedFormat = ODataFormat.Atom,
                },
                new ContentTypeTestCase
                {
                    // reading a property, an entity reference link, entity reference links, and a collection should succeed
                    ContentType    = "text/xml",
                    ExpectedFormat = ODataFormat.Atom,
                },
                new ContentTypeTestCase
                {
                    // reading a service document should succeed
                    ContentType    = "application/atomsvc+xml",
                    ExpectedFormat = ODataFormat.Atom,
                },
                #endregion Atom test cases

                #region RawValue test cases
                new ContentTypeTestCase
                {
                    // only reading a raw value will succeed
                    ContentType    = "text/plain",
                    ExpectedFormat = ODataFormat.RawValue,
                    ShouldSucceedForPayloadKind = pk =>
                                                  pk == ODataPayloadKind.Value ||
                                                  pk == ODataPayloadKind.BinaryValue,
                },
                new ContentTypeTestCase
                {
                    // only reading a raw value or binary value will succeed; raw values can be read as binary values when the content type is application/octet-stream
                    ContentType    = "application/octet-stream",
                    ExpectedFormat = ODataFormat.RawValue,
                    ShouldSucceedForPayloadKind = pk =>
                                                  pk == ODataPayloadKind.Value ||
                                                  pk == ODataPayloadKind.BinaryValue,
                },
                new ContentTypeTestCase
                {
                    // only raw value / binary value will succeed
                    ContentType    = "multipart/mixed",
                    ExpectedFormat = ODataFormat.RawValue,
                    ShouldSucceedForPayloadKind = pk => false,
                },
                new ContentTypeTestCase
                {
                    // Test for: MimeType allows 0x7F character, but ContentType parsing doesn't
                    ContentType    = "application/" + 0x7F,
                    ExpectedFormat = ODataFormat.RawValue,
                    ShouldSucceedForPayloadKind = pk => false,
                },

                #endregion RawValue test cases

                #region JSON Lite test cases
                new ContentTypeTestCase
                {
                    // only batch and raw value will fail (batch payload kind tested separately in BatchContentTypeHeaderParsingTest)
                    ContentType    = ApplicationJsonODataLight,
                    ExpectedFormat = ODataFormat.Json,
                    ShouldSucceedForPayloadKind = pk =>
                                                  pk != ODataPayloadKind.Value &&
                                                  pk != ODataPayloadKind.BinaryValue,
                },
                new ContentTypeTestCase
                {
                    // only batch and raw value will fail (batch payload kind tested separately in BatchContentTypeHeaderParsingTest)
                    ContentType    = ApplicationJsonODataLightStreaming,
                    ExpectedFormat = ODataFormat.Json,
                    ShouldSucceedForPayloadKind = pk =>
                                                  pk != ODataPayloadKind.Value &&
                                                  pk != ODataPayloadKind.BinaryValue,
                },
                new ContentTypeTestCase
                {
                    // only batch and raw value will fail (batch payload kind tested separately in BatchContentTypeHeaderParsingTest)
                    ContentType    = ApplicationJsonODataLightNonStreaming,
                    ExpectedFormat = ODataFormat.Json,
                    ShouldSucceedForPayloadKind = pk =>
                                                  pk != ODataPayloadKind.Value &&
                                                  pk != ODataPayloadKind.BinaryValue,
                },
                #endregion JSON Lite test cases

                #region Error test cases
                new ContentTypeTestCase
                {
                    // unsupported content type; everything will fail
                    ContentType = "application/foo",
                    ShouldSucceedForPayloadKind = pk => false,
                },
                new ContentTypeTestCase
                {
                    // unsupported content type with parameters; everything will fail
                    ContentType = "abc/pqr;a=b;c=d",
                    ShouldSucceedForPayloadKind = pk => false,
                },
                new ContentTypeTestCase
                {
                    // "image/jpeg" is not supported, even for raw values.
                    ContentType = "image/jpeg",
                    ShouldSucceedForPayloadKind = pk => false,
                },
                #endregion Error test cases

                #region Content Type is null or empty
                new ContentTypeTestCase
                {
                    // null content type and zero content length should be default to Json if the payload kind is not binary value or value.
                    ContentType    = null,
                    ContentLength  = 0,
                    ExpectedFormat = ODataFormat.Json,
                    ShouldSucceedForPayloadKind = pk => true,
                    ShouldIgnoreTest            = pk => pk == ODataPayloadKind.BinaryValue || pk == ODataPayloadKind.Value
                },
                new ContentTypeTestCase
                {
                    // null content type and zero content length should be default to RawValue if the payload kind is binary value or value.
                    ContentType    = null,
                    ContentLength  = 0,
                    ExpectedFormat = ODataFormat.RawValue,
                    ShouldSucceedForPayloadKind = pk => true,
                    ShouldIgnoreTest            = pk => pk != ODataPayloadKind.Value
                },
                #endregion
            };

            string[] parameters = new string[]
            {
                "foo=bar",
                "foo1=bar1;foo2=bar2"
            };

            testCases = testCases.Concat(testCases.Where(tc => tc.ContentType != null).SelectMany(tc => parameters.Select(p => new ContentTypeTestCase(tc)
            {
                ContentType = tc.ContentType + ";" + p
            })));

            int oDataPayloadKindCount = EnumExtensionMethods.GetValues <ODataPayloadKind>().Length;

            this.Assert.AreEqual(oDataPayloadKindCount, TestReaderUtils.ODataPayloadKinds.Length, "The number of payload kind have changed, please update this test.");

            IEdmModel model = Microsoft.Test.OData.Utils.Metadata.TestModels.BuildTestModel();

            // We don't support batch payloads here; we test those separately in BatchContentTypeHeaderParsingTest
            IEnumerable <ODataPayloadKind> payloadKinds =
                TestReaderUtils.ODataPayloadKinds.Where(k => k != ODataPayloadKind.Batch && k != ODataPayloadKind.Unsupported);

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                payloadKinds,
                this.ReaderTestConfigurationProvider.AllFormatConfigurations,
                (testCase, payloadKind, testConfiguration) =>
            {
                testConfiguration = new ReaderTestConfiguration(testConfiguration);
                testConfiguration.MessageReaderSettings.EnableAtom = false;
                if (IgnoreTestCase(payloadKind, testConfiguration))
                {
                    return;
                }

                if (testCase.ShouldIgnoreTest != null && testCase.ShouldIgnoreTest(payloadKind))
                {
                    return;
                }

                string supportedMediaTypes;

                if (payloadKind == ODataPayloadKind.Value || payloadKind == ODataPayloadKind.BinaryValue)
                {
                    supportedMediaTypes = TestMediaTypeUtils.GetSupportedMediaTypes(ODataPayloadKind.Value) + ", " + TestMediaTypeUtils.GetSupportedMediaTypes(ODataPayloadKind.BinaryValue);
                }
                else
                {
                    supportedMediaTypes = TestMediaTypeUtils.GetSupportedMediaTypes(payloadKind, /*includeAppJson*/ true);
                }

                ExpectedException expectedException = testCase.ExpectedException == null
                         ? testCase.ShouldSucceedForPayloadKind != null && testCase.ShouldSucceedForPayloadKind(payloadKind)
                             ? null
                             : ODataExpectedExceptions.ODataContentTypeException("MediaTypeUtils_CannotDetermineFormatFromContentType", supportedMediaTypes, testCase.ContentType ?? "")
                         : testCase.ExpectedException;

                // Make sure to run success test cases only in configurations that will work.
                if (expectedException == null &&
                    testConfiguration.Format != null &&
                    testCase.ExpectedFormat != testConfiguration.Format)
                {
                    return;
                }

                ODataPayloadElement payloadElement = CreatePayloadElement(model, payloadKind, testConfiguration);

                // When we write a value with a content type different than 'text/plain', we will read it as binary.
                // Likewise, when we write a binary value with a 'text/plain' content type, we will read it as a string.
                Func <ReaderTestConfiguration, ODataPayloadElement> expectedResultElementFunc = null;
                if (payloadKind == ODataPayloadKind.Value && testCase.ContentType != null && !testCase.ContentType.StartsWith("text/plain"))
                {
                    expectedResultElementFunc = (testConfig) => ConvertToBinaryPayloadElement(payloadElement);
                }
                else if (payloadKind == ODataPayloadKind.BinaryValue && testCase.ContentType != null && testCase.ContentType.StartsWith("text/plain"))
                {
                    expectedResultElementFunc = (testConfig) => ConvertToStringPayloadElement(payloadElement);
                }

                ODataFormat expectedFormat = testCase.ExpectedFormat;

                ReaderContentTypeTestDescriptor testDescriptor = new ReaderContentTypeTestDescriptor(this.Settings)
                {
                    PayloadElement = payloadElement,
                    ExpectedResultPayloadElement = expectedResultElementFunc,
                    PayloadEdmModel   = model,
                    ExpectedFormat    = expectedFormat,
                    ContentType       = testCase.ContentType,
                    ExpectedException = expectedException
                };

                testDescriptor.RunTest(testConfiguration);
                testConfiguration.MessageReaderSettings.EnableAtom = true;
            });
        }
        public void ContentTypeHeaderParsingWithClientBehaviorTest()
        {
            // In V1 and V2 clients, application/xml and application/atom+xml are valid for all of the following payload kinds.
            Func <ODataPayloadKind, bool> isXmlPayloadKind =
                pk =>
                pk == ODataPayloadKind.Feed ||
                pk == ODataPayloadKind.Entry ||
                pk == ODataPayloadKind.MetadataDocument ||
                pk == ODataPayloadKind.Property ||
                pk == ODataPayloadKind.EntityReferenceLink ||
                pk == ODataPayloadKind.Collection ||
                pk == ODataPayloadKind.ServiceDocument ||
                pk == ODataPayloadKind.Error;

            // In V3 (whether under client knob or not), we should be spec
            // compliant and only allow application/atom+xml for feeds and
            // entries and application/xml for all other xml payload kinds.
            // When running the test cases, we replace ShouldSucceedForPayloadKind
            // with isXmlPayloadKind when dealing with pre-V3 clients.
            var testCases = new[]
            {
                new ContentTypeTestCase
                {
                    ContentType    = "application/atom+xml",
                    ExpectedFormat = ODataFormat.Atom,
                },
                new ContentTypeTestCase
                {
                    ContentType    = "application/xml",
                    ExpectedFormat = ODataFormat.Atom,
                },
            };

            IEdmModel model = Microsoft.Test.OData.Utils.Metadata.TestModels.BuildTestModel();

            IEnumerable <ODataPayloadKind> payloadKinds =
                TestReaderUtils.ODataPayloadKinds.Where(k => k != ODataPayloadKind.Batch && k != ODataPayloadKind.Unsupported);

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                payloadKinds,
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations,
                (testCase, payloadKind, testConfiguration) =>
            {
                // Run under the client knob.
                testConfiguration = testConfiguration.CloneAndApplyBehavior(TestODataBehaviorKind.WcfDataServicesClient);
                testConfiguration.MessageReaderSettings.EnableAtom = false;

                if (IgnoreTestCase(payloadKind, testConfiguration))
                {
                    return;
                }

                // If version is V1 or V2, we should succeed for all xml payload kinds if the mime type is application/atom+xml or application/xml.
                Func <ODataPayloadKind, bool> shouldSucceedForPayloadKind = testCase.ShouldSucceedForPayloadKind;

                // Get supported media types to use in expected error message.
                string supportedMediaTypes;

                if (payloadKind == ODataPayloadKind.Value || payloadKind == ODataPayloadKind.BinaryValue)
                {
                    supportedMediaTypes = TestMediaTypeUtils.GetSupportedMediaTypes(ODataPayloadKind.Value) + ", " + TestMediaTypeUtils.GetSupportedMediaTypes(ODataPayloadKind.BinaryValue);
                }
                else
                {
                    supportedMediaTypes = TestMediaTypeUtils.GetSupportedMediaTypes(payloadKind);
                }

                ExpectedException expectedException = testCase.ExpectedException == null
                        ? shouldSucceedForPayloadKind != null && shouldSucceedForPayloadKind(payloadKind)
                            ? null
                            : ODataExpectedExceptions.ODataContentTypeException("MediaTypeUtils_CannotDetermineFormatFromContentType", supportedMediaTypes, testCase.ContentType)
                        : testCase.ExpectedException;

                ODataPayloadElement payloadElement = CreatePayloadElement(model, payloadKind, testConfiguration);
                ODataFormat expectedFormat         = testCase.ExpectedFormat;

                ReaderContentTypeTestDescriptor testDescriptor = new ReaderContentTypeTestDescriptor(this.Settings)
                {
                    PayloadElement    = payloadElement,
                    PayloadEdmModel   = model,
                    ExpectedFormat    = expectedFormat,
                    ContentType       = testCase.ContentType,
                    ExpectedException = expectedException
                };

                testDescriptor.RunTest(testConfiguration);
            });
        }