• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

node-opcua / node-opcua / 22636309940

03 Mar 2026 06:03PM UTC coverage: 92.756% (+1.9%) from 90.81%
22636309940

push

github

erossignon
test: disable ENOENT on overlapping trustCertificate invocations in test environments with concurrency tests

18684 of 22141 branches covered (84.39%)

23 of 37 new or added lines in 1 file covered. (62.16%)

5775 existing lines in 228 files now uncovered.

160668 of 173216 relevant lines covered (92.76%)

875869.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.52
/packages/node-opcua-status-code/source/opcua_status_code.ts
1
/**
2✔
2
 * @module node-opcua-status-code
2✔
3
 */
2✔
4
// tslint:disable:no-bitwise
2✔
5

2✔
6
import { assert } from "node-opcua-assert";
2✔
7
import { BinaryStream, OutputBinaryStream } from "node-opcua-binary-stream";
2✔
8

2✔
UNCOV
9
function warnLog(...args: [any?, ...any[]]) {
×
10
    /* c8 ignore next */
2✔
11
    // tslint:disable-next-line:no-console
2✔
UNCOV
12
    console.warn(...args);
×
UNCOV
13
}
×
14

2✔
15
/**
2✔
16
 * StatusCode Special bits
2✔
17
 */
2✔
18
export const extraStatusCodeBits: { [key: string]: number } = {
2✔
19
    /**
2✔
20
     *  **StructureChanged** 15:15
2✔
21
     *   Indicates that the structure of the associated data value has changed since the last
2✔
22
     *   Notification.
2✔
23
     *  - Clients should not process the data value unless they re-read the metadata.
2✔
24
     *  - Servers shall set this bit if the DataTypeEncoding used for a Variable changes.
2✔
25
     *  - Servers shall also set this bit if the EnumStrings Property of the DataType of the Variable changes.
2✔
26
     *  - This bit is provided to warn Clients that parse complex data values that their parsing
2✔
27
     *    routines could fail because the serialized form of the data value has changed.
2✔
28
     *  - This bit has meaning only for StatusCodes returned as part of a data change Notification
2✔
29
     *    or the HistoryRead. StatusCodes used in other contexts shall always set this bit to zero.
2✔
30
     */
2✔
31
    StructureChanged: 0x1 << 15,
2✔
32

2✔
33
    /**
2✔
34
     * **SemanticsChanged** 14:14  Semantics of the associated data value have changed. Clients should not process the data
2✔
35
     *   value until they re-read the metadata associated with the Variable.
2✔
36
     * - Servers should set this bit if the metadata has changed in way that could cause application errors if the
2✔
37
     * - Client does not re-read the metadata. For example, a change to the engineering units
2✔
38
     *   could create problems if the Client uses the value to perform calculations.
2✔
39
     * - Part 8 defines the conditions where a Server shall set this bit for a DA Variable.
2✔
40
     * - Other specifications may define additional conditions.
2✔
41
     * - A Server may define other conditions that cause this bit to be set. This bit has meaning only for StatusCodes returned as part of a data change Notification
2✔
42
     *   or the HistoryRead. StatusCodes used in other contexts shall always set this bit to zero.
2✔
43
     */
2✔
44
    SemanticChanged: 0x1 << 14,
2✔
45

2✔
46
    // Reserved         12:13  Reserved for future use. Shall always be zero.
2✔
47

2✔
48
    /**
2✔
49
     * **InfoType**         10:11
2✔
50
     * The type of information contained in the info bits. These bits have the following meanings:
2✔
51
     *
2✔
52
     * | Meaning                           |value | description|
2✔
53
     * |-----------------------------------|------|----------------------------------------------------|
2✔
54
     * |                         NotUsed   | 00   | The info bits are not used and shall be set to zero. |
2✔
55
     * |                         DataValue | 01   | The StatusCode and its info bits are associated with a data value returned from the Server. This flag is only used in combination with StatusCodes defined in Part 8. |
2✔
56
     * |                         Reserved  |1X    | Reserved for future use. The info bits shall be ignored.|
2✔
57
     */
2✔
58
    InfoTypeDataValue: 0x1 << 10, // 0x0400,
2✔
59

2✔
60
    // InfoBits         0:9    Additional information bits that qualify the StatusCode.
2✔
61
    //                         The structure of these bits depends on the Info Type field.
2✔
62
    //
2✔
63
    // LimitBits        8:9    The limit bits associated with the data value. The limits bits have the
2✔
64
    //                         following meanings:
2✔
65
    //                         Limit     Bits   Description
2✔
66
    //                         None      00     The value is free to change.
2✔
67
    //                         Low       01     The value is at the lower limit for the data source.
2✔
68
    //                         High      10     The value is at the higher limit for the data source.
2✔
69
    //                         Constant  11     The value is constant and cannot change.
2✔
70
    LimitLow: 0x1 << 8,
2✔
71

2✔
72
    LimitHigh: 0x2 << 8,
2✔
73

2✔
74
    LimitConstant: 0x3 << 8,
2✔
75

2✔
76
    /**
2✔
77
     * **Overflow**         7:7
2✔
78
     * - This bit shall only be set if the MonitoredItem queue size is greater than 1.
2✔
79
     * - If this bit is set, not every detected change has been returned since the Server’s
2✔
80
     *  queue buffer for the MonitoredItem reached its limit and had to purge out data.
2✔
81
     *
2✔
82
     */
2✔
83
    Overflow: 0x1 << 7, // 1 << 7
2✔
84

2✔
85
    // Reserved         5:6    Reserved for future use. Shall always be zero.
2✔
86

2✔
87
    // HistorianBits    0:4    These bits are set only when reading historical data. They indicate where the data value
2✔
88
    //                         came from and provide information that affects how the Client uses the data value.
2✔
89
    //                         The historian bits have the following meaning:
2✔
90
    //                         Raw            XXX00      A raw data value.
2✔
91
    //                         Calculated     XXX01      A data value which was calculated.
2✔
92
    //                         Interpolated   XXX10      A data value which was interpolated.
2✔
93
    //                         Reserved       XXX11      Undefined.
2✔
94
    //                         Partial        XX1XX      A data value which was calculated with an incomplete interval.
2✔
95
    //                         Extra Data     X1XXX      A raw data value that hides other data at the same timestamp.
2✔
96
    //                         Multi Value    1XXXX      Multiple values match the Aggregate criteria (i.e. multiple
2✔
97
    //                                                   minimum values at different timestamps within the same interval).
2✔
98
    //                         Part 11 describes how these bits are used in more detail.
2✔
99

2✔
100
    /** historical data contains a data value which was calculated. */
2✔
101
    HistorianCalculated: 0x1 << 0,
2✔
102

2✔
103
    /** historical data contains a data value which was interpolated. */
2✔
104
    HistorianInterpolated: 0x2 << 0,
2✔
105

2✔
106
    /** historical data contains a data value which was calculated with an incomplete interval. */
2✔
107
    HistorianPartial: 0x1 << 2,
2✔
108

2✔
109
    /** historical data contains a raw data value that hides other data at the same timestamp. */
2✔
110
    HistorianExtraData: 0x1 << 3,
2✔
111

2✔
112
    /** Multiple values match the Aggregate criteria (i.e. multiple minimum values at different timestamps within the same interval). */
2✔
113
    HistorianMultiValue: 0x1 << 4
2✔
114
};
2✔
115

