public void ValidateOpenComplexTypeSupported() { var ct = new StubEdmComplexType("NS1", "CT1") { IsOpen = true }; ct.Add(new EdmStructuralProperty(ct, "p1", EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Int16, true))); var model = new EdmModel(); model.AddElement(ct); IEnumerable<EdmError> errors; foreach (var v in new[] { Microsoft.OData.Edm.Library.EdmConstants.EdmVersionLatest }) { model.SetEdmVersion(v); model.Validate(out errors); Assert.AreEqual(0, errors.Count(), "No error should be returned"); } }
public void CsdlWriterShouldFailWithGoodMessageWhenWritingInvalidXml() { var model = new EdmModel(); model.SetEdmVersion(Microsoft.OData.Edm.Library.EdmConstants.EdmVersion4); var fredFlintstone = new EdmComplexType("Flintstones", "Fred"); fredFlintstone.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(false)); model.AddElement(fredFlintstone); // set annotation which will be serialzed (because the value is an IEdmValue) with a name that doesn't match the xml spec for NCName. model.SetAnnotationValue(fredFlintstone, "sap", "-contentversion", new EdmStringConstant(EdmCoreModel.Instance.GetString(false), "hello")); Assert.AreEqual(1, model.DirectValueAnnotations(fredFlintstone).Count(), "Wrong # of Annotations on {0}.", fredFlintstone); var stringWriter = new StringWriter(); var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings() { Indent = true }); try { IEnumerable<EdmError> errors; model.TryWriteCsdl(xmlWriter, out errors); Assert.Fail("Excepted an exception when trying to serialize a direct value annotation which does not match the xml naming spec."); } catch (ArgumentException e) { Assert.AreEqual(e.Message, "Invalid name character in '-contentversion'. The '-' character, hexadecimal value 0x2D, cannot be included in a name.", "Expected exception message did not match."); } xmlWriter.Close(); }
public void ComplexValueIgnorePropertyNullValuesTest() { var versions = new Version[] { null, new Version(4, 0), }; EdmModel edmModel = new EdmModel(); IEdmComplexType countryRegionType = edmModel.ComplexType("CountryRegion") .Property("Name", EdmPrimitiveTypeKind.String) .Property("CountryRegionCode", EdmPrimitiveTypeKind.String); IEdmComplexType countryRegionNullType = edmModel.ComplexType("CountryRegionNull") .Property("Name", EdmPrimitiveTypeKind.String) .Property("CountryRegionCode", EdmPrimitiveTypeKind.String); IEdmComplexType addressType = edmModel.ComplexType("Address") .Property("Street", EdmPrimitiveTypeKind.String) .Property("StreetNull", EdmCoreModel.Instance.GetString(true) as EdmTypeReference) .Property("Numbers", EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false)) as EdmTypeReference) .Property("CountryRegion", new EdmComplexTypeReference(countryRegionType, false)) .Property("CountryRegionNull", new EdmComplexTypeReference(countryRegionNullType, true)); edmModel.EntityType("Customer") .KeyProperty("ID", EdmCoreModel.Instance.GetInt32(false) as EdmTypeReference) .Property("Address", new EdmComplexTypeReference(addressType, false)); edmModel.Fixup(); this.CombinatorialEngineProvider.RunCombinations( new ODataNullValueBehaviorKind[] { ODataNullValueBehaviorKind.Default, ODataNullValueBehaviorKind.DisableValidation, ODataNullValueBehaviorKind.IgnoreValue }, versions, versions, TestReaderUtils.ODataBehaviorKinds, (nullPropertyValueReaderBehavior, dataServiceVersion, edmVersion, behaviorKind) => { edmModel.SetEdmVersion(edmVersion); // Now we set the 'IgnoreNullValues' annotation on all properties IEdmComplexType edmAddressType = (IEdmComplexType)edmModel.FindType("TestModel.Address"); foreach (IEdmStructuralProperty edmProperty in edmAddressType.StructuralProperties()) { edmModel.SetNullValueReaderBehavior(edmProperty, nullPropertyValueReaderBehavior); } EntityInstance customerPayload = PayloadBuilder.Entity("TestModel.Customer") .PrimitiveProperty("ID", 1) .Property("Address", PayloadBuilder.ComplexValue("TestModel.Address") .PrimitiveProperty("Street", "One Microsoft Way") .PrimitiveProperty("StreetNull", "One Microsoft Way") .Property("Numbers", PayloadBuilder.PrimitiveMultiValue("Collection(Edm.Int32)").Item(1).Item(2)) .Property("CountryRegion", PayloadBuilder.ComplexValue("TestModel.CountryRegion") .PrimitiveProperty("Name", "Austria") .PrimitiveProperty("CountryRegionCode", "AUT")) .Property("CountryRegionNull", PayloadBuilder.ComplexValue("TestModel.CountryRegionNull") .PrimitiveProperty("Name", "Austria") .PrimitiveProperty("CountryRegionCode", "AUT"))); var testCases = new[] { // Complex types that are not nullable should not allow null values. // Null primitive property in the payload and non-nullable property in the model new IgnoreNullValueTestCase { PropertyName = "Street", ExpectedResponseException = ODataExpectedExceptions.ODataException("ReaderValidationUtils_NullNamedValueForNonNullableType", "Street", "Edm.String"), }, // Null complex property in the payload and non-nullable property in the model new IgnoreNullValueTestCase { PropertyName = "CountryRegion", ExpectedResponseException = ODataExpectedExceptions.ODataException("ReaderValidationUtils_NullNamedValueForNonNullableType", "CountryRegion", "TestModel.CountryRegion"), }, // Null collection property in the payload and non-nullable property in the model new IgnoreNullValueTestCase { PropertyName = "Numbers", ExpectedResponseException = ODataExpectedExceptions.ODataException("ReaderValidationUtils_NullNamedValueForNonNullableType", "Numbers", "Collection(Edm.Int32)"), }, // Complex types that are nullable should allow null values. // Null primitive property in the payload and nullable property in the model new IgnoreNullValueTestCase { PropertyName = "StreetNull", }, // Null complex property in the payload and nullable property in the model new IgnoreNullValueTestCase { PropertyName = "CountryRegionNull", }, }; Func<IgnoreNullValueTestCase, ReaderTestConfiguration, PayloadReaderTestDescriptor> createTestDescriptor = (testCase, testConfig) => { EntityInstance payloadValue = customerPayload.DeepCopy(); ComplexInstance payloadAddressValue = ((ComplexProperty)payloadValue.GetProperty("Address")).Value; SetToNull(payloadAddressValue, testCase.PropertyName); ComplexInstance resultValue = payloadValue; if (testConfig.IsRequest && nullPropertyValueReaderBehavior == ODataNullValueBehaviorKind.IgnoreValue) { resultValue = customerPayload.DeepCopy(); ComplexInstance resultAddressValue = ((ComplexProperty)resultValue.GetProperty("Address")).Value; resultAddressValue.Remove(resultAddressValue.GetProperty(testCase.PropertyName)); } return new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = payloadValue, PayloadEdmModel = edmModel, ExpectedResultPayloadElement = tc => { if (tc.Format == ODataFormat.Json) { // under the client knob ODL will compute edit links, ids, etc // so we need to update the expected payload if (tc.RunBehaviorKind == TestODataBehaviorKind.WcfDataServicesClient) { var entity = resultValue as EntityInstance; if (entity != null) { if (!tc.IsRequest) { entity.Id = "http://odata.org/test/Customer(1)"; entity.EditLink = "http://odata.org/test/Customer(1)"; entity.WithSelfLink("http://odata.org/test/Customer(1)"); } } } var tempDescriptor = new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = resultValue, PayloadEdmModel = edmModel, }; JsonLightPayloadElementFixup.Fixup(tempDescriptor); return tempDescriptor.PayloadElement; } return resultValue; }, ExpectedException = (testConfig.IsRequest && nullPropertyValueReaderBehavior != ODataNullValueBehaviorKind.Default) ? null : testCase.ExpectedResponseException }; }; this.CombinatorialEngineProvider.RunCombinations( testCases, this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations, (testCase, testConfiguration) => { testConfiguration = testConfiguration.CloneAndApplyBehavior(behaviorKind); testConfiguration.MessageReaderSettings.BaseUri = null; PayloadReaderTestDescriptor testDescriptor = createTestDescriptor(testCase, testConfiguration); testDescriptor.RunTest(testConfiguration); }); }); }
public void AnnotationNameWhichIsNotSimpleIdentifierShouldPassValidation() { var model = new EdmModel(); model.SetEdmVersion(Microsoft.OData.Edm.Library.EdmConstants.EdmVersion4); var fredFlintstone = new EdmComplexType("Flintstones", "Fred"); fredFlintstone.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(false)); model.AddElement(fredFlintstone); // set the annotation name to a value which is valid XML, but not a valid SimpleIdentifier. model.SetAnnotationValue(fredFlintstone, "sap", "content-version", new EdmStringConstant(EdmCoreModel.Instance.GetString(false), "hello")); Assert.AreEqual(1, model.DirectValueAnnotations(fredFlintstone).Count(), "Wrong # of Annotations on {0}.", fredFlintstone); IEnumerable<EdmError> errors; model.Validate(out errors); Assert.AreEqual(0, errors.Count(), "Model expected to be valid."); }
public void NullPropertyTypeNameTest() { Version[] versions = new Version[] { null, new Version(4, 0), }; var innerComplexType = new EdmComplexType("TestNS", "ComplexType"); innerComplexType.AddStructuralProperty("NumberProperty", EdmCoreModel.Instance.GetInt32(true)); innerComplexType.AddStructuralProperty("StringProperty", EdmCoreModel.Instance.GetString(true)); var outerComplexType = new EdmComplexType("TestNS", "ComplexType"); outerComplexType.AddStructuralProperty("NumberProperty", EdmCoreModel.Instance.GetInt32(true)); outerComplexType.AddStructuralProperty("StringProperty", EdmCoreModel.Instance.GetString(true)); outerComplexType.AddStructuralProperty("InnerComplex", new EdmComplexTypeReference(innerComplexType, true)); var model = new EdmModel(); var complexType = new EdmComplexType("TestNS", "ComplexType"); complexType.AddStructuralProperty("NumberProperty", EdmCoreModel.Instance.GetInt32(true)); complexType.AddStructuralProperty("StringProperty", EdmCoreModel.Instance.GetString(true)); complexType.AddStructuralProperty("InnerComplex", new EdmComplexTypeReference(innerComplexType, true)); model.AddElement(complexType); var entityType = new EdmEntityType("TestNS", "EntityType", null, false, true); entityType.AddStructuralProperty("NumberProperty", EdmCoreModel.Instance.GetInt32(true)); entityType.AddStructuralProperty("StringProperty", EdmCoreModel.Instance.GetString(true)); entityType.AddStructuralProperty("ComplexProperty", new EdmComplexTypeReference(outerComplexType, true)); model.AddElement(entityType); var container = new EdmEntityContainer("TestNS", "DefaultContainer"); model.AddElement(container); var testDescriptorSet = versions.SelectMany(dataServiceVersion => versions.SelectMany(edmVersion => { model.SetEdmVersion(edmVersion); // Client only writes type for primitive properties with null value, Server writes it for both primitive and complex. // Edm.String is never written as the default is Edm.String. var testCases = new[] { new { PropertyName = "NumberProperty", ExpectedServerTypeName = "Edm.Int32", ExpectedClientTypeName = "Edm.Int32" }, new { PropertyName = "StringProperty", ExpectedServerTypeName = (string)null, ExpectedClientTypeName = (string)null }, new { PropertyName = "ComplexProperty", ExpectedServerTypeName = "TestNS.ComplexType", ExpectedClientTypeName = (string)null }, new { PropertyName = "OpenProperty", ExpectedServerTypeName = (string)null, ExpectedClientTypeName = (string)null }, new { PropertyName = "OpenProperty", ExpectedServerTypeName = (string)null, ExpectedClientTypeName = (string)null }, new { PropertyName = "ComplexProperty/NumberProperty", ExpectedServerTypeName = "Edm.Int32", ExpectedClientTypeName = "Edm.Int32" }, new { PropertyName = "ComplexProperty/StringProperty", ExpectedServerTypeName = (string)null, ExpectedClientTypeName = (string)null }, new { PropertyName = "ComplexProperty/InnerComplex", ExpectedServerTypeName = "TestNS.ComplexType", ExpectedClientTypeName = (string)null }, new { PropertyName = "ComplexProperty/InnerComplex/NumberProperty", ExpectedServerTypeName = "Edm.Int32", ExpectedClientTypeName = "Edm.Int32" }, new { PropertyName = "ComplexProperty/InnerComplex/StringProperty", ExpectedServerTypeName = (string)null, ExpectedClientTypeName = (string)null }, }; return testCases.Select(testCase => { string[] propertyPath = testCase.PropertyName.Split('/'); ODataProperty property = new ODataProperty { Name = propertyPath[propertyPath.Length - 1], Value = null }; for (int i = propertyPath.Length - 2; i >= 0; i--) { property = new ODataProperty { Name = propertyPath[i], Value = new ODataComplexValue { Properties = new[] { property } } }; } Func<XElement, XElement> extractor = (result) => { result = TestAtomUtils.ExtractPropertiesFromEntry(result); foreach (string name in propertyPath) { result = result.Element(TestAtomConstants.ODataXNamespace + name); } return result; }; return new Func<TestODataBehaviorKind, ODataVersion, PayloadWriterTestDescriptor<ODataItem>>( (behaviorKind, version) => { string expectedTypeName = null; switch (behaviorKind) { case TestODataBehaviorKind.Default: break; case TestODataBehaviorKind.WcfDataServicesClient: expectedTypeName = testCase.ExpectedClientTypeName; break; case TestODataBehaviorKind.WcfDataServicesServer: expectedTypeName = testCase.ExpectedServerTypeName; break; } // Starting with V3, we only support the standard behavior expectedTypeName = null; return new PayloadWriterTestDescriptor<ODataItem>( this.Settings, new ODataEntry() { TypeName = "TestNS.EntityType", Properties = new[] { property }, SerializationInfo = new ODataFeedAndEntrySerializationInfo() { NavigationSourceEntityTypeName = "TestNS.EntityType", NavigationSourceName = "MySet", ExpectedTypeName = "TestNS.EntityType" } }, (tc) => new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Xml = expectedTypeName == null ? "<type/>" : "<type>" + expectedTypeName + "</type>", FragmentExtractor = (result) => new XElement("type", (string)extractor(result).Attribute(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.AtomTypeAttributeName)) } ) { Model = model }; }); }); })); this.CombinatorialEngineProvider.RunCombinations( TestWriterUtils.ODataBehaviorKinds, testDescriptorSet, this.WriterTestConfigurationProvider.AtomFormatConfigurationsWithIndent, (behaviorKind, testDescriptor, testConfiguration) => { testConfiguration = testConfiguration.CloneAndApplyBehavior(behaviorKind); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor(behaviorKind, testConfiguration.Version), testConfiguration, this.Assert, this.Logger); }); }