Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 9 additions & 15 deletions describe.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,9 @@ const baseEnumType = testScl.querySelector("#someID")!;
const diffEnumType = testScl.querySelector("#someDiffID")!;
const equalEnumType = testScl.querySelector("#someOtherID")!;

const baseServer = testScl.querySelector(
`IED[name="IED1"] LDevice[inst="ldInst1"]`,
)!;
const equalServer = testScl.querySelector(
`IED[name="IED2"] LDevice[inst="ldInst2"]`,
)!;
const diffServer = testScl.querySelector(
`IED[name="IED2"] LDevice[inst="ldInst3"]`,
)!;
const baseAP = testScl.querySelector(`IED[name="IED1"]>AccessPoint`)!;
const equalAP = testScl.querySelector(`IED[name="IED2"]>AccessPoint`)!;
const diffAP = testScl.querySelector(`IED[name="IED3"]>AccessPoint`)!;

describe("Describe SCL elements function", () => {
it("returns undefined with missing describe function", () =>
Expand All @@ -176,13 +170,13 @@ describe("Describe SCL elements function", () => {
JSON.stringify(describeSclElement(equalEnumType)),
));

it("returns same description with semantically equal LDevice's", () =>
expect(JSON.stringify(describeSclElement(baseServer))).to.equal(
JSON.stringify(describeSclElement(equalServer)),
it("returns same description with semantically equal AccessPoint's", () =>
expect(JSON.stringify(describeSclElement(baseAP))).to.equal(
JSON.stringify(describeSclElement(equalAP)),
));

it("returns different description with unequal LDevice elements", () =>
expect(JSON.stringify(describeSclElement(baseServer))).to.not.equal(
JSON.stringify(describeSclElement(diffServer)),
it("returns different description with unequal AccessPoint elements", () =>
expect(JSON.stringify(describeSclElement(baseAP))).to.not.equal(
JSON.stringify(describeSclElement(diffAP)),
));
});
5 changes: 4 additions & 1 deletion describe.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AccessPoint, AccessPointDescription } from "./describe/AccessPoint.js";
import { Private, PrivateDescription } from "./describe/Private.js";
import { Text, TextDescription } from "./describe/Text.js";
import { EnumType, EnumTypeDescription } from "./describe/EnumType.js";
Expand All @@ -22,7 +23,8 @@ export type Description =
| LN0Description
| LDeviceDescription
| ServerDescription
| ServicesDescription;
| ServicesDescription
| AccessPointDescription;
const sclElementDescriptors: Partial<
Record<string, (element: Element) => Description | undefined>
> = {
Expand All @@ -37,6 +39,7 @@ const sclElementDescriptors: Partial<
LDevice,
Server,
Services,
AccessPoint,
};

export function describe(element: Element): Description | undefined {
Expand Down
221 changes: 221 additions & 0 deletions describe/AccessPoint.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
import { expect } from "chai";
import { AccessPoint } from "./AccessPoint";

const scl = new DOMParser().parseFromString(
`<SCL xmlns="http://www.iec.ch/61850/2003/SCL" >
<IED name="IED1">
<AccessPoint name="AP1" router="false" clock="false" kdc="false">
<Services />
<Server timeout="30">
<Authentication />
<LDevice inst="lDevice1">
<LN0 lnClass="LLN0" inst="" lnType="LLN0" />
<LN lnClass="MMXU" inst="1" lnType="MMXU" />
<LN lnClass="MMXU" inst="2" lnType="MMXU" />
</LDevice>
<LDevice inst="lDevice2">
<LN0 lnClass="LLN0" inst="" lnType="LLN0" />
<LN lnClass="MMXU" inst="1" lnType="MMXU" />
</LDevice>
<Association iedName="IED3" ldInst="lDevice2" lnClass="LLN0" lnInst="" kind="pre-established" associationId="someId" />
<Association iedName="IED3" ldInst="lDevice2" lnClass="MMXU" lnInst="1" kind="predefined" associationId="someId" />
<Association desc="" iedName="IED3" ldInst="lDevice2" lnClass="MMXU" lnInst="2" kind="predefined" associationId="someId" />
<Association desc="" iedName="IED3" ldInst="lDevice2" lnClass="MMXU" lnInst="2" kind="predefined" associationId="someId" />
</Server>
<ServerAt apName="AP1" />
<GOOSESecurity name="goose1" serialNumber="1" xferNumber="somexfer1" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</GOOSESecurity>
<GOOSESecurity name="goose3" serialNumber="3" xferNumber="somexfer3" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</GOOSESecurity>
<GOOSESecurity name="goose2" serialNumber="2" xferNumber="somexfer2" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</GOOSESecurity>
<SMVSecurity name="smv1" serialNumber="1" xferNumber="somexfer1" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</SMVSecurity>
<SMVSecurity name="smv3" serialNumber="3" xferNumber="somexfer3" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</SMVSecurity>
<SMVSecurity name="smv2" serialNumber="2" xferNumber="somexfer2" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</SMVSecurity>
<SMVSecurity xferNumber="somexfer2" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</SMVSecurity>
<SMVSecurity name="smv13" serialNumber="13" xferNumber="somexfer2" >
<Subject commonName="none" idHierarchy="someId" />
</SMVSecurity>
<SMVSecurity name="14" serialNumber="14" xferNumber="somexfer2" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" />
</SMVSecurity>
</AccessPoint>
</IED>
<IED name="IED2">
<AccessPoint name="AP1">
<Services />
<Server>
<Authentication none="true" password="false" weak="false" strong="false" certificate="false" />
<LDevice inst="lDevice2">
<LN0 lnClass="LLN0" inst="" lnType="LLN0" />
<LN lnClass="MMXU" inst="1" lnType="MMXU" />
</LDevice>
<LDevice inst="lDevice1">
<LN0 lnClass="LLN0" inst="" lnType="LLN0" />
<LN lnClass="MMXU" inst="2" lnType="MMXU" />
<LN lnClass="MMXU" inst="1" lnType="MMXU" />
</LDevice>
<Association iedName="IED3" ldInst="lDevice2" lnClass="MMXU" lnInst="1" />
<Association desc="" iedName="IED3" ldInst="lDevice2" lnClass="MMXU" lnInst="1" kind="predefined" associationId="someId" />
<Association iedName="IED3" ldInst="lDevice2" lnClass="LLN0" lnInst="" kind="pre-established" associationId="someId" />
<Association desc="" iedName="IED3" ldInst="lDevice2" lnClass="MMXU" lnInst="2" kind="predefined" associationId="someId" />
<Association desc="" iedName="IED3" ldInst="lDevice2" lnClass="MMXU" lnInst="2" kind="predefined" associationId="someId" />
</Server>
<ServerAt apName="AP1" />
<GOOSESecurity name="goose3" serialNumber="3" xferNumber="somexfer3" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</GOOSESecurity>
<GOOSESecurity name="goose1" serialNumber="1" xferNumber="somexfer1" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</GOOSESecurity>
<GOOSESecurity name="goose2" serialNumber="2" xferNumber="somexfer2" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</GOOSESecurity>
<GOOSESecurity serialNumber="13" xferNumber="somexfer2" >
<IssuerName commonName="none" idHierarchy="someId" />
</GOOSESecurity>
<GOOSESecurity serialNumber="14" xferNumber="somexfer2" >
<Subject idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</GOOSESecurity>
<SMVSecurity name="smv3" serialNumber="3" xferNumber="somexfer3" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</SMVSecurity>
<SMVSecurity name="smv1" serialNumber="1" xferNumber="somexfer1" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</SMVSecurity>
<SMVSecurity name="smv2" serialNumber="2" xferNumber="somexfer2" >
<Subject commonName="none" idHierarchy="someId" />
<IssuerName commonName="none" idHierarchy="someId" />
</SMVSecurity>
</AccessPoint>
</IED>
<IED name="IED3">
<AccessPoint name="AP1" router="true" clock="true" kdc="true">
<Server timeout="13">
<Authentication none="false" password="true" weak="true" strong="true" certificate="true" />
<LDevice inst="lDevice1">
<LN0 lnClass="LLN0" inst="" lnType="LLN02" />
<LN lnClass="MMXU" inst="2" lnType="MMXU" />
</LDevice>
</Server>
</AccessPoint>
</IED>
<IED name="IED4">
<AccessPoint name="AP1">
<Server timeout="13">
<LDevice inst="lDevice1">
<LN0 lnClass="LLN0" inst="" lnType="LLN02" />
<LN lnClass="MMXU" inst="2" lnType="MMXU" />
</LDevice>
</Server>
</AccessPoint>
</IED>
<IED name="IED5">
<AccessPoint name="AP1">
<LN lnClass="MMXU" inst="1" lnType="invalidType" />
</AccessPoint>
</IED>
<IED name="IED6">
<AccessPoint name="AP1">
<ServerAt />
</AccessPoint>
</IED>
<DataTypeTemplates>
<LNodeType id="LLN0" desc="desc" lnClass="LLN0">
<DO name="Beh" type="BehENS"/>
</LNodeType>
<LNodeType id="MMXU" desc="desc" lnClass="MMXU">
<DO name="A" type="WYE"/>
</LNodeType>
<DOType cdc="ENS" id="BehENS" >
<DA name="stVal" bType="Enum" type="BehModKind" fc="ST" >
<Val>off</Val>
</DA>
</DOType>
<DOType id="WYE" cdc="WYE">
<SDO name="phsA" type="CMV" />
</DOType>
<DOType id="CMV" cdc="CMV" >
<DA name="cVal" bType="Struct" fc="MX" type="Vector"/>
</DOType>
<DAType id="Vector" >
<BDA name="mag" bType="Struct" type="AnalogueValue" />
</DAType>
<DAType id="AnalogueValue" >
<BDA name="f" bType="FLOAT32" >
<Val sGroup="3">60.60</Val>
<Val sGroup="1">10.10</Val>
<Val sGroup="2">40.10</Val>
</BDA>
</DAType>
<EnumType id="BehModKind" >
<EnumVal ord="1">on</EnumVal>
<EnumVal ord="3">test</EnumVal>
<EnumVal ord="5">off</EnumVal>
</EnumType>
</DataTypeTemplates>
</SCL>`,
"application/xml",
);

const baseAP = scl.querySelector('IED[name="IED1"]>AccessPoint')!;
const equalAP = scl.querySelector('IED[name="IED2"]>AccessPoint')!;
const diffAP = scl.querySelector('IED[name="IED3"]>AccessPoint')!;
const invalidAP1 = scl.querySelector('IED[name="IED4"]>AccessPoint')!;
const invalidAP2 = scl.querySelector('IED[name="IED5"]>AccessPoint')!;
const invalidAP3 = scl.querySelector('IED[name="IED6"]>AccessPoint')!;

describe("Description for SCL schema type AccessPoint", () => {
it("returns undefined with invalid Server", () =>
expect(AccessPoint(invalidAP1)).to.be.undefined);

it("return undefined with invalid LN", () =>
expect(AccessPoint(invalidAP2)).to.be.undefined);

it("return undefined with invalid ServerAt", () =>
expect(AccessPoint(invalidAP3)).to.be.undefined);

it("return router attribute defaulting to false", () =>
expect(AccessPoint(baseAP)?.router).to.be.false);

it("return clock attribute defaulting to false", () =>
expect(AccessPoint(baseAP)?.clock).to.be.false);

it("return kdc attribute defaulting to false", () =>
expect(AccessPoint(baseAP)?.kdc).to.be.false);

it("returns same description with semantically equal LDevice's", () =>
expect(JSON.stringify(AccessPoint(baseAP))).to.equal(
JSON.stringify(AccessPoint(equalAP)),
));

it("returns different description with unequal LDevice elements", () =>
expect(JSON.stringify(AccessPoint(baseAP))).to.not.equal(
JSON.stringify(AccessPoint(diffAP)),
));
});
Loading