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

rustymotors / server / 25538948182

08 May 2026 05:37AM UTC coverage: 44.206% (+6.2%) from 37.969%
25538948182

Pull #2831

github

drazisil
Generate lcov coverage so the Coveralls upload step has a file to push

CI's "Upload coverage to Coveralls" step has been failing with

  🚨 ERROR: Couldn't find specified file: ./coverage/lcov.info

The Coveralls action expects ./coverage/lcov.info, but the workflow
runs `npm run coverage` and the script was just `vitest run` — no
--coverage flag, so coverage was never collected. Even with the flag,
Vitest's default reporters are text + html, neither of which write
lcov.info.

Two-line fix:

- package.json: "coverage" script now passes --coverage.
- vitest.config.ts: explicit `coverage: { provider: "v8", reporter:
  ["text", "lcov", "json"] }`. The `lcov` reporter writes
  ./coverage/lcov.info; `json` keeps Codecov's auto-detection paths
  happy.

Verified locally: `npm run coverage` produces ./coverage/lcov.info
(~231 KB) with full statement/branch/function/line summaries.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pull Request #2831: Race flow: MCOTS handlers, packet reassembly, Sentry observability

657 of 1706 branches covered (38.51%)

Branch coverage included in aggregate %.

1004 of 1385 new or added lines in 59 files covered. (72.49%)

47 existing lines in 27 files now uncovered.

4173 of 9220 relevant lines covered (45.26%)

131.52 hits per line

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

66.67
/packages/shared/src/OldServerMessage.ts
1
import type { IServerMessage } from "rusty-motors-protocol";
2
import { MessageNode } from "./MessageNode.js";
3
import { sliceBuff } from "./helpers.js";
4

5

6

7
/**
8
 * A server message is a message that is passed between the server and the client. It has an 11 byte header.
9
 * This is a compatibility wrapper around MessageNode.
10
 *
11
 * @deprecated Use MessageNode directly instead
12
 */
13
export class OldServerMessage extends MessageNode implements IServerMessage {
14
        private _headerProxy: any;
15

16
        /**
17
         * @deprecated Use this.header or this.signature/this.length instead
18
         */
19
        get _header() {
20
                if (!this._headerProxy) {
15✔
21
                        const self = this;
6✔
22
                        this._headerProxy = {
6✔
23
                                get mcoSig() { return self.signature; },
3✔
24
                        set mcoSig(val: string) { 
25
                                (self as any).signature_ = val;
1✔
26
                        },
27
                                get length() { return self.length; },
1✔
UNCOV
28
                                set length(val: number) { (self as any).msgLength_ = val; },
×
29
                                get sequence() { return self.sequence; },
3✔
30
                                set sequence(val: number) { self.sequence = val; },
5✔
31
                                get flags() { return self.flags; },
3✔
32
                                set flags(val: number) { 
33
                                        // MessageNode doesn't have a direct flags setter, so we access the protected field
34
                                        (self as any).flags_ = val; 
3✔
35
                                },
36
                                _size: 11,
37
                                _doDeserialize: (buffer: Buffer) => {
38
                                        // Only deserialize the header (first 11 bytes), not the entire message
39
                                        // This prevents infinite recursion when subclasses call _header._doDeserialize()
40
                                        // This matches MessageNode.deserialize() header parsing (lines 80-86)
41
                                        let offset = 0;
×
42
                                        // Use unsigned 16-bit to match MessageNode and support messages larger than 32767 bytes
43
                                        (self as any).msgLength_ = buffer.readUInt16LE(offset);
×
44
                                        offset += 2;
×
45
                                        (self as any).signature_ = sliceBuff(buffer, offset, 4).toString('utf8');
×
46
                                        offset += 4;
×
47
                                        (self as any).sequence_ = buffer.readInt32LE(offset);
×
48
                                        offset += 4;
×
49
                                        (self as any).flags_ = buffer.readInt8(offset);
×
50
                                        return self._header;
×
51
                                },
52
                                _doSerialize: () => {
53
                                        return self.serialize().subarray(0, 11);
×
54
                                },
55
                        };
56
                }
57
                return this._headerProxy;
15✔
58
        }
59

60
        /**
61
         * @deprecated Use this.msgNo instead
62
         */
63
        get _msgNo() {
64
                return this.msgNo;
3✔
65
        }
66

67
        set _msgNo(val: number) {
68
                // Body is already initialized to 2 bytes minimum (smallest legal MessageNode size)
69
                this.msgNo = val;
3✔
70
        }
71

72
        constructor() {
73
                super();
14✔
74
                // Initialize with minimum legal body size
75
                // The smallest legal MessageNode is GenericRequestMessage which has:
76
                // - msgNo: 2 bytes
77
                // - data: 4 bytes
78
                // - data2: 4 bytes
79
                // Total: 10 bytes minimum body size
80
                // Note: setDataBuffer calls body.deserialize which requires at least 2 bytes,
81
                // so 10 bytes is safe
82
                this.setDataBuffer(Buffer.alloc(10));
14✔
83
        }
84

85
        override size(): number {
86
                // 11 is the header size
87
                // Return header (11) + body size
88
                const bodySize = this.getBody().sizeOf;
1✔
89
                return 11 + bodySize;
1✔
90
        }
91

92
        /**
93
         * @deprecated Use deserialize() instead
94
         * @param {Buffer} buffer
95
         * @returns {OldServerMessage}
96
         */
97
        _doDeserialize(buffer: Buffer): OldServerMessage {
98
                this.deserialize(buffer);
2✔
99
                return this;
2✔
100
        }
101

102
        /**
103
         * @deprecated Use setBody() or setDataBuffer() instead
104
         * @param {Buffer} buffer
105
         */
106
        setBuffer(buffer: Buffer) {
107
                this.setDataBuffer(buffer);
6✔
108
        }
109

110
        /**
111
         * @deprecated Use this.msgNo instead
112
         */
113
        updateMsgNo() {
114
                // msgNo is already synced with body.msgNumber via MessageNode
115
        }
116

117
        override toString() {
118
                return `ServerMessage: ${JSON.stringify({
4✔
119
                        header: {
120
                                mcoSig: this.signature,
121
                                length: this.length,
122
                                sequence: this.sequence,
123
                                flags: this.flags,
124
                        },
125
                        data: this.data.toString("hex"),
126
                })}`;
127
        }
128

129
        override toHexString() {
130
                return this.serialize().toString("hex");
×
131
        }
132

133
        get sequenceNumber(): number {
134
                return this.sequence;
7✔
135
        }
136
}
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