mirror of
https://github.com/hanzoai/telemetry.git
synced 2026-10-30 20:01:49 +00:00
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description The `xconfmap.Validator` interface has existed in some form for a very long time now and is ready to be stabilized. Similarly, the `xconfmap.Validate` method has existed in it's current state for over a year and doesn't have any open issues I'm aware of. It should also be ready for stabilization. Many modules depend on `xconfmap` merely for the validation facilities (as can be seen by the go.mod diffs), so this will allow them to depend on only stable modules. --------- Co-authored-by: Alex Boten <[email protected]>
161 lines
3.6 KiB
Go
161 lines
3.6 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package configopaque_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"go.opentelemetry.io/collector/config/configopaque"
|
|
"go.opentelemetry.io/collector/confmap"
|
|
)
|
|
|
|
const headersList = `
|
|
headers:
|
|
- name: "a"
|
|
value: "b"
|
|
- name: "c"
|
|
value: "d"
|
|
`
|
|
|
|
const headersMap = `
|
|
headers:
|
|
"a": "b"
|
|
"c": "d"
|
|
`
|
|
|
|
const headersBad1 = `
|
|
headers:
|
|
"bad": 1
|
|
`
|
|
|
|
const headersBad2 = `
|
|
headers: "foo"
|
|
`
|
|
|
|
const headersDupe = `
|
|
headers:
|
|
- name: "foo"
|
|
value: "bar"
|
|
- name: "foo"
|
|
value: "baz"
|
|
`
|
|
|
|
type testConfig struct {
|
|
Headers configopaque.MapList `mapstructure:"headers"`
|
|
}
|
|
|
|
func TestMapListDuality(t *testing.T) {
|
|
retrieved1, err := confmap.NewRetrievedFromYAML([]byte(headersList))
|
|
require.NoError(t, err)
|
|
conf1, err := retrieved1.AsConf()
|
|
require.NoError(t, err)
|
|
var tc1 testConfig
|
|
require.NoError(t, conf1.Unmarshal(&tc1))
|
|
assert.NoError(t, confmap.Validate(&tc1))
|
|
|
|
retrieved2, err := confmap.NewRetrievedFromYAML([]byte(headersMap))
|
|
require.NoError(t, err)
|
|
conf2, err := retrieved2.AsConf()
|
|
require.NoError(t, err)
|
|
var tc2 testConfig
|
|
require.NoError(t, conf2.Unmarshal(&tc2))
|
|
assert.NoError(t, confmap.Validate(&tc2))
|
|
|
|
assert.Equal(t, tc1, tc2)
|
|
}
|
|
|
|
func TestMapListUnmarshalError(t *testing.T) {
|
|
var tc testConfig
|
|
|
|
retrieved, err := confmap.NewRetrievedFromYAML([]byte(headersBad1))
|
|
require.NoError(t, err)
|
|
conf, err := retrieved.AsConf()
|
|
require.NoError(t, err)
|
|
require.EqualError(t, conf.Unmarshal(&tc),
|
|
"decoding failed due to the following error(s):\n\n"+
|
|
"'headers' decoding failed due to the following error(s):\n\n"+
|
|
"'[bad]' expected type 'configopaque.String', got unconvertible type 'int'")
|
|
|
|
retrieved, err = confmap.NewRetrievedFromYAML([]byte(headersBad2))
|
|
require.NoError(t, err)
|
|
conf, err = retrieved.AsConf()
|
|
require.NoError(t, err)
|
|
// Not sure if there is a way to change the error message to include the map case?
|
|
require.EqualError(t, conf.Unmarshal(&tc),
|
|
"decoding failed due to the following error(s):\n\n"+
|
|
"'headers' source data must be an array or slice, got string")
|
|
}
|
|
|
|
func TestMapListValidate(t *testing.T) {
|
|
retrieved, err := confmap.NewRetrievedFromYAML([]byte(headersDupe))
|
|
require.NoError(t, err)
|
|
conf, err := retrieved.AsConf()
|
|
require.NoError(t, err)
|
|
var tc testConfig
|
|
require.NoError(t, conf.Unmarshal(&tc))
|
|
require.EqualError(t, confmap.Validate(&tc), `headers: duplicate keys in map-style list: [foo]`)
|
|
}
|
|
|
|
func TestMapListMethods(t *testing.T) {
|
|
ml := configopaque.MapList{
|
|
{Name: "a", Value: "1"},
|
|
{Name: "b", Value: "2"},
|
|
{Name: "c", Value: "3"},
|
|
}
|
|
|
|
type pair = struct {
|
|
k string
|
|
v configopaque.String
|
|
}
|
|
var kvs []pair
|
|
for k, v := range ml.Iter {
|
|
kvs = append(kvs, pair{k, v})
|
|
if k == "b" {
|
|
break
|
|
}
|
|
}
|
|
assert.Equal(t, []pair{{"a", "1"}, {"b", "2"}}, kvs)
|
|
|
|
v, ok := ml.Get("a")
|
|
assert.True(t, ok)
|
|
if ok {
|
|
assert.Equal(t, configopaque.String("1"), v)
|
|
}
|
|
v, ok = ml.Get("d")
|
|
assert.False(t, ok)
|
|
assert.Zero(t, v)
|
|
|
|
ml2 := ml
|
|
assert.Len(t, ml2, 3)
|
|
|
|
// Set existing key
|
|
ml2.Set("c", "4")
|
|
assert.Len(t, ml, 3)
|
|
assert.Len(t, ml2, 3)
|
|
v, _ = ml.Get("c")
|
|
assert.Equal(t, configopaque.String("3"), v)
|
|
v, _ = ml2.Get("c")
|
|
assert.Equal(t, configopaque.String("4"), v)
|
|
|
|
// Set new key
|
|
ml2.Set("d", "5")
|
|
assert.Len(t, ml, 3)
|
|
assert.Len(t, ml2, 4)
|
|
_, ok = ml.Get("d")
|
|
assert.False(t, ok)
|
|
v, ok = ml2.Get("d")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, configopaque.String("5"), v)
|
|
}
|
|
|
|
func TestMapListNil(t *testing.T) {
|
|
var ml *configopaque.MapList
|
|
assert.Panics(t, func() {
|
|
ml.Set("a", "0")
|
|
})
|
|
}
|