@@ -21,6 +21,7 @@ import { IPublishPacket, IPubrelPacket, ISubackPacket, QoS } from 'mqtt-packet'
21
21
import { DoneCallback , ErrorWithReasonCode } from 'src/lib/shared'
22
22
import { fail } from 'assert'
23
23
import { describe , it , beforeEach , afterEach } from 'node:test'
24
+ import { nextTick } from 'process'
24
25
25
26
/**
26
27
* These tests try to be consistent with names for servers (brokers) and clients,
@@ -1309,7 +1310,7 @@ export default function abstractTest(server, config, ports) {
1309
1310
} )
1310
1311
}
1311
1312
callback ( )
1312
- } , 100 )
1313
+ } , 10 )
1313
1314
}
1314
1315
1315
1316
client . on ( 'message' , ( topic , message , packet ) => {
@@ -1342,7 +1343,7 @@ export default function abstractTest(server, config, ports) {
1342
1343
1343
1344
const qosTests = [ 0 , 1 , 2 ]
1344
1345
qosTests . forEach ( ( qos ) => {
1345
- it ( `should publish 10 QoS ${ qos } and receive them only when \`handleMessage\` finishes` , function _test ( t , done ) {
1346
+ it ( `should publish 10 QoS ${ qos } and receive them only when \`handleMessage\` finishes` , function _test ( t , done ) {
1346
1347
testQosHandleMessage ( qos , done )
1347
1348
} )
1348
1349
} )
@@ -2048,40 +2049,83 @@ export default function abstractTest(server, config, ports) {
2048
2049
} )
2049
2050
2050
2051
it (
2051
- 'should reconnect if pingresp is not sent ' ,
2052
+ 'should reconnect on keepalive timeout ' ,
2052
2053
{
2053
- timeout : 4000 ,
2054
+ timeout : 10000 ,
2054
2055
} ,
2055
2056
function _test ( t , done ) {
2056
- const client = connect ( { keepalive : 1 , reconnectPeriod : 100 } )
2057
+ const clock = sinon . useFakeTimers ( )
2057
2058
2058
- // Fake no pingresp being send by stubbing the _handlePingresp function
2059
- client . on ( 'packetreceive' , ( packet ) => {
2060
- if ( packet . cmd === 'pingresp' ) {
2061
- setImmediate ( ( ) => {
2062
- client . pingResp = false
2063
- } )
2059
+ t . after ( ( ) => {
2060
+ clock . restore ( )
2061
+ if ( client ) {
2062
+ client . end ( true )
2063
+ throw new Error ( 'Test timed out' )
2064
2064
}
2065
2065
} )
2066
2066
2067
+ let client = connect ( {
2068
+ keepalive : 60 ,
2069
+ reconnectPeriod : 5000 ,
2070
+ } )
2071
+
2067
2072
client . once ( 'connect' , ( ) => {
2068
- client . once ( 'connect' , ( ) => {
2069
- client . end ( true , done )
2073
+ client . pingResp = false
2074
+
2075
+ client . once ( 'error' , ( err ) => {
2076
+ assert . equal ( err . message , 'Keepalive timeout' )
2077
+ client . once ( 'connect' , ( ) => {
2078
+ client . end ( true , done )
2079
+ client = null
2080
+ } )
2081
+ } )
2082
+
2083
+ client . once ( 'close' , ( ) => {
2084
+ // Wait for the reconnect to happen
2085
+ clock . tick ( client . options . reconnectPeriod )
2070
2086
} )
2087
+
2088
+ clock . tick ( client . options . keepalive * 1000 )
2071
2089
} )
2072
2090
} ,
2073
2091
)
2074
2092
2075
- it ( 'should not reconnect if pingresp is successful' , function _test ( t , done ) {
2076
- const client = connect ( { keepalive : 100 } )
2077
- client . once ( 'close' , ( ) => {
2078
- done ( new Error ( 'Client closed connection' ) )
2079
- } )
2080
- setTimeout ( ( ) => {
2081
- client . removeAllListeners ( 'close' )
2082
- client . end ( true , done )
2083
- } , 1000 )
2084
- } )
2093
+ it (
2094
+ 'should not reconnect if pingresp is successful' ,
2095
+ { timeout : 1000 } ,
2096
+ function _test ( t , done ) {
2097
+ const clock = sinon . useFakeTimers ( )
2098
+
2099
+ t . after ( ( ) => {
2100
+ clock . restore ( )
2101
+ if ( client ) {
2102
+ client . end ( true )
2103
+ }
2104
+ } )
2105
+
2106
+ let client = connect ( { keepalive : 10 } )
2107
+ client . once ( 'close' , ( ) => {
2108
+ done ( new Error ( 'Client closed connection' ) )
2109
+ } )
2110
+
2111
+ client . once ( 'connect' , ( ) => {
2112
+ setImmediate ( ( ) => {
2113
+ // make keepalive check trigger
2114
+ clock . tick ( client . options . keepalive * 1000 )
2115
+ } )
2116
+
2117
+ client . on ( 'packetsend' , ( packet ) => {
2118
+ if ( packet . cmd === 'pingreq' ) {
2119
+ client . removeAllListeners ( 'close' )
2120
+ client . end ( true , done )
2121
+ client = null
2122
+ }
2123
+ } )
2124
+
2125
+ clock . tick ( 1 )
2126
+ } )
2127
+ } ,
2128
+ )
2085
2129
2086
2130
it ( 'should defer the next ping when sending a control packet' , function _test ( t , done ) {
2087
2131
const client = connect ( { keepalive : 1 } )
@@ -2866,13 +2910,22 @@ export default function abstractTest(server, config, ports) {
2866
2910
} )
2867
2911
2868
2912
it ( 'should reconnect after stream disconnect' , function _test ( t , done ) {
2869
- const client = connect ( )
2913
+ const clock = sinon . useFakeTimers ( )
2914
+
2915
+ t . after ( ( ) => {
2916
+ clock . restore ( )
2917
+ } )
2918
+
2919
+ const client = connect ( { reconnectPeriod : 1000 } )
2870
2920
2871
2921
let tryReconnect = true
2872
2922
2873
2923
client . on ( 'connect' , ( ) => {
2874
2924
if ( tryReconnect ) {
2875
2925
client . stream . end ( )
2926
+ client . once ( 'close' , ( ) => {
2927
+ clock . tick ( client . options . reconnectPeriod )
2928
+ } )
2876
2929
tryReconnect = false
2877
2930
} else {
2878
2931
client . end ( true , done )
@@ -2881,7 +2934,15 @@ export default function abstractTest(server, config, ports) {
2881
2934
} )
2882
2935
2883
2936
it ( "should emit 'reconnect' when reconnecting" , function _test ( t , done ) {
2884
- const client = connect ( )
2937
+ const clock = sinon . useFakeTimers ( )
2938
+
2939
+ t . after ( ( ) => {
2940
+ clock . restore ( )
2941
+ } )
2942
+
2943
+ const client = connect ( {
2944
+ reconnectPeriod : 1000 ,
2945
+ } )
2885
2946
let tryReconnect = true
2886
2947
let reconnectEvent = false
2887
2948
@@ -2892,6 +2953,9 @@ export default function abstractTest(server, config, ports) {
2892
2953
client . on ( 'connect' , ( ) => {
2893
2954
if ( tryReconnect ) {
2894
2955
client . stream . end ( )
2956
+ client . once ( 'close' , ( ) => {
2957
+ clock . tick ( client . options . reconnectPeriod )
2958
+ } )
2895
2959
tryReconnect = false
2896
2960
} else {
2897
2961
assert . isTrue ( reconnectEvent )
@@ -2901,7 +2965,14 @@ export default function abstractTest(server, config, ports) {
2901
2965
} )
2902
2966
2903
2967
it ( "should emit 'offline' after going offline" , function _test ( t , done ) {
2904
- const client = connect ( )
2968
+ const clock = sinon . useFakeTimers ( )
2969
+
2970
+ t . after ( ( ) => {
2971
+ clock . restore ( )
2972
+ } )
2973
+ const client = connect ( {
2974
+ reconnectPeriod : 1000 ,
2975
+ } )
2905
2976
2906
2977
let tryReconnect = true
2907
2978
let offlineEvent = false
@@ -2914,6 +2985,9 @@ export default function abstractTest(server, config, ports) {
2914
2985
if ( tryReconnect ) {
2915
2986
client . stream . end ( )
2916
2987
tryReconnect = false
2988
+ client . once ( 'close' , ( ) => {
2989
+ clock . tick ( client . options . reconnectPeriod )
2990
+ } )
2917
2991
} else {
2918
2992
assert . isTrue ( offlineEvent )
2919
2993
client . end ( true , done )
@@ -2956,18 +3030,28 @@ export default function abstractTest(server, config, ports) {
2956
3030
timeout : 10000 ,
2957
3031
} ,
2958
3032
function _test ( t , done ) {
3033
+ const clock = sinon . useFakeTimers ( )
3034
+
3035
+ t . after ( ( ) => {
3036
+ clock . restore ( )
3037
+ } )
3038
+
2959
3039
let end
2960
3040
const reconnectSlushTime = 200
2961
3041
const client = connect ( { reconnectPeriod : test . period } )
2962
3042
let reconnect = false
2963
- const start = Date . now ( )
3043
+ const start = clock . now
2964
3044
2965
3045
client . on ( 'connect' , ( ) => {
2966
3046
if ( ! reconnect ) {
2967
3047
client . stream . end ( )
3048
+ client . once ( 'close' , ( ) => {
3049
+ // ensure the tick is done after the reconnect timer is setup (on close)
3050
+ clock . tick ( test . period )
3051
+ } )
2968
3052
reconnect = true
2969
3053
} else {
2970
- end = Date . now ( )
3054
+ end = clock . now
2971
3055
client . end ( ( ) => {
2972
3056
const reconnectPeriodDuringTest = end - start
2973
3057
if (
0 commit comments