github.com/m3db/m3@v1.5.0/src/metrics/aggregation/type_test.go (about)

     1  // Copyright (c) 2017 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package aggregation
    22  
    23  import (
    24  	"encoding/json"
    25  	"fmt"
    26  	"testing"
    27  
    28  	"github.com/m3db/m3/src/x/pool"
    29  	"github.com/m3db/m3/src/x/test/testmarshal"
    30  
    31  	"github.com/stretchr/testify/require"
    32  	yaml "gopkg.in/yaml.v2"
    33  )
    34  
    35  func TestTypeIsValid(t *testing.T) {
    36  	require.True(t, P75.IsValid())
    37  	require.False(t, Type(int(P75)+1).IsValid())
    38  }
    39  
    40  func TestTypeMaxID(t *testing.T) {
    41  	require.Equal(t, maxTypeID, P75.ID())
    42  	require.Equal(t, P75, Type(maxTypeID))
    43  	require.Equal(t, maxTypeID, len(ValidTypes))
    44  }
    45  
    46  func TestTypeUnmarshalYAML(t *testing.T) {
    47  	inputs := []struct {
    48  		str         string
    49  		expected    Type
    50  		expectedErr bool
    51  	}{
    52  		{
    53  			str:      "Min",
    54  			expected: Min,
    55  		},
    56  		{
    57  			str:         "Mean,",
    58  			expectedErr: true,
    59  		},
    60  		{
    61  			str:         "asd",
    62  			expectedErr: true,
    63  		},
    64  	}
    65  	for _, input := range inputs {
    66  		var aggtype Type
    67  		err := yaml.Unmarshal([]byte(input.str), &aggtype)
    68  
    69  		if input.expectedErr {
    70  			require.Error(t, err)
    71  			continue
    72  		}
    73  
    74  		require.NoError(t, err)
    75  		require.Equal(t, input.expected, aggtype)
    76  	}
    77  }
    78  
    79  func TestTypesIsDefault(t *testing.T) {
    80  	require.True(t, DefaultTypes.IsDefault())
    81  
    82  	require.False(t, Types{Max}.IsDefault())
    83  }
    84  
    85  func TestTypesMarshalJSON(t *testing.T) {
    86  	inputs := []struct {
    87  		types       Types
    88  		expected    string
    89  		expectedErr bool
    90  	}{
    91  		{
    92  			types:    Types{},
    93  			expected: `[]`,
    94  		},
    95  		{
    96  			types:    Types{Min},
    97  			expected: `["Min"]`,
    98  		},
    99  		{
   100  			types:    Types{Mean, Max, P99, P9999},
   101  			expected: `["Mean","Max","P99","P9999"]`,
   102  		},
   103  		{
   104  			types:       Types{Type(1000)},
   105  			expectedErr: true,
   106  		},
   107  	}
   108  	for _, input := range inputs {
   109  		b, err := json.Marshal(input.types)
   110  		if input.expectedErr {
   111  			require.Error(t, err)
   112  			continue
   113  		}
   114  		require.NoError(t, err)
   115  		require.Equal(t, input.expected, string(b))
   116  	}
   117  }
   118  
   119  func TestTypesUnMarshalJSON(t *testing.T) {
   120  	inputs := []struct {
   121  		str         string
   122  		expected    Types
   123  		expectedErr bool
   124  	}{
   125  		{
   126  			str:      `[]`,
   127  			expected: Types{},
   128  		},
   129  		{
   130  			str:      `["Min"]`,
   131  			expected: Types{Min},
   132  		},
   133  		{
   134  			str:      `["Mean","Max","P99","P9999"]`,
   135  			expected: Types{Mean, Max, P99, P9999},
   136  		},
   137  		{
   138  			str:         `[P100]`,
   139  			expectedErr: true,
   140  		},
   141  	}
   142  	for _, input := range inputs {
   143  		var aggTypes Types
   144  		err := json.Unmarshal([]byte(input.str), &aggTypes)
   145  		if input.expectedErr {
   146  			require.Error(t, err)
   147  			continue
   148  		}
   149  		require.NoError(t, err)
   150  		require.Equal(t, input.expected, aggTypes)
   151  	}
   152  }
   153  
   154  func TestTypesMarshalRoundTrip(t *testing.T) {
   155  	inputs := []Types{
   156  		{},
   157  		{Min},
   158  		{Mean, Max, P99, P9999},
   159  	}
   160  
   161  	testmarshal.TestMarshalersRoundtrip(t, inputs, []testmarshal.Marshaler{
   162  		testmarshal.JSONMarshaler,
   163  		testmarshal.YAMLMarshaler,
   164  	})
   165  }
   166  
   167  func TestTypesMarshalText(t *testing.T) {
   168  	cases := []struct {
   169  		In       Type
   170  		Expected string
   171  	}{{
   172  		In:       Mean,
   173  		Expected: "Mean",
   174  	}, {
   175  		In:       Last,
   176  		Expected: "Last",
   177  	}}
   178  
   179  	for _, tc := range cases {
   180  		t.Run(tc.Expected, func(t *testing.T) {
   181  			testmarshal.AssertMarshals(t, testmarshal.TextMarshaler, tc.In, []byte(tc.Expected))
   182  		})
   183  	}
   184  }
   185  
   186  func TestTypesUnmarshalTextError(t *testing.T) {
   187  	cases := []string{
   188  		"unknown_at",
   189  		`"Mean"`, // double JSON encoded
   190  	}
   191  
   192  	for _, tc := range cases {
   193  		t.Run(tc, func(t *testing.T) {
   194  			var target Type
   195  			require.EqualError(t, target.UnmarshalText([]byte(tc)), fmt.Sprintf("invalid aggregation type: %s", tc))
   196  		})
   197  	}
   198  }
   199  
   200  func TestTypesUnmarshalYAML(t *testing.T) {
   201  	inputs := []struct {
   202  		str         string
   203  		expected    Types
   204  		expectedErr bool
   205  	}{
   206  		{
   207  			str:      "",
   208  			expected: Types(nil),
   209  		},
   210  		{
   211  			str:      "[Min]",
   212  			expected: Types{Min},
   213  		},
   214  		{
   215  			str:      "[Mean,Max,P99,P9999]",
   216  			expected: Types{Mean, Max, P99, P9999},
   217  		},
   218  		{
   219  			str:         "[Min,Max,P99,P9999,P100]",
   220  			expectedErr: true,
   221  		},
   222  		{
   223  			str:         "[Min,Max,P99,P9999,P100]",
   224  			expectedErr: true,
   225  		},
   226  		{
   227  			str:         ",Mean",
   228  			expectedErr: true,
   229  		},
   230  		{
   231  			str:         "Mean,",
   232  			expectedErr: true,
   233  		},
   234  		{
   235  			str:         ",Mean,",
   236  			expectedErr: true,
   237  		},
   238  	}
   239  	for _, input := range inputs {
   240  		var aggtypes Types
   241  		err := yaml.Unmarshal([]byte(input.str), &aggtypes)
   242  
   243  		if input.expectedErr {
   244  			require.Error(t, err)
   245  			continue
   246  		}
   247  
   248  		require.NoError(t, err)
   249  		require.Equal(t, input.expected, aggtypes)
   250  	}
   251  }
   252  
   253  func TestParseTypes(t *testing.T) {
   254  	inputs := []struct {
   255  		str      string
   256  		expected Types
   257  	}{
   258  		{
   259  			str:      "Min",
   260  			expected: Types{Min},
   261  		},
   262  		{
   263  			str:      "Min,Max",
   264  			expected: Types{Min, Max},
   265  		},
   266  		{
   267  			str:      "min,max",
   268  			expected: Types{Min, Max},
   269  		},
   270  	}
   271  	for _, input := range inputs {
   272  		res, err := ParseTypes(input.str)
   273  		require.NoError(t, err)
   274  		require.Equal(t, input.expected, res)
   275  	}
   276  }
   277  
   278  func TestQuantiles(t *testing.T) {
   279  	res, ok := Types{Median, P95, P99}.PooledQuantiles(nil)
   280  	require.Equal(t, []float64{0.5, 0.95, 0.99}, res)
   281  	require.False(t, ok)
   282  
   283  	p := pool.NewFloatsPool(
   284  		[]pool.Bucket{
   285  			pool.Bucket{Capacity: 10, Count: 1},
   286  		},
   287  		nil,
   288  	)
   289  	p.Init()
   290  	res, ok = Types{Median, P95, P99}.PooledQuantiles(p)
   291  	require.Equal(t, []float64{0.5, 0.95, 0.99}, res)
   292  	require.True(t, ok)
   293  
   294  	p.Put(res)
   295  
   296  	res2, ok := Types{P90, P95, P99}.PooledQuantiles(p)
   297  	require.Equal(t, []float64{0.9, 0.95, 0.99}, res2)
   298  	require.Equal(t, res, res2)
   299  	require.True(t, ok)
   300  	p.Put(res2)
   301  
   302  	res3, ok := Types{Count}.PooledQuantiles(p)
   303  	require.Nil(t, res3)
   304  	require.False(t, ok)
   305  
   306  	res4, ok := Types{P10, P20, P25, P30, P40, P50, Median, P60, P70, P75, P80, P90, P95, P99, P999, P9999}.
   307  		PooledQuantiles(p)
   308  	require.Equal(
   309  		t,
   310  		[]float64{0.1, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.75, 0.8, 0.9, 0.95, 0.99, 0.999, 0.9999},
   311  		res4)
   312  	require.True(t, ok)
   313  }
   314  
   315  func TestIDContains(t *testing.T) {
   316  	require.True(t, MustCompressTypes(P99).Contains(P99))
   317  	require.True(t, MustCompressTypes(P99, P95).Contains(P99))
   318  	require.True(t, MustCompressTypes(P99, P95).Contains(P95))
   319  	require.True(t, MustCompressTypes(Sum, Last, P999).Contains(Sum))
   320  	require.True(t, MustCompressTypes(Sum, Last, P999).Contains(Last))
   321  	require.True(t, MustCompressTypes(Sum, Last, P999).Contains(P999))
   322  	require.False(t, MustCompressTypes(Sum, Last, P999).Contains(P9999))
   323  	require.False(t, MustCompressTypes().Contains(P99))
   324  	require.False(t, MustCompressTypes(P99, P95).Contains(P9999))
   325  }
   326  
   327  func TestCompressedTypesIsDefault(t *testing.T) {
   328  	var id ID
   329  	require.True(t, id.IsDefault())
   330  
   331  	id[0] = 8
   332  	require.False(t, id.IsDefault())
   333  
   334  	id[0] = 0
   335  	require.True(t, id.IsDefault())
   336  }