66import * as assert from 'assert' ;
77import { Socket } from 'net' ;
88import { EventEmitter } from 'events' ;
9- import { Protocol } from 'vs/base/parts/ipc/node/ipc.net' ;
9+ import { Protocol , PersistentProtocol } from 'vs/base/parts/ipc/node/ipc.net' ;
1010
11- class MockDuplex extends EventEmitter {
11+ class MessageStream {
1212
13- private _cache : Buffer [ ] = [ ] ;
13+ private _currentComplete : ( ( data : Buffer ) => void ) | null ;
14+ private _messages : Buffer [ ] ;
1415
15- readonly destroyed = false ;
16+ constructor ( x : Protocol | PersistentProtocol ) {
17+ this . _currentComplete = null ;
18+ this . _messages = [ ] ;
19+ x . onMessage ( data => {
20+ this . _messages . push ( data ) ;
21+ this . _trigger ( ) ;
22+ } ) ;
23+ }
1624
17- private _deliver ( ) : void {
18- if ( this . _cache . length ) {
19- const data = Buffer . concat ( this . _cache ) ;
20- this . _cache . length = 0 ;
21- this . emit ( 'data' , data ) ;
25+ private _trigger ( ) : void {
26+ if ( ! this . _currentComplete ) {
27+ return ;
2228 }
29+ if ( this . _messages . length === 0 ) {
30+ return ;
31+ }
32+ const complete = this . _currentComplete ;
33+ const msg = this . _messages . shift ( ) ! ;
34+
35+ this . _currentComplete = null ;
36+ complete ( msg ) ;
37+ }
38+
39+ public waitForOne ( ) : Promise < Buffer > {
40+ return new Promise < Buffer > ( ( complete ) => {
41+ this . _currentComplete = complete ;
42+ this . _trigger ( ) ;
43+ } ) ;
44+ }
45+ }
46+
47+ class EtherStream extends EventEmitter {
48+ constructor (
49+ private readonly _ether : Ether ,
50+ private readonly _name : 'a' | 'b'
51+ ) {
52+ super ( ) ;
2353 }
2454
2555 write ( data : Buffer , cb ?: Function ) : boolean {
26- this . _cache . push ( data ) ;
27- setImmediate ( ( ) => this . _deliver ( ) ) ;
56+ this . _ether . write ( this . _name , data ) ;
2857 return true ;
2958 }
3059}
3160
61+ class Ether {
62+
63+ private readonly _a : EtherStream ;
64+ private readonly _b : EtherStream ;
65+
66+ private _ab : Buffer [ ] ;
67+ private _ba : Buffer [ ] ;
68+
69+ public get a ( ) : Socket {
70+ return < any > this . _a ;
71+ }
72+
73+ public get b ( ) : Socket {
74+ return < any > this . _b ;
75+ }
76+
77+ constructor ( ) {
78+ this . _a = new EtherStream ( this , 'a' ) ;
79+ this . _b = new EtherStream ( this , 'b' ) ;
80+ this . _ab = [ ] ;
81+ this . _ba = [ ] ;
82+ }
83+
84+ public write ( from : 'a' | 'b' , data : Buffer ) : void {
85+ if ( from === 'a' ) {
86+ this . _ab . push ( data ) ;
87+ } else {
88+ this . _ba . push ( data ) ;
89+ }
90+
91+ setImmediate ( ( ) => this . _deliver ( ) ) ;
92+ }
93+
94+ private _deliver ( ) : void {
95+
96+ if ( this . _ab . length > 0 ) {
97+ const data = Buffer . concat ( this . _ab ) ;
98+ this . _ab . length = 0 ;
99+ this . _b . emit ( 'data' , data ) ;
100+ setImmediate ( ( ) => this . _deliver ( ) ) ;
101+ return ;
102+ }
103+
104+ if ( this . _ba . length > 0 ) {
105+ const data = Buffer . concat ( this . _ba ) ;
106+ this . _ba . length = 0 ;
107+ this . _a . emit ( 'data' , data ) ;
108+ setImmediate ( ( ) => this . _deliver ( ) ) ;
109+ return ;
110+ }
111+
112+ }
113+ }
32114
33115suite ( 'IPC, Socket Protocol' , ( ) => {
34116
35- let stream : Socket ;
117+ let ether : Ether ;
36118
37119 setup ( ( ) => {
38- stream = < any > new MockDuplex ( ) ;
120+ ether = new Ether ( ) ;
39121 } ) ;
40122
41123 test ( 'read/write' , async ( ) => {
42124
43- const a = new Protocol ( stream ) ;
44- const b = new Protocol ( stream ) ;
125+ const a = new Protocol ( ether . a ) ;
126+ const b = new Protocol ( ether . b ) ;
127+ const bMessages = new MessageStream ( b ) ;
45128
46- await new Promise ( resolve => {
47- const sub = b . onMessage ( data => {
48- sub . dispose ( ) ;
49- assert . equal ( data . toString ( ) , 'foobarfarboo' ) ;
50- resolve ( undefined ) ;
51- } ) ;
52- a . send ( Buffer . from ( 'foobarfarboo' ) ) ;
53- } ) ;
54- return new Promise ( resolve => {
55- const sub_1 = b . onMessage ( data => {
56- sub_1 . dispose ( ) ;
57- assert . equal ( data . readInt8 ( 0 ) , 123 ) ;
58- resolve ( undefined ) ;
59- } ) ;
60- const buffer = Buffer . allocUnsafe ( 1 ) ;
61- buffer . writeInt8 ( 123 , 0 ) ;
62- a . send ( buffer ) ;
63- } ) ;
129+ a . send ( Buffer . from ( 'foobarfarboo' ) ) ;
130+ const msg1 = await bMessages . waitForOne ( ) ;
131+ assert . equal ( msg1 . toString ( ) , 'foobarfarboo' ) ;
132+
133+ const buffer = Buffer . allocUnsafe ( 1 ) ;
134+ buffer . writeInt8 ( 123 , 0 ) ;
135+ a . send ( buffer ) ;
136+ const msg2 = await bMessages . waitForOne ( ) ;
137+ assert . equal ( msg2 . readInt8 ( 0 ) , 123 ) ;
64138 } ) ;
65139
66140
67- test ( 'read/write, object data' , ( ) => {
141+ test ( 'read/write, object data' , async ( ) => {
68142
69- const a = new Protocol ( stream ) ;
70- const b = new Protocol ( stream ) ;
143+ const a = new Protocol ( ether . a ) ;
144+ const b = new Protocol ( ether . b ) ;
145+ const bMessages = new MessageStream ( b ) ;
71146
72147 const data = {
73148 pi : Math . PI ,
@@ -77,12 +152,68 @@ suite('IPC, Socket Protocol', () => {
77152 } ;
78153
79154 a . send ( Buffer . from ( JSON . stringify ( data ) ) ) ;
155+ const msg = await bMessages . waitForOne ( ) ;
156+ assert . deepEqual ( JSON . parse ( msg . toString ( ) ) , data ) ;
157+ } ) ;
80158
81- return new Promise ( resolve => {
82- b . onMessage ( msg => {
83- assert . deepEqual ( JSON . parse ( msg . toString ( ) ) , data ) ;
84- resolve ( undefined ) ;
85- } ) ;
86- } ) ;
159+ } ) ;
160+
161+ suite ( 'PersistentProtocol reconnection' , ( ) => {
162+ let ether : Ether ;
163+
164+ setup ( ( ) => {
165+ ether = new Ether ( ) ;
166+ } ) ;
167+
168+ test ( 'acks get piggybacked with messages' , async ( ) => {
169+ const a = new PersistentProtocol ( ether . a ) ;
170+ const aMessages = new MessageStream ( a ) ;
171+ const b = new PersistentProtocol ( ether . b ) ;
172+ const bMessages = new MessageStream ( b ) ;
173+
174+ a . send ( Buffer . from ( 'a1' ) ) ;
175+ assert . equal ( a . unacknowledgedCount , 1 ) ;
176+ assert . equal ( b . unacknowledgedCount , 0 ) ;
177+
178+ a . send ( Buffer . from ( 'a2' ) ) ;
179+ assert . equal ( a . unacknowledgedCount , 2 ) ;
180+ assert . equal ( b . unacknowledgedCount , 0 ) ;
181+
182+ a . send ( Buffer . from ( 'a3' ) ) ;
183+ assert . equal ( a . unacknowledgedCount , 3 ) ;
184+ assert . equal ( b . unacknowledgedCount , 0 ) ;
185+
186+ const a1 = await bMessages . waitForOne ( ) ;
187+ assert . equal ( a1 . toString ( ) , 'a1' ) ;
188+ assert . equal ( a . unacknowledgedCount , 3 ) ;
189+ assert . equal ( b . unacknowledgedCount , 0 ) ;
190+
191+ const a2 = await bMessages . waitForOne ( ) ;
192+ assert . equal ( a2 . toString ( ) , 'a2' ) ;
193+ assert . equal ( a . unacknowledgedCount , 3 ) ;
194+ assert . equal ( b . unacknowledgedCount , 0 ) ;
195+
196+ const a3 = await bMessages . waitForOne ( ) ;
197+ assert . equal ( a3 . toString ( ) , 'a3' ) ;
198+ assert . equal ( a . unacknowledgedCount , 3 ) ;
199+ assert . equal ( b . unacknowledgedCount , 0 ) ;
200+
201+ b . send ( Buffer . from ( 'b1' ) ) ;
202+ assert . equal ( a . unacknowledgedCount , 3 ) ;
203+ assert . equal ( b . unacknowledgedCount , 1 ) ;
204+
205+ const b1 = await aMessages . waitForOne ( ) ;
206+ assert . equal ( b1 . toString ( ) , 'b1' ) ;
207+ assert . equal ( a . unacknowledgedCount , 0 ) ;
208+ assert . equal ( b . unacknowledgedCount , 1 ) ;
209+
210+ a . send ( Buffer . from ( 'a4' ) ) ;
211+ assert . equal ( a . unacknowledgedCount , 1 ) ;
212+ assert . equal ( b . unacknowledgedCount , 1 ) ;
213+
214+ const b2 = await bMessages . waitForOne ( ) ;
215+ assert . equal ( b2 . toString ( ) , 'a4' ) ;
216+ assert . equal ( a . unacknowledgedCount , 1 ) ;
217+ assert . equal ( b . unacknowledgedCount , 0 ) ;
87218 } ) ;
88219} ) ;
0 commit comments