2✔
116
/**
2✔
117
 * a particular StatusCode , with it's value , name and description
2✔
118
 */
2✔
119

2✔
120
export abstract class StatusCode {
2✔
121
    /**
2✔
122
     *  returns a status code that can be modified
2✔
123
     */
2✔
124
    public static makeStatusCode(statusCode: StatusCode | string, optionalBits: string | number): StatusCode {
2✔
125
        const _base = coerceStatusCode(statusCode);
867✔
126
        const tmp = new ModifiableStatusCode({ _base });
867✔
127
        if (optionalBits || typeof optionalBits === "number") {
867✔
128
            tmp.set(optionalBits);
851✔
129
        }
851✔
130
        return tmp;
867✔
131
    }
867✔
132

2✔
133
    /**
2✔
134
     * returns status code value in numerical form, including extra bits
2✔
135
     */
2✔
136
    public abstract get value(): number;
2✔
137

2✔
138
    /***
2✔
139
     * status code by name, (including  extra bits in textual forms)
2✔
140
     */
2✔
141
    public abstract get name(): string;
2✔
142

2✔
143
    /**
2✔
144
     * return the long description of the status code
2✔
145
     */
2✔
146
    public abstract get description(): string;
2✔
147

2✔
148
    public valueOf(): number {
2✔
149
        return this.value;
66✔
150
    }
66✔
151

2✔
152
    public toString(): string {
2✔
153
        return this.name + " (0x" + this.value.toString(16).padStart(8, "0") + ")";
18,875✔
154
    }
18,875✔
155

2✔
156
    public checkBit(mask: number): boolean {
2✔
157
        return (this.value & mask) === mask;
231✔
158
    }
231✔
159

2✔
160
    /** returns true if the overflow bit is set */
2✔
161
    public get hasOverflowBit(): boolean {
2✔
162
        return this.checkBit(extraStatusCodeBits.Overflow);
189✔
163
    }
189✔
164

2✔
165
    /** returns true if the semanticChange bit is set */
2✔
166
    public get hasSemanticChangedBit(): boolean {
2✔
167
        return this.checkBit(extraStatusCodeBits.SemanticChanged);
38✔
168
    }
38✔
169

2✔
170
    /** returns true if the structureChange bit is set */
2✔
171
    public get hasStructureChangedBit(): boolean {
2✔
172
        return this.checkBit(extraStatusCodeBits.StructureChanged);
4✔
173
    }
4✔
174

2✔
175
    public isNot(other: StatusCode): boolean {
2✔
176
        assert(other instanceof StatusCode);
82,487✔
177
        return this.value !== other.value;
82,487✔
178
    }
82,487✔
179

2✔
180
    public equals(other: StatusCode): boolean {
2✔
181
        assert(other instanceof StatusCode);
5,567,610✔
182
        return this.value === other.value;
5,567,610✔
183
    }
5,567,610✔
184

2✔
185
    public toJSON(): any {
2✔
186
        return { value: this.value };
32,512✔
187
    }
32,512✔
188

2✔
189
    public toJSONFull(): any {
2✔
190
        return { value: this.value, name: this.name, description: this.description };
2✔
191
    }
2✔
192

2✔
193
    public isGood(): boolean {
2✔
194
        return this.value === 0;
2,072,700✔
195
    }
2,072,700✔
196

2✔
197
    public isNotGood(): boolean {
2✔
198
        return this.value !== 0;
860,719✔
199
    }
860,719✔
200

2✔
201
    public isGoodish(): boolean {
2✔
202
        return this.value < 0x10000000;
2,274,185✔
203
    }
2,274,185✔
204

2✔
205
    public isBad(): boolean {
2✔
206
        return this.value >= 0x80000000;
1,226✔
207
    }
1,226✔
208
}
2✔
209

