Skip to content

Commit 3761527

Browse files
[Improve] code coverage: SpecHierarchy
1 parent e5e6d84 commit 3761527

File tree

2 files changed

+182
-32
lines changed

2 files changed

+182
-32
lines changed

ReqIFSharp.Tests/SpecElementWithAttributesTests/SpecHierarchyTestFixture.cs

Lines changed: 152 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,19 @@
2020

2121
namespace ReqIFSharp.Tests.SpecElementWithAttributesTests
2222
{
23+
using System;
2324
using System.IO;
2425
using System.Runtime.Serialization;
2526
using System.Threading;
2627
using System.Threading.Tasks;
2728
using System.Xml;
2829

30+
using Microsoft.Extensions.Logging;
31+
2932
using NUnit.Framework;
3033

34+
using Serilog;
35+
3136
/// <summary>
3237
/// Suite of tests for the <see cref="SpecHierarchy"/> class
3338
/// </summary>
@@ -36,12 +41,35 @@ public class SpecHierarchyTestFixture
3641
{
3742
private XmlWriterSettings settings;
3843

44+
private ILoggerFactory loggerFactory;
45+
46+
[OneTimeSetUp]
47+
public void OneTimeSetUp()
48+
{
49+
Log.Logger = new LoggerConfiguration()
50+
.MinimumLevel.Verbose()
51+
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext} - {Message:lj}{NewLine}{Exception}")
52+
.CreateLogger();
53+
54+
this.loggerFactory = LoggerFactory.Create(builder =>
55+
{
56+
builder.AddSerilog();
57+
});
58+
}
59+
3960
[SetUp]
4061
public void SetUp()
4162
{
4263
this.settings = new XmlWriterSettings();
4364
}
4465

66+
[Test]
67+
public void Verify_that_constructor_does_not_throw_exception()
68+
{
69+
Assert.That(() => new SpecHierarchy(null), Throws.Nothing);
70+
Assert.That(() => new SpecHierarchy(this.loggerFactory), Throws.Nothing);
71+
}
72+
4573
[Test]
4674
public void Verify_that_When_Object_is_null_WriteXml_throws_exception()
4775
{
@@ -82,6 +110,52 @@ public void Verify_that_When_Object_is_null_WriteXmlAsync_throws_exception()
82110
.With.Message.Contains("The Object property of SpecHierarchy identifier:longname may not be null"));
83111
}
84112

113+
[Test]
114+
public void SpecHierarchy_ReadXml_InitialisesContainerAndChildren()
115+
{
116+
var content = new ReqIFContent();
117+
var rootSpecification = new Specification(content, null) { Identifier = "root" };
118+
var existingObject = new SpecObject(content, null) { Identifier = "existing-object" };
119+
120+
var specHierarchy = new SpecHierarchy(rootSpecification, content, null)
121+
{
122+
Identifier = "hierarchy"
123+
};
124+
125+
var xml = """
126+
<SPEC-HIERARCHY IDENTIFIER="hierarchy" IS-TABLE-INTERNAL="true">
127+
<ALTERNATIVE-ID>
128+
<ALTERNATIVE-ID IDENTIFIER="an-alternative-id"/>
129+
</ALTERNATIVE-ID>
130+
<OBJECT>
131+
<SPEC-OBJECT-REF>missing-object</SPEC-OBJECT-REF>
132+
</OBJECT>
133+
<CHILDREN>
134+
<SPEC-HIERARCHY IDENTIFIER="child">
135+
<OBJECT>
136+
<SPEC-OBJECT-REF>existing-object</SPEC-OBJECT-REF>
137+
</OBJECT>
138+
</SPEC-HIERARCHY>
139+
</CHILDREN>
140+
</SPEC-HIERARCHY>
141+
""";
142+
143+
using var reader = XmlReader.Create(new StringReader(xml), new XmlReaderSettings { Async = true });
144+
reader.MoveToContent();
145+
146+
specHierarchy.ReadXml(reader);
147+
148+
using (Assert.EnterMultipleScope())
149+
{
150+
Assert.That(specHierarchy.IsTableInternal, Is.True);
151+
Assert.That(specHierarchy.Object, Is.Null, "Missing objects should yield null reference");
152+
Assert.That(specHierarchy.Children, Has.Count.EqualTo(1));
153+
Assert.That(specHierarchy.Children[0].Object, Is.SameAs(existingObject));
154+
Assert.That(specHierarchy.Children[0].Container, Is.SameAs(specHierarchy));
155+
Assert.That(specHierarchy.AlternativeId.Identifier, Is.EqualTo("an-alternative-id"));
156+
}
157+
}
158+
85159
[Test]
86160
public async Task SpecHierarchy_ReadXmlAsync_InitialisesContainerAndChildren()
87161
{
@@ -96,6 +170,9 @@ public async Task SpecHierarchy_ReadXmlAsync_InitialisesContainerAndChildren()
96170

97171
var xml = """
98172
<SPEC-HIERARCHY IDENTIFIER="hierarchy" IS-TABLE-INTERNAL="true">
173+
<ALTERNATIVE-ID>
174+
<ALTERNATIVE-ID IDENTIFIER="an-alternative-id"/>
175+
</ALTERNATIVE-ID>
99176
<OBJECT>
100177
<SPEC-OBJECT-REF>missing-object</SPEC-OBJECT-REF>
101178
</OBJECT>
@@ -114,14 +191,87 @@ public async Task SpecHierarchy_ReadXmlAsync_InitialisesContainerAndChildren()
114191

115192
await specHierarchy.ReadXmlAsync(reader, CancellationToken.None);
116193

117-
Assert.Multiple(() =>
194+
using (Assert.EnterMultipleScope())
118195
{
119196
Assert.That(specHierarchy.IsTableInternal, Is.True);
120197
Assert.That(specHierarchy.Object, Is.Null, "Missing objects should yield null reference");
121198
Assert.That(specHierarchy.Children, Has.Count.EqualTo(1));
122199
Assert.That(specHierarchy.Children[0].Object, Is.SameAs(existingObject));
123200
Assert.That(specHierarchy.Children[0].Container, Is.SameAs(specHierarchy));
124-
});
201+
Assert.That(specHierarchy.AlternativeId.Identifier, Is.EqualTo("an-alternative-id"));
202+
}
203+
}
204+
205+
[Test]
206+
public async Task SpecHierarchy_ReadXmlAsync_cancel()
207+
{
208+
var content = new ReqIFContent();
209+
var rootSpecification = new Specification(content, null) { Identifier = "root" };
210+
211+
var specHierarchy = new SpecHierarchy(rootSpecification, content, null)
212+
{
213+
Identifier = "hierarchy"
214+
};
215+
216+
var xml = """
217+
<SPEC-HIERARCHY IDENTIFIER="hierarchy" IS-TABLE-INTERNAL="true">
218+
<OBJECT>
219+
<SPEC-OBJECT-REF>missing-object</SPEC-OBJECT-REF>
220+
</OBJECT>
221+
<CHILDREN>
222+
<SPEC-HIERARCHY IDENTIFIER="child">
223+
<OBJECT>
224+
<SPEC-OBJECT-REF>existing-object</SPEC-OBJECT-REF>
225+
</OBJECT>
226+
</SPEC-HIERARCHY>
227+
</CHILDREN>
228+
</SPEC-HIERARCHY>
229+
""";
230+
231+
using var reader = XmlReader.Create(new StringReader(xml), new XmlReaderSettings { Async = true });
232+
await reader.MoveToContentAsync();
233+
234+
var cts = new CancellationTokenSource();
235+
236+
await cts.CancelAsync();
237+
238+
await Assert.ThatAsync(() => specHierarchy.ReadXmlAsync(reader, cts.Token), Throws.InstanceOf<OperationCanceledException>());
239+
}
240+
241+
[Test]
242+
public void SpecHierarchy_ReadXml_VEry_that_when_attribute_is_incorrect_type_exception_is_thrown()
243+
{
244+
var content = new ReqIFContent();
245+
var rootSpecification = new Specification(content, null) { Identifier = "root" };
246+
var existingObject = new SpecObject(content, null) { Identifier = "existing-object" };
247+
248+
var specHierarchy = new SpecHierarchy(rootSpecification, content, null)
249+
{
250+
Identifier = "hierarchy"
251+
};
252+
253+
var xml = """
254+
<SPEC-HIERARCHY IDENTIFIER="hierarchy" IS-TABLE-INTERNAL="INCORRECT-DATA-TYPE">
255+
<ALTERNATIVE-ID>
256+
<ALTERNATIVE-ID IDENTIFIER="an-alternative-id"/>
257+
</ALTERNATIVE-ID>
258+
<OBJECT>
259+
<SPEC-OBJECT-REF>missing-object</SPEC-OBJECT-REF>
260+
</OBJECT>
261+
<CHILDREN>
262+
<SPEC-HIERARCHY IDENTIFIER="child">
263+
<OBJECT>
264+
<SPEC-OBJECT-REF>existing-object</SPEC-OBJECT-REF>
265+
</OBJECT>
266+
</SPEC-HIERARCHY>
267+
</CHILDREN>
268+
</SPEC-HIERARCHY>
269+
""";
270+
271+
using var reader = XmlReader.Create(new StringReader(xml), new XmlReaderSettings { Async = true });
272+
reader.MoveToContent();
273+
274+
Assert.That(() => specHierarchy.ReadXml(reader), Throws.InstanceOf<SerializationException>());
125275
}
126276
}
127277
}

ReqIFSharp/SpecElementWithAttributes/SpecHierarchy.cs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020

2121
namespace ReqIFSharp
2222
{
23-
using Microsoft.Extensions.Logging;
24-
using Microsoft.Extensions.Logging.Abstractions;
2523
using System;
2624
using System.Collections.Generic;
2725
using System.Linq;
@@ -30,6 +28,9 @@ namespace ReqIFSharp
3028
using System.Threading.Tasks;
3129
using System.Xml;
3230

31+
using Microsoft.Extensions.Logging;
32+
using Microsoft.Extensions.Logging.Abstractions;
33+
3334
/// <summary>
3435
/// The <see cref="SpecHierarchy"/> class represents a node in a hierarchically structured requirements specification.
3536
/// </summary>
@@ -174,37 +175,36 @@ internal override void ReadXml(XmlReader reader)
174175

175176
this.ReadXmlAttributes(reader);
176177

177-
using (var specHierarchySubtree = reader.ReadSubtree())
178+
using var specHierarchySubtree = reader.ReadSubtree();
179+
180+
while (specHierarchySubtree.Read())
178181
{
179-
while (specHierarchySubtree.Read())
182+
if (specHierarchySubtree.MoveToContent() == XmlNodeType.Element)
180183
{
181-
if (specHierarchySubtree.MoveToContent() == XmlNodeType.Element)
184+
var xmlLineInfo = reader as IXmlLineInfo;
185+
186+
switch (specHierarchySubtree.LocalName)
182187
{
183-
var xmlLineInfo = reader as IXmlLineInfo;
184-
185-
switch (specHierarchySubtree.LocalName)
186-
{
187-
case "ALTERNATIVE-ID":
188-
this.ReadAlternativeId(specHierarchySubtree);
189-
break;
190-
case "OBJECT":
191-
using (var subtree = specHierarchySubtree.ReadSubtree())
192-
{
193-
subtree.MoveToContent();
194-
this.DeserializeObject(subtree);
195-
}
196-
break;
197-
case "CHILDREN":
198-
using (var subtree = specHierarchySubtree.ReadSubtree())
199-
{
200-
subtree.MoveToContent();
201-
this.DeserializeSpecHierarchy(subtree);
202-
}
203-
break;
204-
default:
205-
this.logger.LogWarning("The {LocalName} element at line:position {LineNumber}:{LinePosition} is not supported", specHierarchySubtree.LocalName, xmlLineInfo?.LineNumber, xmlLineInfo?.LinePosition);
206-
break;
207-
}
188+
case "ALTERNATIVE-ID":
189+
this.ReadAlternativeId(specHierarchySubtree);
190+
break;
191+
case "OBJECT":
192+
using (var subtree = specHierarchySubtree.ReadSubtree())
193+
{
194+
subtree.MoveToContent();
195+
this.DeserializeObject(subtree);
196+
}
197+
break;
198+
case "CHILDREN":
199+
using (var subtree = specHierarchySubtree.ReadSubtree())
200+
{
201+
subtree.MoveToContent();
202+
this.DeserializeSpecHierarchy(subtree);
203+
}
204+
break;
205+
default:
206+
this.logger.LogWarning("The {LocalName} element at line:position {LineNumber}:{LinePosition} is not supported", specHierarchySubtree.LocalName, xmlLineInfo?.LineNumber, xmlLineInfo?.LinePosition);
207+
break;
208208
}
209209
}
210210
}

0 commit comments

Comments
 (0)