Skip to content

Commit

Permalink
Fix long-running test failures detected by pipeline.
Browse files Browse the repository at this point in the history
  • Loading branch information
ewoutkramer committed Mar 8, 2025
1 parent c25f3eb commit 46999fa
Show file tree
Hide file tree
Showing 3 changed files with 359 additions and 366 deletions.
258 changes: 131 additions & 127 deletions src/Hl7.Fhir.STU3.Tests/Model/ValidateAllExamplesSearchExtractionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,180 +19,184 @@
using Hl7.Fhir.Utility;
using Hl7.Fhir.ElementModel;

namespace Hl7.Fhir.Tests.Model
namespace Hl7.Fhir.Tests.Model;

[TestClass]
public class ValidateSearchExtractionAllExamplesTest
{
[TestClass]
public class ValidateSearchExtractionAllExamplesTest
{
public ILookup<ResourceType, SearchParamDefinition> SpList;
public ILookup<ResourceType, SearchParamDefinition> SpList;

[TestMethod]
[TestCategory("LongRunner")]
public void SearchExtractionAllExamples()
{
SpList = ModelInfo.SearchParameters
.Where(spd => !String.IsNullOrEmpty(spd.Expression))
.Select(spd =>
new { Rt = (ResourceType)Enum.Parse(typeof(ResourceType), spd.Resource), Def = spd })
.ToLookup(ks => ks.Rt, es => es.Def);

[TestMethod]
[TestCategory("LongRunner")]
public void SearchExtractionAllExamples()
{
SpList = ModelInfo.SearchParameters
.Where(spd => !String.IsNullOrEmpty(spd.Expression))
.Select(spd =>
new { Rt = (ResourceType)Enum.Parse(typeof(ResourceType), spd.Resource), Def = spd })
.ToLookup(ks => ks.Rt, es => es.Def);

SearchExtractionAllExamplesInternal();
// SearchExtractionAllExamplesInternal();
}
searchExtractionAllExamplesInternal();
}


private void SearchExtractionAllExamplesInternal()
private void searchExtractionAllExamplesInternal()
{
var parser = FhirXmlParser.RECOVERABLE;
int errorCount = 0;
int parserErrorCount = 0;
int testFileCount = 0;
var exampleSearchValues = new Dictionary<SearchParamDefinition, Holder>();
var zip = TestDataHelper.ReadTestZip("examples.zip");

using (zip)
{
var parser = new FhirXmlParser(new ParserSettings().UsingMode(DeserializationMode.Recoverable));
int errorCount = 0;
int parserErrorCount = 0;
int testFileCount = 0;
var exampleSearchValues = new Dictionary<SearchParamDefinition, Holder>();
var zip = TestDataHelper.ReadTestZip("examples.zip");

using (zip)
foreach (var entry in zip.Entries)
{
foreach (var entry in zip.Entries)
Stream file = entry.Open();
using (file)
{
Stream file = entry.Open();
using (file)
{
// Verified examples that fail validations
// Verified examples that fail validations

//// vsd-3, vsd-8
//if (file.EndsWith("valueset-ucum-common(ucum-common).xml"))
// continue;
//// vsd-3, vsd-8
//if (file.EndsWith("valueset-ucum-common(ucum-common).xml"))
// continue;

testFileCount++;
try
{
// Debug.WriteLine(String.Format("Validating {0}", file));
var reader = SerializationUtil.WrapXmlReader(XmlReader.Create(file));
var resource = parser.Parse<Resource>(reader);
testFileCount++;
try
{
// Debug.WriteLine(String.Format("Validating {0}", file));
var reader = SerializationUtil.WrapXmlReader(XmlReader.Create(file));
var resource = parser.Parse<Resource>(reader);

ExtractValuesForSearchParameterFromFile(exampleSearchValues, resource);
extractValuesForSearchParameterFromFile(exampleSearchValues, resource);

if (resource is Bundle)
if (resource is Bundle bundle)
{
foreach (var item in bundle.Entry)
{
foreach (var item in (resource as Bundle).Entry)
if (item.Resource != null)
{
if (item.Resource != null)
{
ExtractValuesForSearchParameterFromFile(exampleSearchValues, item.Resource);
}
extractValuesForSearchParameterFromFile(exampleSearchValues, item.Resource);
}
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine("Error processing file " + entry.Name + ": " + ex.Message);
parserErrorCount++;
}

}
catch (Exception ex)
{
Trace.WriteLine("Error processing file " + entry.Name + ": " + ex.Message);
parserErrorCount++;
}

}
}
}

var missingSearchValues = exampleSearchValues.Where(i => i.Value.count == 0);
var missingSearchValues = exampleSearchValues.Where(i => i.Value.Count == 0).ToArray();

if (missingSearchValues.Count() > 0)
if (missingSearchValues.Any())
{
Debug.WriteLine(
$"\r\n------------------\r\n" +
$"Validation failed, missing data in {missingSearchValues.Length} of " +
$"{exampleSearchValues.Count} search parameters");

foreach (var item in missingSearchValues)
{
Debug.WriteLine(String.Format("\r\n------------------\r\nValidation failed, missing data in {0} of {1} search parameters", missingSearchValues.Count(), exampleSearchValues.Count));
foreach (var item in missingSearchValues)
{
Trace.WriteLine("\t" + item.Key.Resource.ToString() + "_" + item.Key.Name);
}
// Trace.WriteLine(outcome.ToString());
errorCount++;
Trace.WriteLine("\t" + item.Key.Resource + "_" + item.Key.Name);
}

Assert.IsTrue(43 >= errorCount, String.Format("Failed search parameter data extraction, missing data in {0} of {1} search parameters", missingSearchValues.Count(), exampleSearchValues.Count));
Assert.AreEqual(0, parserErrorCount, String.Format("Failed search parameter data extraction, {0} files failed parsing", parserErrorCount));
// Trace.WriteLine(outcome.ToString());
errorCount++;
}

private void ExtractValuesForSearchParameterFromFile(Dictionary<SearchParamDefinition, Holder> exampleSearchValues, Resource resource)
Assert.IsTrue(43 >= errorCount,
$"Failed search parameter data extraction, missing data in {missingSearchValues.Length} of " +
$"{exampleSearchValues.Count} search parameters");
Assert.AreEqual(0, parserErrorCount,
$"Failed search parameter data extraction, {parserErrorCount} files failed parsing");
}

private void extractValuesForSearchParameterFromFile(Dictionary<SearchParamDefinition, Holder> exampleSearchValues, Resource resource)
{
// Extract the search properties
resource.TryDeriveResourceType(out var rt);
var searchparameters = SpList[rt];
foreach (var index in searchparameters)
{
// Extract the search properties
resource.TryDeriveResourceType(out var rt);
var searchparameters = SpList[rt];
foreach (var index in searchparameters)
{
// prepare the search data cache
if (!exampleSearchValues.ContainsKey(index))
exampleSearchValues.Add(index, new Holder());
// prepare the search data cache
if (!exampleSearchValues.ContainsKey(index))
exampleSearchValues.Add(index, new Holder());

// Extract the values from the example
ExtractExamplesFromResource(exampleSearchValues, resource, index);
}
// Extract the values from the example
extractExamplesFromResource(exampleSearchValues, resource, index);
}

// If there are any contained resources, extract index data from those too!
if (resource is DomainResource)
// If there are any contained resources, extract index data from those too!
if (resource is DomainResource domainResource)
{
if (domainResource.Contained is { Count: > 0 })
{
if ((resource as DomainResource).Contained != null && (resource as DomainResource).Contained.Count > 0)
foreach (var conResource in domainResource.Contained)
{
foreach (var conResource in (resource as DomainResource).Contained)
{
ExtractValuesForSearchParameterFromFile(exampleSearchValues, conResource);
}
extractValuesForSearchParameterFromFile(exampleSearchValues, conResource);
}
}
}
}


class Holder
{
public int count;
}
private class Holder
{
public int Count;
}



private static void ExtractExamplesFromResource(Dictionary<SearchParamDefinition, Holder> exampleSearchValues, Resource resource,
SearchParamDefinition index )
{
var resourceModel = resource.ToTypedElement();

try

private static void extractExamplesFromResource(Dictionary<SearchParamDefinition, Holder> exampleSearchValues, Resource resource,
SearchParamDefinition index )
{
var resourceModel = resource.ToTypedElement();

try
{
var results = resourceModel.Select(index.Expression, new EvaluationContext()).ToArray();
if (results.Any())
{
var results = resourceModel.Select(index.Expression, new EvaluationContext());
if (results.Count() > 0)
foreach (var t2 in results)
{
foreach (var t2 in results)
if (t2 != null)
{
if (t2 != null)
{
exampleSearchValues[index].count++;
exampleSearchValues[index].Count++;

if (t2 is PocoElementNode && (t2 as PocoElementNode).FhirValue != null)
{
// Validate the type of data returned against the type of search parameter
// Debug.Write(index.Resource + "." + index.Name + ": ");
// Debug.WriteLine((t2 as FhirPath.ModelNavigator).FhirValue.ToString());// + "\r\n";
if (t2 is PocoElementNode { FhirValue: not null })
{
// Validate the type of data returned against the type of search parameter
// Debug.Write(index.Resource + "." + index.Name + ": ");
// Debug.WriteLine((t2 as FhirPath.ModelNavigator).FhirValue.ToString());// + "\r\n";

}
//else if (t2.Value is Hl7.FhirPath.ConstantValue)
//{
// // Debug.Write(index.Resource + "." + index.Name + ": ");
// // Debug.WriteLine((t2.Value as Hl7.FhirPath.ConstantValue).Value);
//}
else if (t2.Value is bool)
{
// Debug.Write(index.Resource + "." + index.Name + ": ");
// Debug.WriteLine((bool)t2.Value);
}
else
{
Debug.Write(index.Resource + "." + index.Name + ": ");
Debug.WriteLine(t2.Value);
}
}
//else if (t2.Value is Hl7.FhirPath.ConstantValue)
//{
// // Debug.Write(index.Resource + "." + index.Name + ": ");
// // Debug.WriteLine((t2.Value as Hl7.FhirPath.ConstantValue).Value);
//}
else if (t2.Value is bool)
{
// Debug.Write(index.Resource + "." + index.Name + ": ");
// Debug.WriteLine((bool)t2.Value);
}
else
{
Debug.Write(index.Resource + "." + index.Name + ": ");
Debug.WriteLine(t2.Value);
}
}
}
}
catch (ArgumentException ex)
{
Debug.WriteLine("FATAL: Error parsing expression in search index {0}.{1} {2}\r\n\t{3}", index.Resource, index.Name, index.Expression, ex.Message);
}
}
catch (ArgumentException ex)
{
Debug.WriteLine("FATAL: Error parsing expression in search index {0}.{1} {2}\r\n\t{3}", index.Resource, index.Name, index.Expression, ex.Message);
}
}
}
Loading

0 comments on commit 46999fa

Please sign in to comment.