2✔
210
Object.defineProperty(StatusCode.prototype, "value", { enumerable: true });
2✔
211
Object.defineProperty(StatusCode.prototype, "description", { enumerable: true });
2✔
212
Object.defineProperty(StatusCode.prototype, "name", { enumerable: true });
2✔
213

2✔
214
// tslint:disable:max-classes-per-file
2✔
215
export class ConstantStatusCode extends StatusCode {
2,710✔
216
    private readonly _value: number;
2,710✔
217
    private readonly _description: string;
2,710✔
218
    private readonly _name: string;
2,710✔
219

2,710✔
220
    /**
2,710✔
221
     *
2,710✔
222
     * @param options
2,710✔
223
     * @param options
2,710✔
224
     * @param options.value
2,710✔
225
     * @param options.description
2,710✔
226
     * @param options.name
2,710✔
227
     *
2,710✔
228
     */
2,710✔
229
    constructor(options: { value: number; description: string; name: string }) {
2,710✔
230
        super();
2,710✔
231
        this._value = options.value;
2,710✔
232
        this._description = options.description;
2,710✔
233
        this._name = options.name;
2,710✔
234
    }
2,710✔
235

2,710✔
236
    public get value(): number {
2,710✔
237
        return this._value;
24,231,726✔
238
    }
24,231,726✔
239

2,710✔
240
    public get name(): string {
2,710✔
241
        return this._name;
19,029✔
242
    }
19,029✔
243

2,710✔
244
    public get description(): string {
2,710✔
245
        return this._description;
74✔
246
    }
74✔
247
}
2,710✔
248

