[chore] Add component 'Builder' tests (#6862)
This commit is contained in:
parent
13672f4792
commit
2606ce237b
|
|
@ -19,8 +19,11 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.opentelemetry.io/collector/component"
|
||||
"go.opentelemetry.io/collector/component/componenttest"
|
||||
"go.opentelemetry.io/collector/consumer/consumertest"
|
||||
)
|
||||
|
||||
func TestNewFactory(t *testing.T) {
|
||||
|
|
@ -45,9 +48,9 @@ func TestNewFactoryWithOptions(t *testing.T) {
|
|||
factory := NewFactory(
|
||||
typeStr,
|
||||
func() component.Config { return &defaultCfg },
|
||||
WithTraces(createTracesExporter, component.StabilityLevelDevelopment),
|
||||
WithMetrics(createMetricsExporter, component.StabilityLevelAlpha),
|
||||
WithLogs(createLogsExporter, component.StabilityLevelDeprecated))
|
||||
WithTraces(createTraces, component.StabilityLevelDevelopment),
|
||||
WithMetrics(createMetrics, component.StabilityLevelAlpha),
|
||||
WithLogs(createLogs, component.StabilityLevelDeprecated))
|
||||
assert.EqualValues(t, typeStr, factory.Type())
|
||||
assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig())
|
||||
|
||||
|
|
@ -102,14 +105,148 @@ func TestMakeFactoryMap(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func createTracesExporter(context.Context, CreateSettings, component.Config) (Traces, error) {
|
||||
return nil, nil
|
||||
func TestBuilder(t *testing.T) {
|
||||
defaultCfg := struct{}{}
|
||||
factories, err := MakeFactoryMap([]Factory{
|
||||
NewFactory("err", nil),
|
||||
NewFactory(
|
||||
"all",
|
||||
func() component.Config { return &defaultCfg },
|
||||
WithTraces(createTraces, component.StabilityLevelDevelopment),
|
||||
WithMetrics(createMetrics, component.StabilityLevelAlpha),
|
||||
WithLogs(createLogs, component.StabilityLevelDeprecated),
|
||||
),
|
||||
}...)
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
id component.ID
|
||||
err string
|
||||
}{
|
||||
{
|
||||
name: "unknown",
|
||||
id: component.NewID("unknown"),
|
||||
err: "exporter factory not available for: \"unknown\"",
|
||||
},
|
||||
{
|
||||
name: "err",
|
||||
id: component.NewID("err"),
|
||||
err: "telemetry type is not supported",
|
||||
},
|
||||
{
|
||||
name: "all",
|
||||
id: component.NewID("all"),
|
||||
},
|
||||
{
|
||||
name: "all/named",
|
||||
id: component.NewIDWithName("all", "named"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cfgs := map[component.ID]component.Config{tt.id: defaultCfg}
|
||||
b := NewBuilder(cfgs, factories)
|
||||
|
||||
te, err := b.CreateTraces(context.Background(), createSettings(tt.id))
|
||||
if tt.err != "" {
|
||||
assert.EqualError(t, err, tt.err)
|
||||
assert.Nil(t, te)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nopInstance, te)
|
||||
}
|
||||
|
||||
me, err := b.CreateMetrics(context.Background(), createSettings(tt.id))
|
||||
if tt.err != "" {
|
||||
assert.EqualError(t, err, tt.err)
|
||||
assert.Nil(t, me)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nopInstance, me)
|
||||
}
|
||||
|
||||
le, err := b.CreateLogs(context.Background(), createSettings(tt.id))
|
||||
if tt.err != "" {
|
||||
assert.EqualError(t, err, tt.err)
|
||||
assert.Nil(t, le)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nopInstance, le)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func createMetricsExporter(context.Context, CreateSettings, component.Config) (Metrics, error) {
|
||||
return nil, nil
|
||||
func TestBuilderMissingConfig(t *testing.T) {
|
||||
defaultCfg := struct{}{}
|
||||
factories, err := MakeFactoryMap([]Factory{
|
||||
NewFactory(
|
||||
"all",
|
||||
func() component.Config { return &defaultCfg },
|
||||
WithTraces(createTraces, component.StabilityLevelDevelopment),
|
||||
WithMetrics(createMetrics, component.StabilityLevelAlpha),
|
||||
WithLogs(createLogs, component.StabilityLevelDeprecated),
|
||||
),
|
||||
}...)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
bErr := NewBuilder(map[component.ID]component.Config{}, factories)
|
||||
missingID := component.NewIDWithName("all", "missing")
|
||||
|
||||
te, err := bErr.CreateTraces(context.Background(), createSettings(missingID))
|
||||
assert.EqualError(t, err, "exporter \"all/missing\" is not configured")
|
||||
assert.Nil(t, te)
|
||||
|
||||
me, err := bErr.CreateMetrics(context.Background(), createSettings(missingID))
|
||||
assert.EqualError(t, err, "exporter \"all/missing\" is not configured")
|
||||
assert.Nil(t, me)
|
||||
|
||||
le, err := bErr.CreateLogs(context.Background(), createSettings(missingID))
|
||||
assert.EqualError(t, err, "exporter \"all/missing\" is not configured")
|
||||
assert.Nil(t, le)
|
||||
}
|
||||
|
||||
func createLogsExporter(context.Context, CreateSettings, component.Config) (Logs, error) {
|
||||
return nil, nil
|
||||
func TestBuilderFactory(t *testing.T) {
|
||||
factories, err := MakeFactoryMap([]Factory{NewFactory("foo", nil)}...)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfgs := map[component.ID]component.Config{component.NewID("foo"): struct{}{}}
|
||||
b := NewBuilder(cfgs, factories)
|
||||
|
||||
assert.NotNil(t, b.Factory(component.NewID("foo").Type()))
|
||||
assert.Nil(t, b.Factory(component.NewID("bar").Type()))
|
||||
}
|
||||
|
||||
var nopInstance = &nopExporter{
|
||||
Consumer: consumertest.NewNop(),
|
||||
}
|
||||
|
||||
// nopExporter stores consumed traces and metrics for testing purposes.
|
||||
type nopExporter struct {
|
||||
component.StartFunc
|
||||
component.ShutdownFunc
|
||||
consumertest.Consumer
|
||||
}
|
||||
|
||||
func createTraces(context.Context, CreateSettings, component.Config) (Traces, error) {
|
||||
return nopInstance, nil
|
||||
}
|
||||
|
||||
func createMetrics(context.Context, CreateSettings, component.Config) (Metrics, error) {
|
||||
return nopInstance, nil
|
||||
}
|
||||
|
||||
func createLogs(context.Context, CreateSettings, component.Config) (Logs, error) {
|
||||
return nopInstance, nil
|
||||
}
|
||||
|
||||
func createSettings(id component.ID) CreateSettings {
|
||||
return CreateSettings{
|
||||
ID: id,
|
||||
TelemetrySettings: componenttest.NewNopTelemetrySettings(),
|
||||
BuildInfo: component.NewDefaultBuildInfo(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,10 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.opentelemetry.io/collector/component"
|
||||
"go.opentelemetry.io/collector/component/componenttest"
|
||||
)
|
||||
|
||||
type nopExtension struct {
|
||||
|
|
@ -85,3 +87,56 @@ func TestMakeFactoryMap(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilder(t *testing.T) {
|
||||
const typeStr = "test"
|
||||
defaultCfg := struct{}{}
|
||||
nopExtensionInstance := new(nopExtension)
|
||||
testID := component.NewID(typeStr)
|
||||
unknownID := component.NewID("unknown")
|
||||
|
||||
factories, err := MakeFactoryMap([]Factory{
|
||||
NewFactory(
|
||||
typeStr,
|
||||
func() component.Config { return &defaultCfg },
|
||||
func(ctx context.Context, settings CreateSettings, extension component.Config) (Extension, error) {
|
||||
return nopExtensionInstance, nil
|
||||
},
|
||||
component.StabilityLevelDevelopment),
|
||||
}...)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfgs := map[component.ID]component.Config{testID: defaultCfg, unknownID: defaultCfg}
|
||||
b := NewBuilder(cfgs, factories)
|
||||
|
||||
e, err := b.Create(context.Background(), createSettings(testID))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, e)
|
||||
|
||||
missingType, err := b.Create(context.Background(), createSettings(unknownID))
|
||||
assert.EqualError(t, err, "extension factory not available for: \"unknown\"")
|
||||
assert.Nil(t, missingType)
|
||||
|
||||
missingCfg, err := b.Create(context.Background(), createSettings(component.NewIDWithName(typeStr, "foo")))
|
||||
assert.EqualError(t, err, "extension \"test/foo\" is not configured")
|
||||
assert.Nil(t, missingCfg)
|
||||
}
|
||||
|
||||
func TestBuilderFactory(t *testing.T) {
|
||||
factories, err := MakeFactoryMap([]Factory{NewFactory("foo", nil, nil, component.StabilityLevelDevelopment)}...)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfgs := map[component.ID]component.Config{component.NewID("foo"): struct{}{}}
|
||||
b := NewBuilder(cfgs, factories)
|
||||
|
||||
assert.NotNil(t, b.Factory(component.NewID("foo").Type()))
|
||||
assert.Nil(t, b.Factory(component.NewID("bar").Type()))
|
||||
}
|
||||
|
||||
func createSettings(id component.ID) CreateSettings {
|
||||
return CreateSettings{
|
||||
ID: id,
|
||||
TelemetrySettings: componenttest.NewNopTelemetrySettings(),
|
||||
BuildInfo: component.NewDefaultBuildInfo(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,12 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.opentelemetry.io/collector/component"
|
||||
"go.opentelemetry.io/collector/component/componenttest"
|
||||
"go.opentelemetry.io/collector/consumer"
|
||||
"go.opentelemetry.io/collector/consumer/consumertest"
|
||||
)
|
||||
|
||||
func TestNewFactory(t *testing.T) {
|
||||
|
|
@ -103,14 +106,148 @@ func TestMakeFactoryMap(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBuilder(t *testing.T) {
|
||||
defaultCfg := struct{}{}
|
||||
factories, err := MakeFactoryMap([]Factory{
|
||||
NewFactory("err", nil),
|
||||
NewFactory(
|
||||
"all",
|
||||
func() component.Config { return &defaultCfg },
|
||||
WithTraces(createTraces, component.StabilityLevelDevelopment),
|
||||
WithMetrics(createMetrics, component.StabilityLevelAlpha),
|
||||
WithLogs(createLogs, component.StabilityLevelDeprecated),
|
||||
),
|
||||
}...)
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
id component.ID
|
||||
err string
|
||||
}{
|
||||
{
|
||||
name: "unknown",
|
||||
id: component.NewID("unknown"),
|
||||
err: "processor factory not available for: \"unknown\"",
|
||||
},
|
||||
{
|
||||
name: "err",
|
||||
id: component.NewID("err"),
|
||||
err: "telemetry type is not supported",
|
||||
},
|
||||
{
|
||||
name: "all",
|
||||
id: component.NewID("all"),
|
||||
},
|
||||
{
|
||||
name: "all/named",
|
||||
id: component.NewIDWithName("all", "named"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cfgs := map[component.ID]component.Config{tt.id: defaultCfg}
|
||||
b := NewBuilder(cfgs, factories)
|
||||
|
||||
te, err := b.CreateTraces(context.Background(), createSettings(tt.id), nil)
|
||||
if tt.err != "" {
|
||||
assert.EqualError(t, err, tt.err)
|
||||
assert.Nil(t, te)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nopInstance, te)
|
||||
}
|
||||
|
||||
me, err := b.CreateMetrics(context.Background(), createSettings(tt.id), nil)
|
||||
if tt.err != "" {
|
||||
assert.EqualError(t, err, tt.err)
|
||||
assert.Nil(t, me)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nopInstance, me)
|
||||
}
|
||||
|
||||
le, err := b.CreateLogs(context.Background(), createSettings(tt.id), nil)
|
||||
if tt.err != "" {
|
||||
assert.EqualError(t, err, tt.err)
|
||||
assert.Nil(t, le)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nopInstance, le)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderMissingConfig(t *testing.T) {
|
||||
defaultCfg := struct{}{}
|
||||
factories, err := MakeFactoryMap([]Factory{
|
||||
NewFactory(
|
||||
"all",
|
||||
func() component.Config { return &defaultCfg },
|
||||
WithTraces(createTraces, component.StabilityLevelDevelopment),
|
||||
WithMetrics(createMetrics, component.StabilityLevelAlpha),
|
||||
WithLogs(createLogs, component.StabilityLevelDeprecated),
|
||||
),
|
||||
}...)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
bErr := NewBuilder(map[component.ID]component.Config{}, factories)
|
||||
missingID := component.NewIDWithName("all", "missing")
|
||||
|
||||
te, err := bErr.CreateTraces(context.Background(), createSettings(missingID), nil)
|
||||
assert.EqualError(t, err, "processor \"all/missing\" is not configured")
|
||||
assert.Nil(t, te)
|
||||
|
||||
me, err := bErr.CreateMetrics(context.Background(), createSettings(missingID), nil)
|
||||
assert.EqualError(t, err, "processor \"all/missing\" is not configured")
|
||||
assert.Nil(t, me)
|
||||
|
||||
le, err := bErr.CreateLogs(context.Background(), createSettings(missingID), nil)
|
||||
assert.EqualError(t, err, "processor \"all/missing\" is not configured")
|
||||
assert.Nil(t, le)
|
||||
}
|
||||
|
||||
func TestBuilderFactory(t *testing.T) {
|
||||
factories, err := MakeFactoryMap([]Factory{NewFactory("foo", nil)}...)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfgs := map[component.ID]component.Config{component.NewID("foo"): struct{}{}}
|
||||
b := NewBuilder(cfgs, factories)
|
||||
|
||||
assert.NotNil(t, b.Factory(component.NewID("foo").Type()))
|
||||
assert.Nil(t, b.Factory(component.NewID("bar").Type()))
|
||||
}
|
||||
|
||||
var nopInstance = &nopProcessor{
|
||||
Consumer: consumertest.NewNop(),
|
||||
}
|
||||
|
||||
// nopProcessor stores consumed traces and metrics for testing purposes.
|
||||
type nopProcessor struct {
|
||||
component.StartFunc
|
||||
component.ShutdownFunc
|
||||
consumertest.Consumer
|
||||
}
|
||||
|
||||
func createTraces(context.Context, CreateSettings, component.Config, consumer.Traces) (Traces, error) {
|
||||
return nil, nil
|
||||
return nopInstance, nil
|
||||
}
|
||||
|
||||
func createMetrics(context.Context, CreateSettings, component.Config, consumer.Metrics) (Metrics, error) {
|
||||
return nil, nil
|
||||
return nopInstance, nil
|
||||
}
|
||||
|
||||
func createLogs(context.Context, CreateSettings, component.Config, consumer.Logs) (Logs, error) {
|
||||
return nil, nil
|
||||
return nopInstance, nil
|
||||
}
|
||||
|
||||
func createSettings(id component.ID) CreateSettings {
|
||||
return CreateSettings{
|
||||
ID: id,
|
||||
TelemetrySettings: componenttest.NewNopTelemetrySettings(),
|
||||
BuildInfo: component.NewDefaultBuildInfo(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,12 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.opentelemetry.io/collector/component"
|
||||
"go.opentelemetry.io/collector/component/componenttest"
|
||||
"go.opentelemetry.io/collector/consumer"
|
||||
"go.opentelemetry.io/collector/consumer/consumertest"
|
||||
)
|
||||
|
||||
func TestNewFactory(t *testing.T) {
|
||||
|
|
@ -103,14 +106,148 @@ func TestMakeFactoryMap(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBuilder(t *testing.T) {
|
||||
defaultCfg := struct{}{}
|
||||
factories, err := MakeFactoryMap([]Factory{
|
||||
NewFactory("err", nil),
|
||||
NewFactory(
|
||||
"all",
|
||||
func() component.Config { return &defaultCfg },
|
||||
WithTraces(createTraces, component.StabilityLevelDevelopment),
|
||||
WithMetrics(createMetrics, component.StabilityLevelAlpha),
|
||||
WithLogs(createLogs, component.StabilityLevelDeprecated),
|
||||
),
|
||||
}...)
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
id component.ID
|
||||
err string
|
||||
}{
|
||||
{
|
||||
name: "unknown",
|
||||
id: component.NewID("unknown"),
|
||||
err: "receiver factory not available for: \"unknown\"",
|
||||
},
|
||||
{
|
||||
name: "err",
|
||||
id: component.NewID("err"),
|
||||
err: "telemetry type is not supported",
|
||||
},
|
||||
{
|
||||
name: "all",
|
||||
id: component.NewID("all"),
|
||||
},
|
||||
{
|
||||
name: "all/named",
|
||||
id: component.NewIDWithName("all", "named"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cfgs := map[component.ID]component.Config{tt.id: defaultCfg}
|
||||
b := NewBuilder(cfgs, factories)
|
||||
|
||||
te, err := b.CreateTraces(context.Background(), createSettings(tt.id), nil)
|
||||
if tt.err != "" {
|
||||
assert.EqualError(t, err, tt.err)
|
||||
assert.Nil(t, te)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nopInstance, te)
|
||||
}
|
||||
|
||||
me, err := b.CreateMetrics(context.Background(), createSettings(tt.id), nil)
|
||||
if tt.err != "" {
|
||||
assert.EqualError(t, err, tt.err)
|
||||
assert.Nil(t, me)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nopInstance, me)
|
||||
}
|
||||
|
||||
le, err := b.CreateLogs(context.Background(), createSettings(tt.id), nil)
|
||||
if tt.err != "" {
|
||||
assert.EqualError(t, err, tt.err)
|
||||
assert.Nil(t, le)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nopInstance, le)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderMissingConfig(t *testing.T) {
|
||||
defaultCfg := struct{}{}
|
||||
factories, err := MakeFactoryMap([]Factory{
|
||||
NewFactory(
|
||||
"all",
|
||||
func() component.Config { return &defaultCfg },
|
||||
WithTraces(createTraces, component.StabilityLevelDevelopment),
|
||||
WithMetrics(createMetrics, component.StabilityLevelAlpha),
|
||||
WithLogs(createLogs, component.StabilityLevelDeprecated),
|
||||
),
|
||||
}...)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
bErr := NewBuilder(map[component.ID]component.Config{}, factories)
|
||||
missingID := component.NewIDWithName("all", "missing")
|
||||
|
||||
te, err := bErr.CreateTraces(context.Background(), createSettings(missingID), nil)
|
||||
assert.EqualError(t, err, "receiver \"all/missing\" is not configured")
|
||||
assert.Nil(t, te)
|
||||
|
||||
me, err := bErr.CreateMetrics(context.Background(), createSettings(missingID), nil)
|
||||
assert.EqualError(t, err, "receiver \"all/missing\" is not configured")
|
||||
assert.Nil(t, me)
|
||||
|
||||
le, err := bErr.CreateLogs(context.Background(), createSettings(missingID), nil)
|
||||
assert.EqualError(t, err, "receiver \"all/missing\" is not configured")
|
||||
assert.Nil(t, le)
|
||||
}
|
||||
|
||||
func TestBuilderFactory(t *testing.T) {
|
||||
factories, err := MakeFactoryMap([]Factory{NewFactory("foo", nil)}...)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfgs := map[component.ID]component.Config{component.NewID("foo"): struct{}{}}
|
||||
b := NewBuilder(cfgs, factories)
|
||||
|
||||
assert.NotNil(t, b.Factory(component.NewID("foo").Type()))
|
||||
assert.Nil(t, b.Factory(component.NewID("bar").Type()))
|
||||
}
|
||||
|
||||
var nopInstance = &nopReceiver{
|
||||
Consumer: consumertest.NewNop(),
|
||||
}
|
||||
|
||||
// nopReceiver stores consumed traces and metrics for testing purposes.
|
||||
type nopReceiver struct {
|
||||
component.StartFunc
|
||||
component.ShutdownFunc
|
||||
consumertest.Consumer
|
||||
}
|
||||
|
||||
func createTraces(context.Context, CreateSettings, component.Config, consumer.Traces) (Traces, error) {
|
||||
return nil, nil
|
||||
return nopInstance, nil
|
||||
}
|
||||
|
||||
func createMetrics(context.Context, CreateSettings, component.Config, consumer.Metrics) (Metrics, error) {
|
||||
return nil, nil
|
||||
return nopInstance, nil
|
||||
}
|
||||
|
||||
func createLogs(context.Context, CreateSettings, component.Config, consumer.Logs) (Logs, error) {
|
||||
return nil, nil
|
||||
return nopInstance, nil
|
||||
}
|
||||
|
||||
func createSettings(id component.ID) CreateSettings {
|
||||
return CreateSettings{
|
||||
ID: id,
|
||||
TelemetrySettings: componenttest.NewNopTelemetrySettings(),
|
||||
BuildInfo: component.NewDefaultBuildInfo(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue