...

Source file src/github.com/prometheus/alertmanager/dispatch/route_test.go

Documentation: github.com/prometheus/alertmanager/dispatch

     1  // Copyright 2015 Prometheus Team
     2  // Licensed under the Apache License, Version 2.0 (the "License");
     3  // you may not use this file except in compliance with the License.
     4  // You may obtain a copy of the License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package dispatch
    15  
    16  import (
    17  	"reflect"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/prometheus/common/model"
    22  	"github.com/stretchr/testify/require"
    23  	"gopkg.in/yaml.v2"
    24  
    25  	"github.com/prometheus/alertmanager/config"
    26  )
    27  
    28  func TestRouteMatch(t *testing.T) {
    29  	in := `
    30  receiver: 'notify-def'
    31  
    32  routes:
    33  - match:
    34      owner: 'team-A'
    35  
    36    receiver: 'notify-A'
    37  
    38    routes:
    39    - match:
    40        env: 'testing'
    41  
    42      receiver: 'notify-testing'
    43      group_by: [...]
    44  
    45    - match:
    46        env: "production"
    47  
    48      receiver: 'notify-productionA'
    49      group_wait: 1m
    50  
    51      continue: true
    52  
    53    - match_re:
    54        env: "produ.*"
    55        job: ".*"
    56  
    57      receiver: 'notify-productionB'
    58      group_wait: 30s
    59      group_interval: 5m
    60      repeat_interval: 1h
    61      group_by: ['job']
    62  
    63  - match_re:
    64      owner: 'team-(B|C)'
    65  
    66    group_by: ['foo', 'bar']
    67    group_wait: 2m
    68    receiver: 'notify-BC'
    69  
    70  - match:
    71      group_by: 'role'
    72    group_by: ['role']
    73  
    74    routes:
    75    - match:
    76        env: 'testing'
    77      receiver: 'notify-testing'
    78      routes:
    79      - match:
    80          wait: 'long'
    81        group_wait: 2m
    82  `
    83  
    84  	var ctree config.Route
    85  	if err := yaml.UnmarshalStrict([]byte(in), &ctree); err != nil {
    86  		t.Fatal(err)
    87  	}
    88  	var (
    89  		def  = DefaultRouteOpts
    90  		tree = NewRoute(&ctree, nil)
    91  	)
    92  	lset := func(labels ...string) map[model.LabelName]struct{} {
    93  		s := map[model.LabelName]struct{}{}
    94  		for _, ls := range labels {
    95  			s[model.LabelName(ls)] = struct{}{}
    96  		}
    97  		return s
    98  	}
    99  
   100  	tests := []struct {
   101  		input  model.LabelSet
   102  		result []*RouteOpts
   103  		keys   []string
   104  	}{
   105  		{
   106  			input: model.LabelSet{
   107  				"owner": "team-A",
   108  			},
   109  			result: []*RouteOpts{
   110  				{
   111  					Receiver:       "notify-A",
   112  					GroupBy:        def.GroupBy,
   113  					GroupByAll:     false,
   114  					GroupWait:      def.GroupWait,
   115  					GroupInterval:  def.GroupInterval,
   116  					RepeatInterval: def.RepeatInterval,
   117  				},
   118  			},
   119  			keys: []string{"{}/{owner=\"team-A\"}"},
   120  		},
   121  		{
   122  			input: model.LabelSet{
   123  				"owner": "team-A",
   124  				"env":   "unset",
   125  			},
   126  			result: []*RouteOpts{
   127  				{
   128  					Receiver:       "notify-A",
   129  					GroupBy:        def.GroupBy,
   130  					GroupByAll:     false,
   131  					GroupWait:      def.GroupWait,
   132  					GroupInterval:  def.GroupInterval,
   133  					RepeatInterval: def.RepeatInterval,
   134  				},
   135  			},
   136  			keys: []string{"{}/{owner=\"team-A\"}"},
   137  		},
   138  		{
   139  			input: model.LabelSet{
   140  				"owner": "team-C",
   141  			},
   142  			result: []*RouteOpts{
   143  				{
   144  					Receiver:       "notify-BC",
   145  					GroupBy:        lset("foo", "bar"),
   146  					GroupByAll:     false,
   147  					GroupWait:      2 * time.Minute,
   148  					GroupInterval:  def.GroupInterval,
   149  					RepeatInterval: def.RepeatInterval,
   150  				},
   151  			},
   152  			keys: []string{"{}/{owner=~\"^(?:team-(B|C))$\"}"},
   153  		},
   154  		{
   155  			input: model.LabelSet{
   156  				"owner": "team-A",
   157  				"env":   "testing",
   158  			},
   159  			result: []*RouteOpts{
   160  				{
   161  					Receiver:       "notify-testing",
   162  					GroupBy:        lset(),
   163  					GroupByAll:     true,
   164  					GroupWait:      def.GroupWait,
   165  					GroupInterval:  def.GroupInterval,
   166  					RepeatInterval: def.RepeatInterval,
   167  				},
   168  			},
   169  			keys: []string{"{}/{owner=\"team-A\"}/{env=\"testing\"}"},
   170  		},
   171  		{
   172  			input: model.LabelSet{
   173  				"owner": "team-A",
   174  				"env":   "production",
   175  			},
   176  			result: []*RouteOpts{
   177  				{
   178  					Receiver:       "notify-productionA",
   179  					GroupBy:        def.GroupBy,
   180  					GroupByAll:     false,
   181  					GroupWait:      1 * time.Minute,
   182  					GroupInterval:  def.GroupInterval,
   183  					RepeatInterval: def.RepeatInterval,
   184  				},
   185  				{
   186  					Receiver:       "notify-productionB",
   187  					GroupBy:        lset("job"),
   188  					GroupByAll:     false,
   189  					GroupWait:      30 * time.Second,
   190  					GroupInterval:  5 * time.Minute,
   191  					RepeatInterval: 1 * time.Hour,
   192  				},
   193  			},
   194  			keys: []string{
   195  				"{}/{owner=\"team-A\"}/{env=\"production\"}",
   196  				"{}/{owner=\"team-A\"}/{env=~\"^(?:produ.*)$\",job=~\"^(?:.*)$\"}",
   197  			},
   198  		},
   199  		{
   200  			input: model.LabelSet{
   201  				"group_by": "role",
   202  			},
   203  			result: []*RouteOpts{
   204  				{
   205  					Receiver:       "notify-def",
   206  					GroupBy:        lset("role"),
   207  					GroupByAll:     false,
   208  					GroupWait:      def.GroupWait,
   209  					GroupInterval:  def.GroupInterval,
   210  					RepeatInterval: def.RepeatInterval,
   211  				},
   212  			},
   213  			keys: []string{"{}/{group_by=\"role\"}"},
   214  		},
   215  		{
   216  			input: model.LabelSet{
   217  				"env":      "testing",
   218  				"group_by": "role",
   219  			},
   220  			result: []*RouteOpts{
   221  				{
   222  					Receiver:       "notify-testing",
   223  					GroupBy:        lset("role"),
   224  					GroupByAll:     false,
   225  					GroupWait:      def.GroupWait,
   226  					GroupInterval:  def.GroupInterval,
   227  					RepeatInterval: def.RepeatInterval,
   228  				},
   229  			},
   230  			keys: []string{"{}/{group_by=\"role\"}/{env=\"testing\"}"},
   231  		},
   232  		{
   233  			input: model.LabelSet{
   234  				"env":      "testing",
   235  				"group_by": "role",
   236  				"wait":     "long",
   237  			},
   238  			result: []*RouteOpts{
   239  				{
   240  					Receiver:       "notify-testing",
   241  					GroupBy:        lset("role"),
   242  					GroupByAll:     false,
   243  					GroupWait:      2 * time.Minute,
   244  					GroupInterval:  def.GroupInterval,
   245  					RepeatInterval: def.RepeatInterval,
   246  				},
   247  			},
   248  			keys: []string{"{}/{group_by=\"role\"}/{env=\"testing\"}/{wait=\"long\"}"},
   249  		},
   250  	}
   251  
   252  	for _, test := range tests {
   253  		var matches []*RouteOpts
   254  		var keys []string
   255  
   256  		for _, r := range tree.Match(test.input) {
   257  			matches = append(matches, &r.RouteOpts)
   258  			keys = append(keys, r.Key())
   259  		}
   260  
   261  		if !reflect.DeepEqual(matches, test.result) {
   262  			t.Errorf("\nexpected:\n%v\ngot:\n%v", test.result, matches)
   263  		}
   264  
   265  		if !reflect.DeepEqual(keys, test.keys) {
   266  			t.Errorf("\nexpected:\n%v\ngot:\n%v", test.keys, keys)
   267  		}
   268  	}
   269  }
   270  
   271  func TestRouteWalk(t *testing.T) {
   272  	in := `
   273  receiver: 'notify-def'
   274  
   275  routes:
   276  - match:
   277      owner: 'team-A'
   278  
   279    receiver: 'notify-A'
   280  
   281    routes:
   282    - match:
   283        env: 'testing'
   284  
   285      receiver: 'notify-testing'
   286      group_by: [...]
   287  
   288    - match:
   289        env: "production"
   290  
   291      receiver: 'notify-productionA'
   292      group_wait: 1m
   293  
   294      continue: true
   295  
   296    - match_re:
   297        env: "produ.*"
   298        job: ".*"
   299  
   300      receiver: 'notify-productionB'
   301      group_wait: 30s
   302      group_interval: 5m
   303      repeat_interval: 1h
   304      group_by: ['job']
   305  
   306  
   307  - match_re:
   308      owner: 'team-(B|C)'
   309  
   310    group_by: ['foo', 'bar']
   311    group_wait: 2m
   312    receiver: 'notify-BC'
   313  
   314  - match:
   315      group_by: 'role'
   316    group_by: ['role']
   317  
   318    routes:
   319    - match:
   320        env: 'testing'
   321      receiver: 'notify-testing'
   322      routes:
   323      - match:
   324          wait: 'long'
   325        group_wait: 2m
   326  `
   327  
   328  	var ctree config.Route
   329  	if err := yaml.UnmarshalStrict([]byte(in), &ctree); err != nil {
   330  		t.Fatal(err)
   331  	}
   332  	tree := NewRoute(&ctree, nil)
   333  
   334  	expected := []string{
   335  		"notify-def",
   336  		"notify-A",
   337  		"notify-testing",
   338  		"notify-productionA",
   339  		"notify-productionB",
   340  		"notify-BC",
   341  		"notify-def",
   342  		"notify-testing",
   343  		"notify-testing",
   344  	}
   345  
   346  	var got []string
   347  	tree.Walk(func(r *Route) {
   348  		got = append(got, r.RouteOpts.Receiver)
   349  	})
   350  
   351  	if !reflect.DeepEqual(got, expected) {
   352  		t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, got)
   353  	}
   354  }
   355  
   356  func TestInheritParentGroupByAll(t *testing.T) {
   357  	in := `
   358  routes:
   359  - match:
   360      env: 'parent'
   361    group_by: ['...']
   362  
   363    routes:
   364    - match:
   365        env: 'child1'
   366  
   367    - match:
   368        env: 'child2'
   369      group_by: ['foo']
   370  `
   371  
   372  	var ctree config.Route
   373  	if err := yaml.UnmarshalStrict([]byte(in), &ctree); err != nil {
   374  		t.Fatal(err)
   375  	}
   376  
   377  	tree := NewRoute(&ctree, nil)
   378  	parent := tree.Routes[0]
   379  	child1 := parent.Routes[0]
   380  	child2 := parent.Routes[1]
   381  	require.Equal(t, parent.RouteOpts.GroupByAll, true)
   382  	require.Equal(t, child1.RouteOpts.GroupByAll, true)
   383  	require.Equal(t, child2.RouteOpts.GroupByAll, false)
   384  }
   385  
   386  func TestRouteMatchers(t *testing.T) {
   387  	in := `
   388  receiver: 'notify-def'
   389  
   390  routes:
   391  - matchers: ['{owner="team-A"}', '{level!="critical"}']
   392  
   393    receiver: 'notify-A'
   394  
   395    routes:
   396    - matchers: ['{env="testing"}', '{baz!~".*quux"}']
   397  
   398      receiver: 'notify-testing'
   399      group_by: [...]
   400  
   401    - matchers: ['{env="production"}']
   402  
   403      receiver: 'notify-productionA'
   404      group_wait: 1m
   405  
   406      continue: true
   407  
   408    - matchers: [ env=~"produ.*", job=~".*"]
   409  
   410      receiver: 'notify-productionB'
   411      group_wait: 30s
   412      group_interval: 5m
   413      repeat_interval: 1h
   414      group_by: ['job']
   415  
   416  
   417  - matchers: [owner=~"team-(B|C)"]
   418  
   419    group_by: ['foo', 'bar']
   420    group_wait: 2m
   421    receiver: 'notify-BC'
   422  
   423  - matchers: [group_by="role"]
   424    group_by: ['role']
   425  
   426    routes:
   427    - matchers: ['{env="testing"}']
   428      receiver: 'notify-testing'
   429      routes:
   430      - matchers: [wait="long"]
   431        group_wait: 2m
   432  `
   433  
   434  	var ctree config.Route
   435  	if err := yaml.UnmarshalStrict([]byte(in), &ctree); err != nil {
   436  		t.Fatal(err)
   437  	}
   438  	var (
   439  		def  = DefaultRouteOpts
   440  		tree = NewRoute(&ctree, nil)
   441  	)
   442  	lset := func(labels ...string) map[model.LabelName]struct{} {
   443  		s := map[model.LabelName]struct{}{}
   444  		for _, ls := range labels {
   445  			s[model.LabelName(ls)] = struct{}{}
   446  		}
   447  		return s
   448  	}
   449  
   450  	tests := []struct {
   451  		input  model.LabelSet
   452  		result []*RouteOpts
   453  		keys   []string
   454  	}{
   455  		{
   456  			input: model.LabelSet{
   457  				"owner": "team-A",
   458  			},
   459  			result: []*RouteOpts{
   460  				{
   461  					Receiver:       "notify-A",
   462  					GroupBy:        def.GroupBy,
   463  					GroupByAll:     false,
   464  					GroupWait:      def.GroupWait,
   465  					GroupInterval:  def.GroupInterval,
   466  					RepeatInterval: def.RepeatInterval,
   467  				},
   468  			},
   469  			keys: []string{"{}/{level!=\"critical\",owner=\"team-A\"}"},
   470  		},
   471  		{
   472  			input: model.LabelSet{
   473  				"owner": "team-A",
   474  				"env":   "unset",
   475  			},
   476  			result: []*RouteOpts{
   477  				{
   478  					Receiver:       "notify-A",
   479  					GroupBy:        def.GroupBy,
   480  					GroupByAll:     false,
   481  					GroupWait:      def.GroupWait,
   482  					GroupInterval:  def.GroupInterval,
   483  					RepeatInterval: def.RepeatInterval,
   484  				},
   485  			},
   486  			keys: []string{"{}/{level!=\"critical\",owner=\"team-A\"}"},
   487  		},
   488  		{
   489  			input: model.LabelSet{
   490  				"owner": "team-C",
   491  			},
   492  			result: []*RouteOpts{
   493  				{
   494  					Receiver:       "notify-BC",
   495  					GroupBy:        lset("foo", "bar"),
   496  					GroupByAll:     false,
   497  					GroupWait:      2 * time.Minute,
   498  					GroupInterval:  def.GroupInterval,
   499  					RepeatInterval: def.RepeatInterval,
   500  				},
   501  			},
   502  			keys: []string{"{}/{owner=~\"team-(B|C)\"}"},
   503  		},
   504  		{
   505  			input: model.LabelSet{
   506  				"owner": "team-A",
   507  				"env":   "testing",
   508  			},
   509  			result: []*RouteOpts{
   510  				{
   511  					Receiver:       "notify-testing",
   512  					GroupBy:        lset(),
   513  					GroupByAll:     true,
   514  					GroupWait:      def.GroupWait,
   515  					GroupInterval:  def.GroupInterval,
   516  					RepeatInterval: def.RepeatInterval,
   517  				},
   518  			},
   519  			keys: []string{"{}/{level!=\"critical\",owner=\"team-A\"}/{baz!~\".*quux\",env=\"testing\"}"},
   520  		},
   521  		{
   522  			input: model.LabelSet{
   523  				"owner": "team-A",
   524  				"env":   "production",
   525  			},
   526  			result: []*RouteOpts{
   527  				{
   528  					Receiver:       "notify-productionA",
   529  					GroupBy:        def.GroupBy,
   530  					GroupByAll:     false,
   531  					GroupWait:      1 * time.Minute,
   532  					GroupInterval:  def.GroupInterval,
   533  					RepeatInterval: def.RepeatInterval,
   534  				},
   535  				{
   536  					Receiver:       "notify-productionB",
   537  					GroupBy:        lset("job"),
   538  					GroupByAll:     false,
   539  					GroupWait:      30 * time.Second,
   540  					GroupInterval:  5 * time.Minute,
   541  					RepeatInterval: 1 * time.Hour,
   542  				},
   543  			},
   544  			keys: []string{
   545  				"{}/{level!=\"critical\",owner=\"team-A\"}/{env=\"production\"}",
   546  				"{}/{level!=\"critical\",owner=\"team-A\"}/{env=~\"produ.*\",job=~\".*\"}",
   547  			},
   548  		},
   549  		{
   550  			input: model.LabelSet{
   551  				"group_by": "role",
   552  			},
   553  			result: []*RouteOpts{
   554  				{
   555  					Receiver:       "notify-def",
   556  					GroupBy:        lset("role"),
   557  					GroupByAll:     false,
   558  					GroupWait:      def.GroupWait,
   559  					GroupInterval:  def.GroupInterval,
   560  					RepeatInterval: def.RepeatInterval,
   561  				},
   562  			},
   563  			keys: []string{"{}/{group_by=\"role\"}"},
   564  		},
   565  		{
   566  			input: model.LabelSet{
   567  				"env":      "testing",
   568  				"group_by": "role",
   569  			},
   570  			result: []*RouteOpts{
   571  				{
   572  					Receiver:       "notify-testing",
   573  					GroupBy:        lset("role"),
   574  					GroupByAll:     false,
   575  					GroupWait:      def.GroupWait,
   576  					GroupInterval:  def.GroupInterval,
   577  					RepeatInterval: def.RepeatInterval,
   578  				},
   579  			},
   580  			keys: []string{"{}/{group_by=\"role\"}/{env=\"testing\"}"},
   581  		},
   582  		{
   583  			input: model.LabelSet{
   584  				"env":      "testing",
   585  				"group_by": "role",
   586  				"wait":     "long",
   587  			},
   588  			result: []*RouteOpts{
   589  				{
   590  					Receiver:       "notify-testing",
   591  					GroupBy:        lset("role"),
   592  					GroupByAll:     false,
   593  					GroupWait:      2 * time.Minute,
   594  					GroupInterval:  def.GroupInterval,
   595  					RepeatInterval: def.RepeatInterval,
   596  				},
   597  			},
   598  			keys: []string{"{}/{group_by=\"role\"}/{env=\"testing\"}/{wait=\"long\"}"},
   599  		},
   600  	}
   601  
   602  	for _, test := range tests {
   603  		var matches []*RouteOpts
   604  		var keys []string
   605  
   606  		for _, r := range tree.Match(test.input) {
   607  			matches = append(matches, &r.RouteOpts)
   608  			keys = append(keys, r.Key())
   609  		}
   610  
   611  		if !reflect.DeepEqual(matches, test.result) {
   612  			t.Errorf("\nexpected:\n%v\ngot:\n%v", test.result, matches)
   613  		}
   614  
   615  		if !reflect.DeepEqual(keys, test.keys) {
   616  			t.Errorf("\nexpected:\n%v\ngot:\n%v", test.keys, keys)
   617  		}
   618  	}
   619  }
   620  
   621  func TestRouteMatchersAndMatch(t *testing.T) {
   622  	in := `
   623  receiver: 'notify-def'
   624  
   625  routes:
   626  - matchers: ['{owner="team-A"}', '{level!="critical"}']
   627  
   628    receiver: 'notify-A'
   629  
   630    routes:
   631    - matchers: ['{env="testing"}', '{baz!~".*quux"}']
   632  
   633      receiver: 'notify-testing'
   634      group_by: [...]
   635  
   636    - match:
   637        env: "production"
   638  
   639      receiver: 'notify-productionA'
   640      group_wait: 1m
   641  
   642      continue: true
   643  
   644    - matchers: [ env=~"produ.*", job=~".*"]
   645  
   646      receiver: 'notify-productionB'
   647      group_wait: 30s
   648      group_interval: 5m
   649      repeat_interval: 1h
   650      group_by: ['job']
   651  
   652  - match_re:
   653      owner: 'team-(B|C)'
   654  
   655    group_by: ['foo', 'bar']
   656    group_wait: 2m
   657    receiver: 'notify-BC'
   658  
   659  - matchers: [group_by="role"]
   660    group_by: ['role']
   661  
   662    routes:
   663    - matchers: ['{env="testing"}']
   664      receiver: 'notify-testing'
   665      routes:
   666      - matchers: [wait="long"]
   667        group_wait: 2m
   668  `
   669  
   670  	var ctree config.Route
   671  	if err := yaml.UnmarshalStrict([]byte(in), &ctree); err != nil {
   672  		t.Fatal(err)
   673  	}
   674  	var (
   675  		def  = DefaultRouteOpts
   676  		tree = NewRoute(&ctree, nil)
   677  	)
   678  	lset := func(labels ...string) map[model.LabelName]struct{} {
   679  		s := map[model.LabelName]struct{}{}
   680  		for _, ls := range labels {
   681  			s[model.LabelName(ls)] = struct{}{}
   682  		}
   683  		return s
   684  	}
   685  
   686  	tests := []struct {
   687  		input  model.LabelSet
   688  		result []*RouteOpts
   689  		keys   []string
   690  	}{
   691  		{
   692  			input: model.LabelSet{
   693  				"owner": "team-A",
   694  			},
   695  			result: []*RouteOpts{
   696  				{
   697  					Receiver:       "notify-A",
   698  					GroupBy:        def.GroupBy,
   699  					GroupByAll:     false,
   700  					GroupWait:      def.GroupWait,
   701  					GroupInterval:  def.GroupInterval,
   702  					RepeatInterval: def.RepeatInterval,
   703  				},
   704  			},
   705  			keys: []string{"{}/{level!=\"critical\",owner=\"team-A\"}"},
   706  		},
   707  		{
   708  			input: model.LabelSet{
   709  				"owner": "team-A",
   710  				"env":   "unset",
   711  			},
   712  			result: []*RouteOpts{
   713  				{
   714  					Receiver:       "notify-A",
   715  					GroupBy:        def.GroupBy,
   716  					GroupByAll:     false,
   717  					GroupWait:      def.GroupWait,
   718  					GroupInterval:  def.GroupInterval,
   719  					RepeatInterval: def.RepeatInterval,
   720  				},
   721  			},
   722  			keys: []string{"{}/{level!=\"critical\",owner=\"team-A\"}"},
   723  		},
   724  		{
   725  			input: model.LabelSet{
   726  				"owner": "team-C",
   727  			},
   728  			result: []*RouteOpts{
   729  				{
   730  					Receiver:       "notify-BC",
   731  					GroupBy:        lset("foo", "bar"),
   732  					GroupByAll:     false,
   733  					GroupWait:      2 * time.Minute,
   734  					GroupInterval:  def.GroupInterval,
   735  					RepeatInterval: def.RepeatInterval,
   736  				},
   737  			},
   738  			keys: []string{"{}/{owner=~\"^(?:team-(B|C))$\"}"},
   739  		},
   740  		{
   741  			input: model.LabelSet{
   742  				"owner": "team-A",
   743  				"env":   "testing",
   744  			},
   745  			result: []*RouteOpts{
   746  				{
   747  					Receiver:       "notify-testing",
   748  					GroupBy:        lset(),
   749  					GroupByAll:     true,
   750  					GroupWait:      def.GroupWait,
   751  					GroupInterval:  def.GroupInterval,
   752  					RepeatInterval: def.RepeatInterval,
   753  				},
   754  			},
   755  			keys: []string{"{}/{level!=\"critical\",owner=\"team-A\"}/{baz!~\".*quux\",env=\"testing\"}"},
   756  		},
   757  		{
   758  			input: model.LabelSet{
   759  				"owner": "team-A",
   760  				"env":   "production",
   761  			},
   762  			result: []*RouteOpts{
   763  				{
   764  					Receiver:       "notify-productionA",
   765  					GroupBy:        def.GroupBy,
   766  					GroupByAll:     false,
   767  					GroupWait:      1 * time.Minute,
   768  					GroupInterval:  def.GroupInterval,
   769  					RepeatInterval: def.RepeatInterval,
   770  				},
   771  				{
   772  					Receiver:       "notify-productionB",
   773  					GroupBy:        lset("job"),
   774  					GroupByAll:     false,
   775  					GroupWait:      30 * time.Second,
   776  					GroupInterval:  5 * time.Minute,
   777  					RepeatInterval: 1 * time.Hour,
   778  				},
   779  			},
   780  			keys: []string{
   781  				"{}/{level!=\"critical\",owner=\"team-A\"}/{env=\"production\"}",
   782  				"{}/{level!=\"critical\",owner=\"team-A\"}/{env=~\"produ.*\",job=~\".*\"}",
   783  			},
   784  		},
   785  		{
   786  			input: model.LabelSet{
   787  				"group_by": "role",
   788  			},
   789  			result: []*RouteOpts{
   790  				{
   791  					Receiver:       "notify-def",
   792  					GroupBy:        lset("role"),
   793  					GroupByAll:     false,
   794  					GroupWait:      def.GroupWait,
   795  					GroupInterval:  def.GroupInterval,
   796  					RepeatInterval: def.RepeatInterval,
   797  				},
   798  			},
   799  			keys: []string{"{}/{group_by=\"role\"}"},
   800  		},
   801  		{
   802  			input: model.LabelSet{
   803  				"env":      "testing",
   804  				"group_by": "role",
   805  			},
   806  			result: []*RouteOpts{
   807  				{
   808  					Receiver:       "notify-testing",
   809  					GroupBy:        lset("role"),
   810  					GroupByAll:     false,
   811  					GroupWait:      def.GroupWait,
   812  					GroupInterval:  def.GroupInterval,
   813  					RepeatInterval: def.RepeatInterval,
   814  				},
   815  			},
   816  			keys: []string{"{}/{group_by=\"role\"}/{env=\"testing\"}"},
   817  		},
   818  		{
   819  			input: model.LabelSet{
   820  				"env":      "testing",
   821  				"group_by": "role",
   822  				"wait":     "long",
   823  			},
   824  			result: []*RouteOpts{
   825  				{
   826  					Receiver:       "notify-testing",
   827  					GroupBy:        lset("role"),
   828  					GroupByAll:     false,
   829  					GroupWait:      2 * time.Minute,
   830  					GroupInterval:  def.GroupInterval,
   831  					RepeatInterval: def.RepeatInterval,
   832  				},
   833  			},
   834  			keys: []string{"{}/{group_by=\"role\"}/{env=\"testing\"}/{wait=\"long\"}"},
   835  		},
   836  	}
   837  
   838  	for _, test := range tests {
   839  		var matches []*RouteOpts
   840  		var keys []string
   841  
   842  		for _, r := range tree.Match(test.input) {
   843  			matches = append(matches, &r.RouteOpts)
   844  			keys = append(keys, r.Key())
   845  		}
   846  
   847  		if !reflect.DeepEqual(matches, test.result) {
   848  			t.Errorf("\nexpected:\n%v\ngot:\n%v", test.result, matches)
   849  		}
   850  
   851  		if !reflect.DeepEqual(keys, test.keys) {
   852  			t.Errorf("\nexpected:\n%v\ngot:\n%v", test.keys, keys)
   853  		}
   854  	}
   855  }
   856  

View as plain text