2✔
249
Object.defineProperty(ConstantStatusCode.prototype, "_value", { enumerable: false, writable: true });
2✔
250
Object.defineProperty(ConstantStatusCode.prototype, "_description", { enumerable: false, writable: true });
2✔
251
Object.defineProperty(ConstantStatusCode.prototype, "_name", { enumerable: false, writable: true });
2✔
252
Object.defineProperty(ConstantStatusCode.prototype, "value", { enumerable: true });
2✔
253
Object.defineProperty(ConstantStatusCode.prototype, "description", { enumerable: true });
2✔
254
Object.defineProperty(ConstantStatusCode.prototype, "name", { enumerable: true });
2✔
255

2✔
256
export function encodeStatusCode(statusCode: StatusCode | ConstantStatusCode, stream: OutputBinaryStream): void {
515,398✔
257
    stream.writeUInt32(statusCode.value);
515,398✔
258
}
515,398✔
259

2✔
260
/** @internal construct status codes fast search indexes */
2✔
261
const statusCodesReversedMap: any = {};
2✔
262

2✔
263
/**
2✔
264
 * returns the StatusCode corresponding to the provided value, if any
2✔
265
 * @note: if code is not known , then StatusCodes.Bad will be returned
2✔
266
 * @param code
2✔
267
 */
2✔
268
export function getStatusCodeFromCode(code: number): StatusCode {
256,195✔
269
    const codeWithoutInfoBits = (code & 0xffff0000) >>> 0;
256,195✔
270
    const infoBits = code & 0x0000ffff;
256,195✔
271
    let sc = statusCodesReversedMap[codeWithoutInfoBits];
256,195✔
272

256,195✔
273
    /* c8 ignore next */
2✔
274
    if (!sc) {
2✔
UNCOV
275
        sc = StatusCodes.Bad;
×
UNCOV
276
        warnLog("expecting a known StatusCode but got 0x" + codeWithoutInfoBits.toString(16), " code was 0x" + code.toString(16));
×
UNCOV
277
    }
×
278
    if (infoBits) {
256,195✔
279
        const tmp = new ModifiableStatusCode({ _base: sc });
140✔
280
        tmp.set(infoBits);
140✔
281
        sc = tmp;
140✔
282
    }
140✔
283
    return sc;
256,195✔
284
}
256,195✔
285

2✔
286
export function decodeStatusCode(stream: BinaryStream, _value?: StatusCode): StatusCode {
256,179✔
287
    const code = stream.readUInt32();
256,179✔
288
    return getStatusCodeFromCode(code);
256,179✔
289
}
256,179✔
290

