github.com/m3db/m3@v1.5.0/src/metrics/rules/active_ruleset_test.go (about)

     1  // Copyright (c) 2020 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 rules
    22  
    23  import (
    24  	"fmt"
    25  	"math"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/m3db/m3/src/metrics/aggregation"
    30  	"github.com/m3db/m3/src/metrics/filters"
    31  	"github.com/m3db/m3/src/metrics/matcher/namespace"
    32  	"github.com/m3db/m3/src/metrics/metadata"
    33  	"github.com/m3db/m3/src/metrics/metric"
    34  	"github.com/m3db/m3/src/metrics/pipeline"
    35  	"github.com/m3db/m3/src/metrics/pipeline/applied"
    36  	"github.com/m3db/m3/src/metrics/policy"
    37  	"github.com/m3db/m3/src/metrics/transformation"
    38  	"github.com/m3db/m3/src/query/models"
    39  	xtime "github.com/m3db/m3/src/x/time"
    40  
    41  	"github.com/google/go-cmp/cmp"
    42  	"github.com/google/go-cmp/cmp/cmpopts"
    43  	"github.com/stretchr/testify/require"
    44  )
    45  
    46  var (
    47  	testStagedMetadatasCmptOpts = []cmp.Option{
    48  		cmpopts.EquateEmpty(),
    49  	}
    50  	testIDWithMetadatasCmpOpts = []cmp.Option{
    51  		cmpopts.EquateEmpty(),
    52  	}
    53  )
    54  
    55  func TestActiveRuleSetCutoverTimesWithMappingRules(t *testing.T) {
    56  	as := newActiveRuleSet(
    57  		0,
    58  		testMappingRules(t),
    59  		nil,
    60  		testTagsFilterOptions(),
    61  		mockNewID,
    62  		nil,
    63  	)
    64  	expectedCutovers := []int64{5000, 8000, 10000, 15000, 20000, 22000, 24000, 30000, 34000, 35000, 100000}
    65  	require.Equal(t, expectedCutovers, as.cutoverTimesAsc)
    66  }
    67  
    68  func TestActiveRuleSetCutoverTimesWithRollupRules(t *testing.T) {
    69  	as := newActiveRuleSet(
    70  		0,
    71  		nil,
    72  		testRollupRules(t),
    73  		testTagsFilterOptions(),
    74  		mockNewID,
    75  		nil,
    76  	)
    77  	expectedCutovers := []int64{10000, 15000, 20000, 22000, 24000, 30000, 34000, 35000, 38000, 90000, 100000, 120000}
    78  	require.Equal(t, expectedCutovers, as.cutoverTimesAsc)
    79  }
    80  
    81  func TestActiveRuleSetLatestRollupRules(t *testing.T) {
    82  	rules := testRollupRules(t)
    83  	as := newActiveRuleSet(
    84  		0,
    85  		nil,
    86  		rules,
    87  		testTagsFilterOptions(),
    88  		mockNewID,
    89  		nil,
    90  	)
    91  	timeNanos := int64(95000)
    92  	rollupView, err := as.LatestRollupRules(nil, timeNanos)
    93  	require.NoError(t, err)
    94  	// rr3 is tombstoned, so it should not be returned
    95  	require.Equal(t, len(rules)-1, len(rollupView))
    96  	for _, rr := range rollupView {
    97  		// explicitly check that rollupRule3 is not returned..
    98  		require.NotEqual(t, rr.Name, "rollupRule3.snapshot3")
    99  		// ..and that we only get the non-Tombstoned entries.
   100  		require.False(t, rr.Tombstoned)
   101  	}
   102  }
   103  
   104  func TestActiveRuleSetCutoverTimesWithMappingRulesAndRollupRules(t *testing.T) {
   105  	as := newActiveRuleSet(
   106  		0,
   107  		testMappingRules(t),
   108  		testRollupRules(t),
   109  		testTagsFilterOptions(),
   110  		mockNewID,
   111  		nil,
   112  	)
   113  	expectedCutovers := []int64{5000, 8000, 10000, 15000, 20000, 22000, 24000, 30000, 34000, 35000, 38000, 90000, 100000, 120000}
   114  	require.Equal(t, expectedCutovers, as.cutoverTimesAsc)
   115  }
   116  
   117  func TestActiveRuleSetForwardMatchWithMappingRules(t *testing.T) {
   118  	inputs := []testMatchInput{
   119  		{
   120  			id:            "mtagName1=mtagValue1",
   121  			matchFrom:     25000,
   122  			matchTo:       25001,
   123  			expireAtNanos: 30000,
   124  			forExistingIDResult: metadata.StagedMetadatas{
   125  				metadata.StagedMetadata{
   126  					CutoverNanos: 22000,
   127  					Tombstoned:   false,
   128  					Metadata: metadata.Metadata{
   129  						Pipelines: []metadata.PipelineMetadata{
   130  							{
   131  								AggregationID: aggregation.DefaultID,
   132  								StoragePolicies: policy.StoragePolicies{
   133  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
   134  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   135  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
   136  								},
   137  							},
   138  							{
   139  								AggregationID: aggregation.DefaultID,
   140  								StoragePolicies: policy.StoragePolicies{
   141  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
   142  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   143  								},
   144  							},
   145  							{
   146  								AggregationID: aggregation.DefaultID,
   147  								StoragePolicies: policy.StoragePolicies{
   148  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
   149  									policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
   150  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   151  								},
   152  							},
   153  						},
   154  					},
   155  				},
   156  			},
   157  		},
   158  		{
   159  			id:            "mtagName1=mtagValue1",
   160  			matchFrom:     35000,
   161  			matchTo:       35001,
   162  			expireAtNanos: 100000,
   163  			forExistingIDResult: metadata.StagedMetadatas{
   164  				metadata.StagedMetadata{
   165  					CutoverNanos: 35000,
   166  					Tombstoned:   false,
   167  					Metadata: metadata.Metadata{
   168  						Pipelines: []metadata.PipelineMetadata{
   169  							{
   170  								AggregationID: aggregation.DefaultID,
   171  								StoragePolicies: policy.StoragePolicies{
   172  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
   173  								},
   174  							},
   175  							{
   176  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
   177  								StoragePolicies: policy.StoragePolicies{
   178  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
   179  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   180  								},
   181  							},
   182  						},
   183  					},
   184  				},
   185  			},
   186  		},
   187  		{
   188  			id:            "mtagName1=mtagValue2",
   189  			matchFrom:     25000,
   190  			matchTo:       25001,
   191  			expireAtNanos: 30000,
   192  			forExistingIDResult: metadata.StagedMetadatas{
   193  				metadata.StagedMetadata{
   194  					CutoverNanos: 24000,
   195  					Tombstoned:   false,
   196  					Metadata: metadata.Metadata{
   197  						Pipelines: []metadata.PipelineMetadata{
   198  							{
   199  								AggregationID: aggregation.DefaultID,
   200  								StoragePolicies: policy.StoragePolicies{
   201  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
   202  								},
   203  							},
   204  						},
   205  					},
   206  				},
   207  			},
   208  		},
   209  		{
   210  			id:                  "mtagName1=mtagValue3",
   211  			matchFrom:           25000,
   212  			matchTo:             25001,
   213  			expireAtNanos:       30000,
   214  			forExistingIDResult: metadata.DefaultStagedMetadatas,
   215  		},
   216  		{
   217  			id:            "mtagName1=mtagValue1",
   218  			matchFrom:     10000,
   219  			matchTo:       40000,
   220  			expireAtNanos: 100000,
   221  			forExistingIDResult: metadata.StagedMetadatas{
   222  				metadata.StagedMetadata{
   223  					CutoverNanos: 10000,
   224  					Tombstoned:   false,
   225  					Metadata: metadata.Metadata{
   226  						Pipelines: []metadata.PipelineMetadata{
   227  							{
   228  								AggregationID: aggregation.MustCompressTypes(aggregation.Count),
   229  								StoragePolicies: policy.StoragePolicies{
   230  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
   231  								},
   232  							},
   233  						},
   234  					},
   235  				},
   236  				metadata.StagedMetadata{
   237  					CutoverNanos: 15000,
   238  					Tombstoned:   false,
   239  					Metadata: metadata.Metadata{
   240  						Pipelines: []metadata.PipelineMetadata{
   241  							{
   242  								AggregationID: aggregation.MustCompressTypes(aggregation.Count),
   243  								StoragePolicies: policy.StoragePolicies{
   244  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
   245  								},
   246  							},
   247  							{
   248  								AggregationID: aggregation.MustCompressTypes(aggregation.Mean),
   249  								StoragePolicies: policy.StoragePolicies{
   250  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
   251  								},
   252  							},
   253  						},
   254  					},
   255  				},
   256  				metadata.StagedMetadata{
   257  					CutoverNanos: 20000,
   258  					Tombstoned:   false,
   259  					Metadata: metadata.Metadata{
   260  						Pipelines: []metadata.PipelineMetadata{
   261  							{
   262  								AggregationID: aggregation.DefaultID,
   263  								StoragePolicies: policy.StoragePolicies{
   264  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
   265  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   266  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
   267  								},
   268  							},
   269  							{
   270  								AggregationID: aggregation.MustCompressTypes(aggregation.Mean),
   271  								StoragePolicies: policy.StoragePolicies{
   272  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
   273  								},
   274  							},
   275  						},
   276  					},
   277  				},
   278  				metadata.StagedMetadata{
   279  					CutoverNanos: 22000,
   280  					Tombstoned:   false,
   281  					Metadata: metadata.Metadata{
   282  						Pipelines: []metadata.PipelineMetadata{
   283  							{
   284  								AggregationID: aggregation.DefaultID,
   285  								StoragePolicies: policy.StoragePolicies{
   286  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
   287  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   288  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
   289  								},
   290  							},
   291  							{
   292  								AggregationID: aggregation.DefaultID,
   293  								StoragePolicies: policy.StoragePolicies{
   294  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
   295  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   296  								},
   297  							},
   298  							{
   299  								AggregationID: aggregation.DefaultID,
   300  								StoragePolicies: policy.StoragePolicies{
   301  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
   302  									policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
   303  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   304  								},
   305  							},
   306  						},
   307  					},
   308  				},
   309  				metadata.StagedMetadata{
   310  					CutoverNanos: 22000,
   311  					Tombstoned:   false,
   312  					Metadata: metadata.Metadata{
   313  						Pipelines: []metadata.PipelineMetadata{
   314  							{
   315  								AggregationID: aggregation.DefaultID,
   316  								StoragePolicies: policy.StoragePolicies{
   317  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
   318  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   319  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
   320  								},
   321  							},
   322  							{
   323  								AggregationID: aggregation.DefaultID,
   324  								StoragePolicies: policy.StoragePolicies{
   325  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
   326  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   327  								},
   328  							},
   329  							{
   330  								AggregationID: aggregation.DefaultID,
   331  								StoragePolicies: policy.StoragePolicies{
   332  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
   333  									policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
   334  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   335  								},
   336  							},
   337  						},
   338  					},
   339  				},
   340  				metadata.StagedMetadata{
   341  					CutoverNanos: 30000,
   342  					Tombstoned:   false,
   343  					Metadata: metadata.Metadata{
   344  						Pipelines: []metadata.PipelineMetadata{
   345  							{
   346  								AggregationID: aggregation.DefaultID,
   347  								StoragePolicies: policy.StoragePolicies{
   348  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
   349  								},
   350  							},
   351  							{
   352  								AggregationID: aggregation.DefaultID,
   353  								StoragePolicies: policy.StoragePolicies{
   354  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
   355  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   356  								},
   357  							},
   358  							{
   359  								AggregationID: aggregation.DefaultID,
   360  								StoragePolicies: policy.StoragePolicies{
   361  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
   362  									policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
   363  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   364  								},
   365  							},
   366  						},
   367  					},
   368  				},
   369  				metadata.StagedMetadata{
   370  					CutoverNanos: 34000,
   371  					Tombstoned:   false,
   372  					Metadata: metadata.Metadata{
   373  						Pipelines: []metadata.PipelineMetadata{
   374  							{
   375  								AggregationID: aggregation.DefaultID,
   376  								StoragePolicies: policy.StoragePolicies{
   377  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
   378  								},
   379  							},
   380  							{
   381  								AggregationID: aggregation.DefaultID,
   382  								StoragePolicies: policy.StoragePolicies{
   383  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
   384  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   385  								},
   386  							},
   387  							{
   388  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
   389  								StoragePolicies: policy.StoragePolicies{
   390  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
   391  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   392  								},
   393  							},
   394  						},
   395  					},
   396  				},
   397  				metadata.StagedMetadata{
   398  					CutoverNanos: 35000,
   399  					Tombstoned:   false,
   400  					Metadata: metadata.Metadata{
   401  						Pipelines: []metadata.PipelineMetadata{
   402  							{
   403  								AggregationID: aggregation.DefaultID,
   404  								StoragePolicies: policy.StoragePolicies{
   405  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
   406  								},
   407  							},
   408  							{
   409  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
   410  								StoragePolicies: policy.StoragePolicies{
   411  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
   412  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   413  								},
   414  							},
   415  						},
   416  					},
   417  				},
   418  			},
   419  		},
   420  		{
   421  			id:            "mtagName1=mtagValue3",
   422  			matchFrom:     4000,
   423  			matchTo:       9000,
   424  			expireAtNanos: 10000,
   425  			forExistingIDResult: metadata.StagedMetadatas{
   426  				metadata.DefaultStagedMetadata,
   427  				metadata.StagedMetadata{
   428  					CutoverNanos: 5000,
   429  					Tombstoned:   false,
   430  					Metadata: metadata.Metadata{
   431  						Pipelines: []metadata.PipelineMetadata{
   432  							{
   433  								AggregationID: aggregation.DefaultID,
   434  								StoragePolicies: policy.StoragePolicies{
   435  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
   436  								},
   437  							},
   438  						},
   439  					},
   440  				},
   441  				metadata.StagedMetadata{
   442  					CutoverNanos: 8000,
   443  					Tombstoned:   false,
   444  					Metadata:     metadata.DefaultMetadata,
   445  				},
   446  			},
   447  		},
   448  		{
   449  			id:            "mtagName1=mtagValue2",
   450  			matchFrom:     10000,
   451  			matchTo:       40000,
   452  			expireAtNanos: 100000,
   453  			forExistingIDResult: metadata.StagedMetadatas{
   454  				metadata.DefaultStagedMetadata,
   455  				metadata.StagedMetadata{
   456  					CutoverNanos: 24000,
   457  					Tombstoned:   false,
   458  					Metadata: metadata.Metadata{
   459  						Pipelines: []metadata.PipelineMetadata{
   460  							{
   461  								AggregationID: aggregation.DefaultID,
   462  								StoragePolicies: policy.StoragePolicies{
   463  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
   464  								},
   465  							},
   466  						},
   467  					},
   468  				},
   469  				metadata.StagedMetadata{
   470  					CutoverNanos: 24000,
   471  					Tombstoned:   false,
   472  					Metadata: metadata.Metadata{
   473  						Pipelines: []metadata.PipelineMetadata{
   474  							{
   475  								AggregationID: aggregation.DefaultID,
   476  								StoragePolicies: policy.StoragePolicies{
   477  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
   478  								},
   479  							},
   480  						},
   481  					},
   482  				},
   483  				metadata.StagedMetadata{
   484  					CutoverNanos: 24000,
   485  					Tombstoned:   false,
   486  					Metadata: metadata.Metadata{
   487  						Pipelines: []metadata.PipelineMetadata{
   488  							{
   489  								AggregationID: aggregation.DefaultID,
   490  								StoragePolicies: policy.StoragePolicies{
   491  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
   492  								},
   493  							},
   494  						},
   495  					},
   496  				},
   497  				metadata.StagedMetadata{
   498  					CutoverNanos: 24000,
   499  					Tombstoned:   false,
   500  					Metadata: metadata.Metadata{
   501  						Pipelines: []metadata.PipelineMetadata{
   502  							{
   503  								AggregationID: aggregation.DefaultID,
   504  								StoragePolicies: policy.StoragePolicies{
   505  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
   506  								},
   507  							},
   508  						},
   509  					},
   510  				},
   511  			},
   512  		},
   513  		{
   514  			id:            "shouldDropTagName1=shouldDropTagValue1",
   515  			matchFrom:     25000,
   516  			matchTo:       25001,
   517  			expireAtNanos: 30000,
   518  			forExistingIDResult: metadata.StagedMetadatas{
   519  				metadata.StagedMetadata{
   520  					CutoverNanos: 20000,
   521  					Tombstoned:   false,
   522  					Metadata: metadata.Metadata{
   523  						Pipelines: []metadata.PipelineMetadata{
   524  							{
   525  								AggregationID: aggregation.DefaultID,
   526  								StoragePolicies: policy.StoragePolicies{
   527  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
   528  								},
   529  							},
   530  							metadata.DropPipelineMetadata,
   531  						},
   532  					},
   533  				},
   534  			},
   535  		},
   536  		{
   537  			id:            "shouldDrop2TagName1=shouldDrop2TagValue1",
   538  			matchFrom:     25000,
   539  			matchTo:       25001,
   540  			expireAtNanos: 30000,
   541  			forExistingIDResult: metadata.StagedMetadatas{
   542  				metadata.StagedMetadata{
   543  					CutoverNanos: 20000,
   544  					Tombstoned:   false,
   545  					Metadata: metadata.Metadata{
   546  						Pipelines: metadata.DropIfOnlyMatchPipelineMetadatas,
   547  					},
   548  				},
   549  			},
   550  		},
   551  		{
   552  			id:            "shouldNotDropTagName1=shouldNotDropTagValue1",
   553  			matchFrom:     25000,
   554  			matchTo:       25001,
   555  			expireAtNanos: 30000,
   556  			forExistingIDResult: metadata.StagedMetadatas{
   557  				metadata.StagedMetadata{
   558  					CutoverNanos: 20000,
   559  					Tombstoned:   false,
   560  					Metadata: metadata.Metadata{
   561  						Pipelines: []metadata.PipelineMetadata{
   562  							{
   563  								AggregationID: aggregation.DefaultID,
   564  								StoragePolicies: policy.StoragePolicies{
   565  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
   566  								},
   567  							},
   568  							metadata.DropIfOnlyMatchPipelineMetadata,
   569  						},
   570  					},
   571  				},
   572  			},
   573  		},
   574  	}
   575  
   576  	as := newActiveRuleSet(
   577  		0,
   578  		testMappingRules(t),
   579  		nil,
   580  		testTagsFilterOptions(),
   581  		mockNewID,
   582  		nil,
   583  	)
   584  	for i, input := range inputs {
   585  		input := input
   586  		t.Run(fmt.Sprintf("input %d", i), func(t *testing.T) {
   587  			res, err := as.ForwardMatch(input.ID(), input.matchFrom, input.matchTo, testMatchOptions())
   588  			require.NoError(t, err)
   589  			require.Equal(t, input.expireAtNanos, res.expireAtNanos)
   590  			require.True(t, cmp.Equal(input.forExistingIDResult, res.ForExistingIDAt(0), testStagedMetadatasCmptOpts...))
   591  			require.Equal(t, 0, res.NumNewRollupIDs())
   592  		})
   593  	}
   594  }
   595  
   596  func TestActiveRuleSetForwardMatchWithAnyKeepOriginal(t *testing.T) {
   597  	inputs := []testMatchInput{
   598  		{
   599  			id:           "rtagName1=rtagValue1",
   600  			matchFrom:    25000,
   601  			matchTo:      25001,
   602  			keepOriginal: true,
   603  		},
   604  	}
   605  
   606  	as := newActiveRuleSet(
   607  		0,
   608  		nil,
   609  		testKeepOriginalRollupRules(t),
   610  		testTagsFilterOptions(),
   611  		mockNewID,
   612  		nil,
   613  	)
   614  
   615  	for i, input := range inputs {
   616  		input := input
   617  		t.Run(fmt.Sprintf("input %d", i), func(t *testing.T) {
   618  			res, err := as.ForwardMatch(input.ID(), input.matchFrom, input.matchTo, testMatchOptions())
   619  			require.NoError(t, err)
   620  			require.Equal(t, res.keepOriginal, input.keepOriginal)
   621  			require.Equal(t, 3, res.NumNewRollupIDs())
   622  		})
   623  	}
   624  }
   625  
   626  func TestActiveRuleSetForwardMatchWithRollupRules(t *testing.T) {
   627  	inputs := []testMatchInput{
   628  		{
   629  			id:            "rtagName1=rtagValue1,rtagName2=rtagValue2,rtagName3=rtagValue3",
   630  			matchFrom:     25000,
   631  			matchTo:       25001,
   632  			expireAtNanos: 30000,
   633  			keepOriginal:  true,
   634  			forExistingIDResult: metadata.StagedMetadatas{
   635  				metadata.StagedMetadata{
   636  					CutoverNanos: 22000,
   637  					Tombstoned:   false,
   638  					Metadata: metadata.Metadata{
   639  						Pipelines: []metadata.PipelineMetadata{
   640  							metadata.DefaultPipelineMetadata,
   641  							{
   642  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
   643  								StoragePolicies: policy.StoragePolicies{
   644  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
   645  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   646  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
   647  								},
   648  								Pipeline: applied.NewPipeline([]applied.OpUnion{
   649  									{
   650  										Type: pipeline.RollupOpType,
   651  										Rollup: applied.RollupOp{
   652  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
   653  											AggregationID: aggregation.DefaultID,
   654  										},
   655  									},
   656  								}),
   657  							},
   658  							{
   659  								AggregationID: aggregation.MustCompressTypes(aggregation.Last),
   660  								StoragePolicies: policy.StoragePolicies{
   661  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
   662  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   663  								},
   664  								Pipeline: applied.NewPipeline([]applied.OpUnion{
   665  									{
   666  										Type: pipeline.TransformationOpType,
   667  										Transformation: pipeline.TransformationOp{
   668  											Type: transformation.PerSecond,
   669  										},
   670  									},
   671  									{
   672  										Type: pipeline.RollupOpType,
   673  										Rollup: applied.RollupOp{
   674  											ID:            b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
   675  											AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
   676  										},
   677  									},
   678  								}),
   679  							},
   680  						},
   681  					},
   682  				},
   683  			},
   684  			forNewRollupIDsResult: []IDWithMetadatas{
   685  				{
   686  					ID: b("rName3|rtagName1=rtagValue1"),
   687  					Metadatas: metadata.StagedMetadatas{
   688  						metadata.StagedMetadata{
   689  							CutoverNanos: 22000,
   690  							Tombstoned:   false,
   691  							Metadata: metadata.Metadata{
   692  								Pipelines: []metadata.PipelineMetadata{
   693  									{
   694  										AggregationID: aggregation.DefaultID,
   695  										StoragePolicies: policy.StoragePolicies{
   696  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
   697  										},
   698  									},
   699  								},
   700  							},
   701  						},
   702  					},
   703  				},
   704  				{
   705  					ID: b("rName3|rtagName1=rtagValue1,rtagName2=rtagValue2"),
   706  					Metadatas: metadata.StagedMetadatas{
   707  						metadata.StagedMetadata{
   708  							CutoverNanos: 22000,
   709  							Tombstoned:   false,
   710  							Metadata: metadata.Metadata{
   711  								Pipelines: []metadata.PipelineMetadata{
   712  									{
   713  										AggregationID: aggregation.DefaultID,
   714  										StoragePolicies: policy.StoragePolicies{
   715  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
   716  											policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
   717  											policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   718  										},
   719  									},
   720  								},
   721  							},
   722  						},
   723  					},
   724  				},
   725  			},
   726  		},
   727  		{
   728  			id:            "rtagName1=rtagValue2",
   729  			matchFrom:     25000,
   730  			matchTo:       25001,
   731  			expireAtNanos: 30000,
   732  			keepOriginal:  false,
   733  			forExistingIDResult: metadata.StagedMetadatas{
   734  				{
   735  					CutoverNanos: 24000,
   736  					Tombstoned:   false,
   737  					Metadata:     metadata.DefaultMetadata,
   738  				},
   739  			},
   740  			forNewRollupIDsResult: []IDWithMetadatas{
   741  				{
   742  					ID: b("rName4|rtagName1=rtagValue2"),
   743  					Metadatas: metadata.StagedMetadatas{
   744  						metadata.StagedMetadata{
   745  							CutoverNanos: 24000,
   746  							Tombstoned:   false,
   747  							Metadata: metadata.Metadata{
   748  								Pipelines: []metadata.PipelineMetadata{
   749  									{
   750  										AggregationID: aggregation.DefaultID,
   751  										StoragePolicies: policy.StoragePolicies{
   752  											policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   753  										},
   754  									},
   755  								},
   756  							},
   757  						},
   758  					},
   759  				},
   760  				{
   761  					ID: b("rName5|rtagName1=rtagValue2"),
   762  					Metadatas: metadata.StagedMetadatas{
   763  						metadata.StagedMetadata{
   764  							CutoverNanos: 24000,
   765  							Tombstoned:   false,
   766  							Metadata: metadata.Metadata{
   767  								Pipelines: []metadata.PipelineMetadata{
   768  									{
   769  										AggregationID: aggregation.DefaultID,
   770  										StoragePolicies: policy.StoragePolicies{
   771  											policy.NewStoragePolicy(time.Second, xtime.Second, time.Minute),
   772  										},
   773  									},
   774  								},
   775  							},
   776  						},
   777  					},
   778  				},
   779  			},
   780  		},
   781  		{
   782  			id:                  "rtagName5=rtagValue5",
   783  			matchFrom:           25000,
   784  			matchTo:             25001,
   785  			expireAtNanos:       30000,
   786  			keepOriginal:        false,
   787  			forExistingIDResult: metadata.DefaultStagedMetadatas,
   788  		},
   789  		{
   790  			id:            "rtagName1=rtagValue1,rtagName2=rtagValue2,rtagName3=rtagValue3",
   791  			matchFrom:     10000,
   792  			matchTo:       40000,
   793  			expireAtNanos: 90000,
   794  			keepOriginal:  false,
   795  			forExistingIDResult: metadata.StagedMetadatas{
   796  				{
   797  					CutoverNanos: 10000,
   798  					Tombstoned:   false,
   799  					Metadata:     metadata.DefaultMetadata,
   800  				},
   801  				{
   802  					CutoverNanos: 15000,
   803  					Tombstoned:   false,
   804  					Metadata:     metadata.DefaultMetadata,
   805  				},
   806  				{
   807  					CutoverNanos: 20000,
   808  					Tombstoned:   false,
   809  					Metadata: metadata.Metadata{
   810  						Pipelines: []metadata.PipelineMetadata{
   811  							metadata.DefaultPipelineMetadata,
   812  							{
   813  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
   814  								StoragePolicies: policy.StoragePolicies{
   815  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
   816  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   817  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
   818  								},
   819  								Pipeline: applied.NewPipeline([]applied.OpUnion{
   820  									{
   821  										Type: pipeline.RollupOpType,
   822  										Rollup: applied.RollupOp{
   823  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
   824  											AggregationID: aggregation.DefaultID,
   825  										},
   826  									},
   827  								}),
   828  							},
   829  						},
   830  					},
   831  				},
   832  				{
   833  					CutoverNanos: 22000,
   834  					Tombstoned:   false,
   835  					Metadata: metadata.Metadata{
   836  						Pipelines: []metadata.PipelineMetadata{
   837  							metadata.DefaultPipelineMetadata,
   838  							{
   839  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
   840  								StoragePolicies: policy.StoragePolicies{
   841  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
   842  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   843  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
   844  								},
   845  								Pipeline: applied.NewPipeline([]applied.OpUnion{
   846  									{
   847  										Type: pipeline.RollupOpType,
   848  										Rollup: applied.RollupOp{
   849  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
   850  											AggregationID: aggregation.DefaultID,
   851  										},
   852  									},
   853  								}),
   854  							},
   855  							{
   856  								AggregationID: aggregation.MustCompressTypes(aggregation.Last),
   857  								StoragePolicies: policy.StoragePolicies{
   858  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
   859  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   860  								},
   861  								Pipeline: applied.NewPipeline([]applied.OpUnion{
   862  									{
   863  										Type: pipeline.TransformationOpType,
   864  										Transformation: pipeline.TransformationOp{
   865  											Type: transformation.PerSecond,
   866  										},
   867  									},
   868  									{
   869  										Type: pipeline.RollupOpType,
   870  										Rollup: applied.RollupOp{
   871  											ID:            b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
   872  											AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
   873  										},
   874  									},
   875  								}),
   876  							},
   877  						},
   878  					},
   879  				},
   880  				{
   881  					CutoverNanos: 22000,
   882  					Tombstoned:   false,
   883  					Metadata: metadata.Metadata{
   884  						Pipelines: []metadata.PipelineMetadata{
   885  							metadata.DefaultPipelineMetadata,
   886  							{
   887  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
   888  								StoragePolicies: policy.StoragePolicies{
   889  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
   890  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
   891  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
   892  								},
   893  								Pipeline: applied.NewPipeline([]applied.OpUnion{
   894  									{
   895  										Type: pipeline.RollupOpType,
   896  										Rollup: applied.RollupOp{
   897  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
   898  											AggregationID: aggregation.DefaultID,
   899  										},
   900  									},
   901  								}),
   902  							},
   903  							{
   904  								AggregationID: aggregation.MustCompressTypes(aggregation.Last),
   905  								StoragePolicies: policy.StoragePolicies{
   906  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
   907  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   908  								},
   909  								Pipeline: applied.NewPipeline([]applied.OpUnion{
   910  									{
   911  										Type: pipeline.TransformationOpType,
   912  										Transformation: pipeline.TransformationOp{
   913  											Type: transformation.PerSecond,
   914  										},
   915  									},
   916  									{
   917  										Type: pipeline.RollupOpType,
   918  										Rollup: applied.RollupOp{
   919  											ID:            b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
   920  											AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
   921  										},
   922  									},
   923  								}),
   924  							},
   925  						},
   926  					},
   927  				},
   928  				{
   929  					CutoverNanos: 30000,
   930  					Tombstoned:   false,
   931  					Metadata: metadata.Metadata{
   932  						Pipelines: []metadata.PipelineMetadata{
   933  							metadata.DefaultPipelineMetadata,
   934  							{
   935  								AggregationID: aggregation.DefaultID,
   936  								StoragePolicies: policy.StoragePolicies{
   937  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
   938  								},
   939  								Pipeline: applied.NewPipeline([]applied.OpUnion{
   940  									{
   941  										Type: pipeline.TransformationOpType,
   942  										Transformation: pipeline.TransformationOp{
   943  											Type: transformation.PerSecond,
   944  										},
   945  									},
   946  									{
   947  										Type: pipeline.RollupOpType,
   948  										Rollup: applied.RollupOp{
   949  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
   950  											AggregationID: aggregation.DefaultID,
   951  										},
   952  									},
   953  								}),
   954  							},
   955  							{
   956  								AggregationID: aggregation.MustCompressTypes(aggregation.Last),
   957  								StoragePolicies: policy.StoragePolicies{
   958  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
   959  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
   960  								},
   961  								Pipeline: applied.NewPipeline([]applied.OpUnion{
   962  									{
   963  										Type: pipeline.TransformationOpType,
   964  										Transformation: pipeline.TransformationOp{
   965  											Type: transformation.PerSecond,
   966  										},
   967  									},
   968  									{
   969  										Type: pipeline.RollupOpType,
   970  										Rollup: applied.RollupOp{
   971  											ID:            b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
   972  											AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
   973  										},
   974  									},
   975  								}),
   976  							},
   977  						},
   978  					},
   979  				},
   980  				{
   981  					CutoverNanos: 34000,
   982  					Tombstoned:   false,
   983  					Metadata: metadata.Metadata{
   984  						Pipelines: []metadata.PipelineMetadata{
   985  							metadata.DefaultPipelineMetadata,
   986  							{
   987  								AggregationID: aggregation.DefaultID,
   988  								StoragePolicies: policy.StoragePolicies{
   989  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
   990  								},
   991  								Pipeline: applied.NewPipeline([]applied.OpUnion{
   992  									{
   993  										Type: pipeline.TransformationOpType,
   994  										Transformation: pipeline.TransformationOp{
   995  											Type: transformation.PerSecond,
   996  										},
   997  									},
   998  									{
   999  										Type: pipeline.RollupOpType,
  1000  										Rollup: applied.RollupOp{
  1001  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1002  											AggregationID: aggregation.DefaultID,
  1003  										},
  1004  									},
  1005  								}),
  1006  							},
  1007  							{
  1008  								AggregationID: aggregation.MustCompressTypes(aggregation.Last),
  1009  								StoragePolicies: policy.StoragePolicies{
  1010  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  1011  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  1012  								},
  1013  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  1014  									{
  1015  										Type: pipeline.TransformationOpType,
  1016  										Transformation: pipeline.TransformationOp{
  1017  											Type: transformation.PerSecond,
  1018  										},
  1019  									},
  1020  									{
  1021  										Type: pipeline.RollupOpType,
  1022  										Rollup: applied.RollupOp{
  1023  											ID:            b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1024  											AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  1025  										},
  1026  									},
  1027  								}),
  1028  							},
  1029  						},
  1030  					},
  1031  				},
  1032  				{
  1033  					CutoverNanos: 35000,
  1034  					Tombstoned:   false,
  1035  					Metadata: metadata.Metadata{
  1036  						Pipelines: []metadata.PipelineMetadata{
  1037  							metadata.DefaultPipelineMetadata,
  1038  							{
  1039  								AggregationID: aggregation.DefaultID,
  1040  								StoragePolicies: policy.StoragePolicies{
  1041  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  1042  								},
  1043  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  1044  									{
  1045  										Type: pipeline.TransformationOpType,
  1046  										Transformation: pipeline.TransformationOp{
  1047  											Type: transformation.PerSecond,
  1048  										},
  1049  									},
  1050  									{
  1051  										Type: pipeline.RollupOpType,
  1052  										Rollup: applied.RollupOp{
  1053  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1054  											AggregationID: aggregation.DefaultID,
  1055  										},
  1056  									},
  1057  								}),
  1058  							},
  1059  						},
  1060  					},
  1061  				},
  1062  				{
  1063  					CutoverNanos: 38000,
  1064  					Tombstoned:   false,
  1065  					Metadata: metadata.Metadata{
  1066  						Pipelines: []metadata.PipelineMetadata{
  1067  							metadata.DefaultPipelineMetadata,
  1068  							{
  1069  								AggregationID: aggregation.DefaultID,
  1070  								StoragePolicies: policy.StoragePolicies{
  1071  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  1072  								},
  1073  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  1074  									{
  1075  										Type: pipeline.TransformationOpType,
  1076  										Transformation: pipeline.TransformationOp{
  1077  											Type: transformation.PerSecond,
  1078  										},
  1079  									},
  1080  									{
  1081  										Type: pipeline.RollupOpType,
  1082  										Rollup: applied.RollupOp{
  1083  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1084  											AggregationID: aggregation.DefaultID,
  1085  										},
  1086  									},
  1087  								}),
  1088  							},
  1089  						},
  1090  					},
  1091  				},
  1092  			},
  1093  			forNewRollupIDsResult: []IDWithMetadatas{
  1094  				{
  1095  					ID: b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1096  					Metadatas: metadata.StagedMetadatas{
  1097  						{
  1098  							CutoverNanos: 10000,
  1099  							Tombstoned:   false,
  1100  							Metadata: metadata.Metadata{
  1101  								Pipelines: []metadata.PipelineMetadata{
  1102  									{
  1103  										AggregationID: aggregation.DefaultID,
  1104  										StoragePolicies: policy.StoragePolicies{
  1105  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  1106  										},
  1107  									},
  1108  								},
  1109  							},
  1110  						},
  1111  						{
  1112  							CutoverNanos: 15000,
  1113  							Tombstoned:   false,
  1114  							Metadata: metadata.Metadata{
  1115  								Pipelines: []metadata.PipelineMetadata{
  1116  									{
  1117  										AggregationID: aggregation.DefaultID,
  1118  										StoragePolicies: policy.StoragePolicies{
  1119  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  1120  										},
  1121  									},
  1122  								},
  1123  							},
  1124  						},
  1125  						{
  1126  							CutoverNanos: 20000,
  1127  							Tombstoned:   true,
  1128  						},
  1129  						{
  1130  							CutoverNanos: 22000,
  1131  							Tombstoned:   true,
  1132  						},
  1133  						{
  1134  							CutoverNanos: 24000,
  1135  							Tombstoned:   true,
  1136  						},
  1137  						{
  1138  							CutoverNanos: 30000,
  1139  							Tombstoned:   true,
  1140  						},
  1141  						{
  1142  							CutoverNanos: 34000,
  1143  							Tombstoned:   true,
  1144  						},
  1145  						{
  1146  							CutoverNanos: 35000,
  1147  							Tombstoned:   true,
  1148  						},
  1149  						{
  1150  							CutoverNanos: 38000,
  1151  							Tombstoned:   true,
  1152  						},
  1153  					},
  1154  				},
  1155  				{
  1156  					ID: b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1157  					Metadatas: metadata.StagedMetadatas{
  1158  						{
  1159  							CutoverNanos: 15000,
  1160  							Tombstoned:   false,
  1161  							Metadata: metadata.Metadata{
  1162  								Pipelines: []metadata.PipelineMetadata{
  1163  									{
  1164  										AggregationID: aggregation.DefaultID,
  1165  										StoragePolicies: policy.StoragePolicies{
  1166  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  1167  										},
  1168  									},
  1169  								},
  1170  							},
  1171  						},
  1172  						{
  1173  							CutoverNanos: 20000,
  1174  							Tombstoned:   false,
  1175  							Metadata: metadata.Metadata{
  1176  								Pipelines: []metadata.PipelineMetadata{
  1177  									{
  1178  										AggregationID: aggregation.DefaultID,
  1179  										StoragePolicies: policy.StoragePolicies{
  1180  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  1181  										},
  1182  									},
  1183  								},
  1184  							},
  1185  						},
  1186  						{
  1187  							CutoverNanos: 22000,
  1188  							Tombstoned:   true,
  1189  						},
  1190  						{
  1191  							CutoverNanos: 24000,
  1192  							Tombstoned:   true,
  1193  						},
  1194  						{
  1195  							CutoverNanos: 30000,
  1196  							Tombstoned:   true,
  1197  						},
  1198  						{
  1199  							CutoverNanos: 34000,
  1200  							Tombstoned:   true,
  1201  						},
  1202  						{
  1203  							CutoverNanos: 35000,
  1204  							Tombstoned:   false,
  1205  							Metadata: metadata.Metadata{
  1206  								Pipelines: []metadata.PipelineMetadata{
  1207  									{
  1208  										AggregationID: aggregation.DefaultID,
  1209  										StoragePolicies: policy.StoragePolicies{
  1210  											policy.NewStoragePolicy(45*time.Second, xtime.Second, 12*time.Hour),
  1211  										},
  1212  									},
  1213  								},
  1214  							},
  1215  						},
  1216  						{
  1217  							CutoverNanos: 38000,
  1218  							Tombstoned:   false,
  1219  							Metadata: metadata.Metadata{
  1220  								Pipelines: []metadata.PipelineMetadata{
  1221  									{
  1222  										AggregationID: aggregation.DefaultID,
  1223  										StoragePolicies: policy.StoragePolicies{
  1224  											policy.NewStoragePolicy(45*time.Second, xtime.Second, 12*time.Hour),
  1225  										},
  1226  									},
  1227  								},
  1228  							},
  1229  						},
  1230  					},
  1231  				},
  1232  				{
  1233  					ID: b("rName3|rtagName1=rtagValue1"),
  1234  					Metadatas: metadata.StagedMetadatas{
  1235  						{
  1236  							CutoverNanos: 22000,
  1237  							Tombstoned:   false,
  1238  							Metadata: metadata.Metadata{
  1239  								Pipelines: []metadata.PipelineMetadata{
  1240  									{
  1241  										AggregationID: aggregation.DefaultID,
  1242  										StoragePolicies: policy.StoragePolicies{
  1243  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  1244  										},
  1245  									},
  1246  								},
  1247  							},
  1248  						},
  1249  						{
  1250  							CutoverNanos: 22000,
  1251  							Tombstoned:   false,
  1252  							Metadata: metadata.Metadata{
  1253  								Pipelines: []metadata.PipelineMetadata{
  1254  									{
  1255  										AggregationID: aggregation.DefaultID,
  1256  										StoragePolicies: policy.StoragePolicies{
  1257  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  1258  										},
  1259  									},
  1260  								},
  1261  							},
  1262  						},
  1263  						{
  1264  							CutoverNanos: 30000,
  1265  							Tombstoned:   false,
  1266  							Metadata: metadata.Metadata{
  1267  								Pipelines: []metadata.PipelineMetadata{
  1268  									{
  1269  										AggregationID: aggregation.DefaultID,
  1270  										StoragePolicies: policy.StoragePolicies{
  1271  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  1272  										},
  1273  									},
  1274  								},
  1275  							},
  1276  						},
  1277  						{
  1278  							CutoverNanos: 34000,
  1279  							Tombstoned:   true,
  1280  						},
  1281  						{
  1282  							CutoverNanos: 35000,
  1283  							Tombstoned:   true,
  1284  						},
  1285  						{
  1286  							CutoverNanos: 38000,
  1287  							Tombstoned:   true,
  1288  						},
  1289  					},
  1290  				},
  1291  				{
  1292  					ID: b("rName3|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1293  					Metadatas: metadata.StagedMetadatas{
  1294  						{
  1295  							CutoverNanos: 22000,
  1296  							Tombstoned:   false,
  1297  							Metadata: metadata.Metadata{
  1298  								Pipelines: []metadata.PipelineMetadata{
  1299  									{
  1300  										AggregationID: aggregation.DefaultID,
  1301  										StoragePolicies: policy.StoragePolicies{
  1302  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  1303  											policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  1304  											policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1305  										},
  1306  									},
  1307  								},
  1308  							},
  1309  						},
  1310  						{
  1311  							CutoverNanos: 22000,
  1312  							Tombstoned:   false,
  1313  							Metadata: metadata.Metadata{
  1314  								Pipelines: []metadata.PipelineMetadata{
  1315  									{
  1316  										AggregationID: aggregation.DefaultID,
  1317  										StoragePolicies: policy.StoragePolicies{
  1318  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  1319  											policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  1320  											policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1321  										},
  1322  									},
  1323  								},
  1324  							},
  1325  						},
  1326  						{
  1327  							CutoverNanos: 30000,
  1328  							Tombstoned:   false,
  1329  							Metadata: metadata.Metadata{
  1330  								Pipelines: []metadata.PipelineMetadata{
  1331  									{
  1332  										AggregationID: aggregation.DefaultID,
  1333  										StoragePolicies: policy.StoragePolicies{
  1334  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  1335  											policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  1336  											policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1337  										},
  1338  									},
  1339  								},
  1340  							},
  1341  						},
  1342  						{
  1343  							CutoverNanos: 34000,
  1344  							Tombstoned:   false,
  1345  							Metadata: metadata.Metadata{
  1346  								Pipelines: []metadata.PipelineMetadata{
  1347  									{
  1348  										AggregationID: aggregation.DefaultID,
  1349  										StoragePolicies: policy.StoragePolicies{
  1350  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  1351  											policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  1352  										},
  1353  									},
  1354  								},
  1355  							},
  1356  						},
  1357  						{
  1358  							CutoverNanos: 35000,
  1359  							Tombstoned:   false,
  1360  							Metadata: metadata.Metadata{
  1361  								Pipelines: []metadata.PipelineMetadata{
  1362  									{
  1363  										AggregationID: aggregation.DefaultID,
  1364  										StoragePolicies: policy.StoragePolicies{
  1365  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  1366  											policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  1367  										},
  1368  									},
  1369  								},
  1370  							},
  1371  						},
  1372  						{
  1373  							CutoverNanos: 38000,
  1374  							Tombstoned:   true,
  1375  						},
  1376  					},
  1377  				},
  1378  			},
  1379  		},
  1380  		//nolint:dupl
  1381  		{
  1382  			id:            "rtagName1=rtagValue3,rtagName2=rtagValue2,rtagName3=rtagValue3",
  1383  			matchFrom:     100000,
  1384  			matchTo:       110000,
  1385  			expireAtNanos: 120000,
  1386  			keepOriginal:  false,
  1387  			forExistingIDResult: metadata.StagedMetadatas{
  1388  				{
  1389  					CutoverNanos: 100000,
  1390  					Tombstoned:   false,
  1391  					Metadata: metadata.Metadata{
  1392  						Pipelines: []metadata.PipelineMetadata{
  1393  							metadata.DefaultPipelineMetadata,
  1394  						},
  1395  					},
  1396  				},
  1397  			},
  1398  			forNewRollupIDsResult: []IDWithMetadatas{
  1399  				{
  1400  					ID: b("rName9A|rtagName2=rtagValue2,rtagName3=rtagValue3"), // rtagName1 is excluded away.
  1401  					Metadatas: metadata.StagedMetadatas{
  1402  						{
  1403  							CutoverNanos: 100000,
  1404  							Tombstoned:   false,
  1405  							Metadata: metadata.Metadata{
  1406  								Pipelines: []metadata.PipelineMetadata{
  1407  									{
  1408  										AggregationID: aggregation.MustCompressTypes(aggregation.Last),
  1409  										StoragePolicies: policy.StoragePolicies{
  1410  											policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  1411  											policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  1412  										},
  1413  										Pipeline: applied.Pipeline{Operations: []applied.OpUnion{}},
  1414  									},
  1415  								},
  1416  							},
  1417  						},
  1418  					},
  1419  				},
  1420  				{
  1421  					ID: b("rName9B|rtagName2=rtagValue2,rtagName3=rtagValue3"), // rtagName1 is excluded away.
  1422  					Metadatas: metadata.StagedMetadatas{
  1423  						{
  1424  							CutoverNanos: 100000,
  1425  							Tombstoned:   false,
  1426  							Metadata: metadata.Metadata{
  1427  								Pipelines: []metadata.PipelineMetadata{
  1428  									{
  1429  										AggregationID: aggregation.MustCompressTypes(aggregation.Last),
  1430  										StoragePolicies: policy.StoragePolicies{
  1431  											policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  1432  											policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  1433  										},
  1434  										Pipeline: applied.Pipeline{Operations: []applied.OpUnion{}},
  1435  									},
  1436  								},
  1437  							},
  1438  						},
  1439  					},
  1440  				},
  1441  				{
  1442  					ID: b("rName9C|rtagName2=rtagValue2"), // rtagName1 and rtagName3 are excluded away.
  1443  					Metadatas: metadata.StagedMetadatas{
  1444  						{
  1445  							CutoverNanos: 100000,
  1446  							Tombstoned:   false,
  1447  							Metadata: metadata.Metadata{
  1448  								Pipelines: []metadata.PipelineMetadata{
  1449  									{
  1450  										AggregationID: aggregation.MustCompressTypes(aggregation.Last),
  1451  										StoragePolicies: policy.StoragePolicies{
  1452  											policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  1453  											policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  1454  										},
  1455  										Pipeline: applied.Pipeline{Operations: []applied.OpUnion{}},
  1456  									},
  1457  								},
  1458  							},
  1459  						},
  1460  					},
  1461  				},
  1462  			},
  1463  		},
  1464  	}
  1465  
  1466  	as := newActiveRuleSet(
  1467  		0,
  1468  		nil,
  1469  		testRollupRules(t),
  1470  		testTagsFilterOptions(),
  1471  		mockNewID,
  1472  		nil,
  1473  	)
  1474  
  1475  	for i, input := range inputs {
  1476  		input := input
  1477  		t.Run(fmt.Sprintf("input %d", i), func(t *testing.T) {
  1478  			res, err := as.ForwardMatch(input.ID(), input.matchFrom, input.matchTo, testMatchOptions())
  1479  			require.NoError(t, err)
  1480  			require.Equal(t, input.expireAtNanos, res.expireAtNanos)
  1481  			require.True(t, cmp.Equal(input.forExistingIDResult, res.ForExistingIDAt(0), testStagedMetadatasCmptOpts...))
  1482  			require.Equal(t, len(input.forNewRollupIDsResult), res.NumNewRollupIDs())
  1483  			require.Equal(t, input.keepOriginal, res.KeepOriginal())
  1484  			for i := 0; i < len(input.forNewRollupIDsResult); i++ {
  1485  				rollup := res.ForNewRollupIDsAt(i, 0)
  1486  				require.True(t, cmp.Equal(input.forNewRollupIDsResult[i], rollup, testIDWithMetadatasCmpOpts...))
  1487  			}
  1488  		})
  1489  	}
  1490  }
  1491  
  1492  func TestActiveRuleSetForwardMatchWithMappingRulesAndRollupRules(t *testing.T) {
  1493  	inputs := []testMatchInput{
  1494  		{
  1495  			id:            "mtagName1=mtagValue1,rtagName1=rtagValue1,rtagName2=rtagValue2,rtagName3=rtagValue3",
  1496  			matchFrom:     25000,
  1497  			matchTo:       25001,
  1498  			expireAtNanos: 30000,
  1499  			keepOriginal:  true,
  1500  			forExistingIDResult: metadata.StagedMetadatas{
  1501  				metadata.StagedMetadata{
  1502  					CutoverNanos: 22000,
  1503  					Tombstoned:   false,
  1504  					Metadata: metadata.Metadata{
  1505  						Pipelines: []metadata.PipelineMetadata{
  1506  							{
  1507  								AggregationID: aggregation.DefaultID,
  1508  								StoragePolicies: policy.StoragePolicies{
  1509  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  1510  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1511  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  1512  								},
  1513  							},
  1514  							{
  1515  								AggregationID: aggregation.DefaultID,
  1516  								StoragePolicies: policy.StoragePolicies{
  1517  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  1518  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  1519  								},
  1520  							},
  1521  							{
  1522  								AggregationID: aggregation.DefaultID,
  1523  								StoragePolicies: policy.StoragePolicies{
  1524  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  1525  									policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  1526  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1527  								},
  1528  							},
  1529  							{
  1530  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  1531  								StoragePolicies: policy.StoragePolicies{
  1532  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  1533  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1534  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  1535  								},
  1536  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  1537  									{
  1538  										Type: pipeline.RollupOpType,
  1539  										Rollup: applied.RollupOp{
  1540  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1541  											AggregationID: aggregation.DefaultID,
  1542  										},
  1543  									},
  1544  								}),
  1545  							},
  1546  							{
  1547  								AggregationID: aggregation.MustCompressTypes(aggregation.Last),
  1548  								StoragePolicies: policy.StoragePolicies{
  1549  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  1550  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  1551  								},
  1552  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  1553  									{
  1554  										Type: pipeline.TransformationOpType,
  1555  										Transformation: pipeline.TransformationOp{
  1556  											Type: transformation.PerSecond,
  1557  										},
  1558  									},
  1559  									{
  1560  										Type: pipeline.RollupOpType,
  1561  										Rollup: applied.RollupOp{
  1562  											ID:            b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1563  											AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  1564  										},
  1565  									},
  1566  								}),
  1567  							},
  1568  						},
  1569  					},
  1570  				},
  1571  			},
  1572  			forNewRollupIDsResult: []IDWithMetadatas{
  1573  				{
  1574  					ID: b("rName3|rtagName1=rtagValue1"),
  1575  					Metadatas: metadata.StagedMetadatas{
  1576  						metadata.StagedMetadata{
  1577  							CutoverNanos: 22000,
  1578  							Tombstoned:   false,
  1579  							Metadata: metadata.Metadata{
  1580  								Pipelines: []metadata.PipelineMetadata{
  1581  									{
  1582  										AggregationID: aggregation.DefaultID,
  1583  										StoragePolicies: policy.StoragePolicies{
  1584  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  1585  										},
  1586  									},
  1587  								},
  1588  							},
  1589  						},
  1590  					},
  1591  				},
  1592  				{
  1593  					ID: b("rName3|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1594  					Metadatas: metadata.StagedMetadatas{
  1595  						metadata.StagedMetadata{
  1596  							CutoverNanos: 22000,
  1597  							Tombstoned:   false,
  1598  							Metadata: metadata.Metadata{
  1599  								Pipelines: []metadata.PipelineMetadata{
  1600  									{
  1601  										AggregationID: aggregation.DefaultID,
  1602  										StoragePolicies: policy.StoragePolicies{
  1603  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  1604  											policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  1605  											policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1606  										},
  1607  									},
  1608  								},
  1609  							},
  1610  						},
  1611  					},
  1612  				},
  1613  			},
  1614  		},
  1615  		{
  1616  			id:            "mtagName1=mtagValue1,rtagName1=rtagValue1,rtagName2=rtagValue2,rtagName3=rtagValue3",
  1617  			matchFrom:     35000,
  1618  			matchTo:       35001,
  1619  			expireAtNanos: 38000,
  1620  			forExistingIDResult: metadata.StagedMetadatas{
  1621  				metadata.StagedMetadata{
  1622  					CutoverNanos: 35000,
  1623  					Tombstoned:   false,
  1624  					Metadata: metadata.Metadata{
  1625  						Pipelines: []metadata.PipelineMetadata{
  1626  							{
  1627  								AggregationID: aggregation.DefaultID,
  1628  								StoragePolicies: policy.StoragePolicies{
  1629  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  1630  								},
  1631  							},
  1632  							{
  1633  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  1634  								StoragePolicies: policy.StoragePolicies{
  1635  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  1636  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  1637  								},
  1638  							},
  1639  							{
  1640  								AggregationID: aggregation.DefaultID,
  1641  								StoragePolicies: policy.StoragePolicies{
  1642  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  1643  								},
  1644  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  1645  									{
  1646  										Type: pipeline.TransformationOpType,
  1647  										Transformation: pipeline.TransformationOp{
  1648  											Type: transformation.PerSecond,
  1649  										},
  1650  									},
  1651  									{
  1652  										Type: pipeline.RollupOpType,
  1653  										Rollup: applied.RollupOp{
  1654  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1655  											AggregationID: aggregation.DefaultID,
  1656  										},
  1657  									},
  1658  								}),
  1659  							},
  1660  						},
  1661  					},
  1662  				},
  1663  			},
  1664  			forNewRollupIDsResult: []IDWithMetadatas{
  1665  				{
  1666  					ID: b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1667  					Metadatas: metadata.StagedMetadatas{
  1668  						{
  1669  							CutoverNanos: 35000,
  1670  							Tombstoned:   false,
  1671  							Metadata: metadata.Metadata{
  1672  								Pipelines: []metadata.PipelineMetadata{
  1673  									{
  1674  										AggregationID: aggregation.DefaultID,
  1675  										StoragePolicies: policy.StoragePolicies{
  1676  											policy.NewStoragePolicy(45*time.Second, xtime.Second, 12*time.Hour),
  1677  										},
  1678  									},
  1679  								},
  1680  							},
  1681  						},
  1682  					},
  1683  				},
  1684  				{
  1685  					ID: b("rName3|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1686  					Metadatas: metadata.StagedMetadatas{
  1687  						{
  1688  							CutoverNanos: 35000,
  1689  							Tombstoned:   false,
  1690  							Metadata: metadata.Metadata{
  1691  								Pipelines: []metadata.PipelineMetadata{
  1692  									{
  1693  										AggregationID: aggregation.DefaultID,
  1694  										StoragePolicies: policy.StoragePolicies{
  1695  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  1696  											policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  1697  										},
  1698  									},
  1699  								},
  1700  							},
  1701  						},
  1702  					},
  1703  				},
  1704  			},
  1705  		},
  1706  		{
  1707  			id:            "mtagName1=mtagValue2,rtagName1=rtagValue2",
  1708  			matchFrom:     25000,
  1709  			matchTo:       25001,
  1710  			expireAtNanos: 30000,
  1711  			forExistingIDResult: metadata.StagedMetadatas{
  1712  				metadata.StagedMetadata{
  1713  					CutoverNanos: 24000,
  1714  					Tombstoned:   false,
  1715  					Metadata: metadata.Metadata{
  1716  						Pipelines: []metadata.PipelineMetadata{
  1717  							{
  1718  								AggregationID: aggregation.DefaultID,
  1719  								StoragePolicies: policy.StoragePolicies{
  1720  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  1721  								},
  1722  							},
  1723  						},
  1724  					},
  1725  				},
  1726  			},
  1727  			forNewRollupIDsResult: []IDWithMetadatas{
  1728  				{
  1729  					ID: b("rName4|rtagName1=rtagValue2"),
  1730  					Metadatas: metadata.StagedMetadatas{
  1731  						metadata.StagedMetadata{
  1732  							CutoverNanos: 24000,
  1733  							Tombstoned:   false,
  1734  							Metadata: metadata.Metadata{
  1735  								Pipelines: []metadata.PipelineMetadata{
  1736  									{
  1737  										AggregationID: aggregation.DefaultID,
  1738  										StoragePolicies: policy.StoragePolicies{
  1739  											policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  1740  										},
  1741  									},
  1742  								},
  1743  							},
  1744  						},
  1745  					},
  1746  				},
  1747  				{
  1748  					ID: b("rName5|rtagName1=rtagValue2"),
  1749  					Metadatas: metadata.StagedMetadatas{
  1750  						metadata.StagedMetadata{
  1751  							CutoverNanos: 24000,
  1752  							Tombstoned:   false,
  1753  							Metadata: metadata.Metadata{
  1754  								Pipelines: []metadata.PipelineMetadata{
  1755  									{
  1756  										AggregationID: aggregation.DefaultID,
  1757  										StoragePolicies: policy.StoragePolicies{
  1758  											policy.NewStoragePolicy(time.Second, xtime.Second, time.Minute),
  1759  										},
  1760  									},
  1761  								},
  1762  							},
  1763  						},
  1764  					},
  1765  				},
  1766  			},
  1767  		},
  1768  		{
  1769  			id:                  "mtagName1=mtagValue3,rtagName5=rtagValue5",
  1770  			matchFrom:           25000,
  1771  			matchTo:             25001,
  1772  			expireAtNanos:       30000,
  1773  			forExistingIDResult: metadata.DefaultStagedMetadatas,
  1774  		},
  1775  		{
  1776  			id:            "mtagName1=mtagValue1,rtagName1=rtagValue1,rtagName2=rtagValue2,rtagName3=rtagValue3",
  1777  			matchFrom:     10000,
  1778  			matchTo:       40000,
  1779  			expireAtNanos: 90000,
  1780  			forExistingIDResult: metadata.StagedMetadatas{
  1781  				metadata.StagedMetadata{
  1782  					CutoverNanos: 10000,
  1783  					Tombstoned:   false,
  1784  					Metadata: metadata.Metadata{
  1785  						Pipelines: []metadata.PipelineMetadata{
  1786  							{
  1787  								AggregationID: aggregation.MustCompressTypes(aggregation.Count),
  1788  								StoragePolicies: policy.StoragePolicies{
  1789  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  1790  								},
  1791  							},
  1792  						},
  1793  					},
  1794  				},
  1795  				metadata.StagedMetadata{
  1796  					CutoverNanos: 15000,
  1797  					Tombstoned:   false,
  1798  					Metadata: metadata.Metadata{
  1799  						Pipelines: []metadata.PipelineMetadata{
  1800  							{
  1801  								AggregationID: aggregation.MustCompressTypes(aggregation.Count),
  1802  								StoragePolicies: policy.StoragePolicies{
  1803  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  1804  								},
  1805  							},
  1806  							{
  1807  								AggregationID: aggregation.MustCompressTypes(aggregation.Mean),
  1808  								StoragePolicies: policy.StoragePolicies{
  1809  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  1810  								},
  1811  							},
  1812  						},
  1813  					},
  1814  				},
  1815  				metadata.StagedMetadata{
  1816  					CutoverNanos: 20000,
  1817  					Tombstoned:   false,
  1818  					Metadata: metadata.Metadata{
  1819  						Pipelines: []metadata.PipelineMetadata{
  1820  							{
  1821  								AggregationID: aggregation.DefaultID,
  1822  								StoragePolicies: policy.StoragePolicies{
  1823  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  1824  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1825  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  1826  								},
  1827  							},
  1828  							{
  1829  								AggregationID: aggregation.MustCompressTypes(aggregation.Mean),
  1830  								StoragePolicies: policy.StoragePolicies{
  1831  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  1832  								},
  1833  							},
  1834  							{
  1835  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  1836  								StoragePolicies: policy.StoragePolicies{
  1837  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  1838  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1839  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  1840  								},
  1841  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  1842  									{
  1843  										Type: pipeline.RollupOpType,
  1844  										Rollup: applied.RollupOp{
  1845  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1846  											AggregationID: aggregation.DefaultID,
  1847  										},
  1848  									},
  1849  								}),
  1850  							},
  1851  						},
  1852  					},
  1853  				},
  1854  				metadata.StagedMetadata{
  1855  					CutoverNanos: 22000,
  1856  					Tombstoned:   false,
  1857  					Metadata: metadata.Metadata{
  1858  						Pipelines: []metadata.PipelineMetadata{
  1859  							{
  1860  								AggregationID: aggregation.DefaultID,
  1861  								StoragePolicies: policy.StoragePolicies{
  1862  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  1863  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1864  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  1865  								},
  1866  							},
  1867  							{
  1868  								AggregationID: aggregation.DefaultID,
  1869  								StoragePolicies: policy.StoragePolicies{
  1870  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  1871  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  1872  								},
  1873  							},
  1874  							{
  1875  								AggregationID: aggregation.DefaultID,
  1876  								StoragePolicies: policy.StoragePolicies{
  1877  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  1878  									policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  1879  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1880  								},
  1881  							},
  1882  							{
  1883  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  1884  								StoragePolicies: policy.StoragePolicies{
  1885  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  1886  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1887  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  1888  								},
  1889  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  1890  									{
  1891  										Type: pipeline.RollupOpType,
  1892  										Rollup: applied.RollupOp{
  1893  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1894  											AggregationID: aggregation.DefaultID,
  1895  										},
  1896  									},
  1897  								}),
  1898  							},
  1899  							{
  1900  								AggregationID: aggregation.MustCompressTypes(aggregation.Last),
  1901  								StoragePolicies: policy.StoragePolicies{
  1902  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  1903  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  1904  								},
  1905  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  1906  									{
  1907  										Type: pipeline.TransformationOpType,
  1908  										Transformation: pipeline.TransformationOp{
  1909  											Type: transformation.PerSecond,
  1910  										},
  1911  									},
  1912  									{
  1913  										Type: pipeline.RollupOpType,
  1914  										Rollup: applied.RollupOp{
  1915  											ID:            b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1916  											AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  1917  										},
  1918  									},
  1919  								}),
  1920  							},
  1921  						},
  1922  					},
  1923  				},
  1924  				metadata.StagedMetadata{
  1925  					CutoverNanos: 22000,
  1926  					Tombstoned:   false,
  1927  					Metadata: metadata.Metadata{
  1928  						Pipelines: []metadata.PipelineMetadata{
  1929  							{
  1930  								AggregationID: aggregation.DefaultID,
  1931  								StoragePolicies: policy.StoragePolicies{
  1932  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  1933  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1934  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  1935  								},
  1936  							},
  1937  							{
  1938  								AggregationID: aggregation.DefaultID,
  1939  								StoragePolicies: policy.StoragePolicies{
  1940  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  1941  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  1942  								},
  1943  							},
  1944  							{
  1945  								AggregationID: aggregation.DefaultID,
  1946  								StoragePolicies: policy.StoragePolicies{
  1947  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  1948  									policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  1949  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1950  								},
  1951  							},
  1952  							{
  1953  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  1954  								StoragePolicies: policy.StoragePolicies{
  1955  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  1956  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  1957  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  1958  								},
  1959  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  1960  									{
  1961  										Type: pipeline.RollupOpType,
  1962  										Rollup: applied.RollupOp{
  1963  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1964  											AggregationID: aggregation.DefaultID,
  1965  										},
  1966  									},
  1967  								}),
  1968  							},
  1969  							{
  1970  								AggregationID: aggregation.MustCompressTypes(aggregation.Last),
  1971  								StoragePolicies: policy.StoragePolicies{
  1972  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  1973  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  1974  								},
  1975  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  1976  									{
  1977  										Type: pipeline.TransformationOpType,
  1978  										Transformation: pipeline.TransformationOp{
  1979  											Type: transformation.PerSecond,
  1980  										},
  1981  									},
  1982  									{
  1983  										Type: pipeline.RollupOpType,
  1984  										Rollup: applied.RollupOp{
  1985  											ID:            b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  1986  											AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  1987  										},
  1988  									},
  1989  								}),
  1990  							},
  1991  						},
  1992  					},
  1993  				},
  1994  				metadata.StagedMetadata{
  1995  					CutoverNanos: 30000,
  1996  					Tombstoned:   false,
  1997  					Metadata: metadata.Metadata{
  1998  						Pipelines: []metadata.PipelineMetadata{
  1999  							{
  2000  								AggregationID: aggregation.DefaultID,
  2001  								StoragePolicies: policy.StoragePolicies{
  2002  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  2003  								},
  2004  							},
  2005  							{
  2006  								AggregationID: aggregation.DefaultID,
  2007  								StoragePolicies: policy.StoragePolicies{
  2008  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2009  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2010  								},
  2011  							},
  2012  							{
  2013  								AggregationID: aggregation.DefaultID,
  2014  								StoragePolicies: policy.StoragePolicies{
  2015  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  2016  									policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  2017  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  2018  								},
  2019  							},
  2020  							{
  2021  								AggregationID: aggregation.DefaultID,
  2022  								StoragePolicies: policy.StoragePolicies{
  2023  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  2024  								},
  2025  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  2026  									{
  2027  										Type: pipeline.TransformationOpType,
  2028  										Transformation: pipeline.TransformationOp{
  2029  											Type: transformation.PerSecond,
  2030  										},
  2031  									},
  2032  									{
  2033  										Type: pipeline.RollupOpType,
  2034  										Rollup: applied.RollupOp{
  2035  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  2036  											AggregationID: aggregation.DefaultID,
  2037  										},
  2038  									},
  2039  								}),
  2040  							},
  2041  							{
  2042  								AggregationID: aggregation.MustCompressTypes(aggregation.Last),
  2043  								StoragePolicies: policy.StoragePolicies{
  2044  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2045  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2046  								},
  2047  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  2048  									{
  2049  										Type: pipeline.TransformationOpType,
  2050  										Transformation: pipeline.TransformationOp{
  2051  											Type: transformation.PerSecond,
  2052  										},
  2053  									},
  2054  									{
  2055  										Type: pipeline.RollupOpType,
  2056  										Rollup: applied.RollupOp{
  2057  											ID:            b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  2058  											AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  2059  										},
  2060  									},
  2061  								}),
  2062  							},
  2063  						},
  2064  					},
  2065  				},
  2066  				metadata.StagedMetadata{
  2067  					CutoverNanos: 34000,
  2068  					Tombstoned:   false,
  2069  					Metadata: metadata.Metadata{
  2070  						Pipelines: []metadata.PipelineMetadata{
  2071  							{
  2072  								AggregationID: aggregation.DefaultID,
  2073  								StoragePolicies: policy.StoragePolicies{
  2074  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  2075  								},
  2076  							},
  2077  							{
  2078  								AggregationID: aggregation.DefaultID,
  2079  								StoragePolicies: policy.StoragePolicies{
  2080  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2081  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2082  								},
  2083  							},
  2084  							{
  2085  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  2086  								StoragePolicies: policy.StoragePolicies{
  2087  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2088  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2089  								},
  2090  							},
  2091  							{
  2092  								AggregationID: aggregation.DefaultID,
  2093  								StoragePolicies: policy.StoragePolicies{
  2094  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  2095  								},
  2096  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  2097  									{
  2098  										Type: pipeline.TransformationOpType,
  2099  										Transformation: pipeline.TransformationOp{
  2100  											Type: transformation.PerSecond,
  2101  										},
  2102  									},
  2103  									{
  2104  										Type: pipeline.RollupOpType,
  2105  										Rollup: applied.RollupOp{
  2106  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  2107  											AggregationID: aggregation.DefaultID,
  2108  										},
  2109  									},
  2110  								}),
  2111  							},
  2112  							{
  2113  								AggregationID: aggregation.MustCompressTypes(aggregation.Last),
  2114  								StoragePolicies: policy.StoragePolicies{
  2115  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2116  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2117  								},
  2118  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  2119  									{
  2120  										Type: pipeline.TransformationOpType,
  2121  										Transformation: pipeline.TransformationOp{
  2122  											Type: transformation.PerSecond,
  2123  										},
  2124  									},
  2125  									{
  2126  										Type: pipeline.RollupOpType,
  2127  										Rollup: applied.RollupOp{
  2128  											ID:            b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  2129  											AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  2130  										},
  2131  									},
  2132  								}),
  2133  							},
  2134  						},
  2135  					},
  2136  				},
  2137  				metadata.StagedMetadata{
  2138  					CutoverNanos: 35000,
  2139  					Tombstoned:   false,
  2140  					Metadata: metadata.Metadata{
  2141  						Pipelines: []metadata.PipelineMetadata{
  2142  							{
  2143  								AggregationID: aggregation.DefaultID,
  2144  								StoragePolicies: policy.StoragePolicies{
  2145  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  2146  								},
  2147  							},
  2148  							{
  2149  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  2150  								StoragePolicies: policy.StoragePolicies{
  2151  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2152  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2153  								},
  2154  							},
  2155  							{
  2156  								AggregationID: aggregation.DefaultID,
  2157  								StoragePolicies: policy.StoragePolicies{
  2158  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  2159  								},
  2160  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  2161  									{
  2162  										Type: pipeline.TransformationOpType,
  2163  										Transformation: pipeline.TransformationOp{
  2164  											Type: transformation.PerSecond,
  2165  										},
  2166  									},
  2167  									{
  2168  										Type: pipeline.RollupOpType,
  2169  										Rollup: applied.RollupOp{
  2170  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  2171  											AggregationID: aggregation.DefaultID,
  2172  										},
  2173  									},
  2174  								}),
  2175  							},
  2176  						},
  2177  					},
  2178  				},
  2179  				metadata.StagedMetadata{
  2180  					CutoverNanos: 38000,
  2181  					Tombstoned:   false,
  2182  					Metadata: metadata.Metadata{
  2183  						Pipelines: []metadata.PipelineMetadata{
  2184  							{
  2185  								AggregationID: aggregation.DefaultID,
  2186  								StoragePolicies: policy.StoragePolicies{
  2187  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  2188  								},
  2189  							},
  2190  							{
  2191  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  2192  								StoragePolicies: policy.StoragePolicies{
  2193  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2194  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2195  								},
  2196  							},
  2197  							{
  2198  								AggregationID: aggregation.DefaultID,
  2199  								StoragePolicies: policy.StoragePolicies{
  2200  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  2201  								},
  2202  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  2203  									{
  2204  										Type: pipeline.TransformationOpType,
  2205  										Transformation: pipeline.TransformationOp{
  2206  											Type: transformation.PerSecond,
  2207  										},
  2208  									},
  2209  									{
  2210  										Type: pipeline.RollupOpType,
  2211  										Rollup: applied.RollupOp{
  2212  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  2213  											AggregationID: aggregation.DefaultID,
  2214  										},
  2215  									},
  2216  								}),
  2217  							},
  2218  						},
  2219  					},
  2220  				},
  2221  			},
  2222  			forNewRollupIDsResult: []IDWithMetadatas{
  2223  				{
  2224  					ID: b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  2225  					Metadatas: metadata.StagedMetadatas{
  2226  						{
  2227  							CutoverNanos: 10000,
  2228  							Tombstoned:   false,
  2229  							Metadata: metadata.Metadata{
  2230  								Pipelines: []metadata.PipelineMetadata{
  2231  									{
  2232  										AggregationID: aggregation.DefaultID,
  2233  										StoragePolicies: policy.StoragePolicies{
  2234  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  2235  										},
  2236  									},
  2237  								},
  2238  							},
  2239  						},
  2240  						{
  2241  							CutoverNanos: 15000,
  2242  							Tombstoned:   false,
  2243  							Metadata: metadata.Metadata{
  2244  								Pipelines: []metadata.PipelineMetadata{
  2245  									{
  2246  										AggregationID: aggregation.DefaultID,
  2247  										StoragePolicies: policy.StoragePolicies{
  2248  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  2249  										},
  2250  									},
  2251  								},
  2252  							},
  2253  						},
  2254  						{
  2255  							CutoverNanos: 20000,
  2256  							Tombstoned:   true,
  2257  						},
  2258  						{
  2259  							CutoverNanos: 22000,
  2260  							Tombstoned:   true,
  2261  						},
  2262  						{
  2263  							CutoverNanos: 24000,
  2264  							Tombstoned:   true,
  2265  						},
  2266  						{
  2267  							CutoverNanos: 30000,
  2268  							Tombstoned:   true,
  2269  						},
  2270  						{
  2271  							CutoverNanos: 34000,
  2272  							Tombstoned:   true,
  2273  						},
  2274  						{
  2275  							CutoverNanos: 35000,
  2276  							Tombstoned:   true,
  2277  						},
  2278  						{
  2279  							CutoverNanos: 38000,
  2280  							Tombstoned:   true,
  2281  						},
  2282  					},
  2283  				},
  2284  				{
  2285  					ID: b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  2286  					Metadatas: metadata.StagedMetadatas{
  2287  						{
  2288  							CutoverNanos: 15000,
  2289  							Tombstoned:   false,
  2290  							Metadata: metadata.Metadata{
  2291  								Pipelines: []metadata.PipelineMetadata{
  2292  									{
  2293  										AggregationID: aggregation.DefaultID,
  2294  										StoragePolicies: policy.StoragePolicies{
  2295  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  2296  										},
  2297  									},
  2298  								},
  2299  							},
  2300  						},
  2301  						{
  2302  							CutoverNanos: 20000,
  2303  							Tombstoned:   false,
  2304  							Metadata: metadata.Metadata{
  2305  								Pipelines: []metadata.PipelineMetadata{
  2306  									{
  2307  										AggregationID: aggregation.DefaultID,
  2308  										StoragePolicies: policy.StoragePolicies{
  2309  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  2310  										},
  2311  									},
  2312  								},
  2313  							},
  2314  						},
  2315  						{
  2316  							CutoverNanos: 22000,
  2317  							Tombstoned:   true,
  2318  						},
  2319  						{
  2320  							CutoverNanos: 24000,
  2321  							Tombstoned:   true,
  2322  						},
  2323  						{
  2324  							CutoverNanos: 30000,
  2325  							Tombstoned:   true,
  2326  						},
  2327  						{
  2328  							CutoverNanos: 34000,
  2329  							Tombstoned:   true,
  2330  						},
  2331  						{
  2332  							CutoverNanos: 35000,
  2333  							Tombstoned:   false,
  2334  							Metadata: metadata.Metadata{
  2335  								Pipelines: []metadata.PipelineMetadata{
  2336  									{
  2337  										AggregationID: aggregation.DefaultID,
  2338  										StoragePolicies: policy.StoragePolicies{
  2339  											policy.NewStoragePolicy(45*time.Second, xtime.Second, 12*time.Hour),
  2340  										},
  2341  									},
  2342  								},
  2343  							},
  2344  						},
  2345  						{
  2346  							CutoverNanos: 38000,
  2347  							Tombstoned:   false,
  2348  							Metadata: metadata.Metadata{
  2349  								Pipelines: []metadata.PipelineMetadata{
  2350  									{
  2351  										AggregationID: aggregation.DefaultID,
  2352  										StoragePolicies: policy.StoragePolicies{
  2353  											policy.NewStoragePolicy(45*time.Second, xtime.Second, 12*time.Hour),
  2354  										},
  2355  									},
  2356  								},
  2357  							},
  2358  						},
  2359  					},
  2360  				},
  2361  				{
  2362  					ID: b("rName3|rtagName1=rtagValue1"),
  2363  					Metadatas: metadata.StagedMetadatas{
  2364  						{
  2365  							CutoverNanos: 22000,
  2366  							Tombstoned:   false,
  2367  							Metadata: metadata.Metadata{
  2368  								Pipelines: []metadata.PipelineMetadata{
  2369  									{
  2370  										AggregationID: aggregation.DefaultID,
  2371  										StoragePolicies: policy.StoragePolicies{
  2372  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  2373  										},
  2374  									},
  2375  								},
  2376  							},
  2377  						},
  2378  						{
  2379  							CutoverNanos: 22000,
  2380  							Tombstoned:   false,
  2381  							Metadata: metadata.Metadata{
  2382  								Pipelines: []metadata.PipelineMetadata{
  2383  									{
  2384  										AggregationID: aggregation.DefaultID,
  2385  										StoragePolicies: policy.StoragePolicies{
  2386  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  2387  										},
  2388  									},
  2389  								},
  2390  							},
  2391  						},
  2392  						{
  2393  							CutoverNanos: 30000,
  2394  							Tombstoned:   false,
  2395  							Metadata: metadata.Metadata{
  2396  								Pipelines: []metadata.PipelineMetadata{
  2397  									{
  2398  										AggregationID: aggregation.DefaultID,
  2399  										StoragePolicies: policy.StoragePolicies{
  2400  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  2401  										},
  2402  									},
  2403  								},
  2404  							},
  2405  						},
  2406  						{
  2407  							CutoverNanos: 34000,
  2408  							Tombstoned:   true,
  2409  						},
  2410  						{
  2411  							CutoverNanos: 35000,
  2412  							Tombstoned:   true,
  2413  						},
  2414  						{
  2415  							CutoverNanos: 38000,
  2416  							Tombstoned:   true,
  2417  						},
  2418  					},
  2419  				},
  2420  				{
  2421  					ID: b("rName3|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  2422  					Metadatas: metadata.StagedMetadatas{
  2423  						{
  2424  							CutoverNanos: 22000,
  2425  							Tombstoned:   false,
  2426  							Metadata: metadata.Metadata{
  2427  								Pipelines: []metadata.PipelineMetadata{
  2428  									{
  2429  										AggregationID: aggregation.DefaultID,
  2430  										StoragePolicies: policy.StoragePolicies{
  2431  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  2432  											policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  2433  											policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  2434  										},
  2435  									},
  2436  								},
  2437  							},
  2438  						},
  2439  						{
  2440  							CutoverNanos: 22000,
  2441  							Tombstoned:   false,
  2442  							Metadata: metadata.Metadata{
  2443  								Pipelines: []metadata.PipelineMetadata{
  2444  									{
  2445  										AggregationID: aggregation.DefaultID,
  2446  										StoragePolicies: policy.StoragePolicies{
  2447  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  2448  											policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  2449  											policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  2450  										},
  2451  									},
  2452  								},
  2453  							},
  2454  						},
  2455  						{
  2456  							CutoverNanos: 30000,
  2457  							Tombstoned:   false,
  2458  							Metadata: metadata.Metadata{
  2459  								Pipelines: []metadata.PipelineMetadata{
  2460  									{
  2461  										AggregationID: aggregation.DefaultID,
  2462  										StoragePolicies: policy.StoragePolicies{
  2463  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  2464  											policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  2465  											policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  2466  										},
  2467  									},
  2468  								},
  2469  							},
  2470  						},
  2471  						{
  2472  							CutoverNanos: 34000,
  2473  							Tombstoned:   false,
  2474  							Metadata: metadata.Metadata{
  2475  								Pipelines: []metadata.PipelineMetadata{
  2476  									{
  2477  										AggregationID: aggregation.DefaultID,
  2478  										StoragePolicies: policy.StoragePolicies{
  2479  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2480  											policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2481  										},
  2482  									},
  2483  								},
  2484  							},
  2485  						},
  2486  						{
  2487  							CutoverNanos: 35000,
  2488  							Tombstoned:   false,
  2489  							Metadata: metadata.Metadata{
  2490  								Pipelines: []metadata.PipelineMetadata{
  2491  									{
  2492  										AggregationID: aggregation.DefaultID,
  2493  										StoragePolicies: policy.StoragePolicies{
  2494  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2495  											policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2496  										},
  2497  									},
  2498  								},
  2499  							},
  2500  						},
  2501  						{
  2502  							CutoverNanos: 38000,
  2503  							Tombstoned:   true,
  2504  						},
  2505  					},
  2506  				},
  2507  			},
  2508  		},
  2509  		{
  2510  			id:            "mtagName1=mtagValue3",
  2511  			matchFrom:     4000,
  2512  			matchTo:       9000,
  2513  			expireAtNanos: 10000,
  2514  			forExistingIDResult: metadata.StagedMetadatas{
  2515  				metadata.DefaultStagedMetadata,
  2516  				metadata.StagedMetadata{
  2517  					CutoverNanos: 5000,
  2518  					Tombstoned:   false,
  2519  					Metadata: metadata.Metadata{
  2520  						Pipelines: []metadata.PipelineMetadata{
  2521  							{
  2522  								AggregationID: aggregation.DefaultID,
  2523  								StoragePolicies: policy.StoragePolicies{
  2524  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  2525  								},
  2526  							},
  2527  						},
  2528  					},
  2529  				},
  2530  				metadata.StagedMetadata{
  2531  					CutoverNanos: 8000,
  2532  					Tombstoned:   false,
  2533  					Metadata:     metadata.DefaultMetadata,
  2534  				},
  2535  			},
  2536  		},
  2537  		{
  2538  			id:            "rtagName1=rtagValue1,rtagName2=rtagValue2,rtagName3=rtagValue3,shouldDropTagName1=shouldDropTagValue1",
  2539  			matchFrom:     35000,
  2540  			matchTo:       35001,
  2541  			expireAtNanos: 38000,
  2542  			forExistingIDResult: metadata.StagedMetadatas{
  2543  				metadata.StagedMetadata{
  2544  					CutoverNanos: 35000,
  2545  					Tombstoned:   false,
  2546  					Metadata: metadata.Metadata{
  2547  						Pipelines: []metadata.PipelineMetadata{
  2548  							{
  2549  								AggregationID: aggregation.DefaultID,
  2550  								StoragePolicies: policy.StoragePolicies{
  2551  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  2552  								},
  2553  							},
  2554  							metadata.DropPipelineMetadata,
  2555  							{
  2556  								AggregationID: aggregation.DefaultID,
  2557  								StoragePolicies: policy.StoragePolicies{
  2558  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  2559  								},
  2560  								Pipeline: applied.NewPipeline([]applied.OpUnion{
  2561  									{
  2562  										Type: pipeline.TransformationOpType,
  2563  										Transformation: pipeline.TransformationOp{
  2564  											Type: transformation.PerSecond,
  2565  										},
  2566  									},
  2567  									{
  2568  										Type: pipeline.RollupOpType,
  2569  										Rollup: applied.RollupOp{
  2570  											ID:            b("rName1|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  2571  											AggregationID: aggregation.DefaultID,
  2572  										},
  2573  									},
  2574  								}),
  2575  							},
  2576  						},
  2577  					},
  2578  				},
  2579  			},
  2580  			forNewRollupIDsResult: []IDWithMetadatas{
  2581  				{
  2582  					ID: b("rName2|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  2583  					Metadatas: metadata.StagedMetadatas{
  2584  						{
  2585  							CutoverNanos: 35000,
  2586  							Tombstoned:   false,
  2587  							Metadata: metadata.Metadata{
  2588  								Pipelines: []metadata.PipelineMetadata{
  2589  									{
  2590  										AggregationID: aggregation.DefaultID,
  2591  										StoragePolicies: policy.StoragePolicies{
  2592  											policy.NewStoragePolicy(45*time.Second, xtime.Second, 12*time.Hour),
  2593  										},
  2594  									},
  2595  								},
  2596  							},
  2597  						},
  2598  					},
  2599  				},
  2600  				{
  2601  					ID: b("rName3|rtagName1=rtagValue1,rtagName2=rtagValue2"),
  2602  					Metadatas: metadata.StagedMetadatas{
  2603  						{
  2604  							CutoverNanos: 35000,
  2605  							Tombstoned:   false,
  2606  							Metadata: metadata.Metadata{
  2607  								Pipelines: []metadata.PipelineMetadata{
  2608  									{
  2609  										AggregationID: aggregation.DefaultID,
  2610  										StoragePolicies: policy.StoragePolicies{
  2611  											policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2612  											policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2613  										},
  2614  									},
  2615  								},
  2616  							},
  2617  						},
  2618  					},
  2619  				},
  2620  			},
  2621  		},
  2622  		//nolint:dupl
  2623  		{
  2624  			id:            "rtagName1=rtagValue3,rtagName2=rtagValue2,rtagName3=rtagValue3",
  2625  			matchFrom:     100000,
  2626  			matchTo:       110000,
  2627  			expireAtNanos: 120000,
  2628  			keepOriginal:  false,
  2629  			forExistingIDResult: metadata.StagedMetadatas{
  2630  				{
  2631  					CutoverNanos: 100000,
  2632  					Tombstoned:   false,
  2633  					Metadata: metadata.Metadata{
  2634  						Pipelines: []metadata.PipelineMetadata{
  2635  							metadata.DefaultPipelineMetadata,
  2636  						},
  2637  					},
  2638  				},
  2639  			},
  2640  			forNewRollupIDsResult: []IDWithMetadatas{
  2641  				{
  2642  					ID: b("rName9A|rtagName2=rtagValue2,rtagName3=rtagValue3"), // rtagName1 is excluded away.
  2643  					Metadatas: metadata.StagedMetadatas{
  2644  						{
  2645  							CutoverNanos: 100000,
  2646  							Tombstoned:   false,
  2647  							Metadata: metadata.Metadata{
  2648  								Pipelines: []metadata.PipelineMetadata{
  2649  									{
  2650  										AggregationID: aggregation.MustCompressTypes(aggregation.Last),
  2651  										StoragePolicies: policy.StoragePolicies{
  2652  											policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  2653  											policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  2654  										},
  2655  										Pipeline: applied.Pipeline{Operations: []applied.OpUnion{}},
  2656  									},
  2657  								},
  2658  							},
  2659  						},
  2660  					},
  2661  				},
  2662  				{
  2663  					ID: b("rName9B|rtagName2=rtagValue2,rtagName3=rtagValue3"), // rtagName1 is excluded away.
  2664  					Metadatas: metadata.StagedMetadatas{
  2665  						{
  2666  							CutoverNanos: 100000,
  2667  							Tombstoned:   false,
  2668  							Metadata: metadata.Metadata{
  2669  								Pipelines: []metadata.PipelineMetadata{
  2670  									{
  2671  										AggregationID: aggregation.MustCompressTypes(aggregation.Last),
  2672  										StoragePolicies: policy.StoragePolicies{
  2673  											policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  2674  											policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  2675  										},
  2676  										Pipeline: applied.Pipeline{Operations: []applied.OpUnion{}},
  2677  									},
  2678  								},
  2679  							},
  2680  						},
  2681  					},
  2682  				},
  2683  				{
  2684  					ID: b("rName9C|rtagName2=rtagValue2"), // rtagName1 and rtagName3 are excluded away.
  2685  					Metadatas: metadata.StagedMetadatas{
  2686  						{
  2687  							CutoverNanos: 100000,
  2688  							Tombstoned:   false,
  2689  							Metadata: metadata.Metadata{
  2690  								Pipelines: []metadata.PipelineMetadata{
  2691  									{
  2692  										AggregationID: aggregation.MustCompressTypes(aggregation.Last),
  2693  										StoragePolicies: policy.StoragePolicies{
  2694  											policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  2695  											policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  2696  										},
  2697  										Pipeline: applied.Pipeline{Operations: []applied.OpUnion{}},
  2698  									},
  2699  								},
  2700  							},
  2701  						},
  2702  					},
  2703  				},
  2704  			},
  2705  		},
  2706  	}
  2707  
  2708  	as := newActiveRuleSet(
  2709  		0,
  2710  		testMappingRules(t),
  2711  		testRollupRules(t),
  2712  		testTagsFilterOptions(),
  2713  		mockNewID,
  2714  		nil,
  2715  	)
  2716  	for i, input := range inputs {
  2717  		input := input
  2718  		t.Run(fmt.Sprintf("input %d", i), func(t *testing.T) {
  2719  			res, err := as.ForwardMatch(input.ID(), input.matchFrom, input.matchTo, testMatchOptions())
  2720  			require.NoError(t, err)
  2721  			require.Equal(t, input.expireAtNanos, res.expireAtNanos)
  2722  			require.True(t, cmp.Equal(input.forExistingIDResult, res.ForExistingIDAt(0), testStagedMetadatasCmptOpts...))
  2723  			require.Equal(t, len(input.forNewRollupIDsResult), res.NumNewRollupIDs())
  2724  			require.Equal(t, input.keepOriginal, res.KeepOriginal())
  2725  			for i := 0; i < len(input.forNewRollupIDsResult); i++ {
  2726  				rollup := res.ForNewRollupIDsAt(i, 0)
  2727  				require.True(t, cmp.Equal(input.forNewRollupIDsResult[i], rollup, testIDWithMetadatasCmpOpts...))
  2728  			}
  2729  		})
  2730  	}
  2731  }
  2732  
  2733  func TestActiveRuleSetReverseMatchWithMappingRulesForNonRollupID(t *testing.T) {
  2734  	inputs := []testMatchInput{
  2735  		{
  2736  			id:              "mtagName1=mtagValue1",
  2737  			matchFrom:       25000,
  2738  			matchTo:         25001,
  2739  			metricType:      metric.CounterType,
  2740  			aggregationType: aggregation.Sum,
  2741  			expireAtNanos:   30000,
  2742  			forExistingIDResult: metadata.StagedMetadatas{
  2743  				metadata.StagedMetadata{
  2744  					CutoverNanos: 22000,
  2745  					Tombstoned:   false,
  2746  					Metadata: metadata.Metadata{
  2747  						Pipelines: []metadata.PipelineMetadata{
  2748  							{
  2749  								AggregationID: aggregation.DefaultID,
  2750  								StoragePolicies: policy.StoragePolicies{
  2751  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  2752  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  2753  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  2754  								},
  2755  							},
  2756  							{
  2757  								AggregationID: aggregation.DefaultID,
  2758  								StoragePolicies: policy.StoragePolicies{
  2759  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2760  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2761  								},
  2762  							},
  2763  							{
  2764  								AggregationID: aggregation.DefaultID,
  2765  								StoragePolicies: policy.StoragePolicies{
  2766  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  2767  									policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  2768  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  2769  								},
  2770  							},
  2771  						},
  2772  					},
  2773  				},
  2774  			},
  2775  		},
  2776  		{
  2777  			id:              "mtagName1=mtagValue1",
  2778  			matchFrom:       35000,
  2779  			matchTo:         35001,
  2780  			metricType:      metric.CounterType,
  2781  			aggregationType: aggregation.Sum,
  2782  			expireAtNanos:   100000,
  2783  			forExistingIDResult: metadata.StagedMetadatas{
  2784  				metadata.StagedMetadata{
  2785  					CutoverNanos: 35000,
  2786  					Tombstoned:   false,
  2787  					Metadata: metadata.Metadata{
  2788  						Pipelines: []metadata.PipelineMetadata{
  2789  							{
  2790  								AggregationID: aggregation.DefaultID,
  2791  								StoragePolicies: policy.StoragePolicies{
  2792  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  2793  								},
  2794  							},
  2795  							{
  2796  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  2797  								StoragePolicies: policy.StoragePolicies{
  2798  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2799  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2800  								},
  2801  							},
  2802  						},
  2803  					},
  2804  				},
  2805  			},
  2806  		},
  2807  		{
  2808  			id:              "mtagName1=mtagValue2",
  2809  			matchFrom:       25000,
  2810  			matchTo:         25001,
  2811  			metricType:      metric.CounterType,
  2812  			aggregationType: aggregation.Sum,
  2813  			expireAtNanos:   30000,
  2814  			forExistingIDResult: metadata.StagedMetadatas{
  2815  				metadata.StagedMetadata{
  2816  					CutoverNanos: 24000,
  2817  					Tombstoned:   false,
  2818  					Metadata: metadata.Metadata{
  2819  						Pipelines: []metadata.PipelineMetadata{
  2820  							{
  2821  								AggregationID: aggregation.DefaultID,
  2822  								StoragePolicies: policy.StoragePolicies{
  2823  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  2824  								},
  2825  							},
  2826  						},
  2827  					},
  2828  				},
  2829  			},
  2830  		},
  2831  		{
  2832  			id:                  "mtagName1=mtagValue3",
  2833  			matchFrom:           25000,
  2834  			matchTo:             25001,
  2835  			metricType:          metric.CounterType,
  2836  			aggregationType:     aggregation.Sum,
  2837  			expireAtNanos:       30000,
  2838  			forExistingIDResult: metadata.DefaultStagedMetadatas,
  2839  		},
  2840  		{
  2841  			id:                  "mtagName1=mtagValue3",
  2842  			matchFrom:           25000,
  2843  			matchTo:             25001,
  2844  			metricType:          metric.CounterType,
  2845  			aggregationType:     aggregation.Min,
  2846  			expireAtNanos:       30000,
  2847  			forExistingIDResult: nil,
  2848  		},
  2849  		{
  2850  			id:                  "mtagName1=mtagValue1",
  2851  			matchFrom:           10000,
  2852  			matchTo:             12000,
  2853  			metricType:          metric.CounterType,
  2854  			aggregationType:     aggregation.Sum,
  2855  			expireAtNanos:       15000,
  2856  			forExistingIDResult: nil,
  2857  		},
  2858  		{
  2859  			id:              "mtagName1=mtagValue1",
  2860  			matchFrom:       10000,
  2861  			matchTo:         21000,
  2862  			metricType:      metric.CounterType,
  2863  			aggregationType: aggregation.Sum,
  2864  			expireAtNanos:   22000,
  2865  			forExistingIDResult: metadata.StagedMetadatas{
  2866  				metadata.StagedMetadata{
  2867  					CutoverNanos: 20000,
  2868  					Tombstoned:   false,
  2869  					Metadata: metadata.Metadata{
  2870  						Pipelines: []metadata.PipelineMetadata{
  2871  							{
  2872  								AggregationID: aggregation.DefaultID,
  2873  								StoragePolicies: policy.StoragePolicies{
  2874  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  2875  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  2876  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  2877  								},
  2878  							},
  2879  						},
  2880  					},
  2881  				},
  2882  			},
  2883  		},
  2884  		{
  2885  			id:              "mtagName1=mtagValue1",
  2886  			matchFrom:       10000,
  2887  			matchTo:         40000,
  2888  			metricType:      metric.TimerType,
  2889  			aggregationType: aggregation.Count,
  2890  			expireAtNanos:   100000,
  2891  			forExistingIDResult: metadata.StagedMetadatas{
  2892  				metadata.StagedMetadata{
  2893  					CutoverNanos: 10000,
  2894  					Tombstoned:   false,
  2895  					Metadata: metadata.Metadata{
  2896  						Pipelines: []metadata.PipelineMetadata{
  2897  							{
  2898  								AggregationID: aggregation.MustCompressTypes(aggregation.Count),
  2899  								StoragePolicies: policy.StoragePolicies{
  2900  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  2901  								},
  2902  							},
  2903  						},
  2904  					},
  2905  				},
  2906  				metadata.StagedMetadata{
  2907  					CutoverNanos: 15000,
  2908  					Tombstoned:   false,
  2909  					Metadata: metadata.Metadata{
  2910  						Pipelines: []metadata.PipelineMetadata{
  2911  							{
  2912  								AggregationID: aggregation.MustCompressTypes(aggregation.Count),
  2913  								StoragePolicies: policy.StoragePolicies{
  2914  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  2915  								},
  2916  							},
  2917  						},
  2918  					},
  2919  				},
  2920  				metadata.StagedMetadata{
  2921  					CutoverNanos: 20000,
  2922  					Tombstoned:   false,
  2923  					Metadata: metadata.Metadata{
  2924  						Pipelines: []metadata.PipelineMetadata{
  2925  							{
  2926  								AggregationID: aggregation.DefaultID,
  2927  								StoragePolicies: policy.StoragePolicies{
  2928  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  2929  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  2930  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  2931  								},
  2932  							},
  2933  						},
  2934  					},
  2935  				},
  2936  				metadata.StagedMetadata{
  2937  					CutoverNanos: 22000,
  2938  					Tombstoned:   false,
  2939  					Metadata: metadata.Metadata{
  2940  						Pipelines: []metadata.PipelineMetadata{
  2941  							{
  2942  								AggregationID: aggregation.DefaultID,
  2943  								StoragePolicies: policy.StoragePolicies{
  2944  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  2945  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  2946  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  2947  								},
  2948  							},
  2949  							{
  2950  								AggregationID: aggregation.DefaultID,
  2951  								StoragePolicies: policy.StoragePolicies{
  2952  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2953  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2954  								},
  2955  							},
  2956  							{
  2957  								AggregationID: aggregation.DefaultID,
  2958  								StoragePolicies: policy.StoragePolicies{
  2959  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  2960  									policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  2961  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  2962  								},
  2963  							},
  2964  						},
  2965  					},
  2966  				},
  2967  				metadata.StagedMetadata{
  2968  					CutoverNanos: 22000,
  2969  					Tombstoned:   false,
  2970  					Metadata: metadata.Metadata{
  2971  						Pipelines: []metadata.PipelineMetadata{
  2972  							{
  2973  								AggregationID: aggregation.DefaultID,
  2974  								StoragePolicies: policy.StoragePolicies{
  2975  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  2976  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  2977  									policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  2978  								},
  2979  							},
  2980  							{
  2981  								AggregationID: aggregation.DefaultID,
  2982  								StoragePolicies: policy.StoragePolicies{
  2983  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  2984  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  2985  								},
  2986  							},
  2987  							{
  2988  								AggregationID: aggregation.DefaultID,
  2989  								StoragePolicies: policy.StoragePolicies{
  2990  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  2991  									policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  2992  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  2993  								},
  2994  							},
  2995  						},
  2996  					},
  2997  				},
  2998  				metadata.StagedMetadata{
  2999  					CutoverNanos: 30000,
  3000  					Tombstoned:   false,
  3001  					Metadata: metadata.Metadata{
  3002  						Pipelines: []metadata.PipelineMetadata{
  3003  							{
  3004  								AggregationID: aggregation.DefaultID,
  3005  								StoragePolicies: policy.StoragePolicies{
  3006  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  3007  								},
  3008  							},
  3009  							{
  3010  								AggregationID: aggregation.DefaultID,
  3011  								StoragePolicies: policy.StoragePolicies{
  3012  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  3013  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  3014  								},
  3015  							},
  3016  							{
  3017  								AggregationID: aggregation.DefaultID,
  3018  								StoragePolicies: policy.StoragePolicies{
  3019  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  3020  									policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  3021  									policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  3022  								},
  3023  							},
  3024  						},
  3025  					},
  3026  				},
  3027  				metadata.StagedMetadata{
  3028  					CutoverNanos: 34000,
  3029  					Tombstoned:   false,
  3030  					Metadata: metadata.Metadata{
  3031  						Pipelines: []metadata.PipelineMetadata{
  3032  							{
  3033  								AggregationID: aggregation.DefaultID,
  3034  								StoragePolicies: policy.StoragePolicies{
  3035  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  3036  								},
  3037  							},
  3038  							{
  3039  								AggregationID: aggregation.DefaultID,
  3040  								StoragePolicies: policy.StoragePolicies{
  3041  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  3042  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  3043  								},
  3044  							},
  3045  						},
  3046  					},
  3047  				},
  3048  				metadata.StagedMetadata{
  3049  					CutoverNanos: 35000,
  3050  					Tombstoned:   false,
  3051  					Metadata: metadata.Metadata{
  3052  						Pipelines: []metadata.PipelineMetadata{
  3053  							{
  3054  								AggregationID: aggregation.DefaultID,
  3055  								StoragePolicies: policy.StoragePolicies{
  3056  									policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  3057  								},
  3058  							},
  3059  						},
  3060  					},
  3061  				},
  3062  			},
  3063  		},
  3064  		{
  3065  			id:              "mtagName1=mtagValue2",
  3066  			matchFrom:       10000,
  3067  			matchTo:         40000,
  3068  			metricType:      metric.CounterType,
  3069  			aggregationType: aggregation.Sum,
  3070  			expireAtNanos:   100000,
  3071  			forExistingIDResult: metadata.StagedMetadatas{
  3072  				metadata.DefaultStagedMetadata,
  3073  				metadata.StagedMetadata{
  3074  					CutoverNanos: 24000,
  3075  					Tombstoned:   false,
  3076  					Metadata: metadata.Metadata{
  3077  						Pipelines: []metadata.PipelineMetadata{
  3078  							{
  3079  								AggregationID: aggregation.DefaultID,
  3080  								StoragePolicies: policy.StoragePolicies{
  3081  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3082  								},
  3083  							},
  3084  						},
  3085  					},
  3086  				},
  3087  				metadata.StagedMetadata{
  3088  					CutoverNanos: 24000,
  3089  					Tombstoned:   false,
  3090  					Metadata: metadata.Metadata{
  3091  						Pipelines: []metadata.PipelineMetadata{
  3092  							{
  3093  								AggregationID: aggregation.DefaultID,
  3094  								StoragePolicies: policy.StoragePolicies{
  3095  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3096  								},
  3097  							},
  3098  						},
  3099  					},
  3100  				},
  3101  				metadata.StagedMetadata{
  3102  					CutoverNanos: 24000,
  3103  					Tombstoned:   false,
  3104  					Metadata: metadata.Metadata{
  3105  						Pipelines: []metadata.PipelineMetadata{
  3106  							{
  3107  								AggregationID: aggregation.DefaultID,
  3108  								StoragePolicies: policy.StoragePolicies{
  3109  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3110  								},
  3111  							},
  3112  						},
  3113  					},
  3114  				},
  3115  				metadata.StagedMetadata{
  3116  					CutoverNanos: 24000,
  3117  					Tombstoned:   false,
  3118  					Metadata: metadata.Metadata{
  3119  						Pipelines: []metadata.PipelineMetadata{
  3120  							{
  3121  								AggregationID: aggregation.DefaultID,
  3122  								StoragePolicies: policy.StoragePolicies{
  3123  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3124  								},
  3125  							},
  3126  						},
  3127  					},
  3128  				},
  3129  			},
  3130  		},
  3131  		{
  3132  			id:              "shouldDropTagName1=shouldDropTagValue1",
  3133  			matchFrom:       25000,
  3134  			matchTo:         25001,
  3135  			metricType:      metric.CounterType,
  3136  			aggregationType: aggregation.Sum,
  3137  			expireAtNanos:   30000,
  3138  			forExistingIDResult: metadata.StagedMetadatas{
  3139  				metadata.StagedMetadata{
  3140  					CutoverNanos: 20000,
  3141  					Tombstoned:   false,
  3142  					Metadata: metadata.Metadata{
  3143  						Pipelines: []metadata.PipelineMetadata{
  3144  							{
  3145  								AggregationID: aggregation.DefaultID,
  3146  								StoragePolicies: policy.StoragePolicies{
  3147  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3148  								},
  3149  							},
  3150  							metadata.DropPipelineMetadata,
  3151  						},
  3152  					},
  3153  				},
  3154  			},
  3155  		},
  3156  		{
  3157  			id:              "shouldDrop2TagName1=shouldDrop2TagValue1",
  3158  			matchFrom:       25000,
  3159  			matchTo:         25001,
  3160  			metricType:      metric.CounterType,
  3161  			aggregationType: aggregation.Sum,
  3162  			expireAtNanos:   30000,
  3163  			forExistingIDResult: metadata.StagedMetadatas{
  3164  				metadata.StagedMetadata{
  3165  					CutoverNanos: 20000,
  3166  					Tombstoned:   false,
  3167  					Metadata: metadata.Metadata{
  3168  						Pipelines: metadata.DropIfOnlyMatchPipelineMetadatas,
  3169  					},
  3170  				},
  3171  			},
  3172  		},
  3173  		{
  3174  			id:              "shouldNotDropTagName1=shouldNotDropTagValue1",
  3175  			matchFrom:       25000,
  3176  			matchTo:         25001,
  3177  			metricType:      metric.CounterType,
  3178  			aggregationType: aggregation.Sum,
  3179  			expireAtNanos:   30000,
  3180  			forExistingIDResult: metadata.StagedMetadatas{
  3181  				metadata.StagedMetadata{
  3182  					CutoverNanos: 20000,
  3183  					Tombstoned:   false,
  3184  					Metadata: metadata.Metadata{
  3185  						Pipelines: []metadata.PipelineMetadata{
  3186  							{
  3187  								AggregationID: aggregation.DefaultID,
  3188  								StoragePolicies: policy.StoragePolicies{
  3189  									policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3190  								},
  3191  							},
  3192  							metadata.DropIfOnlyMatchPipelineMetadata,
  3193  						},
  3194  					},
  3195  				},
  3196  			},
  3197  		},
  3198  	}
  3199  
  3200  	isMultiAggregationTypesAllowed := true
  3201  	aggTypesOpts := aggregation.NewTypesOptions()
  3202  	as := newActiveRuleSet(
  3203  		0,
  3204  		testMappingRules(t),
  3205  		nil,
  3206  		testTagsFilterOptions(),
  3207  		mockNewID,
  3208  		func([]byte, []byte) bool { return false },
  3209  	)
  3210  	for i, input := range inputs {
  3211  		input := input
  3212  		t.Run(fmt.Sprintf("input %d", i), func(t *testing.T) {
  3213  			res, err := as.ReverseMatch(input.ID(), input.matchFrom, input.matchTo,
  3214  				input.metricType, input.aggregationType, isMultiAggregationTypesAllowed, aggTypesOpts)
  3215  			require.NoError(t, err)
  3216  			require.Equal(t, input.expireAtNanos, res.expireAtNanos)
  3217  			require.True(t, cmp.Equal(input.forExistingIDResult, res.ForExistingIDAt(0), testStagedMetadatasCmptOpts...))
  3218  			require.Equal(t, input.keepOriginal, res.KeepOriginal())
  3219  		})
  3220  	}
  3221  }
  3222  
  3223  func TestActiveRuleSetReverseMatchWithRollupRulesForRollupID(t *testing.T) {
  3224  	inputs := []testMatchInput{
  3225  		{
  3226  			id:              "rName4|rtagName1=rtagValue2",
  3227  			matchFrom:       25000,
  3228  			matchTo:         25001,
  3229  			metricType:      metric.CounterType,
  3230  			aggregationType: aggregation.Sum,
  3231  			expireAtNanos:   30000,
  3232  			forExistingIDResult: metadata.StagedMetadatas{
  3233  				{
  3234  					CutoverNanos: 24000,
  3235  					Tombstoned:   false,
  3236  					Metadata: metadata.Metadata{
  3237  						Pipelines: []metadata.PipelineMetadata{
  3238  							{
  3239  								AggregationID: aggregation.DefaultID,
  3240  								StoragePolicies: policy.StoragePolicies{
  3241  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  3242  								},
  3243  							},
  3244  						},
  3245  					},
  3246  				},
  3247  			},
  3248  		},
  3249  		{
  3250  			id:                  "rName4|rtagName1=rtagValue2",
  3251  			matchFrom:           25000,
  3252  			matchTo:             25001,
  3253  			metricType:          metric.CounterType,
  3254  			aggregationType:     aggregation.Min,
  3255  			expireAtNanos:       30000,
  3256  			forExistingIDResult: nil,
  3257  		},
  3258  		{
  3259  			id:                  "rName4|rtagName1=rtagValue2",
  3260  			matchFrom:           25000,
  3261  			matchTo:             25001,
  3262  			metricType:          metric.UnknownType,
  3263  			aggregationType:     aggregation.UnknownType,
  3264  			expireAtNanos:       30000,
  3265  			forExistingIDResult: nil,
  3266  		},
  3267  		{
  3268  			id:              "rName4|rtagName1=rtagValue2",
  3269  			matchFrom:       25000,
  3270  			matchTo:         25001,
  3271  			metricType:      metric.TimerType,
  3272  			aggregationType: aggregation.P99,
  3273  			expireAtNanos:   30000,
  3274  			forExistingIDResult: metadata.StagedMetadatas{
  3275  				{
  3276  					CutoverNanos: 24000,
  3277  					Tombstoned:   false,
  3278  					Metadata: metadata.Metadata{
  3279  						Pipelines: []metadata.PipelineMetadata{
  3280  							{
  3281  								AggregationID: aggregation.DefaultID,
  3282  								StoragePolicies: policy.StoragePolicies{
  3283  									policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  3284  								},
  3285  							},
  3286  						},
  3287  					},
  3288  				},
  3289  			},
  3290  		},
  3291  		{
  3292  			id:                  "rName4|rtagName2=rtagValue2",
  3293  			matchFrom:           25000,
  3294  			matchTo:             25001,
  3295  			metricType:          metric.CounterType,
  3296  			aggregationType:     aggregation.Sum,
  3297  			expireAtNanos:       30000,
  3298  			forExistingIDResult: nil,
  3299  		},
  3300  		{
  3301  			id:                  "rName4|rtagName1=rtagValue2",
  3302  			matchFrom:           10000,
  3303  			matchTo:             10001,
  3304  			expireAtNanos:       15000,
  3305  			forExistingIDResult: nil,
  3306  		},
  3307  		{
  3308  			id:              "rName5|rtagName1=rtagValue2",
  3309  			matchFrom:       130000,
  3310  			matchTo:         130001,
  3311  			metricType:      metric.TimerType,
  3312  			aggregationType: aggregation.P99,
  3313  			expireAtNanos:   math.MaxInt64,
  3314  			forExistingIDResult: metadata.StagedMetadatas{
  3315  				{
  3316  					CutoverNanos: 24000,
  3317  					Tombstoned:   false,
  3318  					Metadata: metadata.Metadata{
  3319  						Pipelines: []metadata.PipelineMetadata{
  3320  							{
  3321  								AggregationID: aggregation.DefaultID,
  3322  								StoragePolicies: policy.StoragePolicies{
  3323  									policy.NewStoragePolicy(time.Second, xtime.Second, time.Minute),
  3324  								},
  3325  							},
  3326  						},
  3327  					},
  3328  				},
  3329  			},
  3330  		},
  3331  		{
  3332  			id:              "rName5|rtagName1=rtagValue2",
  3333  			matchFrom:       130000,
  3334  			matchTo:         130001,
  3335  			metricType:      metric.GaugeType,
  3336  			aggregationType: aggregation.Last,
  3337  			expireAtNanos:   math.MaxInt64,
  3338  			forExistingIDResult: metadata.StagedMetadatas{
  3339  				{
  3340  					CutoverNanos: 24000,
  3341  					Tombstoned:   false,
  3342  					Metadata: metadata.Metadata{
  3343  						Pipelines: []metadata.PipelineMetadata{
  3344  							{
  3345  								AggregationID: aggregation.DefaultID,
  3346  								StoragePolicies: policy.StoragePolicies{
  3347  									policy.NewStoragePolicy(time.Second, xtime.Second, time.Minute),
  3348  								},
  3349  							},
  3350  						},
  3351  					},
  3352  				},
  3353  			},
  3354  		},
  3355  		{
  3356  			id:              "rName7|rtagName1=rtagValue2",
  3357  			matchFrom:       130000,
  3358  			matchTo:         130001,
  3359  			metricType:      metric.TimerType,
  3360  			aggregationType: aggregation.P90,
  3361  			expireAtNanos:   math.MaxInt64,
  3362  			forExistingIDResult: metadata.StagedMetadatas{
  3363  				{
  3364  					CutoverNanos: 120000,
  3365  					Tombstoned:   false,
  3366  					Metadata: metadata.Metadata{
  3367  						Pipelines: []metadata.PipelineMetadata{
  3368  							{
  3369  								AggregationID: aggregation.MustCompressTypes(aggregation.Sum, aggregation.P90),
  3370  								StoragePolicies: policy.StoragePolicies{
  3371  									policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  3372  									policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  3373  								},
  3374  							},
  3375  						},
  3376  					},
  3377  				},
  3378  			},
  3379  		},
  3380  		{
  3381  			id:              "rName83|rtagName1=rtagValue2",
  3382  			matchFrom:       130000,
  3383  			matchTo:         130001,
  3384  			metricType:      metric.TimerType,
  3385  			aggregationType: aggregation.Min,
  3386  			expireAtNanos:   math.MaxInt64,
  3387  			forExistingIDResult: metadata.StagedMetadatas{
  3388  				{
  3389  					CutoverNanos: 90000,
  3390  					Tombstoned:   false,
  3391  					Metadata: metadata.Metadata{
  3392  						Pipelines: []metadata.PipelineMetadata{
  3393  							{
  3394  								AggregationID: aggregation.MustCompressTypes(aggregation.Min),
  3395  								StoragePolicies: policy.StoragePolicies{
  3396  									policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  3397  									policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  3398  								},
  3399  							},
  3400  						},
  3401  					},
  3402  				},
  3403  			},
  3404  		},
  3405  	}
  3406  
  3407  	isMultiAggregationTypesAllowed := true
  3408  	aggTypesOpts := aggregation.NewTypesOptions()
  3409  	as := newActiveRuleSet(
  3410  		0,
  3411  		nil,
  3412  		testRollupRules(t),
  3413  		testTagsFilterOptions(),
  3414  		mockNewID,
  3415  		func([]byte, []byte) bool { return true },
  3416  	)
  3417  	for _, input := range inputs {
  3418  		res, err := as.ReverseMatch(input.ID(), input.matchFrom, input.matchTo, input.metricType, input.aggregationType,
  3419  			isMultiAggregationTypesAllowed, aggTypesOpts)
  3420  		require.NoError(t, err)
  3421  		require.Equal(t, input.expireAtNanos, res.expireAtNanos)
  3422  		require.Equal(t, input.forExistingIDResult, res.ForExistingIDAt(0))
  3423  		require.Equal(t, 0, res.NumNewRollupIDs())
  3424  		require.Equal(t, input.keepOriginal, res.KeepOriginal())
  3425  	}
  3426  }
  3427  
  3428  func TestMatchedKeepOriginal(t *testing.T) {
  3429  	rr1, err := pipeline.NewRollupOp(
  3430  		pipeline.GroupByRollupType,
  3431  		"rollup.r2",
  3432  		[]string{"foo"},
  3433  		aggregation.DefaultID,
  3434  	)
  3435  	require.NoError(t, err)
  3436  
  3437  	filter, err := filters.NewTagsFilter(
  3438  		filters.TagFilterValueMap{
  3439  			"foo": filters.FilterValue{Pattern: "bar"},
  3440  			"baz": filters.FilterValue{Pattern: "bat"},
  3441  		},
  3442  		filters.Conjunction,
  3443  		testTagsFilterOptions(),
  3444  	)
  3445  	require.NoError(t, err)
  3446  
  3447  	var (
  3448  		targets = []rollupTarget{
  3449  			{
  3450  				Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  3451  					{
  3452  						Type:   pipeline.RollupOpType,
  3453  						Rollup: rr1,
  3454  					},
  3455  				}),
  3456  				StoragePolicies: policy.StoragePolicies{
  3457  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3458  				},
  3459  			},
  3460  		}
  3461  		rollups = []*rollupRule{
  3462  			{
  3463  				uuid: "rollup",
  3464  				snapshots: []*rollupRuleSnapshot{
  3465  					{
  3466  						name:         "rollup.1.nokeep",
  3467  						cutoverNanos: 0,
  3468  						filter:       filter,
  3469  						keepOriginal: false,
  3470  						targets:      targets,
  3471  					},
  3472  					{
  3473  						name:         "rollup.2.keep",
  3474  						cutoverNanos: 10000,
  3475  						filter:       filter,
  3476  						keepOriginal: true,
  3477  						targets:      targets,
  3478  					},
  3479  					{
  3480  						name:         "rollup.2.nokeep",
  3481  						tombstoned:   false,
  3482  						cutoverNanos: 20000,
  3483  						filter:       filter,
  3484  						targets:      targets,
  3485  					},
  3486  				},
  3487  			},
  3488  		}
  3489  		as = newActiveRuleSet(
  3490  			0,
  3491  			nil,
  3492  			rollups,
  3493  			testTagsFilterOptions(),
  3494  			mockNewID,
  3495  			func([]byte, []byte) bool { return true },
  3496  		)
  3497  	)
  3498  
  3499  	cases := map[string]struct {
  3500  		expectKeepOriginal bool
  3501  		cutoverNanos       int64
  3502  	}{
  3503  		"latest-nokeep-first": {
  3504  			expectKeepOriginal: false,
  3505  			cutoverNanos:       0,
  3506  		},
  3507  		"latest-keep-nested": {
  3508  			expectKeepOriginal: true,
  3509  			cutoverNanos:       10000,
  3510  		},
  3511  		"latest-nokeep-last": {
  3512  			expectKeepOriginal: false,
  3513  			cutoverNanos:       20000,
  3514  		},
  3515  	}
  3516  
  3517  	for name, tt := range cases {
  3518  		t.Run(name, func(t *testing.T) {
  3519  			res, err := as.ForwardMatch(
  3520  				namespace.NewTestID("baz=bat,foo=bar", "ns"),
  3521  				tt.cutoverNanos,
  3522  				tt.cutoverNanos+10000,
  3523  				testMatchOptions(),
  3524  			)
  3525  			require.NoError(t, err)
  3526  			require.Equal(t, 1, res.NumNewRollupIDs())
  3527  			require.Equal(t, tt.expectKeepOriginal, res.KeepOriginal())
  3528  		})
  3529  	}
  3530  }
  3531  
  3532  func testMappingRules(t *testing.T) []*mappingRule {
  3533  	filter1, err := filters.NewTagsFilter(
  3534  		filters.TagFilterValueMap{"mtagName1": filters.FilterValue{Pattern: "mtagValue1"}},
  3535  		filters.Conjunction,
  3536  		testTagsFilterOptions(),
  3537  	)
  3538  	require.NoError(t, err)
  3539  	filter2, err := filters.NewTagsFilter(
  3540  		filters.TagFilterValueMap{"mtagName1": filters.FilterValue{Pattern: "mtagValue2"}},
  3541  		filters.Conjunction,
  3542  		testTagsFilterOptions(),
  3543  	)
  3544  	require.NoError(t, err)
  3545  	filter3, err := filters.NewTagsFilter(
  3546  		filters.TagFilterValueMap{"mtagName1": filters.FilterValue{Pattern: "mtagValue3"}},
  3547  		filters.Conjunction,
  3548  		testTagsFilterOptions(),
  3549  	)
  3550  	require.NoError(t, err)
  3551  	filter4, err := filters.NewTagsFilter(
  3552  		filters.TagFilterValueMap{"mtagName1": filters.FilterValue{Pattern: "mtagValue4"}},
  3553  		filters.Conjunction,
  3554  		testTagsFilterOptions(),
  3555  	)
  3556  	require.NoError(t, err)
  3557  	filter5, err := filters.NewTagsFilter(
  3558  		filters.TagFilterValueMap{"shouldDropTagName1": filters.FilterValue{Pattern: "shouldDropTagValue1"}},
  3559  		filters.Conjunction,
  3560  		testTagsFilterOptions(),
  3561  	)
  3562  	require.NoError(t, err)
  3563  	filter6, err := filters.NewTagsFilter(
  3564  		filters.TagFilterValueMap{"shouldDrop2TagName1": filters.FilterValue{Pattern: "shouldDrop2TagValue1"}},
  3565  		filters.Conjunction,
  3566  		testTagsFilterOptions(),
  3567  	)
  3568  	require.NoError(t, err)
  3569  	filter7, err := filters.NewTagsFilter(
  3570  		filters.TagFilterValueMap{"shouldNotDropTagName1": filters.FilterValue{Pattern: "shouldNotDropTagValue1"}},
  3571  		filters.Conjunction,
  3572  		testTagsFilterOptions(),
  3573  	)
  3574  	require.NoError(t, err)
  3575  
  3576  	tags := []models.Tag{{Name: []byte("service")}}
  3577  	mappingRule1 := &mappingRule{
  3578  		uuid: "mappingRule1",
  3579  		snapshots: []*mappingRuleSnapshot{
  3580  			{
  3581  				name:          "mappingRule1.snapshot1",
  3582  				tombstoned:    false,
  3583  				cutoverNanos:  10000,
  3584  				filter:        filter1,
  3585  				aggregationID: aggregation.MustCompressTypes(aggregation.Count),
  3586  				storagePolicies: policy.StoragePolicies{
  3587  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3588  				},
  3589  				tags: tags,
  3590  			},
  3591  			{
  3592  				name:          "mappingRule1.snapshot1",
  3593  				tombstoned:    false,
  3594  				cutoverNanos:  15000,
  3595  				filter:        filter1,
  3596  				aggregationID: aggregation.MustCompressTypes(aggregation.Count),
  3597  				storagePolicies: policy.StoragePolicies{
  3598  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  3599  				},
  3600  				tags: tags,
  3601  			},
  3602  			{
  3603  				name:          "mappingRule1.snapshot2",
  3604  				tombstoned:    false,
  3605  				cutoverNanos:  20000,
  3606  				filter:        filter1,
  3607  				aggregationID: aggregation.DefaultID,
  3608  				storagePolicies: policy.StoragePolicies{
  3609  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  3610  					policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  3611  					policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  3612  				},
  3613  				tags: tags,
  3614  			},
  3615  			{
  3616  				name:          "mappingRule1.snapshot3",
  3617  				tombstoned:    false,
  3618  				cutoverNanos:  30000,
  3619  				filter:        filter1,
  3620  				aggregationID: aggregation.DefaultID,
  3621  				storagePolicies: policy.StoragePolicies{
  3622  					policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  3623  				},
  3624  				tags: tags,
  3625  			},
  3626  		},
  3627  	}
  3628  
  3629  	mappingRule2 := &mappingRule{
  3630  		uuid: "mappingRule2",
  3631  		snapshots: []*mappingRuleSnapshot{
  3632  			{
  3633  				name:          "mappingRule2.snapshot1",
  3634  				tombstoned:    false,
  3635  				cutoverNanos:  15000,
  3636  				filter:        filter1,
  3637  				aggregationID: aggregation.MustCompressTypes(aggregation.Mean),
  3638  				storagePolicies: policy.StoragePolicies{
  3639  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  3640  				},
  3641  			},
  3642  			{
  3643  				name:          "mappingRule2.snapshot2",
  3644  				tombstoned:    false,
  3645  				cutoverNanos:  22000,
  3646  				filter:        filter1,
  3647  				aggregationID: aggregation.DefaultID,
  3648  				storagePolicies: policy.StoragePolicies{
  3649  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  3650  					policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  3651  				},
  3652  			},
  3653  			{
  3654  				name:          "mappingRule2.snapshot3",
  3655  				tombstoned:    true,
  3656  				cutoverNanos:  35000,
  3657  				filter:        filter1,
  3658  				aggregationID: aggregation.DefaultID,
  3659  				storagePolicies: policy.StoragePolicies{
  3660  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  3661  					policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  3662  				},
  3663  			},
  3664  		},
  3665  	}
  3666  
  3667  	mappingRule3 := &mappingRule{
  3668  		uuid: "mappingRule3",
  3669  		snapshots: []*mappingRuleSnapshot{
  3670  			{
  3671  				name:          "mappingRule3.snapshot1",
  3672  				tombstoned:    false,
  3673  				cutoverNanos:  22000,
  3674  				filter:        filter1,
  3675  				aggregationID: aggregation.DefaultID,
  3676  				storagePolicies: policy.StoragePolicies{
  3677  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  3678  					policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  3679  					policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  3680  				},
  3681  			},
  3682  			{
  3683  				name:          "mappingRule3.snapshot2",
  3684  				tombstoned:    false,
  3685  				cutoverNanos:  34000,
  3686  				filter:        filter1,
  3687  				aggregationID: aggregation.MustCompressTypes(aggregation.Sum),
  3688  				storagePolicies: policy.StoragePolicies{
  3689  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  3690  					policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  3691  				},
  3692  			},
  3693  		},
  3694  	}
  3695  
  3696  	mappingRule4 := &mappingRule{
  3697  		uuid: "mappingRule4",
  3698  		snapshots: []*mappingRuleSnapshot{
  3699  			{
  3700  				name:          "mappingRule4.snapshot1",
  3701  				tombstoned:    false,
  3702  				cutoverNanos:  24000,
  3703  				filter:        filter2,
  3704  				aggregationID: aggregation.DefaultID,
  3705  				storagePolicies: policy.StoragePolicies{
  3706  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3707  				},
  3708  			},
  3709  		},
  3710  	}
  3711  
  3712  	mappingRule5 := &mappingRule{
  3713  		uuid: "mappingRule5",
  3714  		snapshots: []*mappingRuleSnapshot{
  3715  			{
  3716  				name:          "mappingRule5.snapshot1",
  3717  				tombstoned:    false,
  3718  				cutoverNanos:  100000,
  3719  				filter:        filter1,
  3720  				aggregationID: aggregation.DefaultID,
  3721  				storagePolicies: policy.StoragePolicies{
  3722  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3723  				},
  3724  			},
  3725  		},
  3726  	}
  3727  
  3728  	mappingRule6 := &mappingRule{
  3729  		uuid: "mappingRule6",
  3730  		snapshots: []*mappingRuleSnapshot{
  3731  			{
  3732  				name:          "mappingRule6.snapshot1",
  3733  				tombstoned:    false,
  3734  				cutoverNanos:  5000,
  3735  				filter:        filter3,
  3736  				aggregationID: aggregation.DefaultID,
  3737  				storagePolicies: policy.StoragePolicies{
  3738  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3739  				},
  3740  			},
  3741  			{
  3742  				name:          "mappingRule6.snapshot2",
  3743  				tombstoned:    false,
  3744  				cutoverNanos:  8000,
  3745  				filter:        filter4,
  3746  				aggregationID: aggregation.DefaultID,
  3747  				storagePolicies: policy.StoragePolicies{
  3748  					policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  3749  				},
  3750  			},
  3751  		},
  3752  	}
  3753  
  3754  	// Mapping rule 7 and 8 should combine to have the the aggregation as per
  3755  	// mapping rule 7 to occur with the metrics being dropped for the default
  3756  	// aggregation as per mapping rule 8 which explicitly says must be dropped
  3757  	mappingRule7 := &mappingRule{
  3758  		uuid: "mappingRule7",
  3759  		snapshots: []*mappingRuleSnapshot{
  3760  			{
  3761  				name:          "mappingRule7.snapshot1",
  3762  				tombstoned:    false,
  3763  				cutoverNanos:  20000,
  3764  				filter:        filter5,
  3765  				aggregationID: aggregation.DefaultID,
  3766  				storagePolicies: policy.StoragePolicies{
  3767  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3768  				},
  3769  			},
  3770  		},
  3771  	}
  3772  
  3773  	mappingRule8 := &mappingRule{
  3774  		uuid: "mappingRule8",
  3775  		snapshots: []*mappingRuleSnapshot{
  3776  			{
  3777  				name:            "mappingRule8.snapshot1",
  3778  				tombstoned:      false,
  3779  				cutoverNanos:    20000,
  3780  				filter:          filter5,
  3781  				aggregationID:   aggregation.DefaultID,
  3782  				storagePolicies: policy.StoragePolicies{},
  3783  				dropPolicy:      policy.DropMust,
  3784  			},
  3785  		},
  3786  	}
  3787  
  3788  	// Mapping rule 9 should effectively be a drop since no other mapping rules match and
  3789  	// mapping rule 9 explicitly says must be dropped except if there is another match
  3790  	mappingRule9 := &mappingRule{
  3791  		uuid: "mappingRule9",
  3792  		snapshots: []*mappingRuleSnapshot{
  3793  			{
  3794  				name:            "mappingRule9.snapshot1",
  3795  				tombstoned:      false,
  3796  				cutoverNanos:    20000,
  3797  				filter:          filter6,
  3798  				aggregationID:   aggregation.DefaultID,
  3799  				storagePolicies: policy.StoragePolicies{},
  3800  				dropPolicy:      policy.DropIfOnlyMatch,
  3801  			},
  3802  		},
  3803  	}
  3804  
  3805  	// Mapping rule 10 and 11 should combine to have the the aggregation as per
  3806  	// mapping rule 10 to occur with the metrics being dropped for the default
  3807  	// aggregation as per mapping rule 11 which says it must be dropped on
  3808  	// match
  3809  	mappingRule10 := &mappingRule{
  3810  		uuid: "mappingRule10",
  3811  		snapshots: []*mappingRuleSnapshot{
  3812  			{
  3813  				name:          "mappingRule10.snapshot1",
  3814  				tombstoned:    false,
  3815  				cutoverNanos:  20000,
  3816  				filter:        filter7,
  3817  				aggregationID: aggregation.DefaultID,
  3818  				storagePolicies: policy.StoragePolicies{
  3819  					policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3820  				},
  3821  			},
  3822  		},
  3823  	}
  3824  
  3825  	mappingRule11 := &mappingRule{
  3826  		uuid: "mappingRule11",
  3827  		snapshots: []*mappingRuleSnapshot{
  3828  			{
  3829  				name:            "mappingRule11.snapshot1",
  3830  				tombstoned:      false,
  3831  				cutoverNanos:    20000,
  3832  				filter:          filter7,
  3833  				aggregationID:   aggregation.DefaultID,
  3834  				storagePolicies: policy.StoragePolicies{},
  3835  				dropPolicy:      policy.DropIfOnlyMatch,
  3836  			},
  3837  		},
  3838  	}
  3839  
  3840  	return []*mappingRule{mappingRule1, mappingRule2, mappingRule3, mappingRule4,
  3841  		mappingRule5, mappingRule6, mappingRule7, mappingRule8, mappingRule9,
  3842  		mappingRule10, mappingRule11}
  3843  }
  3844  
  3845  func testKeepOriginalRollupRules(t *testing.T) []*rollupRule {
  3846  	filter, err := filters.NewTagsFilter(
  3847  		filters.TagFilterValueMap{
  3848  			"rtagName1": filters.FilterValue{Pattern: "rtagValue1"},
  3849  		},
  3850  		filters.Conjunction,
  3851  		testTagsFilterOptions(),
  3852  	)
  3853  	require.NoError(t, err)
  3854  
  3855  	rr1, err := pipeline.NewRollupOp(
  3856  		pipeline.GroupByRollupType,
  3857  		"rName1",
  3858  		[]string{"rtagName1"},
  3859  		aggregation.DefaultID,
  3860  	)
  3861  	require.NoError(t, err)
  3862  	rr2, err := pipeline.NewRollupOp(
  3863  		pipeline.GroupByRollupType,
  3864  		"rName2",
  3865  		[]string{"rtagName1"},
  3866  		aggregation.DefaultID,
  3867  	)
  3868  	require.NoError(t, err)
  3869  	rr3, err := pipeline.NewRollupOp(
  3870  		pipeline.GroupByRollupType,
  3871  		"rName3",
  3872  		[]string{"rtagName1"},
  3873  		aggregation.DefaultID,
  3874  	)
  3875  	require.NoError(t, err)
  3876  
  3877  	rollupRule1 := &rollupRule{
  3878  		uuid: "rollupRule1",
  3879  		snapshots: []*rollupRuleSnapshot{
  3880  			{
  3881  				name:         "rollupRule1.snapshot",
  3882  				tombstoned:   false,
  3883  				cutoverNanos: 0,
  3884  				filter:       filter,
  3885  				keepOriginal: false,
  3886  				targets: []rollupTarget{
  3887  					{
  3888  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  3889  							{
  3890  								Type:   pipeline.RollupOpType,
  3891  								Rollup: rr1,
  3892  							},
  3893  						}),
  3894  						StoragePolicies: policy.StoragePolicies{
  3895  							policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3896  						},
  3897  					},
  3898  				},
  3899  			},
  3900  		},
  3901  	}
  3902  
  3903  	rollupRule2 := &rollupRule{
  3904  		uuid: "rollupRule2",
  3905  		snapshots: []*rollupRuleSnapshot{
  3906  			{
  3907  				name:         "rollupRule2.snapshot",
  3908  				tombstoned:   false,
  3909  				cutoverNanos: 0,
  3910  				filter:       filter,
  3911  				keepOriginal: true,
  3912  				targets: []rollupTarget{
  3913  					{
  3914  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  3915  							{
  3916  								Type:   pipeline.RollupOpType,
  3917  								Rollup: rr2,
  3918  							},
  3919  						}),
  3920  						StoragePolicies: policy.StoragePolicies{
  3921  							policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3922  						},
  3923  					},
  3924  				},
  3925  			},
  3926  		},
  3927  	}
  3928  
  3929  	rollupRule3 := &rollupRule{
  3930  		uuid: "rollupRule3",
  3931  		snapshots: []*rollupRuleSnapshot{
  3932  			{
  3933  				name:         "rollupRule3.snapshot",
  3934  				tombstoned:   false,
  3935  				cutoverNanos: 0,
  3936  				filter:       filter,
  3937  				keepOriginal: true,
  3938  				targets: []rollupTarget{
  3939  					{
  3940  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  3941  							{
  3942  								Type:   pipeline.RollupOpType,
  3943  								Rollup: rr3,
  3944  							},
  3945  						}),
  3946  						StoragePolicies: policy.StoragePolicies{
  3947  							policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  3948  						},
  3949  					},
  3950  				},
  3951  			},
  3952  		},
  3953  	}
  3954  
  3955  	return []*rollupRule{rollupRule1, rollupRule2, rollupRule3}
  3956  }
  3957  
  3958  func testRollupRules(t *testing.T) []*rollupRule {
  3959  	filter1, err := filters.NewTagsFilter(
  3960  		filters.TagFilterValueMap{
  3961  			"rtagName1": filters.FilterValue{Pattern: "rtagValue1"},
  3962  			"rtagName2": filters.FilterValue{Pattern: "rtagValue2"},
  3963  		},
  3964  		filters.Conjunction,
  3965  		testTagsFilterOptions(),
  3966  	)
  3967  	require.NoError(t, err)
  3968  	filter2, err := filters.NewTagsFilter(
  3969  		filters.TagFilterValueMap{
  3970  			"rtagName1": filters.FilterValue{Pattern: "rtagValue2"},
  3971  		},
  3972  		filters.Conjunction,
  3973  		testTagsFilterOptions(),
  3974  	)
  3975  	require.NoError(t, err)
  3976  	filter3, err := filters.NewTagsFilter(
  3977  		filters.TagFilterValueMap{
  3978  			"rtagName1": filters.FilterValue{Pattern: "rtagValue3"},
  3979  		},
  3980  		filters.Conjunction,
  3981  		testTagsFilterOptions(),
  3982  	)
  3983  	require.NoError(t, err)
  3984  
  3985  	rr1, err := pipeline.NewRollupOp(
  3986  		pipeline.GroupByRollupType,
  3987  		"rName1",
  3988  		[]string{"rtagName1", "rtagName2"},
  3989  		aggregation.DefaultID,
  3990  	)
  3991  	require.NoError(t, err)
  3992  	rr2, err := pipeline.NewRollupOp(
  3993  		pipeline.GroupByRollupType,
  3994  		"rName2",
  3995  		[]string{"rtagName1", "rtagName2"},
  3996  		aggregation.DefaultID,
  3997  	)
  3998  	require.NoError(t, err)
  3999  	rr2_2, err := pipeline.NewRollupOp(
  4000  		pipeline.GroupByRollupType,
  4001  		"rName2",
  4002  		[]string{"rtagName1", "rtagName2"},
  4003  		aggregation.MustCompressTypes(aggregation.Sum),
  4004  	)
  4005  	require.NoError(t, err)
  4006  	rr3, err := pipeline.NewRollupOp(
  4007  		pipeline.GroupByRollupType,
  4008  		"rName3",
  4009  		[]string{"rtagName1", "rtagName2"},
  4010  		aggregation.DefaultID,
  4011  	)
  4012  	require.NoError(t, err)
  4013  	rr3_2, err := pipeline.NewRollupOp(
  4014  		pipeline.GroupByRollupType,
  4015  		"rName3",
  4016  		[]string{"rtagName1"},
  4017  		aggregation.DefaultID,
  4018  	)
  4019  	require.NoError(t, err)
  4020  	rr4, err := pipeline.NewRollupOp(
  4021  		pipeline.GroupByRollupType,
  4022  		"rName4",
  4023  		[]string{"rtagName1"},
  4024  		aggregation.DefaultID,
  4025  	)
  4026  	require.NoError(t, err)
  4027  	rr5, err := pipeline.NewRollupOp(
  4028  		pipeline.GroupByRollupType,
  4029  		"rName5",
  4030  		[]string{"rtagName1"},
  4031  		aggregation.DefaultID,
  4032  	)
  4033  	require.NoError(t, err)
  4034  	rr6, err := pipeline.NewRollupOp(
  4035  		pipeline.GroupByRollupType,
  4036  		"rName6",
  4037  		[]string{"rtagName1", "rtagName2"},
  4038  		aggregation.DefaultID,
  4039  	)
  4040  	require.NoError(t, err)
  4041  	rr7, err := pipeline.NewRollupOp(
  4042  		pipeline.GroupByRollupType,
  4043  		"rName7",
  4044  		[]string{"rtagName1"},
  4045  		aggregation.MustCompressTypes(aggregation.Sum, aggregation.P90),
  4046  	)
  4047  	require.NoError(t, err)
  4048  	rr8, err := pipeline.NewRollupOp(
  4049  		pipeline.GroupByRollupType,
  4050  		"rName81",
  4051  		[]string{"rtagName1", "rtagName2", "rtagName3"},
  4052  		aggregation.MustCompressTypes(aggregation.Sum, aggregation.P90),
  4053  	)
  4054  	require.NoError(t, err)
  4055  	rr8_2, err := pipeline.NewRollupOp(
  4056  		pipeline.GroupByRollupType,
  4057  		"rName82",
  4058  		[]string{"rtagName1", "rtagName2"},
  4059  		aggregation.MustCompressTypes(aggregation.Count),
  4060  	)
  4061  	require.NoError(t, err)
  4062  	rr8_3, err := pipeline.NewRollupOp(
  4063  		pipeline.GroupByRollupType,
  4064  		"rName83",
  4065  		[]string{"rtagName1"},
  4066  		aggregation.MustCompressTypes(aggregation.Min),
  4067  	)
  4068  	require.NoError(t, err)
  4069  
  4070  	rr9, err := pipeline.NewRollupOp(
  4071  		pipeline.ExcludeByRollupType,
  4072  		"rName9A",
  4073  		[]string{"rtagName1"},
  4074  		aggregation.MustCompressTypes(aggregation.Last),
  4075  	)
  4076  	require.NoError(t, err)
  4077  
  4078  	rr10, err := pipeline.NewRollupOp(
  4079  		pipeline.ExcludeByRollupType,
  4080  		"rName9B",
  4081  		// Include a case where an exclude rule references a tag that doesn't
  4082  		// exist in the input metric and is lexicographyically less than the
  4083  		// other rules. This covers regressions around sorted list merge behavior
  4084  		// in the excludeBy (vs groupBy) case.
  4085  		[]string{"atagName1", "rtagName1"},
  4086  		aggregation.MustCompressTypes(aggregation.Last),
  4087  	)
  4088  	require.NoError(t, err)
  4089  
  4090  	rr11, err := pipeline.NewRollupOp(
  4091  		pipeline.ExcludeByRollupType,
  4092  		"rName9C",
  4093  		[]string{"rtagName1", "rtagName3"},
  4094  		aggregation.MustCompressTypes(aggregation.Last),
  4095  	)
  4096  	require.NoError(t, err)
  4097  
  4098  	rollupRule1 := &rollupRule{
  4099  		uuid: "rollupRule1",
  4100  		snapshots: []*rollupRuleSnapshot{
  4101  			{
  4102  				name:         "rollupRule1.snapshot1",
  4103  				tombstoned:   false,
  4104  				cutoverNanos: 10000,
  4105  				filter:       filter1,
  4106  				targets: []rollupTarget{
  4107  					{
  4108  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4109  							{
  4110  								Type:   pipeline.RollupOpType,
  4111  								Rollup: rr1,
  4112  							},
  4113  						}),
  4114  						StoragePolicies: policy.StoragePolicies{
  4115  							policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  4116  						},
  4117  					},
  4118  				},
  4119  			},
  4120  			{
  4121  				name:         "rollupRule1.snapshot2",
  4122  				tombstoned:   false,
  4123  				cutoverNanos: 20000,
  4124  				filter:       filter1,
  4125  				keepOriginal: true,
  4126  				targets: []rollupTarget{
  4127  					{
  4128  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4129  							{
  4130  								Type: pipeline.AggregationOpType,
  4131  								Aggregation: pipeline.AggregationOp{
  4132  									Type: aggregation.Sum,
  4133  								},
  4134  							},
  4135  							{
  4136  								Type:   pipeline.RollupOpType,
  4137  								Rollup: rr1,
  4138  							},
  4139  						}),
  4140  						StoragePolicies: policy.StoragePolicies{
  4141  							policy.NewStoragePolicy(10*time.Second, xtime.Second, 6*time.Hour),
  4142  							policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  4143  							policy.NewStoragePolicy(10*time.Minute, xtime.Minute, 48*time.Hour),
  4144  						},
  4145  					},
  4146  				},
  4147  			},
  4148  			{
  4149  				name:         "rollupRule1.snapshot3",
  4150  				tombstoned:   false,
  4151  				cutoverNanos: 30000,
  4152  				filter:       filter1,
  4153  				targets: []rollupTarget{
  4154  					{
  4155  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4156  							{
  4157  								Type: pipeline.TransformationOpType,
  4158  								Transformation: pipeline.TransformationOp{
  4159  									Type: transformation.PerSecond,
  4160  								},
  4161  							},
  4162  							{
  4163  								Type:   pipeline.RollupOpType,
  4164  								Rollup: rr1,
  4165  							},
  4166  						}),
  4167  						StoragePolicies: policy.StoragePolicies{
  4168  							policy.NewStoragePolicy(30*time.Second, xtime.Second, 6*time.Hour),
  4169  						},
  4170  					},
  4171  				},
  4172  			},
  4173  		},
  4174  	}
  4175  
  4176  	rollupRule2 := &rollupRule{
  4177  		uuid: "rollupRule2",
  4178  		snapshots: []*rollupRuleSnapshot{
  4179  			{
  4180  				name:         "rollupRule2.snapshot1",
  4181  				tombstoned:   false,
  4182  				cutoverNanos: 15000,
  4183  				filter:       filter1,
  4184  				targets: []rollupTarget{
  4185  					{
  4186  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4187  							{
  4188  								Type:   pipeline.RollupOpType,
  4189  								Rollup: rr2,
  4190  							},
  4191  						}),
  4192  						StoragePolicies: policy.StoragePolicies{
  4193  							policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  4194  						},
  4195  					},
  4196  				},
  4197  			},
  4198  			{
  4199  				name:         "rollupRule2.snapshot2",
  4200  				tombstoned:   false,
  4201  				cutoverNanos: 22000,
  4202  				filter:       filter1,
  4203  				targets: []rollupTarget{
  4204  					{
  4205  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4206  							{
  4207  								Type: pipeline.AggregationOpType,
  4208  								Aggregation: pipeline.AggregationOp{
  4209  									Type: aggregation.Last,
  4210  								},
  4211  							},
  4212  							{
  4213  								Type: pipeline.TransformationOpType,
  4214  								Transformation: pipeline.TransformationOp{
  4215  									Type: transformation.PerSecond,
  4216  								},
  4217  							},
  4218  							{
  4219  								Type:   pipeline.RollupOpType,
  4220  								Rollup: rr2_2,
  4221  							},
  4222  						}),
  4223  						StoragePolicies: policy.StoragePolicies{
  4224  							policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  4225  							policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  4226  						},
  4227  					},
  4228  				},
  4229  			},
  4230  			{
  4231  				name:         "rollupRule2.snapshot3",
  4232  				tombstoned:   false,
  4233  				cutoverNanos: 35000,
  4234  				filter:       filter1,
  4235  				targets: []rollupTarget{
  4236  					{
  4237  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4238  							{
  4239  								Type:   pipeline.RollupOpType,
  4240  								Rollup: rr2,
  4241  							},
  4242  						}),
  4243  						StoragePolicies: policy.StoragePolicies{
  4244  							policy.NewStoragePolicy(45*time.Second, xtime.Second, 12*time.Hour),
  4245  						},
  4246  					},
  4247  				},
  4248  			},
  4249  		},
  4250  	}
  4251  
  4252  	rollupRule3 := &rollupRule{
  4253  		uuid: "rollupRule3",
  4254  		snapshots: []*rollupRuleSnapshot{
  4255  			{
  4256  				name:         "rollupRule3.snapshot1",
  4257  				tombstoned:   false,
  4258  				cutoverNanos: 22000,
  4259  				filter:       filter1,
  4260  				targets: []rollupTarget{
  4261  					{
  4262  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4263  							{
  4264  								Type:   pipeline.RollupOpType,
  4265  								Rollup: rr3,
  4266  							},
  4267  						}),
  4268  						StoragePolicies: policy.StoragePolicies{
  4269  							policy.NewStoragePolicy(10*time.Second, xtime.Second, 12*time.Hour),
  4270  							policy.NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour),
  4271  							policy.NewStoragePolicy(5*time.Minute, xtime.Minute, 48*time.Hour),
  4272  						},
  4273  					},
  4274  					{
  4275  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4276  							{
  4277  								Type:   pipeline.RollupOpType,
  4278  								Rollup: rr3_2,
  4279  							},
  4280  						}),
  4281  						StoragePolicies: policy.StoragePolicies{
  4282  							policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour),
  4283  						},
  4284  					},
  4285  				},
  4286  			},
  4287  			{
  4288  				name:         "rollupRule3.snapshot2",
  4289  				tombstoned:   false,
  4290  				cutoverNanos: 34000,
  4291  				filter:       filter1,
  4292  				targets: []rollupTarget{
  4293  					{
  4294  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4295  							{
  4296  								Type:   pipeline.RollupOpType,
  4297  								Rollup: rr3,
  4298  							},
  4299  						}),
  4300  						StoragePolicies: policy.StoragePolicies{
  4301  							policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  4302  							policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  4303  						},
  4304  					},
  4305  				},
  4306  			},
  4307  			{
  4308  				name:         "rollupRule3.snapshot3",
  4309  				tombstoned:   true,
  4310  				cutoverNanos: 38000,
  4311  				filter:       filter1,
  4312  				targets: []rollupTarget{
  4313  					{
  4314  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4315  							{
  4316  								Type:   pipeline.RollupOpType,
  4317  								Rollup: rr3,
  4318  							},
  4319  						}),
  4320  						StoragePolicies: policy.StoragePolicies{
  4321  							policy.NewStoragePolicy(10*time.Second, xtime.Second, 2*time.Hour),
  4322  							policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  4323  						},
  4324  					},
  4325  				},
  4326  			},
  4327  		},
  4328  	}
  4329  
  4330  	rollupRule4 := &rollupRule{
  4331  		uuid: "rollupRule4",
  4332  		snapshots: []*rollupRuleSnapshot{
  4333  			{
  4334  				name:         "rollupRule4.snapshot1",
  4335  				tombstoned:   false,
  4336  				cutoverNanos: 24000,
  4337  				filter:       filter2,
  4338  				targets: []rollupTarget{
  4339  					{
  4340  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4341  							{
  4342  								Type:   pipeline.RollupOpType,
  4343  								Rollup: rr4,
  4344  							},
  4345  						}),
  4346  						StoragePolicies: policy.StoragePolicies{
  4347  							policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  4348  						},
  4349  					},
  4350  				},
  4351  			},
  4352  		},
  4353  	}
  4354  
  4355  	rollupRule5 := &rollupRule{
  4356  		uuid: "rollupRule5",
  4357  		snapshots: []*rollupRuleSnapshot{
  4358  			{
  4359  				name:               "rollupRule5.snapshot1",
  4360  				tombstoned:         false,
  4361  				cutoverNanos:       24000,
  4362  				filter:             filter2,
  4363  				lastUpdatedAtNanos: 123456,
  4364  				lastUpdatedBy:      "test",
  4365  				targets: []rollupTarget{
  4366  					{
  4367  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4368  							{
  4369  								Type:   pipeline.RollupOpType,
  4370  								Rollup: rr5,
  4371  							},
  4372  						}),
  4373  						StoragePolicies: policy.StoragePolicies{
  4374  							policy.NewStoragePolicy(time.Second, xtime.Second, time.Minute),
  4375  						},
  4376  					},
  4377  				},
  4378  			},
  4379  		},
  4380  	}
  4381  
  4382  	rollupRule6 := &rollupRule{
  4383  		uuid: "rollupRule6",
  4384  		snapshots: []*rollupRuleSnapshot{
  4385  			{
  4386  				name:         "rollupRule6.snapshot1",
  4387  				tombstoned:   false,
  4388  				cutoverNanos: 100000,
  4389  				filter:       filter1,
  4390  				targets: []rollupTarget{
  4391  					{
  4392  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4393  							{
  4394  								Type:   pipeline.RollupOpType,
  4395  								Rollup: rr6,
  4396  							},
  4397  						}),
  4398  						StoragePolicies: policy.StoragePolicies{
  4399  							policy.NewStoragePolicy(time.Minute, xtime.Minute, time.Hour),
  4400  						},
  4401  					},
  4402  				},
  4403  			},
  4404  		},
  4405  	}
  4406  
  4407  	rollupRule7 := &rollupRule{
  4408  		uuid: "rollupRule7",
  4409  		snapshots: []*rollupRuleSnapshot{
  4410  			{
  4411  				name:               "rollupRule7.snapshot1",
  4412  				tombstoned:         false,
  4413  				cutoverNanos:       120000,
  4414  				filter:             filter2,
  4415  				lastUpdatedAtNanos: 125000,
  4416  				lastUpdatedBy:      "test",
  4417  				targets: []rollupTarget{
  4418  					{
  4419  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4420  							{
  4421  								Type:   pipeline.RollupOpType,
  4422  								Rollup: rr7,
  4423  							},
  4424  						}),
  4425  						StoragePolicies: policy.StoragePolicies{
  4426  							policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  4427  							policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  4428  						},
  4429  					},
  4430  				},
  4431  			},
  4432  		},
  4433  	}
  4434  
  4435  	rollupRule8 := &rollupRule{
  4436  		uuid: "rollupRule8",
  4437  		snapshots: []*rollupRuleSnapshot{
  4438  			{
  4439  				name:               "rollupRule8.snapshot1",
  4440  				tombstoned:         false,
  4441  				cutoverNanos:       90000,
  4442  				filter:             filter2,
  4443  				lastUpdatedAtNanos: 95000,
  4444  				lastUpdatedBy:      "test",
  4445  				targets: []rollupTarget{
  4446  					{
  4447  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4448  							{
  4449  								Type:   pipeline.RollupOpType,
  4450  								Rollup: rr8,
  4451  							},
  4452  							{
  4453  								Type:   pipeline.RollupOpType,
  4454  								Rollup: rr8_2,
  4455  							},
  4456  							{
  4457  								Type:   pipeline.RollupOpType,
  4458  								Rollup: rr8_3,
  4459  							},
  4460  						}),
  4461  						StoragePolicies: policy.StoragePolicies{
  4462  							policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  4463  							policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  4464  						},
  4465  					},
  4466  				},
  4467  			},
  4468  		},
  4469  	}
  4470  
  4471  	rollupRule9 := &rollupRule{
  4472  		uuid: "rollupRule9",
  4473  		snapshots: []*rollupRuleSnapshot{
  4474  			{
  4475  				name:               "rollupRule9.snapshot1",
  4476  				tombstoned:         false,
  4477  				cutoverNanos:       100000,
  4478  				filter:             filter3,
  4479  				lastUpdatedAtNanos: 105000,
  4480  				lastUpdatedBy:      "test",
  4481  				targets: []rollupTarget{
  4482  					{
  4483  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4484  							{
  4485  								Type:   pipeline.RollupOpType,
  4486  								Rollup: rr9,
  4487  							},
  4488  						}),
  4489  						StoragePolicies: policy.StoragePolicies{
  4490  							policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  4491  							policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  4492  						},
  4493  					},
  4494  				},
  4495  			},
  4496  		},
  4497  	}
  4498  
  4499  	rollupRule10 := &rollupRule{
  4500  		uuid: "rollupRule10",
  4501  		snapshots: []*rollupRuleSnapshot{
  4502  			{
  4503  				name:               "rollupRule10.snapshot1",
  4504  				tombstoned:         false,
  4505  				cutoverNanos:       100000,
  4506  				filter:             filter3,
  4507  				lastUpdatedAtNanos: 105000,
  4508  				lastUpdatedBy:      "test",
  4509  				targets: []rollupTarget{
  4510  					{
  4511  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4512  							{
  4513  								Type:   pipeline.RollupOpType,
  4514  								Rollup: rr10,
  4515  							},
  4516  						}),
  4517  						StoragePolicies: policy.StoragePolicies{
  4518  							policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  4519  							policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  4520  						},
  4521  					},
  4522  				},
  4523  			},
  4524  		},
  4525  	}
  4526  
  4527  	rollupRule11 := &rollupRule{
  4528  		uuid: "rollupRule11",
  4529  		snapshots: []*rollupRuleSnapshot{
  4530  			{
  4531  				name:               "rollupRule11.snapshot1",
  4532  				tombstoned:         false,
  4533  				cutoverNanos:       100000,
  4534  				filter:             filter3,
  4535  				lastUpdatedAtNanos: 105000,
  4536  				lastUpdatedBy:      "test",
  4537  				targets: []rollupTarget{
  4538  					{
  4539  						Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{
  4540  							{
  4541  								Type:   pipeline.RollupOpType,
  4542  								Rollup: rr11,
  4543  							},
  4544  						}),
  4545  						StoragePolicies: policy.StoragePolicies{
  4546  							policy.NewStoragePolicy(time.Second, xtime.Second, time.Hour),
  4547  							policy.NewStoragePolicy(time.Minute, xtime.Second, 10*time.Hour),
  4548  						},
  4549  					},
  4550  				},
  4551  			},
  4552  		},
  4553  	}
  4554  
  4555  	return []*rollupRule{
  4556  		rollupRule1,
  4557  		rollupRule2,
  4558  		rollupRule3,
  4559  		rollupRule4,
  4560  		rollupRule5,
  4561  		rollupRule6,
  4562  		rollupRule7,
  4563  		rollupRule8,
  4564  		rollupRule9,
  4565  		rollupRule10,
  4566  		rollupRule11,
  4567  	}
  4568  }