Skip to content

Commit e5fa65f

Browse files
galtmaj-stein-nist
authored andcommitted
Implement opr:oscal-version and v:compare functions. (#1420)
The opr:oscal-version function meets the "req-meta-oscal-version" requirement from #1386. The v:compare utility function helps opr:oscal-version meet the "req-meta-oscalversion-error" requirement.
1 parent 22f423e commit e5fa65f

File tree

4 files changed

+916
-71
lines changed

4 files changed

+916
-71
lines changed

src/utils/util/resolver-pipeline/oscal-profile-resolve-metadata.xsl

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<xsl:stylesheet version="2.0"
2+
<xsl:stylesheet version="3.0"
33
xmlns="http://csrc.nist.gov/ns/oscal/1.0"
4+
xmlns:mh="http://csrc.nist.gov/ns/message"
45
xmlns:o="http://csrc.nist.gov/ns/oscal/1.0"
56
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
67
xmlns:xs="http://www.w3.org/2001/XMLSchema"
78
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
89
xmlns:opr="http://csrc.nist.gov/ns/oscal/profile-resolution"
910
xmlns:u="http://csrc.nist.gov/ns/uuid"
10-
exclude-result-prefixes="xs math o opr u"
11+
xmlns:v="http://csrc.nist.gov/ns/version"
12+
exclude-result-prefixes="xs math o opr u v"
1113
xpath-default-namespace="http://csrc.nist.gov/ns/oscal/1.0" >
12-
13-
<!-- XSLT 2.0 so as to validate against XSLT 3.0 constructs -->
14+
1415

1516
<!-- How to specify top-level UUID for result catalog:
1617
@@ -27,6 +28,9 @@
2728
$uuid-method, $top-uuid, and $uuid-service. -->
2829
<xsl:import href="uuid-method-choice.xsl"/>
2930

31+
<!-- version-util.xsl has semantic version comparison. -->
32+
<xsl:import href="version-util.xsl"/>
33+
3034
<!-- Top-level UUID for result catalog. -->
3135
<xsl:param name="top-uuid-computed" as="xs:string">
3236
<xsl:call-template name="u:determine-uuid"/>
@@ -38,9 +42,6 @@
3842
metadata, due to privacy or security concerns. This parameter is
3943
passed from oscal-profile-RESOLVE.xsl and the end user can override it. -->
4044
<xsl:param name="hide-source-profile-uri" as="xs:boolean" select="false()"/>
41-
42-
<!-- Version of this resolution tool -->
43-
<xsl:variable name="tool-oscal-version" as="xs:string" select="'1.1.0'"/>
4445

4546
<xsl:variable name="source-profile" as="xs:string"
4647
select="if ($hide-source-profile-uri) then 'profile' else $profile-origin-uri"/>
@@ -84,21 +85,42 @@
8485
<xsl:copy>
8586
<xsl:sequence select="opr:oscal-version(
8687
.,
87-
ancestor::profile/selection/metadata/oscal-version/normalize-space(),
88-
$tool-oscal-version
88+
ancestor::profile/selection/metadata/oscal-version/normalize-space()
8989
)"/>
9090
</xsl:copy>
9191
</xsl:template>
9292

93-
<!-- If there is a common major version among all inputs,
94-
return the most recent minor version or the tool version,
95-
whichever is earlier.
96-
If there is no common major version, return fatal error. -->
97-
<xsl:function name="opr:oscal-version" as="xs:string">
93+
<!-- Return the oscal-version of the source profile.
94+
Perform error checking as in requirement
95+
"req-meta-oscalversion-error".
96+
-->
97+
<xsl:function name="opr:oscal-version" as="xs:string" visibility="public">
98+
<!-- Without visiblity="public" the XSpec test returns
99+
XTDE0041: Cannot invoke function opr:oscal-version#2 externally, because it is not public
100+
-->
98101
<xsl:param name="source" as="xs:string"/>
99102
<xsl:param name="imported" as="xs:string*"/>
100-
<xsl:param name="tool" as="xs:string"/>
101-
<xsl:value-of select="'TODO: Not implemented yet'"/>
103+
104+
<xsl:variable name="options" as="map(*)"
105+
select="map{
106+
'normalize-space': true(),
107+
'supply-missing-zeros': true(),
108+
'remove-leading-zeros': true(),
109+
'allow-empty-string': true()
110+
}"/>
111+
<xsl:for-each select="$imported">
112+
<xsl:if test="v:compare($source, ., $options) eq xs:integer(-1)">
113+
<xsl:call-template name="mh:message-handler">
114+
<xsl:with-param name="message-type" select="'Error'"/>
115+
<xsl:with-param name="terminate" select="true()"/>
116+
<xsl:with-param name="text" expand-text="yes">Import uses oscal-version of {.
117+
}, which is newer than profile oscal-version of {
118+
$source}.</xsl:with-param>
119+
</xsl:call-template>
120+
</xsl:if>
121+
</xsl:for-each>
122+
<!-- Return the version from the source parameter. -->
123+
<xsl:value-of select="$source"/>
102124
</xsl:function>
103125

104126
<!--<xsl:template match="selection" mode="imported-metadata">

src/utils/util/resolver-pipeline/testing/2_metadata/metadata.xspec

Lines changed: 24 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,8 @@
226226
<oscal-version>...</oscal-version>
227227
</x:expect>
228228
</x:scenario>
229-
<x:scenario label="Sanity checks for calling opr:oscal-version with correct inputs: " pending="opr:oscal-version not implemented yet">
230-
<x:scenario label="Most recent version is in selection metadata">
229+
<x:scenario label="Sanity checks for calling opr:oscal-version with correct inputs: ">
230+
<x:scenario label="Most recent version is in selection metadata" catch="yes">
231231
<x:context select="/o:profile/o:metadata/o:oscal-version">
232232
<profile>
233233
<metadata>
@@ -252,9 +252,8 @@
252252
</selection>
253253
</profile>
254254
</x:context>
255-
<x:expect label="Most recent minor version mentioned in document">
256-
<oscal-version>1.0.4</oscal-version>
257-
</x:expect>
255+
<x:expect label="Error"
256+
test="$x:result instance of map(*) and $x:result('err') instance of map(*)"/>
258257
</x:scenario>
259258
<x:scenario label="Most recent version is in profile metadata">
260259
<x:context select="/o:profile/o:metadata/o:oscal-version">
@@ -269,81 +268,51 @@
269268
</selection>
270269
</profile>
271270
</x:context>
272-
<x:expect label="Most recent minor version mentioned in document">
271+
<x:expect label="Version from profile">
273272
<oscal-version>1.0.4</oscal-version>
274273
</x:expect>
275274
</x:scenario>
276-
<x:scenario label="Tool version is older than document versions">
277-
<x:context select="/o:profile/o:metadata/o:oscal-version">
278-
<profile>
279-
<metadata>
280-
<oscal-version>1.4.0</oscal-version>
281-
</metadata>
282-
<selection>
283-
<metadata>
284-
<oscal-version>1.2.0</oscal-version>
285-
</metadata>
286-
</selection>
287-
</profile>
288-
</x:context>
289-
<x:expect label="Tool version">
290-
<oscal-version>1.1.0</oscal-version>
291-
</x:expect>
292-
</x:scenario>
293275
</x:scenario>
294276
</x:scenario>
295277

