cactus-test-definitions 1.6.0__py3-none-any.whl

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.

Potentially problematic release.


This version of cactus-test-definitions might be problematic. Click here for more details.

Files changed (139) hide show
  1. cactus_test_definitions/__init__.py +39 -0
  2. cactus_test_definitions/__pycache__/__init__.cpython-312.pyc +0 -0
  3. cactus_test_definitions/__pycache__/actions.cpython-312.pyc +0 -0
  4. cactus_test_definitions/__pycache__/checks.cpython-312.pyc +0 -0
  5. cactus_test_definitions/__pycache__/csipaus.cpython-312.pyc +0 -0
  6. cactus_test_definitions/__pycache__/errors.cpython-312.pyc +0 -0
  7. cactus_test_definitions/__pycache__/events.cpython-312.pyc +0 -0
  8. cactus_test_definitions/__pycache__/parameters.cpython-312.pyc +0 -0
  9. cactus_test_definitions/__pycache__/schema.cpython-312.pyc +0 -0
  10. cactus_test_definitions/__pycache__/test_procedures.cpython-312-pytest-8.3.5.pyc +0 -0
  11. cactus_test_definitions/__pycache__/test_procedures.cpython-312.pyc +0 -0
  12. cactus_test_definitions/__pycache__/variable_expressions.cpython-312.pyc +0 -0
  13. cactus_test_definitions/__pycache__/version.cpython-312.pyc +0 -0
  14. cactus_test_definitions/client/__init__.py +26 -0
  15. cactus_test_definitions/client/__pycache__/__init__.cpython-312.pyc +0 -0
  16. cactus_test_definitions/client/__pycache__/actions.cpython-312.pyc +0 -0
  17. cactus_test_definitions/client/__pycache__/checks.cpython-312.pyc +0 -0
  18. cactus_test_definitions/client/__pycache__/events.cpython-312.pyc +0 -0
  19. cactus_test_definitions/client/__pycache__/test_procedures.cpython-312-pytest-8.3.5.pyc +0 -0
  20. cactus_test_definitions/client/__pycache__/validate.cpython-312.pyc +0 -0
  21. cactus_test_definitions/client/actions.py +98 -0
  22. cactus_test_definitions/client/checks.py +127 -0
  23. cactus_test_definitions/client/events.py +71 -0
  24. cactus_test_definitions/client/procedures/ALL-01.yaml +94 -0
  25. cactus_test_definitions/client/procedures/ALL-02.yaml +113 -0
  26. cactus_test_definitions/client/procedures/ALL-03-REJ.yaml +69 -0
  27. cactus_test_definitions/client/procedures/ALL-03.yaml +110 -0
  28. cactus_test_definitions/client/procedures/ALL-04.yaml +69 -0
  29. cactus_test_definitions/client/procedures/ALL-05.yaml +117 -0
  30. cactus_test_definitions/client/procedures/ALL-06.yaml +128 -0
  31. cactus_test_definitions/client/procedures/ALL-07.yaml +76 -0
  32. cactus_test_definitions/client/procedures/ALL-08.yaml +78 -0
  33. cactus_test_definitions/client/procedures/ALL-09.yaml +111 -0
  34. cactus_test_definitions/client/procedures/ALL-10.yaml +128 -0
  35. cactus_test_definitions/client/procedures/ALL-11.yaml +111 -0
  36. cactus_test_definitions/client/procedures/ALL-12.yaml +108 -0
  37. cactus_test_definitions/client/procedures/ALL-13.yaml +112 -0
  38. cactus_test_definitions/client/procedures/ALL-14.yaml +165 -0
  39. cactus_test_definitions/client/procedures/ALL-15.yaml +109 -0
  40. cactus_test_definitions/client/procedures/ALL-16.yaml +102 -0
  41. cactus_test_definitions/client/procedures/ALL-17.yaml +63 -0
  42. cactus_test_definitions/client/procedures/ALL-18.yaml +288 -0
  43. cactus_test_definitions/client/procedures/ALL-19.yaml +78 -0
  44. cactus_test_definitions/client/procedures/ALL-20.yaml +136 -0
  45. cactus_test_definitions/client/procedures/ALL-21.yaml +203 -0
  46. cactus_test_definitions/client/procedures/ALL-22.yaml +82 -0
  47. cactus_test_definitions/client/procedures/ALL-23.yaml +158 -0
  48. cactus_test_definitions/client/procedures/ALL-24.yaml +132 -0
  49. cactus_test_definitions/client/procedures/ALL-25-EXT.yaml +228 -0
  50. cactus_test_definitions/client/procedures/ALL-25.yaml +136 -0
  51. cactus_test_definitions/client/procedures/ALL-26.yaml +147 -0
  52. cactus_test_definitions/client/procedures/ALL-27.yaml +144 -0
  53. cactus_test_definitions/client/procedures/ALL-28.yaml +274 -0
  54. cactus_test_definitions/client/procedures/ALL-29.yaml +87 -0
  55. cactus_test_definitions/client/procedures/ALL-30.yaml +188 -0
  56. cactus_test_definitions/client/procedures/BES-01.yaml +136 -0
  57. cactus_test_definitions/client/procedures/BES-02.yaml +137 -0
  58. cactus_test_definitions/client/procedures/BES-03.yaml +135 -0
  59. cactus_test_definitions/client/procedures/BES-04.yaml +228 -0
  60. cactus_test_definitions/client/procedures/DRA-01.yaml +54 -0
  61. cactus_test_definitions/client/procedures/DRA-02.yaml +64 -0
  62. cactus_test_definitions/client/procedures/DRD-01.yaml +667 -0
  63. cactus_test_definitions/client/procedures/DRL-01.yaml +327 -0
  64. cactus_test_definitions/client/procedures/GEN-01.yaml +73 -0
  65. cactus_test_definitions/client/procedures/GEN-02.yaml +72 -0
  66. cactus_test_definitions/client/procedures/GEN-03.yaml +160 -0
  67. cactus_test_definitions/client/procedures/GEN-04.yaml +161 -0
  68. cactus_test_definitions/client/procedures/GEN-05.yaml +89 -0
  69. cactus_test_definitions/client/procedures/GEN-06.yaml +90 -0
  70. cactus_test_definitions/client/procedures/GEN-07.yaml +145 -0
  71. cactus_test_definitions/client/procedures/GEN-08.yaml +145 -0
  72. cactus_test_definitions/client/procedures/GEN-09.yaml +117 -0
  73. cactus_test_definitions/client/procedures/GEN-10.yaml +739 -0
  74. cactus_test_definitions/client/procedures/GEN-11.yaml +378 -0
  75. cactus_test_definitions/client/procedures/GEN-12.yaml +378 -0
  76. cactus_test_definitions/client/procedures/GEN-13.yaml +70 -0
  77. cactus_test_definitions/client/procedures/LOA-01.yaml +73 -0
  78. cactus_test_definitions/client/procedures/LOA-02.yaml +73 -0
  79. cactus_test_definitions/client/procedures/LOA-03.yaml +160 -0
  80. cactus_test_definitions/client/procedures/LOA-04.yaml +161 -0
  81. cactus_test_definitions/client/procedures/LOA-05.yaml +89 -0
  82. cactus_test_definitions/client/procedures/LOA-06.yaml +89 -0
  83. cactus_test_definitions/client/procedures/LOA-07.yaml +145 -0
  84. cactus_test_definitions/client/procedures/LOA-08.yaml +145 -0
  85. cactus_test_definitions/client/procedures/LOA-09.yaml +117 -0
  86. cactus_test_definitions/client/procedures/LOA-10.yaml +741 -0
  87. cactus_test_definitions/client/procedures/LOA-11.yaml +378 -0
  88. cactus_test_definitions/client/procedures/LOA-12.yaml +378 -0
  89. cactus_test_definitions/client/procedures/LOA-13.yaml +71 -0
  90. cactus_test_definitions/client/procedures/MUL-01.yaml +92 -0
  91. cactus_test_definitions/client/procedures/MUL-02.yaml +80 -0
  92. cactus_test_definitions/client/procedures/MUL-03.yaml +74 -0
  93. cactus_test_definitions/client/test_procedures.py +185 -0
  94. cactus_test_definitions/client/validate.py +98 -0
  95. cactus_test_definitions/csipaus.py +81 -0
  96. cactus_test_definitions/errors.py +15 -0
  97. cactus_test_definitions/parameters.py +153 -0
  98. cactus_test_definitions/py.typed +0 -0
  99. cactus_test_definitions/schema.py +22 -0
  100. cactus_test_definitions/server/README.md +170 -0
  101. cactus_test_definitions/server/__init__.py +23 -0
  102. cactus_test_definitions/server/__pycache__/__init__.cpython-312.pyc +0 -0
  103. cactus_test_definitions/server/__pycache__/actions.cpython-312.pyc +0 -0
  104. cactus_test_definitions/server/__pycache__/checks.cpython-312.pyc +0 -0
  105. cactus_test_definitions/server/__pycache__/test_procedures.cpython-312-pytest-8.3.5.pyc +0 -0
  106. cactus_test_definitions/server/__pycache__/validate.cpython-312.pyc +0 -0
  107. cactus_test_definitions/server/actions.py +139 -0
  108. cactus_test_definitions/server/checks.py +117 -0
  109. cactus_test_definitions/server/procedures/S-ALL-01.yaml +42 -0
  110. cactus_test_definitions/server/procedures/S-ALL-02.yaml +65 -0
  111. cactus_test_definitions/server/procedures/S-ALL-03.yaml +65 -0
  112. cactus_test_definitions/server/procedures/S-ALL-04.yaml +137 -0
  113. cactus_test_definitions/server/procedures/S-ALL-05.yaml +111 -0
  114. cactus_test_definitions/server/procedures/S-OPT-01.yaml +42 -0
  115. cactus_test_definitions/server/procedures/S-OPT-02.yaml +40 -0
  116. cactus_test_definitions/server/procedures/S-OPT-03.yaml +44 -0
  117. cactus_test_definitions/server/procedures/S-OPT-04.yaml +32 -0
  118. cactus_test_definitions/server/test_procedures.py +122 -0
  119. cactus_test_definitions/server/validate.py +30 -0
  120. cactus_test_definitions/variable_expressions.py +419 -0
  121. cactus_test_definitions-1.6.0.dist-info/METADATA +289 -0
  122. cactus_test_definitions-1.6.0.dist-info/RECORD +139 -0
  123. cactus_test_definitions-1.6.0.dist-info/WHEEL +5 -0
  124. cactus_test_definitions-1.6.0.dist-info/licenses/LICENSE.txt +22 -0
  125. cactus_test_definitions-1.6.0.dist-info/top_level.txt +2 -0
  126. tests/__init__.py +0 -0
  127. tests/unit/__init__.py +0 -0
  128. tests/unit/client/__init__.py +0 -0
  129. tests/unit/client/test_actions.py +72 -0
  130. tests/unit/client/test_checks.py +71 -0
  131. tests/unit/client/test_events.py +36 -0
  132. tests/unit/client/test_test_procedures.py +103 -0
  133. tests/unit/client/test_validate.py +153 -0
  134. tests/unit/server/__init__.py +0 -0
  135. tests/unit/server/test_test_procedures.py +60 -0
  136. tests/unit/server/test_validate.py +62 -0
  137. tests/unit/test_csipaus.py +49 -0
  138. tests/unit/test_parameters.py +197 -0
  139. tests/unit/test_variable_expressions.py +402 -0
