From 5633ec35dff19774699080b8afe8befff2c74186 Mon Sep 17 00:00:00 2001 From: Xi Chen Date: Wed, 3 May 2017 09:09:09 -0400 Subject: [PATCH] Better test coverage --- policy/policy_test.go | 133 +++++++++ protocol/msgpack/unaggregated_encoder_test.go | 51 ++-- .../msgpack/unaggregated_iterator_test.go | 74 +++-- .../msgpack/unaggregated_roundtrip_test.go | 159 +++++++++-- rules/result_test.go | 112 ++++++-- rules/ruleset.go | 48 +++- rules/ruleset_test.go | 256 +++++++++++++++--- 7 files changed, 691 insertions(+), 142 deletions(-) diff --git a/policy/policy_test.go b/policy/policy_test.go index 17c73fa..750c8ac 100644 --- a/policy/policy_test.go +++ b/policy/policy_test.go @@ -62,3 +62,136 @@ func TestStagedPoliciesHasCustomPolicies(t *testing.T) { require.False(t, sp.hasDefaultPolicies()) require.Equal(t, policies, sp.Policies()) } + +func TestStagedPoliciesSamePoliciesDefaultPolicies(t *testing.T) { + inputs := []struct { + sp [2]StagedPolicies + expected bool + }{ + { + sp: [2]StagedPolicies{ + NewStagedPolicies(0, false, nil), + NewStagedPolicies(0, true, []Policy{}), + }, + expected: true, + }, + { + sp: [2]StagedPolicies{ + NewStagedPolicies(0, false, nil), + NewStagedPolicies(0, true, []Policy{ + NewPolicy(10*time.Second, xtime.Second, 6*time.Hour), + NewPolicy(time.Minute, xtime.Minute, 12*time.Hour), + }), + }, + expected: false, + }, + { + sp: [2]StagedPolicies{ + NewStagedPolicies(1000, false, []Policy{ + NewPolicy(10*time.Second, xtime.Second, 6*time.Hour), + NewPolicy(time.Minute, xtime.Minute, 12*time.Hour), + }), + NewStagedPolicies(0, true, []Policy{ + NewPolicy(10*time.Second, xtime.Second, 6*time.Hour), + NewPolicy(time.Minute, xtime.Minute, 12*time.Hour), + }), + }, + expected: true, + }, + { + sp: [2]StagedPolicies{ + NewStagedPolicies(1000, false, []Policy{ + NewPolicy(10*time.Second, xtime.Second, 6*time.Hour), + NewPolicy(time.Minute, xtime.Minute, 12*time.Hour), + }), + NewStagedPolicies(0, true, []Policy{ + NewPolicy(10*time.Second, xtime.Second, 6*time.Hour), + NewPolicy(time.Minute, xtime.Minute, 12*time.Hour), + NewPolicy(10*time.Minute, xtime.Minute, 24*time.Hour), + }), + }, + expected: false, + }, + { + sp: [2]StagedPolicies{ + NewStagedPolicies(0, true, []Policy{ + NewPolicy(10*time.Second, xtime.Second, 6*time.Hour), + NewPolicy(time.Minute, xtime.Minute, 12*time.Hour), + NewPolicy(10*time.Minute, xtime.Minute, 24*time.Hour), + }), + NewStagedPolicies(1000, false, []Policy{ + NewPolicy(10*time.Second, xtime.Second, 6*time.Hour), + NewPolicy(time.Minute, xtime.Minute, 12*time.Hour), + }), + }, + expected: false, + }, + } + for _, input := range inputs { + require.Equal(t, input.expected, input.sp[0].SamePolicies(input.sp[1])) + } +} + +func TestStagedPoliciesIsEmpty(t *testing.T) { + inputs := []struct { + sp StagedPolicies + expected bool + }{ + { + sp: NewStagedPolicies(0, false, nil), + expected: true, + }, + { + sp: NewStagedPolicies(0, false, []Policy{}), + expected: true, + }, + { + sp: NewStagedPolicies(100, false, nil), + expected: false, + }, + { + sp: NewStagedPolicies(0, true, nil), + expected: false, + }, + { + sp: NewStagedPolicies(0, true, []Policy{ + NewPolicy(10*time.Second, xtime.Second, 6*time.Hour), + NewPolicy(time.Minute, xtime.Minute, 12*time.Hour), + }), + expected: false, + }, + } + for _, input := range inputs { + require.Equal(t, input.expected, input.sp.isEmpty()) + } +} + +func TestPoliciesListIsDefault(t *testing.T) { + inputs := []struct { + pl PoliciesList + expected bool + }{ + { + pl: DefaultPoliciesList, + expected: true, + }, + { + pl: []StagedPolicies{}, + expected: false, + }, + { + pl: []StagedPolicies{NewStagedPolicies(0, true, []Policy{ + NewPolicy(10*time.Second, xtime.Second, 6*time.Hour), + NewPolicy(time.Minute, xtime.Minute, 12*time.Hour), + })}, + expected: false, + }, + { + pl: []StagedPolicies{EmptyStagedPolicies, EmptyStagedPolicies}, + expected: false, + }, + } + for _, input := range inputs { + require.Equal(t, input.expected, input.pl.IsDefault()) + } +} diff --git a/protocol/msgpack/unaggregated_encoder_test.go b/protocol/msgpack/unaggregated_encoder_test.go index d4b4904..d19306f 100644 --- a/protocol/msgpack/unaggregated_encoder_test.go +++ b/protocol/msgpack/unaggregated_encoder_test.go @@ -40,47 +40,58 @@ var ( errTestArrayLen = errors.New("test array len error") ) -func TestUnaggregatedEncodeCounterWithDefaultPolicies(t *testing.T) { - policies := testDefaultStagedPolicies +func TestUnaggregatedEncodeCounterWithDefaultPoliciesList(t *testing.T) { + policies := testDefaultStagedPoliciesList encoder, results := testCapturingUnaggregatedEncoder(t) require.NoError(t, testUnaggregatedEncode(t, encoder, testCounter, policies)) - expected := expectedResultsForUnaggregatedMetricWithPolicies(t, testCounter, policies) + expected := expectedResultsForUnaggregatedMetricWithPoliciesList(t, testCounter, policies) require.Equal(t, expected, *results) } -func TestUnaggregatedEncodeBatchTimerWithDefaultPolicies(t *testing.T) { - policies := testDefaultStagedPolicies +func TestUnaggregatedEncodeBatchTimerWithDefaultPoliciesList(t *testing.T) { + policies := testDefaultStagedPoliciesList encoder, results := testCapturingUnaggregatedEncoder(t) require.NoError(t, testUnaggregatedEncode(t, encoder, testBatchTimer, policies)) - expected := expectedResultsForUnaggregatedMetricWithPolicies(t, testBatchTimer, policies) + expected := expectedResultsForUnaggregatedMetricWithPoliciesList(t, testBatchTimer, policies) require.Equal(t, expected, *results) } -func TestUnaggregatedEncodeGaugeWithDefaultPolicies(t *testing.T) { - policies := testDefaultStagedPolicies +func TestUnaggregatedEncodeGaugeWithDefaultPoliciesList(t *testing.T) { + policies := testDefaultStagedPoliciesList encoder, results := testCapturingUnaggregatedEncoder(t) require.NoError(t, testUnaggregatedEncode(t, encoder, testGauge, policies)) - expected := expectedResultsForUnaggregatedMetricWithPolicies(t, testGauge, policies) + expected := expectedResultsForUnaggregatedMetricWithPoliciesList(t, testGauge, policies) require.Equal(t, expected, *results) } -func TestUnaggregatedEncodeAllTypesWithDefaultPolicies(t *testing.T) { +func TestUnaggregatedEncodeAllTypesWithDefaultPoliciesList(t *testing.T) { var expected []interface{} encoder, results := testCapturingUnaggregatedEncoder(t) - for _, input := range testInputWithAllTypesAndDefaultPolicies { + for _, input := range testInputWithAllTypesAndDefaultPoliciesList { require.NoError(t, testUnaggregatedEncode(t, encoder, input.metric, input.policiesList)) - expected = append(expected, expectedResultsForUnaggregatedMetricWithPolicies(t, input.metric, input.policiesList)...) + expected = append(expected, expectedResultsForUnaggregatedMetricWithPoliciesList(t, input.metric, input.policiesList)...) } require.Equal(t, expected, *results) } -func TestUnaggregatedEncodeAllTypesWithSingleCustomPolicies(t *testing.T) { +func TestUnaggregatedEncodeAllTypesWithSingleCustomPoliciesList(t *testing.T) { var expected []interface{} encoder, results := testCapturingUnaggregatedEncoder(t) - for _, input := range testInputWithAllTypesAndSingleCustomPolicies { + for _, input := range testInputWithAllTypesAndSingleCustomPoliciesList { require.NoError(t, testUnaggregatedEncode(t, encoder, input.metric, input.policiesList)) - expected = append(expected, expectedResultsForUnaggregatedMetricWithPolicies(t, input.metric, input.policiesList)...) + expected = append(expected, expectedResultsForUnaggregatedMetricWithPoliciesList(t, input.metric, input.policiesList)...) + } + + require.Equal(t, expected, *results) +} + +func TestUnaggregatedEncodeAllTypesWithMultiCustomPolicies(t *testing.T) { + var expected []interface{} + encoder, results := testCapturingUnaggregatedEncoder(t) + for _, input := range testInputWithAllTypesAndMultiCustomPoliciesList { + require.NoError(t, testUnaggregatedEncode(t, encoder, input.metric, input.policiesList)) + expected = append(expected, expectedResultsForUnaggregatedMetricWithPoliciesList(t, input.metric, input.policiesList)...) } require.Equal(t, expected, *results) @@ -88,7 +99,7 @@ func TestUnaggregatedEncodeAllTypesWithSingleCustomPolicies(t *testing.T) { func TestUnaggregatedEncodeVarintError(t *testing.T) { counter := testCounter - policies := testDefaultStagedPolicies + policies := testDefaultStagedPoliciesList // Intentionally return an error when encoding varint. encoder := testUnaggregatedEncoder(t).(*unaggregatedEncoder) @@ -106,7 +117,7 @@ func TestUnaggregatedEncodeVarintError(t *testing.T) { func TestUnaggregatedEncodeFloat64Error(t *testing.T) { gauge := testGauge - policies := testDefaultStagedPolicies + policies := testDefaultStagedPoliciesList // Intentionally return an error when encoding float64. encoder := testUnaggregatedEncoder(t).(*unaggregatedEncoder) @@ -124,7 +135,7 @@ func TestUnaggregatedEncodeFloat64Error(t *testing.T) { func TestUnaggregatedEncodeBytesError(t *testing.T) { timer := testBatchTimer - policies := testDefaultStagedPolicies + policies := testDefaultStagedPoliciesList // Intentionally return an error when encoding array length. encoder := testUnaggregatedEncoder(t).(*unaggregatedEncoder) @@ -168,7 +179,7 @@ func TestUnaggregatedEncodeArrayLenError(t *testing.T) { func TestUnaggregatedEncoderReset(t *testing.T) { metric := testCounter - policies := testDefaultStagedPolicies + policies := testDefaultStagedPoliciesList encoder := testUnaggregatedEncoder(t).(*unaggregatedEncoder) baseEncoder := encoder.encoderBase.(*baseEncoder) @@ -254,7 +265,7 @@ func expectedResultsForPoliciesList(t *testing.T, pl policy.PoliciesList) []inte return results } -func expectedResultsForUnaggregatedMetricWithPolicies( +func expectedResultsForUnaggregatedMetricWithPoliciesList( t *testing.T, m unaggregated.MetricUnion, pl policy.PoliciesList, diff --git a/protocol/msgpack/unaggregated_iterator_test.go b/protocol/msgpack/unaggregated_iterator_test.go index 4e22f70..76349e8 100644 --- a/protocol/msgpack/unaggregated_iterator_test.go +++ b/protocol/msgpack/unaggregated_iterator_test.go @@ -38,40 +38,72 @@ import ( func TestUnaggregatedIteratorDecodeDefaultPoliciesList(t *testing.T) { enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) - enc.encodePoliciesList(testDefaultStagedPolicies) + enc.encodePoliciesList(testDefaultStagedPoliciesList) require.NoError(t, enc.err()) it := testUnaggregatedIterator(t, enc.Encoder().Buffer()).(*unaggregatedIterator) it.decodePoliciesList() require.NoError(t, it.Err()) _, pl := it.Value() - require.Equal(t, testDefaultStagedPolicies, pl) + require.Equal(t, testDefaultStagedPoliciesList, pl) } func TestUnaggregatedIteratorDecodeSingleCustomPoliciesListWithAlloc(t *testing.T) { enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) - enc.encodePoliciesList(testSingleCustomStagedPolicies) + enc.encodePoliciesList(testSingleCustomStagedPoliciesList) require.NoError(t, enc.err()) it := testUnaggregatedIterator(t, enc.Encoder().Buffer()).(*unaggregatedIterator) it.decodePoliciesList() require.NoError(t, it.Err()) _, pl := it.Value() - require.Equal(t, testSingleCustomStagedPolicies, pl) - require.Equal(t, len(it.cachedPolicies), len(testSingleCustomStagedPolicies)) - require.Equal(t, it.cachedPolicies[0], testSingleCustomStagedPolicies[0].Policies()) + require.Equal(t, testSingleCustomStagedPoliciesList, pl) + require.Equal(t, len(it.cachedPolicies), len(testSingleCustomStagedPoliciesList)) + require.Equal(t, it.cachedPolicies[0], testSingleCustomStagedPoliciesList[0].Policies()) } -func TestUnaggregatedIteratorDecodeSingleCustomPoliciesNoPoliciesListAlloc(t *testing.T) { +func TestUnaggregatedIteratorDecodeSingleCustomPoliciesListNoPoliciesListAlloc(t *testing.T) { enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) - enc.encodePoliciesList(testSingleCustomStagedPolicies) + enc.encodePoliciesList(testSingleCustomStagedPoliciesList) require.NoError(t, enc.err()) it := testUnaggregatedIterator(t, enc.Encoder().Buffer()).(*unaggregatedIterator) - it.cachedPoliciesList = make(policy.PoliciesList, len(testSingleCustomStagedPolicies)*3) + it.cachedPoliciesList = make(policy.PoliciesList, len(testSingleCustomStagedPoliciesList)*3) it.decodePoliciesList() require.NoError(t, it.Err()) _, pl := it.Value() - require.Equal(t, testSingleCustomStagedPolicies, pl) - require.Equal(t, len(it.cachedPolicies), len(testSingleCustomStagedPolicies)) - require.Equal(t, it.cachedPolicies[0], testSingleCustomStagedPolicies[0].Policies()) + require.Equal(t, testSingleCustomStagedPoliciesList, pl) + require.Equal(t, len(it.cachedPolicies), len(testSingleCustomStagedPoliciesList)) + require.Equal(t, it.cachedPolicies[0], testSingleCustomStagedPoliciesList[0].Policies()) +} + +func TestUnaggregatedIteratorDecodeSingleCustomPoliciesListNoAlloc(t *testing.T) { + enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) + enc.encodePoliciesList(testSingleCustomStagedPoliciesList) + require.NoError(t, enc.err()) + it := testUnaggregatedIterator(t, enc.Encoder().Buffer()).(*unaggregatedIterator) + it.cachedPoliciesList = make(policy.PoliciesList, len(testSingleCustomStagedPoliciesList)*3) + it.cachedPolicies = make([][]policy.Policy, len(testSingleCustomStagedPoliciesList)*3) + it.cachedPolicies[0] = make([]policy.Policy, 32) + it.decodePoliciesList() + require.NoError(t, it.Err()) + _, pl := it.Value() + require.Equal(t, testSingleCustomStagedPoliciesList, pl) + require.Equal(t, len(it.cachedPolicies), len(testSingleCustomStagedPoliciesList)) + require.Equal(t, it.cachedPolicies[0], testSingleCustomStagedPoliciesList[0].Policies()) +} + +func TestUnaggregatedIteratorDecodeMultiCustomPoliciesListWithAlloc(t *testing.T) { + input := testMultiCustomStagedPoliciesList + enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) + enc.encodePoliciesList(input) + require.NoError(t, enc.err()) + it := testUnaggregatedIterator(t, enc.Encoder().Buffer()).(*unaggregatedIterator) + it.decodePoliciesList() + require.NoError(t, it.Err()) + _, pl := it.Value() + require.Equal(t, input, pl) + require.Equal(t, len(it.cachedPolicies), len(input)) + for i := 0; i < len(input); i++ { + require.Equal(t, it.cachedPolicies[i], input[i].Policies()) + } } func TestUnaggregatedIteratorDecodeIDDecodeBytesLenError(t *testing.T) { @@ -264,7 +296,7 @@ func TestUnaggregatedIteratorDecodeBatchTimerWithAllocPoolAlloc(t *testing.T) { func TestUnaggregatedIteratorDecodeNewerVersionThanSupported(t *testing.T) { input := metricWithPoliciesList{ metric: testCounter, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, } enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) @@ -293,7 +325,7 @@ func TestUnaggregatedIteratorDecodeNewerVersionThanSupported(t *testing.T) { func TestUnaggregatedIteratorDecodeRootObjectMoreFieldsThanExpected(t *testing.T) { input := metricWithPoliciesList{ metric: testCounter, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, } enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) @@ -316,7 +348,7 @@ func TestUnaggregatedIteratorDecodeRootObjectMoreFieldsThanExpected(t *testing.T func TestUnaggregatedIteratorDecodeCounterWithPoliciesMoreFieldsThanExpected(t *testing.T) { input := metricWithPoliciesList{ metric: testCounter, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, } enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) @@ -339,7 +371,7 @@ func TestUnaggregatedIteratorDecodeCounterWithPoliciesMoreFieldsThanExpected(t * func TestUnaggregatedIteratorDecodeCounterMoreFieldsThanExpected(t *testing.T) { input := metricWithPoliciesList{ metric: testCounter, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, } enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) @@ -361,7 +393,7 @@ func TestUnaggregatedIteratorDecodeCounterMoreFieldsThanExpected(t *testing.T) { func TestUnaggregatedIteratorDecodeBatchTimerMoreFieldsThanExpected(t *testing.T) { input := metricWithPoliciesList{ metric: testBatchTimer, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, } enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) @@ -386,7 +418,7 @@ func TestUnaggregatedIteratorDecodeBatchTimerMoreFieldsThanExpected(t *testing.T func TestUnaggregatedIteratorDecodeGaugeMoreFieldsThanExpected(t *testing.T) { input := metricWithPoliciesList{ metric: testGauge, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, } enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) @@ -483,7 +515,7 @@ func TestUnaggregatedIteratorDecodePolicyMoreFieldsThanExpected(t *testing.T) { func TestUnaggregatedIteratorDecodePoliciesListMoreFieldsThanExpected(t *testing.T) { input := metricWithPoliciesList{ metric: testGauge, - policiesList: testSingleCustomStagedPolicies, + policiesList: testSingleCustomStagedPoliciesList, } enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) @@ -508,7 +540,7 @@ func TestUnaggregatedIteratorDecodePoliciesListMoreFieldsThanExpected(t *testing func TestUnaggregatedIteratorDecodeCounterFewerFieldsThanExpected(t *testing.T) { input := metricWithPoliciesList{ metric: testCounter, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, } enc := testUnaggregatedEncoder(t).(*unaggregatedEncoder) @@ -579,5 +611,5 @@ func validateUnaggregatedDecodeResults( }) } require.Equal(t, expectedErr, it.Err()) - validateMetricsWithPolicies(t, expectedResults, results) + validateMetricsWithPoliciesList(t, expectedResults, results) } diff --git a/protocol/msgpack/unaggregated_roundtrip_test.go b/protocol/msgpack/unaggregated_roundtrip_test.go index ce05032..796ff7e 100644 --- a/protocol/msgpack/unaggregated_roundtrip_test.go +++ b/protocol/msgpack/unaggregated_roundtrip_test.go @@ -54,9 +54,9 @@ var ( GaugeVal: 123.456, } - testDefaultStagedPolicies = policy.DefaultPoliciesList + testDefaultStagedPoliciesList = policy.DefaultPoliciesList - testSingleCustomStagedPolicies = policy.PoliciesList{ + testSingleCustomStagedPoliciesList = policy.PoliciesList{ policy.NewStagedPolicies( time.Now().UnixNano(), false, @@ -68,6 +68,25 @@ var ( ), } + testMultiCustomStagedPoliciesList = policy.PoliciesList{ + policy.NewStagedPolicies( + time.Now().UnixNano(), + false, + []policy.Policy{ + policy.NewPolicy(20*time.Second, xtime.Second, 6*time.Hour), + policy.NewPolicy(time.Minute, xtime.Minute, 2*24*time.Hour), + policy.NewPolicy(10*time.Minute, xtime.Minute, 25*24*time.Hour), + }, + ), + policy.NewStagedPolicies( + time.Now().Add(time.Minute).UnixNano(), + true, + []policy.Policy{ + policy.NewPolicy(time.Second, xtime.Second, time.Hour), + }, + ), + } + testStagedPoliciesWithInvalidTimeUnit = policy.PoliciesList{ policy.NewStagedPolicies( time.Now().UnixNano(), @@ -78,22 +97,22 @@ var ( ), } - testInputWithAllTypesAndDefaultPolicies = []metricWithPoliciesList{ + testInputWithAllTypesAndDefaultPoliciesList = []metricWithPoliciesList{ { metric: testCounter, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, }, { metric: testBatchTimer, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, }, { metric: testGauge, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, }, } - testInputWithAllTypesAndSingleCustomPolicies = []metricWithPoliciesList{ + testInputWithAllTypesAndSingleCustomPoliciesList = []metricWithPoliciesList{ // Retain this metric at 20 second resolution for 6 hours, // then 1 minute for 2 days, then 10 minutes for 25 days. { @@ -137,35 +156,101 @@ var ( }, }, } + + testInputWithAllTypesAndMultiCustomPoliciesList = []metricWithPoliciesList{ + { + metric: testBatchTimer, + policiesList: policy.PoliciesList{ + policy.NewStagedPolicies( + time.Now().UnixNano(), + false, + []policy.Policy{ + policy.NewPolicy(20*time.Second, xtime.Second, 6*time.Hour), + policy.NewPolicy(time.Minute, xtime.Minute, 2*24*time.Hour), + policy.NewPolicy(10*time.Minute, xtime.Minute, 25*24*time.Hour), + }, + ), + policy.NewStagedPolicies( + time.Now().Add(time.Minute).UnixNano(), + true, + []policy.Policy{ + policy.NewPolicy(time.Second, xtime.Second, time.Hour), + }, + ), + }, + }, + { + metric: testCounter, + policiesList: policy.PoliciesList{ + policy.NewStagedPolicies( + time.Now().UnixNano(), + true, + []policy.Policy{ + policy.NewPolicy(time.Second, xtime.Second, time.Hour), + }, + ), + policy.NewStagedPolicies( + time.Now().Add(time.Hour).UnixNano(), + false, + []policy.Policy{ + policy.NewPolicy(10*time.Minute, xtime.Minute, 45*24*time.Hour), + }, + ), + }, + }, + { + metric: testGauge, + policiesList: policy.PoliciesList{ + policy.NewStagedPolicies( + time.Now().UnixNano(), + false, + []policy.Policy{ + policy.NewPolicy(10*time.Minute, xtime.Minute, 45*24*time.Hour), + }, + ), + policy.NewStagedPolicies( + time.Now().Add(time.Nanosecond).UnixNano(), + false, + []policy.Policy{ + policy.NewPolicy(5*time.Minute, xtime.Minute, 36*time.Hour), + }, + ), + }, + }, + } ) -func TestUnaggregatedEncodeDecodeCounterWithDefaultPolicies(t *testing.T) { +func TestUnaggregatedEncodeDecodeCounterWithDefaultPoliciesList(t *testing.T) { validateUnaggregatedRoundtrip(t, metricWithPoliciesList{ metric: testCounter, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, }) } -func TestUnaggregatedEncodeDecodeBatchTimerWithDefaultPolicies(t *testing.T) { +func TestUnaggregatedEncodeDecodeBatchTimerWithDefaultPoliciesList(t *testing.T) { validateUnaggregatedRoundtrip(t, metricWithPoliciesList{ metric: testBatchTimer, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, }) } -func TestUnaggregatedEncodeDecodeGaugeWithDefaultPolicies(t *testing.T) { +func TestUnaggregatedEncodeDecodeGaugeWithDefaultPoliciesList(t *testing.T) { validateUnaggregatedRoundtrip(t, metricWithPoliciesList{ metric: testGauge, - policiesList: testDefaultStagedPolicies, + policiesList: testDefaultStagedPoliciesList, }) } -func TestUnaggregatedEncodeDecodeAllTypesWithDefaultPolicies(t *testing.T) { - validateUnaggregatedRoundtrip(t, testInputWithAllTypesAndDefaultPolicies...) +func TestUnaggregatedEncodeDecodeAllTypesWithDefaultPoliciesList(t *testing.T) { + validateUnaggregatedRoundtrip(t, testInputWithAllTypesAndDefaultPoliciesList...) +} + +func TestUnaggregatedEncodeDecodeAllTypesWithSingleCustomPoliciesList(t *testing.T) { + validateUnaggregatedRoundtrip(t, testInputWithAllTypesAndSingleCustomPoliciesList...) } -func TestUnaggregatedEncodeDecodeAllTypesWithCustomPolicies(t *testing.T) { - validateUnaggregatedRoundtrip(t, testInputWithAllTypesAndSingleCustomPolicies...) +func TestUnaggregatedEncodeDecodeAllTypesWithMultiCustomPoliciesList(t *testing.T) { + validateUnaggregatedRoundtrip(t, testInputWithAllTypesAndMultiCustomPoliciesList...) } func TestUnaggregatedEncodeDecodeStress(t *testing.T) { @@ -173,7 +258,7 @@ func TestUnaggregatedEncodeDecodeStress(t *testing.T) { numMetrics := 10000 allMetrics := []unaggregated.MetricUnion{testCounter, testBatchTimer, testGauge} allPolicies := []policy.PoliciesList{ - testDefaultStagedPolicies, + testDefaultStagedPoliciesList, policy.PoliciesList{ policy.NewStagedPolicies( time.Now().UnixNano(), @@ -184,6 +269,29 @@ func TestUnaggregatedEncodeDecodeStress(t *testing.T) { }, ), }, + policy.PoliciesList{ + policy.NewStagedPolicies( + time.Now().UnixNano(), + false, + []policy.Policy{ + policy.NewPolicy(20*time.Second, xtime.Second, 6*time.Hour), + policy.NewPolicy(time.Minute, xtime.Minute, 2*24*time.Hour), + policy.NewPolicy(10*time.Minute, xtime.Minute, 25*24*time.Hour), + }, + ), + policy.NewStagedPolicies( + time.Now().Add(time.Minute).UnixNano(), + true, + []policy.Policy{ + policy.NewPolicy(time.Second, xtime.Second, time.Hour), + }, + ), + policy.NewStagedPolicies( + time.Now().Add(time.Minute).UnixNano(), + false, + []policy.Policy{}, + ), + }, } encoder := testUnaggregatedEncoder(t) @@ -275,6 +383,15 @@ func compareUnaggregatedMetric(t *testing.T, expected unaggregated.MetricUnion, } } +func comparedPoliciesList(t *testing.T, expected policy.PoliciesList, actual policy.PoliciesList) { + require.Equal(t, len(expected), len(actual)) + for i := 0; i < len(expected); i++ { + require.Equal(t, expected[i].CutoverNs, actual[i].CutoverNs) + require.Equal(t, expected[i].Tombstoned, actual[i].Tombstoned) + require.Equal(t, expected[i].Policies(), actual[i].Policies()) + } +} + func validateUnaggregatedRoundtrip(t *testing.T, inputs ...metricWithPoliciesList) { encoder := testUnaggregatedEncoder(t) it := testUnaggregatedIterator(t, nil) @@ -313,14 +430,14 @@ func validateUnaggregatedRoundtripWithEncoderAndIterator( // Assert the results match expectations. require.Equal(t, io.EOF, it.Err()) - validateMetricsWithPolicies(t, inputs, results) + validateMetricsWithPoliciesList(t, inputs, results) } -func validateMetricsWithPolicies(t *testing.T, inputs, results []metricWithPoliciesList) { +func validateMetricsWithPoliciesList(t *testing.T, inputs, results []metricWithPoliciesList) { require.Equal(t, len(inputs), len(results)) for i := 0; i < len(inputs); i++ { compareUnaggregatedMetric(t, inputs[i].metric, results[i].metric) - require.Equal(t, inputs[i].policiesList, results[i].policiesList) + comparedPoliciesList(t, inputs[i].policiesList, results[i].policiesList) } } diff --git a/rules/result_test.go b/rules/result_test.go index f99331d..f395b12 100644 --- a/rules/result_test.go +++ b/rules/result_test.go @@ -30,13 +30,18 @@ import ( "github.com/stretchr/testify/require" ) +func TestMatchResultHasExpired(t *testing.T) { + r := NewMatchResult(1000, nil, nil) + require.False(t, r.HasExpired(time.Unix(0, 0))) + require.True(t, r.HasExpired(time.Unix(0, 1000))) +} + func TestMatchResult(t *testing.T) { var ( - cutoverNs = int64(12345) - expireAtNs = int64(67890) - mappings = policy.PoliciesList{ + testExpireAtNs = int64(67890) + testResultMappings = policy.PoliciesList{ policy.NewStagedPolicies( - cutoverNs, + 12345, false, []policy.Policy{ policy.NewPolicy(10*time.Second, xtime.Second, 12*time.Hour), @@ -44,13 +49,21 @@ func TestMatchResult(t *testing.T) { policy.NewPolicy(5*time.Minute, xtime.Minute, 48*time.Hour), }, ), + policy.NewStagedPolicies( + 23456, + true, + []policy.Policy{ + policy.NewPolicy(30*time.Second, xtime.Second, 10*time.Hour), + policy.NewPolicy(2*time.Minute, xtime.Minute, 48*time.Hour), + }, + ), } - rollups = []RollupResult{ + testResultRollups = []RollupResult{ { ID: b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"), PoliciesList: policy.PoliciesList{ policy.NewStagedPolicies( - cutoverNs, + 12345, false, []policy.Policy{ policy.NewPolicy(10*time.Second, xtime.Second, 12*time.Hour), @@ -58,39 +71,78 @@ func TestMatchResult(t *testing.T) { policy.NewPolicy(5*time.Minute, xtime.Minute, 48*time.Hour), }, ), + policy.NewStagedPolicies( + 23456, + false, + []policy.Policy{ + policy.NewPolicy(30*time.Second, xtime.Second, 10*time.Hour), + policy.NewPolicy(2*time.Minute, xtime.Minute, 48*time.Hour), + }, + ), }, }, { ID: b("rName2|rtagName1=rtagValue1"), - PoliciesList: policy.PoliciesList{policy.NewStagedPolicies(cutoverNs, false, nil)}, + PoliciesList: policy.PoliciesList{policy.NewStagedPolicies(12345, false, nil)}, }, } ) - res := NewMatchResult(expireAtNs, mappings, rollups) - require.False(t, res.HasExpired(time.Unix(0, 0))) - require.True(t, res.HasExpired(time.Unix(0, 100000))) - - require.Equal(t, mappings, res.MappingsAt(time.Unix(0, 0))) + inputs := []struct { + matchAt time.Time + expectedMappings policy.PoliciesList + expectedRollups []RollupResult + }{ + { + matchAt: time.Unix(0, 0), + expectedMappings: testResultMappings, + expectedRollups: testResultRollups, + }, + { + matchAt: time.Unix(0, 20000), + expectedMappings: testResultMappings, + expectedRollups: testResultRollups, + }, + { + matchAt: time.Unix(0, 30000), + expectedMappings: policy.PoliciesList{ + policy.NewStagedPolicies( + 23456, + true, + []policy.Policy{ + policy.NewPolicy(30*time.Second, xtime.Second, 10*time.Hour), + policy.NewPolicy(2*time.Minute, xtime.Minute, 48*time.Hour), + }, + ), + }, + expectedRollups: []RollupResult{ + { + ID: b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"), + PoliciesList: policy.PoliciesList{ + policy.NewStagedPolicies( + 23456, + false, + []policy.Policy{ + policy.NewPolicy(30*time.Second, xtime.Second, 10*time.Hour), + policy.NewPolicy(2*time.Minute, xtime.Minute, 48*time.Hour), + }, + ), + }, + }, + { + ID: b("rName2|rtagName1=rtagValue1"), + PoliciesList: policy.PoliciesList{policy.NewStagedPolicies(12345, false, nil)}, + }, + }, + }, + } - var ( - expectedRollupIDs = [][]byte{ - b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"), - b("rName2|rtagName1=rtagValue1"), + res := NewMatchResult(testExpireAtNs, testResultMappings, testResultRollups) + for _, input := range inputs { + require.Equal(t, input.expectedMappings, res.MappingsAt(input.matchAt)) + require.Equal(t, len(input.expectedRollups), res.NumRollups()) + for i := 0; i < len(input.expectedRollups); i++ { + require.Equal(t, input.expectedRollups[i], res.RollupsAt(i, input.matchAt)) } - expectedRollupPolicies = policy.PoliciesList{ - rollups[0].PoliciesList[0], - rollups[1].PoliciesList[0], - } - rollupIDs [][]byte - rollupPolicies policy.PoliciesList - ) - require.Equal(t, 2, res.NumRollups()) - for i := 0; i < 2; i++ { - rollup := res.RollupsAt(i, time.Unix(0, 0)) - rollupIDs = append(rollupIDs, rollup.ID) - rollupPolicies = append(rollupPolicies, rollup.PoliciesList...) } - require.Equal(t, expectedRollupIDs, rollupIDs) - require.Equal(t, expectedRollupPolicies, rollupPolicies) } diff --git a/rules/ruleset.go b/rules/ruleset.go index 927befd..c9b06c8 100644 --- a/rules/ruleset.go +++ b/rules/ruleset.go @@ -127,7 +127,21 @@ func (as *activeRuleSet) matchMappings(id []byte, timeNs int64) policy.StagedPol ) for _, mappingRule := range as.mappingRules { snapshot := mappingRule.ActiveSnapshot(timeNs) - if snapshot == nil || snapshot.tombstoned || !snapshot.filter.Matches(id) { + if snapshot == nil { + continue + } + // NB(xichen): if the snapshot is tombstoned, we don't perform id matching with it. + // However, because it may affect the final resolved policies for this id, we need + // to update the cutover time. This is okay even though the tombstoned snapshot doesn't + // match the id because the cutover time of the result policies only needs to be best effort + // as long as it is before the time passed in. + if snapshot.tombstoned { + if cutoverNs < snapshot.cutoverNs { + cutoverNs = snapshot.cutoverNs + } + continue + } + if !snapshot.filter.Matches(id) { continue } if cutoverNs < snapshot.cutoverNs { @@ -135,6 +149,9 @@ func (as *activeRuleSet) matchMappings(id []byte, timeNs int64) policy.StagedPol } policies = append(policies, snapshot.policies...) } + if len(policies) == 0 { + return policy.EmptyStagedPolicies + } resolved := resolvePolicies(policies) return policy.NewStagedPolicies(cutoverNs, false, resolved) } @@ -147,7 +164,16 @@ func (as *activeRuleSet) matchRollups(id []byte, timeNs int64) []RollupResult { ) for _, rollupRule := range as.rollupRules { snapshot := rollupRule.ActiveSnapshot(timeNs) - if snapshot == nil || snapshot.tombstoned || !snapshot.filter.Matches(id) { + if snapshot == nil { + continue + } + if snapshot.tombstoned { + if cutoverNs < snapshot.cutoverNs { + cutoverNs = snapshot.cutoverNs + } + continue + } + if !snapshot.filter.Matches(id) { continue } if cutoverNs < snapshot.cutoverNs { @@ -172,6 +198,9 @@ func (as *activeRuleSet) matchRollups(id []byte, timeNs int64) []RollupResult { } // Resolve the policies for each rollup target. + if len(rollups) == 0 { + return nil + } for i := range rollups { rollups[i].Policies = resolvePolicies(rollups[i].Policies) } @@ -408,8 +437,11 @@ func mergeRollupResults( // If the current id is smaller, it means the id is deleted in the next rollup result. if compareResult < 0 { - tombstonedPolicies := policy.NewStagedPolicies(nextCutoverNs, true, nil) - currRollupResults[currRollupIdx].PoliciesList = append(currRollupResults[currRollupIdx].PoliciesList, tombstonedPolicies) + currRollupPolicies := currRollupResult.PoliciesList[len(currRollupResult.PoliciesList)-1] + if !currRollupPolicies.Tombstoned { + tombstonedPolicies := policy.NewStagedPolicies(nextCutoverNs, true, nil) + currRollupResults[currRollupIdx].PoliciesList = append(currRollupResults[currRollupIdx].PoliciesList, tombstonedPolicies) + } currRollupIdx++ continue } @@ -422,8 +454,12 @@ func mergeRollupResults( // If there are leftover ids in the current rollup result, these ids must have been deleted // in the next rollup result. for currRollupIdx < numCurrRollupResults { - tombstonedPolicies := policy.NewStagedPolicies(nextCutoverNs, true, nil) - currRollupResults[currRollupIdx].PoliciesList = append(currRollupResults[currRollupIdx].PoliciesList, tombstonedPolicies) + currRollupResult := currRollupResults[currRollupIdx] + currRollupPolicies := currRollupResult.PoliciesList[len(currRollupResult.PoliciesList)-1] + if !currRollupPolicies.Tombstoned { + tombstonedPolicies := policy.NewStagedPolicies(nextCutoverNs, true, nil) + currRollupResults[currRollupIdx].PoliciesList = append(currRollupResults[currRollupIdx].PoliciesList, tombstonedPolicies) + } currRollupIdx++ } diff --git a/rules/ruleset_test.go b/rules/ruleset_test.go index f8f38c4..d68dd64 100644 --- a/rules/ruleset_test.go +++ b/rules/ruleset_test.go @@ -37,7 +37,8 @@ func TestActiveRuleSetMatchMappingRules(t *testing.T) { inputs := []testMappingsData{ { id: "mtagName1=mtagValue1", - matchAt: time.Unix(0, 25000), + matchFrom: time.Unix(0, 25000), + matchTo: time.Unix(0, 25001), expireAtNs: 30000, result: policy.PoliciesList{ policy.NewStagedPolicies( @@ -53,11 +54,12 @@ func TestActiveRuleSetMatchMappingRules(t *testing.T) { }, { id: "mtagName1=mtagValue1", - matchAt: time.Unix(0, 35000), + matchFrom: time.Unix(0, 35000), + matchTo: time.Unix(0, 35001), expireAtNs: 100000, result: policy.PoliciesList{ policy.NewStagedPolicies( - 34000, + 35000, false, []policy.Policy{ policy.NewPolicy(10*time.Second, xtime.Second, 2*time.Hour), @@ -68,7 +70,8 @@ func TestActiveRuleSetMatchMappingRules(t *testing.T) { }, { id: "mtagName1=mtagValue2", - matchAt: time.Unix(0, 25000), + matchFrom: time.Unix(0, 25000), + matchTo: time.Unix(0, 25001), expireAtNs: 30000, result: policy.PoliciesList{ policy.NewStagedPolicies( @@ -82,10 +85,67 @@ func TestActiveRuleSetMatchMappingRules(t *testing.T) { }, { id: "mtagName1=mtagValue3", - matchAt: time.Unix(0, 25000), + matchFrom: time.Unix(0, 25000), + matchTo: time.Unix(0, 25001), expireAtNs: 30000, result: policy.DefaultPoliciesList, }, + { + id: "mtagName1=mtagValue1", + matchFrom: time.Unix(0, 10000), + matchTo: time.Unix(0, 40000), + expireAtNs: 100000, + result: policy.PoliciesList{ + policy.NewStagedPolicies( + 10000, + false, + []policy.Policy{ + policy.NewPolicy(10*time.Second, xtime.Second, 24*time.Hour), + }, + ), + policy.NewStagedPolicies( + 20000, + false, + []policy.Policy{ + policy.NewPolicy(10*time.Second, xtime.Second, 12*time.Hour), + policy.NewPolicy(5*time.Minute, xtime.Minute, 48*time.Hour), + }, + ), + policy.NewStagedPolicies( + 22000, + false, + []policy.Policy{ + policy.NewPolicy(10*time.Second, xtime.Second, 12*time.Hour), + policy.NewPolicy(time.Minute, xtime.Minute, 24*time.Hour), + policy.NewPolicy(5*time.Minute, xtime.Minute, 48*time.Hour), + }, + ), + policy.NewStagedPolicies( + 34000, + false, + []policy.Policy{ + policy.NewPolicy(10*time.Second, xtime.Second, 2*time.Hour), + policy.NewPolicy(30*time.Second, xtime.Second, 6*time.Hour), + }, + ), + }, + }, + { + id: "mtagName1=mtagValue2", + matchFrom: time.Unix(0, 10000), + matchTo: time.Unix(0, 40000), + expireAtNs: 100000, + result: policy.PoliciesList{ + policy.EmptyStagedPolicies, + policy.NewStagedPolicies( + 24000, + false, + []policy.Policy{ + policy.NewPolicy(10*time.Second, xtime.Second, 24*time.Hour), + }, + ), + }, + }, } mappingRules := testMappingRules(t) @@ -98,7 +158,7 @@ func TestActiveRuleSetMatchMappingRules(t *testing.T) { expectedCutovers := []int64{10000, 15000, 20000, 22000, 24000, 30000, 34000, 35000, 100000} require.Equal(t, expectedCutovers, as.cutoverTimesAsc) for _, input := range inputs { - res := as.MatchAll(b(input.id), input.matchAt, input.matchAt.Add(time.Nanosecond)) + res := as.MatchAll(b(input.id), input.matchFrom, input.matchTo) require.Equal(t, input.expireAtNs, res.expireAtNs) require.Equal(t, input.result, res.MappingsAt(time.Unix(0, 0))) } @@ -108,7 +168,8 @@ func TestActiveRuleSetMatchRollupRules(t *testing.T) { inputs := []testRollupResultsData{ { id: "rtagName1=rtagValue1,rtagName2=rtagValue2,rtagName3=rtagValue3", - matchAt: time.Unix(0, 25000), + matchFrom: time.Unix(0, 25000), + matchTo: time.Unix(0, 25001), expireAtNs: 30000, result: []RollupResult{ { @@ -141,7 +202,8 @@ func TestActiveRuleSetMatchRollupRules(t *testing.T) { }, { id: "rtagName1=rtagValue2", - matchAt: time.Unix(0, 25000), + matchFrom: time.Unix(0, 25000), + matchTo: time.Unix(0, 25001), expireAtNs: 30000, result: []RollupResult{ { @@ -160,10 +222,90 @@ func TestActiveRuleSetMatchRollupRules(t *testing.T) { }, { id: "rtagName5=rtagValue5", - matchAt: time.Unix(0, 25000), + matchFrom: time.Unix(0, 25000), + matchTo: time.Unix(0, 25001), expireAtNs: 30000, result: []RollupResult{}, }, + { + id: "rtagName1=rtagValue1,rtagName2=rtagValue2,rtagName3=rtagValue3", + matchFrom: time.Unix(0, 10000), + matchTo: time.Unix(0, 40000), + expireAtNs: 100000, + result: []RollupResult{ + { + ID: b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"), + PoliciesList: policy.PoliciesList{ + policy.NewStagedPolicies( + 10000, + false, + []policy.Policy{ + policy.NewPolicy(10*time.Second, xtime.Second, 24*time.Hour), + }, + ), + policy.NewStagedPolicies( + 20000, + false, + []policy.Policy{ + policy.NewPolicy(10*time.Second, xtime.Second, 12*time.Hour), + policy.NewPolicy(5*time.Minute, xtime.Minute, 48*time.Hour), + }, + ), + policy.NewStagedPolicies( + 22000, + false, + []policy.Policy{ + policy.NewPolicy(10*time.Second, xtime.Second, 12*time.Hour), + policy.NewPolicy(time.Minute, xtime.Minute, 24*time.Hour), + policy.NewPolicy(5*time.Minute, xtime.Minute, 48*time.Hour), + }, + ), + policy.NewStagedPolicies( + 34000, + false, + []policy.Policy{ + policy.NewPolicy(10*time.Second, xtime.Second, 2*time.Hour), + policy.NewPolicy(30*time.Second, xtime.Second, 6*time.Hour), + }, + ), + policy.NewStagedPolicies( + 35000, + false, + []policy.Policy{ + policy.NewPolicy(10*time.Second, xtime.Second, 2*time.Hour), + policy.NewPolicy(30*time.Second, xtime.Second, 6*time.Hour), + policy.NewPolicy(45*time.Second, xtime.Second, 12*time.Hour), + }, + ), + policy.NewStagedPolicies( + 38000, + false, + []policy.Policy{ + policy.NewPolicy(30*time.Second, xtime.Second, 6*time.Hour), + policy.NewPolicy(45*time.Second, xtime.Second, 12*time.Hour), + }, + ), + }, + }, + { + ID: b("rName2|rtagName1=rtagValue1"), + PoliciesList: policy.PoliciesList{ + policy.NewStagedPolicies( + 22000, + false, + []policy.Policy{ + policy.NewPolicy(10*time.Second, xtime.Second, 24*time.Hour), + }, + ), + policy.NewStagedPolicies( + 34000, + true, + nil, + ), + }, + }, + }, + }, } rollupRules := testRollupRules(t) @@ -173,10 +315,10 @@ func TestActiveRuleSetMatchRollupRules(t *testing.T) { nil, rollupRules, ) - expectedCutovers := []int64{10000, 15000, 20000, 22000, 24000, 30000, 34000, 35000, 100000} + expectedCutovers := []int64{10000, 15000, 20000, 22000, 24000, 30000, 34000, 35000, 38000, 100000} require.Equal(t, expectedCutovers, as.cutoverTimesAsc) for _, input := range inputs { - res := as.MatchAll(b(input.id), input.matchAt, input.matchAt.Add(time.Nanosecond)) + res := as.MatchAll(b(input.id), input.matchFrom, input.matchTo) require.Equal(t, input.expireAtNs, res.expireAtNs) require.Equal(t, len(input.result), res.NumRollups()) for i := 0; i < len(input.result); i++ { @@ -230,7 +372,8 @@ func TestRuleSetActiveSet(t *testing.T) { mappingInputs: []testMappingsData{ { id: "mtagName1=mtagValue1", - matchAt: time.Unix(0, 25000), + matchFrom: time.Unix(0, 25000), + matchTo: time.Unix(0, 25001), expireAtNs: 30000, result: policy.PoliciesList{ policy.NewStagedPolicies( @@ -246,11 +389,12 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "mtagName1=mtagValue1", - matchAt: time.Unix(0, 35000), + matchFrom: time.Unix(0, 35000), + matchTo: time.Unix(0, 35001), expireAtNs: 100000, result: policy.PoliciesList{ policy.NewStagedPolicies( - 34000, + 35000, false, []policy.Policy{ policy.NewPolicy(10*time.Second, xtime.Second, 2*time.Hour), @@ -261,7 +405,8 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "mtagName1=mtagValue2", - matchAt: time.Unix(0, 25000), + matchFrom: time.Unix(0, 25000), + matchTo: time.Unix(0, 25001), expireAtNs: 30000, result: policy.PoliciesList{ policy.NewStagedPolicies( @@ -275,7 +420,8 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "mtagName1=mtagValue3", - matchAt: time.Unix(0, 25000), + matchFrom: time.Unix(0, 25000), + matchTo: time.Unix(0, 25001), expireAtNs: 30000, result: policy.DefaultPoliciesList, }, @@ -283,7 +429,8 @@ func TestRuleSetActiveSet(t *testing.T) { rollupInputs: []testRollupResultsData{ { id: "rtagName1=rtagValue1,rtagName2=rtagValue2,rtagName3=rtagValue3", - matchAt: time.Unix(0, 25000), + matchFrom: time.Unix(0, 25000), + matchTo: time.Unix(0, 25001), expireAtNs: 30000, result: []RollupResult{ { @@ -316,7 +463,8 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "rtagName1=rtagValue2", - matchAt: time.Unix(0, 25000), + matchFrom: time.Unix(0, 25000), + matchTo: time.Unix(0, 25001), expireAtNs: 30000, result: []RollupResult{ { @@ -335,7 +483,8 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "rtagName5=rtagValue5", - matchAt: time.Unix(0, 25000), + matchFrom: time.Unix(0, 25000), + matchTo: time.Unix(0, 25001), expireAtNs: 30000, result: []RollupResult{}, }, @@ -346,11 +495,12 @@ func TestRuleSetActiveSet(t *testing.T) { mappingInputs: []testMappingsData{ { id: "mtagName1=mtagValue1", - matchAt: time.Unix(0, 35000), + matchFrom: time.Unix(0, 35000), + matchTo: time.Unix(0, 35001), expireAtNs: 100000, result: policy.PoliciesList{ policy.NewStagedPolicies( - 34000, + 35000, false, []policy.Policy{ policy.NewPolicy(10*time.Second, xtime.Second, 2*time.Hour), @@ -361,11 +511,12 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "mtagName1=mtagValue2", - matchAt: time.Unix(0, 35000), + matchFrom: time.Unix(0, 35000), + matchTo: time.Unix(0, 35001), expireAtNs: 100000, result: policy.PoliciesList{ policy.NewStagedPolicies( - 24000, + 35000, false, []policy.Policy{ policy.NewPolicy(10*time.Second, xtime.Second, 24*time.Hour), @@ -375,7 +526,8 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "mtagName1=mtagValue3", - matchAt: time.Unix(0, 35000), + matchFrom: time.Unix(0, 35000), + matchTo: time.Unix(0, 35001), expireAtNs: 100000, result: policy.DefaultPoliciesList, }, @@ -383,14 +535,15 @@ func TestRuleSetActiveSet(t *testing.T) { rollupInputs: []testRollupResultsData{ { id: "rtagName1=rtagValue1,rtagName2=rtagValue2,rtagName3=rtagValue3", - matchAt: time.Unix(0, 35000), + matchFrom: time.Unix(0, 35000), + matchTo: time.Unix(0, 35001), expireAtNs: 100000, result: []RollupResult{ { ID: b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"), PoliciesList: policy.PoliciesList{ policy.NewStagedPolicies( - 34000, + 35000, false, []policy.Policy{ policy.NewPolicy(10*time.Second, xtime.Second, 2*time.Hour), @@ -403,14 +556,15 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "rtagName1=rtagValue2", - matchAt: time.Unix(0, 35000), + matchFrom: time.Unix(0, 35000), + matchTo: time.Unix(0, 35001), expireAtNs: 100000, result: []RollupResult{ { ID: b("rName3|rtagName1=rtagValue2"), PoliciesList: policy.PoliciesList{ policy.NewStagedPolicies( - 24000, + 35000, false, []policy.Policy{ policy.NewPolicy(time.Minute, xtime.Minute, time.Hour), @@ -422,7 +576,8 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "rtagName5=rtagValue5", - matchAt: time.Unix(0, 35000), + matchFrom: time.Unix(0, 35000), + matchTo: time.Unix(0, 35001), expireAtNs: 100000, result: []RollupResult{}, }, @@ -433,7 +588,8 @@ func TestRuleSetActiveSet(t *testing.T) { mappingInputs: []testMappingsData{ { id: "mtagName1=mtagValue1", - matchAt: time.Unix(0, 250000), + matchFrom: time.Unix(0, 250000), + matchTo: time.Unix(0, 250001), expireAtNs: timeNsMax, result: policy.PoliciesList{ policy.NewStagedPolicies( @@ -447,11 +603,12 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "mtagName1=mtagValue2", - matchAt: time.Unix(0, 250000), + matchFrom: time.Unix(0, 250000), + matchTo: time.Unix(0, 250001), expireAtNs: timeNsMax, result: policy.PoliciesList{ policy.NewStagedPolicies( - 24000, + 35000, false, []policy.Policy{ policy.NewPolicy(10*time.Second, xtime.Second, 24*time.Hour), @@ -461,7 +618,8 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "mtagName1=mtagValue3", - matchAt: time.Unix(0, 250000), + matchFrom: time.Unix(0, 250000), + matchTo: time.Unix(0, 250001), expireAtNs: timeNsMax, result: policy.DefaultPoliciesList, }, @@ -469,7 +627,8 @@ func TestRuleSetActiveSet(t *testing.T) { rollupInputs: []testRollupResultsData{ { id: "rtagName1=rtagValue1,rtagName2=rtagValue2,rtagName3=rtagValue3", - matchAt: time.Unix(0, 250000), + matchFrom: time.Unix(0, 250000), + matchTo: time.Unix(0, 250001), expireAtNs: timeNsMax, result: []RollupResult{ { @@ -501,14 +660,15 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "rtagName1=rtagValue2", - matchAt: time.Unix(0, 250000), + matchFrom: time.Unix(0, 250000), + matchTo: time.Unix(0, 250001), expireAtNs: timeNsMax, result: []RollupResult{ { ID: b("rName3|rtagName1=rtagValue2"), PoliciesList: policy.PoliciesList{ policy.NewStagedPolicies( - 24000, + 35000, false, []policy.Policy{ policy.NewPolicy(time.Minute, xtime.Minute, time.Hour), @@ -520,7 +680,8 @@ func TestRuleSetActiveSet(t *testing.T) { }, { id: "rtagName5=rtagValue5", - matchAt: time.Unix(0, 250000), + matchFrom: time.Unix(0, 250000), + matchTo: time.Unix(0, 250001), expireAtNs: timeNsMax, result: []RollupResult{}, }, @@ -531,12 +692,12 @@ func TestRuleSetActiveSet(t *testing.T) { for _, inputs := range allInputs { as := newRuleSet.ActiveSet(inputs.activeSetTime) for _, input := range inputs.mappingInputs { - res := as.MatchAll(b(input.id), input.matchAt, input.matchAt.Add(time.Nanosecond)) + res := as.MatchAll(b(input.id), input.matchFrom, input.matchTo) require.Equal(t, input.expireAtNs, res.expireAtNs) require.Equal(t, input.result, res.MappingsAt(time.Unix(0, 0))) } for _, input := range inputs.rollupInputs { - res := as.MatchAll(b(input.id), input.matchAt, input.matchAt.Add(time.Nanosecond)) + res := as.MatchAll(b(input.id), input.matchFrom, input.matchTo) require.Equal(t, input.expireAtNs, res.expireAtNs) require.Equal(t, len(input.result), res.NumRollups()) for i := 0; i < len(input.result); i++ { @@ -625,9 +786,7 @@ func testMappingRules(t *testing.T) []*mappingRule { tombstoned: true, cutoverNs: 35000, filter: filter1, - policies: []policy.Policy{ - policy.NewPolicy(45*time.Second, xtime.Second, 12*time.Hour), - }, + policies: []policy.Policy{}, }, }, } @@ -859,6 +1018,13 @@ func testRollupRules(t *testing.T) []*rollupRule { }, }, }, + &rollupRuleSnapshot{ + name: "rollupRule3.snapshot3", + tombstoned: true, + cutoverNs: 38000, + filter: filter1, + targets: []rollupTarget{}, + }, }, } @@ -1547,14 +1713,16 @@ func testRollupRulesConfig() []*schema.RollupRule { type testMappingsData struct { id string - matchAt time.Time + matchFrom time.Time + matchTo time.Time expireAtNs int64 result policy.PoliciesList } type testRollupResultsData struct { id string - matchAt time.Time + matchFrom time.Time + matchTo time.Time expireAtNs int64 result []RollupResult }