2016-06-04 08:05:54 +00:00
// Copyright 2016 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
2017-06-08 11:14:37 +00:00
"encoding/json"
2018-07-26 10:39:33 +00:00
"net/url"
2019-10-25 09:44:45 +00:00
"os"
2017-06-20 17:09:14 +00:00
"reflect"
2017-06-06 11:02:49 +00:00
"regexp"
"strings"
2016-06-04 08:05:54 +00:00
"testing"
2017-06-20 17:09:14 +00:00
"time"
2016-06-04 08:05:54 +00:00
2017-07-27 08:48:24 +00:00
commoncfg "github.com/prometheus/common/config"
2017-06-20 17:09:14 +00:00
"github.com/prometheus/common/model"
2017-06-08 11:14:37 +00:00
"github.com/stretchr/testify/require"
2021-06-15 03:14:12 +00:00
"gopkg.in/yaml.v2"
2016-06-04 08:05:54 +00:00
)
2017-10-19 19:00:35 +00:00
func TestLoadEmptyString ( t * testing . T ) {
var in string
_ , err := Load ( in )
expected := "no route provided in config"
if err == nil {
t . Fatalf ( "no error returned, expected:\n%v" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%v\ngot:\n%v" , expected , err . Error ( ) )
}
}
2016-06-04 08:05:54 +00:00
func TestDefaultReceiverExists ( t * testing . T ) {
in := `
route :
group_wait : 30 s
`
2018-05-07 16:12:14 +00:00
_ , err := Load ( in )
2016-06-04 08:05:54 +00:00
2018-05-07 16:12:14 +00:00
expected := "root route must specify a default receiver"
2016-06-04 08:05:54 +00:00
if err == nil {
t . Fatalf ( "no error returned, expected:\n%v" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%v\ngot:\n%v" , expected , err . Error ( ) )
}
}
2017-05-09 08:11:40 +00:00
2017-10-19 19:00:35 +00:00
func TestReceiverNameIsUnique ( t * testing . T ) {
in := `
route :
receiver : team - X
receivers :
- name : ' team - X '
- name : ' team - X '
`
_ , err := Load ( in )
expected := "notification config name \"team-X\" is not unique"
if err == nil {
2018-02-09 09:53:46 +00:00
t . Fatalf ( "no error returned, expected:\n%q" , expected )
2017-10-19 19:00:35 +00:00
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
func TestReceiverExists ( t * testing . T ) {
in := `
route :
receiver : team - X
receivers :
- name : ' team - Y '
`
_ , err := Load ( in )
expected := "undefined receiver \"team-X\" used in route"
if err == nil {
2018-02-09 09:53:46 +00:00
t . Fatalf ( "no error returned, expected:\n%q" , expected )
2017-10-19 19:00:35 +00:00
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2019-03-02 11:33:40 +00:00
func TestReceiverExistsForDeepSubRoute ( t * testing . T ) {
in := `
route :
receiver : team - X
routes :
- match :
foo : bar
routes :
- match :
foo : bar
receiver : nonexistent
receivers :
- name : ' team - X '
`
_ , err := Load ( in )
expected := "undefined receiver \"nonexistent\" used in route"
if err == nil {
t . Fatalf ( "no error returned, expected:\n%q" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2017-10-19 19:00:35 +00:00
func TestReceiverHasName ( t * testing . T ) {
in := `
route :
receivers :
- name : ' '
`
_ , err := Load ( in )
expected := "missing name in receiver"
if err == nil {
2018-02-09 09:53:46 +00:00
t . Fatalf ( "no error returned, expected:\n%q" , expected )
2017-10-19 19:00:35 +00:00
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2020-10-14 10:26:55 +00:00
func TestMuteTimeExists ( t * testing . T ) {
in := `
route :
receiver : team - Y
routes :
- match :
severity : critical
2020-11-24 04:02:07 +00:00
mute_time_intervals :
2020-10-14 10:26:55 +00:00
- business_hours
receivers :
- name : ' team - Y '
`
_ , err := Load ( in )
expected := "undefined time interval \"business_hours\" used in route"
if err == nil {
t . Fatalf ( "no error returned, expected:\n%q" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2022-03-04 14:24:29 +00:00
func TestActiveTimeExists ( t * testing . T ) {
2020-10-14 10:26:55 +00:00
in := `
2022-03-04 14:24:29 +00:00
route :
receiver : team - Y
routes :
- match :
severity : critical
active_time_intervals :
- business_hours
receivers :
- name : ' team - Y '
`
_ , err := Load ( in )
expected := "undefined time interval \"business_hours\" used in route"
if err == nil {
t . Fatalf ( "no error returned, expected:\n%q" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
func TestTimeIntervalHasName ( t * testing . T ) {
in := `
time_intervals :
2020-10-14 10:26:55 +00:00
- name :
time_intervals :
- times :
- start_time : ' 0 9 : 00 '
end_time : ' 17 : 00 '
receivers :
- name : ' team - X - mails '
route :
receiver : ' team - X - mails '
routes :
- match :
severity : critical
2020-11-24 04:02:07 +00:00
mute_time_intervals :
2020-10-14 10:26:55 +00:00
- business_hours
`
_ , err := Load ( in )
2022-03-04 14:24:29 +00:00
expected := "missing name in time interval"
2020-10-14 10:26:55 +00:00
if err == nil {
t . Fatalf ( "no error returned, expected:\n%q" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2020-11-24 03:38:32 +00:00
func TestMuteTimeNoDuplicates ( t * testing . T ) {
in := `
mute_time_intervals :
- name : duplicate
time_intervals :
- times :
- start_time : ' 0 9 : 00 '
end_time : ' 17 : 00 '
- name : duplicate
time_intervals :
- times :
- start_time : ' 10 : 00 '
end_time : ' 14 : 00 '
receivers :
- name : ' team - X - mails '
route :
receiver : ' team - X - mails '
routes :
- match :
severity : critical
2020-11-24 04:02:07 +00:00
mute_time_intervals :
2020-11-24 03:38:32 +00:00
- business_hours
`
_ , err := Load ( in )
expected := "mute time interval \"duplicate\" is not unique"
if err == nil {
t . Fatalf ( "no error returned, expected:\n%q" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2017-10-19 19:00:35 +00:00
func TestGroupByHasNoDuplicatedLabels ( t * testing . T ) {
in := `
route :
group_by : [ ' alertname ' , ' cluster ' , ' service ' , ' cluster ' ]
receivers :
- name : ' team - X - mails '
`
_ , err := Load ( in )
expected := "duplicated label \"cluster\" in group_by"
if err == nil {
2018-02-09 09:53:46 +00:00
t . Fatalf ( "no error returned, expected:\n%q" , expected )
2017-10-19 19:00:35 +00:00
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2018-11-29 11:31:14 +00:00
func TestWildcardGroupByWithOtherGroupByLabels ( t * testing . T ) {
in := `
route :
group_by : [ ' alertname ' , ' cluster ' , ' ... ' ]
receiver : team - X - mails
receivers :
- name : ' team - X - mails '
`
_ , err := Load ( in )
expected := "cannot have wildcard group_by (`...`) and other other labels at the same time"
if err == nil {
t . Fatalf ( "no error returned, expected:\n%q" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
func TestGroupByInvalidLabel ( t * testing . T ) {
in := `
route :
group_by : [ ' - invalid - ' ]
receiver : team - X - mails
receivers :
- name : ' team - X - mails '
`
_ , err := Load ( in )
expected := "invalid label name \"-invalid-\" in group_by list"
if err == nil {
t . Fatalf ( "no error returned, expected:\n%q" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2017-10-19 19:00:35 +00:00
func TestRootRouteExists ( t * testing . T ) {
in := `
receivers :
- name : ' team - X - mails '
`
_ , err := Load ( in )
expected := "no routes provided"
if err == nil {
2018-02-09 09:53:46 +00:00
t . Fatalf ( "no error returned, expected:\n%q" , expected )
2017-10-19 19:00:35 +00:00
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2020-10-14 10:26:55 +00:00
func TestRootRouteNoMuteTimes ( t * testing . T ) {
in := `
mute_time_intervals :
- name : my_mute_time
time_intervals :
- times :
- start_time : ' 0 9 : 00 '
end_time : ' 17 : 00 '
receivers :
- name : ' team - X - mails '
route :
receiver : ' team - X - mails '
2020-11-24 04:02:07 +00:00
mute_time_intervals :
2020-10-14 10:26:55 +00:00
- my_mute_time
`
_ , err := Load ( in )
2020-12-16 10:33:37 +00:00
expected := "root route must not have any mute time intervals"
2020-10-14 10:26:55 +00:00
if err == nil {
t . Fatalf ( "no error returned, expected:\n%q" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2022-03-04 14:24:29 +00:00
func TestRootRouteNoActiveTimes ( t * testing . T ) {
in := `
time_intervals :
- name : my_active_time
time_intervals :
- times :
- start_time : ' 0 9 : 00 '
end_time : ' 17 : 00 '
receivers :
- name : ' team - X - mails '
route :
receiver : ' team - X - mails '
active_time_intervals :
- my_active_time
`
_ , err := Load ( in )
expected := "root route must not have any active time intervals"
if err == nil {
t . Fatalf ( "no error returned, expected:\n%q" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2017-10-19 19:00:35 +00:00
func TestRootRouteHasNoMatcher ( t * testing . T ) {
2021-12-02 12:08:35 +00:00
testCases := [ ] struct {
name string
in string
} {
{
name : "Test deprecated matchers on root route not allowed" ,
in : `
2017-10-19 19:00:35 +00:00
route :
receiver : ' team - X '
match :
severity : critical
receivers :
- name : ' team - X '
2021-12-02 12:08:35 +00:00
` ,
} ,
{
name : "Test matchers not allowed on root route" ,
in : `
route :
receiver : ' team - X '
matchers :
- severity = critical
receivers :
- name : ' team - X '
` ,
} ,
}
2017-10-19 19:00:35 +00:00
expected := "root route must not have any matchers"
2021-12-02 12:08:35 +00:00
for _ , tc := range testCases {
t . Run ( tc . name , func ( t * testing . T ) {
_ , err := Load ( tc . in )
2017-10-19 19:00:35 +00:00
2021-12-02 12:08:35 +00:00
if err == nil {
t . Fatalf ( "no error returned, expected:\n%q" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
} )
}
2017-10-19 19:00:35 +00:00
}
2017-05-09 08:11:40 +00:00
func TestContinueErrorInRouteRoot ( t * testing . T ) {
in := `
route :
receiver : team - X - mails
continue : true
receivers :
- name : ' team - X - mails '
`
_ , err := Load ( in )
expected := "cannot have continue in root route"
if err == nil {
2018-02-09 09:53:46 +00:00
t . Fatalf ( "no error returned, expected:\n%q" , expected )
2017-05-09 08:11:40 +00:00
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2017-06-06 11:02:49 +00:00
2018-02-09 09:53:46 +00:00
func TestGroupIntervalIsGreaterThanZero ( t * testing . T ) {
in := `
route :
receiver : team - X - mails
group_interval : 0 s
receivers :
- name : ' team - X - mails '
`
_ , err := Load ( in )
expected := "group_interval cannot be zero"
if err == nil {
t . Fatalf ( "no error returned, expected:\n%q" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
func TestRepeatIntervalIsGreaterThanZero ( t * testing . T ) {
in := `
route :
receiver : team - X - mails
repeat_interval : 0 s
receivers :
- name : ' team - X - mails '
`
_ , err := Load ( in )
expected := "repeat_interval cannot be zero"
if err == nil {
t . Fatalf ( "no error returned, expected:\n%q" , expected )
}
if err . Error ( ) != expected {
t . Errorf ( "\nexpected:\n%q\ngot:\n%q" , expected , err . Error ( ) )
}
}
2017-06-06 11:02:49 +00:00
func TestHideConfigSecrets ( t * testing . T ) {
2019-08-26 12:01:40 +00:00
c , err := LoadFile ( "testdata/conf.good.yml" )
2017-06-06 11:02:49 +00:00
if err != nil {
2018-07-26 10:39:33 +00:00
t . Fatalf ( "Error parsing %s: %s" , "testdata/conf.good.yml" , err )
2017-06-06 11:02:49 +00:00
}
// String method must not reveal authentication credentials.
s := c . String ( )
2020-06-11 13:51:10 +00:00
if strings . Count ( s , "<secret>" ) != 13 || strings . Contains ( s , "mysecret" ) {
2017-06-08 11:14:37 +00:00
t . Fatal ( "config's String method reveals authentication credentials." )
}
}
func TestJSONMarshal ( t * testing . T ) {
2019-08-26 12:01:40 +00:00
c , err := LoadFile ( "testdata/conf.good.yml" )
2017-06-08 11:14:37 +00:00
if err != nil {
2017-06-20 17:09:14 +00:00
t . Errorf ( "Error parsing %s: %s" , "testdata/conf.good.yml" , err )
2017-06-08 11:14:37 +00:00
}
_ , err = json . Marshal ( c )
if err != nil {
t . Fatal ( "JSON Marshaling failed:" , err )
}
}
func TestJSONMarshalSecret ( t * testing . T ) {
test := struct {
S Secret
} {
S : Secret ( "test" ) ,
}
c , err := json . Marshal ( test )
if err != nil {
t . Fatal ( err )
2017-06-06 11:02:49 +00:00
}
2017-06-08 11:14:37 +00:00
// u003c -> "<"
// u003e -> ">"
require . Equal ( t , "{\"S\":\"\\u003csecret\\u003e\"}" , string ( c ) , "Secret not properly elided." )
}
2018-07-26 10:39:33 +00:00
func TestMarshalSecretURL ( t * testing . T ) {
urlp , err := url . Parse ( "http://example.com/" )
if err != nil {
t . Fatal ( err )
}
u := & SecretURL { urlp }
2019-12-12 15:35:19 +00:00
c , err := json . Marshal ( u )
2018-07-26 10:39:33 +00:00
if err != nil {
t . Fatal ( err )
}
2019-12-12 15:35:19 +00:00
// u003c -> "<"
// u003e -> ">"
require . Equal ( t , "\"\\u003csecret\\u003e\"" , string ( c ) , "SecretURL not properly elided in JSON." )
2018-12-13 10:09:03 +00:00
// Check that the marshaled data can be unmarshaled again.
2019-10-29 09:45:42 +00:00
out := & SecretURL { }
2019-12-12 15:35:19 +00:00
err = json . Unmarshal ( c , out )
if err != nil {
t . Fatal ( err )
}
c , err = yaml . Marshal ( u )
if err != nil {
t . Fatal ( err )
}
require . Equal ( t , "<secret>\n" , string ( c ) , "SecretURL not properly elided in YAML." )
// Check that the marshaled data can be unmarshaled again.
out = & SecretURL { }
2018-12-13 10:09:03 +00:00
err = yaml . Unmarshal ( c , & out )
if err != nil {
t . Fatal ( err )
}
2018-07-26 10:39:33 +00:00
}
func TestUnmarshalSecretURL ( t * testing . T ) {
b := [ ] byte ( ` "http://example.com/se cret" ` )
var u SecretURL
2019-12-12 15:35:19 +00:00
err := json . Unmarshal ( b , & u )
if err != nil {
t . Fatal ( err )
}
2020-01-23 16:06:16 +00:00
require . Equal ( t , "http://example.com/se%20cret" , u . String ( ) , "SecretURL not properly unmarshaled in JSON." )
2019-12-12 15:35:19 +00:00
err = yaml . Unmarshal ( b , & u )
2018-07-26 10:39:33 +00:00
if err != nil {
t . Fatal ( err )
}
2020-01-23 16:06:16 +00:00
require . Equal ( t , "http://example.com/se%20cret" , u . String ( ) , "SecretURL not properly unmarshaled in YAML." )
2018-07-26 10:39:33 +00:00
}
func TestMarshalURL ( t * testing . T ) {
2021-06-02 07:11:15 +00:00
for name , tc := range map [ string ] struct {
input * URL
expectedJSON string
expectedYAML string
} {
"url" : {
input : mustParseURL ( "http://example.com/" ) ,
expectedJSON : "\"http://example.com/\"" ,
expectedYAML : "http://example.com/\n" ,
} ,
"wrapped nil value" : {
input : & URL { } ,
expectedJSON : "null" ,
expectedYAML : "null\n" ,
} ,
"wrapped empty URL" : {
input : & URL { & url . URL { } } ,
expectedJSON : "\"\"" ,
expectedYAML : "\"\"\n" ,
} ,
} {
t . Run ( name , func ( t * testing . T ) {
j , err := json . Marshal ( tc . input )
require . NoError ( t , err )
2021-06-03 12:16:29 +00:00
require . Equal ( t , tc . expectedJSON , string ( j ) , "URL not properly marshaled into JSON." )
2021-06-02 07:11:15 +00:00
y , err := yaml . Marshal ( tc . input )
require . NoError ( t , err )
2021-06-03 12:16:29 +00:00
require . Equal ( t , tc . expectedYAML , string ( y ) , "URL not properly marshaled into YAML." )
2021-06-02 07:11:15 +00:00
} )
2018-07-26 10:39:33 +00:00
}
2021-06-02 07:11:15 +00:00
}
2018-07-26 10:39:33 +00:00
2021-06-02 07:11:15 +00:00
func TestUnmarshalNilURL ( t * testing . T ) {
b := [ ] byte ( ` null ` )
{
var u URL
err := json . Unmarshal ( b , & u )
require . Error ( t , err , "unsupported scheme \"\" for URL" )
require . Nil ( t , nil , u . URL )
2018-07-26 10:39:33 +00:00
}
2021-06-02 07:11:15 +00:00
{
var u URL
err := yaml . Unmarshal ( b , & u )
require . NoError ( t , err )
require . Nil ( t , nil , u . URL ) // UnmarshalYAML is not even called when unmarshalling "null".
}
}
func TestUnmarshalEmptyURL ( t * testing . T ) {
b := [ ] byte ( ` "" ` )
{
var u URL
err := json . Unmarshal ( b , & u )
require . Error ( t , err , "unsupported scheme \"\" for URL" )
require . Equal ( t , ( * url . URL ) ( nil ) , u . URL )
}
{
var u URL
err := yaml . Unmarshal ( b , & u )
require . Error ( t , err , "unsupported scheme \"\" for URL" )
require . Equal ( t , ( * url . URL ) ( nil ) , u . URL )
2018-07-26 10:39:33 +00:00
}
}
func TestUnmarshalURL ( t * testing . T ) {
b := [ ] byte ( ` "http://example.com/a b" ` )
var u URL
2019-12-12 15:35:19 +00:00
err := json . Unmarshal ( b , & u )
if err != nil {
t . Fatal ( err )
}
2020-01-23 16:06:16 +00:00
require . Equal ( t , "http://example.com/a%20b" , u . String ( ) , "URL not properly unmarshaled in JSON." )
2019-12-12 15:35:19 +00:00
err = yaml . Unmarshal ( b , & u )
2018-07-26 10:39:33 +00:00
if err != nil {
t . Fatal ( err )
}
2020-01-23 16:06:16 +00:00
require . Equal ( t , "http://example.com/a%20b" , u . String ( ) , "URL not properly unmarshaled in YAML." )
2018-07-26 10:39:33 +00:00
}
func TestUnmarshalInvalidURL ( t * testing . T ) {
2018-10-05 17:29:52 +00:00
for _ , b := range [ ] [ ] byte {
[ ] byte ( ` "://example.com" ` ) ,
[ ] byte ( ` "http:example.com" ` ) ,
[ ] byte ( ` "telnet://example.com" ` ) ,
} {
var u URL
2019-12-12 15:35:19 +00:00
err := json . Unmarshal ( b , & u )
if err == nil {
2020-01-23 16:06:16 +00:00
t . Errorf ( "Expected an error unmarshaling %q from JSON" , string ( b ) )
2019-12-12 15:35:19 +00:00
}
err = yaml . Unmarshal ( b , & u )
2018-10-05 17:29:52 +00:00
if err == nil {
2020-01-23 16:06:16 +00:00
t . Errorf ( "Expected an error unmarshaling %q from YAML" , string ( b ) )
2018-10-05 17:29:52 +00:00
}
t . Logf ( "%s" , err )
}
}
func TestUnmarshalRelativeURL ( t * testing . T ) {
b := [ ] byte ( ` "/home" ` )
2018-07-26 10:39:33 +00:00
var u URL
2019-12-12 15:35:19 +00:00
err := json . Unmarshal ( b , & u )
2018-07-26 10:39:33 +00:00
if err == nil {
t . Errorf ( "Expected an error parsing URL" )
}
2019-12-12 15:35:19 +00:00
err = yaml . Unmarshal ( b , & u )
if err == nil {
t . Errorf ( "Expected an error parsing URL" )
}
}
2021-06-02 07:11:15 +00:00
func TestMarshalRegexpWithNilValue ( t * testing . T ) {
r := & Regexp { }
out , err := json . Marshal ( r )
require . NoError ( t , err )
require . Equal ( t , "null" , string ( out ) )
out , err = yaml . Marshal ( r )
require . NoError ( t , err )
require . Equal ( t , "null\n" , string ( out ) )
}
func TestUnmarshalEmptyRegexp ( t * testing . T ) {
b := [ ] byte ( ` "" ` )
{
var re Regexp
err := json . Unmarshal ( b , & re )
require . NoError ( t , err )
require . Equal ( t , regexp . MustCompile ( "^(?:)$" ) , re . Regexp )
require . Equal ( t , "" , re . original )
}
{
var re Regexp
err := yaml . Unmarshal ( b , & re )
require . NoError ( t , err )
require . Equal ( t , regexp . MustCompile ( "^(?:)$" ) , re . Regexp )
require . Equal ( t , "" , re . original )
}
}
func TestUnmarshalNullRegexp ( t * testing . T ) {
input := [ ] byte ( ` null ` )
{
var re Regexp
err := json . Unmarshal ( input , & re )
require . NoError ( t , err )
require . Nil ( t , nil , re . Regexp )
require . Equal ( t , "" , re . original )
}
{
var re Regexp
err := yaml . Unmarshal ( input , & re ) // Interestingly enough, unmarshalling `null` in YAML doesn't even call UnmarshalYAML.
require . NoError ( t , err )
require . Nil ( t , re . Regexp )
require . Equal ( t , "" , re . original )
}
}
func TestMarshalEmptyMatchers ( t * testing . T ) {
r := Matchers { }
out , err := json . Marshal ( r )
require . NoError ( t , err )
require . Equal ( t , "[]" , string ( out ) )
out , err = yaml . Marshal ( r )
require . NoError ( t , err )
require . Equal ( t , "[]\n" , string ( out ) )
}
2019-12-12 15:35:19 +00:00
func TestJSONUnmarshal ( t * testing . T ) {
c , err := LoadFile ( "testdata/conf.good.yml" )
if err != nil {
t . Errorf ( "Error parsing %s: %s" , "testdata/conf.good.yml" , err )
}
_ , err = json . Marshal ( c )
if err != nil {
t . Fatal ( "JSON Marshaling failed:" , err )
}
2017-06-06 11:02:49 +00:00
}
2017-06-20 17:09:14 +00:00
2018-12-13 10:51:49 +00:00
func TestMarshalIdempotency ( t * testing . T ) {
2019-08-26 12:01:40 +00:00
c , err := LoadFile ( "testdata/conf.good.yml" )
2018-12-13 10:51:49 +00:00
if err != nil {
t . Errorf ( "Error parsing %s: %s" , "testdata/conf.good.yml" , err )
}
marshaled , err := yaml . Marshal ( c )
if err != nil {
t . Fatal ( "YAML Marshaling failed:" , err )
}
c = new ( Config )
if err := yaml . Unmarshal ( marshaled , c ) ; err != nil {
t . Fatal ( "YAML Unmarshaling failed:" , err )
}
}
func TestGroupByAllNotMarshaled ( t * testing . T ) {
in := `
route :
receiver : team - X - mails
group_by : [ ... ]
receivers :
- name : ' team - X - mails '
`
c , err := Load ( in )
if err != nil {
t . Fatal ( "load failed:" , err )
}
dat , err := yaml . Marshal ( c )
if err != nil {
t . Fatal ( "YAML Marshaling failed:" , err )
}
if strings . Contains ( string ( dat ) , "groupbyall" ) {
t . Fatal ( "groupbyall found in config file" )
}
}
2017-06-20 17:09:14 +00:00
func TestEmptyFieldsAndRegex ( t * testing . T ) {
boolFoo := true
2022-03-25 16:59:51 +00:00
regexpFoo := Regexp {
2019-02-19 10:08:35 +00:00
Regexp : regexp . MustCompile ( "^(?:^(foo1|foo2|baz)$)$" ) ,
original : "^(foo1|foo2|baz)$" ,
}
2017-06-20 17:09:14 +00:00
2022-03-25 16:59:51 +00:00
expectedConf := Config {
2017-06-20 17:09:14 +00:00
Global : & GlobalConfig {
2021-03-01 22:19:38 +00:00
HTTPConfig : & commoncfg . HTTPClientConfig {
FollowRedirects : true ,
2022-07-25 18:49:29 +00:00
EnableHTTP2 : true ,
2021-03-01 22:19:38 +00:00
} ,
2020-06-11 13:51:10 +00:00
ResolveTimeout : model . Duration ( 5 * time . Minute ) ,
SMTPSmarthost : HostPort { Host : "localhost" , Port : "25" } ,
SMTPFrom : "alertmanager@example.org" ,
SlackAPIURL : ( * SecretURL ) ( mustParseURL ( "http://slack.example.com/" ) ) ,
SMTPRequireTLS : true ,
PagerdutyURL : mustParseURL ( "https://events.pagerduty.com/v2/enqueue" ) ,
OpsGenieAPIURL : mustParseURL ( "https://api.opsgenie.com/" ) ,
WeChatAPIURL : mustParseURL ( "https://qyapi.weixin.qq.com/cgi-bin/" ) ,
VictorOpsAPIURL : mustParseURL ( "https://alert.victorops.com/integrations/generic/20131114/alert/" ) ,
2022-02-22 16:51:02 +00:00
TelegramAPIUrl : mustParseURL ( "https://api.telegram.org" ) ,
2022-11-09 14:16:00 +00:00
WebexAPIURL : mustParseURL ( "https://webexapis.com/v1/messages" ) ,
2017-06-20 17:09:14 +00:00
} ,
Templates : [ ] string {
"/etc/alertmanager/template/*.tmpl" ,
} ,
Route : & Route {
Receiver : "team-X-mails" ,
GroupBy : [ ] model . LabelName {
"alertname" ,
"cluster" ,
"service" ,
} ,
2018-11-29 11:31:14 +00:00
GroupByStr : [ ] string {
"alertname" ,
"cluster" ,
"service" ,
} ,
GroupByAll : false ,
2017-06-20 17:09:14 +00:00
Routes : [ ] * Route {
{
Receiver : "team-X-mails" ,
MatchRE : map [ string ] Regexp {
"service" : regexpFoo ,
} ,
} ,
} ,
} ,
2023-01-09 21:12:12 +00:00
Receivers : [ ] Receiver {
2017-06-20 17:09:14 +00:00
{
Name : "team-X-mails" ,
EmailConfigs : [ ] * EmailConfig {
{
To : "team-X+alerts@example.org" ,
From : "alertmanager@example.org" ,
2019-08-28 13:04:40 +00:00
Smarthost : HostPort { Host : "localhost" , Port : "25" } ,
2017-06-20 17:09:14 +00:00
HTML : "{{ template \"email.default.html\" . }}" ,
RequireTLS : & boolFoo ,
} ,
} ,
} ,
} ,
}
2019-01-15 17:03:45 +00:00
// Load a non-empty configuration to ensure that all fields are overwritten.
// See https://github.com/prometheus/alertmanager/issues/1649.
2019-08-26 12:01:40 +00:00
_ , err := LoadFile ( "testdata/conf.good.yml" )
2019-01-15 17:03:45 +00:00
if err != nil {
t . Errorf ( "Error parsing %s: %s" , "testdata/conf.good.yml" , err )
}
2019-08-26 12:01:40 +00:00
config , err := LoadFile ( "testdata/conf.empty-fields.yml" )
2017-06-20 17:09:14 +00:00
if err != nil {
t . Errorf ( "Error parsing %s: %s" , "testdata/conf.empty-fields.yml" , err )
}
configGot , err := yaml . Marshal ( config )
if err != nil {
t . Fatal ( "YAML Marshaling failed:" , err )
}
configExp , err := yaml . Marshal ( expectedConf )
if err != nil {
t . Fatalf ( "%s" , err )
}
if ! reflect . DeepEqual ( configGot , configExp ) {
t . Fatalf ( "%s: unexpected config result: \n\n%s\n expected\n\n%s" , "testdata/conf.empty-fields.yml" , configGot , configExp )
}
}
2017-07-12 07:25:47 +00:00
2021-03-01 22:19:38 +00:00
func TestGlobalAndLocalHTTPConfig ( t * testing . T ) {
config , err := LoadFile ( "testdata/conf.http-config.good.yml" )
if err != nil {
t . Fatalf ( "Error parsing %s: %s" , "testdata/conf-http-config.good.yml" , err )
}
if config . Global . HTTPConfig . FollowRedirects {
t . Fatalf ( "global HTTP config should not follow redirects" )
}
if ! config . Receivers [ 0 ] . SlackConfigs [ 0 ] . HTTPConfig . FollowRedirects {
t . Fatalf ( "global HTTP config should follow redirects" )
}
}
2017-07-18 07:32:57 +00:00
func TestSMTPHello ( t * testing . T ) {
2019-08-26 12:01:40 +00:00
c , err := LoadFile ( "testdata/conf.good.yml" )
2017-07-18 07:32:57 +00:00
if err != nil {
2019-05-13 12:51:26 +00:00
t . Fatalf ( "Error parsing %s: %s" , "testdata/conf.good.yml" , err )
2017-07-18 07:32:57 +00:00
}
const refValue = "host.example.org"
2022-03-25 16:59:51 +00:00
hostName := c . Global . SMTPHello
2017-07-18 07:32:57 +00:00
if hostName != refValue {
t . Errorf ( "Invalid SMTP Hello hostname: %s\nExpected: %s" , hostName , refValue )
}
}
2022-09-16 12:36:57 +00:00
func TestSMTPBothPasswordAndFile ( t * testing . T ) {
_ , err := LoadFile ( "testdata/conf.smtp-both-password-and-file.yml" )
if err == nil {
t . Fatalf ( "Expected an error parsing %s: %s" , "testdata/conf.smtp-both-password-and-file.yml" , err )
}
if err . Error ( ) != "at most one of smtp_auth_password & smtp_auth_password_file must be configured" {
t . Errorf ( "Expected: %s\nGot: %s" , "at most one of auth_password & auth_password_file must be configured" , err . Error ( ) )
}
}
func TestSMTPNoUsernameOrPassword ( t * testing . T ) {
_ , err := LoadFile ( "testdata/conf.smtp-no-username-or-password.yml" )
if err != nil {
t . Fatalf ( "Error parsing %s: %s" , "testdata/conf.smtp-no-username-or-password.yml" , err )
}
}
func TestGlobalAndLocalSMTPPassword ( t * testing . T ) {
config , err := LoadFile ( "testdata/conf.smtp-password-global-and-local.yml" )
if err != nil {
t . Fatalf ( "Error parsing %s: %s" , "testdata/conf.smtp-password-global-and-local.yml" , err )
}
require . Equal ( t , "/tmp/globaluserpassword" , config . Receivers [ 0 ] . EmailConfigs [ 0 ] . AuthPasswordFile , "first email should use password file /tmp/globaluserpassword" )
require . Emptyf ( t , config . Receivers [ 0 ] . EmailConfigs [ 0 ] . AuthPassword , "password field should be empty when file provided" )
require . Equal ( t , "/tmp/localuser1password" , config . Receivers [ 0 ] . EmailConfigs [ 1 ] . AuthPasswordFile , "second email should use password file /tmp/localuser1password" )
require . Emptyf ( t , config . Receivers [ 0 ] . EmailConfigs [ 1 ] . AuthPassword , "password field should be empty when file provided" )
require . Equal ( t , Secret ( "mysecret" ) , config . Receivers [ 0 ] . EmailConfigs [ 2 ] . AuthPassword , "third email should use password mysecret" )
require . Emptyf ( t , config . Receivers [ 0 ] . EmailConfigs [ 2 ] . AuthPasswordFile , "file field should be empty when password provided" )
}
2018-11-29 11:31:14 +00:00
func TestGroupByAll ( t * testing . T ) {
2019-08-26 12:01:40 +00:00
c , err := LoadFile ( "testdata/conf.group-by-all.yml" )
2018-11-29 11:31:14 +00:00
if err != nil {
2019-05-13 12:51:26 +00:00
t . Fatalf ( "Error parsing %s: %s" , "testdata/conf.group-by-all.yml" , err )
2018-11-29 11:31:14 +00:00
}
if ! c . Route . GroupByAll {
t . Errorf ( "Invalid group by all param: expected to by true" )
}
}
2017-07-12 07:25:47 +00:00
func TestVictorOpsDefaultAPIKey ( t * testing . T ) {
2019-08-26 12:01:40 +00:00
conf , err := LoadFile ( "testdata/conf.victorops-default-apikey.yml" )
2017-07-12 07:25:47 +00:00
if err != nil {
2019-05-13 12:51:26 +00:00
t . Fatalf ( "Error parsing %s: %s" , "testdata/conf.victorops-default-apikey.yml" , err )
2017-07-12 07:25:47 +00:00
}
2022-03-25 16:59:51 +00:00
defaultKey := conf . Global . VictorOpsAPIKey
2022-10-25 13:40:17 +00:00
overrideKey := Secret ( "qwe456" )
2017-07-12 07:25:47 +00:00
if defaultKey != conf . Receivers [ 0 ] . VictorOpsConfigs [ 0 ] . APIKey {
2019-05-13 12:51:26 +00:00
t . Fatalf ( "Invalid victorops key: %s\nExpected: %s" , conf . Receivers [ 0 ] . VictorOpsConfigs [ 0 ] . APIKey , defaultKey )
2017-07-12 07:25:47 +00:00
}
2022-10-25 13:40:17 +00:00
if overrideKey != conf . Receivers [ 1 ] . VictorOpsConfigs [ 0 ] . APIKey {
t . Errorf ( "Invalid victorops key: %s\nExpected: %s" , conf . Receivers [ 0 ] . VictorOpsConfigs [ 0 ] . APIKey , string ( overrideKey ) )
}
}
func TestVictorOpsDefaultAPIKeyFile ( t * testing . T ) {
conf , err := LoadFile ( "testdata/conf.victorops-default-apikey-file.yml" )
if err != nil {
t . Fatalf ( "Error parsing %s: %s" , "testdata/conf.victorops-default-apikey-file.yml" , err )
}
defaultKey := conf . Global . VictorOpsAPIKeyFile
overrideKey := "/override_file"
if defaultKey != conf . Receivers [ 0 ] . VictorOpsConfigs [ 0 ] . APIKeyFile {
t . Fatalf ( "Invalid VictorOps key_file: %s\nExpected: %s" , conf . Receivers [ 0 ] . VictorOpsConfigs [ 0 ] . APIKeyFile , defaultKey )
}
if overrideKey != conf . Receivers [ 1 ] . VictorOpsConfigs [ 0 ] . APIKeyFile {
t . Errorf ( "Invalid VictorOps key_file: %s\nExpected: %s" , conf . Receivers [ 0 ] . VictorOpsConfigs [ 0 ] . APIKeyFile , overrideKey )
}
}
func TestVictorOpsBothAPIKeyAndFile ( t * testing . T ) {
_ , err := LoadFile ( "testdata/conf.victorops-both-file-and-apikey.yml" )
if err == nil {
t . Fatalf ( "Expected an error parsing %s: %s" , "testdata/conf.victorops-both-file-and-apikey.yml" , err )
}
if err . Error ( ) != "at most one of victorops_api_key & victorops_api_key_file must be configured" {
t . Errorf ( "Expected: %s\nGot: %s" , "at most one of victorops_api_key & victorops_api_key_file must be configured" , err . Error ( ) )
2017-07-12 07:25:47 +00:00
}
}
func TestVictorOpsNoAPIKey ( t * testing . T ) {
2019-08-26 12:01:40 +00:00
_ , err := LoadFile ( "testdata/conf.victorops-no-apikey.yml" )
2017-07-12 07:25:47 +00:00
if err == nil {
2019-05-13 12:51:26 +00:00
t . Fatalf ( "Expected an error parsing %s: %s" , "testdata/conf.victorops-no-apikey.yml" , err )
2017-07-12 07:25:47 +00:00
}
if err . Error ( ) != "no global VictorOps API Key set" {
t . Errorf ( "Expected: %s\nGot: %s" , "no global VictorOps API Key set" , err . Error ( ) )
}
}
2018-01-29 15:05:17 +00:00
func TestOpsGenieDefaultAPIKey ( t * testing . T ) {
2019-08-26 12:01:40 +00:00
conf , err := LoadFile ( "testdata/conf.opsgenie-default-apikey.yml" )
2018-01-29 15:05:17 +00:00
if err != nil {
2019-05-13 12:51:26 +00:00
t . Fatalf ( "Error parsing %s: %s" , "testdata/conf.opsgenie-default-apikey.yml" , err )
2018-01-29 15:05:17 +00:00
}
2022-03-25 16:59:51 +00:00
defaultKey := conf . Global . OpsGenieAPIKey
2018-01-29 15:05:17 +00:00
if defaultKey != conf . Receivers [ 0 ] . OpsGenieConfigs [ 0 ] . APIKey {
2019-05-13 12:51:26 +00:00
t . Fatalf ( "Invalid OpsGenie key: %s\nExpected: %s" , conf . Receivers [ 0 ] . OpsGenieConfigs [ 0 ] . APIKey , defaultKey )
2018-01-29 15:05:17 +00:00
}
if defaultKey == conf . Receivers [ 1 ] . OpsGenieConfigs [ 0 ] . APIKey {
t . Errorf ( "Invalid OpsGenie key: %s\nExpected: %s" , conf . Receivers [ 0 ] . OpsGenieConfigs [ 0 ] . APIKey , "qwe456" )
}
}
2021-10-21 07:29:03 +00:00
func TestOpsGenieDefaultAPIKeyFile ( t * testing . T ) {
conf , err := LoadFile ( "testdata/conf.opsgenie-default-apikey-file.yml" )
if err != nil {
t . Fatalf ( "Error parsing %s: %s" , "testdata/conf.opsgenie-default-apikey-file.yml" , err )
}
2022-03-25 16:59:51 +00:00
defaultKey := conf . Global . OpsGenieAPIKeyFile
2021-10-21 07:29:03 +00:00
if defaultKey != conf . Receivers [ 0 ] . OpsGenieConfigs [ 0 ] . APIKeyFile {
t . Fatalf ( "Invalid OpsGenie key_file: %s\nExpected: %s" , conf . Receivers [ 0 ] . OpsGenieConfigs [ 0 ] . APIKeyFile , defaultKey )
}
if defaultKey == conf . Receivers [ 1 ] . OpsGenieConfigs [ 0 ] . APIKeyFile {
t . Errorf ( "Invalid OpsGenie key_file: %s\nExpected: %s" , conf . Receivers [ 0 ] . OpsGenieConfigs [ 0 ] . APIKeyFile , "/override_file" )
}
}
func TestOpsGenieBothAPIKeyAndFile ( t * testing . T ) {
_ , err := LoadFile ( "testdata/conf.opsgenie-both-file-and-apikey.yml" )
if err == nil {
t . Fatalf ( "Expected an error parsing %s: %s" , "testdata/conf.opsgenie-both-file-and-apikey.yml" , err )
}
if err . Error ( ) != "at most one of opsgenie_api_key & opsgenie_api_key_file must be configured" {
t . Errorf ( "Expected: %s\nGot: %s" , "at most one of opsgenie_api_key & opsgenie_api_key_file must be configured" , err . Error ( ) )
}
}
2018-01-29 15:05:17 +00:00
func TestOpsGenieNoAPIKey ( t * testing . T ) {
2019-08-26 12:01:40 +00:00
_ , err := LoadFile ( "testdata/conf.opsgenie-no-apikey.yml" )
2018-01-29 15:05:17 +00:00
if err == nil {
2019-05-13 12:51:26 +00:00
t . Fatalf ( "Expected an error parsing %s: %s" , "testdata/conf.opsgenie-no-apikey.yml" , err )
2018-01-29 15:05:17 +00:00
}
2021-10-21 07:29:03 +00:00
if err . Error ( ) != "no global OpsGenie API Key set either inline or in a file" {
t . Errorf ( "Expected: %s\nGot: %s" , "no global OpsGenie API Key set either inline or in a file" , err . Error ( ) )
2018-01-29 15:05:17 +00:00
}
}
2019-05-13 12:51:26 +00:00
func TestOpsGenieDeprecatedTeamSpecified ( t * testing . T ) {
2019-08-26 12:01:40 +00:00
_ , err := LoadFile ( "testdata/conf.opsgenie-default-apikey-old-team.yml" )
2019-05-13 12:51:26 +00:00
if err == nil {
t . Fatalf ( "Expected an error parsing %s: %s" , "testdata/conf.opsgenie-default-apikey-old-team.yml" , err )
}
const expectedErr = ` yaml : unmarshal errors :
2021-12-22 13:03:53 +00:00
line 16 : field teams not found in type config . plain `
2019-05-13 12:51:26 +00:00
if err . Error ( ) != expectedErr {
t . Errorf ( "Expected: %s\nGot: %s" , expectedErr , err . Error ( ) )
}
}
2019-08-28 13:04:40 +00:00
2021-04-02 01:57:55 +00:00
func TestSlackBothAPIURLAndFile ( t * testing . T ) {
_ , err := LoadFile ( "testdata/conf.slack-both-file-and-url.yml" )
if err == nil {
t . Fatalf ( "Expected an error parsing %s: %s" , "testdata/conf.slack-both-file-and-url.yml" , err )
}
if err . Error ( ) != "at most one of slack_api_url & slack_api_url_file must be configured" {
t . Errorf ( "Expected: %s\nGot: %s" , "at most one of slack_api_url & slack_api_url_file must be configured" , err . Error ( ) )
}
}
func TestSlackNoAPIURL ( t * testing . T ) {
_ , err := LoadFile ( "testdata/conf.slack-no-api-url.yml" )
if err == nil {
t . Fatalf ( "Expected an error parsing %s: %s" , "testdata/conf.slack-no-api-url.yml" , err )
}
if err . Error ( ) != "no global Slack API URL set either inline or in a file" {
t . Errorf ( "Expected: %s\nGot: %s" , "no global Slack API URL set either inline or in a file" , err . Error ( ) )
}
}
func TestSlackGlobalAPIURLFile ( t * testing . T ) {
conf , err := LoadFile ( "testdata/conf.slack-default-api-url-file.yml" )
if err != nil {
t . Fatalf ( "Error parsing %s: %s" , "testdata/conf.slack-default-api-url-file.yml" , err )
}
// no override
firstConfig := conf . Receivers [ 0 ] . SlackConfigs [ 0 ]
if firstConfig . APIURLFile != "/global_file" || firstConfig . APIURL != nil {
t . Fatalf ( "Invalid Slack URL file: %s\nExpected: %s" , firstConfig . APIURLFile , "/global_file" )
}
// override the file
secondConfig := conf . Receivers [ 0 ] . SlackConfigs [ 1 ]
if secondConfig . APIURLFile != "/override_file" || secondConfig . APIURL != nil {
t . Fatalf ( "Invalid Slack URL file: %s\nExpected: %s" , secondConfig . APIURLFile , "/override_file" )
}
// override the global file with an inline URL
thirdConfig := conf . Receivers [ 0 ] . SlackConfigs [ 2 ]
if thirdConfig . APIURL . String ( ) != "http://mysecret.example.com/" || thirdConfig . APIURLFile != "" {
t . Fatalf ( "Invalid Slack URL: %s\nExpected: %s" , thirdConfig . APIURL . String ( ) , "http://mysecret.example.com/" )
}
}
2021-06-15 03:14:12 +00:00
func TestValidSNSConfig ( t * testing . T ) {
_ , err := LoadFile ( "testdata/conf.sns-topic-arn.yml" )
if err != nil {
t . Fatalf ( "Error parsing %s: %s" , "testdata/conf.sns-topic-arn.yml\"" , err )
}
}
func TestInvalidSNSConfig ( t * testing . T ) {
_ , err := LoadFile ( "testdata/conf.sns-invalid.yml" )
if err == nil {
t . Fatalf ( "expected error with missing fields on SNS config" )
}
2021-07-06 23:17:40 +00:00
const expectedErr = ` must provide either a Target ARN, Topic ARN, or Phone Number for SNS config `
if err . Error ( ) != expectedErr {
t . Errorf ( "Expected: %s\nGot: %s" , expectedErr , err . Error ( ) )
}
2021-06-15 03:14:12 +00:00
}
2019-08-28 13:04:40 +00:00
func TestUnmarshalHostPort ( t * testing . T ) {
for _ , tc := range [ ] struct {
in string
exp HostPort
jsonOut string
yamlOut string
err bool
} {
{
in : ` "" ` ,
exp : HostPort { } ,
yamlOut : ` ""
` ,
jsonOut : ` "" ` ,
} ,
{
in : ` "localhost:25" ` ,
exp : HostPort { Host : "localhost" , Port : "25" } ,
yamlOut : ` localhost : 25
` ,
jsonOut : ` "localhost:25" ` ,
} ,
{
in : ` ":25" ` ,
exp : HostPort { Host : "" , Port : "25" } ,
yamlOut : ` : 25
` ,
jsonOut : ` ":25" ` ,
} ,
{
in : ` "localhost" ` ,
err : true ,
} ,
{
in : ` "localhost:" ` ,
err : true ,
} ,
} {
tc := tc
t . Run ( tc . in , func ( t * testing . T ) {
hp := HostPort { }
err := yaml . Unmarshal ( [ ] byte ( tc . in ) , & hp )
if tc . err {
require . Error ( t , err )
return
}
require . NoError ( t , err )
require . Equal ( t , tc . exp , hp )
b , err := yaml . Marshal ( & hp )
require . NoError ( t , err )
require . Equal ( t , tc . yamlOut , string ( b ) )
b , err = json . Marshal ( & hp )
require . NoError ( t , err )
require . Equal ( t , tc . jsonOut , string ( b ) )
} )
}
}
2019-10-25 09:44:45 +00:00
func TestNilRegexp ( t * testing . T ) {
for _ , tc := range [ ] struct {
file string
errMsg string
} {
{
file : "testdata/conf.nil-match_re-route.yml" ,
errMsg : "invalid_label" ,
} ,
{
2020-01-23 16:06:16 +00:00
file : "testdata/conf.nil-source_match_re-inhibition.yml" ,
2019-10-25 09:44:45 +00:00
errMsg : "invalid_source_label" ,
} ,
{
2020-01-23 16:06:16 +00:00
file : "testdata/conf.nil-target_match_re-inhibition.yml" ,
2019-10-25 09:44:45 +00:00
errMsg : "invalid_target_label" ,
} ,
} {
t . Run ( tc . file , func ( t * testing . T ) {
_ , err := os . Stat ( tc . file )
require . NoError ( t , err )
_ , err = LoadFile ( tc . file )
require . Error ( t , err )
require . Contains ( t , err . Error ( ) , tc . errMsg )
} )
}
}