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  }