github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/model/flow/factory/cluster_list_test.go (about)

     1  package factory_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/require"
     7  
     8  	"github.com/onflow/flow-go/model/flow"
     9  	"github.com/onflow/flow-go/model/flow/factory"
    10  	"github.com/onflow/flow-go/utils/unittest"
    11  )
    12  
    13  // TestNewClusterList ensures that implementation enforces the following protocol rules in case they are violated:
    14  //
    15  //	(a) input `collectors` only contains collector nodes with positive weight
    16  //	(b) collectors have unique node IDs
    17  //	(c) each collector is assigned exactly to one cluster and is only listed once within that cluster
    18  //	(d) cluster contains at least one collector (i.e. is not empty)
    19  //	(e) cluster is composed of known nodes, i.e. for each nodeID in `assignments` an IdentitySkeleton is given in `collectors`
    20  //	(f) cluster assignment lists the nodes in canonical ordering
    21  func TestNewClusterList(t *testing.T) {
    22  	identities := unittest.IdentityListFixture(100, unittest.WithRole(flow.RoleCollection))
    23  
    24  	t.Run("valid inputs", func(t *testing.T) {
    25  		assignments := unittest.ClusterAssignment(10, identities.ToSkeleton())
    26  		_, err := factory.NewClusterList(assignments, identities.ToSkeleton())
    27  		require.NoError(t, err)
    28  	})
    29  	t.Run("(a) input `collectors` only contains collector nodes with positive weight", func(t *testing.T) {
    30  		identities := identities.Copy()
    31  		identities[0].InitialWeight = 0
    32  		assignments := unittest.ClusterAssignment(10, identities.ToSkeleton())
    33  		_, err := factory.NewClusterList(assignments, identities.ToSkeleton())
    34  		require.Error(t, err)
    35  	})
    36  	t.Run("(b) collectors have unique node IDs", func(t *testing.T) {
    37  		identities := identities.Copy()
    38  		identities[0].NodeID = identities[1].NodeID
    39  		assignments := unittest.ClusterAssignment(10, identities.ToSkeleton())
    40  		_, err := factory.NewClusterList(assignments, identities.ToSkeleton())
    41  		require.Error(t, err)
    42  	})
    43  	t.Run("(c) each collector is assigned exactly to one cluster", func(t *testing.T) {
    44  		assignments := unittest.ClusterAssignment(10, identities.ToSkeleton())
    45  		assignments[1][0] = assignments[0][0]
    46  		_, err := factory.NewClusterList(assignments, identities.ToSkeleton())
    47  		require.Error(t, err)
    48  	})
    49  	t.Run("(c) each collector is only listed once within that cluster", func(t *testing.T) {
    50  		assignments := unittest.ClusterAssignment(10, identities.ToSkeleton())
    51  		assignments[0][0] = assignments[0][1]
    52  		_, err := factory.NewClusterList(assignments, identities.ToSkeleton())
    53  		require.Error(t, err)
    54  	})
    55  	t.Run("(d) cluster contains at least one collector (i.e. is not empty)", func(t *testing.T) {
    56  		assignments := unittest.ClusterAssignment(10, identities.ToSkeleton())
    57  		assignments[0] = flow.IdentifierList{}
    58  		_, err := factory.NewClusterList(assignments, identities.ToSkeleton())
    59  		require.Error(t, err)
    60  	})
    61  	t.Run("(e) cluster is composed of known nodes, i.e. for each nodeID in `assignments` an IdentitySkeleton is given in `collectors` ", func(t *testing.T) {
    62  		assignments := unittest.ClusterAssignment(10, identities.ToSkeleton())
    63  		assignments[0][0] = unittest.IdentifierFixture()
    64  		_, err := factory.NewClusterList(assignments, identities.ToSkeleton())
    65  		require.Error(t, err)
    66  	})
    67  	t.Run("(f) cluster assignment lists the nodes in canonical ordering", func(t *testing.T) {
    68  		assignments := unittest.ClusterAssignment(10, identities.ToSkeleton())
    69  		// sort in non-canonical order
    70  		assignments[0] = assignments[0].Sort(func(lhs flow.Identifier, rhs flow.Identifier) int {
    71  			return -flow.IdentifierCanonical(lhs, rhs)
    72  		})
    73  		_, err := factory.NewClusterList(assignments, identities.ToSkeleton())
    74  		require.Error(t, err)
    75  	})
    76  }