2✔
291
export class ModifiableStatusCode extends StatusCode {
1,007✔
292
    private readonly _base: StatusCode;
1,007✔
293
    private _extraBits: number;
1,007✔
294

1,007✔
295
    constructor(options: { _base: StatusCode }) {
1,007✔
296
        super();
1,007✔
297
        this._base = options._base;
1,007✔
298
        this._extraBits = 0;
1,007✔
299
        if (this._base instanceof ModifiableStatusCode) {
1,007✔
300
            this._extraBits = this._base._extraBits;
36✔
301
            this._base = this._base._base;
36✔
302
        }
36✔
303
    }
1,007✔
304

1,007✔
305
    public get value(): number {
1,007✔
306
        return this._base.value + this._extraBits;
2,283✔
307
    }
2,283✔
308

1,007✔
309
    public get name(): string {
1,007✔
310
        return this._base.name + this._getExtraName();
494✔
311
    }
494✔
312

1,007✔
313
    public get description(): string {
1,007✔
314
        return this._base.description;
2✔
315
    }
2✔
316

1,007✔
317
    public set(bit: string | number): void {
1,007✔
318
        if (typeof bit === "string") {
1,367✔
319
            const bitsArray = bit.split(" | ");
963✔
320
            if (bitsArray.length > 1) {
963✔
321
                for (const bitArray of bitsArray) {
179✔
322
                    this.set(bitArray);
358✔
323
                }
358✔
324
                return;
179✔
325
            }
179✔
326
            const tmp = extraStatusCodeBits[bit as string];
784✔
327

784✔
328
            /* c8 ignore next */
2✔
329
            if (!tmp) {
2✔
UNCOV
330
                throw new Error("Invalid StatusCode Bit " + bit);
×
UNCOV
331
            }
×
332
            bit = tmp;
784✔
333
        }
784✔
334
        this._extraBits = this._extraBits | (bit as number);
1,188✔
335
    }
1,188✔
336

1,007✔
337
    public unset(bit: string | number): void {
1,007✔
338
        if (typeof bit === "string") {
16✔
339
            const bitsArray = bit.split(" | ");
16✔
340
            if (bitsArray.length > 1) {
16✔
341
                for (const bitArray of bitsArray) {
4✔
342
                    this.unset(bitArray);
8✔
343
                }
8✔
344
                return;
4✔
345
            }
4✔
346
            const tmp = extraStatusCodeBits[bit];
12✔
347

12✔
348
            /* c8 ignore next */
2✔
349
            if (!tmp) {
2✔
UNCOV
350
                throw new Error("Invalid StatusCode Bit " + bit);
×
UNCOV
351
            }
×
352
            bit = tmp;
12✔
353
        }
12✔
354
        this._extraBits = this._extraBits & (~bit >>> 0);
12✔
355
    }
12✔
356

1,007✔
357
    private _getExtraName() {
1,007✔
358
        const str: string[] = [];
494✔
359
        for (const [key, value] of Object.entries(extraStatusCodeBits)) {
494✔
360
            if ((this._extraBits & value) === value) {
5,928✔
361
                str.push(key);
610✔
362
            }
610✔
363
        }
5,928✔
364

494✔
365
        /* c8 ignore next */
2✔
366
        if (str.length === 0) {
2✔
UNCOV
367
            return "";
×
UNCOV
368
        }
×
369
        return "#" + str.join("|");
494✔
370
    }
494✔
371
}
1,007✔
372

2✔
373
// hide private properties
2✔
374
Object.defineProperty(ModifiableStatusCode.prototype, "_base", { enumerable: false, writable: true });
2✔
375
Object.defineProperty(ModifiableStatusCode.prototype, "_extraBits", { enumerable: false, writable: true });
2✔
376

2✔
377
import { StatusCodes } from "./_generated_status_codes";
2✔
378
export { StatusCodes } from "./_generated_status_codes";
2✔
379

2✔
380
export function coerceStatusCode(statusCode: StatusCode | number | string | { value: number }): StatusCode {
14,222,235✔
381
    if (statusCode instanceof StatusCode) {
14,222,235✔
382
        return statusCode;
14,222,219✔
383
    }
14,222,219✔
384
    if (Object.prototype.hasOwnProperty.call(statusCode, "value")) {
14,220,747✔
385
        return getStatusCodeFromCode((statusCode as { value: number }).value);
10✔
386
    }
10✔
387
    if (typeof statusCode === "number") {
14,220,747✔
388
        return getStatusCodeFromCode(statusCode);
4✔
389
    }
4✔
390
    const _StatusCodes = StatusCodes as any;
2✔
391
    if (!_StatusCodes[statusCode as string]) {
14,220,747!
392
        throw new Error("Cannot find StatusCode " + statusCode);
×
UNCOV
393
    }
×
394
    return _StatusCodes[statusCode as string];
2✔
395
}
2✔
396

2✔
397
for (const name of Object.keys(StatusCodes)) {
2✔
398
    const code = (StatusCodes as any)[name];
2,720✔
399
    statusCodesReversedMap[code.value.toString()] = code;
2,720✔
400
}
2,720✔
401

2✔
402
(StatusCodes as any).makeStatusCode = StatusCode.makeStatusCode;
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc