diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1b43a20857c5fd19de5421b592931db7a423b45b..b4e3df33f5089456fc4d64b9dcd03d40ab38864c 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,13 +1,17 @@
-image: "python:3.7"
-
-before_script:
- - python3 --version
- - pip3 install -q asn1tools lxml xmlschema
-
stages:
- - Check Schemas
+ - check
-checkASN1:
- stage: Check Schemas
+process_asn:
+ image: "mcanterb/asn1test:latest"
+ stage: check
+ interruptible: true
script:
- - python3 testing/check_asn1.py
\ No newline at end of file
+ - python3 testing/asn_process.py
+
+process_xsd:
+ image: "mcanterb/xsdtest:latest"
+ stage: check
+ interruptible: true
+ script:
+ - python3 testing/xsd_process.py
+
diff --git a/102232-1/LI-PS-PDU.asn b/102232-1/LI-PS-PDU.asn
index 25f72fc6b49f91d65a74524745105796e2b7aa78..714ecf85b3130bd500dc922f76ddf0ffba14b2e3 100644
--- a/102232-1/LI-PS-PDU.asn
+++ b/102232-1/LI-PS-PDU.asn
@@ -1,5 +1,5 @@
LI-PS-PDU
-{itu-t(0) identified-organization(4) etsi(0) securityDomain(2) lawfulIntercept(2) li-ps(5) genHeader(1) version32(32)}
+{itu-t(0) identified-organization(4) etsi(0) securityDomain(2) lawfulIntercept(2) li-ps(5) genHeader(1) version33(33)}
DEFINITIONS IMPLICIT TAGS ::=
@@ -34,7 +34,7 @@ IMPORTS
MessagingMMCC,
MessagingIRI
FROM EmailPDU
- {itu-t(0) identified-organization(4) etsi(0) securityDomain(2) lawfulIntercept(2) li-ps(5) email(2) version18(18)}
+ {itu-t(0) identified-organization(4) etsi(0) securityDomain(2) lawfulIntercept(2) li-ps(5) email(2) version19(19)}
-- from ETSI TS 102 232-3 [6]
IPCC,
@@ -54,7 +54,7 @@ IMPORTS
IPMMCC,
IPMMIRI
FROM IPMultimediaPDU
- {itu-t(0) identified-organization(4) etsi(0) securityDomain(2) lawfulIntercept(2) li-ps(5) iPMultimedia(5) version13(13)}
+ {itu-t(0) identified-organization(4) etsi(0) securityDomain(2) lawfulIntercept(2) li-ps(5) iPMultimedia(5) version14(14)}
-- from ETSI TS 102 232-6 [36]
PstnIsdnCC,
@@ -204,7 +204,7 @@ IMPORTS
lawfulInterceptDomainId OBJECT IDENTIFIER ::= {itu-t(0) identified-organization(4) etsi(0) securityDomain(2) lawfulIntercept(2)}
-li-psDomainId OBJECT IDENTIFIER ::= {lawfulInterceptDomainId li-ps(5) genHeader(1) version32(32)}
+li-psDomainId OBJECT IDENTIFIER ::= {lawfulInterceptDomainId li-ps(5) genHeader(1) version33(33)}
-- ====================
-- Top-level definition
@@ -732,4 +732,4 @@ LawfulInterceptionIdentifier ::= LIID
-- module to preserve the original type name during the
-- removal of imports from ETSI TS 101 671 [4].
-END --end of LI-PS-PDU
\ No newline at end of file
+END --end of LI-PS-PDU
diff --git a/102232-2/EmailPDU.asn b/102232-2/EmailPDU.asn
index afedfc6f3179f7f51edb9bdac063bc3de7dda07e..6f8457e3eb2006dddb017b7fa0b2c4727e303f54 100644
--- a/102232-2/EmailPDU.asn
+++ b/102232-2/EmailPDU.asn
@@ -391,7 +391,7 @@ Messaging-Party-Identity ::= CHOICE
{
msisdn [0] OCTET STRING (SIZE (1..9)),
-- MSISDN of the target, encoded in the same format as the AddressString
- -- parameters defined in MAP format 3GPP TS 09.02 [22], clause 17.7.8.
+ -- parameters defined in MAP format 3GPP TS 29.002 [36], clause 17.7.8.
e164-format [1] OCTET STRING (SIZE (1..25)),
-- E.164 address of the node in international format. Coded in the same format as
-- the calling party number parameter of the ISUP (parameter part: EN 300 356 [23])
@@ -541,4 +541,4 @@ Messaging-Property-Requested-Reports ::= ENUMERATED
...
}
-END -- end of EmailPDU
\ No newline at end of file
+END -- end of EmailPDU
diff --git a/102232-4/L2AccessPDU.asn b/102232-4/L2AccessPDU.asn
index df562af6659bca77e854cad9faa9f5e0148ef827..7f18d897c49c6f59feef3002fd3904d1e10e1ce6 100644
--- a/102232-4/L2AccessPDU.asn
+++ b/102232-4/L2AccessPDU.asn
@@ -36,9 +36,9 @@ L2CC ::= SEQUENCE
-- The ethernet protocol is used
...,
l2ATM2684 [6] OCTET STRING,
- -- The protocol RFC 2684, method "LLC Encapsulation for Bridged Protocols` [16] is used
+ -- The protocol RFC 2684, method "LLC Encapsulation for Bridged Protocols" [16] is used
l2FR2427 [7] OCTET STRING
- -- The protocol RFC 2427 “Multiprotocol Interconnect over Frame Relay” [18] is used
+ -- The protocol RFC 2427 "Multiprotocol Interconnect over Frame Relay" [18] is used
}
}
@@ -194,7 +194,7 @@ L2ProtocolInformation ::= ENUMERATED
l2ProtocolATM2684(7),
-- The protocol RFC 2684, method "LLC Encapsulation for Bridged Protocols" [16] is used
l2ProtocolFR2427(8)
- -- The protocol RFC2427 “Multiprotocol Interconnect over Frame Relay” [18] is used
+ -- The protocol RFC2427 "Multiprotocol Interconnect over Frame Relay" [18] is used
}
END -- end of L2AccessPDU
diff --git a/102232-5/IPMultimediaPDU.asn b/102232-5/IPMultimediaPDU.asn
index d70768d6e317678923593920530fc57507fff441..c9408c388c8ff7daea692ce018fd50d67a859397 100644
--- a/102232-5/IPMultimediaPDU.asn
+++ b/102232-5/IPMultimediaPDU.asn
@@ -4,7 +4,7 @@
IPMultimediaPDU
-{itu-t(0) identified-organization(4) etsi(0) securityDomain(2) lawfulIntercept(2) li-ps(5) iPMultimedia(5) version13(13)}
+{itu-t(0) identified-organization(4) etsi(0) securityDomain(2) lawfulIntercept(2) li-ps(5) iPMultimedia(5) version14(14)}
DEFINITIONS IMPLICIT TAGS ::=
BEGIN
@@ -22,8 +22,8 @@ IMPORTS
-- Object Identifier Definition
-- ============================
-iPMMIRIObjId RELATIVE-OID ::= {li-ps(5) iPMultimedia(5) version13(13) iRI(1)}
-iPMMCCObjId RELATIVE-OID ::= {li-ps(5) iPMultimedia(5) version13(13) cC(2)}
+iPMMIRIObjId RELATIVE-OID ::= {li-ps(5) iPMultimedia(5) version14(14) iRI(1)}
+iPMMCCObjId RELATIVE-OID ::= {li-ps(5) iPMultimedia(5) version14(14) cC(2)}
-- both definitions relative to:
-- {itu-t(0) identified-organization(4) etsi(0) securityDomain(2) lawfulIntercept(2)}
@@ -51,7 +51,9 @@ IPMMCC ::= SEQUENCE
-- May contain c= and m= lines extracts for instance
mMCCprotocol [4] MMCCprotocol OPTIONAL
-- Used to identify the protocol of packets sent in MMCCContent (RTP, UDPTL, MSRP, etc.)
- -- Absence means mMCCContents contains RTP/RTCP packets
+ -- Absence means mMCCContents contains RTP/RTCP packets or audio frame as indicated by the
+ -- frameType parameter.
+
}
FrameType ::= ENUMERATED
diff --git a/103120/examples/mutliple-auth-example-request.xml b/103120/examples/mutliple-auth-example-request.xml
index 8fd893c24d5aec216cb2197368892483015204f0..ab1b79ea3216856cd5cde2b9ac99880b43b23b3d 100644
--- a/103120/examples/mutliple-auth-example-request.xml
+++ b/103120/examples/mutliple-auth-example-request.xml
@@ -12,7 +12,7 @@
d442c58c-d5e1-4fd9-90ec-9c228ad947f1
2020-09-22T08:06:17.025833Z
- V1.10.1
+ V1.11.1
XX
v1.1.1
diff --git a/103120/examples/request1.xml b/103120/examples/request1.xml
index a5e40d645c53e549c6002e105a5352b44dbbec47..2479534c73654e0576c1db35cb8a8eafbe6271d9 100644
--- a/103120/examples/request1.xml
+++ b/103120/examples/request1.xml
@@ -12,7 +12,7 @@
c02358b2-76cf-4ba4-a8eb-f6436ccaea2e
2015-09-01T12:00:00.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/request2.xml b/103120/examples/request2.xml
index 2b1d012346c37b7d0b5689aa2fe895b1fa5c393e..582bb6e4b0dae70594ded44c55bad4a6af5a90ef 100644
--- a/103120/examples/request2.xml
+++ b/103120/examples/request2.xml
@@ -12,7 +12,7 @@
45002c1e-dc4a-470a-9152-8e752638c86c
2015-09-01T12:01:00.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/request3.xml b/103120/examples/request3.xml
index dce66207fc39648701cd1673074b547fb02ca5bd..7168d8401745d33330730bd9070055ebe2a41650 100644
--- a/103120/examples/request3.xml
+++ b/103120/examples/request3.xml
@@ -12,7 +12,7 @@
69353ac0-9582-4c71-b162-86259c99de20
2015-09-01T12:02:00.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/request4.xml b/103120/examples/request4.xml
index 73d6c07783352e8bfe3bd8327c2b261196de5e10..9093778542fe2decd848fb7b159525838d898ed9 100644
--- a/103120/examples/request4.xml
+++ b/103120/examples/request4.xml
@@ -12,7 +12,7 @@
c02358b2-76cf-4ba4-a8eb-f6436ccaea2e
2019-09-30T13:37:00.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/request5-Binary-Delivery.xml b/103120/examples/request5-Binary-Delivery.xml
index 2a13dfbbe6b9ad652b8dd8cb82195d8757a49267..27b7f8a83614ebf1913c6c9760736a196930bfe3 100644
--- a/103120/examples/request5-Binary-Delivery.xml
+++ b/103120/examples/request5-Binary-Delivery.xml
@@ -12,7 +12,7 @@
8854cfad-44ac-43b8-99ae-530b690b43da
2019-09-30T13:37:37.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/request5-XML-Delivery.xml b/103120/examples/request5-XML-Delivery.xml
index c345dbbe507c78e3c2b581f5410b964232920437..57b627c5d495284298f3e6d164ea9affd718849b 100644
--- a/103120/examples/request5-XML-Delivery.xml
+++ b/103120/examples/request5-XML-Delivery.xml
@@ -12,7 +12,7 @@
8854cfad-44ac-43b8-99ae-530b690b43da
2019-09-30T13:37:37.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/request6.xml b/103120/examples/request6.xml
index 15a2bf1f259595a8f2c4520a146253429287bcfb..5ff9ed243e3e2ab8da1c4e1f3589cf1d28b10b76 100644
--- a/103120/examples/request6.xml
+++ b/103120/examples/request6.xml
@@ -12,7 +12,7 @@
c02358b2-76cf-4ba4-a8eb-f6436ccaea2f
2021-10-11T13:37:00.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/request6_signed.xml b/103120/examples/request6_signed.xml
index 2bc0404ef924498e7280669c399ac4c430873787..61bbf4399da17ef7ef79681f892bf8f91c09f052 100644
--- a/103120/examples/request6_signed.xml
+++ b/103120/examples/request6_signed.xml
@@ -11,7 +11,7 @@
9964584e-c1a5-4ffa-b949-d9da504c4efb
2021-06-25T12:00:00.000000Z
- V1.9.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/response1.xml b/103120/examples/response1.xml
index 54fad1cea1741d9c2d3fd9e8fac21816b4206551..7a989b9977170a745de48e156c9ddb2e2d3f9fd5 100644
--- a/103120/examples/response1.xml
+++ b/103120/examples/response1.xml
@@ -12,7 +12,7 @@
c02358b2-76cf-4ba4-a8eb-f6436ccaea2e
2015-09-01T12:00:01.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/response2.xml b/103120/examples/response2.xml
index 104a76f5455b7625ca859d4e5cb919d9d6a40b57..a08f8d689d47309315b8671ffb381c5584e2281b 100644
--- a/103120/examples/response2.xml
+++ b/103120/examples/response2.xml
@@ -12,7 +12,7 @@
45002c1e-dc4a-470a-9152-8e752638c86c
2015-09-01T12:01:00.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/response3.xml b/103120/examples/response3.xml
index 445187d48fdb19f46e96cfb813f467c9190d9b01..184967b2f7b43940235d7eeb64ef928c2fe1eb00 100644
--- a/103120/examples/response3.xml
+++ b/103120/examples/response3.xml
@@ -12,7 +12,7 @@
69353ac0-9582-4c71-b162-86259c99de20
2015-09-01T12:02:00.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/response4.xml b/103120/examples/response4.xml
index 3ca45c26bb40c2ab11ec4c7dda7a2490639ad354..3c9f48204be94ed3a05329b0c24f92469294d716 100644
--- a/103120/examples/response4.xml
+++ b/103120/examples/response4.xml
@@ -12,7 +12,7 @@
c02358b2-76cf-4ba4-a8eb-f6436ccaea2e
2019-09-30T13:37:01.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/response5.xml b/103120/examples/response5.xml
index d02dff5149c3ae24115c323f76194bfa70b93677..54572b35ffde7b3ee89b5b11d0e179bf0c8e274e 100644
--- a/103120/examples/response5.xml
+++ b/103120/examples/response5.xml
@@ -17,7 +17,7 @@
8854cfad-44ac-43b8-99ae-530b690b43da
2019-09-30T13:37:37.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/examples/response6.xml b/103120/examples/response6.xml
index 99b0ddc135eb3e7269dab1b19373cf53b8c5b7ef..f5ab20932f9440d9a40772f725162cb45fd197eb 100644
--- a/103120/examples/response6.xml
+++ b/103120/examples/response6.xml
@@ -12,7 +12,7 @@
c02358b2-76cf-4ba4-a8eb-f6436ccaea2f
2021-10-11T13:37:01.000000Z
- V1.10.1
+ V1.11.1
XX
v1.0
diff --git a/103120/schema/ts_103120_Delivery.xsd b/103120/schema/ts_103120_Delivery.xsd
index 5fb2536ca89c68c0bb21a6bb97ecf77bb95fed20..367f0650e3655f9cbd35e3103e303d32346482ec 100644
--- a/103120/schema/ts_103120_Delivery.xsd
+++ b/103120/schema/ts_103120_Delivery.xsd
@@ -27,7 +27,7 @@
-
+
@@ -39,7 +39,7 @@
-
+
@@ -59,7 +59,7 @@
-
+
@@ -73,6 +73,7 @@
+
@@ -80,5 +81,5 @@
-
+
diff --git a/103120/schema/ts_103120_Document.xsd b/103120/schema/ts_103120_Document.xsd
index af6f13979824aba2c967860b1473bc7df91fac32..499e1cde702e82a7973113efe028d53039c5248d 100644
--- a/103120/schema/ts_103120_Document.xsd
+++ b/103120/schema/ts_103120_Document.xsd
@@ -53,6 +53,7 @@
+
diff --git a/103221-1/TS_103_221_01.xsd b/103221-1/TS_103_221_01.xsd
index 490e9c4eb68f36c6bb328608b07571c4edf1ff71..fcf37429e6453e24f1b80306bfec941a67bd14cc 100644
--- a/103221-1/TS_103_221_01.xsd
+++ b/103221-1/TS_103_221_01.xsd
@@ -1,5 +1,5 @@
-
+
@@ -107,6 +107,7 @@
+
@@ -299,6 +300,7 @@
+
@@ -922,4 +924,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/103221-1/TS_103_221_01_DestinationSet.xsd b/103221-1/TS_103_221_01_DestinationSet.xsd
new file mode 100644
index 0000000000000000000000000000000000000000..1bdcb98121179e30fb9899187955b904bf928f48
--- /dev/null
+++ b/103221-1/TS_103_221_01_DestinationSet.xsd
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/103221-1/examples/CreateDestinationSet_example.xml b/103221-1/examples/CreateDestinationSet_example.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c1388b42c301ea02e20d21e36d6d156f25f736fc
--- /dev/null
+++ b/103221-1/examples/CreateDestinationSet_example.xml
@@ -0,0 +1,88 @@
+
+
+
+ admfID
+ neID
+ 2022-02-16T18:46:21.247432Z
+ v1.11.1
+ 7fa872e0-4bc7-4a98-a416-5f22b3de1dca
+
+ 44b739c4-73f0-48d5-8d6a-3576ab100141
+ X2andX3
+
+
+
+ 203.0.113.1
+
+
+ 9999
+
+
+
+
+
+
+ admfID
+ neID
+ 2022-02-16T18:46:21.247432Z
+ v1.11.1
+ 8286e40c-0b4b-4d4c-94f0-1e7ab8489e44
+
+ 36adec69-e0f0-4a41-8e85-66bbe12c5a60
+ X2andX3
+
+
+
+ 203.0.113.2
+
+
+ 9999
+
+
+
+
+
+
+ admfID
+ neID
+ 2022-02-16T18:46:21.247432Z
+ v1.11.1
+ 7afbf8e3-7699-4008-ac1a-4475ed50c14b
+
+ 30fbde5e-3195-4a22-b3e9-15e1d60d0528
+ My First Destination Set
+
+
+ 44b739c4-73f0-48d5-8d6a-3576ab100141
+ 1
+
+
+ 36adec69-e0f0-4a41-8e85-66bbe12c5a60
+ 2
+
+
+ Redundant
+
+
+
+ admfID
+ neID
+ 2022-02-16T18:46:21.247432Z
+ v1.11.1
+ 4afef6be-5252-41cb-9275-123d308deb50
+
+ 1d7d7eb7-e0b9-4a5c-827a-bc3639d48124
+
+
+ 6125550123
+
+
+ X2andX3
+
+ 30fbde5e-3195-4a22-b3e9-15e1d60d0528
+
+
+
+
diff --git a/103221-1/examples/DeleteAllObjectsRequest_example.xml b/103221-1/examples/DeleteAllObjectsRequest_example.xml
new file mode 100644
index 0000000000000000000000000000000000000000..86b1650e2bb80cd0b33c36b27b3aded365ed1893
--- /dev/null
+++ b/103221-1/examples/DeleteAllObjectsRequest_example.xml
@@ -0,0 +1,10 @@
+
+
+
+ admfID
+ neID
+ 2022-01-20T14:04:20.123456Z
+ v1.11.1
+ 5775af53-a4a0-46ab-818a-86a406a335a1
+
+
diff --git a/103221-1/examples/DeleteAllObjectsResponse_example.xml b/103221-1/examples/DeleteAllObjectsResponse_example.xml
new file mode 100644
index 0000000000000000000000000000000000000000..596d5189e03c23070fdd65bfae286c365addb068
--- /dev/null
+++ b/103221-1/examples/DeleteAllObjectsResponse_example.xml
@@ -0,0 +1,11 @@
+
+
+
+ admfID
+ neID
+ 2022-01-20T14:04:20.123456Z
+ v1.11.1
+ 5775af53-a4a0-46ab-818a-86a406a335ac
+ AcknowledgedAndCompleted
+
+
diff --git a/103221-1/examples/desktop.ini b/103221-1/examples/desktop.ini
deleted file mode 100644
index 8b699c692d358fa29d7ac0976e524fe25c5da053..0000000000000000000000000000000000000000
Binary files a/103221-1/examples/desktop.ini and /dev/null differ
diff --git a/103280/TS_103_280.xsd b/103280/TS_103_280.xsd
index d6d91c5cca5b344d4a62035e515531407f180d38..3ff4ae13e53186ed51828193f383337448c8e3a1 100644
--- a/103280/TS_103_280.xsd
+++ b/103280/TS_103_280.xsd
@@ -1,5 +1,5 @@
-
+
@@ -246,4 +246,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/103707/TS_103_707.xsd b/103707/TS_103_707.xsd
index 7bce63dbbddf26c259af57022ea51f89f2a12c04..f9e6da158f77ea324effb2a1b519d5e57f7b88ad 100644
--- a/103707/TS_103_707.xsd
+++ b/103707/TS_103_707.xsd
@@ -3,7 +3,7 @@
xmlns:etsi103280="http://uri.etsi.org/03280/common/2017/07"
xmlns="http://uri.etsi.org/03707/2020/02"
targetNamespace="http://uri.etsi.org/03707/2020/02"
- version="1.4.1"
+ version="1.5.1"
elementFormDefault="qualified">
diff --git a/103707/examples/example_multiple_items.xml b/103707/examples/example_multiple_items.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6913c2ba2d454193c7f5c95df3500df657f849b1
--- /dev/null
+++ b/103707/examples/example_multiple_items.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+ target@example.com
+
+ true
+
+
+
+
+ someoneelse@example.com
+
+
+
+ 2021-06-17T06:42:23.000000+01:00
+
+
+
+
+ http://FooServiceSchema.example.com/schema/v1.1.1/
+
+
+
+ Foo
+ Bar
+ Baz
+
+
+
+
+
+
+
+
+
+
+
+
+ someoneelse@example.com
+
+
+
+
+
+ target@example.com
+
+ true
+
+
+ 2021-06-18T06:42:23.000000+01:00
+
+
+
+
+ http://FooServiceSchema.example.com/schema/v1.1.1/
+
+
+
+ Foo
+ Bar
+ Baz
+
+
+
+
+
+
+
+
diff --git a/testing/asn_compile_targets.json b/testing/asn_compile_targets.json
new file mode 100644
index 0000000000000000000000000000000000000000..e186addc0214f2ecf1f25f507336f33725fafe2f
--- /dev/null
+++ b/testing/asn_compile_targets.json
@@ -0,0 +1,33 @@
+[
+ [
+ "./102232-1/LI-PS-PDU.asn",
+ "./103280/TS_103_280.asn1",
+ "./testing/deps/33128/TS33128Payloads.asn",
+ "./testing/deps/33108/Three3gppHI1Notifications.asn",
+ "./testing/deps/33108/UMTSHI2Operations.asn",
+ "./testing/deps/33108/UMTSHI3PS.asn",
+ "./testing/deps/33108/EpsHI3PS.asn",
+ "./testing/deps/33108/ConfHI3IMS.asn",
+ "./testing/deps/33108/VoipHI3IMS.asn",
+ "./testing/deps/33108/GCSEHI3.asn",
+ "./testing/deps/33108/CSVoiceHI3IP.asn",
+ "./testing/deps/33108/UMTSCSHI2Operations.asn",
+ "./testing/deps/33108/EpsHI2Operations.asn",
+ "./testing/deps/33108/ConfHI2Operations.asn",
+ "./testing/deps/33108/ProSeHI2Operations.asn",
+ "./testing/deps/33108/GCSEHI2Operations.asn",
+ "./testing/deps/101671/HI1NotificationOperations,ver7.asn",
+ "./testing/deps/101671/HI2Operations,ver18.asn",
+ "./testing/deps/101909/TS101909201.asn",
+ "./testing/deps/101909/TS101909202.asn",
+ "./testing/deps/101909/PCESP.asn",
+ "./testing/deps/301040/06132v203_C01.asn",
+ "./103462/ILHIPDU.asn",
+ "./102232-2/EmailPDU.asn",
+ "./102232-3/IPAccessPDU.asn",
+ "./102232-4/L2AccessPDU.asn",
+ "./102232-5/IPMultimediaPDU.asn",
+ "./102232-6/PstnIsdnPDU.asn"
+ ],
+ ["./102657/RDMessage.asn"]
+]
\ No newline at end of file
diff --git a/testing/asn_ignore.txt b/testing/asn_ignore.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2d81d205c4e0a24ce60da75c4e11e6fd0bae44cb
--- /dev/null
+++ b/testing/asn_ignore.txt
@@ -0,0 +1,2 @@
+deps
+temp
\ No newline at end of file
diff --git a/testing/asn_ignore_lint.txt b/testing/asn_ignore_lint.txt
new file mode 100644
index 0000000000000000000000000000000000000000..03e7f54e7937f1cf45bf259cef700a7624bf6912
--- /dev/null
+++ b/testing/asn_ignore_lint.txt
@@ -0,0 +1 @@
+dependencies
\ No newline at end of file
diff --git a/testing/asn_process.py b/testing/asn_process.py
new file mode 100644
index 0000000000000000000000000000000000000000..aa0a0a63777202d29ee51587ffdafb760c360560
--- /dev/null
+++ b/testing/asn_process.py
@@ -0,0 +1,206 @@
+import logging
+import json
+from pathlib import Path
+from subprocess import run
+from re import sub
+
+from pycrate_asn1c.asnproc import *
+
+def reconstrainInteger (filename):
+ Path('temp.asn').write_text(Path(filename).read_text().replace("18446744073709551615", "65536"))
+ return 'temp.asn'
+
+filesWithBigInts = [
+ '102232-1/LI-PS-PDU.asn',
+ '102232-3/IPAccessPDU.asn',
+ '102232-4/L2AccessPDU.asn'
+]
+
+def syntaxCheckASN (fileList):
+ """
+ Performs ASN syntax checking on a list of filenames (or pathlib Paths)
+
+ :param fileList: List of filenames (str or Pathlib Path)
+ :returns: Dict with result, return code and message for each filename
+
+ Calls the open-source asn1c compiler with the "syntax only" option.
+ As a result, asn1c must be available to run.
+ """
+ results = {}
+ for file in fileList:
+ try:
+ if file.as_posix() in filesWithBigInts:
+ newFile = reconstrainInteger(str(file))
+ p = run(['asn1c', '-E', newFile], capture_output=True)
+ Path(newFile).unlink()
+ else:
+ p = run(['asn1c', '-E', str(file)], capture_output=True)
+ if (p.returncode != 0):
+ errorMessage = p.stderr.decode().splitlines()[0]
+ if errorMessage.startswith(' Value "18446744073709551615" at line'):
+ results[str(file)] = { 'ok' : True}
+ continue
+ results[str(file)] = {
+ 'ok' : False,
+ 'code' : p.returncode,
+ 'message' : p.stderr.decode().splitlines()[0]
+ }
+ else:
+ results[str(file)] = {
+ 'ok' : True
+ }
+ except Exception as ex:
+ results[str(file)] = {
+ 'ok' : False,
+ 'code' : -1,
+ 'message' : f"{ex!r}"
+ }
+ return results
+
+
+duplicateObjects = {
+ '102232-1/LI-PS-PDU.asn' : [
+ 'CCPayload',
+ 'IRIPayload',
+ 'Location'
+ ],
+ 'testing/mod1.asn' : [
+ 'ClashField'
+ ]
+}
+def fixDuplicateObjects(filename):
+ stringContent = filename.read_text()
+ for object in duplicateObjects[filename.as_posix()]:
+ stringContent = stringContent.replace(f'{object} ::=', f'Native{object} ::=')
+ stringContent = stringContent.replace(f'SEQUENCE OF {object}', f'SEQUENCE OF Native{object}')
+ #stringContent = sub(f"]\\w{object}", f"] Native{object}", stringContent)
+
+ Path('temp.asn').write_text(stringContent)
+ return 'temp.asn'
+
+
+def compileAllTargets (compileTargets):
+ """
+ Attempts to compile a set of compile targets using the pycrate ASN1 tools
+
+ :param compileTargets: list of compile targets, each of which is a list of filenames
+ :returns: A dict of outcome against the first filename of each compile target. Return code and message are included for failures.
+
+ For each compile target (list of filenames) the first filename is assumed
+ to be the "primary" file. This doesn't have any relavance to the compilation,
+ but will be used as the identifier when reporting any compile errors.
+ The compilation is performed by the pycrate ASN compile functions; errors
+ are caught as exceptions and rendered into a list.
+
+ Unfortunately, the pycrate compiler doesn't report line numbers.
+ The asn1c compiler does, but doesn't properly handle identifiers with the
+ same name in different modules; as this occurs multiple times in TS 33.108,
+ we can't use it.
+ """
+ results = {}
+ for target in compileTargets:
+ firstTarget = target[0]
+ logging.debug(f"Compiling {firstTarget}")
+ try:
+ fileTexts = []
+ fileNames = []
+ GLOBAL.clear()
+ for filename in target:
+ pFile = Path(filename)
+ if pFile.as_posix() in duplicateObjects:
+ tmpFile = Path(fixDuplicateObjects(pFile))
+ fileTexts.append(tmpFile.read_text())
+ #tmpFile.unlink()
+ else:
+ fileTexts.append(pFile.read_text())
+ fileNames.append(filename)
+ logging.debug (f" Loading {filename}")
+ compile_text(fileTexts, filenames = fileNames)
+ results[str(firstTarget)] = {
+ 'ok' : True,
+ }
+ except Exception as ex:
+ results[str(firstTarget)] = {
+ 'ok' : False,
+ 'code' : -1,
+ 'message' : f"{ex!r}"
+ }
+ continue
+ return results
+
+
+
+def processResults (results, stageName):
+ """
+ Counts the number of errors and writes out the output per filename
+
+ :param results: List of filenames (str or Pathlib Path)
+ :param stageName: Name to decorate the output with
+ :returns: The number of files which had errors
+ """
+ print("")
+ errorCount = sum([1 for r in results.values() if not r['ok']])
+ logging.info(f"{errorCount} {stageName} errors encountered")
+
+ print(f"{'-':-<60}")
+ print(f"{stageName} results:")
+ print(f"{'-':-<60}")
+ for filename, result in results.items():
+ print(f" {filename:.<55}{'..OK' if result['ok'] else 'FAIL'}")
+ if not result['ok']:
+ if isinstance(result['message'], list):
+ for thing in result['message']:
+ print(f" {thing['message']}")
+ else:
+ print(f" {result['message']}")
+
+ print(f"{'-':-<60}")
+ print(f"{stageName} errors: {errorCount}")
+ print(f"{'-':-<60}")
+
+ return errorCount
+
+
+if __name__ == '__main__':
+ logging.info('Searching for ASN.1 files')
+ fileList = list(Path(".").rglob("*.asn1")) + list(Path(".").rglob("*.asn"))
+ logging.info(f'{len(fileList)} ASN.1 files found')
+ for file in fileList:
+ logging.debug(f' {file}')
+
+ ignoreList = Path('testing/asn_ignore.txt').read_text().splitlines()
+ ignoredFiles = []
+ for ignore in ignoreList:
+ logging.debug(f'Ignoring pattern {ignore}')
+ for file in fileList:
+ if ignore in str(file):
+ ignoredFiles.append(file)
+ logging.debug(f" Ignoring {str(file)} as contains {ignore}")
+ ignoredFiles = list(set(ignoredFiles))
+ logging.info(f'{len(ignoredFiles)} files ignored')
+ for file in ignoredFiles:
+ logging.debug(f' {file}')
+
+ fileList = [file for file in fileList if file not in ignoredFiles]
+ logging.info(f'{len(fileList)} files to process')
+ for file in fileList:
+ logging.debug(f' {file}')
+
+ if len(fileList) == 0:
+ logging.warning ("No files specified")
+ exit(0)
+
+ logging.info("Parsing ASN1 files")
+ parseResults = syntaxCheckASN(fileList)
+ if processResults(parseResults, "Parsing") > 0:
+ exit(-1)
+
+ logging.info ("Getting compile targets")
+ compileTargets = json.loads(Path('testing/asn_compile_targets.json').read_text())
+ logging.info (f"{len(compileTargets)} compile targets found")
+
+ compileResults = compileAllTargets(compileTargets)
+ if processResults(compileResults, "Compiling") > 0:
+ exit(-1)
+
+ exit(0)
diff --git a/testing/check_asn1.py b/testing/check_asn1.py
deleted file mode 100644
index c87a22619f847248a1281a18356dbbfcbfaf6a13..0000000000000000000000000000000000000000
--- a/testing/check_asn1.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import logging
-from compile_asn import *
-
-
-if __name__ == '__main__':
- log = logging.getLogger()
- log.setLevel(logging.INFO)
- parseErrors, compileErrors, parser = validateAllASN1FilesInPath("./")
- parseErrorCount = 0
- print ("ASN.1 Parser checks:")
- print ("-----------------------------")
- for filename, errors in parseErrors.items():
- if len(errors) > 0:
- parseErrorCount += len(errors)
- print (f"{filename}: {len(errors)} errors")
- for error in errors:
- print (" " + str(error))
- else:
- print (f"{filename}: OK")
- print ("-----------------------------")
- print ("ASN.1 Compilation:")
- print ("-----------------------------")
- if len(compileErrors) > 0:
- for error in compileErrors:
- print (" " + str(error))
- else:
- print ("Compilation OK")
- print ("-----------------------------")
- print (f"{parseErrorCount} parse errors, {len(compileErrors)} compile errors")
- exit (parseErrorCount + len(compileErrors))
-
diff --git a/testing/check_xsd.py b/testing/check_xsd.py
deleted file mode 100644
index 816e3898aa2305c476a665b32c14237c82c22c3d..0000000000000000000000000000000000000000
--- a/testing/check_xsd.py
+++ /dev/null
@@ -1,194 +0,0 @@
-import logging
-
-import glob
-import sys
-import argparse
-from pathlib import Path
-from pprint import pprint
-import os
-
-from lxml import etree
-from xml.etree.ElementTree import ParseError
-from xmlschema import XMLSchema, XMLSchemaParseError
-
-def BuildSchemaDictonary (fileList):
- if len(fileList) == 0:
- logging.info("No schema files provided")
- return []
-
- logging.info("Schema locations:")
- schemaLocations = []
- for schemaFile in fileList:
- try:
- xs = XMLSchema(schemaFile, validation='skip')
- schemaLocations.append((xs.target_namespace, str(Path(schemaFile).resolve())))
- logging.info(" [ {0} -> {1} ]".format(xs.default_namespace, schemaFile))
- except ParseError as ex:
- logging.warning (" [ {0} failed to parse: {1} ]".format(schemaFile, ex))
- return schemaLocations
-
-
-def BuildSchema (coreFile, fileList = None):
- schemaLocations = []
- if fileList and len(fileList) > 0:
- schemaLocations = BuildSchemaDictonary(fileList)
-
- coreSchema = XMLSchema(str(Path(coreFile)), locations=schemaLocations)
- return coreSchema
-
-def ValidateSingleFile (schemaFile):
- try:
- xs = XMLSchema(schemaFile, validation='skip')
- except ParseError as ex:
- logging.warning (" [ {0} failed to parse: {1} ]".format(schemaFile, ex))
- return ex
- return None
-
-
-def ValidateXSDFiles (fileList):
- if len(fileList) == 0:
- logging.info("No schema files provided")
- return {}
-
- schemaLocations = BuildSchemaDictonary(fileList)
- errors = {}
- schemaDictionary = {}
-
- logging.info("Schema validation:")
- for schemaFile in fileList:
- try:
- schema = XMLSchema(schemaFile, locations = schemaLocations)
- logging.info(schemaFile + ": OK")
- errors[schemaFile] = []
- schemaDictionary[schema.target_namespace] = schema
- except XMLSchemaParseError as ex:
- if (ex.schema_url) and (ex.schema_url != ex.origin_url):
- logging.info(" Error {1} comes from {0}, suppressing".format(ex.schema_url, ex.message))
- errors[schemaFile] = []
- else:
- logging.warning(schemaFile + ": Failed validation ({0})".format(ex))
- errors[schemaFile] = [ex.message]
- return errors, schemaDictionary
-
-
-def ValidateInstanceDocuments (coreFile, supportingSchemas, instanceDocs):
- if (instanceDocs is None) or len(instanceDocs) == 0:
- logging.warning ("No instance documents provided")
- return []
-
- schema = BuildSchema(coreFile, supportingSchemas)
- errors = []
- for instanceDoc in instanceDocs:
- try:
- schema.validate(instanceDoc)
- logging.info ("{0} passed validation".format(instanceDoc))
- except Exception as ex:
- logging.error ("{0} failed validation: {1}".format(instanceDoc, ex))
- return errors
-
-
-
-if __name__ == '__main__':
- parser = argparse.ArgumentParser()
- parser.add_argument("-v", "--verbosity", help="verbosity level", action="count", default=0)
- parser.add_argument("input", help="include a directory or file", action="append", nargs="+")
- parser.add_argument("-p", "--primaryNamespace", help="Primary schema namespace for instance doc validation")
- args = parser.parse_args()
-
- logging.getLogger().setLevel(logging.WARNING)
- if (args.verbosity >= 1):
- logging.getLogger().setLevel(logging.INFO)
- if (args.verbosity >= 2):
- logging.getLogger().setLevel(logging.DEBUG)
- logging.debug("Very verbose selected")
-
-
- logging.debug(f"Path: {args.input}")
- includeFileList = []
- includeInstanceDocList = []
- for path in args.input[0]:
- p = Path(path)
- if not p.exists():
- logging.error(f"Include path {path} not found")
- exit(1)
- if p.is_dir():
- logging.debug(f"Expanding directory")
- for g in glob.glob(os.path.join(str(p), "*.xsd")):
- logging.info(f">Including {g}")
- includeFileList.append(g)
- for g in glob.glob(os.path.join(str(p), "*.xml")):
- logging.info(f">Including instance doc {g}")
- includeInstanceDocList.append(g)
- else:
- logging.info(f">Including {p.absolute()}")
- if str(p.absolute()).endswith('.xml'):
- includeInstanceDocList.append(str(p.absolute()))
- elif str(p.absolute()).endswith('.xsd'):
- includeFileList.append(str(p.absolute()))
- else:
- logging.warning(f'Ignoring file {p.absolute()}')
-
- if len(includeInstanceDocList) and (args.primaryNamespace is None):
- print("Cannot validate instance documents without specifying a primary namespace (use -h for usage guidelines)")
- exit(-1)
-
- syntaxErrors = 0
-
- print ("=============================")
- print ("XSD syntax checks:")
- print ("-----------------------------")
- for file in includeFileList:
- error = ValidateSingleFile(file)
- if (error):
- print (f" {file} : Syntax error [{error}]")
- syntaxErrors += 1
- else:
- print (f" {file} : OK")
-
- print ("-----------------------------")
- if (syntaxErrors > 0):
- print (f"{syntaxErrors} syntax errors detected")
- exit(syntaxErrors)
- else:
- print ("0 syntax errors detected")
-
- results, schemaDict = ValidateXSDFiles(includeFileList)
-
- print ("=============================")
- print ("XSD build checks:")
- print ("-----------------------------")
- errorCount = 0
- for fileName, errors in results.items():
- if len(errors) > 0:
- errorCount += len(errors)
- print (f" {fileName}: {len(errors)} errors")
- for error in errors:
- if isinstance(error, XMLSchemaParseError):
- print (error.msg)
- else:
- print (f" {str(error.strip())}")
- else:
- print (f" {fileName}: OK")
-
- print ("-----------------------------")
- print (f"{errorCount} build errors detected")
- if (errorCount > 0):
- exit(errorCount)
-
- print ("=============================")
- print ("Instance document checks")
- print ("-----------------------------")
- errorCount = 0
-
- primarySchema = schemaDict[args.primaryNamespace]
- for instanceDoc in includeInstanceDocList:
- try:
- results = primarySchema.validate(instanceDoc)
- print (f" {instanceDoc} : OK")
- except Exception as ex:
- errorCount += 1
- print (f" {instanceDoc} : {str(ex)}")
- print ("-----------------------------")
- print (f"{errorCount} instance doc errors detected")
- print ("=============================")
- exit(errorCount)
diff --git a/testing/compile_asn.py b/testing/compile_asn.py
deleted file mode 100644
index e291e42d4077915416bbabba5be97db1cbb7ed50..0000000000000000000000000000000000000000
--- a/testing/compile_asn.py
+++ /dev/null
@@ -1,140 +0,0 @@
-import logging
-import copy
-from asn1tools import parse_files, compile_dict, ParseError, CompileError
-from glob import glob
-from pathlib import Path
-from pprint import pprint
-
-def parseASN1File (asnFile):
- try:
- parse_files(asnFile)
- except ParseError as ex:
- return [ex]
- return []
-
-
-def parseASN1Files (fileList):
- if len(fileList) == 0:
- logging.warning ("No files specified")
- return {}
- errors = {}
- logging.info("Parsing files...")
- for f in fileList:
- ex = parseASN1File(f)
- if ex:
- logging.info (f" {f}: Failed - {ex!r}")
- else:
- logging.info (f" {f}: OK")
- errors[f] = ex
- return errors
-
-def fixDottedReference (dict, importingModule, importingType, importingMember, importedModule, importedType):
- newName = importedModule + "_" + importedType
- dict[importedModule]['types'][newName] = copy.deepcopy(dict[importedModule]['types'][importedType])
- dict[importingModule]['imports'][importedModule].append(newName)
- member = [x for x in dict[importingModule]['types'][importingType]['members'] if x is not None and x['name'] == importingMember][0]
- member['type'] = newName
-
-def compileASN1Files (fileList):
- logging.info("Compiling files...")
- errors = []
- imports = {}
-
- #p = re.compile(r"]\s+\S+\.\S+")
- #for f in fileList:
- # with open(f) as fh:
- # s = fh.read()
- # for match in p.findall(s):
- # print (f"In {f}: {match}")
- #exit()
-
- try:
- dr = parse_files(fileList)
- for modulename, module in dr.items():
- # Weird fix because the compiler doesn't like RELATIVE-OID as a type
- # Not sure if the on-the-wire encoding would be affected or not
- # but for most checking purposes this doesn't matter
- module['types']["RELATIVE-OID"] = {'type' : 'OBJECT IDENTIFIER'}
- for k,v in module['imports'].items():
- if not k in imports:
- imports[k] = []
- imports[k].append({
- "in" : modulename,
- "types" : v
- })
- for k,v in imports.items():
- if not k in dr.keys():
- importers = [i['in'] for i in v]
- errors.append(f"Unsatisfied import [{k}] for {importers}")
-
- fixDottedReference(dr, 'LI-PS-PDU', 'Location', 'umtsHI2Location', 'UmtsHI2Operations', 'Location')
- fixDottedReference(dr, 'LI-PS-PDU', 'Location', 'epsLocation', 'EpsHI2Operations', 'Location')
- fixDottedReference(dr, 'LI-PS-PDU', 'Location', 'eTSI671HI2Location', 'HI2Operations', 'Location')
-
- fixDottedReference(dr, 'LI-PS-PDU', 'UMTSIRI', 'iRI-Parameters', 'UmtsHI2Operations', 'IRI-Parameters')
- fixDottedReference(dr, 'LI-PS-PDU', 'UMTSIRI', 'iRI-CS-Parameters', 'UmtsCS-HI2Operations', 'IRI-Parameters')
- fixDottedReference(dr, 'LI-PS-PDU', 'ETSI671IRI', 'iRI-Parameters', 'HI2Operations', 'IRI-Parameters')
- fixDottedReference(dr, 'LI-PS-PDU', 'EPSIRI', 'iRI-EPS-Parameters', 'EpsHI2Operations', 'IRI-Parameters')
- fixDottedReference(dr, 'LI-PS-PDU', 'ConfIRI', 'iRI-Conf-Parameters', 'CONFHI2Operations', 'IRI-Parameters')
- fixDottedReference(dr, 'LI-PS-PDU', 'ProSeIRI', 'iRI-ProSe-Parameters', 'ProSeHI2Operations', 'IRI-Parameters')
- fixDottedReference(dr, 'LI-PS-PDU', 'GcseIRI', 'iRI-Gcse-Parameters', 'GCSEHI2Operations', 'IRI-Parameters')
-
- fixDottedReference(dr, 'LI-PS-PDU', 'CCContents', 'tTRAFFIC-1', 'TS101909201', 'TTRAFFIC')
- fixDottedReference(dr, 'LI-PS-PDU', 'CCContents', 'cTTRAFFIC-1', 'TS101909201', 'CTTRAFFIC')
- fixDottedReference(dr, 'LI-PS-PDU', 'CCContents', 'tTRAFFIC-2', 'TS101909202', 'TTRAFFIC')
- fixDottedReference(dr, 'LI-PS-PDU', 'CCContents', 'cTTRAFFIC-2', 'TS101909202', 'CTTRAFFIC')
- #fixDottedReference(dr, 'LI-PS-PDU', 'CCContents', 'cCIPPacketHeader', 'CDMA2000CCModule', 'CCIPPacketHeader')
- fixDottedReference(dr, 'LI-PS-PDU', 'CCContents', 'uMTSCC-CC-PDU', 'Umts-HI3-PS', 'CC-PDU')
- fixDottedReference(dr, 'LI-PS-PDU', 'CCContents', 'ePSCC-CC-PDU', 'Eps-HI3-PS', 'CC-PDU')
- fixDottedReference(dr, 'LI-PS-PDU', 'CCContents', 'confCC-CC-PDU', 'CONF-HI3-IMS', 'Conf-CC-PDU')
- fixDottedReference(dr, 'LI-PS-PDU', 'CCContents', 'voipCC-CC-PDU', 'VoIP-HI3-IMS', 'Voip-CC-PDU')
- fixDottedReference(dr, 'LI-PS-PDU', 'CCContents', 'gcseCC-CC-PDU', 'GCSE-HI3', 'Gcse-CC-PDU')
- fixDottedReference(dr, 'LI-PS-PDU', 'CCContents', 'cSvoice-CC-PDU', 'CSvoice-HI3-IP', 'CSvoice-CC-PDU')
-
- fixDottedReference(dr, 'LI-PS-PDU', 'IRIContents', 'tARGETACTIVITYMONITOR-1', 'TS101909201', 'TARGETACTIVITYMONITOR-1')
- fixDottedReference(dr, 'LI-PS-PDU', 'IRIContents', 'tARGETACTIVITYMONITOR-2', 'TS101909202', 'TARGETACTIVITYMONITOR')
- #fixDottedReference(dr, 'LI-PS-PDU', 'IRIContents', 'lAESProtocol', 'Laesp-j-std-025-b', 'LAESProtocol')
- #fixDottedReference(dr, 'LI-PS-PDU', 'IRIContents', 'cDMA2000LAESMessage', 'CDMA2000CIIModule', 'CDMA2000LAESMessage')
-
- fixDottedReference(dr, 'LI-PS-PDU', 'HI4Payload', 'threeGPP-LI-Notification', 'TS33128Payloads', 'LINotificationPayload')
-
- fixDottedReference(dr, 'ILHIPDU', 'TimestampMapping', 'timeStampQualifier', 'LI-PS-PDU', 'TimeStampQualifier')
-
- fixDottedReference(dr, 'ILHIPDU', 'ILHITimestamp', 'qualifiedDateTime', 'Common-Parameters', 'QualifiedDateTime')
- fixDottedReference(dr, 'ILHIPDU', 'ILHITimestamp', 'qualifiedMicrosecondDateTime', 'Common-Parameters', 'QualifiedMicrosecondDateTime')
-
- fixDottedReference(dr, 'ILHIPDU', 'OriginalTimestamp', 'microSecondTimeStamp', 'LI-PS-PDU', 'MicroSecondTimeStamp')
-
- fixDottedReference(dr, 'ILHIPDU', 'LocationMapping', 'originalLocation', 'LI-PS-PDU', 'Location')
-
- fixDottedReference(dr, 'ILHIPDU', 'GeocodedLocationData', 'wGS84CoordinateDecimal', 'Common-Parameters', 'WGS84CoordinateDecimal')
- fixDottedReference(dr, 'ILHIPDU', 'GeocodedLocationData', 'wGS84CoordinateAngular', 'Common-Parameters', 'WGS84CoordinateAngular')
-
- c = compile_dict(dr)
- except CompileError as ex:
- logging.info (f"Compiler error: {ex}")
- errors.append(ex)
- return errors, None
- except ParseError as ex:
- logging.info (f"Parse error: {ex}")
- errors.append(ex)
- return errors, None
- logging.info ("Compiled OK")
- return errors, c
-
-
-def validateASN1Files (fileList):
- parseErrors = parseASN1Files(fileList)
- errorCount = sum([len(v) for k,v in parseErrors.items()])
- if errorCount > 0:
- logging.info ("Abandoning compile due to parse errors")
- return parseErrors, [], None
- compileErrors, parser = compileASN1Files(fileList)
- return parseErrors, compileErrors, parser
-
-
-def validateAllASN1FilesInPath (path):
- p = Path(path)
- fileGlob = [str(f) for f in p.rglob('*.asn')]
- fileGlob += [str(f) for f in p.rglob('*.asn1')]
- return validateASN1Files(fileGlob)
\ No newline at end of file
diff --git a/testing/deps/301040/06132v203_C01.asn b/testing/deps/301040/06132v203_C01.asn
index 56305a2033eb1305d0b89a5d14d9443f3b7a361f..30c32121a5f83b5ce70fa71d29289f9fea022837 100644
--- a/testing/deps/301040/06132v203_C01.asn
+++ b/testing/deps/301040/06132v203_C01.asn
@@ -56,9 +56,9 @@ LISTATUSind ::= SEQUENCE
TARGETACTIVITYMONITORind ::= SEQUENCE
{
- tLIInstanceid TLIIdType, -- header, who –
- timestamp UTCTime, -- header, when –
- targetLocation LocationType, -- header, where –
+ tLIInstanceid TLIIdType, -- header, who
+ timestamp UTCTime, -- header, when
+ targetLocation LocationType, -- header, where
targetAction ActivityType,
supplementaryTargetaddress AddressType OPTIONAL,
cotargetaddress SEQUENCE OF AddressType OPTIONAL,
@@ -178,16 +178,16 @@ TETRAAddressType ::= CHOICE
{
tETRAaddress TSIType,
pISNaddress NumericString (SIZE (20)),
- iP4address BIT STRING (SIZE (32)), -- 32 bits –
- iP6address BIT STRING (SIZE (128)), -- 128 bits –
+ iP4address BIT STRING (SIZE (32)), -- 32 bits
+ iP6address BIT STRING (SIZE (128)), -- 128 bits
e164address NumericString (SIZE (20)),
tEI TEIType
}
-CellIdType ::= BIT STRING (SIZE (16)) -- 16 bits –
+CellIdType ::= BIT STRING (SIZE (16)) -- 16 bits
-LocationAreaType ::= BIT STRING (SIZE (14)) -- 14 bits, as defined in ETS 300 392-2 –
+LocationAreaType ::= BIT STRING (SIZE (14)) -- 14 bits, as defined in ETS 300 392-2
LocationType ::= CHOICE
{
@@ -196,11 +196,11 @@ LocationType ::= CHOICE
}
-MCCType ::= BIT STRING (SIZE (10)) -- 10 bits, as defined in ETS 300 392-1 –
+MCCType ::= BIT STRING (SIZE (10)) -- 10 bits, as defined in ETS 300 392-1
-MNCType ::= BIT STRING (SIZE (14)) -- 14 bits, as defined in ETS 300 392-1 –
+MNCType ::= BIT STRING (SIZE (14)) -- 14 bits, as defined in ETS 300 392-1
-SSIType ::= BIT STRING (SIZE (24)) -- 24 bits, as defined in ETS 300 392-1 –
+SSIType ::= BIT STRING (SIZE (24)) -- 24 bits, as defined in ETS 300 392-1
CircuitIdType ::= NumericString (SIZE (20))
@@ -255,7 +255,7 @@ TETRACGIType ::= SEQUENCE
cI CellIdType OPTIONAL
}
-TLIIdType ::= BIT STRING (SIZE (16)) -- 16 bits –
+TLIIdType ::= BIT STRING (SIZE (16)) -- 16 bits
TSIType ::= SEQUENCE
{
@@ -264,6 +264,6 @@ TSIType ::= SEQUENCE
ssi SSIType
}
-TEIType ::= BIT STRING (SIZE (60)) -- 60 bits, as defined in ETS 300 392-1 –
+TEIType ::= BIT STRING (SIZE (60)) -- 60 bits, as defined in ETS 300 392-1
END
diff --git a/testing/dockerfile_asn b/testing/dockerfile_asn
new file mode 100644
index 0000000000000000000000000000000000000000..2a4198b43ab2d126a9db22fc372a3b1dbee8e4e5
--- /dev/null
+++ b/testing/dockerfile_asn
@@ -0,0 +1,11 @@
+# docker build -t mcanterb/asn1test
+# docker push mcanterb/asn1test
+
+FROM python:3.9-slim-bullseye
+RUN apt-get update -y && \
+ apt-get install -y asn1c && \
+ rm -rf /var/lib/apt/lists/* && \
+ pip install --no-cache-dir asn1tools pycrate
+
+
+
diff --git a/testing/dockerfile_xsd b/testing/dockerfile_xsd
new file mode 100644
index 0000000000000000000000000000000000000000..9ceeee360715afa316f1fc9dd060a6c301015cb6
--- /dev/null
+++ b/testing/dockerfile_xsd
@@ -0,0 +1,10 @@
+# docker build -t mcanterb/xsdtest
+# docker push mcanterb/xsdtest
+
+FROM python:3.9-slim-bullseye
+RUN apt-get update -y && \
+ rm -rf /var/lib/apt/lists/* && \
+ pip install --no-cache-dir lxml xmlschema
+
+
+
diff --git a/testing/merge_test.py b/testing/merge_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..b7a82b39c4958ea30d4ac9a96e100e3041fe73c0
--- /dev/null
+++ b/testing/merge_test.py
@@ -0,0 +1,68 @@
+import os
+import pprint
+import requests
+import json
+import subprocess
+
+crCommitBranch = os.environ.get("CI_COMMIT_REF_NAME", "NOTFOUND")
+apiUrl = os.environ.get("CI_API_V4_URL", "https://forge.3gpp.org/rep/api/v4")
+projectId = os.environ.get("CI_PROJECT_ID", "13")
+
+def gapi (query):
+ url = f"{apiUrl}/projects/{projectId}/{query}"
+ r = requests.get(url)
+ return json.loads(r.text)
+
+def do (commandline):
+ #print (" Attempting: " + commandline)
+ completedProc = subprocess.run(commandline, capture_output=True, shell=True)
+ #print (" STDOUT > " + ("empty" if completedProc.stdout is None else completedProc.stdout.decode('utf-8')))
+ #print (" STDERR > " + ("empty" if completedProc.stderr is None else completedProc.stderr.decode('utf-8')))
+ #print (f" Completed with code {completedProc.returncode}")
+ return (completedProc.returncode == 0, completedProc.stdout.decode('utf-8'))
+
+print ("Searching for corresponding MR...")
+
+mrs = gapi(f"merge_requests?source_branch={crCommitBranch}&state=opened")
+if len(mrs) == 0:
+ print ("No MR found... aborting")
+ exit()
+
+if len(mrs) > 1:
+ print (f"{len(mrs)} MRs found, 1 expected - aborting")
+ for m in mrs:
+ pprint.pprint(m)
+ exit(-1)
+
+mr = mrs[0]
+
+print (f"Found MR {mr['reference']} ({mr['title']})")
+print (f"Target branch is {mr['target_branch']}")
+print ("Searching for open MRs targeting same branch...")
+
+mrs = gapi(f"merge_requests?target_branch={mr['target_branch']}&state=opened")
+mrs = [m for m in mrs if m['reference'] != mr['reference']]
+print (f"{len(mrs)} MRs found")
+
+mergeConflicts = {}
+
+for mr in mrs:
+ source_branch = mr['source_branch']
+ print (source_branch)
+
+ try:
+ do(f"git fetch origin {source_branch}:{source_branch}")
+ success, errStr = do(f"git merge --no-commit {source_branch}")
+ if not success:
+ print ("Merge NOT OK")
+ mergeConflicts[source_branch] = errStr
+ else:
+ print ("Merge OK")
+ except Exception as ex:
+ mergeConflicts[source_branch] = str(ex)
+ raise
+ finally:
+ do("git merge --abort")
+
+print (f"Merge conflicts with following branches: {mergeConflicts}")
+exit(len(mergeConflicts.keys()))
\ No newline at end of file
diff --git a/testing/xsd_compile_targets.json b/testing/xsd_compile_targets.json
new file mode 100644
index 0000000000000000000000000000000000000000..69ad1b50881635e0b2aa86dd159dc1110217da5e
--- /dev/null
+++ b/testing/xsd_compile_targets.json
@@ -0,0 +1,49 @@
+[
+ {
+ "coreSchema" : "102657/RDMessage.xsd",
+ "supportingSchemas" : [],
+ "exampleFiles" : []
+ },
+ {
+ "coreSchema" : "103280/TS_103_280.xsd",
+ "supportingSchemas" : [],
+ "exampleFiles" : []
+ },
+ {
+ "coreSchema" : "103221-1/TS_103_221_01.xsd",
+ "supportingSchemas" : [
+ "103221-1/TS_103_221_01.xsd",
+ "103221-1/TS_103_221_01_HashedID.xsd",
+ "103221-1/TS_103_221_01_DestinationSet.xsd",
+ "103280/TS_103_280.xsd",
+ "103221-1/examples/ExampleGenericObjects.xsd"
+ ],
+ "exampleFiles" : [
+ "103221-1/examples"
+ ]
+ },
+ {
+ "coreSchema" : "103120/dictionaries/ts_103120_Dictionaries.xsd",
+ "supportingSchemas" : [],
+ "exampleFiles" : [
+ "103120/dictionaries/ts_103120_ETSIDictionaryDefinitions.xml"
+ ]
+ },
+ {
+ "coreSchema" : "103120/schema/ts_103120_Core.xsd",
+ "supportingSchemas" : [
+ "103120/schema/ts_103120_Authorisation.xsd",
+ "103120/schema/ts_103120_Common.xsd",
+ "103120/schema/ts_103120_Delivery.xsd",
+ "103120/schema/ts_103120_Document.xsd",
+ "103120/schema/ts_103120_Notification.xsd",
+ "103120/schema/ts_103120_Task.xsd",
+ "103280/TS_103_280.xsd",
+ "testing/deps/xmldsig/xmldsig-core-schema.xsd",
+ "103120/examples/FooServiceSchema.xsd"
+ ],
+ "exampleFiles" : [
+ "103120/examples"
+ ]
+ }
+]
\ No newline at end of file
diff --git a/testing/xsd_ignore.txt b/testing/xsd_ignore.txt
new file mode 100644
index 0000000000000000000000000000000000000000..90bfe5d59c3b61099ed6685d7ddd6023be91efe5
--- /dev/null
+++ b/testing/xsd_ignore.txt
@@ -0,0 +1,3 @@
+deps
+portal
+temp
\ No newline at end of file
diff --git a/testing/xsd_process.py b/testing/xsd_process.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0efd07b5b43db84e9797e965c8e06d4d213e5b9
--- /dev/null
+++ b/testing/xsd_process.py
@@ -0,0 +1,222 @@
+import json
+import logging
+from pathlib import Path
+
+from xmlschema.etree import etree_tostring
+from xmlschema import XMLSchema, XMLSchemaParseError
+
+
+def BuildSchemaDictonary (fileList):
+ if len(fileList) == 0:
+ logging.info("No schema files provided")
+ return []
+
+ logging.info("Schema locations:")
+ schemaLocations = []
+ for schemaFile in fileList:
+ try:
+ xs = XMLSchema(schemaFile, validation='skip')
+ schemaLocations.append((xs.default_namespace, str(Path(schemaFile).resolve())))
+ logging.info(" [ {0} -> {1} ]".format(xs.default_namespace, schemaFile))
+ except XMLSchemaParseError as ex:
+ logging.warning (" [ {0} failed to parse: {1} ]".format(schemaFile, ex))
+ return schemaLocations
+
+
+def BuildSchema (coreFile, fileList = None):
+ schemaLocations = []
+ if fileList and len(fileList) > 0:
+ schemaLocations = BuildSchemaDictonary(fileList)
+
+ coreSchema = XMLSchema(str(Path(coreFile)), locations=schemaLocations)
+ return coreSchema
+
+
+def ValidateXSDFiles (fileList):
+ if len(fileList) == 0:
+ logging.info("No schema files provided")
+ return {}
+
+ schemaLocations = BuildSchemaDictonary(fileList)
+ errors = {}
+
+ logging.info("Schema validation:")
+ for schemaFile in fileList:
+ try:
+ schema = XMLSchema(schemaFile, locations = schemaLocations, validation="lax")
+ logging.info(schemaFile + ": OK")
+ errors[schemaFile] = [f"{etree_tostring(e.elem, e.namespaces, ' ', 20)} - {e.message}" for e in schema.all_errors]
+ except XMLSchemaParseError as ex:
+ logging.warning(schemaFile + ": Failed validation ({0})".format(ex.message))
+ if (ex.schema_url) and (ex.schema_url != ex.origin_url):
+ logging.warning(" Error comes from {0}, suppressing".format(ex.schema_url))
+ errors[schemaFile] = []
+ else:
+ errors[schemaFile] = [ex]
+ return errors
+
+
+def ValidateAllXSDFilesInPath (path):
+ schemaGlob = [str(f) for f in Path(path).rglob("*.xsd")]
+ return ValidateXSDFiles(schemaGlob)
+
+
+def ValidateInstanceDocuments (coreFile, supportingSchemas, instanceDocs):
+ if (instanceDocs is None) or len(instanceDocs) == 0:
+ logging.warning ("No instance documents provided")
+ return []
+
+ schema = BuildSchema(coreFile, supportingSchemas)
+ errors = []
+ for instanceDoc in instanceDocs:
+ try:
+ schema.validate(instanceDoc)
+ logging.info ("{0} passed validation".format(instanceDoc))
+ except Exception as ex:
+ logging.error ("{0} failed validation: {1}".format(instanceDoc, ex))
+ return errors
+
+
+def processResults (results, stageName):
+ """
+ Counts the number of errors and writes out the output per filename
+
+ :param results: List of filenames (str or Pathlib Path)
+ :param stageName: Name to decorate the output with
+ :returns: The number of files which had errors
+ """
+ print("")
+ errorCount = sum([1 for r in results.values() if not r['ok']])
+ logging.info(f"{errorCount} {stageName} errors encountered")
+
+ print(f"{'-':-<60}")
+ print(f"{stageName} results:")
+ print(f"{'-':-<60}")
+ for filename, result in results.items():
+ print(f" {filename:.<55}{'..OK' if result['ok'] else 'FAIL'}")
+ if not result['ok']:
+ if isinstance(result['message'], list):
+ for thing in result['message']:
+ print(f" {thing['message']}")
+ else:
+ print(f" {result['message']}")
+
+ print(f"{'-':-<60}")
+ print(f"{stageName} errors: {errorCount}")
+ print(f"{'-':-<60}")
+
+ return errorCount
+
+
+def syntaxCheckXSD (fileList):
+ results = {}
+ for file in fileList:
+ try:
+ logging.info(f"Syntax checking {str(file)}")
+
+ schema = XMLSchema(str(file), validation="skip")
+ results[str(file)] = {
+ 'ok' : len(schema.all_errors) == 0,
+ 'message' : None if len(schema.all_errors) == 0 else [{'message' : f"{etree_tostring(e.elem, e.namespaces, ' ', 20)} - {e.message}"} for e in schema.all_errors]
+ }
+ except XMLSchemaParseError as ex:
+ logging.warning(str(file) + ": Failed validation ({0})".format(ex.message))
+ results[str(file)] = {
+ 'ok' : False,
+ 'message' : f"{ex!r}"
+ }
+ return results
+
+
+if __name__ == '__main__':
+ #logging.basicConfig(level=logging.DEBUG)
+
+ compileTargets = json.loads(Path('testing/xsd_compile_targets.json').read_text())
+ results = {}
+ for target in compileTargets:
+ coreFile = target['coreSchema']
+ logging.info(f"Attempting to compile {coreFile}")
+ schemaLocations = []
+ for supportSchema in target['supportingSchemas']:
+ logging.debug(f"Adding supporting schema {supportSchema}")
+ try:
+ xs = XMLSchema(supportSchema, validation='skip')
+ schemaLocations.append((xs.target_namespace, str(Path(supportSchema).resolve())))
+ logging.info(" [ {0} -> {1} ]".format(xs.default_namespace, supportSchema))
+ except Exception as ex:
+ logging.warning (" [ {0} exception parsing: {1} ]".format(supportSchema, ex))
+ results[coreFile] = {
+ 'ok' : False,
+ 'message' : f"{ex!r}"
+ }
+ break
+ try:
+ schema = XMLSchema(coreFile, locations = schemaLocations, validation="strict")
+ results[coreFile] = {
+ 'ok' : len(schema.all_errors) == 0,
+ 'message' : None if len(schema.all_errors) == 0 else [{'message' : f"{etree_tostring(e.elem, e.namespaces, ' ', 20)} - {e.message}"} for e in schema.all_errors]
+ }
+ target["schemaInstance"] = schema
+ except Exception as ex:
+ results[coreFile] = {
+ 'ok' : False,
+ 'message' : f"{ex!r}"
+ }
+ continue
+
+ if (processResults(results, "Compile") > 0):
+ exit(-1)
+
+ results = {}
+
+ for target in compileTargets:
+ schema = target["schemaInstance"]
+ testResults = {}
+ failureCount = 0
+ logging.info (f"Validating example {len(target['exampleFiles'])} entries for {target['coreSchema']}")
+ for example in target["exampleFiles"]:
+ examplePath = Path(example)
+ if examplePath.is_dir():
+ logging.debug (f"Expanding {str(examplePath)}")
+ testFiles = list(examplePath.rglob("./*.xml"))
+ else:
+ testFiles = [examplePath]
+ logging.debug(f"Found {len(testFiles)} test files")
+ for test in testFiles:
+ logging.debug(f"Validating {str(test)} against schema")
+ try:
+ errors = list(schema.iter_errors(str(test)))
+ testResults[test] = [f"{etree_tostring(e.elem, e.namespaces, ' ', 20)} - {e.message}" for e in errors]
+ failureCount += len(errors)
+ except Exception as ex:
+ testResults[test] = [f"{ex!r}"]
+ failureCount += 1
+ results[target['coreSchema']] = {
+ 'ok' : failureCount == 0,
+ 'testResults' : testResults,
+ 'failureCount' : failureCount
+ }
+
+ print(f"{'-':-<75}")
+ print(f"Validation results:")
+ print(f"{'-':-<75}")
+
+ totalErrors = 0
+ for filename, result in results.items():
+ if len(result['testResults']) == 0:
+ print (f"{filename:.<70}SKIP (0)")
+ continue
+ else:
+ print (f"{filename:.<70}{'..OK' if result['ok'] else 'FAIL'} ({len(result['testResults'])})")
+ totalErrors += result['failureCount']
+ if result['failureCount'] > 0:
+ for testFile, testResult in result['testResults'].items():
+ print(f" {str(testFile):.<65}{'..OK' if len(testResult) == 0 else 'FAIL'}")
+ for tr in testResult:
+ print(f" {tr}")
+
+ print(f"{'-':-<75}")
+ print(f"Validation errors: {totalErrors}")
+ print(f"{'-':-<75}")
+
+ exit(totalErrors > 0)