11import chains from '../../src/connection-manager/chains'
22import { destroy , query , setupTables } from '../../src/shared/database'
3-
3+ import skippedLedgersValidations from './fixtures/skipped-ledgers-validations.json'
4+ import outOfOrderValidations from './fixtures/out-of-order-validations.json'
45import validations from './fixtures/all-validations.json'
6+ import { Chain } from '../../src/shared/types'
7+ import duplicateValidations from './fixtures/duplicate-validations.json'
8+ import newValidatorsVotes from './fixtures/new-validators-votes.json'
59
610jest . useFakeTimers ( )
711
@@ -17,6 +21,7 @@ describe('Creates chains', () => {
1721 beforeEach ( async ( ) => {
1822 await query ( 'connection_health' ) . delete ( '*' )
1923 await query ( 'crawls' ) . delete ( '*' )
24+ chains . __resetChainsSingletonForTests ( )
2025 } )
2126
2227 test ( 'Perfect validation scores' , async ( ) => {
@@ -43,6 +48,17 @@ describe('Creates chains', () => {
4348 } )
4449
4550 test ( 'Purge chains removes ledgers' , async ( ) => {
51+ // This test validates the behavior of purgeChains. As a pre-requisite, assign sample ledgers into appropriate chain-IDs before the purge operation.
52+ for ( const validation of validations ) {
53+ chains . updateLedgers ( validation )
54+ }
55+ // Mock date.now
56+ const time = Date . now ( ) + 11000
57+ Date . now = ( ) : number => time
58+
59+ // assign ledgers into the appropriate chains
60+ chains . calculateChainsFromLedgers ( )
61+
4662 await chains . purgeChains ( )
4763
4864 const constructed : Array < {
@@ -56,4 +72,87 @@ describe('Creates chains', () => {
5672 expect ( constructed [ 0 ] . validators ) . toContain ( 'VALIDATOR2' )
5773 expect ( constructed [ 0 ] . validators ) . toContain ( 'VALIDATOR3' )
5874 } )
75+
76+ test ( `Validate the case where VHS misses > 20 ledgers` , async ( ) => {
77+ for ( const validation of skippedLedgersValidations ) {
78+ chains . updateLedgers ( validation )
79+ }
80+
81+ const time = Date . now ( ) + 11000
82+
83+ // Mock date.now
84+ Date . now = ( ) : number => time
85+ const updatedChains = chains . calculateChainsFromLedgers ( )
86+ expect ( updatedChains ) . toHaveLength ( 1 )
87+
88+ expect ( updatedChains [ 0 ] . id ) . toBe ( 'chain.0' )
89+ expect ( updatedChains [ 0 ] . current ) . toBe ( 38 )
90+ expect ( updatedChains [ 0 ] . first ) . toBe ( 1 )
91+ expect ( updatedChains [ 0 ] . validators ) . toEqual ( new Set ( [ 'VALIDATOR1' , 'VALIDATOR2' , 'VALIDATOR3' ] ) )
92+ // Note: It is fragile to test the time when the chain was updated with the latest values.
93+ expect ( updatedChains [ 0 ] . ledgers ) . toEqual ( new Set ( [ 'LEDGER1' , 'LEDGER2' , 'LEDGER3' , 'LEDGER33' , 'LEDGER34' , 'LEDGER35' , 'LEDGER36' , 'LEDGER37' , 'LEDGER38' ] ) )
94+ expect ( updatedChains [ 0 ] . incomplete ) . toBe ( true )
95+ } )
96+
97+ test ( `Simulate the case where VHS misses <0 ledgers (VHS receives out-of-sync historical ledger)` , async ( ) => {
98+ for ( const validation of outOfOrderValidations ) {
99+ chains . updateLedgers ( validation )
100+ }
101+
102+ const time = Date . now ( ) + 11000
103+
104+ // Mock date.now
105+ Date . now = ( ) : number => time
106+ const constructed : Array < Chain > = chains . calculateChainsFromLedgers ( )
107+
108+ expect ( constructed ) . toHaveLength ( 1 )
109+ expect ( constructed [ 0 ] . id ) . toBe ( 'chain.0' )
110+ expect ( constructed [ 0 ] . current ) . toBe ( 38 )
111+ expect ( constructed [ 0 ] . first ) . toBe ( 1 )
112+ expect ( constructed [ 0 ] . validators ) . toEqual ( new Set ( [ 'VALIDATOR1' , 'VALIDATOR2' , 'VALIDATOR3' ] ) )
113+ expect ( constructed [ 0 ] . ledgers ) . toEqual ( new Set ( [ 'LEDGER1' , 'LEDGER2' , 'LEDGER3' , 'LEDGER33' , 'LEDGER34' , 'LEDGER35' , 'LEDGER36' , 'LEDGER37' , 'LEDGER38' , 'LEDGER20' , 'LEDGER11' ] ) )
114+ expect ( constructed [ 0 ] . incomplete ) . toBe ( true )
115+ } )
116+
117+ test ( `VHS receives identical copies of the validationReceived message` , async ( ) => {
118+ for ( const validation of duplicateValidations ) {
119+ chains . updateLedgers ( validation )
120+ }
121+
122+ const time = Date . now ( ) + 11000
123+
124+ // Mock date.now
125+ Date . now = ( ) : number => time
126+ const constructed : Array < Chain > = chains . calculateChainsFromLedgers ( )
127+
128+ expect ( constructed ) . toHaveLength ( 1 )
129+ // Note: duplicate validations are ignored.
130+ expect ( constructed [ 0 ] . ledgers ) . toEqual ( new Set ( [ 'LEDGER1' , 'LEDGER2' , 'LEDGER3' ] ) )
131+ expect ( constructed [ 0 ] . validators ) . toEqual ( new Set ( [ 'VALIDATOR1' , 'VALIDATOR2' , 'VALIDATOR3' ] ) )
132+ expect ( constructed [ 0 ] . id ) . toBe ( 'chain.0' )
133+ expect ( constructed [ 0 ] . current ) . toBe ( 3 )
134+ expect ( constructed [ 0 ] . first ) . toBe ( 1 )
135+ expect ( constructed [ 0 ] . incomplete ) . toBe ( true )
136+ } )
137+
138+ test ( `Simulate the inclusion of two new validators in the validationReceived messages` , async ( ) => {
139+ for ( const validation of newValidatorsVotes ) {
140+ chains . updateLedgers ( validation )
141+ }
142+
143+ const time = Date . now ( ) + 11000
144+
145+ // Mock date.now
146+ Date . now = ( ) : number => time
147+ const constructed : Array < Chain > = chains . calculateChainsFromLedgers ( )
148+
149+ expect ( constructed ) . toHaveLength ( 1 )
150+ // Note: duplicate validations are ignored.
151+ expect ( constructed [ 0 ] . ledgers ) . toEqual ( new Set ( [ 'LEDGER1' , 'LEDGER2' , 'LEDGER3' , 'LEDGER4' ] ) )
152+ expect ( constructed [ 0 ] . validators ) . toEqual ( new Set ( [ 'VALIDATOR1' , 'VALIDATOR2' , 'VALIDATOR3' , 'VALIDATOR4' , 'VALIDATOR5' ] ) )
153+ expect ( constructed [ 0 ] . id ) . toBe ( 'chain.0' )
154+ expect ( constructed [ 0 ] . current ) . toBe ( 4 )
155+ expect ( constructed [ 0 ] . first ) . toBe ( 1 )
156+ expect ( constructed [ 0 ] . incomplete ) . toBe ( true )
157+ } )
59158} )
0 commit comments