github.com/m3db/m3@v1.5.0/src/dbnode/storage/series_resolver_test.go (about)

     1  // Copyright (c) 2021 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 storage
    22  
    23  import (
    24  	"fmt"
    25  	"sync"
    26  	"testing"
    27  
    28  	"github.com/stretchr/testify/require"
    29  
    30  	"github.com/m3db/m3/src/x/ident"
    31  	xtest "github.com/m3db/m3/src/x/test"
    32  )
    33  
    34  func TestResolveError(t *testing.T) {
    35  	wg := sync.WaitGroup{}
    36  	id := ident.StringID("foo")
    37  	sut := NewSeriesResolver(&wg, &Entry{ID: id}, func(id ident.ID) (*Entry, error) {
    38  		return nil, fmt.Errorf("unable to resolve series")
    39  	})
    40  	_, err := sut.SeriesRef()
    41  	require.Error(t, err)
    42  }
    43  
    44  func TestResolveNilEntry(t *testing.T) {
    45  	wg := sync.WaitGroup{}
    46  	id := ident.StringID("foo")
    47  	sut := NewSeriesResolver(&wg, &Entry{ID: id}, func(id ident.ID) (*Entry, error) {
    48  		return nil, nil
    49  	})
    50  	_, err := sut.SeriesRef()
    51  	require.Error(t, err)
    52  }
    53  
    54  func TestResolve(t *testing.T) {
    55  	ctrl := xtest.NewController(t)
    56  	defer ctrl.Finish()
    57  
    58  	wg := sync.WaitGroup{}
    59  	id := ident.StringID("foo")
    60  	sut := NewSeriesResolver(&wg, &Entry{ID: id}, func(id ident.ID) (*Entry, error) {
    61  		return NewEntry(NewEntryOptions{
    62  			Series: newMockSeries(ctrl),
    63  			Index:  11,
    64  		}), nil
    65  	})
    66  	seriesRef, err := sut.SeriesRef()
    67  	require.NoError(t, err)
    68  	require.IsType(t, &Entry{}, seriesRef)
    69  	entry := seriesRef.(*Entry)
    70  	require.Equal(t, uint64(11), entry.Index)
    71  }
    72  
    73  func TestSecondResolveWontWait(t *testing.T) {
    74  	ctrl := xtest.NewController(t)
    75  	defer ctrl.Finish()
    76  
    77  	wg := sync.WaitGroup{}
    78  	id := ident.StringID("foo")
    79  	sut := NewSeriesResolver(&wg, &Entry{ID: id}, func(id ident.ID) (*Entry, error) {
    80  		return NewEntry(NewEntryOptions{
    81  			Series: newMockSeries(ctrl),
    82  			Index:  11,
    83  		}), nil
    84  	})
    85  	seriesRef, err := sut.SeriesRef()
    86  	require.NoError(t, err)
    87  	require.IsType(t, &Entry{}, seriesRef)
    88  	entry := seriesRef.(*Entry)
    89  	require.Equal(t, uint64(11), entry.Index)
    90  
    91  	wg.Add(1)
    92  	seriesRef2, err := sut.SeriesRef()
    93  	require.NoError(t, err)
    94  	require.IsType(t, &Entry{}, seriesRef2)
    95  	entry2 := seriesRef2.(*Entry)
    96  	require.Equal(t, entry, entry2)
    97  }
    98  
    99  func TestReleaseRef(t *testing.T) {
   100  	ctrl := xtest.NewController(t)
   101  	defer ctrl.Finish()
   102  
   103  	wg := sync.WaitGroup{}
   104  	entry := NewEntry(NewEntryOptions{Series: newMockSeries(ctrl)})
   105  	entry.IncrementReaderWriterCount()
   106  	sut := NewSeriesResolver(&wg, entry, func(id ident.ID) (*Entry, error) {
   107  		entry.IncrementReaderWriterCount()
   108  		return entry, nil
   109  	})
   110  
   111  	// Initial creation increments the entry.
   112  	require.Equal(t, int32(1), entry.ReaderWriterCount())
   113  
   114  	seriesRef, err := sut.SeriesRef()
   115  	require.NoError(t, err)
   116  	require.IsType(t, &Entry{}, seriesRef)
   117  
   118  	// Subsequent reference increments the entry (this is to be defensive around
   119  	// ref counting based on the one that happened to be created vs one persisted in the shard).
   120  	require.Equal(t, int32(2), entry.ReaderWriterCount())
   121  
   122  	sut.ReleaseRef()
   123  
   124  	// All references released.
   125  	require.Zero(t, entry.ReaderWriterCount())
   126  }
   127  
   128  func TestReleaseRefWithoutSeriesRef(t *testing.T) {
   129  	ctrl := xtest.NewController(t)
   130  	defer ctrl.Finish()
   131  
   132  	wg := sync.WaitGroup{}
   133  	id := ident.StringID("foo")
   134  	sut := NewSeriesResolver(&wg, &Entry{ID: id}, func(id ident.ID) (*Entry, error) {
   135  		entry := NewEntry(NewEntryOptions{Series: newMockSeries(ctrl)})
   136  		entry.IncrementReaderWriterCount()
   137  		return entry, nil
   138  	})
   139  	sut.ReleaseRef()
   140  }