/// <summary> /// Converts a <see cref="PayloadReaderTestDescriptor"/> to an in-stream error <see cref="PayloadReaderTestDescriptor"/>. /// </summary> /// <param name="descriptor">The <see cref="PayloadReaderTestDescriptor"/> to convert.</param> /// <param name="format">The <see cref="ODataFormat"/> the test descriptor is created for.</param> /// <returns>An in-stream error <see cref="PayloadReaderTestDescriptor"/> based on the <paramref name="descriptor"/>.</returns> /// <remarks>The <paramref name="descriptor"/> is expected to represent a top-level error payload test descriptor.</remarks> internal static PayloadReaderTestDescriptor ToInStreamErrorTestDescriptor(this PayloadReaderTestDescriptor descriptor, ODataFormat format) { ExceptionUtilities.CheckArgumentNotNull(descriptor, "descriptor"); ExceptionUtilities.CheckArgumentNotNull(format, "format"); ExceptionUtilities.Assert(descriptor.PayloadElement.ElementType == ODataPayloadElementType.ODataErrorPayload, "Only error payloads expected."); ExceptionUtilities.Assert(descriptor.ExpectedResultCallback == null, "No expected results callback expected."); ExceptionUtilities.Assert(descriptor.PayloadEdmModel == null, "No model expected."); // Model that defines the CityType to be used for wrapping the error payload to convert it into an in-stream error. IEdmModel testModel = Test.OData.Utils.Metadata.TestModels.BuildTestModel(); bool isValidTopLevelError = descriptor.ExpectedException == null; ODataPayloadElement wrappedPayloadElement = null; ExpectedException expectedException = null; if (format == ODataFormat.Atom) { var atomRepresentation = (XmlPayloadElementRepresentationAnnotation)descriptor.PayloadElement.GetAnnotation(typeof(XmlPayloadElementRepresentationAnnotation)); ExceptionUtilities.Assert(atomRepresentation != null, "Expected a format-specific annotation."); XNode xmlRepresentation = atomRepresentation.XmlNodes.Single(); XElement wrapperObject = new XElement(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomEntryElementName, new XElement(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomCategoryElementName, new XAttribute(TestAtomConstants.AtomCategoryTermAttributeName, "TestModel.CityType"), new XAttribute(TestAtomConstants.AtomCategorySchemeAttributeName, TestAtomConstants.ODataSchemeNamespace), new XElement(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomContentElementName, new XAttribute(TestAtomConstants.AtomTypeAttributeName, "application/xml"), new XElement(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.AtomPropertiesElementName, new XElement(TestAtomConstants.ODataXNamespace + "PoliceStation", xmlRepresentation))))); // replace the payload and ATOM representation of the test descriptor and set the expected error message wrappedPayloadElement = PayloadBuilder.Entity("TestModel.CityType").XmlRepresentation(wrapperObject); if (isValidTopLevelError) { // if we have a valid top-level error we expect an ODataErrorException to be thrown. ODataError error = ConvertErrorPayload((ODataErrorPayload)descriptor.PayloadElement, /*forAtom*/true); expectedException = ODataExpectedExceptions.ODataErrorException(error, "ODataErrorException_GeneralError"); } else { expectedException = descriptor.ExpectedException; } } else if (format == ODataFormat.Json) { IEdmEntitySet citiesSet = testModel.EntityContainer.FindEntitySet("Cities"); IEdmEntityType cityType = testModel.FindType("TestModel.CityType") as IEdmEntityType; var jsonRepresentation = (JsonPayloadElementRepresentationAnnotation)descriptor.PayloadElement.GetAnnotation(typeof(JsonPayloadElementRepresentationAnnotation)); ExceptionUtilities.Assert(jsonRepresentation != null, "Expected a format-specific annotation."); JsonObject jsonObject = (JsonObject)jsonRepresentation.Json; // wrap the existing payload in an entity of type 'CityType'; the existing payload is used as value of the 'PoliceStation' property JsonObject wrapperObject = (JsonObject)JsonTextPreservingParser.ParseValue(new StringReader("{ \"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#TestModel.DefaultContainer.Cities/$entity\" }")); wrapperObject.Add(new JsonProperty("PoliceStation", jsonObject)); // replace the payload and Json representation of the test descriptor and set the expected error message wrappedPayloadElement = PayloadBuilder.Entity("TestModel.CityType") .ExpectedEntityType(cityType, citiesSet) .JsonRepresentation(wrapperObject); if (isValidTopLevelError) { // if we have a valid top-level error we expect an ODataErrorException to be thrown. ODataError error = ConvertErrorPayload((ODataErrorPayload)descriptor.PayloadElement, /*forAtom*/false); expectedException = ODataExpectedExceptions.ODataErrorException(error, "ODataErrorException_GeneralError"); } else { // if the top-level error is too deeply recursive, we expect to fail in the same way for the in-stream error. if (descriptor.ExpectedException.ExpectedMessage.ResourceIdentifier == "ValidationUtils_RecursionDepthLimitReached") { expectedException = descriptor.ExpectedException; } else { // otherwise, if the top-level error is not valid, we expect an error message that the first // property of the invalid top-level error object is not defined on type OfficeType. string firstPropertyName = jsonObject.Properties.First().Name; expectedException = ODataExpectedExceptions.ODataException("ValidationUtils_PropertyDoesNotExistOnType", firstPropertyName, "TestModel.OfficeType"); } } } else { throw new TaupoInvalidOperationException("Unsupported format for error test descriptor found: " + format.GetType().Name); } return new PayloadReaderTestDescriptor(descriptor) { PayloadElement = wrappedPayloadElement, PayloadEdmModel = testModel, ExpectedResultPayloadElement = tc => descriptor.PayloadElement, ExpectedException = expectedException, }; }