Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ The repository ships two NuGet packages that version independently: **ReqIFSharp

- A `REQ-IF` root element in a namespace other than the ReqIF namespace (`http://www.omg.org/spec/ReqIF/20110401/reqif.xsd`) is no longer read as a ReqIF document; it is skipped and a warning is logged. Before, such an element was read when it had no prefix. A root in no namespace is still read ([#87](https://github.com/STARIONGROUP/ReqIFSharp/issues/87)).
- An element other than `SPEC-RELATION-REF` inside the `SPEC-RELATIONS` of a relation group is now skipped with a warning, and the references after it are read. Before, it caused an `XmlException` ([#94](https://github.com/STARIONGROUP/ReqIFSharp/issues/94)).
- An element that has the name of a ReqIF element but is in another namespace (for example `<other:THE-VALUE xmlns:other="...">`) is no longer read as that ReqIF element. It is skipped, with its content, and a warning is logged. Elements in the ReqIF namespace or in no namespace are read as before, in any document ([#97](https://github.com/STARIONGROUP/ReqIFSharp/issues/97)).

### Fixed

- A document that binds the ReqIF namespace to a prefix (`<reqif:REQ-IF xmlns:reqif="...">`) was read as zero documents, and type, source/target and relation-group references in it were not read. Elements are now matched on their local name and namespace ([#87](https://github.com/STARIONGROUP/ReqIFSharp/issues/87)).
- A document without whitespace between its elements (minified XML) lost data without an error: every other header field (such as `CREATION-TIME` and `REQ-IF-TOOL-ID`) and every other enumeration value of an attribute value was skipped, and the spec relations of a relation group were not read or caused an `XmlException` ([#94](https://github.com/STARIONGROUP/ReqIFSharp/issues/94)).
- `AttributeValueXHTML.TheOriginalValue` was not read from `THE-ORIGINAL-VALUE`, so it was always `null` after reading, and a document that was read and written again lost the original values of its simplified XHTML attribute values ([#95](https://github.com/STARIONGROUP/ReqIFSharp/issues/95)).
- Attribute values did not log anything, also when an `ILoggerFactory` was passed to the deserializer: the `AttributeValue` constructors did not keep the logger factory. An enumeration attribute value no longer reports its own element and its `DEFINITION` and `VALUES` elements as not supported ([#97](https://github.com/STARIONGROUP/ReqIFSharp/issues/97)).

## [10.1.2] - 2026-10-18

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ namespace ReqIFSharp.Tests
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;

using Microsoft.Extensions.Logging;
Expand All @@ -34,6 +36,7 @@ namespace ReqIFSharp.Tests
using ReqIFSharp;

using Serilog;
using Serilog.Events;

/// <summary>
/// Suite of tests for the <see cref="AttributeValueEnumeration"/>
Expand Down Expand Up @@ -171,5 +174,68 @@ public void Verify_that_when_ObjectValue_is_not_real_an_exception_is_thrown()
Throws.Exception.TypeOf<InvalidOperationException>()
.With.Message.Contains("The value to set is not an IEnumerable<EnumValue>."));
}

[TestCase(false)]
[TestCase(true)]
public async Task Verify_that_an_unknown_ReqIF_element_in_an_enumeration_value_is_reported_as_not_supported(bool async)
{
const string xml = "<ATTRIBUTE-VALUE-ENUMERATION xmlns=\"http://www.omg.org/spec/ReqIF/20110401/reqif.xsd\"><DEFINITION/><VALUES><UNKNOWN/></VALUES></ATTRIBUTE-VALUE-ENUMERATION>";

var sink = new TestLogEventSink();
var serilogLogger = new LoggerConfiguration().MinimumLevel.Verbose().WriteTo.Sink(sink).CreateLogger();

using var testLoggerFactory = LoggerFactory.Create(builder => builder.AddSerilog(serilogLogger, dispose: true));
using var reader = XmlReader.Create(new StringReader(xml), new XmlReaderSettings { Async = async });
reader.MoveToContent();

var attributeValueEnumeration = new AttributeValueEnumeration(testLoggerFactory);

if (async)
{
await attributeValueEnumeration.ReadXmlAsync(reader, CancellationToken.None);
}
else
{
attributeValueEnumeration.ReadXml(reader);
}

var warnings = sink.Events.Where(e => e.Level == LogEventLevel.Warning).Select(e => e.RenderMessage()).ToList();

// also the positive control of Verify_that_reading_enumeration_values_logs_no_warnings, which filters on the same SourceContext
var fromEnumeration = sink.Events.Where(e => e.Level == LogEventLevel.Warning && e.Properties.TryGetValue("SourceContext", out var source) && source.ToString().Contains(nameof(AttributeValueEnumeration))).ToList();

Assert.That(warnings, Has.Count.EqualTo(1));
Assert.That(warnings[0], Does.Contain("UNKNOWN").And.Contain("is not supported"));
Assert.That(fromEnumeration, Has.Count.EqualTo(1));
}

[TestCase("Datatype-Demo.reqif", false)]
[TestCase("Datatype-Demo.reqif", true)]
[TestCase("reqifsharpgenerated.reqif", false)]
[TestCase("reqifsharpgenerated.reqif", true)]
public async Task Verify_that_reading_enumeration_values_logs_no_warnings(string fileName, bool async)
{
var sink = new TestLogEventSink();
var serilogLogger = new LoggerConfiguration().MinimumLevel.Verbose().WriteTo.Sink(sink).CreateLogger();

using var testLoggerFactory = LoggerFactory.Create(builder => builder.AddSerilog(serilogLogger, dispose: true));
using var stream = File.OpenRead(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData", fileName));

var deserializer = new ReqIFDeserializer(testLoggerFactory);

var reqifs = async
? (await deserializer.DeserializeAsync(stream, SupportedFileExtensionKind.Reqif, CancellationToken.None)).ToList()
: deserializer.Deserialize(stream, SupportedFileExtensionKind.Reqif).ToList();

var enumerationValues = reqifs.SelectMany(x => x.CoreContent.SpecObjects).SelectMany(x => x.Values).OfType<AttributeValueEnumeration>().ToList();

var warnings = sink.Events
.Where(e => e.Level == LogEventLevel.Warning && e.Properties.TryGetValue("SourceContext", out var source) && source.ToString().Contains(nameof(AttributeValueEnumeration)))
.Select(e => e.RenderMessage())
.ToList();

Assert.That(enumerationValues, Is.Not.Empty, "the document must contain enumeration values");
Assert.That(warnings, Is.Empty);
}
}
}
Loading
Loading