296-
<x:scenario label="Tests for opr:oscal-version function" pending="opr:oscal-version not implemented yet">
278+
<x:scenario label="Tests for opr:oscal-version function">
297279
<x:scenario label="Same major version">
298-
<x:scenario label="Source profile version newer than imported document">
280+
<x:scenario label="Source profile version at least as new as all imported documents">
299281
<x:call function="opr:oscal-version">
300282
<x:param name="source" select="'1.0.1'"/>
301-
<x:param name="imported" select="('1.0.0','1.0.0')"/>
302-
<x:param name="tool" select="'1.0.1'"/>
283+
<x:param name="imported" select="('1.0.0','1.0.1')"/>
303284
</x:call>
304-
<x:expect label="Newest minor version" select="'1.0.1'"/>
285+
<x:expect label="Source version and no error" select="'1.0.1'"/>
305286
</x:scenario>
306-
<x:scenario label="Source profile version older than imported document">
287+
<x:scenario label="Source profile version older than at least one imported document" catch="yes">
307288
<x:call function="opr:oscal-version">
308289
<x:param name="source" select="'1.0.0'"/>
309-
<x:param name="imported" select="('1.0.1','1.0.1')"/>
310-
<x:param name="tool" select="'1.0.1'"/>
290+
<x:param name="imported" select="('1.0.0','1.0.1')"/>
311291
</x:call>
312-
<x:expect label="Newest minor version" select="'1.0.1'"/>
292+
<x:expect label="Error"
293+
test="$x:result instance of map(*) and $x:result('err') instance of map(*)"/>
313294
</x:scenario>
314-
<x:scenario label="Tool version is older">
295+
<x:scenario label="Imported document has a newer pre-release identifier" catch="yes">
315296
<x:call function="opr:oscal-version">
316-
<x:param name="source" select="'1.0.1'"/>
317-
<x:param name="imported" select="('1.0.1','1.0.1')"/>
318-
<x:param name="tool" select="'1.0.0'"/>
297+
<x:param name="source" select="'1.0.1-rc1'"/>
298+
<x:param name="imported" select="('1.0.0','1.0.1-rc2')"/>
319299
</x:call>
320-
<x:expect label="Tool version" select="'1.0.0'"/>
300+
<x:expect label="Error"
301+
test="$x:result instance of map(*) and $x:result('err') instance of map(*)"/>
321302
</x:scenario>
322303
</x:scenario>
323304
<x:scenario label="Different major version">
324-
<x:scenario label="Source profile version newer than imported document">
305+
<x:scenario label="Source profile version at least as new as all imported documents">
325306
<x:call function="opr:oscal-version">
326307
<x:param name="source" select="'2.0.1'"/>
327-
<x:param name="imported" select="('1.0.0','1.0.0')"/>
328-
<x:param name="tool" select="'2.0.1'"/>
308+
<x:param name="imported" select="('1.37.40','1.37')"/>
329309
</x:call>
330-
<x:expect label="Error"
331-
test="$x:result instance of map(*) and $x:result('err') instance of map(*)"/>
310+
<x:expect label="Source version and no error" select="'2.0.1'"/>
332311
</x:scenario>
333-
<x:scenario label="Source profile version older than imported document">
312+
<x:scenario label="Source profile version older than at least one imported document" catch="yes">
334313
<x:call function="opr:oscal-version">
335-
<x:param name="source" select="'1.0.0'"/>
336-
<x:param name="imported" select="('2.0.1','2.0.1')"/>
337-
<x:param name="tool" select="'2.0.1'"/>
338-
</x:call>
339-
<x:expect label="Error"
340-
test="$x:result instance of map(*) and $x:result('err') instance of map(*)"/>
341-
</x:scenario>
342-
<x:scenario label="Tool version is older">
343-
<x:call function="opr:oscal-version">
344-
<x:param name="source" select="'2.0.1'"/>
345-
<x:param name="imported" select="('2.0.1','2.0.1')"/>
346-
<x:param name="tool" select="'1.0.0'"/>
314+
<x:param name="source" select="'1.37.40'"/>
315+
<x:param name="imported" select="('2.0','1.0.1')"/>
347316
</x:call>
348317
<x:expect label="Error"
349318
test="$x:result instance of map(*) and $x:result('err') instance of map(*)"/>

0 commit comments

Comments
 (0)