Skip to content

Commit 8a63ba1

Browse files
authored
Merge branch 'zeromicro:master' into master
2 parents 7850693 + b20f0e3 commit 8a63ba1

File tree

2 files changed

+220
-5
lines changed

2 files changed

+220
-5
lines changed

core/conf/config.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,7 @@ func Load(file string, v any, opts ...Option) error {
6262
return loader([]byte(os.ExpandEnv(string(content))), v)
6363
}
6464

65-
if err = loader(content, v); err != nil {
66-
return err
67-
}
68-
69-
return validate(v)
65+
return loader(content, v)
7066
}
7167

7268
// LoadConfig loads config into v from file, .json, .yaml and .yml are acceptable.

core/conf/config_test.go

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,3 +1397,222 @@ func TestGetFullName(t *testing.T) {
13971397
})
13981398
}
13991399
}
1400+
1401+
// validatorConfig is a test config that implements Validate() for testing validation behavior
1402+
type validatorConfig struct {
1403+
Value int `json:"value"`
1404+
}
1405+
1406+
func (v *validatorConfig) Validate() error {
1407+
if v.Value < 10 {
1408+
return errors.New("value must be >= 10")
1409+
}
1410+
return nil
1411+
}
1412+
1413+
// TestLoadValidation_WithoutEnv tests that validation is called correctly in normal loading path
1414+
func TestLoadValidation_WithoutEnv(t *testing.T) {
1415+
tests := []struct {
1416+
name string
1417+
extension string
1418+
content string
1419+
wantErr bool
1420+
errMsg string
1421+
}{
1422+
{
1423+
name: "json valid value",
1424+
extension: ".json",
1425+
content: `{"value": 15}`,
1426+
wantErr: false,
1427+
},
1428+
{
1429+
name: "json invalid value",
1430+
extension: ".json",
1431+
content: `{"value": 5}`,
1432+
wantErr: true,
1433+
errMsg: "value must be >= 10",
1434+
},
1435+
{
1436+
name: "yaml valid value",
1437+
extension: ".yaml",
1438+
content: "value: 20\n",
1439+
wantErr: false,
1440+
},
1441+
{
1442+
name: "yaml invalid value",
1443+
extension: ".yaml",
1444+
content: "value: 3\n",
1445+
wantErr: true,
1446+
errMsg: "value must be >= 10",
1447+
},
1448+
{
1449+
name: "toml valid value",
1450+
extension: ".toml",
1451+
content: "value = 100\n",
1452+
wantErr: false,
1453+
},
1454+
{
1455+
name: "toml invalid value",
1456+
extension: ".toml",
1457+
content: "value = 1\n",
1458+
wantErr: true,
1459+
errMsg: "value must be >= 10",
1460+
},
1461+
}
1462+
1463+
for _, tt := range tests {
1464+
t.Run(tt.name, func(t *testing.T) {
1465+
tmpfile, err := createTempFile(t, tt.extension, tt.content)
1466+
assert.Nil(t, err)
1467+
1468+
var cfg validatorConfig
1469+
err = Load(tmpfile, &cfg)
1470+
1471+
if tt.wantErr {
1472+
assert.Error(t, err)
1473+
assert.Contains(t, err.Error(), tt.errMsg)
1474+
} else {
1475+
assert.NoError(t, err)
1476+
}
1477+
})
1478+
}
1479+
}
1480+
1481+
// TestLoadValidation_WithEnv tests that validation is called correctly with UseEnv() option
1482+
func TestLoadValidation_WithEnv(t *testing.T) {
1483+
tests := []struct {
1484+
name string
1485+
extension string
1486+
content string
1487+
envValue string
1488+
wantErr bool
1489+
errMsg string
1490+
}{
1491+
{
1492+
name: "json valid value with env",
1493+
extension: ".json",
1494+
content: `{"value": ${TEST_VALUE}}`,
1495+
envValue: "25",
1496+
wantErr: false,
1497+
},
1498+
{
1499+
name: "json invalid value with env",
1500+
extension: ".json",
1501+
content: `{"value": ${TEST_VALUE}}`,
1502+
envValue: "7",
1503+
wantErr: true,
1504+
errMsg: "value must be >= 10",
1505+
},
1506+
{
1507+
name: "yaml valid value with env",
1508+
extension: ".yaml",
1509+
content: "value: ${TEST_VALUE}\n",
1510+
envValue: "50",
1511+
wantErr: false,
1512+
},
1513+
{
1514+
name: "yaml invalid value with env",
1515+
extension: ".yaml",
1516+
content: "value: ${TEST_VALUE}\n",
1517+
envValue: "2",
1518+
wantErr: true,
1519+
errMsg: "value must be >= 10",
1520+
},
1521+
{
1522+
name: "toml valid value with env",
1523+
extension: ".toml",
1524+
content: "value = ${TEST_VALUE}\n",
1525+
envValue: "99",
1526+
wantErr: false,
1527+
},
1528+
{
1529+
name: "toml invalid value with env",
1530+
extension: ".toml",
1531+
content: "value = ${TEST_VALUE}\n",
1532+
envValue: "8",
1533+
wantErr: true,
1534+
errMsg: "value must be >= 10",
1535+
},
1536+
}
1537+
1538+
for _, tt := range tests {
1539+
t.Run(tt.name, func(t *testing.T) {
1540+
t.Setenv("TEST_VALUE", tt.envValue)
1541+
1542+
tmpfile, err := createTempFile(t, tt.extension, tt.content)
1543+
assert.Nil(t, err)
1544+
1545+
var cfg validatorConfig
1546+
err = Load(tmpfile, &cfg, UseEnv())
1547+
1548+
if tt.wantErr {
1549+
assert.Error(t, err)
1550+
assert.Contains(t, err.Error(), tt.errMsg)
1551+
} else {
1552+
assert.NoError(t, err)
1553+
}
1554+
})
1555+
}
1556+
}
1557+
1558+
// TestLoadValidation_Consistency verifies validation behavior is consistent between paths
1559+
func TestLoadValidation_Consistency(t *testing.T) {
1560+
// Test that both paths (with and without UseEnv) produce the same validation results
1561+
const validValue = 15
1562+
1563+
formats := []struct {
1564+
ext string
1565+
invalid string
1566+
valid string
1567+
}{
1568+
{".json", `{"value": 5}`, `{"value": 15}`},
1569+
{".yaml", "value: 5\n", "value: 15\n"},
1570+
{".toml", "value = 5\n", "value = 15\n"},
1571+
}
1572+
1573+
for _, format := range formats {
1574+
t.Run("invalid_"+format.ext, func(t *testing.T) {
1575+
// Test without UseEnv()
1576+
tmpfile1, err := createTempFile(t, format.ext, format.invalid)
1577+
assert.Nil(t, err)
1578+
1579+
var cfg1 validatorConfig
1580+
err1 := Load(tmpfile1, &cfg1)
1581+
1582+
// Test with UseEnv()
1583+
tmpfile2, err := createTempFile(t, format.ext, format.invalid)
1584+
assert.Nil(t, err)
1585+
1586+
var cfg2 validatorConfig
1587+
err2 := Load(tmpfile2, &cfg2, UseEnv())
1588+
1589+
// Both should fail validation
1590+
assert.Error(t, err1, "validation should fail without UseEnv()")
1591+
assert.Error(t, err2, "validation should fail with UseEnv()")
1592+
assert.Contains(t, err1.Error(), "value must be >= 10")
1593+
assert.Contains(t, err2.Error(), "value must be >= 10")
1594+
})
1595+
1596+
t.Run("valid_"+format.ext, func(t *testing.T) {
1597+
// Test without UseEnv()
1598+
tmpfile1, err := createTempFile(t, format.ext, format.valid)
1599+
assert.Nil(t, err)
1600+
1601+
var cfg1 validatorConfig
1602+
err1 := Load(tmpfile1, &cfg1)
1603+
1604+
// Test with UseEnv()
1605+
tmpfile2, err := createTempFile(t, format.ext, format.valid)
1606+
assert.Nil(t, err)
1607+
1608+
var cfg2 validatorConfig
1609+
err2 := Load(tmpfile2, &cfg2, UseEnv())
1610+
1611+
// Both should pass validation
1612+
assert.NoError(t, err1, "validation should pass without UseEnv()")
1613+
assert.NoError(t, err2, "validation should pass with UseEnv()")
1614+
assert.Equal(t, validValue, cfg1.Value)
1615+
assert.Equal(t, validValue, cfg2.Value)
1616+
})
1617+
}
1618+
}

0 commit comments

Comments
 (0)