github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/broadcast/syshandler_network_node_test.go (about) 1 // Copyright © 2021 Kaleido, Inc. 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package broadcast 18 19 import ( 20 "context" 21 "encoding/json" 22 "fmt" 23 "testing" 24 25 "github.com/kaleido-io/firefly/mocks/databasemocks" 26 "github.com/kaleido-io/firefly/mocks/dataexchangemocks" 27 "github.com/kaleido-io/firefly/mocks/identitymocks" 28 "github.com/kaleido-io/firefly/pkg/fftypes" 29 "github.com/stretchr/testify/assert" 30 "github.com/stretchr/testify/mock" 31 ) 32 33 func TestHandleSystemBroadcastNodeOk(t *testing.T) { 34 bm, cancel := newTestBroadcast(t) 35 defer cancel() 36 37 node := &fftypes.Node{ 38 ID: fftypes.NewUUID(), 39 Name: "node1", 40 Owner: "0x23456", 41 Description: "my org", 42 DX: fftypes.DXInfo{ 43 Peer: "peer1", 44 Endpoint: fftypes.JSONObject{"some": "info"}, 45 }, 46 } 47 b, err := json.Marshal(&node) 48 assert.NoError(t, err) 49 data := &fftypes.Data{ 50 Value: fftypes.Byteable(b), 51 } 52 53 mii := bm.identity.(*identitymocks.Plugin) 54 mii.On("Resolve", mock.Anything, "0x23456").Return(&fftypes.Identity{OnChain: "0x23456"}, nil) 55 mdi := bm.database.(*databasemocks.Plugin) 56 mdi.On("GetOrganizationByIdentity", mock.Anything, "0x23456").Return(&fftypes.Organization{ID: fftypes.NewUUID(), Identity: "0x23456"}, nil) 57 mdi.On("GetNode", mock.Anything, "0x23456", "node1").Return(nil, nil) 58 mdi.On("GetNodeByID", mock.Anything, node.ID).Return(nil, nil) 59 mdi.On("UpsertNode", mock.Anything, mock.Anything, true).Return(nil) 60 mdx := bm.exchange.(*dataexchangemocks.Plugin) 61 mdx.On("AddPeer", mock.Anything, mock.Anything).Return(nil) 62 valid, err := bm.HandleSystemBroadcast(context.Background(), &fftypes.Message{ 63 Header: fftypes.MessageHeader{ 64 Namespace: "ns1", 65 Author: "0x23456", 66 Tag: string(fftypes.SystemTagDefineNode), 67 }, 68 }, []*fftypes.Data{data}) 69 assert.True(t, valid) 70 assert.NoError(t, err) 71 72 mii.AssertExpectations(t) 73 mdi.AssertExpectations(t) 74 } 75 76 func TestHandleSystemBroadcastNodeUpsertFail(t *testing.T) { 77 bm, cancel := newTestBroadcast(t) 78 defer cancel() 79 80 node := &fftypes.Node{ 81 ID: fftypes.NewUUID(), 82 Name: "node1", 83 Owner: "0x23456", 84 Description: "my org", 85 DX: fftypes.DXInfo{ 86 Peer: "peer1", 87 Endpoint: fftypes.JSONObject{"some": "info"}, 88 }, 89 } 90 b, err := json.Marshal(&node) 91 assert.NoError(t, err) 92 data := &fftypes.Data{ 93 Value: fftypes.Byteable(b), 94 } 95 96 mii := bm.identity.(*identitymocks.Plugin) 97 mii.On("Resolve", mock.Anything, "0x23456").Return(&fftypes.Identity{OnChain: "0x23456"}, nil) 98 mdi := bm.database.(*databasemocks.Plugin) 99 mdi.On("GetOrganizationByIdentity", mock.Anything, "0x23456").Return(&fftypes.Organization{ID: fftypes.NewUUID(), Identity: "0x23456"}, nil) 100 mdi.On("GetNode", mock.Anything, "0x23456", "node1").Return(nil, nil) 101 mdi.On("GetNodeByID", mock.Anything, node.ID).Return(nil, nil) 102 mdi.On("UpsertNode", mock.Anything, mock.Anything, true).Return(fmt.Errorf("pop")) 103 valid, err := bm.HandleSystemBroadcast(context.Background(), &fftypes.Message{ 104 Header: fftypes.MessageHeader{ 105 Namespace: "ns1", 106 Author: "0x23456", 107 Tag: string(fftypes.SystemTagDefineNode), 108 }, 109 }, []*fftypes.Data{data}) 110 assert.False(t, valid) 111 assert.EqualError(t, err, "pop") 112 113 mii.AssertExpectations(t) 114 mdi.AssertExpectations(t) 115 } 116 117 func TestHandleSystemBroadcastNodeAddPeerFail(t *testing.T) { 118 bm, cancel := newTestBroadcast(t) 119 defer cancel() 120 121 node := &fftypes.Node{ 122 ID: fftypes.NewUUID(), 123 Name: "node1", 124 Owner: "0x23456", 125 Description: "my org", 126 DX: fftypes.DXInfo{ 127 Peer: "peer1", 128 Endpoint: fftypes.JSONObject{"some": "info"}, 129 }, 130 } 131 b, err := json.Marshal(&node) 132 assert.NoError(t, err) 133 data := &fftypes.Data{ 134 Value: fftypes.Byteable(b), 135 } 136 137 mii := bm.identity.(*identitymocks.Plugin) 138 mii.On("Resolve", mock.Anything, "0x23456").Return(&fftypes.Identity{OnChain: "0x23456"}, nil) 139 mdi := bm.database.(*databasemocks.Plugin) 140 mdi.On("GetOrganizationByIdentity", mock.Anything, "0x23456").Return(&fftypes.Organization{ID: fftypes.NewUUID(), Identity: "0x23456"}, nil) 141 mdi.On("GetNode", mock.Anything, "0x23456", "node1").Return(nil, nil) 142 mdi.On("GetNodeByID", mock.Anything, node.ID).Return(nil, nil) 143 mdi.On("UpsertNode", mock.Anything, mock.Anything, true).Return(nil) 144 mdx := bm.exchange.(*dataexchangemocks.Plugin) 145 mdx.On("AddPeer", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) 146 valid, err := bm.HandleSystemBroadcast(context.Background(), &fftypes.Message{ 147 Header: fftypes.MessageHeader{ 148 Namespace: "ns1", 149 Author: "0x23456", 150 Tag: string(fftypes.SystemTagDefineNode), 151 }, 152 }, []*fftypes.Data{data}) 153 assert.False(t, valid) 154 assert.EqualError(t, err, "pop") 155 156 mii.AssertExpectations(t) 157 mdi.AssertExpectations(t) 158 } 159 160 func TestHandleSystemBroadcastNodeDupMismatch(t *testing.T) { 161 bm, cancel := newTestBroadcast(t) 162 defer cancel() 163 164 node := &fftypes.Node{ 165 ID: fftypes.NewUUID(), 166 Name: "node1", 167 Owner: "0x23456", 168 Description: "my org", 169 DX: fftypes.DXInfo{ 170 Peer: "peer1", 171 Endpoint: fftypes.JSONObject{"some": "info"}, 172 }, 173 } 174 b, err := json.Marshal(&node) 175 assert.NoError(t, err) 176 data := &fftypes.Data{ 177 Value: fftypes.Byteable(b), 178 } 179 180 mii := bm.identity.(*identitymocks.Plugin) 181 mii.On("Resolve", mock.Anything, "0x23456").Return(&fftypes.Identity{OnChain: "0x23456"}, nil) 182 mdi := bm.database.(*databasemocks.Plugin) 183 mdi.On("GetOrganizationByIdentity", mock.Anything, "0x23456").Return(&fftypes.Organization{ID: fftypes.NewUUID(), Identity: "0x23456"}, nil) 184 mdi.On("GetNode", mock.Anything, "0x23456", "node1").Return(&fftypes.Node{Owner: "0x99999"}, nil) 185 valid, err := bm.HandleSystemBroadcast(context.Background(), &fftypes.Message{ 186 Header: fftypes.MessageHeader{ 187 Namespace: "ns1", 188 Author: "0x23456", 189 Tag: string(fftypes.SystemTagDefineNode), 190 }, 191 }, []*fftypes.Data{data}) 192 assert.False(t, valid) 193 assert.NoError(t, err) 194 195 mii.AssertExpectations(t) 196 mdi.AssertExpectations(t) 197 } 198 199 func TestHandleSystemBroadcastNodeDupOK(t *testing.T) { 200 bm, cancel := newTestBroadcast(t) 201 defer cancel() 202 203 node := &fftypes.Node{ 204 ID: fftypes.NewUUID(), 205 Name: "node1", 206 Owner: "0x23456", 207 Description: "my org", 208 DX: fftypes.DXInfo{ 209 Peer: "peer1", 210 Endpoint: fftypes.JSONObject{"some": "info"}, 211 }, 212 } 213 b, err := json.Marshal(&node) 214 assert.NoError(t, err) 215 data := &fftypes.Data{ 216 Value: fftypes.Byteable(b), 217 } 218 219 mii := bm.identity.(*identitymocks.Plugin) 220 mii.On("Resolve", mock.Anything, "0x23456").Return(&fftypes.Identity{OnChain: "0x23456"}, nil) 221 mdi := bm.database.(*databasemocks.Plugin) 222 mdi.On("GetOrganizationByIdentity", mock.Anything, "0x23456").Return(&fftypes.Organization{ID: fftypes.NewUUID(), Identity: "0x23456"}, nil) 223 mdi.On("GetNode", mock.Anything, "0x23456", "node1").Return(&fftypes.Node{Owner: "0x23456"}, nil) 224 mdi.On("UpsertNode", mock.Anything, mock.Anything, true).Return(nil) 225 mdx := bm.exchange.(*dataexchangemocks.Plugin) 226 mdx.On("AddPeer", mock.Anything, mock.Anything).Return(nil) 227 valid, err := bm.HandleSystemBroadcast(context.Background(), &fftypes.Message{ 228 Header: fftypes.MessageHeader{ 229 Namespace: "ns1", 230 Author: "0x23456", 231 Tag: string(fftypes.SystemTagDefineNode), 232 }, 233 }, []*fftypes.Data{data}) 234 assert.True(t, valid) 235 assert.NoError(t, err) 236 237 mii.AssertExpectations(t) 238 mdi.AssertExpectations(t) 239 } 240 241 func TestHandleSystemBroadcastNodeGetFail(t *testing.T) { 242 bm, cancel := newTestBroadcast(t) 243 defer cancel() 244 245 node := &fftypes.Node{ 246 ID: fftypes.NewUUID(), 247 Name: "node1", 248 Owner: "0x23456", 249 Description: "my org", 250 DX: fftypes.DXInfo{ 251 Peer: "peer1", 252 Endpoint: fftypes.JSONObject{"some": "info"}, 253 }, 254 } 255 b, err := json.Marshal(&node) 256 assert.NoError(t, err) 257 data := &fftypes.Data{ 258 Value: fftypes.Byteable(b), 259 } 260 261 mii := bm.identity.(*identitymocks.Plugin) 262 mii.On("Resolve", mock.Anything, "0x23456").Return(&fftypes.Identity{OnChain: "0x23456"}, nil) 263 mdi := bm.database.(*databasemocks.Plugin) 264 mdi.On("GetOrganizationByIdentity", mock.Anything, "0x23456").Return(&fftypes.Organization{ID: fftypes.NewUUID(), Identity: "0x23456"}, nil) 265 mdi.On("GetNode", mock.Anything, "0x23456", "node1").Return(nil, fmt.Errorf("pop")) 266 valid, err := bm.HandleSystemBroadcast(context.Background(), &fftypes.Message{ 267 Header: fftypes.MessageHeader{ 268 Namespace: "ns1", 269 Author: "0x23456", 270 Tag: string(fftypes.SystemTagDefineNode), 271 }, 272 }, []*fftypes.Data{data}) 273 assert.False(t, valid) 274 assert.EqualError(t, err, "pop") 275 276 mii.AssertExpectations(t) 277 mdi.AssertExpectations(t) 278 } 279 280 func TestHandleSystemBroadcastNodeBadAuthor(t *testing.T) { 281 bm, cancel := newTestBroadcast(t) 282 defer cancel() 283 284 node := &fftypes.Node{ 285 ID: fftypes.NewUUID(), 286 Name: "node1", 287 Owner: "0x23456", 288 Description: "my org", 289 DX: fftypes.DXInfo{ 290 Peer: "peer1", 291 Endpoint: fftypes.JSONObject{"some": "info"}, 292 }, 293 } 294 b, err := json.Marshal(&node) 295 assert.NoError(t, err) 296 data := &fftypes.Data{ 297 Value: fftypes.Byteable(b), 298 } 299 300 mii := bm.identity.(*identitymocks.Plugin) 301 mii.On("Resolve", mock.Anything, "0x23456").Return(&fftypes.Identity{OnChain: "0x23456"}, nil) 302 mdi := bm.database.(*databasemocks.Plugin) 303 mdi.On("GetOrganizationByIdentity", mock.Anything, "0x23456").Return(&fftypes.Organization{ID: fftypes.NewUUID(), Identity: "0x23456"}, nil) 304 valid, err := bm.HandleSystemBroadcast(context.Background(), &fftypes.Message{ 305 Header: fftypes.MessageHeader{ 306 Namespace: "ns1", 307 Author: "0x99999", 308 Tag: string(fftypes.SystemTagDefineNode), 309 }, 310 }, []*fftypes.Data{data}) 311 assert.False(t, valid) 312 assert.NoError(t, err) 313 314 mii.AssertExpectations(t) 315 mdi.AssertExpectations(t) 316 } 317 318 func TestHandleSystemBroadcastNodeResolveFail(t *testing.T) { 319 bm, cancel := newTestBroadcast(t) 320 defer cancel() 321 322 node := &fftypes.Node{ 323 ID: fftypes.NewUUID(), 324 Name: "node1", 325 Owner: "0x23456", 326 Description: "my org", 327 DX: fftypes.DXInfo{ 328 Peer: "peer1", 329 Endpoint: fftypes.JSONObject{"some": "info"}, 330 }, 331 } 332 b, err := json.Marshal(&node) 333 assert.NoError(t, err) 334 data := &fftypes.Data{ 335 Value: fftypes.Byteable(b), 336 } 337 338 mii := bm.identity.(*identitymocks.Plugin) 339 mii.On("Resolve", mock.Anything, "0x23456").Return(nil, fmt.Errorf("pop")) 340 mdi := bm.database.(*databasemocks.Plugin) 341 mdi.On("GetOrganizationByIdentity", mock.Anything, "0x23456").Return(&fftypes.Organization{ID: fftypes.NewUUID(), Identity: "0x23456"}, nil) 342 valid, err := bm.HandleSystemBroadcast(context.Background(), &fftypes.Message{ 343 Header: fftypes.MessageHeader{ 344 Namespace: "ns1", 345 Author: "0x23456", 346 Tag: string(fftypes.SystemTagDefineNode), 347 }, 348 }, []*fftypes.Data{data}) 349 assert.False(t, valid) 350 assert.NoError(t, err) 351 352 mii.AssertExpectations(t) 353 mdi.AssertExpectations(t) 354 } 355 356 func TestHandleSystemBroadcastNodeGetOrgNotFound(t *testing.T) { 357 bm, cancel := newTestBroadcast(t) 358 defer cancel() 359 360 node := &fftypes.Node{ 361 ID: fftypes.NewUUID(), 362 Name: "node1", 363 Owner: "0x23456", 364 Description: "my org", 365 DX: fftypes.DXInfo{ 366 Peer: "peer1", 367 Endpoint: fftypes.JSONObject{"some": "info"}, 368 }, 369 } 370 b, err := json.Marshal(&node) 371 assert.NoError(t, err) 372 data := &fftypes.Data{ 373 Value: fftypes.Byteable(b), 374 } 375 376 mdi := bm.database.(*databasemocks.Plugin) 377 mdi.On("GetOrganizationByIdentity", mock.Anything, "0x23456").Return(nil, nil) 378 valid, err := bm.HandleSystemBroadcast(context.Background(), &fftypes.Message{ 379 Header: fftypes.MessageHeader{ 380 Namespace: "ns1", 381 Author: "0x23456", 382 Tag: string(fftypes.SystemTagDefineNode), 383 }, 384 }, []*fftypes.Data{data}) 385 assert.False(t, valid) 386 assert.NoError(t, err) 387 388 mdi.AssertExpectations(t) 389 } 390 391 func TestHandleSystemBroadcastNodeGetOrgFail(t *testing.T) { 392 bm, cancel := newTestBroadcast(t) 393 defer cancel() 394 395 node := &fftypes.Node{ 396 ID: fftypes.NewUUID(), 397 Name: "node1", 398 Owner: "0x23456", 399 Description: "my org", 400 DX: fftypes.DXInfo{ 401 Peer: "peer1", 402 Endpoint: fftypes.JSONObject{"some": "info"}, 403 }, 404 } 405 b, err := json.Marshal(&node) 406 assert.NoError(t, err) 407 data := &fftypes.Data{ 408 Value: fftypes.Byteable(b), 409 } 410 411 mdi := bm.database.(*databasemocks.Plugin) 412 mdi.On("GetOrganizationByIdentity", mock.Anything, "0x23456").Return(nil, fmt.Errorf("pop")) 413 valid, err := bm.HandleSystemBroadcast(context.Background(), &fftypes.Message{ 414 Header: fftypes.MessageHeader{ 415 Namespace: "ns1", 416 Author: "0x23456", 417 Tag: string(fftypes.SystemTagDefineNode), 418 }, 419 }, []*fftypes.Data{data}) 420 assert.False(t, valid) 421 assert.EqualError(t, err, "pop") 422 423 mdi.AssertExpectations(t) 424 } 425 426 func TestHandleSystemBroadcastNodeValidateFail(t *testing.T) { 427 bm, cancel := newTestBroadcast(t) 428 defer cancel() 429 430 node := &fftypes.Node{ 431 ID: fftypes.NewUUID(), 432 Name: "node1", 433 Owner: "0x23456", 434 Description: string(make([]byte, 4097)), 435 DX: fftypes.DXInfo{ 436 Peer: "peer1", 437 Endpoint: fftypes.JSONObject{"some": "info"}, 438 }, 439 } 440 b, err := json.Marshal(&node) 441 assert.NoError(t, err) 442 data := &fftypes.Data{ 443 Value: fftypes.Byteable(b), 444 } 445 446 valid, err := bm.HandleSystemBroadcast(context.Background(), &fftypes.Message{ 447 Header: fftypes.MessageHeader{ 448 Namespace: "ns1", 449 Author: "0x23456", 450 Tag: string(fftypes.SystemTagDefineNode), 451 }, 452 }, []*fftypes.Data{data}) 453 assert.False(t, valid) 454 assert.NoError(t, err) 455 } 456 457 func TestHandleSystemBroadcastNodeUnmarshalFail(t *testing.T) { 458 bm, cancel := newTestBroadcast(t) 459 defer cancel() 460 461 data := &fftypes.Data{ 462 Value: fftypes.Byteable(`!json`), 463 } 464 465 valid, err := bm.HandleSystemBroadcast(context.Background(), &fftypes.Message{ 466 Header: fftypes.MessageHeader{ 467 Namespace: "ns1", 468 Author: "0x23456", 469 Tag: string(fftypes.SystemTagDefineNode), 470 }, 471 }, []*fftypes.Data{data}) 472 assert.False(t, valid) 473 assert.NoError(t, err) 474 }