modspec 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +4 -0
- data/.github/workflows/release.yml +5 -0
- data/.rubocop.yml +16 -7
- data/.rubocop_todo.yml +67 -80
- data/CLAUDE.md +61 -0
- data/Gemfile +4 -3
- data/lib/modspec/conformance_class.rb +4 -6
- data/lib/modspec/conformance_test.rb +19 -4
- data/lib/modspec/normative_statement.rb +2 -2
- data/lib/modspec/normative_statements_class.rb +3 -1
- data/lib/modspec/suite.rb +45 -38
- data/lib/modspec/version.rb +1 -1
- data/lib/modspec.rb +1 -12
- data/modspec.gemspec +3 -2
- data/spec/conformance_class.liquid +2 -2
- data/spec/fixtures/advanced-json-rc.yaml +5 -7
- data/spec/fixtures/advanced-rc.yaml +12 -14
- data/spec/fixtures/basic-quaternion-json-rc.yaml +5 -7
- data/spec/fixtures/basic-quaternion-json-strict-rc.yaml +4 -5
- data/spec/fixtures/basic-quaternion-rc.yaml +7 -8
- data/spec/fixtures/basic-ypr-json-rc.yaml +5 -8
- data/spec/fixtures/basic-ypr-rc.yaml +7 -7
- data/spec/fixtures/chain-json-rc.yaml +5 -7
- data/spec/fixtures/chain-rc.yaml +11 -13
- data/spec/fixtures/frame-spec-rc.yaml +10 -10
- data/spec/fixtures/global-rc.yaml +7 -4
- data/spec/fixtures/graph-json-rc.yaml +5 -7
- data/spec/fixtures/graph-rc.yaml +11 -13
- data/spec/fixtures/series-irregular-json-rc.yaml +5 -7
- data/spec/fixtures/series-irregular-rc.yaml +13 -15
- data/spec/fixtures/series-regular-json-rc.yaml +5 -7
- data/spec/fixtures/series-regular-rc.yaml +15 -17
- data/spec/fixtures/stream-json-rc.yaml +9 -11
- data/spec/fixtures/stream-rc.yaml +10 -12
- data/spec/fixtures/tangent-point-rc.yaml +10 -11
- data/spec/fixtures/time-rc.yaml +6 -8
- data/spec/modspec/conformance_class_spec.rb +29 -27
- data/spec/modspec/conformance_test_spec.rb +6 -5
- data/spec/modspec/normative_statement_spec.rb +16 -12
- data/spec/modspec/normative_statements_class_spec.rb +4 -4
- data/spec/modspec/suite_spec.rb +26 -22
- data/spec/modspec_spec.rb +7 -7
- data/spec/spec_helper.rb +1 -0
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 925062f2457c7aa978de3d2eabc679f4a33b9177e8ba2f3a80494c46377ff0b8
|
|
4
|
+
data.tar.gz: '083c357ffd578b297ae28753e48dccacd08a10d202f336299b037d1d6b08fe9a'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ce9246f0f6b4ce811bf498d52a59c25949ad0016b024ab215c332ce7e1e34fa311c2a78267a3a1b07cb1a2f0f468559c1aeaedb638c4552e9500016ad8a3235b
|
|
7
|
+
data.tar.gz: 7132a3d0194c87222d077752784d1d1d7197481d1db1ae356c9f959d8cccd8163f3ef268a2e4e6b75812095768e133ab6da81c629fd3d33b0122f7f2789079fe
|
data/.github/workflows/rake.yml
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
# Auto-generated by Cimas: Do not edit it manually!
|
|
2
|
+
# See https://github.com/metanorma/cimas
|
|
3
|
+
inherit_from:
|
|
4
|
+
- https://raw.githubusercontent.com/riboseinc/oss-guides/main/ci/rubocop.yml
|
|
5
|
+
- .rubocop_todo.yml
|
|
2
6
|
|
|
3
|
-
|
|
4
|
-
|
|
7
|
+
inherit_mode:
|
|
8
|
+
merge:
|
|
9
|
+
- Exclude
|
|
5
10
|
|
|
6
|
-
|
|
7
|
-
|
|
11
|
+
# local repo-specific modifications
|
|
12
|
+
# ...
|
|
13
|
+
plugins:
|
|
14
|
+
- rubocop-rspec
|
|
15
|
+
- rubocop-performance
|
|
16
|
+
- rubocop-rake
|
|
8
17
|
|
|
9
|
-
|
|
10
|
-
|
|
18
|
+
AllCops:
|
|
19
|
+
TargetRubyVersion: 3.0
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,118 +1,105 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on
|
|
3
|
+
# on 2026-05-05 14:09:35 UTC using RuboCop version 1.86.1.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
|
8
8
|
|
|
9
|
-
# Offense count: 4
|
|
10
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
11
|
-
# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
|
|
12
|
-
# Include: **/*.gemfile, **/Gemfile, **/gems.rb
|
|
13
|
-
Bundler/OrderedGems:
|
|
14
|
-
Exclude:
|
|
15
|
-
- 'Gemfile'
|
|
16
|
-
|
|
17
9
|
# Offense count: 1
|
|
18
|
-
# Configuration parameters: Severity, Include.
|
|
19
|
-
# Include: **/*.gemspec
|
|
20
10
|
Gemspec/RequiredRubyVersion:
|
|
21
11
|
Exclude:
|
|
22
12
|
- 'modspec.gemspec'
|
|
23
13
|
|
|
24
|
-
# Offense count:
|
|
14
|
+
# Offense count: 33
|
|
25
15
|
# This cop supports safe autocorrection (--autocorrect).
|
|
26
|
-
# Configuration parameters:
|
|
27
|
-
#
|
|
28
|
-
Layout/
|
|
16
|
+
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
17
|
+
# URISchemes: http, https
|
|
18
|
+
Layout/LineLength:
|
|
29
19
|
Exclude:
|
|
30
|
-
- 'modspec.
|
|
20
|
+
- 'lib/modspec/conformance_class.rb'
|
|
21
|
+
- 'lib/modspec/conformance_test.rb'
|
|
22
|
+
- 'lib/modspec/normative_statement.rb'
|
|
23
|
+
- 'lib/modspec/normative_statements_class.rb'
|
|
24
|
+
- 'lib/modspec/suite.rb'
|
|
25
|
+
- 'spec/modspec/conformance_class_spec.rb'
|
|
26
|
+
- 'spec/modspec/conformance_test_spec.rb'
|
|
27
|
+
- 'spec/modspec/normative_statement_spec.rb'
|
|
28
|
+
- 'spec/modspec/normative_statements_class_spec.rb'
|
|
31
29
|
- 'spec/modspec/suite_spec.rb'
|
|
32
30
|
|
|
33
31
|
# Offense count: 4
|
|
34
|
-
# Configuration parameters:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
40
|
-
# AllowedMethods: refine
|
|
41
|
-
Metrics/BlockLength:
|
|
42
|
-
Max: 138
|
|
32
|
+
# Configuration parameters: AllowComments, AllowEmptyLambdas.
|
|
33
|
+
Lint/EmptyBlock:
|
|
34
|
+
Exclude:
|
|
35
|
+
- 'spec/modspec/conformance_class_spec.rb'
|
|
36
|
+
- 'spec/modspec/suite_spec.rb'
|
|
43
37
|
|
|
44
38
|
# Offense count: 1
|
|
45
|
-
#
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
40
|
+
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
|
|
41
|
+
# NotImplementedExceptions: NotImplementedError
|
|
42
|
+
Lint/UnusedMethodArgument:
|
|
43
|
+
Exclude:
|
|
44
|
+
- 'lib/modspec/normative_statement.rb'
|
|
48
45
|
|
|
49
|
-
# Offense count:
|
|
50
|
-
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
|
51
|
-
Metrics/
|
|
52
|
-
|
|
46
|
+
# Offense count: 7
|
|
47
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
48
|
+
Metrics/AbcSize:
|
|
49
|
+
Exclude:
|
|
50
|
+
- 'lib/modspec/suite.rb'
|
|
53
51
|
|
|
54
52
|
# Offense count: 5
|
|
53
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
54
|
+
Metrics/CyclomaticComplexity:
|
|
55
|
+
Exclude:
|
|
56
|
+
- 'lib/modspec/suite.rb'
|
|
57
|
+
|
|
58
|
+
# Offense count: 9
|
|
55
59
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
56
60
|
Metrics/MethodLength:
|
|
57
|
-
Max:
|
|
61
|
+
Max: 21
|
|
58
62
|
|
|
59
|
-
# Offense count:
|
|
60
|
-
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
|
63
|
+
# Offense count: 3
|
|
64
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
61
65
|
Metrics/PerceivedComplexity:
|
|
62
|
-
Max: 12
|
|
63
|
-
|
|
64
|
-
# Offense count: 1
|
|
65
|
-
# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros.
|
|
66
|
-
# NamePrefix: is_, has_, have_
|
|
67
|
-
# ForbiddenPrefixes: is_, has_, have_
|
|
68
|
-
# AllowedMethods: is_a?
|
|
69
|
-
# MethodDefinitionMacros: define_method, define_singleton_method
|
|
70
|
-
Naming/PredicateName:
|
|
71
66
|
Exclude:
|
|
72
|
-
- '
|
|
73
|
-
- 'lib/modspec/normative_statement.rb'
|
|
67
|
+
- 'lib/modspec/suite.rb'
|
|
74
68
|
|
|
75
|
-
# Offense count:
|
|
76
|
-
# Configuration parameters:
|
|
77
|
-
|
|
69
|
+
# Offense count: 1
|
|
70
|
+
# Configuration parameters: MinSize.
|
|
71
|
+
Performance/CollectionLiteralInLoop:
|
|
78
72
|
Exclude:
|
|
79
|
-
- 'spec/**/*'
|
|
80
|
-
- 'test/**/*'
|
|
81
|
-
- 'lib/modspec/conformance_class.rb'
|
|
82
|
-
- 'lib/modspec/conformance_test.rb'
|
|
83
|
-
- 'lib/modspec/normative_statement.rb'
|
|
84
|
-
- 'lib/modspec/normative_statements_class.rb'
|
|
85
73
|
- 'lib/modspec/suite.rb'
|
|
86
74
|
|
|
87
|
-
# Offense count:
|
|
88
|
-
#
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
- 'lib/modspec/conformance_class.rb'
|
|
92
|
-
- 'lib/modspec/normative_statements_class.rb'
|
|
75
|
+
# Offense count: 5
|
|
76
|
+
# Configuration parameters: CountAsOne.
|
|
77
|
+
RSpec/ExampleLength:
|
|
78
|
+
Max: 15
|
|
93
79
|
|
|
94
|
-
# Offense count:
|
|
80
|
+
# Offense count: 1
|
|
95
81
|
# This cop supports safe autocorrection (--autocorrect).
|
|
96
|
-
|
|
97
|
-
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
|
|
98
|
-
Style/TrailingCommaInArguments:
|
|
82
|
+
RSpec/ExpectActual:
|
|
99
83
|
Exclude:
|
|
100
|
-
- 'spec/modspec/conformance_class_spec.rb'
|
|
101
|
-
- 'spec/modspec/conformance_test_spec.rb'
|
|
102
84
|
- 'spec/modspec/normative_statement_spec.rb'
|
|
103
|
-
- 'spec/modspec/normative_statements_class_spec.rb'
|
|
104
85
|
|
|
105
|
-
# Offense count:
|
|
106
|
-
#
|
|
107
|
-
|
|
108
|
-
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
|
|
109
|
-
Style/TrailingCommaInArrayLiteral:
|
|
86
|
+
# Offense count: 4
|
|
87
|
+
# Configuration parameters: Max, AllowedIdentifiers, AllowedPatterns.
|
|
88
|
+
RSpec/IndexedLet:
|
|
110
89
|
Exclude:
|
|
111
|
-
- 'spec/modspec/
|
|
90
|
+
- 'spec/modspec/normative_statements_class_spec.rb'
|
|
91
|
+
- 'spec/modspec/suite_spec.rb'
|
|
112
92
|
|
|
113
|
-
# Offense count:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
93
|
+
# Offense count: 7
|
|
94
|
+
RSpec/MultipleExpectations:
|
|
95
|
+
Max: 9
|
|
96
|
+
|
|
97
|
+
# Offense count: 7
|
|
98
|
+
# Configuration parameters: AllowSubject.
|
|
99
|
+
RSpec/MultipleMemoizedHelpers:
|
|
100
|
+
Max: 12
|
|
101
|
+
|
|
102
|
+
# Offense count: 2
|
|
103
|
+
RSpec/RepeatedExample:
|
|
104
|
+
Exclude:
|
|
105
|
+
- 'spec/modspec_spec.rb'
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
`modspec` is a Ruby gem for working with OGC ModSpec — a specification format (OGC 08-131r3) for defining requirements and conformance tests for standards. All models use `lutaml-model` (`Lutaml::Model::Serializable`) for serialization to/from YAML, JSON, and XML.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
- **Run all tests:** `bundle exec rake` or `bundle exec rspec`
|
|
12
|
+
- **Run a single test file:** `bundle exec rspec spec/modspec/suite_spec.rb`
|
|
13
|
+
- **Run a single example:** `bundle exec rspec spec/modspec/suite_spec.rb:42`
|
|
14
|
+
- **Lint:** RuboCop is configured but not in the default rake task. Run with `bundle exec rubocop` if needed.
|
|
15
|
+
- **Console:** `bin/console` (loads IRB with the gem)
|
|
16
|
+
|
|
17
|
+
## Architecture
|
|
18
|
+
|
|
19
|
+
All model classes inherit from `Lutaml::Model::Serializable` and define attributes via the `attribute` DSL with serialization mappings in `xml do` blocks. YAML/JSON serialization comes from lutaml-model automatically.
|
|
20
|
+
|
|
21
|
+
### Identifier convention (critical)
|
|
22
|
+
|
|
23
|
+
Identifiers are URIs with a specific structure:
|
|
24
|
+
- Class-level: `/<type>/<class>` (e.g., `/req/example`, `/conf/example`)
|
|
25
|
+
- Instance-level: `/<type>/<class>/<name>` (e.g., `/req/example/foo`)
|
|
26
|
+
- Type prefix: `req` = normative statements, `conf` = conformance tests
|
|
27
|
+
|
|
28
|
+
Validation enforces that children share their parent's identifier prefix.
|
|
29
|
+
|
|
30
|
+
### Model hierarchy
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
Suite
|
|
34
|
+
├── NormativeStatementsClass (collection) → groups normative statements
|
|
35
|
+
│ └── NormativeStatement (collection)
|
|
36
|
+
│ └── NormativeStatementPart (collection) → sub-parts of a statement
|
|
37
|
+
├── ConformanceClass (collection) → groups conformance tests
|
|
38
|
+
│ └── ConformanceTest (collection)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- `NormativeStatement` has obligation (`requirement`/`recommendation`/`permission`), dependencies, inherit, indirect_dependency, implements, parts
|
|
42
|
+
- `ConformanceTest` has targets (referencing normative statement identifiers), abstract flag, method, purpose
|
|
43
|
+
- `ConformanceTest` uses runtime-only `corresponding_requirements` and `parent_class` attrs set by `Suite#setup_relationships`
|
|
44
|
+
|
|
45
|
+
### Validation
|
|
46
|
+
|
|
47
|
+
Each model class has a `validate` method that returns an array of error strings. `Suite#validate` orchestrates full validation: cycles (dependency graph via DFS), label uniqueness, dependency resolution, and delegating to child class validators.
|
|
48
|
+
|
|
49
|
+
### Key Suite operations
|
|
50
|
+
|
|
51
|
+
- `combine(other_suite)` — merges two suites, deduplicating by identifier
|
|
52
|
+
- `from_yaml_files(*files)` — loads and combines multiple YAML files
|
|
53
|
+
- `setup_relationships` — cross-links conformance tests to their target normative statements
|
|
54
|
+
|
|
55
|
+
### Custom types
|
|
56
|
+
|
|
57
|
+
`Modspec::Identifier` extends `Lutaml::Model::Type::String` — used as the type for all identifier attributes and reference fields (dependencies, targets, inherit, etc.).
|
|
58
|
+
|
|
59
|
+
## Key dependency
|
|
60
|
+
|
|
61
|
+
`lutaml-model ~> 0.7.7` — provides the `Serializable` base class, attribute DSL, and serialization adapters. Breaking changes in lutaml-model may affect this gem.
|
data/Gemfile
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
# Specify your gem's dependencies in modspec.gemspec
|
|
6
5
|
gemspec
|
|
7
6
|
|
|
8
|
-
gem "
|
|
9
|
-
gem "pry"
|
|
7
|
+
gem "canon"
|
|
10
8
|
gem "rake"
|
|
11
9
|
gem "rspec"
|
|
12
10
|
gem "rubocop"
|
|
11
|
+
gem "rubocop-performance"
|
|
12
|
+
gem "rubocop-rake"
|
|
13
|
+
gem "rubocop-rspec"
|
|
@@ -18,7 +18,7 @@ module Modspec
|
|
|
18
18
|
attribute :reference, :string
|
|
19
19
|
|
|
20
20
|
xml do
|
|
21
|
-
|
|
21
|
+
element "conformance-class"
|
|
22
22
|
map_attribute "identifier", to: :identifier
|
|
23
23
|
map_element "name", to: :name
|
|
24
24
|
map_element "dependencies", to: :dependencies
|
|
@@ -32,7 +32,7 @@ module Modspec
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def validate
|
|
35
|
-
errors = super
|
|
35
|
+
errors = super
|
|
36
36
|
errors.concat(validate_identifier_prefix)
|
|
37
37
|
errors.concat(validate_class_children_mapping)
|
|
38
38
|
errors.concat(tests.flat_map(&:validate))
|
|
@@ -52,10 +52,8 @@ module Modspec
|
|
|
52
52
|
def validate_identifier_prefix
|
|
53
53
|
errors = []
|
|
54
54
|
expected_prefix = "#{identifier}/"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
errors << "Conformance test #{test.identifier} does not share the expected prefix #{expected_prefix}" unless test.identifier.to_s.start_with?(expected_prefix)
|
|
58
|
-
end
|
|
55
|
+
tests&.each do |test|
|
|
56
|
+
errors << "Conformance test #{test.identifier} does not share the expected prefix #{expected_prefix}" unless test.identifier.to_s.start_with?(expected_prefix)
|
|
59
57
|
end
|
|
60
58
|
errors
|
|
61
59
|
end
|
|
@@ -13,13 +13,13 @@ module Modspec
|
|
|
13
13
|
attribute :description, :string
|
|
14
14
|
attribute :guidance, :string, collection: true
|
|
15
15
|
attribute :purpose, :string
|
|
16
|
-
attribute :
|
|
16
|
+
attribute :test_method, :string
|
|
17
17
|
attribute :type, :string
|
|
18
18
|
attribute :reference, :string
|
|
19
19
|
attribute :abstract, :boolean
|
|
20
20
|
|
|
21
21
|
xml do
|
|
22
|
-
|
|
22
|
+
element "conformance-test"
|
|
23
23
|
map_attribute "identifier", to: :identifier
|
|
24
24
|
map_attribute "abstract", to: :abstract
|
|
25
25
|
map_element "name", to: :name
|
|
@@ -29,15 +29,30 @@ module Modspec
|
|
|
29
29
|
map_element "description", to: :description
|
|
30
30
|
map_element "guidance", to: :guidance
|
|
31
31
|
map_element "purpose", to: :purpose
|
|
32
|
-
map_element "method", to: :
|
|
32
|
+
map_element "method", to: :test_method
|
|
33
33
|
map_element "type", to: :type
|
|
34
34
|
map_element "reference", to: :reference
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
key_value do
|
|
38
|
+
map "identifier", to: :identifier
|
|
39
|
+
map "name", to: :name
|
|
40
|
+
map "dependencies", to: :dependencies
|
|
41
|
+
map "targets", to: :targets
|
|
42
|
+
map "belongs_to", to: :belongs_to
|
|
43
|
+
map "description", to: :description
|
|
44
|
+
map "guidance", to: :guidance
|
|
45
|
+
map "purpose", to: :purpose
|
|
46
|
+
map "method", to: :test_method
|
|
47
|
+
map "type", to: :type
|
|
48
|
+
map "reference", to: :reference
|
|
49
|
+
map "abstract", to: :abstract
|
|
50
|
+
end
|
|
51
|
+
|
|
37
52
|
attr_accessor :corresponding_requirements, :parent_class
|
|
38
53
|
|
|
39
54
|
def validate
|
|
40
|
-
errors = super
|
|
55
|
+
errors = super
|
|
41
56
|
errors.concat(validate_requirement_mapping)
|
|
42
57
|
errors.concat(validate_class_mapping)
|
|
43
58
|
errors
|
|
@@ -29,7 +29,7 @@ module Modspec
|
|
|
29
29
|
default: -> { "requirement" }
|
|
30
30
|
|
|
31
31
|
xml do
|
|
32
|
-
|
|
32
|
+
element "normative-statement"
|
|
33
33
|
map_attribute "identifier", to: :identifier
|
|
34
34
|
map_element "name", to: :name
|
|
35
35
|
map_element "subject", to: :subject
|
|
@@ -46,7 +46,7 @@ module Modspec
|
|
|
46
46
|
map_element "parts", to: :parts
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
def validate(suite = nil)
|
|
49
|
+
def validate(suite = nil, register: Lutaml::Model::Config.default_register)
|
|
50
50
|
errors = super()
|
|
51
51
|
errors.concat(validate_dependencies(suite)) if suite
|
|
52
52
|
errors.concat(validate_nested_requirement)
|
|
@@ -12,19 +12,21 @@ module Modspec
|
|
|
12
12
|
attribute :subject, :string
|
|
13
13
|
attribute :guidance, :string, collection: true
|
|
14
14
|
attribute :dependencies, Identifier, collection: true
|
|
15
|
+
attribute :implements, Identifier, collection: true
|
|
15
16
|
attribute :normative_statements, NormativeStatement, collection: true
|
|
16
17
|
attribute :belongs_to, Identifier, collection: true
|
|
17
18
|
attribute :reference, :string
|
|
18
19
|
attribute :source, :string
|
|
19
20
|
|
|
20
21
|
xml do
|
|
21
|
-
|
|
22
|
+
element "normative-statements-class"
|
|
22
23
|
map_attribute "identifier", to: :identifier
|
|
23
24
|
map_element "name", to: :name
|
|
24
25
|
map_element "description", to: :description
|
|
25
26
|
map_element "subject", to: :subject
|
|
26
27
|
map_element "guidance", to: :guidance
|
|
27
28
|
map_element "dependencies", to: :dependencies
|
|
29
|
+
map_element "implements", to: :implements
|
|
28
30
|
map_element "normative-statements", to: :normative_statements
|
|
29
31
|
map_element "belongs_to", to: :belongs_to
|
|
30
32
|
map_element "reference", to: :reference
|
data/lib/modspec/suite.rb
CHANGED
|
@@ -6,14 +6,16 @@ module Modspec
|
|
|
6
6
|
class Suite < Lutaml::Model::Serializable
|
|
7
7
|
attribute :identifier, Identifier
|
|
8
8
|
attribute :name, :string
|
|
9
|
-
attribute :normative_statements_classes, NormativeStatementsClass,
|
|
9
|
+
attribute :normative_statements_classes, NormativeStatementsClass,
|
|
10
|
+
collection: true
|
|
10
11
|
attribute :conformance_classes, ConformanceClass, collection: true
|
|
11
12
|
|
|
12
13
|
xml do
|
|
13
|
-
|
|
14
|
+
element "suite"
|
|
14
15
|
map_attribute "identifier", to: :identifier
|
|
15
16
|
map_element "name", to: :name
|
|
16
|
-
map_element "normative-statements-classes",
|
|
17
|
+
map_element "normative-statements-classes",
|
|
18
|
+
to: :normative_statements_classes
|
|
17
19
|
map_element "conformance-classes", to: :conformance_classes
|
|
18
20
|
end
|
|
19
21
|
|
|
@@ -24,13 +26,20 @@ module Modspec
|
|
|
24
26
|
errors.concat(validate_cycles)
|
|
25
27
|
errors.concat(validate_label_uniqueness)
|
|
26
28
|
errors.concat(validate_dependencies)
|
|
27
|
-
|
|
29
|
+
unless normative_statements_classes.nil?
|
|
30
|
+
errors.concat(normative_statements_classes.flat_map do |n|
|
|
31
|
+
n.validate(self)
|
|
32
|
+
end)
|
|
33
|
+
end
|
|
28
34
|
errors.concat(conformance_classes.flat_map(&:validate)) unless conformance_classes.nil?
|
|
29
35
|
errors
|
|
30
36
|
end
|
|
31
37
|
|
|
32
38
|
def combine(other_suite)
|
|
33
|
-
|
|
39
|
+
unless other_suite.is_a?(Modspec::Suite)
|
|
40
|
+
raise ArgumentError,
|
|
41
|
+
"Argument must be a Modspec::Suite"
|
|
42
|
+
end
|
|
34
43
|
|
|
35
44
|
combined_suite = dup
|
|
36
45
|
combined_suite.all_identifiers = nil
|
|
@@ -45,9 +54,9 @@ module Modspec
|
|
|
45
54
|
end
|
|
46
55
|
|
|
47
56
|
# Ensure uniqueness of identifiers
|
|
48
|
-
combined_suite.normative_statements_classes
|
|
57
|
+
combined_suite.normative_statements_classes&.uniq!(&:identifier)
|
|
49
58
|
|
|
50
|
-
combined_suite.conformance_classes
|
|
59
|
+
combined_suite.conformance_classes&.uniq!(&:identifier)
|
|
51
60
|
|
|
52
61
|
combined_suite.name = "#{name} + #{other_suite.name}"
|
|
53
62
|
|
|
@@ -69,8 +78,10 @@ module Modspec
|
|
|
69
78
|
attr_writer :all_identifiers
|
|
70
79
|
|
|
71
80
|
def resolve_conflicts(other_suite)
|
|
72
|
-
resolve_conflicts_for(normative_statements_classes,
|
|
73
|
-
|
|
81
|
+
resolve_conflicts_for(normative_statements_classes,
|
|
82
|
+
other_suite.normative_statements_classes)
|
|
83
|
+
resolve_conflicts_for(conformance_classes,
|
|
84
|
+
other_suite.conformance_classes)
|
|
74
85
|
end
|
|
75
86
|
|
|
76
87
|
def self.from_yaml_files(*files)
|
|
@@ -95,7 +106,7 @@ module Modspec
|
|
|
95
106
|
conformance_classes.each do |cc|
|
|
96
107
|
cc.tests.each do |ct|
|
|
97
108
|
ct.corresponding_requirements = all_requirements.select do |r|
|
|
98
|
-
ct.targets.map(&:to_s).include?(r.identifier.to_s)
|
|
109
|
+
Array(ct.targets).map(&:to_s).include?(r.identifier.to_s)
|
|
99
110
|
end
|
|
100
111
|
ct.parent_class = cc
|
|
101
112
|
end
|
|
@@ -108,7 +119,9 @@ module Modspec
|
|
|
108
119
|
return if self_collection.nil? || other_collection.nil?
|
|
109
120
|
|
|
110
121
|
other_collection.each do |other_item|
|
|
111
|
-
existing_item = self_collection.find
|
|
122
|
+
existing_item = self_collection.find do |item|
|
|
123
|
+
item.identifier == other_item.identifier
|
|
124
|
+
end
|
|
112
125
|
if existing_item
|
|
113
126
|
# Merge attributes of conflicting items
|
|
114
127
|
merge_attributes(existing_item, other_item)
|
|
@@ -133,7 +146,7 @@ module Modspec
|
|
|
133
146
|
def validate_cycles
|
|
134
147
|
graph = build_dependency_graph
|
|
135
148
|
cycles = detect_cycles(graph)
|
|
136
|
-
cycles.map { |cycle| "Cycle detected: #{cycle.join(
|
|
149
|
+
cycles.map { |cycle| "Cycle detected: #{cycle.join(' -> ')}" }
|
|
137
150
|
end
|
|
138
151
|
|
|
139
152
|
# Combine all statements into a single array
|
|
@@ -161,7 +174,8 @@ module Modspec
|
|
|
161
174
|
graph[id] = Set.new
|
|
162
175
|
|
|
163
176
|
# Define all dependency-like properties to check
|
|
164
|
-
dependency_properties = %i[dependencies indirect_dependency implements
|
|
177
|
+
dependency_properties = %i[dependencies indirect_dependency implements
|
|
178
|
+
targets]
|
|
165
179
|
|
|
166
180
|
dependency_properties.each do |property|
|
|
167
181
|
graph[id].merge(statement.send(property).map(&:to_s)) if statement.respond_to?(property) && !statement.send(property).nil?
|
|
@@ -195,7 +209,8 @@ module Modspec
|
|
|
195
209
|
if graph[node]
|
|
196
210
|
graph[node].each do |neighbor|
|
|
197
211
|
if !visited.include?(neighbor)
|
|
198
|
-
cycle = detect_cycle_util(neighbor, graph, visited,
|
|
212
|
+
cycle = detect_cycle_util(neighbor, graph, visited,
|
|
213
|
+
recursion_stack, path)
|
|
199
214
|
return cycle if cycle
|
|
200
215
|
elsif recursion_stack.include?(neighbor)
|
|
201
216
|
return path[path.index(neighbor)..] + [neighbor]
|
|
@@ -228,21 +243,17 @@ module Modspec
|
|
|
228
243
|
all_identifiers = collect_all_identifiers
|
|
229
244
|
|
|
230
245
|
errors = []
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
errors.concat(validate_statement_dependencies(ns, all_identifiers))
|
|
236
|
-
end
|
|
246
|
+
normative_statements_classes&.each do |nsc|
|
|
247
|
+
errors.concat(validate_class_dependencies(nsc, all_identifiers))
|
|
248
|
+
nsc.normative_statements.each do |ns|
|
|
249
|
+
errors.concat(validate_statement_dependencies(ns, all_identifiers))
|
|
237
250
|
end
|
|
238
251
|
end
|
|
239
252
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
errors.concat(validate_test_targets(ct, all_identifiers))
|
|
245
|
-
end
|
|
253
|
+
conformance_classes&.each do |cc|
|
|
254
|
+
errors.concat(validate_class_dependencies(cc, all_identifiers))
|
|
255
|
+
cc.tests.each do |ct|
|
|
256
|
+
errors.concat(validate_test_targets(ct, all_identifiers))
|
|
246
257
|
end
|
|
247
258
|
end
|
|
248
259
|
|
|
@@ -252,21 +263,17 @@ module Modspec
|
|
|
252
263
|
def collect_all_identifiers
|
|
253
264
|
identifiers = {}
|
|
254
265
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
identifiers[ns.identifier.to_s] = ns
|
|
260
|
-
end
|
|
266
|
+
normative_statements_classes&.each do |nsc|
|
|
267
|
+
identifiers[nsc.identifier.to_s] = nsc
|
|
268
|
+
nsc.normative_statements.each do |ns|
|
|
269
|
+
identifiers[ns.identifier.to_s] = ns
|
|
261
270
|
end
|
|
262
271
|
end
|
|
263
272
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
identifiers[ct.identifier.to_s] = ct
|
|
269
|
-
end
|
|
273
|
+
conformance_classes&.each do |cc|
|
|
274
|
+
identifiers[cc.identifier.to_s] = cc
|
|
275
|
+
cc.tests.each do |ct|
|
|
276
|
+
identifiers[ct.identifier.to_s] = ct
|
|
270
277
|
end
|
|
271
278
|
end
|
|
272
279
|
|
data/lib/modspec/version.rb
CHANGED
data/lib/modspec.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "modspec/version"
|
|
4
4
|
require "lutaml/model"
|
|
5
|
+
require "set"
|
|
5
6
|
|
|
6
7
|
module Modspec
|
|
7
8
|
class Error < StandardError; end
|
|
@@ -15,15 +16,3 @@ require_relative "modspec/normative_statements_class"
|
|
|
15
16
|
require_relative "modspec/conformance_test"
|
|
16
17
|
require_relative "modspec/conformance_class"
|
|
17
18
|
require_relative "modspec/suite"
|
|
18
|
-
|
|
19
|
-
require "lutaml/model/xml_adapter/nokogiri_adapter"
|
|
20
|
-
require "lutaml/model/json_adapter/standard_json_adapter"
|
|
21
|
-
require "lutaml/model/toml_adapter/toml_rb_adapter"
|
|
22
|
-
require "lutaml/model/yaml_adapter/standard_yaml_adapter"
|
|
23
|
-
|
|
24
|
-
Lutaml::Model::Config.configure do |config|
|
|
25
|
-
config.xml_adapter = Lutaml::Model::XmlAdapter::NokogiriAdapter
|
|
26
|
-
config.yaml_adapter = Lutaml::Model::YamlAdapter::StandardYamlAdapter
|
|
27
|
-
config.json_adapter = Lutaml::Model::JsonAdapter::StandardJsonAdapter
|
|
28
|
-
config.toml_adapter = Lutaml::Model::TomlAdapter::TomlRbAdapter
|
|
29
|
-
end
|