github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/ingester/mapper_test.go (about)

     1  package ingester
     2  
     3  import (
     4  	"sort"
     5  	"testing"
     6  
     7  	"github.com/prometheus/common/model"
     8  	"github.com/prometheus/prometheus/model/labels"
     9  )
    10  
    11  var (
    12  	// cm11, cm12, cm13 are colliding with fp1.
    13  	// cm21, cm22 are colliding with fp2.
    14  	// cm31, cm32 are colliding with fp3, which is below maxMappedFP.
    15  	// Note that fingerprints are set and not actually calculated.
    16  	// The collision detection is independent from the actually used
    17  	// fingerprinting algorithm.
    18  	fp1  = model.Fingerprint(maxMappedFP + 1)
    19  	fp2  = model.Fingerprint(maxMappedFP + 2)
    20  	fp3  = model.Fingerprint(1)
    21  	cm11 = []labels.Label{
    22  		{Name: "dings", Value: "bumms"},
    23  		{Name: "foo", Value: "bar"},
    24  	}
    25  	cm12 = []labels.Label{
    26  		{Name: "bar", Value: "foo"},
    27  	}
    28  	cm13 = []labels.Label{
    29  		{Name: "foo", Value: "bar"},
    30  	}
    31  	cm21 = []labels.Label{
    32  		{Name: "dings", Value: "bar"},
    33  		{Name: "foo", Value: "bumms"},
    34  	}
    35  	cm22 = []labels.Label{
    36  		{Name: "bar", Value: "bumms"},
    37  		{Name: "dings", Value: "foo"},
    38  	}
    39  	cm31 = []labels.Label{
    40  		{Name: "bumms", Value: "dings"},
    41  	}
    42  	cm32 = []labels.Label{
    43  		{Name: "bar", Value: "foo"},
    44  		{Name: "bumms", Value: "dings"},
    45  	}
    46  )
    47  
    48  func copyValuesAndSort(a []labels.Label) labels.Labels {
    49  	c := make(labels.Labels, len(a))
    50  	for i, pair := range a {
    51  		c[i].Name = pair.Name
    52  		c[i].Value = pair.Value
    53  	}
    54  	sort.Sort(c)
    55  	return c
    56  }
    57  
    58  func TestFPMapper(t *testing.T) {
    59  	sm := map[model.Fingerprint]labels.Labels{}
    60  
    61  	mapper := newFPMapper(func(fp model.Fingerprint) labels.Labels {
    62  		return sm[fp]
    63  	})
    64  
    65  	// Everything is empty, resolving a FP should do nothing.
    66  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm11), fp1)
    67  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm12), fp1)
    68  
    69  	// cm11 is in sm. Adding cm11 should do nothing. Mapping cm12 should resolve
    70  	// the collision.
    71  	sm[fp1] = copyValuesAndSort(cm11)
    72  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm11), fp1)
    73  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm12), model.Fingerprint(1))
    74  
    75  	// The mapped cm12 is added to sm, too. That should not change the outcome.
    76  	sm[model.Fingerprint(1)] = copyValuesAndSort(cm12)
    77  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm11), fp1)
    78  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm12), model.Fingerprint(1))
    79  
    80  	// Now map cm13, should reproducibly result in the next mapped FP.
    81  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm13), model.Fingerprint(2))
    82  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm13), model.Fingerprint(2))
    83  
    84  	// Add cm13 to sm. Should not change anything.
    85  	sm[model.Fingerprint(2)] = copyValuesAndSort(cm13)
    86  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm11), fp1)
    87  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm12), model.Fingerprint(1))
    88  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm13), model.Fingerprint(2))
    89  
    90  	// Now add cm21 and cm22 in the same way, checking the mapped FPs.
    91  	assertFingerprintEqual(t, mapper.mapFP(fp2, cm21), fp2)
    92  	sm[fp2] = copyValuesAndSort(cm21)
    93  	assertFingerprintEqual(t, mapper.mapFP(fp2, cm21), fp2)
    94  	assertFingerprintEqual(t, mapper.mapFP(fp2, cm22), model.Fingerprint(3))
    95  	sm[model.Fingerprint(3)] = copyValuesAndSort(cm22)
    96  	assertFingerprintEqual(t, mapper.mapFP(fp2, cm21), fp2)
    97  	assertFingerprintEqual(t, mapper.mapFP(fp2, cm22), model.Fingerprint(3))
    98  
    99  	// Map cm31, resulting in a mapping straight away.
   100  	assertFingerprintEqual(t, mapper.mapFP(fp3, cm31), model.Fingerprint(4))
   101  	sm[model.Fingerprint(4)] = copyValuesAndSort(cm31)
   102  
   103  	// Map cm32, which is now mapped for two reasons...
   104  	assertFingerprintEqual(t, mapper.mapFP(fp3, cm32), model.Fingerprint(5))
   105  	sm[model.Fingerprint(5)] = copyValuesAndSort(cm32)
   106  
   107  	// Now check ALL the mappings, just to be sure.
   108  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm11), fp1)
   109  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm12), model.Fingerprint(1))
   110  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm13), model.Fingerprint(2))
   111  	assertFingerprintEqual(t, mapper.mapFP(fp2, cm21), fp2)
   112  	assertFingerprintEqual(t, mapper.mapFP(fp2, cm22), model.Fingerprint(3))
   113  	assertFingerprintEqual(t, mapper.mapFP(fp3, cm31), model.Fingerprint(4))
   114  	assertFingerprintEqual(t, mapper.mapFP(fp3, cm32), model.Fingerprint(5))
   115  
   116  	// Remove all the fingerprints from sm, which should change nothing, as
   117  	// the existing mappings stay and should be detected.
   118  	delete(sm, fp1)
   119  	delete(sm, fp2)
   120  	delete(sm, fp3)
   121  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm11), fp1)
   122  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm12), model.Fingerprint(1))
   123  	assertFingerprintEqual(t, mapper.mapFP(fp1, cm13), model.Fingerprint(2))
   124  	assertFingerprintEqual(t, mapper.mapFP(fp2, cm21), fp2)
   125  	assertFingerprintEqual(t, mapper.mapFP(fp2, cm22), model.Fingerprint(3))
   126  	assertFingerprintEqual(t, mapper.mapFP(fp3, cm31), model.Fingerprint(4))
   127  	assertFingerprintEqual(t, mapper.mapFP(fp3, cm32), model.Fingerprint(5))
   128  }
   129  
   130  // assertFingerprintEqual asserts that two fingerprints are equal.
   131  func assertFingerprintEqual(t *testing.T, gotFP, wantFP model.Fingerprint) {
   132  	t.Helper()
   133  	if gotFP != wantFP {
   134  		t.Errorf("got fingerprint %v, want fingerprint %v", gotFP, wantFP)
   135  	}
   136  }