@@ -0,0 +1,137 @@
1
+ Description: Support for Multiple End Clients
2
+ Category: Registration
3
+ Classes:
4
+ - A
5
+
6
+ TargetVersions:
7
+ - v1.2
8
+
9
+ Preconditions:
10
+ required_clients:
11
+ - id: CLIENT-A
12
+ - id: CLIENT-B
13
+
14
+ Steps:
15
+ - id: CLIENT-A PRECONDITION
16
+ repeat_until_pass: true
17
+ client: CLIENT-A
18
+ instructions:
19
+ - Create at least 5 DERControls for CLIENT-A
20
+ action:
21
+ type: discovery
22
+ parameters:
23
+ resources:
24
+ - DERControl
25
+ checks:
26
+ - type: end-device
27
+ parameters:
28
+ matches_client: true
29
+ - type: der-control
30
+ parameters:
31
+ minimum_count: 5
32
+
33
+ - id: CLIENT-B PRECONDITION
34
+ repeat_until_pass: true
35
+ client: CLIENT-B
36
+ instructions:
37
+ - Create at least 5 DERControls for CLIENT-B
38
+ action:
39
+ type: discovery
40
+ parameters:
41
+ resources:
42
+ - DERControl
43
+ checks:
44
+ - type: end-device
45
+ parameters:
46
+ matches_client: true
47
+ - type: der-control
48
+ parameters:
49
+ minimum_count: 5
50
+
51
+ - id: CLIENT-A DISCOVER MUPS
52
+ repeat_until_pass: true
53
+ client: CLIENT-A
54
+ instructions:
55
+ - MirrorUsagePoints for CLIENT-A must be initially empty.
56
+ action:
57
+ type: discovery
58
+ parameters:
59
+ resources:
60
+ - MirrorUsagePoint
61
+ checks:
62
+ - type: mirror-usage-point
63
+ parameters:
64
+ matches: false # This will only match an empty list
65
+
66
+ - id: CLIENT-B DISCOVER MUPS
67
+ repeat_until_pass: true
68
+ client: CLIENT-B
69
+ instructions:
70
+ - MirrorUsagePoints for CLIENT-B must be initially empty.
71
+ action:
72
+ type: discovery
73
+ parameters:
74
+ resources:
75
+ - MirrorUsagePoint
76
+ checks:
77
+ - type: mirror-usage-point
78
+ parameters:
79
+ matches: false # This will only match an empty list
80
+
81
+ - id: CLIENT-A CREATE MUPS
82
+ client: CLIENT-A
83
+ action:
84
+ type: upsert-mup
85
+ parameters:
86
+ mup_id: mupa
87
+ location: Device
88
+ reading_types:
89
+ - ActivePowerAverage
90
+ - VoltageSinglePhaseAverage
91
+ checks:
92
+ - type: mirror-usage-point
93
+ parameters:
94
+ matches: true
95
+ location: Device
96
+ reading_types:
97
+ - ActivePowerAverage
98
+ - VoltageSinglePhaseAverage
99
+
100
+ - id: CLIENT-B CREATE MUPS
101
+ client: CLIENT-B
102
+ action:
103
+ type: upsert-mup
104
+ parameters:
105
+ mup_id: mupb
106
+ location: Device
107
+ reading_types:
108
+ - ActivePowerAverage
109
+ - VoltageSinglePhaseAverage
110
+ checks:
111
+ - type: mirror-usage-point
112
+ parameters:
113
+ matches: true
114
+ location: Device
115
+ reading_types:
116
+ - ActivePowerAverage
117
+ - VoltageSinglePhaseAverage
118
+
119
+ - id: CLIENT-A SEND READINGS
120
+ client: CLIENT-A
121
+ action:
122
+ type: insert-readings
123
+ parameters:
124
+ mup_id: mupa
125
+ values:
126
+ ActivePowerAverage: [1000, 1234, 0, -4567]
127
+ VoltageSinglePhaseAverage: [241.1, 232.2, 233.9, 244.1]
128
+
129
+ - id: CLIENT-B SEND READINGS
130
+ client: CLIENT-B
131
+ action:
132
+ type: insert-readings
133
+ parameters:
134
+ mup_id: mupb
135
+ values:
136
+ ActivePowerAverage: [2000, 2234, 0, -8567]
137
+ VoltageSinglePhaseAverage: [243.1, 233.2, 234.9, 240]
@@ -0,0 +1,111 @@
1
+ Description: Authorisation
2
+ Category: Registration
3
+ Classes:
4
+ - A
5
+
6
+ TargetVersions:
7
+ - v1.2
8
+
9
+ Preconditions:
10
+ required_clients:
11
+ - id: CLIENT-A
12
+ client_type: device
13
+ - id: CLIENT-B
14
+ client_type: device
15
+
16
+ Steps:
17
+ - id: (A) PRECONDITION
18
+ repeat_until_pass: true
19
+ client: CLIENT-A
20
+ instructions:
21
+ - Create an EndDevice registration for CLIENT-A (or rerun S-ALL-02 / S-ALL-03).
22
+ action:
23
+ type: discovery
24
+ parameters:
25
+ resources:
26
+ - EndDevice
27
+ - DERControlList
28
+ - DER
29
+ checks:
30
+ - type: end-device
31
+ parameters:
32
+ matches_client: true
33
+
34
+ - id: (B) PRECONDITION
35
+ repeat_until_pass: true
36
+ client: CLIENT-B
37
+ instructions:
38
+ - Create an EndDevice registration for CLIENT-B (or rerun S-ALL-02 / S-ALL-03).
39
+ action:
40
+ type: discovery
41
+ parameters:
42
+ resources:
43
+ - EndDevice
44
+ - DERControlList
45
+ - DER
46
+ checks:
47
+ - type: end-device
48
+ parameters:
49
+ matches_client: true
50
+
51
+ - id: (A-B) AUTH EndDeviceList
52
+ client: CLIENT-A
53
+ use_client_context: CLIENT-B
54
+ action:
55
+ type: refresh-resource
56
+ parameters:
57
+ resource: EndDeviceList
58
+ expect_rejection: true
59
+
60
+ - id: (A-B) AUTH DerControlList
61
+ client: CLIENT-A
62
+ use_client_context: CLIENT-B
63
+ action:
64
+ type: refresh-resource
65
+ parameters:
66
+ resource: DERControlList
67
+ expect_rejection: true
68
+
69
+ - id: (A-B) AUTH DERStatus
70
+ client: CLIENT-A
71
+ use_client_context: CLIENT-B
72
+ action:
73
+ type: upsert-der-status
74
+ parameters:
75
+ genConnectStatus: 1
76
+ expect_rejection: true
77
+
78
+ - id: (A-B) AUTH MirrorUsagePoint
79
+ client: CLIENT-A
80
+ use_client_context: CLIENT-B
81
+ action:
82
+ type: upsert-mup
83
+ parameters:
84
+ expect_rejection: true
85
+ mup_id: mupa
86
+ location: Device
87
+ reading_types:
88
+ - ActivePowerAverage
89
+ - VoltageSinglePhaseAverage
90
+
91
+ - id: (A) OK EndDeviceList
92
+ client: CLIENT-A
93
+ action:
94
+ type: refresh-resource
95
+ parameters:
96
+ resource: EndDeviceList
97
+ checks:
98
+ - type: end-device
99
+ parameters:
100
+ matches_client: true
101
+
102
+ - id: (A) DISALLOW ACCESS
103
+ repeat_until_pass: true
104
+ instructions:
105
+ - Remove EndDevice entry for ClientA (or disallow access).
106
+ client: CLIENT-A
107
+ action:
108
+ type: refresh-resource
109
+ parameters:
110
+ resource: EndDeviceList
111
+ expect_rejection_or_empty: true
@@ -0,0 +1,42 @@
1
+ Description: Discovery Rejecting In-Band Registration
2
+ Category: Registration
3
+ Classes:
4
+ - A
5
+
6
+ TargetVersions:
7
+ - v1.2
8
+
9
+ Preconditions:
10
+ required_clients:
11
+ - id: client
12
+
13
+ Steps:
14
+ - id: PRECONDITION
15
+ repeat_until_pass: true
16
+ instructions:
17
+ - Create an EndDevice registration for client (or rerun S-ALL-02 / S-ALL-03).
18
+ action:
19
+ type: discovery
20
+ parameters:
21
+ resources:
22
+ - DeviceCapability
23
+ - Time
24
+ - MirrorUsagePointList
25
+ - EndDevice
26
+ - DER
27
+ checks:
28
+ - type: end-device # This will be the check that will block UNTIL there is an existing EndDevice registration
29
+ parameters:
30
+ matches_client: true
31
+
32
+ - id: REGISTER AGAIN
33
+ action:
34
+ type: insert-end-device
35
+ parameters:
36
+ expect_rejection: true
37
+ checks:
38
+ - type: end-device
39
+ parameters:
40
+ matches_client: true
41
+
42
+
@@ -0,0 +1,40 @@
1
+ Description: Incorrect Connection Point Registration
2
+ Category: Registration
3
+ Classes:
4
+ - A
5
+
6
+ TargetVersions:
7
+ - v1.2
8
+
9
+ Preconditions:
10
+ required_clients:
11
+ - id: client
12
+
13
+ Steps:
14
+ - id: PRECONDITION
15
+ repeat_until_pass: true
16
+ instructions:
17
+ - Create an EndDevice registration for client (or rerun S-ALL-02 / S-ALL-03).
18
+ action:
19
+ type: discovery
20
+ parameters:
21
+ resources:
22
+ - DeviceCapability
23
+ - Time
24
+ - MirrorUsagePointList
25
+ - EndDevice
26
+ - DER
27
+ checks:
28
+ - type: end-device # This will be the check that will block UNTIL there is an existing EndDevice registration
29
+ parameters:
30
+ matches_client: true
31
+
32
+ - id: SEND BAD CONNECTION POINT ID
33
+ action:
34
+ type: upsert-connection-point
35
+ parameters:
36
+ connectionPointId: NOTAVALIDID
37
+ expect_rejection: true
38
+
39
+
40
+
@@ -0,0 +1,44 @@
1
+ Description: Connection Point Registration
2
+ Category: Registration
3
+ Classes:
4
+ - A
5
+
6
+ TargetVersions:
7
+ - v1.2
8
+
9
+ Preconditions:
10
+ required_clients:
11
+ - id: client
12
+
13
+ Steps:
14
+ - id: PRECONDITION
15
+ repeat_until_pass: true
16
+ instructions:
17
+ - Create an EndDevice registration for client (or rerun S-ALL-02 / S-ALL-03).
18
+ action:
19
+ type: discovery
20
+ parameters:
21
+ resources:
22
+ - DeviceCapability
23
+ - Time
24
+ - MirrorUsagePointList
25
+ - EndDevice
26
+ - DER
27
+ checks:
28
+ - type: end-device # This will be the check that will block UNTIL there is an existing EndDevice registration
29
+ parameters:
30
+ matches_client: true
31
+
32
+ - id: SEND CONNECTION POINT ID
33
+ action:
34
+ type: upsert-connection-point
35
+ parameters:
36
+ connectionPointId: "1234567890" # A valid NMI (in the testing range)
37
+ checks:
38
+ - type: discovered
39
+ parameters:
40
+ links:
41
+ - ConnectionPoint
42
+
43
+
44
+
@@ -0,0 +1,32 @@
1
+ Description: Client Registration and PIN Validation
2
+ Category: Registration
3
+ Classes:
4
+ - A
5
+
6
+ TargetVersions:
7
+ - v1.2
8
+
9
+ Preconditions:
10
+ required_clients:
11
+ - id: client
12
+
13
+ Steps:
14
+ - id: MATCH PIN
15
+ repeat_until_pass: true
16
+ instructions:
17
+ - Create an EndDevice (with RegistrationLink) registration for client (or rerun S-ALL-02 / S-ALL-03).
18
+ action:
19
+ type: discovery
20
+ parameters:
21
+ resources:
22
+ - Registration
23
+ checks:
24
+ - type: end-device # This will be the check that will block UNTIL there is an existing EndDevice registration
25
+ parameters:
26
+ matches_client: true
27
+ matches_pin: true
28
+
29
+
30
+
31
+
32
+
@@ -0,0 +1,122 @@
1
+ from dataclasses import dataclass
2
+ from enum import StrEnum
3
+ from importlib import resources
4
+
5
+ import yaml
6
+ from cactus_test_definitions.csipaus import CSIPAusVersion
7
+ from cactus_test_definitions.schema import UniqueKeyLoader
8
+ from cactus_test_definitions.server.actions import Action
9
+ from cactus_test_definitions.server.checks import Check
10
+ from dataclass_wizard import LoadMeta, YAMLWizard
11
+
12
+
13
+ class TestProcedureId(StrEnum):
14
+ """The set of all available test ID's
15
+
16
+ This should be kept in sync with the current set of test procedures loaded from the procedures directory"""
17
+
18
+ __test__ = False # Prevent pytest from picking up this class
19
+ S_ALL_01 = "S-ALL-01"
20
+ S_ALL_02 = "S-ALL-02"
21
+ S_ALL_03 = "S-ALL-03"
22
+ S_ALL_04 = "S-ALL-04"
23
+ S_ALL_05 = "S-ALL-05"
24
+ S_OPT_01 = "S-OPT-01"
25
+ S_OPT_02 = "S-OPT-02"
26
+ S_OPT_03 = "S-OPT-03"
27
+ S_OPT_04 = "S-OPT-04"
28
+
29
+
30
+ class ClientType(StrEnum):
31
+ DEVICE = "device" # This is a direct device client - i.e. the cert will match a SPECIFIC EndDevice
32
+ AGGREGATOR = "aggregator" # This is an aggregator client - i.e. the cert can manage MANY EndDevices
33
+
34
+
35
+ @dataclass
36
+ class RequiredClient:
37
+ """A RequiredClient is a way for a test to assert that it needs a specific client type or set of clients. The id
38
+ will be used internally within a test to reference a specific client"""
39
+
40
+ id: str # How this client will be referred to within the step's of the test
41
+ client_type: ClientType | None = None # If set - the client type that is required
42
+
43
+
44
+ @dataclass
45
+ class Step:
46
+ """A step is an action for a client to execute and then a series of checks to validate the results. If the action
47
+ raises an exception OR any of the checks fail, this step will marked as failed and the test will be aborted.
48
+
49
+ Actions might represent a single operation or they may represent a series of polls/checks over a period of time.
50
+ """
51
+
52
+ id: str # Descriptive identifier for this step (must be unique)
53
+ action: Action # The action to execute when the step starts
54
+ client: str | None = None # The RequiredClient.id that will execute this step. If None - use the 0th client.
55
+ use_client_context: str | None = (
56
+ None # Specify to allow a request to execute with clientX using the context of clientY
57
+ )
58
+ checks: list[Check] | None = None # The checks (if any) to execute AFTER action completes to determine success
59
+ instructions: list[str] | None = None # Text to display while this step executes
60
+
61
+ repeat_until_pass: bool = False # If True - failing checks will cause this step to re-execute until successful
62
+
63
+
64
+ @dataclass
65
+ class Preconditions:
66
+ """Preconditions are a way of setting up the test / server before the test begins.
67
+
68
+ Instructions are out-of-band information to show until the preconditions are all met.
69
+
70
+ If any checks are required - they will be polled regularly until ALL pass. For each check poll, a discovery
71
+ will be run to ensure data is available.
72
+ """
73
+
74
+ required_clients: list[RequiredClient] # What client(s) need to be supplied to run this test procedure
75
+
76
+
77
+ @dataclass
78
+ class TestProcedure(YAMLWizard):
79
+ """Top level object for collecting everything relevant to a single TestProcedure"""
80
+
81
+ __test__ = False # Prevent pytest from picking up this class
82
+ description: str # Metadata from test definitions
83
+ category: str # Metadata from test definitions
84
+ classes: list[str] # Metadata from test definitions
85
+ target_versions: list[CSIPAusVersion] # What version(s) of csip-aus is this test targeting?
86
+ preconditions: Preconditions
87
+ steps: list[Step] # What behavior will the test procedure be evaluating?
88
+
89
+
90
+ LoadMeta(raise_on_unknown_json_key=True).bind_to(TestProcedure)
91
+
92
+
93
+ def parse_test_procedure(yaml_contents: str) -> TestProcedure:
94
+ """Given a YAML string - parse a TestProcedure.
95
+
96
+ This will ensure the YAML parser will use all the "strict" extensions to reduce the incidence of errors"""
97
+
98
+ return TestProcedure.from_yaml(
99
+ yaml_contents,
100
+ decoder=yaml.load, # type: ignore
101
+ Loader=UniqueKeyLoader,
102
+ )
103
+
104
+
105
+ def get_yaml_contents(test_procedure_id: TestProcedureId) -> str:
106
+ """Finds the YAML contents for the TestProcedure with the specified TestProcedureId"""
107
+ yaml_resource = resources.files("cactus_test_definitions.server.procedures") / f"{test_procedure_id}.yaml"
108
+ with resources.as_file(yaml_resource) as yaml_file:
109
+ with open(yaml_file, "r") as f:
110
+ yaml_contents = f.read()
111
+ return yaml_contents
112
+
113
+
114
+ def get_test_procedure(test_procedure_id: TestProcedureId) -> TestProcedure:
115
+ """Gets the TestProcedure with the nominated ID by loading its definition from disk"""
116
+ yaml_contents = get_yaml_contents(test_procedure_id)
117
+ return parse_test_procedure(yaml_contents)
118
+
119
+
120
+ def get_all_test_procedures() -> dict[TestProcedureId, TestProcedure]:
121
+ """Gets every TestProcedure, keyed by their TestProcedureId"""
122
+ return {tp_id: get_test_procedure(tp_id) for tp_id in TestProcedureId}
@@ -0,0 +1,30 @@
1
+ from cactus_test_definitions.errors import TestProcedureDefinitionError
2
+ from cactus_test_definitions.server.actions import validate_action_parameters
3
+ from cactus_test_definitions.server.checks import validate_check_parameters
4
+ from cactus_test_definitions.server.test_procedures import (
5
+ TestProcedure,
6
+ TestProcedureId,
7
+ )
8
+
9
+
10
+ def validate_test_procedure(test_procedure: TestProcedure, test_procedure_id: TestProcedureId):
11
+ # Check preconditions
12
+ if not test_procedure.preconditions.required_clients:
13
+ raise TestProcedureDefinitionError(
14
+ f"{test_procedure_id} has no RequiredClients element. At least 1 entry required"
15
+ )
16
+ required_clients_by_id = dict(((rc.id, rc) for rc in test_procedure.preconditions.required_clients))
17
+
18
+ for step in test_procedure.steps:
19
+ validate_action_parameters(test_procedure_id, step.id, step.action)
20
+
21
+ # Validate step checks
22
+ if step.checks:
23
+ for check in step.checks:
24
+ validate_check_parameters(test_procedure_id, check)
25
+
26
+ # Ensure client exists
27
+ if step.client is not None and step.client not in required_clients_by_id:
28
+ raise TestProcedureDefinitionError(
29
+ f"{test_procedure_id} reference client {step.client} that isn't listed in RequiredClients."
30
+ )