github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/discovery/brokerdiscovery/repository_test.go (about) 1 /* 2 * Copyright (C) 2019 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package brokerdiscovery 19 20 import ( 21 "encoding/json" 22 "testing" 23 "time" 24 25 "github.com/mysteriumnetwork/node/communication/nats" 26 "github.com/mysteriumnetwork/node/eventbus" 27 "github.com/mysteriumnetwork/node/market" 28 "github.com/stretchr/testify/assert" 29 ) 30 31 func init() { 32 market.RegisterServiceType("mock_service") 33 market.RegisterContactUnserializer("mock_contact", 34 func(rawMessage *json.RawMessage) (market.ContactDefinition, error) { 35 return mockContact{}, nil 36 }, 37 ) 38 } 39 40 var ( 41 proposalFirst = func() market.ServiceProposal { 42 return market.NewProposal("0x1", "mock_service", market.NewProposalOpts{ 43 Contacts: []market.Contact{{Type: "mock_contact", Definition: mockContact{}}}, 44 }) 45 } 46 proposalSecond = func() market.ServiceProposal { 47 return market.NewProposal("0x2", "mock_service", market.NewProposalOpts{ 48 Contacts: []market.Contact{{Type: "mock_contact", Definition: mockContact{}}}, 49 }) 50 } 51 ) 52 53 func Test_Subscriber_StartSyncsNewProposals(t *testing.T) { 54 connection := nats.StartConnectionMock() 55 defer connection.Close() 56 57 repo := NewRepository(connection, NewStorage(eventbus.New()), 500*time.Millisecond, 1*time.Second) 58 err := repo.Start() 59 defer repo.Stop() 60 assert.NoError(t, err) 61 62 proposalRegister(connection, ` 63 { 64 "proposal": { 65 "format": "service-proposal/v3", 66 "compatibility": 2, 67 "provider_id": "0x1", 68 "service_type": "mock_service", 69 "contacts": [ 70 { 71 "type": "mock_contact" 72 } 73 ] 74 } 75 } 76 `) 77 78 assert.Eventually(t, proposalCountEquals(repo, 1), 2*time.Second, 10*time.Millisecond) 79 assert.Exactly(t, []market.ServiceProposal{proposalFirst()}, repo.storage.Proposals()) 80 } 81 82 func Test_Subscriber_SkipUnsupportedProposal(t *testing.T) { 83 connection := nats.StartConnectionMock() 84 defer connection.Close() 85 86 repo := NewRepository(connection, NewStorage(eventbus.New()), 500*time.Millisecond, 10*time.Millisecond) 87 err := repo.Start() 88 defer repo.Stop() 89 assert.NoError(t, err) 90 91 proposalRegister(connection, `{ 92 "proposal": {"provider_id": "0x1", "service_type": "unknown"} 93 }`) 94 95 time.Sleep(10 * time.Millisecond) 96 assert.Len(t, repo.storage.Proposals(), 0) 97 assert.Exactly(t, []market.ServiceProposal{}, repo.storage.Proposals()) 98 } 99 100 func Test_Subscriber_StartSyncsIdleProposals(t *testing.T) { 101 connection := nats.StartConnectionMock() 102 defer connection.Close() 103 104 repo := NewRepository(connection, NewStorage(eventbus.New()), 10*time.Millisecond, 10*time.Millisecond) 105 err := repo.Start() 106 defer repo.Stop() 107 assert.NoError(t, err) 108 109 proposalRegister(connection, `{ 110 "proposal": { 111 "format": "service-proposal/v2", 112 "provider_id": "0x1", 113 "service_type": "mock_service", 114 "contacts": [ 115 { 116 "type": "mock_contact" 117 } 118 ] 119 } 120 }`) 121 assert.Eventually(t, proposalCountEquals(repo, 0), 2*time.Second, 10*time.Millisecond) 122 } 123 124 func Test_Subscriber_StartSyncsHealthyProposals(t *testing.T) { 125 connection := nats.StartConnectionMock() 126 defer connection.Close() 127 128 repo := NewRepository(connection, NewStorage(eventbus.New()), 100*time.Millisecond, 10*time.Millisecond) 129 err := repo.Start() 130 defer repo.Stop() 131 assert.NoError(t, err) 132 133 proposalRegister(connection, `{ 134 "proposal": { 135 "format": "service-proposal/v3", 136 "compatibility": 2, 137 "provider_id": "0x1", 138 "service_type": "mock_service", 139 "contacts": [ 140 { 141 "type": "mock_contact" 142 } 143 ] 144 } 145 }`) 146 147 proposalPing(connection, `{ 148 "proposal": { 149 "format": "service-proposal/v3", 150 "compatibility": 2, 151 "provider_id": "0x1", 152 "service_type": "mock_service", 153 "contacts": [ 154 { 155 "type": "mock_contact" 156 } 157 ] 158 } 159 }`) 160 161 assert.Eventually(t, proposalCountEquals(repo, 1), 2*time.Second, 10*time.Millisecond) 162 expected := []market.ServiceProposal{proposalFirst()} 163 actual := repo.storage.Proposals() 164 assert.Exactly(t, expected, actual) 165 } 166 167 func Test_Subscriber_StartSyncsStoppedProposals(t *testing.T) { 168 connection := nats.StartConnectionMock() 169 defer connection.Close() 170 171 repo := NewRepository(connection, NewStorage(eventbus.New()), 500*time.Millisecond, 10*time.Millisecond) 172 repo.storage.AddProposal(proposalFirst(), proposalSecond()) 173 err := repo.Start() 174 defer repo.Stop() 175 assert.NoError(t, err) 176 177 proposalUnregister(connection, `{ 178 "proposal": { 179 "format": "service-proposal/v2", 180 "provider_id": "0x1", 181 "service_type": "mock_service", 182 "contacts": [ 183 { 184 "type": "mock_contact" 185 } 186 ] 187 } 188 }`) 189 } 190 191 func proposalRegister(connection nats.Connection, payload string) { 192 err := connection.Publish("*.proposal-register.v3", []byte(payload)) 193 if err != nil { 194 panic(err) 195 } 196 } 197 198 func proposalUnregister(connection nats.Connection, payload string) { 199 err := connection.Publish("*.proposal-unregister.v3", []byte(payload)) 200 if err != nil { 201 panic(err) 202 } 203 } 204 205 func proposalPing(connection nats.Connection, payload string) { 206 err := connection.Publish("*.proposal-ping.v3", []byte(payload)) 207 if err != nil { 208 panic(err) 209 } 210 } 211 212 func proposalCountEquals(subscriber *Repository, count int) func() bool { 213 return func() bool { 214 return len(subscriber.storage.Proposals()) == count 215 } 216 } 217 218 type mockContact struct{}