github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/consensus/hotstuff/cruisectl/aggregators_test.go (about)

     1  package cruisectl
     2  
     3  import (
     4  	"math"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  )
     9  
    10  // Test_Instantiation verifies successful instantiation of Ewma
    11  func Test_EWMA_Instantiation(t *testing.T) {
    12  	w, err := NewEwma(0.5, 17.2)
    13  	require.NoError(t, err)
    14  	require.Equal(t, 17.2, w.Value())
    15  }
    16  
    17  // Test_EnforceNumericalBounds verifies that constructor only accepts
    18  // alpha values that satisfy 0 < alpha  < 1
    19  func Test_EWMA_EnforceNumericalBounds(t *testing.T) {
    20  	for _, alpha := range []float64{-1, 0, 1, 2} {
    21  		_, err := NewEwma(alpha, 17.2)
    22  		require.Error(t, err)
    23  	}
    24  }
    25  
    26  // Test_AddingObservations verifies correct numerics when adding a single value.
    27  // Reference values were generated via python
    28  func Test_EWMA_AddingObservations(t *testing.T) {
    29  	alpha := math.Pi / 7.0
    30  	initialValue := 17.0
    31  	w, err := NewEwma(alpha, initialValue)
    32  	require.NoError(t, err)
    33  
    34  	v := w.AddObservation(6.0)
    35  	require.InEpsilon(t, 12.063211544358897, v, 1e-12)
    36  	require.InEpsilon(t, 12.063211544358897, w.Value(), 1e-12)
    37  	v = w.AddObservation(-1.16)
    38  	require.InEpsilon(t, 6.128648080841518, v, 1e-12)
    39  	require.InEpsilon(t, 6.128648080841518, w.Value(), 1e-12)
    40  	v = w.AddObservation(1.23)
    41  	require.InEpsilon(t, 3.9301399632281675, v, 1e-12)
    42  	require.InEpsilon(t, 3.9301399632281675, w.Value(), 1e-12)
    43  }
    44  
    45  // Test_AddingRepeatedObservations verifies correct numerics when repeated observations.
    46  // Reference values were generated via python
    47  func Test_EWMA_AddingRepeatedObservations(t *testing.T) {
    48  	alpha := math.Pi / 7.0
    49  	initialValue := 17.0
    50  	w, err := NewEwma(alpha, initialValue)
    51  	require.NoError(t, err)
    52  
    53  	v := w.AddRepeatedObservation(6.0, 11)
    54  	require.InEpsilon(t, 6.015696509200239, v, 1e-12)
    55  	require.InEpsilon(t, 6.015696509200239, w.Value(), 1e-12)
    56  	v = w.AddRepeatedObservation(-1.16, 4)
    57  	require.InEpsilon(t, -0.49762458373978324, v, 1e-12)
    58  	require.InEpsilon(t, -0.49762458373978324, w.Value(), 1e-12)
    59  	v = w.AddRepeatedObservation(1.23, 1)
    60  	require.InEpsilon(t, 0.27773151632279214, v, 1e-12)
    61  	require.InEpsilon(t, 0.27773151632279214, w.Value(), 1e-12)
    62  }
    63  
    64  // Test_AddingRepeatedObservations_selfConsistency applies a self-consistency check
    65  // for  repeated observations.
    66  func Test_EWMA_AddingRepeatedObservations_selfConsistency(t *testing.T) {
    67  	alpha := math.Pi / 7.0
    68  	initialValue := 17.0
    69  	w1, err := NewEwma(alpha, initialValue)
    70  	require.NoError(t, err)
    71  	w2, err := NewEwma(alpha, initialValue)
    72  	require.NoError(t, err)
    73  
    74  	for i := 7; i > 0; i-- {
    75  		w1.AddObservation(6.0)
    76  	}
    77  	v := w2.AddRepeatedObservation(6.0, 7)
    78  	require.InEpsilon(t, w1.Value(), v, 1e-12)
    79  	require.InEpsilon(t, w1.Value(), w2.Value(), 1e-12)
    80  
    81  	for i := 4; i > 0; i-- {
    82  		w2.AddObservation(6.0)
    83  	}
    84  	v = w1.AddRepeatedObservation(6.0, 4)
    85  	require.InEpsilon(t, w2.Value(), v, 1e-12)
    86  	require.InEpsilon(t, w2.Value(), w1.Value(), 1e-12)
    87  }
    88  
    89  // Test_LI_Instantiation verifies successful instantiation of LeakyIntegrator
    90  func Test_LI_Instantiation(t *testing.T) {
    91  	li, err := NewLeakyIntegrator(0.5, 17.2)
    92  	require.NoError(t, err)
    93  	require.Equal(t, 17.2, li.Value())
    94  }
    95  
    96  // Test_EnforceNumericalBounds verifies that constructor only accepts
    97  // alpha values that satisfy 0 < alpha  < 1
    98  func Test_LI_EnforceNumericalBounds(t *testing.T) {
    99  	for _, beta := range []float64{-1, 0, 1, 2} {
   100  		_, err := NewLeakyIntegrator(beta, 17.2)
   101  		require.Error(t, err)
   102  	}
   103  }
   104  
   105  // Test_AddingObservations verifies correct numerics when adding a single value.
   106  // Reference values were generated via python
   107  func Test_LI_AddingObservations(t *testing.T) {
   108  	beta := math.Pi / 7.0
   109  	initialValue := 17.0
   110  	li, err := NewLeakyIntegrator(beta, initialValue)
   111  	require.NoError(t, err)
   112  
   113  	v := li.AddObservation(6.0)
   114  	require.InEpsilon(t, 15.370417841281931, v, 1e-12)
   115  	require.InEpsilon(t, 15.370417841281931, li.Value(), 1e-12)
   116  	v = li.AddObservation(-1.16)
   117  	require.InEpsilon(t, 7.312190445170959, v, 1e-12)
   118  	require.InEpsilon(t, 7.312190445170959, li.Value(), 1e-12)
   119  	v = li.AddObservation(1.23)
   120  	require.InEpsilon(t, 5.260487047428308, v, 1e-12)
   121  	require.InEpsilon(t, 5.260487047428308, li.Value(), 1e-12)
   122  }
   123  
   124  // Test_AddingRepeatedObservations verifies correct numerics when repeated observations.
   125  // Reference values were generated via python
   126  func Test_LI_AddingRepeatedObservations(t *testing.T) {
   127  	beta := math.Pi / 7.0
   128  	initialValue := 17.0
   129  	li, err := NewLeakyIntegrator(beta, initialValue)
   130  	require.NoError(t, err)
   131  
   132  	v := li.AddRepeatedObservation(6.0, 11)
   133  	require.InEpsilon(t, 13.374196472992809, v, 1e-12)
   134  	require.InEpsilon(t, 13.374196472992809, li.Value(), 1e-12)
   135  	v = li.AddRepeatedObservation(-1.16, 4)
   136  	require.InEpsilon(t, -1.1115419303895382, v, 1e-12)
   137  	require.InEpsilon(t, -1.1115419303895382, li.Value(), 1e-12)
   138  	v = li.AddRepeatedObservation(1.23, 1)
   139  	require.InEpsilon(t, 0.617316921420289, v, 1e-12)
   140  	require.InEpsilon(t, 0.617316921420289, li.Value(), 1e-12)
   141  
   142  }
   143  
   144  // Test_AddingRepeatedObservations_selfConsistency applies a self-consistency check
   145  // for repeated observations.
   146  func Test_LI_AddingRepeatedObservations_selfConsistency(t *testing.T) {
   147  	beta := math.Pi / 7.0
   148  	initialValue := 17.0
   149  	li1, err := NewLeakyIntegrator(beta, initialValue)
   150  	require.NoError(t, err)
   151  	li2, err := NewLeakyIntegrator(beta, initialValue)
   152  	require.NoError(t, err)
   153  
   154  	for i := 7; i > 0; i-- {
   155  		li1.AddObservation(6.0)
   156  	}
   157  	v := li2.AddRepeatedObservation(6.0, 7)
   158  	require.InEpsilon(t, li1.Value(), v, 1e-12)
   159  	require.InEpsilon(t, li1.Value(), li2.Value(), 1e-12)
   160  
   161  	for i := 4; i > 0; i-- {
   162  		li2.AddObservation(6.0)
   163  	}
   164  	v = li1.AddRepeatedObservation(6.0, 4)
   165  	require.InEpsilon(t, li2.Value(), v, 1e-12)
   166  	require.InEpsilon(t, li2.Value(), li1.Value(), 1e-12)
   167  }