339 lines
8.8 KiB
Go
339 lines
8.8 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package viperutil
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hyperledger/fabric/bccsp/factory"
|
|
"github.com/hyperledger/fabric/orderer/mocks/util"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
const (
|
|
testConfigName = "viperutil"
|
|
testEnvPrefix = "VIPERUTIL"
|
|
)
|
|
|
|
func TestEnvSlice(t *testing.T) {
|
|
type testSlice struct {
|
|
Inner struct {
|
|
Slice []string
|
|
}
|
|
}
|
|
|
|
envVar := testEnvPrefix + "_INNER_SLICE"
|
|
t.Setenv(envVar, "[a, b, c]")
|
|
|
|
data := "---\nInner:\n Slice: [d,e,f]"
|
|
|
|
config := New()
|
|
config.SetConfigName(testConfigName)
|
|
err := config.ReadConfig(strings.NewReader(data))
|
|
require.NoError(t, err, "error reading %s plugin config", testConfigName)
|
|
|
|
var uconf testSlice
|
|
err = config.EnhancedExactUnmarshal(&uconf)
|
|
require.NoError(t, err, "failed to unmarshal")
|
|
|
|
expected := []string{"a", "b", "c"}
|
|
require.Exactly(t, expected, uconf.Inner.Slice, "did not get the expected slice")
|
|
}
|
|
|
|
type testByteSize struct {
|
|
Inner struct {
|
|
ByteSize uint32
|
|
}
|
|
}
|
|
|
|
func TestByteSize(t *testing.T) {
|
|
testCases := []struct {
|
|
data string
|
|
expected uint32
|
|
}{
|
|
{"", 0},
|
|
{"42", 42},
|
|
{"42k", 42 * 1024},
|
|
{"42kb", 42 * 1024},
|
|
{"42K", 42 * 1024},
|
|
{"42KB", 42 * 1024},
|
|
{"42 K", 42 * 1024},
|
|
{"42 KB", 42 * 1024},
|
|
{"42m", 42 * 1024 * 1024},
|
|
{"42mb", 42 * 1024 * 1024},
|
|
{"42M", 42 * 1024 * 1024},
|
|
{"42MB", 42 * 1024 * 1024},
|
|
{"42 M", 42 * 1024 * 1024},
|
|
{"42 MB", 42 * 1024 * 1024},
|
|
{"3g", 3 * 1024 * 1024 * 1024},
|
|
{"3gb", 3 * 1024 * 1024 * 1024},
|
|
{"3G", 3 * 1024 * 1024 * 1024},
|
|
{"3GB", 3 * 1024 * 1024 * 1024},
|
|
{"3 G", 3 * 1024 * 1024 * 1024},
|
|
{"3 GB", 3 * 1024 * 1024 * 1024},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.data, func(t *testing.T) {
|
|
data := fmt.Sprintf("---\nInner:\n ByteSize: %s", tc.data)
|
|
|
|
config := New()
|
|
err := config.ReadConfig(strings.NewReader(data))
|
|
require.NoError(t, err, "error reading config")
|
|
|
|
var uconf testByteSize
|
|
err = config.EnhancedExactUnmarshal(&uconf)
|
|
require.NoError(t, err, "failed to unmarshal")
|
|
require.Exactly(t, tc.expected, uconf.Inner.ByteSize, "incorrect byte size")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestByteSizeOverflow(t *testing.T) {
|
|
data := "---\nInner:\n ByteSize: 4GB"
|
|
|
|
config := New()
|
|
err := config.ReadConfig(strings.NewReader(data))
|
|
require.NoError(t, err, "error reading config")
|
|
|
|
var uconf testByteSize
|
|
err = config.EnhancedExactUnmarshal(&uconf)
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "Inner.ByteSize")
|
|
require.Contains(t, err.Error(), "value '4GB' overflows uint32")
|
|
}
|
|
|
|
type stringFromFileConfig struct {
|
|
Inner struct {
|
|
Single string
|
|
Multiple []string
|
|
}
|
|
}
|
|
|
|
func TestStringNotFromFile(t *testing.T) {
|
|
yaml := "---\nInner:\n Single: expected_value\n"
|
|
|
|
config := New()
|
|
err := config.ReadConfig(strings.NewReader(yaml))
|
|
require.NoError(t, err, "error reading config")
|
|
|
|
var uconf stringFromFileConfig
|
|
err = config.EnhancedExactUnmarshal(&uconf)
|
|
require.NoError(t, err, "failed to unmarshal")
|
|
require.Equal(t, "expected_value", uconf.Inner.Single)
|
|
}
|
|
|
|
func TestStringFromFile(t *testing.T) {
|
|
file, err := ioutil.TempFile(os.TempDir(), "test")
|
|
require.NoError(t, err, "failed to create temp file")
|
|
defer os.Remove(file.Name())
|
|
|
|
expectedValue := "this is the text in the file"
|
|
|
|
err = ioutil.WriteFile(file.Name(), []byte(expectedValue), 0o644)
|
|
require.NoError(t, err, "uname to write temp file")
|
|
|
|
yaml := fmt.Sprintf("---\nInner:\n Single:\n File: %s", file.Name())
|
|
|
|
config := New()
|
|
err = config.ReadConfig(strings.NewReader(yaml))
|
|
require.NoError(t, err, "error reading config")
|
|
|
|
var uconf stringFromFileConfig
|
|
err = config.EnhancedExactUnmarshal(&uconf)
|
|
require.NoError(t, err, "unmarshal failed")
|
|
require.Equal(t, expectedValue, uconf.Inner.Single)
|
|
}
|
|
|
|
func TestPEMBlocksFromFile(t *testing.T) {
|
|
file, err := ioutil.TempFile(os.TempDir(), "test")
|
|
require.NoError(t, err, "failed to create temp file")
|
|
defer os.Remove(file.Name())
|
|
|
|
var pems []byte
|
|
for i := 0; i < 3; i++ {
|
|
publicKeyCert, _, _ := util.GenerateMockPublicPrivateKeyPairPEM(true)
|
|
pems = append(pems, publicKeyCert...)
|
|
}
|
|
|
|
err = ioutil.WriteFile(file.Name(), pems, 0o644)
|
|
require.NoError(t, err, "failed to write temp file")
|
|
|
|
yaml := fmt.Sprintf("---\nInner:\n Multiple:\n File: %s", file.Name())
|
|
|
|
config := New()
|
|
err = config.ReadConfig(strings.NewReader(yaml))
|
|
require.NoError(t, err, "error reading config")
|
|
|
|
var uconf stringFromFileConfig
|
|
err = config.EnhancedExactUnmarshal(&uconf)
|
|
require.NoError(t, err, "failed to unmarshal")
|
|
require.Len(t, uconf.Inner.Multiple, 3)
|
|
}
|
|
|
|
func TestPEMBlocksFromFileEnv(t *testing.T) {
|
|
file, err := ioutil.TempFile(os.TempDir(), "test")
|
|
require.NoError(t, err, "failed to create temp file")
|
|
defer os.Remove(file.Name())
|
|
|
|
var pems []byte
|
|
for i := 0; i < 3; i++ {
|
|
publicKeyCert, _, _ := util.GenerateMockPublicPrivateKeyPairPEM(true)
|
|
pems = append(pems, publicKeyCert...)
|
|
}
|
|
|
|
err = ioutil.WriteFile(file.Name(), pems, 0o644)
|
|
require.NoError(t, err, "failed to write temp file")
|
|
|
|
envVar := testEnvPrefix + "_INNER_MULTIPLE_FILE"
|
|
t.Setenv(envVar, file.Name())
|
|
|
|
testCases := []struct {
|
|
name string
|
|
data string
|
|
}{
|
|
{"Override", "---\nInner:\n Multiple:\n File: wrong_file"},
|
|
{"NoFileElement", "---\nInner:\n Multiple:\n"},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
config := New()
|
|
config.SetConfigName(testConfigName)
|
|
|
|
err := config.ReadConfig(strings.NewReader(tc.data))
|
|
require.NoError(t, err, "error reading config")
|
|
|
|
var uconf stringFromFileConfig
|
|
err = config.EnhancedExactUnmarshal(&uconf)
|
|
require.NoError(t, err, "failed to unmarshal")
|
|
require.Len(t, uconf.Inner.Multiple, 3)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestStringFromFileNotSpecified(t *testing.T) {
|
|
yaml := "---\nInner:\n Single:\n File:\n"
|
|
|
|
config := New()
|
|
err := config.ReadConfig(strings.NewReader(yaml))
|
|
require.NoError(t, err, "error reading config")
|
|
|
|
var uconf stringFromFileConfig
|
|
err = config.EnhancedExactUnmarshal(&uconf)
|
|
require.Error(t, err, "umarshal should fail")
|
|
}
|
|
|
|
func TestStringFromFileEnv(t *testing.T) {
|
|
expectedValue := "this is the text in the file"
|
|
|
|
file, err := ioutil.TempFile(os.TempDir(), "test")
|
|
require.NoError(t, err, "failed to create temp file")
|
|
defer os.Remove(file.Name())
|
|
|
|
err = ioutil.WriteFile(file.Name(), []byte(expectedValue), 0o644)
|
|
require.NoError(t, err, "failed to write temp file")
|
|
|
|
envVar := testEnvPrefix + "_INNER_SINGLE_FILE"
|
|
t.Setenv(envVar, file.Name())
|
|
|
|
testCases := []struct {
|
|
name string
|
|
data string
|
|
}{
|
|
{"Override", "---\nInner:\n Single:\n File: wrong_file"},
|
|
{"NoFileElement", "---\nInner:\n Single:\n"},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
config := New()
|
|
config.SetConfigName(testConfigName)
|
|
|
|
err := config.ReadConfig(strings.NewReader(tc.data))
|
|
require.NoError(t, err, "error reading config")
|
|
|
|
var uconf stringFromFileConfig
|
|
err = config.EnhancedExactUnmarshal(&uconf)
|
|
require.NoError(t, err, "failed to unmarshal")
|
|
require.Exactly(t, expectedValue, uconf.Inner.Single)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDecodeOpaqueField(t *testing.T) {
|
|
yaml := "---\nFoo: bar\nHello:\n World: 42\n"
|
|
|
|
config := New()
|
|
err := config.ReadConfig(strings.NewReader(yaml))
|
|
require.NoError(t, err, "error reading config")
|
|
|
|
var conf struct {
|
|
Foo string
|
|
Hello struct{ World int }
|
|
}
|
|
err = config.EnhancedExactUnmarshal(&conf)
|
|
require.NoError(t, err, "failed to unmarshal")
|
|
require.Equal(t, "bar", conf.Foo)
|
|
require.Equal(t, 42, conf.Hello.World)
|
|
}
|
|
|
|
func TestBCCSPDecodeHookOverride(t *testing.T) {
|
|
yaml := "---\nBCCSP:\n Default: default-provider\n SW:\n Security: 999\n"
|
|
|
|
overrideVar := testEnvPrefix + "_BCCSP_SW_SECURITY"
|
|
t.Setenv(overrideVar, "1111")
|
|
|
|
config := New()
|
|
config.SetConfigName(testConfigName)
|
|
err := config.ReadConfig(strings.NewReader(yaml))
|
|
require.NoError(t, err, "error reading config")
|
|
|
|
var tc struct {
|
|
BCCSP *factory.FactoryOpts
|
|
}
|
|
err = config.EnhancedExactUnmarshal(&tc)
|
|
require.NoError(t, err, "failed to unmarshal")
|
|
require.NotNil(t, tc.BCCSP)
|
|
require.NotNil(t, tc.BCCSP.SW)
|
|
require.Equal(t, 1111, tc.BCCSP.SW.Security)
|
|
}
|
|
|
|
func TestDurationDecode(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
expected time.Duration
|
|
}{
|
|
{"", 0},
|
|
{"100", 100 * time.Nanosecond},
|
|
{"1s", time.Second},
|
|
{"1m", time.Minute},
|
|
{"1m1s", 61 * time.Second},
|
|
{"90s", 90 * time.Second},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.expected.String(), func(t *testing.T) {
|
|
yaml := fmt.Sprintf("---\nDuration: %s\n", tt.input)
|
|
|
|
config := New()
|
|
config.SetConfigName(testConfigName)
|
|
err := config.ReadConfig(strings.NewReader(yaml))
|
|
require.NoError(t, err, "error reading config")
|
|
|
|
var conf struct{ Duration time.Duration }
|
|
err = config.EnhancedExactUnmarshal(&conf)
|
|
require.NoError(t, err, "failed to unmarshal")
|
|
require.Equal(t, tt.expected, conf.Duration)
|
|
})
|
|
}
|
|
}
|