github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/metrics/rules/validator/namespace/kv/validator_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 kv
    22  
    23  import (
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/m3db/m3/src/cluster/generated/proto/commonpb"
    28  	"github.com/m3db/m3/src/cluster/kv"
    29  	"github.com/m3db/m3/src/cluster/kv/mem"
    30  
    31  	"github.com/fortytw2/leaktest"
    32  	"github.com/stretchr/testify/require"
    33  )
    34  
    35  const (
    36  	testValidNamespacesKey = "validNamespaces"
    37  )
    38  
    39  var (
    40  	testNamespaces1 = []string{"foo", "bar", "baz"}
    41  	testNamespaces2 = []string{"blah", "invalid"}
    42  )
    43  
    44  func TestValidatorInitTimeoutWithUpdate(t *testing.T) {
    45  	defer leaktest.Check(t)()
    46  
    47  	store := mem.NewStore()
    48  	v := testValidator(t, store)
    49  
    50  	// Timed out getting initial value and by default
    51  	// no namespace is valid.
    52  	for _, ns := range testNamespaces1 {
    53  		require.Error(t, v.Validate(ns))
    54  	}
    55  	for _, ns := range testNamespaces2 {
    56  		require.Error(t, v.Validate(ns))
    57  	}
    58  
    59  	// Set valid namespaces in KV and wait for changes to be processed.
    60  	nss := &commonpb.StringArrayProto{Values: testNamespaces1}
    61  	_, err := store.Set(testValidNamespacesKey, nss)
    62  	require.NoError(t, err)
    63  	for {
    64  		v.RLock()
    65  		currValidNamespaces := v.validNamespaces
    66  		v.RUnlock()
    67  		if len(currValidNamespaces) == len(testNamespaces1) {
    68  			break
    69  		}
    70  		time.Sleep(50 * time.Millisecond)
    71  	}
    72  
    73  	// Now validating the valid namespaces should be ok and validating
    74  	// invalid namespaces should return an error.
    75  	for _, ns := range testNamespaces1 {
    76  		require.NoError(t, v.Validate(ns))
    77  	}
    78  	for _, ns := range testNamespaces2 {
    79  		require.Error(t, v.Validate(ns))
    80  	}
    81  
    82  	// Close the validator.
    83  	require.False(t, v.closed)
    84  	v.Close()
    85  	require.True(t, v.closed)
    86  
    87  	// Validating after the validator is closed results in an error.
    88  	for _, ns := range testNamespaces1 {
    89  		require.Equal(t, errValidatorClosed, v.Validate(ns))
    90  	}
    91  	for _, ns := range testNamespaces2 {
    92  		require.Equal(t, errValidatorClosed, v.Validate(ns))
    93  	}
    94  }
    95  
    96  func TestValidatorWithUpdateAndDeletion(t *testing.T) {
    97  	defer leaktest.Check(t)()
    98  
    99  	// Set valid namespaces in KV and wait for changes to be processed.
   100  	store := mem.NewStore()
   101  	nss := &commonpb.StringArrayProto{Values: testNamespaces1}
   102  	_, err := store.Set(testValidNamespacesKey, nss)
   103  	require.NoError(t, err)
   104  
   105  	// Assert that the validator has successfully received the list
   106  	// of valid namespaces from KV.
   107  	v := testValidator(t, store)
   108  	for _, ns := range testNamespaces1 {
   109  		require.NoError(t, v.Validate(ns))
   110  	}
   111  	for _, ns := range testNamespaces2 {
   112  		require.Error(t, v.Validate(ns))
   113  	}
   114  
   115  	// Change valid namespaces in KV and wait for changes to be processed.
   116  	nss = &commonpb.StringArrayProto{Values: testNamespaces2}
   117  	_, err = store.Set(testValidNamespacesKey, nss)
   118  	require.NoError(t, err)
   119  	for {
   120  		v.RLock()
   121  		currValidNamespaces := v.validNamespaces
   122  		v.RUnlock()
   123  		if len(currValidNamespaces) == len(testNamespaces2) {
   124  			break
   125  		}
   126  		time.Sleep(50 * time.Millisecond)
   127  	}
   128  
   129  	// Now validating the valid namespaces should be ok and validating
   130  	// invalid namespaces should return an error.
   131  	for _, ns := range testNamespaces1 {
   132  		require.Error(t, v.Validate(ns))
   133  	}
   134  	for _, ns := range testNamespaces2 {
   135  		require.NoError(t, v.Validate(ns))
   136  	}
   137  
   138  	// Delete the valid namespaces key.
   139  	_, err = store.Delete(testValidNamespacesKey)
   140  	require.NoError(t, err)
   141  	for {
   142  		v.RLock()
   143  		currValidNamespaces := v.validNamespaces
   144  		v.RUnlock()
   145  		if len(currValidNamespaces) == 0 {
   146  			break
   147  		}
   148  		time.Sleep(50 * time.Millisecond)
   149  	}
   150  
   151  	// No namespaces are valid by default after the key is deleted.
   152  	for _, ns := range testNamespaces1 {
   153  		require.Error(t, v.Validate(ns))
   154  	}
   155  	for _, ns := range testNamespaces2 {
   156  		require.Error(t, v.Validate(ns))
   157  	}
   158  
   159  	// Close the validator.
   160  	require.False(t, v.closed)
   161  	v.Close()
   162  	require.True(t, v.closed)
   163  
   164  	// Validating after the validator is closed results in an error.
   165  	for _, ns := range testNamespaces1 {
   166  		require.Equal(t, errValidatorClosed, v.Validate(ns))
   167  	}
   168  	for _, ns := range testNamespaces2 {
   169  		require.Equal(t, errValidatorClosed, v.Validate(ns))
   170  	}
   171  }
   172  
   173  func testValidatorOptions(store kv.Store) NamespaceValidatorOptions {
   174  	return NewNamespaceValidatorOptions().
   175  		SetInitWatchTimeout(100 * time.Millisecond).
   176  		SetKVStore(store).
   177  		SetValidNamespacesKey(testValidNamespacesKey)
   178  }
   179  
   180  func testValidator(t *testing.T, store kv.Store) *validator {
   181  	v, err := NewNamespaceValidator(testValidatorOptions(store))
   182  	require.NoError(t, err)
   183  	return v.(*validator)
   184  }