github.com/MetalBlockchain/metalgo@v1.11.9/snow/consensus/snowball/parameters_test.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package snowball
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  func TestParametersVerify(t *testing.T) {
    13  	tests := []struct {
    14  		name          string
    15  		params        Parameters
    16  		expectedError error
    17  	}{
    18  		{
    19  			name: "valid",
    20  			params: Parameters{
    21  				K:                     1,
    22  				AlphaPreference:       1,
    23  				AlphaConfidence:       1,
    24  				Beta:                  1,
    25  				ConcurrentRepolls:     1,
    26  				OptimalProcessing:     1,
    27  				MaxOutstandingItems:   1,
    28  				MaxItemProcessingTime: 1,
    29  			},
    30  			expectedError: nil,
    31  		},
    32  		{
    33  			name: "invalid K",
    34  			params: Parameters{
    35  				K:                     0,
    36  				AlphaPreference:       1,
    37  				AlphaConfidence:       1,
    38  				Beta:                  1,
    39  				ConcurrentRepolls:     1,
    40  				OptimalProcessing:     1,
    41  				MaxOutstandingItems:   1,
    42  				MaxItemProcessingTime: 1,
    43  			},
    44  			expectedError: ErrParametersInvalid,
    45  		},
    46  		{
    47  			name: "invalid AlphaPreference 1",
    48  			params: Parameters{
    49  				K:                     2,
    50  				AlphaPreference:       1,
    51  				AlphaConfidence:       1,
    52  				Beta:                  1,
    53  				ConcurrentRepolls:     1,
    54  				OptimalProcessing:     1,
    55  				MaxOutstandingItems:   1,
    56  				MaxItemProcessingTime: 1,
    57  			},
    58  			expectedError: ErrParametersInvalid,
    59  		},
    60  		{
    61  			name: "invalid AlphaPreference 0",
    62  			params: Parameters{
    63  				K:                     1,
    64  				AlphaPreference:       0,
    65  				AlphaConfidence:       1,
    66  				Beta:                  1,
    67  				ConcurrentRepolls:     1,
    68  				OptimalProcessing:     1,
    69  				MaxOutstandingItems:   1,
    70  				MaxItemProcessingTime: 1,
    71  			},
    72  			expectedError: ErrParametersInvalid,
    73  		},
    74  		{
    75  			name: "invalid AlphaConfidence",
    76  			params: Parameters{
    77  				K:                     3,
    78  				AlphaPreference:       3,
    79  				AlphaConfidence:       2,
    80  				Beta:                  1,
    81  				ConcurrentRepolls:     1,
    82  				OptimalProcessing:     1,
    83  				MaxOutstandingItems:   1,
    84  				MaxItemProcessingTime: 1,
    85  			},
    86  			expectedError: ErrParametersInvalid,
    87  		},
    88  		{
    89  			name: "invalid beta",
    90  			params: Parameters{
    91  				K:                     1,
    92  				AlphaPreference:       1,
    93  				AlphaConfidence:       1,
    94  				Beta:                  0,
    95  				ConcurrentRepolls:     1,
    96  				OptimalProcessing:     1,
    97  				MaxOutstandingItems:   1,
    98  				MaxItemProcessingTime: 1,
    99  			},
   100  			expectedError: ErrParametersInvalid,
   101  		},
   102  		{
   103  			name: "first half fun alphaConfidence",
   104  			params: Parameters{
   105  				K:                     30,
   106  				AlphaPreference:       28,
   107  				AlphaConfidence:       30,
   108  				Beta:                  2,
   109  				ConcurrentRepolls:     1,
   110  				OptimalProcessing:     1,
   111  				MaxOutstandingItems:   1,
   112  				MaxItemProcessingTime: 1,
   113  			},
   114  			expectedError: nil,
   115  		},
   116  		{
   117  			name: "second half fun alphaConfidence",
   118  			params: Parameters{
   119  				K:                     3,
   120  				AlphaPreference:       2,
   121  				AlphaConfidence:       3,
   122  				Beta:                  2,
   123  				ConcurrentRepolls:     1,
   124  				OptimalProcessing:     1,
   125  				MaxOutstandingItems:   1,
   126  				MaxItemProcessingTime: 1,
   127  			},
   128  			expectedError: nil,
   129  		},
   130  		{
   131  			name: "fun invalid alphaConfidence",
   132  			params: Parameters{
   133  				K:                     1,
   134  				AlphaPreference:       28,
   135  				AlphaConfidence:       3,
   136  				Beta:                  2,
   137  				ConcurrentRepolls:     1,
   138  				OptimalProcessing:     1,
   139  				MaxOutstandingItems:   1,
   140  				MaxItemProcessingTime: 1,
   141  			},
   142  			expectedError: ErrParametersInvalid,
   143  		},
   144  		{
   145  			name: "too few ConcurrentRepolls",
   146  			params: Parameters{
   147  				K:                     1,
   148  				AlphaPreference:       1,
   149  				AlphaConfidence:       1,
   150  				Beta:                  1,
   151  				ConcurrentRepolls:     0,
   152  				OptimalProcessing:     1,
   153  				MaxOutstandingItems:   1,
   154  				MaxItemProcessingTime: 1,
   155  			},
   156  			expectedError: ErrParametersInvalid,
   157  		},
   158  		{
   159  			name: "too many ConcurrentRepolls",
   160  			params: Parameters{
   161  				K:                     1,
   162  				AlphaPreference:       1,
   163  				AlphaConfidence:       1,
   164  				Beta:                  1,
   165  				ConcurrentRepolls:     2,
   166  				OptimalProcessing:     1,
   167  				MaxOutstandingItems:   1,
   168  				MaxItemProcessingTime: 1,
   169  			},
   170  			expectedError: ErrParametersInvalid,
   171  		},
   172  		{
   173  			name: "invalid OptimalProcessing",
   174  			params: Parameters{
   175  				K:                     1,
   176  				AlphaPreference:       1,
   177  				AlphaConfidence:       1,
   178  				Beta:                  1,
   179  				ConcurrentRepolls:     1,
   180  				OptimalProcessing:     0,
   181  				MaxOutstandingItems:   1,
   182  				MaxItemProcessingTime: 1,
   183  			},
   184  			expectedError: ErrParametersInvalid,
   185  		},
   186  		{
   187  			name: "invalid MaxOutstandingItems",
   188  			params: Parameters{
   189  				K:                     1,
   190  				AlphaPreference:       1,
   191  				AlphaConfidence:       1,
   192  				Beta:                  1,
   193  				ConcurrentRepolls:     1,
   194  				OptimalProcessing:     1,
   195  				MaxOutstandingItems:   0,
   196  				MaxItemProcessingTime: 1,
   197  			},
   198  			expectedError: ErrParametersInvalid,
   199  		},
   200  		{
   201  			name: "invalid MaxItemProcessingTime",
   202  			params: Parameters{
   203  				K:                     1,
   204  				AlphaPreference:       1,
   205  				AlphaConfidence:       1,
   206  				Beta:                  1,
   207  				ConcurrentRepolls:     1,
   208  				OptimalProcessing:     1,
   209  				MaxOutstandingItems:   1,
   210  				MaxItemProcessingTime: 0,
   211  			},
   212  			expectedError: ErrParametersInvalid,
   213  		},
   214  	}
   215  	for _, test := range tests {
   216  		t.Run(test.name, func(t *testing.T) {
   217  			err := test.params.Verify()
   218  			require.ErrorIs(t, err, test.expectedError)
   219  		})
   220  	}
   221  }
   222  
   223  func TestParametersMinPercentConnectedHealthy(t *testing.T) {
   224  	tests := []struct {
   225  		name                        string
   226  		params                      Parameters
   227  		expectedMinPercentConnected float64
   228  	}{
   229  		{
   230  			name:                        "default",
   231  			params:                      DefaultParameters,
   232  			expectedMinPercentConnected: 0.8,
   233  		},
   234  		{
   235  			name: "custom",
   236  			params: Parameters{
   237  				K:               5,
   238  				AlphaConfidence: 4,
   239  			},
   240  			expectedMinPercentConnected: 0.84,
   241  		},
   242  		{
   243  			name: "custom",
   244  			params: Parameters{
   245  				K:               1001,
   246  				AlphaConfidence: 501,
   247  			},
   248  			expectedMinPercentConnected: 0.6,
   249  		},
   250  	}
   251  
   252  	for _, tt := range tests {
   253  		t.Run(tt.name, func(t *testing.T) {
   254  			minStake := tt.params.MinPercentConnectedHealthy()
   255  			require.InEpsilon(t, tt.expectedMinPercentConnected, minStake, .001)
   256  		})
   257  	}
   258  }