github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/aggregator/numerical_test.go (about)

     1  //                           _       _
     2  // __      _____  __ ___   ___  __ _| |_ ___
     3  // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
     4  //  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
     5  //   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
     6  //
     7  //  Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
     8  //
     9  //  CONTACT: hello@weaviate.io
    10  //
    11  
    12  package aggregator
    13  
    14  import (
    15  	"testing"
    16  
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  func TestNumericalAggregator_MedianCalculation(t *testing.T) {
    21  	tests := []struct {
    22  		name           string
    23  		numbers        []float64
    24  		expectedMedian float64
    25  	}{
    26  		{
    27  			name:           "Uneven number of elements",
    28  			numbers:        []float64{1, 2, 3, 4, 5, 6, 7},
    29  			expectedMedian: 4,
    30  		},
    31  		{
    32  			name:           "Uneven number of elements with double elements",
    33  			numbers:        []float64{2, 4, 4, 4, 5, 5, 7},
    34  			expectedMedian: 4,
    35  		},
    36  		{
    37  			name:           "Even number of elements",
    38  			numbers:        []float64{1, 2, 3, 5, 7, 7},
    39  			expectedMedian: 4,
    40  		},
    41  		{
    42  			name:           "Even number of elements with double elements, median is within double entries",
    43  			numbers:        []float64{1, 2, 3, 3, 6, 7},
    44  			expectedMedian: 3,
    45  		},
    46  		{
    47  			name:           "Even number of elements with double elements, median is after double entries",
    48  			numbers:        []float64{3, 3, 3, 5, 5, 7},
    49  			expectedMedian: 4,
    50  		},
    51  		{
    52  			name:           "Single value",
    53  			numbers:        []float64{42},
    54  			expectedMedian: 42,
    55  		},
    56  	}
    57  	for _, tt := range tests {
    58  		for i := 0; i < 2; i++ { // test two ways of adding the value to the aggregator
    59  			t.Run(tt.name, func(t *testing.T) {
    60  				agg := newNumericalAggregator()
    61  				for _, num := range tt.numbers {
    62  					if i == 0 {
    63  						agg.AddFloat64(num)
    64  					} else {
    65  						agg.AddNumberRow(num, 1)
    66  					}
    67  				}
    68  				agg.buildPairsFromCounts() // needed to populate all required info
    69  				assert.Equal(t, tt.expectedMedian, agg.Median())
    70  			})
    71  		}
    72  	}
    73  }
    74  
    75  func TestNumericalAggregator_ModeCalculation(t *testing.T) {
    76  	tests := []struct {
    77  		name         string
    78  		numbers      []float64
    79  		expectedMode float64
    80  	}{
    81  		{
    82  			name:         "Different elements (asc)",
    83  			numbers:      []float64{1, 2, 3, 4, 5, 6, 7},
    84  			expectedMode: 1,
    85  		},
    86  		{
    87  			name:         "Different elements (desc)",
    88  			numbers:      []float64{7, 6, 5, 4, 3, 2, 1},
    89  			expectedMode: 1,
    90  		},
    91  		{
    92  			name:         "Elements with different number of duplicates",
    93  			numbers:      []float64{2, 4, 4, 5, 5, 5, 7},
    94  			expectedMode: 5,
    95  		},
    96  		{
    97  			name:         "Elements with same number of duplicates (asc)",
    98  			numbers:      []float64{1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7},
    99  			expectedMode: 1,
   100  		},
   101  		{
   102  			name:         "Elements with same number of duplicates (desc)",
   103  			numbers:      []float64{7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1},
   104  			expectedMode: 1,
   105  		},
   106  		{
   107  			name:         "Elements with same number of duplicates (mixed oreder)",
   108  			numbers:      []float64{5, 2, 6, 2, 1, 4, 7, 5, 7, 4, 3, 1, 6, 3},
   109  			expectedMode: 1,
   110  		},
   111  		{
   112  			name:         "Single element",
   113  			numbers:      []float64{42},
   114  			expectedMode: 42,
   115  		},
   116  	}
   117  	for _, tt := range tests {
   118  		t.Run(tt.name, func(t *testing.T) {
   119  			agg := newNumericalAggregator()
   120  			for _, num := range tt.numbers {
   121  				agg.AddFloat64(num)
   122  			}
   123  			agg.buildPairsFromCounts() // needed to populate all required info
   124  
   125  			assert.Equal(t, tt.expectedMode, agg.Mode())
   126  		})
   127  
   128  		t.Run(tt.name, func(t *testing.T) {
   129  			agg := newNumericalAggregator()
   130  			for _, num := range tt.numbers {
   131  				agg.AddNumberRow(num, 1)
   132  			}
   133  			agg.buildPairsFromCounts() // needed to populate all required info
   134  
   135  			assert.Equal(t, tt.expectedMode, agg.Mode())
   136  		})
   137  	}
   138  }
   139  
   140  func TestNumericalAggregator_MinMaxCalculation(t *testing.T) {
   141  	tests := []struct {
   142  		name        string
   143  		numbers     []float64
   144  		expectedMin float64
   145  		expectedMax float64
   146  	}{
   147  		{
   148  			name:        "Different positive elements (asc)",
   149  			numbers:     []float64{0, 1, 2, 3, 4, 5, 6, 7},
   150  			expectedMin: 0,
   151  			expectedMax: 7,
   152  		},
   153  		{
   154  			name:        "Different positive elements (desc)",
   155  			numbers:     []float64{7, 6, 5, 4, 3, 2, 1, 0},
   156  			expectedMin: 0,
   157  			expectedMax: 7,
   158  		},
   159  		{
   160  			name:        "Different negative elements (desc)",
   161  			numbers:     []float64{-1, -2, -3, -4, -5, -6, -7},
   162  			expectedMin: -7,
   163  			expectedMax: -1,
   164  		},
   165  		{
   166  			name:        "Different negative elements (asc)",
   167  			numbers:     []float64{-7, -6, -5, -4, -3, -2, -1},
   168  			expectedMin: -7,
   169  			expectedMax: -1,
   170  		},
   171  		{
   172  			name:        "Different elements (mixed order)",
   173  			numbers:     []float64{-7, 6, -5, 4, -3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7},
   174  			expectedMin: -7,
   175  			expectedMax: 7,
   176  		},
   177  		{
   178  			name:        "Single element",
   179  			numbers:     []float64{-42},
   180  			expectedMin: -42,
   181  			expectedMax: -42,
   182  		},
   183  	}
   184  
   185  	for _, tt := range tests {
   186  		t.Run(tt.name, func(t *testing.T) {
   187  			agg := newNumericalAggregator()
   188  			for _, num := range tt.numbers {
   189  				agg.AddFloat64(num)
   190  			}
   191  			assert.Equal(t, tt.expectedMin, agg.Min())
   192  			assert.Equal(t, tt.expectedMax, agg.Max())
   193  		})
   194  
   195  		t.Run(tt.name, func(t *testing.T) {
   196  			agg := newNumericalAggregator()
   197  			for _, num := range tt.numbers {
   198  				agg.AddNumberRow(num, 1)
   199  			}
   200  			assert.Equal(t, tt.expectedMin, agg.Min())
   201  			assert.Equal(t, tt.expectedMax, agg.Max())
   202  		})
   203  	}
   204  }